feat: session naming, username/persona rename, help page, contrast fixes
- Session name field: PATCH /sessions/{id} endpoint, inline rename button in UI
- Persona rename: inline ✏ toggle form in settings, POST /settings/persona/rename
- Username rename: inline form in settings, POST /settings/username (renames home dir, forces re-login)
- Help page: dedicated /help route replacing modal, collapsible sections
- Per-persona isolation: files.py and session_store.py now scope to correct user/persona
- Contrast/visibility: muted text bumped to slate-400+, session rename btn at 0.4 opacity
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -235,8 +235,12 @@
|
||||
}
|
||||
});
|
||||
|
||||
// session_id → friendly name (populated on each panel render)
|
||||
const sessionNames = new Map();
|
||||
|
||||
function renderPanel(sessions) {
|
||||
sessionsPanel.innerHTML = '';
|
||||
sessionNames.clear();
|
||||
|
||||
const newItem = makeItem('new', '+ New session', '');
|
||||
newItem.addEventListener('click', () => {
|
||||
@@ -259,13 +263,57 @@
|
||||
}
|
||||
|
||||
for (const s of sessions) {
|
||||
const displayName = s.name || s.session_id;
|
||||
sessionNames.set(s.session_id, displayName);
|
||||
|
||||
const item = makeItem(
|
||||
s.session_id === sessionId ? 'active' : '',
|
||||
s.session_id,
|
||||
displayName,
|
||||
`${s.message_count} msgs · ${timeAgo(s.updated)}`
|
||||
);
|
||||
item.addEventListener('click', () => resumeSession(s.session_id));
|
||||
|
||||
// Rename button (✎)
|
||||
const renameBtn = document.createElement('button');
|
||||
renameBtn.className = 'session-rename-btn';
|
||||
renameBtn.textContent = '✎';
|
||||
renameBtn.title = 'Rename session';
|
||||
renameBtn.addEventListener('click', async (e) => {
|
||||
e.stopPropagation();
|
||||
const labelEl = item.querySelector('.session-id');
|
||||
const current = s.name || '';
|
||||
const input = document.createElement('input');
|
||||
input.className = 'session-rename-input';
|
||||
input.value = current;
|
||||
input.placeholder = s.session_id;
|
||||
labelEl.replaceWith(input);
|
||||
input.focus();
|
||||
input.select();
|
||||
|
||||
async function commitRename() {
|
||||
const newName = input.value.trim();
|
||||
await fetch(`/sessions/${s.session_id}?${_fileParams}`, {
|
||||
method: 'PATCH',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ name: newName }),
|
||||
});
|
||||
const res = await fetch(`/sessions?${_fileParams}`);
|
||||
const data = await res.json();
|
||||
renderPanel(data.sessions);
|
||||
// Update status bar if this is the active session
|
||||
if (sessionId === s.session_id) {
|
||||
sessionEl.textContent = `session: ${newName || s.session_id}`;
|
||||
}
|
||||
}
|
||||
|
||||
input.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Enter') { e.preventDefault(); commitRename(); }
|
||||
if (e.key === 'Escape') { renderPanel(sessions); }
|
||||
});
|
||||
input.addEventListener('blur', commitRename);
|
||||
});
|
||||
item.appendChild(renameBtn);
|
||||
|
||||
const delBtn = document.createElement('button');
|
||||
delBtn.className = 'session-delete-btn';
|
||||
delBtn.textContent = '×';
|
||||
@@ -316,7 +364,7 @@
|
||||
|
||||
messagesEl.innerHTML = '';
|
||||
sessionId = id;
|
||||
sessionEl.textContent = `session: ${id}`;
|
||||
sessionEl.textContent = `session: ${sessionNames.get(id) || id}`;
|
||||
currentHistory = [];
|
||||
|
||||
for (let i = 0; i < data.messages.length; i++) {
|
||||
|
||||
Reference in New Issue
Block a user