feat(chat): EA2-backed 1:1 messaging surface

New Chat scene at the Chat top-bar tab. Threads and messages are stored
as flow docs (kind=definition, source_context=EA2_CHAT_THREAD / _MSG)
linked by defines edges with role=next — same proven contract as wizard
steps. Persona directory lets the signed-in operator open a thread with
the CEO / HR / IT personas.

- src/lib/chatApi.ts: listThreads / createThread / listMessages / sendMessage
- src/scenes/Chat.tsx: sidebar (threads + new-thread picker) + main pane
  (header, bubbles, composer with Enter-to-send / Shift-Enter newline)
- src/index.css: chat-scene grid + bubble + composer styles
- src/App.tsx: Chat tab + scene route
This commit is contained in:
2026-06-14 12:33:43 +04:00
parent 4dad78aa86
commit fd8c4853df
6 changed files with 443 additions and 2 deletions
+73
View File
@@ -1825,3 +1825,76 @@ select.studio-input { background: var(--bp-paper); }
.theme-toggle { display: inline-flex; align-items: center; gap: 6px; }
.theme-toggle-label { font-size: 10px; letter-spacing: 0.08em; font-weight: 600; text-transform: uppercase; }
.chat-scene {
display: grid;
grid-template-columns: 280px 1fr;
gap: 16px;
padding: 16px;
height: calc(100vh - 60px);
background: var(--bp-paper);
}
.chat-sidebar {
border: 1px solid var(--bp-navy);
background: var(--bp-paper);
display: flex;
flex-direction: column;
overflow: hidden;
}
.chat-sidebar-head { padding: 12px; border-bottom: 1px solid var(--bp-navy); }
.chat-new-thread { padding: 12px; border-bottom: 1px solid var(--bp-navy); display: flex; flex-direction: column; gap: 6px; }
.chat-new-thread label { font-family: var(--bp-mono); font-size: 10px; letter-spacing: 0.08em; color: var(--bp-muted); text-transform: uppercase; }
.chat-new-row { display: flex; gap: 6px; }
.chat-new-row select {
flex: 1; padding: 6px 8px; background: var(--bp-paper); border: 1px solid var(--bp-navy);
color: var(--bp-navy); font-family: var(--bp-mono); font-size: 11px;
}
.chat-thread-list { flex: 1; overflow-y: auto; }
.chat-thread-row {
width: 100%; text-align: left; padding: 10px 12px; background: var(--bp-paper);
border: 0; border-bottom: 1px solid color-mix(in srgb, var(--bp-navy) 15%, transparent);
color: var(--bp-navy); cursor: pointer; display: flex; flex-direction: column; gap: 4px;
}
.chat-thread-row:hover { background: color-mix(in srgb, var(--bp-amber) 15%, var(--bp-paper)); }
.chat-thread-row.active { background: color-mix(in srgb, var(--bp-amber) 30%, var(--bp-paper)); }
.chat-thread-name { font-weight: 600; font-size: 12px; }
.chat-thread-meta { font-family: var(--bp-mono); font-size: 10px; color: var(--bp-muted); }
.chat-empty { padding: 16px; font-size: 11px; color: var(--bp-muted); text-align: center; }
.chat-main {
border: 1px solid var(--bp-navy);
background: var(--bp-paper);
display: flex;
flex-direction: column;
overflow: hidden;
}
.chat-empty-main { padding: 32px; color: var(--bp-muted); text-align: center; font-size: 12px; }
.chat-main-head { padding: 12px 16px; border-bottom: 1px solid var(--bp-navy); }
.chat-title { font-weight: 700; font-size: 13px; color: var(--bp-navy); }
.chat-subtitle { font-family: var(--bp-mono); font-size: 10px; color: var(--bp-muted); margin-top: 2px; }
.chat-messages { flex: 1; overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 10px; }
.chat-bubble-row { display: flex; }
.chat-bubble-row.mine { justify-content: flex-end; }
.chat-bubble {
max-width: 70%;
padding: 8px 12px;
background: var(--bp-paper);
border: 1px solid var(--bp-navy);
display: flex; flex-direction: column; gap: 4px;
}
.chat-bubble-row.mine .chat-bubble {
background: color-mix(in srgb, var(--bp-amber) 20%, var(--bp-paper));
}
.chat-bubble-author { font-family: var(--bp-mono); font-size: 10px; color: var(--bp-muted); }
.chat-bubble-body { font-size: 12px; line-height: 1.4; color: var(--bp-navy); white-space: pre-wrap; word-break: break-word; }
.chat-bubble-time { font-family: var(--bp-mono); font-size: 9px; color: var(--bp-muted); text-align: right; }
.chat-composer { padding: 12px; border-top: 1px solid var(--bp-navy); display: flex; gap: 8px; align-items: flex-end; }
.chat-composer textarea {
flex: 1; padding: 8px; resize: none;
background: var(--bp-paper); border: 1px solid var(--bp-navy);
color: var(--bp-navy); font-family: var(--bp-mono); font-size: 12px;
}
@media (max-width: 700px) {
.chat-scene { grid-template-columns: 1fr; height: auto; }
.chat-sidebar { max-height: 240px; }
}