- Add blockCounter to Agent, generating sequential hex IDs
- Include #blockId in all block headers: [[[role:name#id]]]
- GUI parses server-provided IDs from headers
- Falls back to client-generated IDs for legacy blocks without server IDs
- Block IDs are now deterministic based on chat history order
- Add blockId field to ChatBlock (12-char MD5 hash of counter+name)
- Bookmarks now use blockId instead of volatile list index
- Plumb URLs use blockId: ollie://session/agent#abc123def456
- Add indexForBlockId() to look up current index from stable ID
- Action buttons always visible (no hover flicker)
Add table rendering support to ChatBlockModel:
- isTableLine(): detect pipe-delimited table rows
- renderTable(): convert table lines to HTML <table>
- renderProse(): split prose into text/table segments
- incrementalAppend: handle table state transitions during streaming
Tables render with header row detection (before |---|---| separator)
and proper incremental updates as content streams in.