Files
claude-nova/docs/features/conversation-model.md
T
2026-08-11 12:38:02 -03:00

2.4 KiB

Conversation model

Status: Implemented · Code: Scripts/session.js

Session consumes CLI messages and holds everything the views render: the ordered transcript, tool activity, changed files, pending approvals, and running cost. Views subscribe via session.onChange.

Entries

session.entries is an ordered array of:

Kind Fields
user text, context (the label of any attached selection)
assistant messageId, blocks[] of {type: "text" | "thinking", text}
tool id, name, input, summary, filePath, state, result
notice text, tone (info | error)

Tool state moves running → done | error.

The assistant-message merge

One assistant message id arrives several times. The CLI emits a separate assistant message per completed content block — one carrying thinking, then another carrying text — and with --include-partial-messages the same id also arrives as stream_event deltas. They are all one bubble.

_assistantEntry(messageId) keeps a map from message id to entry so every delivery merges into the same entry. Two rules make it correct:

  1. If the entry was streamed (entry.streamed), the authoritative assistant message's text/thinking blocks are skipped — they would duplicate content already assembled from deltas. Tool-use blocks are still registered.
  2. _handleAssistant sets liveAssistant to the entry rather than clearing it. Clearing it was a real bug: the authoritative thinking message arrived mid-message, cleared the pointer, and every subsequent text delta was dropped — the reply rendered empty.

The map is cleared on result, which bounds it to one turn.

Changed files

Only recorded when an editing tool's tool_result comes back without is_error. Recording optimistically on tool use was wrong: a denied write never touched the file, but still appeared in the Changed Files list.

tool_use_result.additions / .deletions supply the counts when present.

Ignored message types

rate_limit_event, system:status, system:thinking_tokens, system:commands_changed, system:mcp_status carry nothing renderable. system:permission_denied becomes an error notice.

Usage

result carries total_cost_usd (cumulative for the session, not per turn — read the latest, never sum) and usage. Input tokens are summed across input_tokens + cache_read_input_tokens + cache_creation_input_tokens.