Explainability (/lens), training export, prompt caching#7
Merged
Conversation
Answers 'why did this small command burn 80k tokens?' with a structured
per-turn ledger recorded by the engine:
- Per model request: REAL input/output tokens, thinking share
(estimated from thinking-delta chars at chars/3.5, or the provider's
real reasoning_tokens on OpenAI o-series), duration, stop reason
- Per tool call: name, label, duration, output size, 1500-char output
preview (harness debugging), is_error, hook blocks; ask_user records
human-wait time; MCP calls timed + failures captured
- Per subagent: OWN token attribution (child usage credited to the
subagent entry, still counted in parent totals), steps, duration,
report size, failures
- Engine events: auto-continues, request-cap exits, compactions
- Key insight surfaced explicitly: billed input = Σ per-request input
(whole history resent every request) vs. live context size
/lens → text summary: totals, hottest request, biggest tool
outputs, subagent table, engine events
/lens html → self-contained interactive report (token bars per
request, click-to-expand tool outputs + subagents)
/lens json → full ledger for external tooling
Thinking tokens: output_tokens from the API already INCLUDES thinking
(providers bill reasoning as output) — lens now separates the share.
Ledger capped at 50 turns; tests pin request/tool/total accounting and
subagent attribution against the scripted mock. 102 tests, 0 fail.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Stored sessions are full multi-turn agentic trajectories (real user
prompts, tool calls, tool results, steers) — exactly what open-model
SFT needs. New exporter turns them into training JSONL:
mist --export-training [out.jsonl] [--format=openai] [--min-turns=N]
[--no-redact]
- One line per session: system prompt, the 9 tool specs the model saw,
full message history, session metadata (id/title/created_at/source)
- --format=openai emits the function-calling shape (system message,
assistant.tool_calls, role:'tool' results) consumed directly by
LLaMA-Factory / Axolotl / torchtune; default is the native
Anthropic content-block shape
- Secret redaction ON by default: Anthropic/OpenAI keys, GitHub PATs,
Slack tokens, AWS keys, Bearer tokens, quoted api_key/token/password
JSON values → [REDACTED_*]; --no-redact for raw (labeled loudly)
- --min-turns filters empty/trivial sessions (genuine prompts only —
auto-continue nudges and compaction summaries don't count)
- Shared anthropic→openai translation extracted from OpenAIClient
(toOpenAIMessages) — one mapping, used by both wire client and export
Verified on 11 real stored sessions; tests pin both shapes, redaction
patterns, and filtering. 105 tests, 0 fail.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Mist never sent cache_control before, so Anthropic-protocol endpoints repaid the full history price on every request. Now: - anthropic.ts: system sent as a text block with cache_control ephemeral, plus a breakpoint on the last message's final content block (moves forward each request so the whole history prefix stays cached). MIST_CACHE=0 opts out. Parses cache_read/creation_input_tokens. - TurnResult carries cacheReadTokens/cacheWriteTokens; agent.ts sums input + read + write for the true prompt size — fixes context/compaction accounting, which previously saw only the uncached remainder. - Lens: per-request + total cache fields; /lens shows a cache line (read/written/% served from cache, or a hint when the endpoint doesn't support caching); HTML report shows '(N cached)'. - mock_model: normalize block-array system for branch sniffing; ANSWER usage now includes cache fields; wire-format test asserts breakpoints are sent and MIST_CACHE=0 disables them. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- test_run_pending_credentials_success: input mock had no return value, so the credential prompt received a Mock object instead of a string - mcp conftest: get_current_agent is imported directly by start/stop command modules — patch those import sites too, not just the package Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The user row used a color nearly identical to body text in three of four themes (cinnamon was literally the same hex), so your own inputs vanished while scrolling a long conversation. Now each theme defines a distinct user color plus a subtle userBg band behind the whole ' ❯ prompt ' line: - mist: soft mint on deep misty teal - cinnamon: butterscotch on toasted brown - hinokami: gold on embered dark-gold - moon: gold irises on kimono purple Verified live in tmux against the mock model. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Brings GPT/Gemini to parity with the Anthropic cache work. Both providers cache automatically (no breakpoints needed) but report the cached amount as a SUBSET of their prompt-token count — the opposite of Anthropic's uncached-remainder semantics. The clients now split: inputTokens = uncached remainder, cacheReadTokens = cached subset, so agent-side summing and /lens stay provider-agnostic. - openai.ts: parse prompt_tokens_details.cached_tokens - gemini.ts: parse cachedContentTokenCount + thoughtsTokenCount (real reasoning usage — /lens thinking share is now exact on Gemini too) - provider mocks report cached tokens; tests assert the split Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A 429/529/5xx or network drop used to kill the whole turn. Now every leaf model client is wrapped in RetryingClient: exponential backoff with jitter (1s base, doubling, 30s cap), up to MIST_RETRIES attempts (default 5, 0 disables; MIST_RETRY_BASE_MS tunes the base). The wait is visible in the TUI — '⚠ API error (…) — retrying in Ns (attempt x/y)' — and recorded as a model.retry protocol event. Safety rule: never retry once visible output has streamed — a re-send would duplicate text already on screen; those errors surface and the turn stays resumable. Headless calls (title gen, summarizer) may retry even mid-stream since nothing was displayed. Retryable: 408/409/425/429/500/502/503/504/529, provider 'overloaded' stream errors, fetch-level network failures. 4xx auth/validation errors surface immediately. round_robin candidates are wrapped individually — the outer node is not, so attempts never multiply. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three features that make Mist observable, reusable, and cheaper — plus two legacy-test repairs.
/lens — explainability & interpretability module (f9cf8a3)
Every turn records a structured ledger: model requests (real input/output tokens, thinking share, stop reason), tool calls (duration, output size, previews, errors, hook blocks), subagents with their own token attribution, auto-continues, cap hits, and compactions.
/lens— in-TUI summary: where the tokens went for the last turn/lens html— self-contained interactive report (token bars, expandable tool outputs, subagent cards)/lens json— raw ledger for scripting--export-training — sessions as SFT-ready trajectories (5e4ba16)
mist --export-training out.jsonlconverts recorded sessions into one-trajectory-per-line JSONL in Anthropic or OpenAI function-calling format (--format), with secret redaction (API keys, tokens, bearer headers) on by default.Prompt caching (402c4e7)
Mist never sent
cache_controlbefore — every request repaid the full history at uncached input price. Now:ephemeral), moving forward each request so the history prefix stays cached;MIST_CACHE=0opts outinput + cache_read + cache_write— fixes context-size and compaction-trigger accounting, which previously saw only the uncached remainder/lensshows a cache line with % of input served from cache, or a hint when the endpoint ignores cachingLegacy Python test repairs (358e7ad)
Two stale mocks in the deprecated
mist-pysuite: a credential-prompt input mock with no return value, andget_current_agentpatched at the package but not at the start/stop command import sites.Test plan
cd ts && bun test— 106 tests, 0 fail (includes new cache accounting, context-size, and wire-format tests)bun run build— binary compiles🤖 Generated with Claude Code