codex-linux 1.0.1 → 1.0.3
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/README.md +56 -19
- package/abyss-teal-design-system.html +1449 -0
- package/dist/renderer/assets/main-CU1lrRNa.css +1 -0
- package/dist/renderer/assets/main-DQIKNXUA.js +304 -0
- package/dist/renderer/index.html +2 -2
- package/package.json +2 -2
- package/src/renderer/App.tsx +45 -15
- package/src/renderer/components/AgentPanel.tsx +146 -130
- package/src/renderer/components/AutomationPanel.tsx +39 -34
- package/src/renderer/components/ChatInterface.tsx +81 -123
- package/src/renderer/components/Header.tsx +24 -38
- package/src/renderer/components/SettingsPanel.tsx +89 -96
- package/src/renderer/components/Sidebar.tsx +33 -51
- package/src/renderer/components/SkillsPanel.tsx +54 -56
- package/src/renderer/components/WelcomeChat.tsx +199 -0
- package/src/renderer/components/WorktreePanel.tsx +32 -27
- package/src/renderer/components/ui/Button.tsx +17 -19
- package/src/renderer/components/ui/Card.tsx +14 -15
- package/src/renderer/components/ui/Input.tsx +12 -13
- package/src/renderer/index.css +37 -59
- package/src/renderer/styles/abyss-teal.css +405 -0
- package/dist/renderer/assets/main-DJlZQBCA.js +0 -304
- package/dist/renderer/assets/main-N33ZXEr8.css +0 -1
|
@@ -3,12 +3,8 @@ import { Agent, AIProvider, Skill, CodeChange, ChangeStatus } from '../../shared
|
|
|
3
3
|
import {
|
|
4
4
|
Bot,
|
|
5
5
|
Plus,
|
|
6
|
-
Play,
|
|
7
|
-
Pause,
|
|
8
|
-
Square,
|
|
9
|
-
Trash2,
|
|
10
6
|
MessageSquare,
|
|
11
|
-
|
|
7
|
+
Trash2
|
|
12
8
|
} from 'lucide-react';
|
|
13
9
|
import DiffViewer from './DiffViewer';
|
|
14
10
|
|
|
@@ -41,10 +37,12 @@ export const AgentPanel: React.FC<AgentPanelProps> = ({
|
|
|
41
37
|
const [newAgentConfig, setNewAgentConfig] = useState({
|
|
42
38
|
name: '',
|
|
43
39
|
projectPath: '',
|
|
44
|
-
providerId:
|
|
40
|
+
providerId: '',
|
|
45
41
|
model: '',
|
|
46
42
|
skills: [] as string[]
|
|
47
43
|
});
|
|
44
|
+
const [createError, setCreateError] = useState<string | null>(null);
|
|
45
|
+
const [isCreating, setIsCreating] = useState(false);
|
|
48
46
|
|
|
49
47
|
const selectedAgentChanges = useMemo(() => {
|
|
50
48
|
if (!selectedAgent) return [];
|
|
@@ -88,6 +86,16 @@ export const AgentPanel: React.FC<AgentPanelProps> = ({
|
|
|
88
86
|
void refreshQueueHistory(selectedAgent.id);
|
|
89
87
|
}, [selectedAgent?.id]);
|
|
90
88
|
|
|
89
|
+
useEffect(() => {
|
|
90
|
+
if (providers.length > 0 && !newAgentConfig.providerId) {
|
|
91
|
+
setNewAgentConfig(prev => ({
|
|
92
|
+
...prev,
|
|
93
|
+
providerId: providers[0].id,
|
|
94
|
+
model: providers[0].models[0]?.id || ''
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
}, [providers]);
|
|
98
|
+
|
|
91
99
|
useEffect(() => {
|
|
92
100
|
const onTaskStarted = (event: any, payload: { agentId: string }) => {
|
|
93
101
|
setInFlightByAgent(prev => ({ ...prev, [payload.agentId]: true }));
|
|
@@ -164,7 +172,6 @@ export const AgentPanel: React.FC<AgentPanelProps> = ({
|
|
|
164
172
|
setInFlightByAgent(prev => ({ ...prev, [agentId]: false }));
|
|
165
173
|
} else {
|
|
166
174
|
await window.electronAPI.agent.executeTask(agentId, claimed.content);
|
|
167
|
-
// keep inFlight until taskCompleted/taskFailed
|
|
168
175
|
}
|
|
169
176
|
} catch (error) {
|
|
170
177
|
console.error('Failed to dispatch queued item:', error);
|
|
@@ -173,7 +180,6 @@ export const AgentPanel: React.FC<AgentPanelProps> = ({
|
|
|
173
180
|
try {
|
|
174
181
|
await window.electronAPI.queue.complete(agentId, claimed.id, 'failed', error instanceof Error ? error.message : String(error));
|
|
175
182
|
} catch {
|
|
176
|
-
// ignore
|
|
177
183
|
}
|
|
178
184
|
setClaimedByAgent(prev => ({ ...prev, [agentId]: null }));
|
|
179
185
|
}
|
|
@@ -201,6 +207,22 @@ export const AgentPanel: React.FC<AgentPanelProps> = ({
|
|
|
201
207
|
}, [selectedAgent?.id]);
|
|
202
208
|
|
|
203
209
|
const handleCreateAgent = async () => {
|
|
210
|
+
if (!newAgentConfig.name.trim()) {
|
|
211
|
+
setCreateError('Agent name is required');
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
if (!newAgentConfig.projectPath.trim()) {
|
|
215
|
+
setCreateError('Project path is required');
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
if (!newAgentConfig.model) {
|
|
219
|
+
setCreateError('Please select a model');
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
setCreateError(null);
|
|
224
|
+
setIsCreating(true);
|
|
225
|
+
|
|
204
226
|
try {
|
|
205
227
|
await onCreateAgent(newAgentConfig);
|
|
206
228
|
setShowCreateModal(false);
|
|
@@ -208,11 +230,14 @@ export const AgentPanel: React.FC<AgentPanelProps> = ({
|
|
|
208
230
|
name: '',
|
|
209
231
|
projectPath: '',
|
|
210
232
|
providerId: providers[0]?.id || '',
|
|
211
|
-
model: '',
|
|
233
|
+
model: providers[0]?.models[0]?.id || '',
|
|
212
234
|
skills: []
|
|
213
235
|
});
|
|
214
236
|
} catch (error) {
|
|
215
237
|
console.error('Failed to create agent:', error);
|
|
238
|
+
setCreateError(error instanceof Error ? error.message : 'Failed to create agent');
|
|
239
|
+
} finally {
|
|
240
|
+
setIsCreating(false);
|
|
216
241
|
}
|
|
217
242
|
};
|
|
218
243
|
|
|
@@ -224,14 +249,6 @@ export const AgentPanel: React.FC<AgentPanelProps> = ({
|
|
|
224
249
|
}
|
|
225
250
|
};
|
|
226
251
|
|
|
227
|
-
const handleExecuteTask = async (agentId: string, task: string) => {
|
|
228
|
-
try {
|
|
229
|
-
await window.electronAPI.agent.executeTask(agentId, task);
|
|
230
|
-
} catch (error) {
|
|
231
|
-
console.error('Failed to execute task:', error);
|
|
232
|
-
}
|
|
233
|
-
};
|
|
234
|
-
|
|
235
252
|
const handleApproveChange = async (changeId: string) => {
|
|
236
253
|
if (!selectedAgent) return;
|
|
237
254
|
try {
|
|
@@ -294,49 +311,48 @@ export const AgentPanel: React.FC<AgentPanelProps> = ({
|
|
|
294
311
|
const getStatusIcon = (status: string) => {
|
|
295
312
|
switch (status) {
|
|
296
313
|
case 'running':
|
|
297
|
-
return <div className="w-2 h-2 bg-
|
|
314
|
+
return <div className="w-2 h-2 bg-[var(--success)] rounded-full animate-pulse" />;
|
|
298
315
|
case 'paused':
|
|
299
|
-
return <div className="w-2 h-2 bg-
|
|
316
|
+
return <div className="w-2 h-2 bg-[var(--warning)] rounded-full" />;
|
|
300
317
|
case 'error':
|
|
301
|
-
return <div className="w-2 h-2 bg-
|
|
318
|
+
return <div className="w-2 h-2 bg-[var(--error)] rounded-full" />;
|
|
302
319
|
default:
|
|
303
|
-
return <div className="w-2 h-2 bg-
|
|
320
|
+
return <div className="w-2 h-2 bg-[var(--text-muted)] rounded-full" />;
|
|
304
321
|
}
|
|
305
322
|
};
|
|
306
323
|
|
|
307
324
|
return (
|
|
308
325
|
<div className="h-full flex">
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
<h2 className="font-semibold">Active Agents</h2>
|
|
326
|
+
<div className="w-80 border-r border-[var(--border-subtle)] bg-[var(--bg-surface)] flex flex-col">
|
|
327
|
+
<div className="p-4 border-b border-[var(--border-faint)] flex items-center justify-between">
|
|
328
|
+
<h2 className="font-medium text-[13px] text-[var(--text-primary)]">Active Agents</h2>
|
|
313
329
|
<button
|
|
314
330
|
onClick={() => setShowCreateModal(true)}
|
|
315
|
-
className="p-2 bg-
|
|
331
|
+
className="p-2 bg-[var(--teal-500)] text-[var(--bg-void)] rounded-[var(--radius-sm)] hover:bg-[var(--teal-400)] transition-colors"
|
|
316
332
|
>
|
|
317
333
|
<Plus className="w-4 h-4" />
|
|
318
334
|
</button>
|
|
319
335
|
</div>
|
|
320
336
|
|
|
321
|
-
<div className="flex-1 overflow-auto p-2 space-y-
|
|
337
|
+
<div className="flex-1 overflow-auto p-2 space-y-1">
|
|
322
338
|
{agents.map(agent => (
|
|
323
339
|
<div
|
|
324
340
|
key={agent.id}
|
|
325
341
|
onClick={() => setSelectedAgent(agent)}
|
|
326
|
-
className={`p-3 rounded-
|
|
342
|
+
className={`p-3 rounded-[var(--radius-md)] cursor-pointer transition-all ${
|
|
327
343
|
selectedAgent?.id === agent.id
|
|
328
|
-
? 'bg-
|
|
329
|
-
: 'hover:bg-
|
|
344
|
+
? 'bg-[rgba(0,200,168,0.08)] border border-[var(--border-accent)]'
|
|
345
|
+
: 'hover:bg-[var(--bg-hover)] border border-transparent'
|
|
330
346
|
}`}
|
|
331
347
|
>
|
|
332
348
|
<div className="flex items-start justify-between">
|
|
333
349
|
<div className="flex items-center gap-2">
|
|
334
|
-
<Bot className="w-4 h-4 text-muted
|
|
335
|
-
<span className="font-medium text-
|
|
350
|
+
<Bot className="w-4 h-4 text-[var(--text-muted)]" />
|
|
351
|
+
<span className="font-medium text-[13px] text-[var(--text-primary)]">{agent.name}</span>
|
|
336
352
|
</div>
|
|
337
353
|
{getStatusIcon(agent.status)}
|
|
338
354
|
</div>
|
|
339
|
-
<div className="mt-2 text-
|
|
355
|
+
<div className="mt-2 text-[11px] text-[var(--text-muted)]">
|
|
340
356
|
<div className="truncate">{agent.projectPath}</div>
|
|
341
357
|
<div className="mt-1">{agent.model}</div>
|
|
342
358
|
</div>
|
|
@@ -344,37 +360,36 @@ export const AgentPanel: React.FC<AgentPanelProps> = ({
|
|
|
344
360
|
))}
|
|
345
361
|
|
|
346
362
|
{agents.length === 0 && (
|
|
347
|
-
<div className="text-center py-8 text-muted
|
|
348
|
-
<Bot className="w-12 h-12 mx-auto mb-2 opacity-
|
|
349
|
-
<p className="text-
|
|
350
|
-
<p className="text-
|
|
363
|
+
<div className="text-center py-8 text-[var(--text-muted)]">
|
|
364
|
+
<Bot className="w-12 h-12 mx-auto mb-2 opacity-30" />
|
|
365
|
+
<p className="text-[13px]">No agents yet</p>
|
|
366
|
+
<p className="text-[11px] mt-1">Create your first agent to get started</p>
|
|
351
367
|
</div>
|
|
352
368
|
)}
|
|
353
369
|
</div>
|
|
354
370
|
</div>
|
|
355
371
|
|
|
356
|
-
{/* Agent Detail View */}
|
|
357
372
|
<div className="flex-1 flex flex-col">
|
|
358
373
|
{selectedAgent ? (
|
|
359
374
|
<>
|
|
360
|
-
<div className="p-4 border-b border-border flex items-center justify-between">
|
|
375
|
+
<div className="p-4 border-b border-[var(--border-subtle)] flex items-center justify-between">
|
|
361
376
|
<div>
|
|
362
|
-
<h2 className="text-
|
|
363
|
-
<p className="text-
|
|
364
|
-
{selectedAgent.projectPath}
|
|
377
|
+
<h2 className="text-[16px] font-medium text-[var(--text-primary)]">{selectedAgent.name}</h2>
|
|
378
|
+
<p className="text-[12px] text-[var(--text-muted)]">
|
|
379
|
+
{selectedAgent.projectPath} · {selectedAgent.model}
|
|
365
380
|
</p>
|
|
366
381
|
</div>
|
|
367
382
|
<div className="flex items-center gap-2">
|
|
368
383
|
<button
|
|
369
384
|
onClick={() => handleSendMessage(selectedAgent.id, 'Hello!')}
|
|
370
|
-
className="px-3 py-1.5 text-
|
|
385
|
+
className="px-3 py-1.5 text-[12px] bg-[var(--teal-500)] text-[var(--bg-void)] rounded-[var(--radius-sm)] hover:bg-[var(--teal-400)] transition-colors flex items-center gap-1"
|
|
371
386
|
>
|
|
372
|
-
<MessageSquare className="w-
|
|
387
|
+
<MessageSquare className="w-3.5 h-3.5" />
|
|
373
388
|
Chat
|
|
374
389
|
</button>
|
|
375
390
|
<button
|
|
376
391
|
onClick={() => onDeleteAgent(selectedAgent.id)}
|
|
377
|
-
className="p-2 text-
|
|
392
|
+
className="p-2 text-[var(--error)] hover:bg-[rgba(232,90,106,0.1)] rounded-[var(--radius-sm)] transition-colors"
|
|
378
393
|
>
|
|
379
394
|
<Trash2 className="w-4 h-4" />
|
|
380
395
|
</button>
|
|
@@ -384,15 +399,15 @@ export const AgentPanel: React.FC<AgentPanelProps> = ({
|
|
|
384
399
|
<div className="flex-1 overflow-auto p-4">
|
|
385
400
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
|
386
401
|
<div className="space-y-4">
|
|
387
|
-
<div className="bg-card border border-border rounded-lg p-
|
|
402
|
+
<div className="bg-[var(--bg-card)] border border-[var(--border-subtle)] rounded-[var(--radius-lg)] p-4">
|
|
388
403
|
<div className="flex items-center justify-between">
|
|
389
404
|
<div>
|
|
390
|
-
<h3 className="text-
|
|
391
|
-
<p className="text-
|
|
405
|
+
<h3 className="text-[13px] font-medium text-[var(--text-primary)]">Queue</h3>
|
|
406
|
+
<p className="text-[11px] text-[var(--text-muted)]">Stack work while the agent is busy</p>
|
|
392
407
|
</div>
|
|
393
|
-
<span className="text-
|
|
408
|
+
<span className="text-[11px] text-[var(--text-muted)]">
|
|
394
409
|
{queueItems.length} queued
|
|
395
|
-
{inFlightByAgent[selectedAgent.id] ? '
|
|
410
|
+
{inFlightByAgent[selectedAgent.id] ? ' · running' : ''}
|
|
396
411
|
</span>
|
|
397
412
|
</div>
|
|
398
413
|
|
|
@@ -400,7 +415,7 @@ export const AgentPanel: React.FC<AgentPanelProps> = ({
|
|
|
400
415
|
<select
|
|
401
416
|
value={newQueueType}
|
|
402
417
|
onChange={e => setNewQueueType(e.target.value as any)}
|
|
403
|
-
className="px-2 py-2 bg-
|
|
418
|
+
className="px-2 py-2 bg-[var(--bg-elevated)] border border-[var(--border-subtle)] rounded-[var(--radius-md)] text-[12px] text-[var(--text-primary)]"
|
|
404
419
|
>
|
|
405
420
|
<option value="task">Task</option>
|
|
406
421
|
<option value="message">Message</option>
|
|
@@ -409,7 +424,7 @@ export const AgentPanel: React.FC<AgentPanelProps> = ({
|
|
|
409
424
|
value={newQueueContent}
|
|
410
425
|
onChange={e => setNewQueueContent(e.target.value)}
|
|
411
426
|
placeholder={newQueueType === 'task' ? 'Describe the task...' : 'Type a message...'}
|
|
412
|
-
className="flex-1 px-3 py-2 bg-
|
|
427
|
+
className="flex-1 px-3 py-2 bg-[var(--bg-elevated)] border border-[var(--border-subtle)] rounded-[var(--radius-md)] text-[12px] text-[var(--text-primary)] placeholder:text-[var(--text-disabled)] focus:outline-none focus:border-[var(--teal-500)]"
|
|
413
428
|
/>
|
|
414
429
|
<button
|
|
415
430
|
onClick={() => {
|
|
@@ -428,7 +443,7 @@ export const AgentPanel: React.FC<AgentPanelProps> = ({
|
|
|
428
443
|
}
|
|
429
444
|
})();
|
|
430
445
|
}}
|
|
431
|
-
className="px-3 py-2 bg-
|
|
446
|
+
className="px-3 py-2 bg-[var(--teal-500)] text-[var(--bg-void)] rounded-[var(--radius-md)] hover:bg-[var(--teal-400)] text-[12px] font-medium transition-colors"
|
|
432
447
|
>
|
|
433
448
|
Add
|
|
434
449
|
</button>
|
|
@@ -436,11 +451,11 @@ export const AgentPanel: React.FC<AgentPanelProps> = ({
|
|
|
436
451
|
|
|
437
452
|
<div className="mt-3 space-y-2 max-h-40 overflow-auto">
|
|
438
453
|
{queueItems.map((item, idx) => (
|
|
439
|
-
<div key={item.id} className="flex items-center gap-2 p-2 bg-
|
|
440
|
-
<span className="text-
|
|
454
|
+
<div key={item.id} className="flex items-center gap-2 p-2 bg-[var(--bg-elevated)] rounded-[var(--radius-md)]">
|
|
455
|
+
<span className="text-[10px] px-2 py-0.5 rounded-full bg-[var(--bg-hover)] border border-[var(--border-subtle)] text-[var(--text-secondary)]">
|
|
441
456
|
{item.type}
|
|
442
457
|
</span>
|
|
443
|
-
<span className="text-
|
|
458
|
+
<span className="text-[12px] flex-1 truncate text-[var(--text-primary)]">{item.content}</span>
|
|
444
459
|
<button
|
|
445
460
|
onClick={() => {
|
|
446
461
|
const agentId = selectedAgent.id;
|
|
@@ -449,56 +464,42 @@ export const AgentPanel: React.FC<AgentPanelProps> = ({
|
|
|
449
464
|
await refreshQueue(agentId);
|
|
450
465
|
})();
|
|
451
466
|
}}
|
|
452
|
-
className="text-
|
|
467
|
+
className="text-[11px] text-[var(--error)] hover:underline"
|
|
453
468
|
>
|
|
454
469
|
Remove
|
|
455
470
|
</button>
|
|
456
|
-
<button
|
|
457
|
-
disabled={idx === 0}
|
|
458
|
-
onClick={() => {
|
|
459
|
-
const agentId = selectedAgent.id;
|
|
460
|
-
(async () => {
|
|
461
|
-
await window.electronAPI.queue.moveUp(agentId, item.id);
|
|
462
|
-
await refreshQueue(agentId);
|
|
463
|
-
})();
|
|
464
|
-
}}
|
|
465
|
-
className="text-xs text-muted-foreground disabled:opacity-50"
|
|
466
|
-
>
|
|
467
|
-
Up
|
|
468
|
-
</button>
|
|
469
471
|
</div>
|
|
470
472
|
))}
|
|
471
473
|
{queueItems.length === 0 && (
|
|
472
|
-
<div className="text-
|
|
474
|
+
<div className="text-[11px] text-[var(--text-muted)]">No queued items</div>
|
|
473
475
|
)}
|
|
474
476
|
</div>
|
|
475
477
|
|
|
476
|
-
{/* Queue History */}
|
|
477
478
|
<div className="mt-3">
|
|
478
479
|
<button
|
|
479
480
|
onClick={() => setShowQueueHistory(!showQueueHistory)}
|
|
480
|
-
className="text-
|
|
481
|
+
className="text-[11px] text-[var(--text-muted)] hover:text-[var(--text-secondary)]"
|
|
481
482
|
>
|
|
482
483
|
{showQueueHistory ? 'Hide' : 'Show'} history ({queueHistory.length})
|
|
483
484
|
</button>
|
|
484
485
|
{showQueueHistory && (
|
|
485
486
|
<div className="mt-2 space-y-1 max-h-32 overflow-auto">
|
|
486
487
|
{queueHistory.map(item => (
|
|
487
|
-
<div key={item.id} className="flex items-center gap-2 p-2 bg-
|
|
488
|
+
<div key={item.id} className="flex items-center gap-2 p-2 bg-[var(--bg-elevated)] rounded-[var(--radius-md)] text-[11px]">
|
|
488
489
|
<span className={`px-1.5 py-0.5 rounded-full ${
|
|
489
|
-
item.status === 'completed' ? 'bg-
|
|
490
|
+
item.status === 'completed' ? 'bg-[rgba(60,200,120,0.1)] text-[var(--success)]' : 'bg-[rgba(232,90,106,0.1)] text-[var(--error)]'
|
|
490
491
|
}`}>
|
|
491
492
|
{item.status}
|
|
492
493
|
</span>
|
|
493
|
-
<span className="text-muted
|
|
494
|
-
<span className="flex-1 truncate">{item.content}</span>
|
|
494
|
+
<span className="text-[var(--text-muted)]">{item.type}</span>
|
|
495
|
+
<span className="flex-1 truncate text-[var(--text-primary)]">{item.content}</span>
|
|
495
496
|
{item.error && (
|
|
496
|
-
<span className="text-
|
|
497
|
+
<span className="text-[var(--error)] truncate" title={item.error}>⚠️</span>
|
|
497
498
|
)}
|
|
498
499
|
</div>
|
|
499
500
|
))}
|
|
500
501
|
{queueHistory.length === 0 && (
|
|
501
|
-
<div className="text-
|
|
502
|
+
<div className="text-[11px] text-[var(--text-muted)]">No completed items yet</div>
|
|
502
503
|
)}
|
|
503
504
|
</div>
|
|
504
505
|
)}
|
|
@@ -506,13 +507,13 @@ export const AgentPanel: React.FC<AgentPanelProps> = ({
|
|
|
506
507
|
</div>
|
|
507
508
|
|
|
508
509
|
<div>
|
|
509
|
-
<h3 className="text-
|
|
510
|
+
<h3 className="text-[12px] font-medium text-[var(--text-secondary)] mb-2">Status</h3>
|
|
510
511
|
<div className="flex items-center gap-2">
|
|
511
|
-
<span className={`px-2 py-1 rounded-full text-
|
|
512
|
-
selectedAgent.status === 'running' ? 'bg-
|
|
513
|
-
selectedAgent.status === 'paused' ? 'bg-
|
|
514
|
-
selectedAgent.status === 'error' ? 'bg-
|
|
515
|
-
'bg-
|
|
512
|
+
<span className={`px-2 py-1 rounded-full text-[11px] font-medium ${
|
|
513
|
+
selectedAgent.status === 'running' ? 'bg-[rgba(60,200,120,0.1)] text-[var(--success)]' :
|
|
514
|
+
selectedAgent.status === 'paused' ? 'bg-[rgba(230,185,74,0.1)] text-[var(--warning)]' :
|
|
515
|
+
selectedAgent.status === 'error' ? 'bg-[rgba(232,90,106,0.1)] text-[var(--error)]' :
|
|
516
|
+
'bg-[var(--bg-hover)] text-[var(--text-muted)]'
|
|
516
517
|
}`}>
|
|
517
518
|
{selectedAgent.status}
|
|
518
519
|
</span>
|
|
@@ -520,48 +521,48 @@ export const AgentPanel: React.FC<AgentPanelProps> = ({
|
|
|
520
521
|
</div>
|
|
521
522
|
|
|
522
523
|
<div>
|
|
523
|
-
<h3 className="text-
|
|
524
|
+
<h3 className="text-[12px] font-medium text-[var(--text-secondary)] mb-2">Skills</h3>
|
|
524
525
|
<div className="flex flex-wrap gap-2">
|
|
525
526
|
{selectedAgent.skills.map(skillId => {
|
|
526
527
|
const skill = skills.find(s => s.id === skillId);
|
|
527
528
|
return (
|
|
528
529
|
<span
|
|
529
530
|
key={skillId}
|
|
530
|
-
className="px-2 py-1 bg-
|
|
531
|
+
className="px-2 py-1 bg-[var(--bg-hover)] rounded-[var(--radius-sm)] text-[11px] text-[var(--text-secondary)]"
|
|
531
532
|
>
|
|
532
533
|
{skill?.name || skillId}
|
|
533
534
|
</span>
|
|
534
535
|
);
|
|
535
536
|
})}
|
|
536
537
|
{selectedAgent.skills.length === 0 && (
|
|
537
|
-
<span className="text-
|
|
538
|
+
<span className="text-[12px] text-[var(--text-muted)]">No skills applied</span>
|
|
538
539
|
)}
|
|
539
540
|
</div>
|
|
540
541
|
</div>
|
|
541
542
|
|
|
542
543
|
<div>
|
|
543
|
-
<h3 className="text-
|
|
544
|
+
<h3 className="text-[12px] font-medium text-[var(--text-secondary)] mb-2">Recent Tasks</h3>
|
|
544
545
|
<div className="space-y-2">
|
|
545
546
|
{selectedAgent.tasks.slice(-5).map(task => (
|
|
546
547
|
<div
|
|
547
548
|
key={task.id}
|
|
548
|
-
className="p-3 bg-
|
|
549
|
+
className="p-3 bg-[var(--bg-card)] border border-[var(--border-subtle)] rounded-[var(--radius-md)]"
|
|
549
550
|
>
|
|
550
551
|
<div className="flex items-center justify-between">
|
|
551
|
-
<span className="text-
|
|
552
|
-
<span className={`text-
|
|
553
|
-
task.status === 'completed' ? 'text-
|
|
554
|
-
task.status === 'failed' ? 'text-
|
|
555
|
-
task.status === 'running' ? 'text-
|
|
556
|
-
'text-muted
|
|
552
|
+
<span className="text-[12px] font-medium text-[var(--text-primary)]">{task.description}</span>
|
|
553
|
+
<span className={`text-[11px] ${
|
|
554
|
+
task.status === 'completed' ? 'text-[var(--success)]' :
|
|
555
|
+
task.status === 'failed' ? 'text-[var(--error)]' :
|
|
556
|
+
task.status === 'running' ? 'text-[var(--info)]' :
|
|
557
|
+
'text-[var(--text-muted)]'
|
|
557
558
|
}`}>
|
|
558
559
|
{task.status}
|
|
559
560
|
</span>
|
|
560
561
|
</div>
|
|
561
562
|
{task.status === 'running' && (
|
|
562
|
-
<div className="mt-2 h-1 bg-
|
|
563
|
+
<div className="mt-2 h-1 bg-[var(--bg-hover)] rounded-full overflow-hidden">
|
|
563
564
|
<div
|
|
564
|
-
className="h-full bg-
|
|
565
|
+
className="h-full bg-[var(--teal-500)] transition-all"
|
|
565
566
|
style={{ width: `${task.progress}%` }}
|
|
566
567
|
/>
|
|
567
568
|
</div>
|
|
@@ -569,17 +570,17 @@ export const AgentPanel: React.FC<AgentPanelProps> = ({
|
|
|
569
570
|
</div>
|
|
570
571
|
))}
|
|
571
572
|
{selectedAgent.tasks.length === 0 && (
|
|
572
|
-
<span className="text-
|
|
573
|
+
<span className="text-[12px] text-[var(--text-muted)]">No tasks yet</span>
|
|
573
574
|
)}
|
|
574
575
|
</div>
|
|
575
576
|
</div>
|
|
576
577
|
</div>
|
|
577
578
|
|
|
578
|
-
<div className="bg-card border border-border rounded-lg overflow-hidden min-h-[420px]">
|
|
579
|
-
<div className="p-3 border-b border-border flex items-center justify-between">
|
|
579
|
+
<div className="bg-[var(--bg-card)] border border-[var(--border-subtle)] rounded-[var(--radius-lg)] overflow-hidden min-h-[420px]">
|
|
580
|
+
<div className="p-3 border-b border-[var(--border-subtle)] flex items-center justify-between">
|
|
580
581
|
<div>
|
|
581
|
-
<h3 className="text-
|
|
582
|
-
<p className="text-
|
|
582
|
+
<h3 className="text-[13px] font-medium text-[var(--text-primary)]">Changes</h3>
|
|
583
|
+
<p className="text-[11px] text-[var(--text-muted)]">
|
|
583
584
|
Review and apply changes generated by the agent
|
|
584
585
|
</p>
|
|
585
586
|
</div>
|
|
@@ -606,12 +607,12 @@ export const AgentPanel: React.FC<AgentPanelProps> = ({
|
|
|
606
607
|
});
|
|
607
608
|
}
|
|
608
609
|
}}
|
|
609
|
-
className="px-3 py-1.5 text-
|
|
610
|
+
className="px-3 py-1.5 text-[11px] bg-[var(--bg-hover)] hover:bg-[var(--bg-active)] rounded-[var(--radius-sm)] text-[var(--text-secondary)] transition-colors"
|
|
610
611
|
>
|
|
611
612
|
Undo last apply
|
|
612
613
|
</button>
|
|
613
614
|
{changesLoading && (
|
|
614
|
-
<span className="text-
|
|
615
|
+
<span className="text-[11px] text-[var(--text-muted)]">Loading...</span>
|
|
615
616
|
)}
|
|
616
617
|
</div>
|
|
617
618
|
|
|
@@ -628,41 +629,40 @@ export const AgentPanel: React.FC<AgentPanelProps> = ({
|
|
|
628
629
|
</div>
|
|
629
630
|
</>
|
|
630
631
|
) : (
|
|
631
|
-
<div className="flex-1 flex items-center justify-center text-muted
|
|
632
|
+
<div className="flex-1 flex items-center justify-center text-[var(--text-muted)]">
|
|
632
633
|
<div className="text-center">
|
|
633
634
|
<Bot className="w-16 h-16 mx-auto mb-4 opacity-30" />
|
|
634
|
-
<p>Select an agent to view details</p>
|
|
635
|
+
<p className="text-[14px]">Select an agent to view details</p>
|
|
635
636
|
</div>
|
|
636
637
|
</div>
|
|
637
638
|
)}
|
|
638
639
|
</div>
|
|
639
640
|
|
|
640
|
-
{/* Create Agent Modal */}
|
|
641
641
|
{showCreateModal && (
|
|
642
|
-
<div className="fixed inset-0 bg-
|
|
643
|
-
<div className="bg-card border border-border rounded-lg p-6 w-[500px] max-w-[90vw]">
|
|
644
|
-
<h2 className="text-
|
|
642
|
+
<div className="fixed inset-0 bg-[rgba(3,7,9,0.8)] flex items-center justify-center z-50">
|
|
643
|
+
<div className="bg-[var(--bg-card)] border border-[var(--border-subtle)] rounded-[var(--radius-lg)] p-6 w-[500px] max-w-[90vw]">
|
|
644
|
+
<h2 className="text-[16px] font-medium text-[var(--text-primary)] mb-4">Create New Agent</h2>
|
|
645
645
|
|
|
646
646
|
<div className="space-y-4">
|
|
647
647
|
<div>
|
|
648
|
-
<label className="block text-
|
|
648
|
+
<label className="block text-[11px] font-medium text-[var(--text-secondary)] mb-1">Name</label>
|
|
649
649
|
<input
|
|
650
650
|
type="text"
|
|
651
651
|
value={newAgentConfig.name}
|
|
652
652
|
onChange={e => setNewAgentConfig({ ...newAgentConfig, name: e.target.value })}
|
|
653
|
-
className="w-full px-3 py-2 bg-
|
|
653
|
+
className="w-full px-3 py-2 bg-[var(--bg-elevated)] border border-[var(--border-subtle)] rounded-[var(--radius-md)] text-[13px] text-[var(--text-primary)] placeholder:text-[var(--text-disabled)] focus:outline-none focus:border-[var(--teal-500)]"
|
|
654
654
|
placeholder="My Coding Agent"
|
|
655
655
|
/>
|
|
656
656
|
</div>
|
|
657
657
|
|
|
658
658
|
<div>
|
|
659
|
-
<label className="block text-
|
|
659
|
+
<label className="block text-[11px] font-medium text-[var(--text-secondary)] mb-1">Project Path</label>
|
|
660
660
|
<div className="flex gap-2">
|
|
661
661
|
<input
|
|
662
662
|
type="text"
|
|
663
663
|
value={newAgentConfig.projectPath}
|
|
664
664
|
onChange={e => setNewAgentConfig({ ...newAgentConfig, projectPath: e.target.value })}
|
|
665
|
-
className="flex-1 px-3 py-2 bg-
|
|
665
|
+
className="flex-1 px-3 py-2 bg-[var(--bg-elevated)] border border-[var(--border-subtle)] rounded-[var(--radius-md)] text-[13px] text-[var(--text-primary)] placeholder:text-[var(--text-disabled)] focus:outline-none focus:border-[var(--teal-500)]"
|
|
666
666
|
placeholder="/path/to/project"
|
|
667
667
|
/>
|
|
668
668
|
<button
|
|
@@ -670,7 +670,7 @@ export const AgentPanel: React.FC<AgentPanelProps> = ({
|
|
|
670
670
|
const path = await window.electronAPI.dialog.selectFolder();
|
|
671
671
|
if (path) setNewAgentConfig({ ...newAgentConfig, projectPath: path });
|
|
672
672
|
}}
|
|
673
|
-
className="px-3 py-2 bg-
|
|
673
|
+
className="px-3 py-2 bg-[var(--bg-hover)] rounded-[var(--radius-md)] hover:bg-[var(--bg-active)] text-[13px] text-[var(--text-secondary)] transition-colors"
|
|
674
674
|
>
|
|
675
675
|
Browse
|
|
676
676
|
</button>
|
|
@@ -678,7 +678,7 @@ export const AgentPanel: React.FC<AgentPanelProps> = ({
|
|
|
678
678
|
</div>
|
|
679
679
|
|
|
680
680
|
<div>
|
|
681
|
-
<label className="block text-
|
|
681
|
+
<label className="block text-[11px] font-medium text-[var(--text-secondary)] mb-1">Provider</label>
|
|
682
682
|
<select
|
|
683
683
|
value={newAgentConfig.providerId}
|
|
684
684
|
onChange={e => {
|
|
@@ -689,7 +689,7 @@ export const AgentPanel: React.FC<AgentPanelProps> = ({
|
|
|
689
689
|
model: provider?.models[0]?.id || ''
|
|
690
690
|
});
|
|
691
691
|
}}
|
|
692
|
-
className="w-full px-3 py-2 bg-
|
|
692
|
+
className="w-full px-3 py-2 bg-[var(--bg-elevated)] border border-[var(--border-subtle)] rounded-[var(--radius-md)] text-[13px] text-[var(--text-primary)]"
|
|
693
693
|
>
|
|
694
694
|
{providers.map(provider => (
|
|
695
695
|
<option key={provider.id} value={provider.id}>{provider.name}</option>
|
|
@@ -698,11 +698,11 @@ export const AgentPanel: React.FC<AgentPanelProps> = ({
|
|
|
698
698
|
</div>
|
|
699
699
|
|
|
700
700
|
<div>
|
|
701
|
-
<label className="block text-
|
|
701
|
+
<label className="block text-[11px] font-medium text-[var(--text-secondary)] mb-1">Model</label>
|
|
702
702
|
<select
|
|
703
703
|
value={newAgentConfig.model}
|
|
704
704
|
onChange={e => setNewAgentConfig({ ...newAgentConfig, model: e.target.value })}
|
|
705
|
-
className="w-full px-3 py-2 bg-
|
|
705
|
+
className="w-full px-3 py-2 bg-[var(--bg-elevated)] border border-[var(--border-subtle)] rounded-[var(--radius-md)] text-[13px] text-[var(--text-primary)]"
|
|
706
706
|
>
|
|
707
707
|
{providers
|
|
708
708
|
.find(p => p.id === newAgentConfig.providerId)
|
|
@@ -713,7 +713,7 @@ export const AgentPanel: React.FC<AgentPanelProps> = ({
|
|
|
713
713
|
</div>
|
|
714
714
|
|
|
715
715
|
<div>
|
|
716
|
-
<label className="block text-
|
|
716
|
+
<label className="block text-[11px] font-medium text-[var(--text-secondary)] mb-1">Skills</label>
|
|
717
717
|
<div className="flex flex-wrap gap-2">
|
|
718
718
|
{skills.map(skill => (
|
|
719
719
|
<button
|
|
@@ -724,10 +724,10 @@ export const AgentPanel: React.FC<AgentPanelProps> = ({
|
|
|
724
724
|
: [...newAgentConfig.skills, skill.id];
|
|
725
725
|
setNewAgentConfig({ ...newAgentConfig, skills: newSkills });
|
|
726
726
|
}}
|
|
727
|
-
className={`px-3 py-1.5 rounded-
|
|
727
|
+
className={`px-3 py-1.5 rounded-[var(--radius-sm)] text-[12px] transition-colors ${
|
|
728
728
|
newAgentConfig.skills.includes(skill.id)
|
|
729
|
-
? 'bg-
|
|
730
|
-
: 'bg-
|
|
729
|
+
? 'bg-[var(--teal-500)] text-[var(--bg-void)]'
|
|
730
|
+
: 'bg-[var(--bg-hover)] text-[var(--text-secondary)] hover:bg-[var(--bg-active)]'
|
|
731
731
|
}`}
|
|
732
732
|
>
|
|
733
733
|
{skill.name}
|
|
@@ -737,19 +737,35 @@ export const AgentPanel: React.FC<AgentPanelProps> = ({
|
|
|
737
737
|
</div>
|
|
738
738
|
</div>
|
|
739
739
|
|
|
740
|
+
{createError && (
|
|
741
|
+
<div className="mt-4 p-3 bg-[rgba(232,90,106,0.1)] border border-[rgba(232,90,106,0.3)] rounded-[var(--radius-md)]">
|
|
742
|
+
<p className="text-[12px] text-[var(--error)]">{createError}</p>
|
|
743
|
+
</div>
|
|
744
|
+
)}
|
|
745
|
+
|
|
740
746
|
<div className="flex justify-end gap-2 mt-6">
|
|
741
747
|
<button
|
|
742
|
-
onClick={() =>
|
|
743
|
-
|
|
748
|
+
onClick={() => {
|
|
749
|
+
setShowCreateModal(false);
|
|
750
|
+
setCreateError(null);
|
|
751
|
+
}}
|
|
752
|
+
className="px-4 py-2 text-[var(--text-muted)] hover:text-[var(--text-primary)] text-[13px] transition-colors"
|
|
744
753
|
>
|
|
745
754
|
Cancel
|
|
746
755
|
</button>
|
|
747
756
|
<button
|
|
748
757
|
onClick={handleCreateAgent}
|
|
749
|
-
disabled={!newAgentConfig.name || !newAgentConfig.projectPath}
|
|
750
|
-
className="px-4 py-2 bg-
|
|
758
|
+
disabled={isCreating || !newAgentConfig.name || !newAgentConfig.projectPath}
|
|
759
|
+
className="px-4 py-2 bg-[var(--teal-500)] text-[var(--bg-void)] rounded-[var(--radius-sm)] hover:bg-[var(--teal-400)] disabled:opacity-50 text-[13px] font-medium transition-colors flex items-center gap-2"
|
|
751
760
|
>
|
|
752
|
-
|
|
761
|
+
{isCreating ? (
|
|
762
|
+
<>
|
|
763
|
+
<div className="w-4 h-4 border-2 border-[var(--bg-void)] border-t-transparent rounded-full animate-spin" />
|
|
764
|
+
Creating...
|
|
765
|
+
</>
|
|
766
|
+
) : (
|
|
767
|
+
'Create Agent'
|
|
768
|
+
)}
|
|
753
769
|
</button>
|
|
754
770
|
</div>
|
|
755
771
|
</div>
|
|
@@ -757,4 +773,4 @@ export const AgentPanel: React.FC<AgentPanelProps> = ({
|
|
|
757
773
|
)}
|
|
758
774
|
</div>
|
|
759
775
|
);
|
|
760
|
-
};
|
|
776
|
+
};
|