Netclaw 0.9.0
0.9.0 2026-03-27
Netclaw v0.9.0 — Two-phase streaming timeout, FTS5 memory recall, turn-based distillation, and streaming performance fix
Features
- Added two-phase streaming timeout for LLM calls — introduces separate
FirstTokenTimeoutandStreamIdleTimeoutsettings, replacing the single monolithic timeout. The first-token window catches provider failures fast while the idle timeout tolerates long-running tool-use streams without premature cancellation. (#460) - Added turn-based memory distillation trigger alongside idle timeout — sessions now trigger memory distillation at turn boundaries in addition to the existing 90-second idle timer, so busy multi-turn conversations no longer defer all memory formation until the session goes quiet. (#442, #463)
- Migrated memory recall search from LIKE to SQLite FTS5 full-text search with BM25 scoring — recall queries now use a dedicated FTS5 virtual table for relevance-ranked results instead of substring matching, significantly improving recall quality for multi-word queries. (#436)
- Added token delta and cumulative logging to
LoggingChatClient— each streaming chunk now logs its individual token delta alongside the running cumulative total, making it easier to diagnose token consumption during long tool-use loops. (#443, #445)
Bug Fixes
- Fixed daemon restarting active sessions during config reload — the config restart path now drains all active sessions gracefully before applying the new configuration, preventing mid-turn interruptions. (#468)
- Fixed
web_fetchsaving binary content with incorrect extensions and corrupted bytes — binary responses (images, PDFs, etc.) are now saved with the correct file extension derived from the Content-Type header, and raw bytes are written without text encoding round-trips. (#386, #461) - Enforced HTTPS by default in the
web_fetchtool — requests to plain HTTP URLs are now rejected unless explicitly allowed, hardening the default security posture for outbound fetches. (#458) - Fixed
netclaw initauto-detecting Slack webhook format from URL — the init wizard now inspects the webhook URL to determine whether it is a Slack incoming webhook and sets"Format": "Slack"automatically, eliminating a common misconfiguration. (#401, #462) - Stopped persisting system prompt in Akka journal — the full system prompt was previously included in persisted session state, bloating the journal and slowing recovery. It is now excluded from persistence and reconstructed on recovery. (#451)
- Enforced record-class storage for evidence memories — evidence memory proposals that arrived as plain strings are now normalized into the expected record-class format before storage, preventing downstream deserialization failures. (#446, #452)
- Added
TurnOutcometo prevent quick-exit paths from inflating turn count — tool-only and no-op turns that exit early without an LLM response no longer increment the turn counter, giving more accurate turn-based metrics. (#450) - Added singleton guard and PID file watchdog to prevent duplicate daemons — launching a second daemon instance now fails fast with a clear error instead of silently competing for resources. A PID file watchdog detects stale lock files from crashed processes. (#433)
- Fixed console output leaks in CLI and daemon — stray
Console.Writecalls that bypassed the structured logging pipeline are now routed through the proper output channels. (#425)
Performance
- Fixed O(n^2)
ToolCallTextFilterscanning during streaming — replaced the quadratic per-chunk scan with incremental delta detection, eliminating a hot path that caused visible latency on long tool-call sequences. (#454, #457)
Diagnostics
- Unified daemon uptime into a single
DaemonStartClocksingleton — previously uptime was computed from multiple inconsistent sources. All uptime queries now read from one authoritative clock. (#456) - Surfaced diagnostic detail when update check fails —
netclaw updateand background update checks now log the specific HTTP status and error body instead of a generic "check failed" message. (#431)
Dependencies
- Bumped ModelContextProtocol.Core from 1.0.0 to 1.1.0. (#434)