Now I have the full picture. Here's how Amp differs and what it means for the frontend:
How Amp Stores Sessions Differently
1. Single JSON file per thread (not JSONL)
Other adapters use JSONL (one event per line) or SQLite. Amp uses a single threads/T-{uuid}.json with a messages array — the whole file is rewritten on each update. This means we parse the entire file each time (no tail-scanning optimization like Claude Code).
2. Rich tool_result structure
Claude Code tool results are simple content blocks. Amp wraps them in { run: { status, result, progress } } with structured result objects (not just strings). Our adapter serializes run.result to JSON, which works but means the frontend sees JSON blobs rather than pre-formatted output.
3. Interruptions are state.type: "cancelled" or "streaming"
Claude Code marks interruptions with a [Request interrupted by user] text message. Amp uses:
state.type: "cancelled" on assistant messages
state.type: "streaming" for in-progress (thread read while still running)
tool_result blocks with run.status: "cancelled"
The frontend's isInterruptionMessage() only checks for Claude Code's [Request interrupted...] pattern and OpenCode's (no error message) error parts — it won't detect Amp interruptions.
4. Rich env metadata
Amp stores detailed environment info: git repo URL, branch, SHA, OS, CPU architecture, client version, and workspace tree URIs. Other adapters just store a project path string. We could surface this richer context.
5. No toolName on tool results
Amp's tool_result blocks don't include the tool name — only the toolUseID. Our adapter currently emits toolName: '' for results. The frontend's ToolCallRouter matches results to calls by callId, so this works, but tools that key off toolName in the result might show fallback rendering.
Frontend Changes Worth Considering
| Issue | Impact | Fix |
|---|
| Interruptions invisible | Amp cancelled turns show as blank/empty messages | Add Amp's cancelled state detection to adapter (emit an error event) or teach frontend about it |
| Tool result is JSON blob | Read/Edit results show as raw {"absolutePath":..., "content":...} instead of formatted output | Frontend's parseRawResult already handles JSON with contents field (Cursor format) — could extend to handle Amp's result.content field |
| No agent color | getAgentColor('amp') returns the default muted color | Add an Amp-specific color to the theme |
| Streaming threads | Active threads have state.type: "streaming" messages with incomplete content | Adapter should skip or handle these gracefully |
The most impactful quick wins would be handling interruptions in the adapter and adding an agent color. Want me to tackle any of these?