codex-linux 1.0.0 → 1.0.2

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.
@@ -1,6 +1,6 @@
1
1
  import React, { useState, useRef, useEffect } from 'react';
2
- import { Agent, AgentMessage, AgentStatus, PermissionMode } from '../../shared/types';
3
- import { Send, Bot, User, Loader2, Paperclip, MoreVertical, Copy, Check, ChevronDown, Sparkles, Zap } from 'lucide-react';
2
+ import { Agent, AgentMessage, PermissionMode } from '../../shared/types';
3
+ import { Send, Bot, User, Loader2, Paperclip, MoreVertical, Copy, Check, ChevronDown, Sparkles } from 'lucide-react';
4
4
  import { format } from 'date-fns';
5
5
  import { PermissionSelector } from './PermissionSelector';
6
6
 
@@ -29,34 +29,17 @@ const FREE_MODELS: ModelOption[] = [
29
29
  { id: 'meta-llama/llama-3.3-70b-instruct:free', name: 'Llama 3.3 70B', backend: 'openrouter', isFree: true, contextWindow: 128000 },
30
30
  { id: 'deepseek/deepseek-r1-0528:free', name: 'DeepSeek R1', backend: 'openrouter', isFree: true, contextWindow: 128000 },
31
31
  { id: 'google/gemma-3-27b-it:free', name: 'Gemma 3 27B', backend: 'openrouter', isFree: true, contextWindow: 32768 },
32
- { id: 'google/gemma-3-12b-it:free', name: 'Gemma 3 12B', backend: 'openrouter', isFree: true, contextWindow: 32768 },
33
32
  { id: 'mistralai/mistral-small-3.1-24b-instruct:free', name: 'Mistral Small 3.1', backend: 'openrouter', isFree: true, contextWindow: 128000, supportsVision: true },
34
33
  { id: 'qwen/qwen3-coder:free', name: 'Qwen 3 Coder', backend: 'openrouter', isFree: true, contextWindow: 32768 },
35
- { id: 'nousresearch/hermes-3-llama-3.1-405b:free', name: 'Hermes 3 405B', backend: 'openrouter', isFree: true, contextWindow: 128000 },
36
34
  { id: 'openai/gpt-oss-120b:free', name: 'GPT-OSS 120B', backend: 'openrouter', isFree: true, contextWindow: 128000 },
37
- { id: 'nvidia/nemotron-nano-12b-v2-vl:free', name: 'Nemotron 12B VL', backend: 'openrouter', isFree: true, contextWindow: 32768, supportsVision: true },
38
35
  { id: 'z-ai/glm-4.5-air:free', name: 'GLM 4.5 Air', backend: 'openrouter', isFree: true, contextWindow: 128000 },
39
- { id: 'liquid/lfm-2.5-1.2b-instruct:free', name: 'LFM 2.5 1.2B', backend: 'openrouter', isFree: true, contextWindow: 8192 },
40
- { id: 'upstage/solar-pro-3:free', name: 'Solar Pro 3', backend: 'openrouter', isFree: true, contextWindow: 32768 },
41
- { id: 'moonshotai/kimi-k2.5', name: 'Kimi K2.5', backend: 'nvidia', isFree: true, contextWindow: 128000 },
42
- { id: 'meta/llama-3.3-70b-instruct', name: 'Llama 3.3 70B (NVIDIA)', backend: 'nvidia', isFree: true, contextWindow: 128000 },
43
- { id: 'google/gemma-2-27b-it', name: 'Gemma 2 27B (NVIDIA)', backend: 'nvidia', isFree: true, contextWindow: 8192 },
44
- { id: 'microsoft/phi-3-medium-128k-instruct', name: 'Phi-3 Medium 128K', backend: 'nvidia', isFree: true, contextWindow: 128000 },
45
36
  { id: 'llama-3.3-70b-versatile', name: 'Llama 3.3 70B (Groq)', backend: 'groq', isFree: true, contextWindow: 128000 },
46
- { id: 'llama-3.1-8b-instant', name: 'Llama 3.1 8B (Groq)', backend: 'groq', isFree: true, contextWindow: 128000 },
47
- { id: 'mixtral-8x7b-32768', name: 'Mixtral 8x7B (Groq)', backend: 'groq', isFree: true, contextWindow: 32768 },
48
- { id: 'gemma2-9b-it', name: 'Gemma 2 9B (Groq)', backend: 'groq', isFree: true, contextWindow: 8192 },
49
- { id: 'minimax-m2.5:cloud', name: 'Minimax M2.5 (Ollama)', backend: 'ollama', isFree: true, contextWindow: 128000 },
50
37
  { id: 'llama3.2:latest', name: 'Llama 3.2 (Ollama)', backend: 'ollama', isFree: true, contextWindow: 128000, supportsVision: true },
51
38
  { id: 'llama3.3:latest', name: 'Llama 3.3 70B (Ollama)', backend: 'ollama', isFree: true, contextWindow: 128000 },
52
39
  { id: 'mistral:latest', name: 'Mistral 7B (Ollama)', backend: 'ollama', isFree: true, contextWindow: 32768 },
53
40
  { id: 'deepseek-r1:latest', name: 'DeepSeek R1 (Ollama)', backend: 'ollama', isFree: true, contextWindow: 128000 },
54
41
  { id: 'qwen2.5:latest', name: 'Qwen 2.5 (Ollama)', backend: 'ollama', isFree: true, contextWindow: 128000 },
55
- { id: 'qwen2.5-coder:latest', name: 'Qwen 2.5 Coder (Ollama)', backend: 'ollama', isFree: true, contextWindow: 32768 },
56
- { id: 'gemma3:latest', name: 'Gemma 3 (Ollama)', backend: 'ollama', isFree: true, contextWindow: 32768, supportsVision: true },
57
- { id: 'phi3:latest', name: 'Phi-3 (Ollama)', backend: 'ollama', isFree: true, contextWindow: 128000 },
58
42
  { id: 'codellama:latest', name: 'Code Llama (Ollama)', backend: 'ollama', isFree: true, contextWindow: 16384 },
59
- { id: 'deepseek-coder:latest', name: 'DeepSeek Coder (Ollama)', backend: 'ollama', isFree: true, contextWindow: 16384 },
60
43
  ];
