feat: off the record mode (OTR)
Adds a third input mode toggle alongside Note and Agent. When active: - Textarea gets a subtle purple tint with dashed border - OTR button highlights purple - Placeholder reads "Off the record — not logged or distilled…" - off_record=True is sent to /chat; session_logger is skipped - In-memory session context is preserved within the session Switching to Note or Agent mode deactivates OTR, and vice versa. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -23,6 +23,7 @@ class ChatRequest(BaseModel):
|
|||||||
include_long: bool = True
|
include_long: bool = True
|
||||||
include_mid: bool = True
|
include_mid: bool = True
|
||||||
include_short: bool = True
|
include_short: bool = True
|
||||||
|
off_record: bool = False # skip session log (in-memory context preserved)
|
||||||
user: str = "scott"
|
user: str = "scott"
|
||||||
persona: str = "inara"
|
persona: str = "inara"
|
||||||
|
|
||||||
@@ -92,7 +93,8 @@ async def _stream_chat(req: ChatRequest):
|
|||||||
response_text, actual_backend = task.result()
|
response_text, actual_backend = task.result()
|
||||||
history.append({"role": "assistant", "content": response_text})
|
history.append({"role": "assistant", "content": response_text})
|
||||||
save_session(session_id, history)
|
save_session(session_id, history)
|
||||||
log_turn(session_id, req.message, response_text)
|
if not req.off_record:
|
||||||
|
log_turn(session_id, req.message, response_text)
|
||||||
|
|
||||||
requested = req.model or settings.primary_backend
|
requested = req.model or settings.primary_backend
|
||||||
payload = {
|
payload = {
|
||||||
|
|||||||
@@ -80,11 +80,35 @@
|
|||||||
|
|
||||||
agentModeBtnEl.addEventListener('click', () => {
|
agentModeBtnEl.addEventListener('click', () => {
|
||||||
agentMode = !agentMode;
|
agentMode = !agentMode;
|
||||||
|
if (agentMode) { otr_mode = false; update_otr_ui(); }
|
||||||
localStorage.setItem('agentMode', agentMode);
|
localStorage.setItem('agentMode', agentMode);
|
||||||
updateAgentModeUI();
|
updateAgentModeUI();
|
||||||
inputEl.focus();
|
inputEl.focus();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ── Off the record mode ──────────────────────────────────────
|
||||||
|
let otr_mode = false;
|
||||||
|
const otr_btn_el = document.getElementById('otr-btn');
|
||||||
|
|
||||||
|
function update_otr_ui() {
|
||||||
|
otr_btn_el.classList.toggle('active', otr_mode);
|
||||||
|
inputEl.classList.toggle('otr-mode', otr_mode);
|
||||||
|
updateInputPlaceholder();
|
||||||
|
}
|
||||||
|
|
||||||
|
otr_btn_el.addEventListener('click', () => {
|
||||||
|
otr_mode = !otr_mode;
|
||||||
|
if (otr_mode) {
|
||||||
|
agentMode = false;
|
||||||
|
noteMode = false;
|
||||||
|
localStorage.setItem('agentMode', false);
|
||||||
|
updateAgentModeUI();
|
||||||
|
updateInputMode();
|
||||||
|
}
|
||||||
|
update_otr_ui();
|
||||||
|
inputEl.focus();
|
||||||
|
});
|
||||||
|
|
||||||
// ── Note mode ────────────────────────────────────────────────
|
// ── Note mode ────────────────────────────────────────────────
|
||||||
let noteMode = false;
|
let noteMode = false;
|
||||||
let notePublic = false;
|
let notePublic = false;
|
||||||
@@ -124,6 +148,8 @@
|
|||||||
inputEl.placeholder = ctrlEnterMode
|
inputEl.placeholder = ctrlEnterMode
|
||||||
? `Task for ${personaLabel}… (Gemini tool loop — Ctrl+Enter to run)`
|
? `Task for ${personaLabel}… (Gemini tool loop — Ctrl+Enter to run)`
|
||||||
: `Task for ${personaLabel}… (Gemini tool loop)`;
|
: `Task for ${personaLabel}… (Gemini tool loop)`;
|
||||||
|
} else if (otr_mode) {
|
||||||
|
inputEl.placeholder = `Off the record — not logged or distilled…`;
|
||||||
} else {
|
} else {
|
||||||
inputEl.placeholder = ctrlEnterMode
|
inputEl.placeholder = ctrlEnterMode
|
||||||
? `Message ${personaLabel}… (Ctrl+Enter to send)`
|
? `Message ${personaLabel}… (Ctrl+Enter to send)`
|
||||||
@@ -133,6 +159,7 @@
|
|||||||
|
|
||||||
noteBtnEl.addEventListener('click', () => {
|
noteBtnEl.addEventListener('click', () => {
|
||||||
noteMode = !noteMode;
|
noteMode = !noteMode;
|
||||||
|
if (noteMode) { otr_mode = false; update_otr_ui(); }
|
||||||
updateInputMode();
|
updateInputMode();
|
||||||
inputEl.focus();
|
inputEl.focus();
|
||||||
});
|
});
|
||||||
@@ -690,6 +717,7 @@
|
|||||||
include_long: memLong,
|
include_long: memLong,
|
||||||
include_mid: memMid,
|
include_mid: memMid,
|
||||||
include_short: memShort,
|
include_short: memShort,
|
||||||
|
off_record: otr_mode,
|
||||||
user: CORTEX_USER,
|
user: CORTEX_USER,
|
||||||
persona: CORTEX_PERSONA,
|
persona: CORTEX_PERSONA,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -131,6 +131,7 @@
|
|||||||
<!-- Note mode controls -->
|
<!-- Note mode controls -->
|
||||||
<button id="note-type-btn">private</button>
|
<button id="note-type-btn">private</button>
|
||||||
<button id="note-btn">Note</button>
|
<button id="note-btn">Note</button>
|
||||||
|
<button id="otr-btn" title="Off the record — not logged or distilled into memory">OTR</button>
|
||||||
<button id="agent-mode-btn" title="Agent mode — Gemini tool loop + Claude response">Agent</button>
|
<button id="agent-mode-btn" title="Agent mode — Gemini tool loop + Claude response">Agent</button>
|
||||||
<button id="send">Send</button>
|
<button id="send">Send</button>
|
||||||
<button id="stop">Stop</button>
|
<button id="stop">Stop</button>
|
||||||
|
|||||||
@@ -571,6 +571,27 @@
|
|||||||
#note-btn.active { border-color: rgba(180, 130, 40, 0.6); color: #c9a84c; }
|
#note-btn.active { border-color: rgba(180, 130, 40, 0.6); color: #c9a84c; }
|
||||||
#note-btn.active.public { border-color: rgba(40, 170, 150, 0.6); color: #4abfb0; }
|
#note-btn.active.public { border-color: rgba(40, 170, 150, 0.6); color: #4abfb0; }
|
||||||
|
|
||||||
|
/* OTR button */
|
||||||
|
#otr-btn {
|
||||||
|
background: var(--bg);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
color: var(--muted);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 8px 0;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
text-align: center;
|
||||||
|
transition: border-color 0.15s, color 0.15s;
|
||||||
|
}
|
||||||
|
#otr-btn:hover { border-color: var(--muted); color: var(--text); }
|
||||||
|
#otr-btn.active { border-color: rgba(120, 80, 160, 0.6); color: #a87fd4; }
|
||||||
|
|
||||||
|
/* OTR textarea styling */
|
||||||
|
#input.otr-mode {
|
||||||
|
border-color: rgba(120, 80, 160, 0.4);
|
||||||
|
background: rgba(120, 80, 160, 0.04);
|
||||||
|
}
|
||||||
|
|
||||||
/* Send button */
|
/* Send button */
|
||||||
#send {
|
#send {
|
||||||
background: var(--user-bg);
|
background: var(--user-bg);
|
||||||
|
|||||||
Reference in New Issue
Block a user