Skip to content

Commit c805c1f

Browse files
committed
feat: add Codex session support
1 parent 76be5ae commit c805c1f

11 files changed

Lines changed: 603 additions & 36 deletions

File tree

public/app.js

Lines changed: 53 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,8 @@ function renderStatusIndicator(status) {
425425
function renderDirectoryList() {
426426
const container = document.getElementById('directory-list');
427427
if (!container) return;
428-
container.innerHTML = state.directories.map(dir => `
428+
const enabledDirs = state.directories.filter(dir => dir.enabled !== false);
429+
container.innerHTML = enabledDirs.map(dir => `
429430
<div class="directory-item ${state.filters.directory === dir.path ? 'active' : ''} inline-flex items-center gap-2 rounded-full border border-border/70 bg-background/70 px-2.5 py-1 text-[11px] text-muted-foreground transition-colors hover:bg-muted/60 hover:text-foreground"
430431
data-path="${escapeHtml(dir.path)}" onclick="filterByDirectory('${escapeHtml(dir.path)}')">
431432
<span class="directory-color h-2 w-2 rounded-full" style="background: ${dir.color}"></span>
@@ -838,12 +839,13 @@ function renderDetailEmpty() {
838839
function renderMessages(messages) {
839840
const container = document.getElementById('messages');
840841
const toolResults = collectToolResults(messages);
842+
const assistantLabel = state.currentSession?.assistantLabel || 'Claude';
841843

842844
const html = messages
843845
.filter(msg => hasDisplayableContent(msg.content))
844846
.map(msg => {
845847
const isUser = msg.type === 'user';
846-
const label = isUser ? 'You' : 'Claude';
848+
const label = isUser ? 'You' : assistantLabel;
847849
const contentHtml = renderMessageContent(msg.content, toolResults);
848850
if (!contentHtml.trim()) return '';
849851

@@ -1182,7 +1184,8 @@ function appendMessage(message) {
11821184

11831185
const container = document.getElementById('messages');
11841186
const isUser = message.type === 'user';
1185-
const label = isUser ? 'You' : 'Claude';
1187+
const assistantLabel = state.currentSession?.assistantLabel || 'Claude';
1188+
const label = isUser ? 'You' : assistantLabel;
11861189
const contentHtml = renderMessageContent(message.content);
11871190
if (!contentHtml.trim()) return;
11881191

@@ -1371,10 +1374,13 @@ function renderSettingsDirectories() {
13711374
container.innerHTML = dirs.map(dir => `
13721375
<div class="settings-directory-item flex flex-wrap items-center gap-3 rounded-xl border border-border bg-background/70 p-3" data-path="${escapeHtml(dir.path)}">
13731376
<div class="settings-directory-color h-3 w-3 rounded-full" style="background: ${dir.color}"></div>
1374-
<div class="settings-directory-info flex min-w-[200px] flex-1 flex-col">
1375-
<div class="settings-directory-label text-[13px] font-medium text-foreground">${escapeHtml(dir.label)}</div>
1376-
<div class="settings-directory-path text-[11px] text-muted-foreground">${escapeHtml(dir.path)}</div>
1377-
</div>
1377+
<div class="settings-directory-info flex min-w-[200px] flex-1 flex-col">
1378+
<div class="settings-directory-label flex items-center gap-2 text-[13px] font-medium text-foreground">
1379+
<span>${escapeHtml(dir.label)}</span>
1380+
<span class="rounded-full border border-border bg-card/70 px-2 py-0.5 text-[10px] text-muted-foreground">${escapeHtml((dir.type || 'claude').toUpperCase())}</span>
1381+
</div>
1382+
<div class="settings-directory-path text-[11px] text-muted-foreground">${escapeHtml(dir.path)}</div>
1383+
</div>
13781384
<label class="toggle">
13791385
<input type="checkbox" ${dir.enabled !== false ? 'checked' : ''} onchange="toggleDirectoryEnabled('${escapeHtml(dir.path)}', this.checked)">
13801386
<span class="slider"></span>
@@ -1397,7 +1403,14 @@ function showAddDirectoryForm() {
13971403

13981404
const formHtml = `
13991405
<div class="add-directory-form mt-4 space-y-3 rounded-xl border border-border bg-background/70 p-3" id="add-directory-form">
1400-
<input type="text" id="new-dir-path" placeholder="Directory path (e.g., ~/.claude)" class="input w-full rounded-md border border-input bg-background/80 px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary/40">
1406+
<div class="flex flex-wrap items-center gap-2">
1407+
<label class="text-xs font-medium text-muted-foreground">Type</label>
1408+
<select id="new-dir-type" class="rounded-md border border-border bg-background/80 px-3 py-2 text-sm text-foreground" onchange="updateAddDirectoryTypeHint()">
1409+
<option value="claude" selected>Claude</option>
1410+
<option value="codex">Codex</option>
1411+
</select>
1412+
</div>
1413+
<input type="text" id="new-dir-path" placeholder="Directory path (e.g., ~/.claude/projects)" class="input w-full rounded-md border border-input bg-background/80 px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary/40">
14011414
<input type="text" id="new-dir-label" placeholder="Label (e.g., Work)" class="input w-full rounded-md border border-input bg-background/80 px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary/40">
14021415
<input type="color" id="new-dir-color" value="#10b981" class="input-color h-9 w-16 rounded-md border border-border bg-background/80">
14031416
<div class="form-actions flex items-center justify-end gap-2">
@@ -1407,9 +1420,21 @@ function showAddDirectoryForm() {
14071420
</div>
14081421
`;
14091422
container.insertAdjacentHTML('beforeend', formHtml);
1423+
updateAddDirectoryTypeHint();
14101424
document.getElementById('new-dir-path').focus();
14111425
}
14121426

1427+
function updateAddDirectoryTypeHint() {
1428+
const typeSelect = document.getElementById('new-dir-type');
1429+
const pathInput = document.getElementById('new-dir-path');
1430+
if (!typeSelect || !pathInput) return;
1431+
const type = typeSelect.value;
1432+
pathInput.placeholder =
1433+
type === 'codex'
1434+
? 'Directory path (e.g., ~/.codex/sessions)'
1435+
: 'Directory path (e.g., ~/.claude/projects)';
1436+
}
1437+
14131438
function cancelAddDirectory() {
14141439
const form = document.getElementById('add-directory-form');
14151440
if (form) form.remove();
@@ -1419,10 +1444,12 @@ async function submitAddDirectory() {
14191444
const pathInput = document.getElementById('new-dir-path');
14201445
const labelInput = document.getElementById('new-dir-label');
14211446
const colorInput = document.getElementById('new-dir-color');
1447+
const typeSelect = document.getElementById('new-dir-type');
14221448

14231449
const path = pathInput.value.trim();
14241450
const label = labelInput.value.trim() || path.split('/').pop();
14251451
const color = colorInput.value;
1452+
const type = typeSelect?.value === 'codex' ? 'codex' : 'claude';
14261453

14271454
if (!path) {
14281455
showNotification('Please enter a directory path', 'error');
@@ -1433,7 +1460,7 @@ async function submitAddDirectory() {
14331460
const res = await fetch('/api/directories', {
14341461
method: 'POST',
14351462
headers: { 'Content-Type': 'application/json' },
1436-
body: JSON.stringify({ path, label, color, enabled: true })
1463+
body: JSON.stringify({ path, label, color, enabled: true, type })
14371464
});
14381465

14391466
if (!res.ok) {
@@ -1490,14 +1517,21 @@ function editDirectory(path) {
14901517
<button class="modal-close rounded-full border border-border bg-background/80 px-2.5 py-1 text-sm text-muted-foreground transition-colors hover:bg-muted/60 hover:text-foreground" onclick="closeEditDirectory()">&times;</button>
14911518
</div>
14921519
<div class="modal-body mt-5 space-y-4">
1493-
<div class="form-group space-y-2">
1494-
<label class="text-sm font-medium text-muted-foreground">Path</label>
1495-
<input type="text" id="edit-dir-path" value="${escapeHtml(dir.path)}" class="input w-full rounded-md border border-input bg-background/80 px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary/40 opacity-70" readonly>
1496-
</div>
1497-
<div class="form-group space-y-2">
1498-
<label class="text-sm font-medium text-muted-foreground">Label</label>
1499-
<input type="text" id="edit-dir-label" value="${escapeHtml(dir.label)}" class="input w-full rounded-md border border-input bg-background/80 px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary/40">
1500-
</div>
1520+
<div class="form-group space-y-2">
1521+
<label class="text-sm font-medium text-muted-foreground">Path</label>
1522+
<input type="text" id="edit-dir-path" value="${escapeHtml(dir.path)}" class="input w-full rounded-md border border-input bg-background/80 px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary/40 opacity-70" readonly>
1523+
</div>
1524+
<div class="form-group space-y-2">
1525+
<label class="text-sm font-medium text-muted-foreground">Type</label>
1526+
<select id="edit-dir-type" class="w-full rounded-md border border-border bg-background/80 px-3 py-2 text-sm text-foreground">
1527+
<option value="claude" ${(dir.type || 'claude') === 'claude' ? 'selected' : ''}>Claude</option>
1528+
<option value="codex" ${(dir.type || 'claude') === 'codex' ? 'selected' : ''}>Codex</option>
1529+
</select>
1530+
</div>
1531+
<div class="form-group space-y-2">
1532+
<label class="text-sm font-medium text-muted-foreground">Label</label>
1533+
<input type="text" id="edit-dir-label" value="${escapeHtml(dir.label)}" class="input w-full rounded-md border border-input bg-background/80 px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary/40">
1534+
</div>
15011535
<div class="form-group space-y-2">
15021536
<label class="text-sm font-medium text-muted-foreground">Color</label>
15031537
<input type="color" id="edit-dir-color" value="${dir.color}" class="input-color h-9 w-16 rounded-md border border-border bg-background/80">
@@ -1520,6 +1554,7 @@ function closeEditDirectory() {
15201554
async function submitEditDirectory(originalPath) {
15211555
const label = document.getElementById('edit-dir-label').value.trim();
15221556
const color = document.getElementById('edit-dir-color').value;
1557+
const type = document.getElementById('edit-dir-type')?.value === 'codex' ? 'codex' : 'claude';
15231558

15241559
if (!label) {
15251560
showNotification('Label cannot be empty', 'error');
@@ -1530,7 +1565,7 @@ async function submitEditDirectory(originalPath) {
15301565
const res = await fetch(`/api/directories/${encodeURIComponent(originalPath)}`, {
15311566
method: 'PUT',
15321567
headers: { 'Content-Type': 'application/json' },
1533-
body: JSON.stringify({ label, color })
1568+
body: JSON.stringify({ label, color, type })
15341569
});
15351570

15361571
if (!res.ok) throw new Error('Failed to update directory');

0 commit comments

Comments
 (0)