Fix
Tool cards from chat history were rendering as forever-running amber spinners
because the tool_result data was never linked back to its originating tool_call.
Root cause
OpenClaw gateway persists tool results in a shape Silos wasn't reading:
- Anthropic-style: `{type: 'tool_result'}` content blocks inside the next user message
- OpenClaw-native: separate top-level messages with `role: 'toolResult'`, with `toolCallId` + `toolName` + `content` as siblings on the message
`loadChatHistory` was dropping `role: 'toolResult'` messages via filter, and the link was lost.
Fix
- `buildToolResultMap` scans raw history for both shapes
- `injectToolResultBlocks` inserts synthetic tool_result blocks adjacent to each tool_call so `MessageContent`'s existing pairing catches them inline
- `extractToolMessagesFromBlocks` accepts the map so extracted tool ChatMessages (visible in bottom Tools panel) also get their `result` populated
- True orphans (run aborted mid-tool, no result anywhere) now render with an "aborted" notice instead of spinning forever
Tests
17 tests in `message-normalizer.test.ts` cover both shapes + orphan path.