diff --git a/lyra/chat.py b/lyra/chat.py
index 971bc7d..551d58f 100644
--- a/lyra/chat.py
+++ b/lyra/chat.py
@@ -30,6 +30,11 @@ def _detail_note(exchanges: list[memory.Exchange]) -> Message:
return {"role": "system", "content": body}
+def _render(messages: list[Message]) -> str:
+ """Human-readable dump of the exact prompt, for the live-log inspector."""
+ return "\n\n".join(f"[{m['role']}]\n{m['content']}" for m in messages)
+
+
def build_messages(session_id: str, user_msg: str) -> list[Message]:
"""Assemble the full, tiered message list for one turn."""
messages: list[Message] = [{"role": "system", "content": persona.system_prompt()}]
@@ -51,16 +56,17 @@ def build_messages(session_id: str, user_msg: str) -> list[Message]:
if recalled:
messages.append(_detail_note(recalled))
- logbus.log(
- "debug", "context built",
- recent=len(recent), summaries=len(summaries), details=len(recalled),
- )
-
# Tier 3: current session, full fidelity.
for ex in recent:
messages.append({"role": ex.role, "content": ex.content})
messages.append({"role": "user", "content": user_msg})
+
+ logbus.log(
+ "debug", "context built",
+ recent=len(recent), summaries=len(summaries), details=len(recalled),
+ chars=sum(len(m["content"]) for m in messages), detail=_render(messages),
+ )
return messages
diff --git a/lyra/web/static/index.html b/lyra/web/static/index.html
index 3cbb822..adb30a6 100644
--- a/lyra/web/static/index.html
+++ b/lyra/web/static/index.html
@@ -734,7 +734,10 @@
const level = event.level || 'info';
const time = new Date((event.ts || 0) * 1000).toLocaleTimeString();
- const fields = event.fields || {};
+ const fields = Object.assign({}, event.fields || {});
+ // `detail` is rendered as an expandable block, not an inline field.
+ const detail = fields.detail;
+ delete fields.detail;
const fieldStr = Object.keys(fields).length
? Object.entries(fields).map(([k, v]) => `${k}=${v}`).join(' ')
: '';
@@ -746,6 +749,7 @@
${escapeHtml(level)}
${escapeHtml(event.msg || '')}
${fieldStr ? `${escapeHtml(fieldStr)}` : ''}
+ ${detail ? `view full prompt
${escapeHtml(detail)} ` : ''}
`;
thinkingContent.appendChild(eventDiv);
diff --git a/lyra/web/static/style.css b/lyra/web/static/style.css
index bdfbb46..a93bf8a 100644
--- a/lyra/web/static/style.css
+++ b/lyra/web/static/style.css
@@ -941,3 +941,25 @@ select:hover {
.log-error .log-level, .log-error .log-msg { color: #fca5a5; }
.log-system { border-left-color: #00ff66; }
.log-system .log-level { color: #00ff66; }
+
+.log-detail { width: 100%; margin-top: 4px; }
+.log-detail summary {
+ cursor: pointer;
+ color: var(--accent);
+ font-size: 0.72rem;
+ user-select: none;
+}
+.log-detail pre {
+ margin: 6px 0 0;
+ padding: 8px;
+ max-height: 340px;
+ overflow: auto;
+ background: rgba(0,0,0,0.25);
+ border-left: 2px solid var(--accent);
+ border-radius: 4px;
+ font-size: 0.72rem;
+ line-height: 1.4;
+ white-space: pre-wrap;
+ word-break: break-word;
+ color: var(--text);
+}