Releases: cheapestinference/silos
v2.28.1 — fix: pair orphan tool_calls on history load
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.
v2.28.0 — perf pass: browser freeze fixes + latency tab hardening
Browser performance (fixes freezes under streaming load)
- Narrow zustand selectors in
ChatView,AppSidebar,SessionDetailView,SessionTasksKanban,UsageBar,MainShell,App— unrelated store mutations no longer re-render these components - Batched delta writes via new
recordDelta()action (4set()per delta → 1) - Coarse
hasAnyActivityboolean subscription instead of rawlastActivitytimestamp — stops per-delta ChatView re-renders - Stable
messageGroupsuseMemo deps + module-levelEMPTY_AGENTSfallback —MessageGroupmemo now actually skips re-renders during streaming React.memoonMessageGroup,MessageContent,ToolCard,ThinkingBlock- Virtualization threshold lowered 500 → 80 (typical mid-sized conversations now benefit)
Latency tab correctness
- Skip
effectiveTokensPerSecondwhen tool time dominates (>90% of gen time) — prevents absurd rates from tiny residual divisor finalizeRunLatencyfallback to caller-providedsessionKeywhenmarkRunStartwas missed- TTL reaper for orphan
runTimings(10min) - Strict
toolCallIddedup on both call and result counters — tolerates duplicate phase events - Streaming gap threshold 1s → 3s (accommodates batched-delta providers like MiniMax)
- Gap attributed to
toolTimeMsonly while a tool is actually in flight localStorage-backed per-session latency history (7-day cap, max 200/session)- UI: cap notice when showing last 200, tokenization estimate tooltip, corrected gap-attribution hint
v2.23.0
Highlights
Session telemetry + control pass focused on the CMO-style workflows that live on tools.
Agent control
- Activity-based working signal — dashboard no longer loses track of the agent when OpenClaw's compaction retry transparently swaps runs after a context overflow. 15s recent-activity window keeps the Stop button visible across short gaps.
- Abort fallback via lastKnownRunId — Stop still aborts when
activeRunIdhas been cleared by an intermediate error event.
Latency breakdown
- Per-run tool count badge, gap-based tool time detection (>1s gaps = tool/wait, not generation), and effective tok/s that excludes those gaps.
- Aggregate stats split avg latency by w/tools vs plain runs.
Errors panel
- New reusable
JsonTreecomponent with syntax colors, depth-based collapse, long-string previews, and auto-unwrap of nested JSON strings (tool-resultcontent[0].textrenders as a sub-tree, not an escaped blob). - Copy button produces the flattened form you see on screen, not the wire-format with
\n\"escapes. - Detects OpenClaw's
{content, details}tool-error shape and showsdetailsby default with a toggle for the raw wire format.
Logs
- Fixes tslog's
log.child({subsystem}).info(msg)serialization: parser now correctly extracts the message from1instead of rendering the tag stringified in0as the body. Unwraps_meta.namewhen it arrives as a JSON string. Fallback summary when no primary content field is populated. LogDetailPanelhides the Payload section when it's just the Message repeated, and renders string payloads as preformatted blocks so CLI-table alignment survives.
Chat history stripping
- Replaced the regex-based
stripInboundMetawith a line-by-line parser ported from OpenClaw's canonicalstripInboundMetadata. Handles all 6 sentinels + trailing untrusted-context suffix + timestamp prefix. Silos-specific addition strips asyncSystem (untrusted): [ts] ...lines for cleaner chat.
Task pipeline
- Dropped the
isBackgroundProcessheuristic that substring-matchedpid,still running,backgroundin tool results and created false-positive "Subagent" entries in the kanban. - Sidebar Tasks badge filters stale runs (status=running + startedAt >1h) so it aligns with what
/tasksshows.
Included commits:
18a2b2bfeat(session): activity-based agent-working signal + abort fallbackdda8309feat(latency): tool count, gap-based tool time, effective tok/sc02cc3bfeat(errors): reusable JsonTree + auto-unwrap + tool-result simplificatione040683fix(logs): tslog tag unwrapping, preformatted payloads, dedup empty sections3164291refactor(chat): port stripInboundMeta canonical parser from OpenClaweb170cdfix(tasks): stale-aware sidebar Tasks badge + drop isBackgroundProcess false-positive
v2.22.1
v2.22.0
Summary
- Logs: semantic color tokens for light/dark themes —
--log-*and--syntax-*CSS variables exposed via Tailwind aslog.{error,warn,info,subsystem}andsyntax.{string,number,boolean,key}. AA contrast in both modes withoutdark:modifiers on each class. - Session telemetry: new bottom tab bar in ChatView with Tools / Errors / Latency, persistent selection and auto-switch on new events. Errors panel captures tool failures, provider errors, rate-limited 429s (RPM/TPM/BUDGET), chat errors, and network errors with per-session badge. Latency panel estimates TTFB, total latency, and tokens/s per run with avg/p50/p95 aggregates (client-side, no gateway changes).
- Crons tab in top panel next to Pipeline: lists cron jobs scoped to the agent; expanding a card lazy-loads runs, clicking a run opens
TaskRunDetailwith cron-specific info and conversation filtered by runId. - Tasks redesign (
/tasks): cancel/abort/retry actions across subagent, ACP, CLI, and cron runtimes. - Pipeline kanban: converted to single-expanded accordion — all rows collapsed by default, click to expand one (collapses others), persisted per user.
- Docs: README polish with tighter architecture diagram and Quick Start.
Included commits:
120e161feat(tasks): redesign /tasks + add cancel/abort/retry actions across runtimes73689addocs: polish README0a32a08feat(logs): add semantic color tokens for light/dark themes0f4be26feat(session): add Errors, Latency, and Crons tabs with telemetry6c27d19refactor(tasks): convert vertical kanban to single-expanded accordion
v2.21.0
Summary
- Always show pipeline kanban rows (Queued/Running/Waiting/Done) even when empty
- Add inline LaTeX→Unicode rendering for chat messages
- Decompose dashboard-store monolith into 9 focused Zustand slices
- Fix tsc -b strict build errors
v2.20.1
Summary
- fix: browser viewer auto-reconnects after VNC disconnect (3s retry loop instead of staying stuck)
- Add postMessage bridge between noVNC iframe and React panels for accurate connection status
- Connection status dot now shown in floating browser panel too
v2.20.0
v2.20.0 — Chat & Settings Refactor
Bug Fixes
- Fix tool call/result matching using
toolCallId(aligned with OpenClaw official UI) - Fix duplicate
stripReasoningTags— unified tolib/reasoning-tags.ts - Fix streaming double-strip bug (preserve mode in StreamingMarkdown)
- Fix
tool_usecontent blocks lost inloadChatHistory - Fix invisible URLs in light mode (
text-white→text-primary) - Fix rate limit state lost on component unmount (moved to Zustand store)
- Increase chat history limit 100 → 200 (matches OpenClaw)
- Deduplicate tool messages on history reload
Refactoring
- Extract 10 components from ChatView.tsx (1816 → 689 lines) into
src/components/chat/ - Extract 7 sections from SettingsPage.tsx (2764 → 108 lines) into
src/components/settings/ - Split 730-line
handleEventinto 3 focused handlers inchat-event-handlers.ts - Extract
isSilentReplyto sharedlib/reasoning-tags.ts - Add
toolCallIdfield toChatMessagetype
Cleanup
- Delete 6 unused components
- Net reduction: -2,116 lines
Commits
ca71925 fix: remove unused imports (EventFrame, describeBrowserAction) for strict tsc -b
46d9e45 refactor: extract chat and settings components, fix 7 chat bugs
v2.19.5
Changes
- Fix context window display: Resolve correct context window per model from the model catalog instead of always showing OpenClaw's 200K fallback
- Strip reasoning tags: Remove internal reasoning tags from message content in task detail, task run detail, and sessions views
- UI cleanup: Add vertical layout to session tasks kanban, remove unused Layout/Sidebar components
v2.19.4
fix: hide misleading 200k context window when provider doesn't report real value