Skip to content

Commit 86bd6d6

Browse files
thetronjohnson123vivekr
authored andcommitted
fix issue with cc agents
1 parent 7b380b2 commit 86bd6d6

9 files changed

Lines changed: 293 additions & 205 deletions

File tree

src-tauri/src/commands/claude.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -307,15 +307,6 @@ pub async fn get_home_directory() -> Result<String, String> {
307307
.ok_or_else(|| "Could not determine home directory".to_string())
308308
}
309309

310-
/// Opens native folder picker and returns selected path
311-
#[tauri::command]
312-
pub async fn pick_folder() -> Result<Option<String>, String> {
313-
use tauri_plugin_dialog::DialogExt;
314-
315-
// Note: This requires the dialog plugin to be initialized in main.rs
316-
// The actual dialog will be shown from the frontend using the plugin
317-
Ok(None)
318-
}
319310

320311
/// Lists all projects in the ~/.claude/projects directory
321312
#[tauri::command]

src/components/AgentExecution.tsx

Lines changed: 200 additions & 161 deletions
Large diffs are not rendered by default.

src/components/Agents.tsx

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { useState, useEffect } from 'react';
22
import { motion, AnimatePresence } from 'framer-motion';
3-
import { Bot, Loader2, Play, Clock, CheckCircle, XCircle, Trash2, Import, ChevronDown, FileJson, Globe, Download, Plus } from 'lucide-react';
3+
import { Bot, Loader2, Play, Clock, CheckCircle, XCircle, Trash2, Import, ChevronDown, ChevronRight, FileJson, Globe, Download, Plus, History } from 'lucide-react';
44
import {
55
DropdownMenu,
66
DropdownMenuContent,
@@ -13,12 +13,12 @@ import { Badge } from '@/components/ui/badge';
1313
import { Card } from '@/components/ui/card';
1414
import { Toast } from '@/components/ui/toast';
1515
import { api, type Agent, type AgentRunWithMetrics } from '@/lib/api';
16-
import { useTabState } from '@/hooks/useTabState';
1716
import { formatISOTimestamp } from '@/lib/date-utils';
1817
import { open as openDialog, save } from '@tauri-apps/plugin-dialog';
1918
import { invoke } from '@tauri-apps/api/core';
2019
import { GitHubAgentBrowser } from '@/components/GitHubAgentBrowser';
2120
import { CreateAgent } from '@/components/CreateAgent';
21+
import { useTabState } from '@/hooks/useTabState';
2222

2323
export const Agents: React.FC = () => {
2424
const [activeTab, setActiveTab] = useState('agents');
@@ -62,7 +62,7 @@ export const Agents: React.FC = () => {
6262

6363
const loadRunningAgents = async () => {
6464
try {
65-
const runs = await api.listAgentRuns();
65+
const runs = await api.listAgentRunsWithMetrics();
6666
setRunningAgents(runs);
6767
} catch (error) {
6868
console.error('Failed to load running agents:', error);
@@ -74,14 +74,33 @@ export const Agents: React.FC = () => {
7474
setToast({ message: 'Agent ID is missing', type: 'error' });
7575
return;
7676
}
77+
78+
// Import the dialog function
79+
const { open } = await import('@tauri-apps/plugin-dialog');
80+
7781
try {
78-
const runId = await api.executeAgent(agent.id, '', 'Run agent', undefined);
79-
createAgentTab(runId.toString(), agent.name);
80-
setToast({ message: `Started agent: ${agent.name}`, type: 'success' });
81-
loadRunningAgents();
82+
// Prompt user to select a project directory
83+
const projectPath = await open({
84+
directory: true,
85+
multiple: false,
86+
title: `Select project directory for ${agent.name}`
87+
});
88+
89+
if (!projectPath) {
90+
// User cancelled
91+
return;
92+
}
93+
94+
// Dispatch event to open agent execution in a new tab
95+
const tabId = `agent-exec-${agent.id}-${Date.now()}`;
96+
window.dispatchEvent(new CustomEvent('open-agent-execution', {
97+
detail: { agent, tabId, projectPath }
98+
}));
99+
100+
setToast({ message: `Opening agent: ${agent.name}`, type: 'success' });
82101
} catch (error) {
83-
console.error('Failed to run agent:', error);
84-
setToast({ message: `Failed to run agent: ${agent.name}`, type: 'error' });
102+
console.error('Failed to open agent:', error);
103+
setToast({ message: `Failed to open agent: ${agent.name}`, type: 'error' });
85104
}
86105
};
87106

@@ -292,8 +311,8 @@ export const Agents: React.FC = () => {
292311
Agents ({agents.length})
293312
</TabsTrigger>
294313
<TabsTrigger value="running" className="py-2.5 px-3">
295-
<Loader2 className="w-4 h-4 mr-2" />
296-
Running ({runningAgents.length})
314+
<History className="w-4 h-4 mr-2" />
315+
History ({runningAgents.length})
297316
</TabsTrigger>
298317
</TabsList>
299318

@@ -381,8 +400,8 @@ export const Agents: React.FC = () => {
381400
{runningAgents.length === 0 ? (
382401
<Card className="p-12">
383402
<div className="flex flex-col items-center justify-center text-center">
384-
<Loader2 className="w-12 h-12 text-muted-foreground mb-4" />
385-
<h3 className="text-lg font-semibold mb-2">No Running Agents</h3>
403+
<History className="w-12 h-12 text-muted-foreground mb-4" />
404+
<h3 className="text-lg font-semibold mb-2">No Agent History</h3>
386405
<p className="text-muted-foreground">
387406
Run an agent to see it here
388407
</p>
@@ -404,26 +423,27 @@ export const Agents: React.FC = () => {
404423
</Badge>
405424
</div>
406425
<Button
407-
size="sm"
408-
variant="outline"
426+
size="icon"
427+
variant="ghost"
409428
onClick={() => createAgentTab(run.id?.toString() || '', run.agent_name)}
429+
className="h-8 w-8"
410430
>
411-
View
431+
<ChevronRight className="w-4 h-4" />
412432
</Button>
413433
</div>
414434

415435
<div className="grid grid-cols-3 gap-4 text-sm">
416436
<div>
417437
<span className="text-muted-foreground">Started:</span>
418-
<p className="font-medium">{formatISOTimestamp(run.created_at)}</p>
438+
<p className="font-medium">{new Date(run.created_at).toLocaleString()}</p>
419439
</div>
420440
<div>
421441
<span className="text-muted-foreground">Duration:</span>
422-
<p className="font-medium">{run.metrics?.duration_ms ? `${(run.metrics.duration_ms / 1000).toFixed(1)}s` : 'N/A'}</p>
442+
<p className="font-medium">{run.metrics?.duration_ms ? `${(run.metrics.duration_ms / 1000).toFixed(1)}s` : run.duration_ms ? `${(run.duration_ms / 1000).toFixed(1)}s` : '—'}</p>
423443
</div>
424444
<div>
425445
<span className="text-muted-foreground">Tokens:</span>
426-
<p className="font-medium">{run.metrics?.total_tokens?.toLocaleString() || '0'}</p>
446+
<p className="font-medium">{run.metrics?.total_tokens ? run.metrics.total_tokens.toLocaleString() : run.total_tokens ? run.total_tokens.toLocaleString() : '—'}</p>
427447
</div>
428448
</div>
429449

src/components/AgentsModal.tsx

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -94,16 +94,35 @@ export const AgentsModal: React.FC<AgentsModalProps> = ({ open, onOpenChange })
9494
};
9595

9696
const handleRunAgent = async (agent: Agent) => {
97-
// Create a new agent execution tab
98-
const tabId = `agent-exec-${agent.id}-${Date.now()}`;
97+
// Open directory picker for project path
98+
const { open } = await import('@tauri-apps/plugin-dialog');
9999

100-
// Close modal
101-
onOpenChange(false);
102-
103-
// Dispatch event to open agent execution in the new tab
104-
window.dispatchEvent(new CustomEvent('open-agent-execution', {
105-
detail: { agent, tabId }
106-
}));
100+
try {
101+
const projectPath = await open({
102+
directory: true,
103+
multiple: false,
104+
title: `Select project directory for ${agent.name}`
105+
});
106+
107+
if (!projectPath) {
108+
// User cancelled
109+
return;
110+
}
111+
112+
// Create a new agent execution tab
113+
const tabId = `agent-exec-${agent.id}-${Date.now()}`;
114+
115+
// Close modal
116+
onOpenChange(false);
117+
118+
// Dispatch event to open agent execution in the new tab with project path
119+
window.dispatchEvent(new CustomEvent('open-agent-execution', {
120+
detail: { agent, tabId, projectPath }
121+
}));
122+
} catch (error) {
123+
console.error('Failed to run agent:', error);
124+
setToast({ message: `Failed to run agent: ${agent.name}`, type: 'error' });
125+
}
107126
};
108127

109128
const handleDeleteAgent = async (agent: Agent) => {

src/components/ProjectList.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ export const ProjectList: React.FC<ProjectListProps> = ({
118118
<div className="p-6">
119119
<div className="flex items-center justify-between">
120120
<div>
121-
<h1 className="text-heading-1">Projects</h1>
121+
<h1 className="text-3xl font-bold">Projects</h1>
122122
<p className="mt-1 text-body-small text-muted-foreground">
123123
Select a project to start working with Claude Code
124124
</p>

src/components/TabContent.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,8 @@ const TabPanel: React.FC<TabPanelProps> = ({ tab, isActive }) => {
309309
return (
310310
<AgentExecution
311311
agent={tab.agentData}
312+
projectPath={tab.projectPath}
313+
tabId={tab.id}
312314
onBack={() => {}}
313315
/>
314316
);
@@ -395,8 +397,8 @@ export const TabContent: React.FC = () => {
395397
};
396398

397399
const handleOpenAgentExecution = (event: CustomEvent) => {
398-
const { agent, tabId } = event.detail;
399-
createAgentExecutionTab(agent, tabId);
400+
const { agent, tabId, projectPath } = event.detail;
401+
createAgentExecutionTab(agent, tabId, projectPath);
400402
};
401403

402404
const handleOpenCreateAgentTab = () => {

src/contexts/TabContext.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export interface Tab {
1010
agentData?: any; // for agent-execution tabs
1111
claudeFileId?: string; // for claude-file tabs
1212
initialProjectPath?: string; // for chat tabs
13+
projectPath?: string; // for agent-execution tabs
1314
status: 'active' | 'idle' | 'running' | 'complete' | 'error';
1415
hasUnsavedChanges: boolean;
1516
order: number;

src/hooks/useTabState.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ interface UseTabStateReturn {
1414
// Operations
1515
createChatTab: (projectId?: string, title?: string, projectPath?: string) => string;
1616
createAgentTab: (agentRunId: string, agentName: string) => string;
17-
createAgentExecutionTab: (agent: any, tabId: string) => string;
17+
createAgentExecutionTab: (agent: any, tabId: string, projectPath?: string) => string;
1818
createProjectsTab: () => string | null;
1919
createAgentsTab: () => string | null;
2020
createUsageTab: () => string | null;
@@ -206,11 +206,12 @@ export const useTabState = (): UseTabStateReturn => {
206206
});
207207
}, [addTab, tabs, setActiveTab]);
208208

209-
const createAgentExecutionTab = useCallback((agent: any, _tabId: string): string => {
209+
const createAgentExecutionTab = useCallback((agent: any, _tabId: string, projectPath?: string): string => {
210210
return addTab({
211211
type: 'agent-execution',
212212
title: `Run: ${agent.name}`,
213213
agentData: agent,
214+
projectPath: projectPath,
214215
status: 'idle',
215216
hasUnsavedChanges: false,
216217
icon: 'bot'

src/lib/api.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -848,9 +848,9 @@ export const api = {
848848
},
849849

850850
/**
851-
* Lists agent runs with metrics
851+
* Lists agent runs without metrics (basic info only)
852852
* @param agentId - Optional agent ID to filter runs
853-
* @returns Promise resolving to an array of agent runs with metrics
853+
* @returns Promise resolving to an array of agent runs
854854
*/
855855
async listAgentRuns(agentId?: number): Promise<AgentRunWithMetrics[]> {
856856
try {
@@ -862,6 +862,21 @@ export const api = {
862862
}
863863
},
864864

865+
/**
866+
* Lists agent runs with metrics (includes token counts and duration)
867+
* @param agentId - Optional agent ID to filter runs
868+
* @returns Promise resolving to an array of agent runs with metrics
869+
*/
870+
async listAgentRunsWithMetrics(agentId?: number): Promise<AgentRunWithMetrics[]> {
871+
try {
872+
return await invoke<AgentRunWithMetrics[]>('list_agent_runs_with_metrics', { agentId });
873+
} catch (error) {
874+
console.error("Failed to list agent runs with metrics:", error);
875+
// Return empty array instead of throwing to prevent UI crashes
876+
return [];
877+
}
878+
},
879+
865880
/**
866881
* Gets a single agent run by ID with metrics
867882
* @param id - The run ID

0 commit comments

Comments
 (0)