feat(rag): steering notes — tune how Brain answers, stored in Postgres and injected into every system prompt
This commit is contained in:
@@ -241,6 +241,48 @@ body::after {
|
||||
whole control below 640px. */
|
||||
.new-chat-btn svg { width: 16px; height: 16px; display: none; }
|
||||
|
||||
/* "Tuning" toggle (phase 15): ghost pill like New chat + a mono count
|
||||
badge (brand-ink on brand-soft ≈6.9:1). The label is visually-hidden
|
||||
(not removed) below 640px so the accessible name keeps the word.
|
||||
≥44px touch target at every width. */
|
||||
.steering-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.4rem;
|
||||
min-height: 44px;
|
||||
padding: 0.5rem 0.9rem;
|
||||
border-radius: 999px;
|
||||
border: 1px solid var(--line);
|
||||
background: transparent;
|
||||
color: var(--ink-soft);
|
||||
font: inherit;
|
||||
font-weight: 600;
|
||||
font-size: 0.95rem;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
}
|
||||
.steering-toggle:hover, .steering-toggle[aria-expanded="true"] {
|
||||
background: var(--brand-soft);
|
||||
color: var(--brand-ink);
|
||||
}
|
||||
.steering-toggle svg { width: 16px; height: 16px; display: block; }
|
||||
.steering-count {
|
||||
font-family: var(--mono);
|
||||
font-size: 0.78rem;
|
||||
font-weight: 700;
|
||||
min-width: 1.35rem;
|
||||
text-align: center;
|
||||
padding: 0.05rem 0.4rem;
|
||||
border-radius: 999px;
|
||||
background: var(--brand-soft);
|
||||
color: var(--brand-ink);
|
||||
}
|
||||
.steering-toggle[aria-expanded="true"] .steering-count {
|
||||
background: var(--brand);
|
||||
color: var(--bg); /* dark ink on brand: 5.2:1 */
|
||||
}
|
||||
|
||||
/* ---------- Main frame ---------- */
|
||||
.app-main {
|
||||
flex: 1;
|
||||
@@ -381,6 +423,170 @@ body::after {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* ---------- Steering notes (phase 15) ---------- */
|
||||
/* "Tune" button in the meta row of every completed brain bubble: ghost
|
||||
pill, ≥44px, right-aligned after the source chips. ink-soft on surface
|
||||
≈6.9:1; hover pair brand-ink/brand-soft ≈6.9:1. */
|
||||
.tune-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.35rem;
|
||||
min-height: 44px;
|
||||
margin-left: auto;
|
||||
padding: 0.35rem 0.8rem;
|
||||
border-radius: 999px;
|
||||
border: 1px solid var(--line);
|
||||
background: transparent;
|
||||
color: var(--ink-soft);
|
||||
font: inherit;
|
||||
font-weight: 600;
|
||||
font-size: 0.82rem;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
}
|
||||
.tune-btn svg { width: 14px; height: 14px; display: block; }
|
||||
.tune-btn:hover { background: var(--brand-soft); color: var(--brand-ink); }
|
||||
|
||||
/* Inline tuning form under the bubble: labeled textarea + Save/Cancel
|
||||
(both ≥44px). Save = brand button (dark ink 5.2:1), Cancel = ghost. */
|
||||
.tune-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--brand-soft);
|
||||
border-radius: var(--radius-sm);
|
||||
padding: 0.75rem 0.85rem;
|
||||
}
|
||||
.tune-form label {
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
color: var(--ink-soft);
|
||||
}
|
||||
.tune-form textarea {
|
||||
font: inherit;
|
||||
font-size: 0.9rem;
|
||||
color: var(--ink);
|
||||
background: #0d1120;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: var(--radius-sm);
|
||||
padding: 0.5rem 0.6rem;
|
||||
resize: vertical;
|
||||
min-height: 2.6rem;
|
||||
}
|
||||
.tune-form-actions { display: flex; gap: 0.5rem; }
|
||||
.tune-save {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 44px;
|
||||
padding: 0.4rem 1.1rem;
|
||||
border: 0;
|
||||
border-radius: var(--radius-sm);
|
||||
background: var(--brand);
|
||||
color: var(--bg);
|
||||
font: inherit;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
}
|
||||
.tune-save:hover:not(:disabled) { background: #7d88f5; }
|
||||
.tune-save:disabled { opacity: 0.6; cursor: wait; }
|
||||
.tune-cancel {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 44px;
|
||||
padding: 0.4rem 1rem;
|
||||
border-radius: var(--radius-sm);
|
||||
border: 1px solid var(--line);
|
||||
background: transparent;
|
||||
color: var(--ink-soft);
|
||||
font: inherit;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
}
|
||||
.tune-cancel:hover { background: var(--brand-soft); color: var(--brand-ink); }
|
||||
/* Save confirmation (role=status): ok pair ≈10.6:1. */
|
||||
.tune-saved {
|
||||
margin: 0.2rem 0 0 0.25rem;
|
||||
background: var(--ok-bg);
|
||||
color: var(--ok-ink);
|
||||
border: 1px solid rgb(110 231 168 / 0.35);
|
||||
border-radius: var(--radius-sm);
|
||||
padding: 0.45rem 0.8rem;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
/* Inline save failure (role=alert): err pair ≈9.1:1 — form is kept. */
|
||||
.tune-error {
|
||||
margin: 0 0 0 0.25rem;
|
||||
background: var(--err-bg);
|
||||
color: var(--err-ink);
|
||||
border: 1px solid var(--err-line);
|
||||
border-radius: var(--radius-sm);
|
||||
padding: 0.45rem 0.8rem;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Header panel above the messages: notes newest-first, per-note delete,
|
||||
designed empty state. */
|
||||
.steering-panel {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--brand-soft);
|
||||
border-radius: var(--radius);
|
||||
box-shadow: var(--shadow);
|
||||
padding: 0.9rem 1.1rem 1rem;
|
||||
}
|
||||
.steering-panel-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.15rem 0.6rem; }
|
||||
.steering-panel-title { margin: 0; font-size: 1rem; font-weight: 700; color: var(--ink); }
|
||||
.steering-panel-sub { margin: 0; font-size: 0.82rem; color: var(--ink-soft); }
|
||||
.steering-list {
|
||||
list-style: none;
|
||||
margin: 0.65rem 0 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.4rem;
|
||||
}
|
||||
.steering-note {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
gap: 0.6rem;
|
||||
background: #0d1120;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: var(--radius-sm);
|
||||
padding: 0.35rem 0.4rem 0.35rem 0.8rem;
|
||||
}
|
||||
.steering-note-text {
|
||||
color: var(--ink);
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.45;
|
||||
/* Notes may be multi-line instructions — keep line breaks as typed. */
|
||||
white-space: pre-wrap;
|
||||
overflow-wrap: anywhere;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
.steering-delete {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 44px;
|
||||
min-width: 44px;
|
||||
flex: 0 0 auto;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: var(--radius-sm);
|
||||
background: transparent;
|
||||
color: var(--ink-soft);
|
||||
cursor: pointer;
|
||||
}
|
||||
.steering-delete svg { width: 16px; height: 16px; display: block; }
|
||||
.steering-delete:hover:not(:disabled) { background: var(--err-bg); color: var(--err-ink); border-color: var(--err-line); }
|
||||
.steering-delete:disabled { opacity: 0.5; cursor: wait; }
|
||||
.steering-empty { margin: 0.65rem 0 0; color: var(--ink-soft); font-size: 0.88rem; }
|
||||
|
||||
/* typing indicator */
|
||||
.typing { display: inline-flex; gap: 5px; padding: 0.9rem 1rem; }
|
||||
.typing span {
|
||||
@@ -799,6 +1005,20 @@ body::after {
|
||||
.new-chat-btn { padding: 0.4rem 0.55rem; }
|
||||
.new-chat-label { display: none; }
|
||||
.new-chat-btn svg { display: block; }
|
||||
.steering-toggle { padding: 0.4rem 0.55rem; }
|
||||
/* Visually hidden, NOT display:none — the accessible name keeps the
|
||||
word "Tuning" next to the count badge. */
|
||||
.steering-label {
|
||||
position: absolute !important;
|
||||
width: 1px; height: 1px;
|
||||
margin: -1px; padding: 0;
|
||||
overflow: hidden;
|
||||
clip: rect(0 0 0 0);
|
||||
white-space: nowrap;
|
||||
border: 0;
|
||||
}
|
||||
.steering-note { padding: 0.3rem 0.3rem 0.3rem 0.7rem; }
|
||||
.tune-btn { min-height: 44px; }
|
||||
.msg-body { max-width: 92%; }
|
||||
.empty-state { padding: 1.75rem 1.1rem; margin-top: 0.25rem; }
|
||||
.empty-state-title { font-size: 1.25rem; }
|
||||
|
||||
Reference in New Issue
Block a user