61
44
 
62
45
  const BACKEND_LABELS: Record<string, string> = {
@@ -159,21 +142,6 @@ export const ChatInterface: React.FC<ChatInterfaceProps> = ({
159
142
  }
160
143
  };
161
144
 
162
- const handleImageUpload = async (file: File) => {
163
- if (isLoading) return;
164
-
165
- try {
166
- const reader = new FileReader();
167
- reader.onloadend = async () => {
168
- const base64 = reader.result as string;
169
- await onSendMessage(`[IMAGE] ${base64}`);
170
- };
171
- reader.readAsDataURL(file);
172
- } catch (error) {
173
- console.error('Failed to upload image:', error);
174
- }
175
- };
176
-
177
145
  const handleKeyDown = (e: React.KeyboardEvent) => {
178
146
  if (e.key === 'Enter' && !e.shiftKey) {
179
147
  e.preventDefault();
@@ -212,7 +180,7 @@ export const ChatInterface: React.FC<ChatInterfaceProps> = ({
212
180
  <p key={index} className="my-1">
213
181
  {parts.map((part, i) =>
214
182
  part.startsWith('`') && part.endsWith('`') ? (
215
- <code key={i} className="bg-muted px-1 py-0.5 rounded text-sm font-mono">
183
+ <code key={i} className="bg-[var(--bg-hover)] px-1 py-0.5 rounded text-[11px] font-[var(--font-mono)] text-[var(--teal-300)]">
216
184
  {part.slice(1, -1)}
217
185
  </code>
218
186
  ) : (
@@ -224,24 +192,24 @@ export const ChatInterface: React.FC<ChatInterfaceProps> = ({
224
192
  }
225
193
 
226
194
  if (line.startsWith('### ')) {
227
- return <h3 key={index} className="text-lg font-semibold mt-4 mb-2">{line.slice(4)}</h3>;
195
+ return <h3 key={index} className="text-[15px] font-semibold mt-4 mb-2 text-[var(--text-primary)]">{line.slice(4)}</h3>;
228
196
  }
229
197
  if (line.startsWith('## ')) {
230
- return <h2 key={index} className="text-xl font-semibold mt-4 mb-2">{line.slice(3)}</h2>;
198
+ return <h2 key={index} className="text-[17px] font-semibold mt-4 mb-2 text-[var(--text-primary)]">{line.slice(3)}</h2>;
231
199
  }
232
200
  if (line.startsWith('# ')) {
233
- return <h1 key={index} className="text-2xl font-bold mt-4 mb-2">{line.slice(2)}</h1>;
201
+ return <h1 key={index} className="text-[19px] font-bold mt-4 mb-2 text-[var(--text-primary)]">{line.slice(2)}</h1>;
234
202
  }
235
203
 
236
204
  if (line.startsWith('- ') || line.startsWith('* ')) {
237
- return <li key={index} className="ml-4 my-1">{line.slice(2)}</li>;
205
+ return <li key={index} className="ml-4 my-1 text-[var(--text-secondary)]">{line.slice(2)}</li>;
238
206
  }
239
207
 
240
208
  if (line.trim() === '') {
241
209
  return <br key={index} />;
242
210
  }
243
211
 
244
- return <p key={index} className="my-1">{line}</p>;
212
+ return <p key={index} className="my-1 text-[var(--text-secondary)]">{line}</p>;
245
213
  });
246
214
  };
247
215
 
@@ -261,50 +229,48 @@ export const ChatInterface: React.FC<ChatInterfaceProps> = ({
261
229
  const currentModelInfo = getCurrentModelInfo();
262
230
 
263
231
  return (
264
- <div className="flex flex-col h-full bg-card">
265
- {/* Chat Header */}
266
- <div className="px-4 py-3 border-b border-border flex items-center justify-between bg-background/50">
232
+ <div className="flex flex-col h-full bg-[var(--bg-primary)]">
233
+ <div className="px-4 py-3 border-b border-[var(--border-subtle)] flex items-center justify-between bg-[var(--bg-surface)]">
267
234
  <div className="flex items-center gap-3">
268
235
  <div className={`w-2 h-2 rounded-full ${
269
- agent.status === 'running' ? 'bg-green-500 animate-pulse' :
270
- agent.status === 'error' ? 'bg-red-500' :
271
- agent.status === 'paused' ? 'bg-yellow-500' :
272
- 'bg-gray-400'
236
+ agent.status === 'running' ? 'bg-[var(--success)] animate-pulse' :
237
+ agent.status === 'error' ? 'bg-[var(--error)]' :
238
+ agent.status === 'paused' ? 'bg-[var(--warning)]' :
239
+ 'bg-[var(--text-muted)]'
273
240
  }`} />
274
241
  <div>
275
- <h3 className="font-medium">{agent.name}</h3>
242
+ <h3 className="font-medium text-[13px] text-[var(--text-primary)]">{agent.name}</h3>
276
243
  </div>
277
244
  </div>
278
245
 
279
- {/* Model Selector */}
280
246
  <div className="relative" ref={modelSelectorRef}>
281
247
  <button
282
248
  onClick={() => setShowModelSelector(!showModelSelector)}
283
- className="flex items-center gap-2 px-3 py-1.5 bg-muted hover:bg-muted/80 rounded-lg transition-colors text-sm"
249
+ className="flex items-center gap-2 px-3 py-1.5 bg-[var(--bg-elevated)] hover:bg-[var(--bg-hover)] rounded-lg transition-colors text-[12px] border border-[var(--border-subtle)]"
284
250
  >
285
- <Sparkles className="w-4 h-4 text-green-500" />
286
- <span className="font-medium truncate max-w-[150px]">{currentModelInfo.name}</span>
287
- <span className="text-xs text-muted-foreground px-1.5 py-0.5 bg-background rounded">
251
+ <Sparkles className="w-3.5 h-3.5 text-[var(--success)]" />
252
+ <span className="font-medium truncate max-w-[150px] text-[var(--text-primary)]">{currentModelInfo.name}</span>
253
+ <span className="text-[10px] text-[var(--text-muted)] px-1.5 py-0.5 bg-[var(--bg-hover)] rounded">
288
254
  {BACKEND_LABELS[currentModelInfo.backend || 'unknown'] || currentModelInfo.backend}
289
255
  </span>
290
- <ChevronDown className={`w-4 h-4 transition-transform ${showModelSelector ? 'rotate-180' : ''}`} />
256
+ <ChevronDown className={`w-3.5 h-3.5 text-[var(--text-muted)] transition-transform ${showModelSelector ? 'rotate-180' : ''}`} />
291
257
  </button>
292
258
 
293
259
  {showModelSelector && (
294
- <div className="absolute top-full right-0 mt-2 w-80 bg-background border border-border rounded-lg shadow-xl z-50 max-h-[70vh] overflow-hidden">
295
- <div className="p-3 border-b border-border">
260
+ <div className="absolute top-full right-0 mt-2 w-80 bg-[var(--bg-card)] border border-[var(--border-subtle)] rounded-[var(--radius-lg)] shadow-xl z-50 max-h-[70vh] overflow-hidden">
261
+ <div className="p-3 border-b border-[var(--border-subtle)]">
296
262
  <input
297
263
  type="text"
298
264
  placeholder="Search models..."
299
265
  value={searchQuery}
300
266
  onChange={(e) => setSearchQuery(e.target.value)}
301
- className="w-full px-3 py-2 bg-muted rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-primary"
267
+ className="w-full px-3 py-2 bg-[var(--bg-elevated)] rounded-[var(--radius-md)] text-[12px] text-[var(--text-primary)] placeholder:text-[var(--text-muted)] focus:outline-none focus:border-[var(--teal-500)] border border-[var(--border-subtle)]"
302
268
  />
303
269
  <div className="flex gap-1 mt-2 flex-wrap">
304
270
  <button
305
271
  onClick={() => setSelectedBackend('all')}
306
- className={`px-2 py-1 text-xs rounded-md transition-colors ${
307
- selectedBackend === 'all' ? 'bg-primary text-primary-foreground' : 'bg-muted hover:bg-muted/80'
272
+ className={`px-2 py-1 text-[10px] rounded-md transition-colors ${
273
+ selectedBackend === 'all' ? 'bg-[var(--teal-500)] text-[var(--bg-void)]' : 'bg-[var(--bg-hover)] hover:bg-[var(--bg-active)] text-[var(--text-secondary)]'
308
274
  }`}
309
275
  >
310
276
  All
@@ -313,8 +279,8 @@ export const ChatInterface: React.FC<ChatInterfaceProps> = ({
313
279
  <button
314
280
  key={key}
315
281
  onClick={() => setSelectedBackend(key)}
316
- className={`px-2 py-1 text-xs rounded-md transition-colors ${
317
- selectedBackend === key ? 'bg-primary text-primary-foreground' : 'bg-muted hover:bg-muted/80'
282
+ className={`px-2 py-1 text-[10px] rounded-md transition-colors ${
283
+ selectedBackend === key ? 'bg-[var(--teal-500)] text-[var(--bg-void)]' : 'bg-[var(--bg-hover)] hover:bg-[var(--bg-active)] text-[var(--text-secondary)]'
318
284
  }`}
319
285
  >
320
286
  {label}
@@ -326,40 +292,40 @@ export const ChatInterface: React.FC<ChatInterfaceProps> = ({
326
292
  <div className="overflow-y-auto max-h-[50vh]">
327
293
  {Object.entries(groupedModels).map(([backend, backendModels]) => (
328
294
  <div key={backend}>
329
- <div className="px-3 py-2 bg-muted/50 text-xs font-medium text-muted-foreground sticky top-0">
295
+ <div className="px-3 py-2 bg-[var(--bg-elevated)] text-[10px] font-medium text-[var(--text-muted)] sticky top-0">
330
296
  {BACKEND_LABELS[backend] || backend} ({backendModels.length})
331
297
  </div>
332
298
  {backendModels.map((model) => (
333
299
  <button
334
300
  key={model.id}
335
301
  onClick={() => handleModelSelect(model.id)}
336
- className={`w-full px-3 py-2 text-left hover:bg-muted/50 transition-colors flex items-center justify-between ${
337
- selectedModel === model.id ? 'bg-primary/10' : ''
302
+ className={`w-full px-3 py-2 text-left hover:bg-[var(--bg-hover)] transition-colors flex items-center justify-between ${
303
+ selectedModel === model.id ? 'bg-[rgba(0,200,168,0.08)]' : ''
338
304
  }`}
339
305
  >
340
306
  <div className="flex-1 min-w-0">
341
307
  <div className="flex items-center gap-2">
342
- <span className="font-medium text-sm truncate">{model.name}</span>
308
+ <span className="font-medium text-[12px] truncate text-[var(--text-primary)]">{model.name}</span>
343
309
  {model.isFree && (
344
- <span className="px-1.5 py-0.5 text-[10px] bg-green-500/20 text-green-500 rounded">
310
+ <span className="px-1.5 py-0.5 text-[9px] bg-[rgba(60,200,120,0.1)] text-[var(--success)] rounded">
345
311
  FREE
346
312
  </span>
347
313
  )}
348
314
  {model.supportsVision && (
349
- <span className="px-1.5 py-0.5 text-[10px] bg-purple-500/20 text-purple-500 rounded">
315
+ <span className="px-1.5 py-0.5 text-[9px] bg-[rgba(104,144,244,0.1)] text-[var(--info)] rounded">
350
316
  VISION
351
317
  </span>
352
318
  )}
353
319
  </div>
354
- <div className="text-xs text-muted-foreground truncate">{model.id}</div>
320
+ <div className="text-[10px] text-[var(--text-muted)] truncate">{model.id}</div>
355
321
  </div>
356
322
  {model.contextWindow && model.contextWindow >= 100000 && (
357
- <span className="text-xs text-muted-foreground ml-2">
323
+ <span className="text-[10px] text-[var(--text-muted)] ml-2">
358
324
  {model.contextWindow >= 1000000 ? '1M' : `${model.contextWindow / 1000}K`}
359
325
  </span>
360
326
  )}
361
327
  {selectedModel === model.id && (
362
- <Check className="w-4 h-4 text-primary ml-2" />
328
+ <Check className="w-3.5 h-3.5 text-[var(--teal-400)] ml-2" />
363
329
  )}
364
330
  </button>
365
331
  ))}
@@ -378,41 +344,34 @@ export const ChatInterface: React.FC<ChatInterfaceProps> = ({
378
344
  allowBypass={allowBypassMode}
379
345
  />
380
346
  )}
381
- <span className="text-xs text-muted-foreground">
347
+ <span className="text-[11px] text-[var(--text-muted)]">
382
348
  {agent.messages.length} messages
383
349
  </span>
384
- <button className="p-2 hover:bg-muted rounded-md">
385
- <MoreVertical className="w-4 h-4" />
350
+ <button className="p-2 hover:bg-[var(--bg-hover)] rounded-[var(--radius-sm)] text-[var(--text-muted)] transition-colors">
351
+ <MoreVertical className="w-3.5 h-3.5" />
386
352
  </button>
387
353
  </div>
388
354
  </div>
389
355
 
390
- {/* Messages */}
391
356
  <div className="flex-1 overflow-y-auto p-4 space-y-4">
392
357
  {agent.messages.length === 0 ? (
393
- <div className="flex flex-col items-center justify-center h-full text-muted-foreground">
358
+ <div className="flex flex-col items-center justify-center h-full text-[var(--text-muted)]">
394
359
  <Bot className="w-16 h-16 mb-4 opacity-30" />
395
- <p className="text-lg font-medium">Start a conversation</p>
396
- <p className="text-sm mt-2">Send a message or use /task to assign a task</p>
397
- <div className="mt-6 space-y-2 text-sm">
360
+ <p className="text-[15px] font-medium text-[var(--text-primary)]">Start a conversation</p>
361
+ <p className="text-[12px] mt-2">Send a message or use /task to assign a task</p>
362
+ <div className="mt-6 space-y-2 text-[12px]">
398
363
  <button
399
364
  onClick={() => setInput('Can you help me refactor this code?')}
400
- className="block px-4 py-2 bg-muted rounded-lg hover:bg-muted/80 transition-colors"
365
+ className="block px-4 py-2 bg-[var(--bg-card)] border border-[var(--border-subtle)] rounded-[var(--radius-md)] hover:border-[var(--border-accent)] transition-colors text-[var(--text-secondary)]"
401
366
  >
402
367
  "Can you help me refactor this code?"
403
368
  </button>
404
369
  <button
405
370
  onClick={() => setInput('/task Review all JavaScript files for potential bugs')}
406
- className="block px-4 py-2 bg-muted rounded-lg hover:bg-muted/80 transition-colors"
371
+ className="block px-4 py-2 bg-[var(--bg-card)] border border-[var(--border-subtle)] rounded-[var(--radius-md)] hover:border-[var(--border-accent)] transition-colors text-[var(--text-secondary)]"
407
372
  >
408
373
  "/task Review all JavaScript files..."
409
374
  </button>
410
- <button
411
- onClick={() => setInput('Explain how this function works')}
412
- className="block px-4 py-2 bg-muted rounded-lg hover:bg-muted/80 transition-colors"
413
- >
414
- "Explain how this function works"
415
- </button>
416
375
  </div>
417
376
  </div>
418
377
  ) : (
@@ -425,15 +384,15 @@ export const ChatInterface: React.FC<ChatInterfaceProps> = ({
425
384
  >
426
385
  <div className={`w-8 h-8 rounded-lg flex items-center justify-center flex-shrink-0 ${
427
386
  message.role === 'user'
428
- ? 'bg-primary text-primary-foreground'
387
+ ? 'bg-[var(--teal-500)] text-[var(--bg-void)]'
429
388
  : message.role === 'system'
430
- ? 'bg-muted text-muted-foreground'
431
- : 'bg-green-500/10 text-green-500'
389
+ ? 'bg-[var(--bg-elevated)] text-[var(--text-muted)]'
390
+ : 'bg-[rgba(0,200,168,0.1)] text-[var(--teal-400)]'
432
391
  }`}>
433
392
  {message.role === 'user' ? (
434
393
  <User className="w-4 h-4" />
435
394
  ) : message.role === 'system' ? (
436
- <span className="text-xs font-bold">S</span>
395
+ <span className="text-[10px] font-bold">S</span>
437
396
  ) : (
438
397
  <Bot className="w-4 h-4" />
439
398
  )}
@@ -444,19 +403,19 @@ export const ChatInterface: React.FC<ChatInterfaceProps> = ({
444
403
  }`}>
445
404
  <div className={`relative rounded-2xl px-4 py-3 ${
446
405
  message.role === 'user'
447
- ? 'bg-primary text-primary-foreground'
406
+ ? 'bg-[var(--teal-500)] text-[var(--bg-void)]'
448
407
  : message.role === 'system'
449
- ? 'bg-muted text-muted-foreground text-sm italic'
450
- : 'bg-muted'
408
+ ? 'bg-[var(--bg-elevated)] text-[var(--text-muted)] text-[12px] italic'
409
+ : 'bg-[var(--bg-card)] border border-[var(--border-subtle)]'
451
410
  }`}>
452
411
  <button
453
412
  onClick={() => copyToClipboard(message.content, message.id)}
454
- className="absolute top-2 right-2 p-1.5 opacity-0 group-hover:opacity-100 transition-opacity bg-background/80 rounded-md"
413
+ className="absolute top-2 right-2 p-1.5 opacity-0 group-hover:opacity-100 transition-opacity bg-[var(--bg-surface)] rounded-md"
455
414
  >
456
415
  {copiedId === message.id ? (
457
- <Check className="w-3 h-3 text-green-500" />
416
+ <Check className="w-3 h-3 text-[var(--success)]" />
458
417
  ) : (
459
- <Copy className="w-3 h-3" />
418
+ <Copy className="w-3 h-3 text-[var(--text-muted)]" />
460
419
  )}
461
420
  </button>
462
421
 
@@ -469,7 +428,7 @@ export const ChatInterface: React.FC<ChatInterfaceProps> = ({
469
428
  <div className="mb-3">
470
429
  <button
471
430
  onClick={() => setExpandedAutoContext(prev => ({ ...prev, [message.id]: !isExpanded }))}
472
- className="text-xs px-2 py-1 rounded-md bg-background/60 hover:bg-background/80 border border-border text-muted-foreground"
431
+ className="text-[10px] px-2 py-1 rounded-md bg-[var(--bg-elevated)] hover:bg-[var(--bg-hover)] border border-[var(--border-subtle)] text-[var(--text-muted)]"
473
432
  type="button"
474
433
  >
475
434
  Auto-context: {ac.files.length} files{typeof ac.totalChars === 'number' ? ` ${ac.totalChars} chars` : ''}
@@ -477,12 +436,12 @@ export const ChatInterface: React.FC<ChatInterfaceProps> = ({
477
436
  </button>
478
437
 
479
438
  {isExpanded && (
480
- <div className="mt-2 rounded-md border border-border bg-background/50 p-2 text-xs">
439
+ <div className="mt-2 rounded-md border border-[var(--border-subtle)] bg-[var(--bg-elevated)] p-2 text-[10px]">
481
440
  <div className="space-y-1">
482
441
  {ac.files.map((f, idx) => (
483
442
  <div key={`${message.id}-ac-${idx}`} className="flex gap-2">
484
- <span className="font-mono text-foreground truncate max-w-[260px]">{f.path}</span>
485
- <span className="text-muted-foreground">- {f.reason}</span>
443
+ <span className="font-[var(--font-mono)] text-[var(--text-primary)] truncate max-w-[260px]">{f.path}</span>
444
+ <span className="text-[var(--text-muted)]">- {f.reason}</span>
486
445
  </div>
487
446
  ))}
488
447
  </div>
@@ -496,30 +455,30 @@ export const ChatInterface: React.FC<ChatInterfaceProps> = ({
496
455
  </div>
497
456
 
498
457
  {extractCodeBlocks(message.content).map((block, idx) => (
499
- <div key={idx} className="mt-4 rounded-lg overflow-hidden border border-border">
500
- <div className="flex items-center justify-between px-3 py-2 bg-background/50 border-b border-border">
501
- <span className="text-xs font-medium text-muted-foreground">{block.language}</span>
458
+ <div key={idx} className="mt-4 rounded-lg overflow-hidden border border-[var(--border-subtle)]">
459
+ <div className="flex items-center justify-between px-3 py-2 bg-[var(--bg-elevated)] border-b border-[var(--border-subtle)]">
460
+ <span className="text-[10px] font-medium text-[var(--text-muted)]">{block.language}</span>
502
461
  <button
503
462
  onClick={() => copyToClipboard(block.code, `code-${idx}`)}
504
- className="p-1 hover:bg-background rounded"
463
+ className="p-1 hover:bg-[var(--bg-hover)] rounded"
505
464
  >
506
465
  {copiedId === `code-${idx}` ? (
507
- <Check className="w-3 h-3 text-green-500" />
466
+ <Check className="w-3 h-3 text-[var(--success)]" />
508
467
  ) : (
509
- <Copy className="w-3 h-3" />
468
+ <Copy className="w-3 h-3 text-[var(--text-muted)]" />
510
469
  )}
511
470
  </button>
512
471
  </div>
513
- <pre className="bg-black/50 p-3 rounded-b-lg overflow-x-auto">
514
- <code className="text-sm font-mono text-green-400">{block.code}</code>
472
+ <pre className="bg-[var(--bg-void)] p-3 rounded-b-lg overflow-x-auto">
473
+ <code className="text-[12px] font-[var(--font-mono)] text-[var(--teal-300)]">{block.code}</code>
515
474
  </pre>
516
475
  </div>
517
476
  ))}
518
477
 
519
- <div className={`text-xs mt-2 ${
478
+ <div className={`text-[10px] mt-2 ${
520
479
  message.role === 'user'
521
- ? 'text-primary-foreground/60'
522
- : 'text-muted-foreground'
480
+ ? 'text-[var(--bg-void)] opacity-60'
481
+ : 'text-[var(--text-muted)]'
523
482
  }`}>
524
483
  {format(new Date(message.timestamp), 'HH:mm')}
525
484
  </div>
@@ -531,12 +490,12 @@ export const ChatInterface: React.FC<ChatInterfaceProps> = ({
531
490
 
532
491
  {isLoading && (
533
492
  <div className="flex gap-3">
534
- <div className="w-8 h-8 rounded-lg bg-green-500/10 text-green-500 flex items-center justify-center">
493
+ <div className="w-8 h-8 rounded-lg bg-[rgba(0,200,168,0.1)] text-[var(--teal-400)] flex items-center justify-center">
535
494
  <Bot className="w-4 h-4" />
536
495
  </div>
537
- <div className="bg-muted rounded-2xl px-4 py-3 flex items-center gap-2">
538
- <Loader2 className="w-4 h-4 animate-spin" />
539
- <span className="text-sm text-muted-foreground">Thinking...</span>
496
+ <div className="bg-[var(--bg-card)] border border-[var(--border-subtle)] rounded-2xl px-4 py-3 flex items-center gap-2">
497
+ <Loader2 className="w-4 h-4 animate-spin text-[var(--teal-400)]" />
498
+ <span className="text-[12px] text-[var(--text-muted)]">Thinking...</span>
540
499
  </div>
541
500
  </div>
542
501
  )}
@@ -544,10 +503,9 @@ export const ChatInterface: React.FC<ChatInterfaceProps> = ({
544
503
  <div ref={messagesEndRef} />
545
504
  </div>
546
505
 
547
- {/* Input Area */}
548
- <div className="p-4 border-t border-border bg-background/50">
506
+ <div className="p-4 border-t border-[var(--border-subtle)] bg-[var(--bg-surface)]">
549
507
  <div className="relative flex items-end gap-2">
550
- <button className="p-2 text-muted-foreground hover:text-foreground transition-colors">
508
+ <button className="p-2 text-[var(--text-muted)] hover:text-[var(--text-secondary)] transition-colors">
551
509
  <Paperclip className="w-5 h-5" />
552
510
  </button>
553
511
 
@@ -558,7 +516,7 @@ export const ChatInterface: React.FC<ChatInterfaceProps> = ({
558
516
  onChange={e => setInput(e.target.value)}
559
517
  onKeyDown={handleKeyDown}
560
518
  placeholder="Type a message... (Shift+Enter for new line, /task for tasks)"
561
- className="w-full px-4 py-3 pr-12 bg-background border border-input rounded-xl resize-none focus:outline-none focus:ring-2 focus:ring-primary min-h-[56px] max-h-[200px]"
519
+ className="w-full px-4 py-3 pr-12 bg-[var(--bg-card)] border border-[var(--border-default)] rounded-[var(--radius-lg)] resize-none focus:outline-none focus:border-[var(--teal-500)] text-[13px] text-[var(--text-primary)] placeholder:text-[var(--text-disabled)] min-h-[56px] max-h-[200px]"
562
520
  rows={1}
563
521
  style={{ height: 'auto' }}
564
522
  onInput={(e) => {
@@ -572,19 +530,19 @@ export const ChatInterface: React.FC<ChatInterfaceProps> = ({
572
530
  <button
573
531
  onClick={handleSend}
574
532
  disabled={!input.trim() || isLoading}
575
- className="p-3 bg-primary text-primary-foreground rounded-xl hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
533
+ className="p-3 bg-[var(--teal-500)] text-[var(--bg-void)] rounded-[var(--radius-lg)] hover:bg-[var(--teal-400)] disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
576
534
  >
577
535
  <Send className="w-5 h-5" />
578
536
  </button>
579
537
  </div>
580
538
 
581
- <div className="flex items-center justify-between mt-2 text-xs text-muted-foreground">
539
+ <div className="flex items-center justify-between mt-2 text-[10px] text-[var(--text-muted)]">
582
540
  <div className="flex gap-4">
583
541
  <span className="flex items-center gap-1">
584
- <kbd className="px-1.5 py-0.5 bg-muted rounded">Enter</kbd> to send
542
+ <kbd className="px-1.5 py-0.5 bg-[var(--bg-elevated)] rounded text-[9px]">Enter</kbd> to send
585
543
  </span>
586
544
  <span className="flex items-center gap-1">
587
- <kbd className="px-1.5 py-0.5 bg-muted rounded">Shift</kbd> + <kbd className="px-1.5 py-0.5 bg-muted rounded">Enter</kbd> for new line
545
+ <kbd className="px-1.5 py-0.5 bg-[var(--bg-elevated)] rounded text-[9px]">Shift</kbd> + <kbd className="px-1.5 py-0.5 bg-[var(--bg-elevated)] rounded text-[9px]">Enter</kbd> for new line
588
546
  </span>
589
547
  </div>
590
548
  <span>{input.length} characters</span>
@@ -1,8 +1,6 @@
1
1
  import React from 'react';
2
2
  import { Agent } from '../../shared/types';
3
- import { Bot, MoreVertical, Minus, Square, X, Search } from 'lucide-react';
4
- import { cn } from '@/lib/utils';
5
- import { VoiceCommand } from './VoiceCommand';
3
+ import { Minus, Square, X, Search } from 'lucide-react';
6
4
 
7
5
  interface HeaderProps {
8
6
  activeTab: string;
@@ -10,13 +8,9 @@ interface HeaderProps {
10
8
  onSettingsClick: () => void;
11
9
  }
12
10
 
13
- export const Header: React.FC<HeaderProps> = ({ activeTab, agents, onSettingsClick }) => {
11
+ export const Header: React.FC<HeaderProps> = ({ activeTab, agents }) => {
14
12
  const runningAgents = agents.filter(a => a.status === 'running').length;
15
13
 
16
- const handleVoiceCommand = (transcript: string) => {
17
- console.log('Voice command:', transcript);
18
- };
19
-
20
14
  const getTitle = () => {
21
15
  switch (activeTab) {
22
16
  case 'agents': return 'Agents';
@@ -28,17 +22,6 @@ export const Header: React.FC<HeaderProps> = ({ activeTab, agents, onSettingsCli
28
22
  }
29
23
  };
30
24
 
31
- const getDescription = () => {
32
- switch (activeTab) {
33
- case 'agents': return 'Manage your AI coding agents';
34
- case 'worktrees': return 'Isolated Git workspaces';
35
- case 'skills': return 'Reusable AI capabilities';
36
- case 'automations': return 'Scheduled tasks and workflows';
37
- case 'settings': return 'Configure your preferences';
38
- default: return '';
39
- }
40
- };
41
-
42
25
  const handleMinimize = () => {
43
26
  window.electronAPI.window.minimize();
44
27
  };
@@ -52,34 +35,37 @@ export const Header: React.FC<HeaderProps> = ({ activeTab, agents, onSettingsCli
52
35
  };
53
36
 
54
37
  return (
55
- <header className="h-16 border-b border-[var(--color-border)] bg-[var(--color-bg-elevated)] flex items-center justify-between px-6" data-testid="app-header">
56
- <div className="flex items-center gap-6">
38
+ <header
39
+ className="h-12 border-b border-[var(--border-subtle)] bg-[var(--bg-surface)] flex items-center justify-between px-5"
40
+ data-testid="app-header"
41
+ >
42
+ <div className="flex items-center gap-4">
57
43
  <div>
58
- <h1 className="text-xl font-semibold tracking-tight text-[var(--color-text-primary)]" data-testid="page-title">
44
+ <h1
45
+ className="text-[18px] font-medium text-[var(--text-primary)] tracking-tight"
46
+ data-testid="page-title"
47
+ style={{ fontFamily: 'var(--font-display)', fontStyle: 'italic', fontWeight: 300 }}
48
+ >
59
49
  {getTitle()}
60
50
  </h1>
61
- <p className="text-xs text-[var(--color-text-tertiary)]">
62
- {getDescription()}
63
- </p>
64
51
  </div>
65
52
 
66
53
  {activeTab === 'agents' && runningAgents > 0 && (
67
- <div className="flex items-center gap-2 px-3 py-1.5 bg-green-50 text-green-700 rounded-full text-xs font-medium" data-testid="running-agents-badge">
54
+ <div className="flex items-center gap-2 px-3 py-1 bg-[rgba(60,200,120,0.1)] border border-[rgba(60,200,120,0.2)] rounded-full text-[11px] font-medium text-[var(--success)]">
68
55
  <span className="relative flex h-2 w-2">
69
- <span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75"></span>
70
- <span className="relative inline-flex rounded-full h-2 w-2 bg-green-500"></span>
56
+ <span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-[var(--success)] opacity-75"></span>
57
+ <span className="relative inline-flex rounded-full h-2 w-2 bg-[var(--success)]"></span>
71
58
  </span>
72
59
  {runningAgents} running
73
60
  </div>
74
61
  )}
75
62
 
76
- {/* Search */}
77
63
  <div className="relative hidden md:block">
78
- <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-neutral-400" />
64
+ <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-[var(--text-muted)]" />
79
65
  <input
80
66
  type="text"
81
67
  placeholder="Search..."
82
- className="pl-9 pr-4 py-2 bg-neutral-100 border-0 rounded-lg text-sm w-64 focus:ring-2 focus:ring-neutral-200 transition-all"
68
+ className="pl-8 pr-3 py-1.5 bg-[var(--bg-elevated)] border border-[var(--border-subtle)] rounded-[var(--radius-sm)] text-[12px] text-[var(--text-primary)] placeholder:text-[var(--text-muted)] w-56 focus:outline-none focus:border-[var(--teal-500)] transition-colors"
83
69
  data-testid="search-input"
84
70
  />
85
71
  </div>
@@ -88,26 +74,26 @@ export const Header: React.FC<HeaderProps> = ({ activeTab, agents, onSettingsCli
88
74
  <div className="flex items-center gap-1">
89
75
  <button
90
76
  onClick={handleMinimize}
91
- className="p-2 hover:bg-neutral-100 rounded-lg text-neutral-500 hover:text-neutral-900 transition-colors"
77
+ className="p-2 hover:bg-[var(--bg-hover)] rounded-[var(--radius-sm)] text-[var(--text-muted)] hover:text-[var(--text-secondary)] transition-colors"
92
78
  data-testid="window-minimize"
93
79
  >
94
- <Minus className="w-4 h-4" />
80
+ <Minus className="w-3.5 h-3.5" />
95
81
  </button>
96
82
  <button
97
83
  onClick={handleMaximize}
98
- className="p-2 hover:bg-neutral-100 rounded-lg text-neutral-500 hover:text-neutral-900 transition-colors"
84
+ className="p-2 hover:bg-[var(--bg-hover)] rounded-[var(--radius-sm)] text-[var(--text-muted)] hover:text-[var(--text-secondary)] transition-colors"
99
85
  data-testid="window-maximize"
100
86
  >
101
- <Square className="w-4 h-4" />
87
+ <Square className="w-3.5 h-3.5" />
102
88
  </button>
103
89
  <button
104
90
  onClick={handleClose}
105
- className="p-2 hover:bg-red-50 hover:text-red-600 rounded-lg text-neutral-500 transition-colors"
91
+ className="p-2 hover:bg-[rgba(232,90,106,0.1)] hover:text-[var(--error)] rounded-[var(--radius-sm)] text-[var(--text-muted)] transition-colors"
106
92
  data-testid="window-close"
107
93
  >
108
- <X className="w-4 h-4" />
94
+ <X className="w-3.5 h-3.5" />
109
95
  </button>
110
96
  </div>
111
97
  </header>
112
98
  );
113
- };
99
+ };