Skip to content

fix(runtime, channels): unify session backend behind one factory#6384

Open
singlerider wants to merge 2 commits intozeroclaw-labs:masterfrom
singlerider:fix/5769-session-tools-sqlite-backend
Open

fix(runtime, channels): unify session backend behind one factory#6384
singlerider wants to merge 2 commits intozeroclaw-labs:masterfrom
singlerider:fix/5769-session-tools-sqlite-backend

Conversation

@singlerider
Copy link
Copy Markdown
Collaborator

@singlerider singlerider commented May 5, 2026

Summary

The session tools (sessions_list, sessions_history, sessions_send, sessions_current) were registered against the JSONL SessionStore, but the gateway WebSocket handler persisted sessions to SqliteSessionBackend. Any session created via /ws/chat was therefore invisible to the agent's own session tools (sessions_list returned "No active sessions found" for valid gateway session IDs, and the agent then hallucinated session IDs).

Naively swapping the tool registration to SQLite would have traded one half-blindness for another: the channel orchestrator was opening JSONL too, so channel sessions (Telegram, Slack, Discord, ...) would have stopped showing up in the tools.

Introduce zeroclaw_infra::make_session_backend(workspace_dir, &str) that picks JSONL or SQLite based on the existing [channels].session_backend config field (which the schema already exposed; nothing was reading it). Both call sites, the channel orchestrator's session_store and the runtime tool registration, now go through this factory. The configured backend becomes the single source of truth and channel + WS sessions both surface in the same store.

The orchestrator's session_store field switches from Option<Arc<SessionStore>> to Option<Arc<dyn SessionBackend>>. The mtime-based hydration sort is replaced with the trait's list_sessions_with_metadata().last_activity field, which both backends populate, so no SessionStore-specific method is on the hot path.

Closes #5769

Validation Evidence

cargo fmt --all -- --check
cargo clippy --workspace --exclude zeroclaw-desktop --all-targets --features ci-all -- -D warnings
cargo test --package zeroclaw-channels --lib rollback_orphan_user_turn

All three pass locally.

Security & Privacy Impact

  • New permissions, capabilities, or filesystem access scope? No.
  • New external network calls? No.
  • Secrets / tokens / credentials handling changed? No.
  • PII or real identities in diff, tests, fixtures, or docs? No.

Compatibility

  • Backward compatible? Yes for the default config (session_backend = "sqlite"). Operators who set session_backend = "jsonl" continue to read/write JSONL files; the difference is that runtime tools now honour the same setting, so they see those sessions too.
  • Config / env / CLI surface changed? No new fields. The existing [channels].session_backend is now load-bearing for both call sites instead of just the gateway.

Rollback

git revert <merge-sha>. The orchestrator and tool registration both revert in lockstep; no migration is required because each backend reads its own on-disk format.

The gateway WebSocket handler persists sessions to SqliteSessionBackend
(sessions/sessions.db, with gw_-prefixed keys) and the gateway REST API
reads from the same place. The session tools (sessions_list,
sessions_history, sessions_send) were initialized with the JSONL
SessionStore, so they looked at sessions/*.jsonl files the gateway
never writes.

Result: gateway sessions are invisible to the agent. sessions_list
returns "No active sessions found" even when the SQLite store has
gw_ entries, and sessions_history returns "No messages found" for any
gateway session ID. The agent then hallucinates session IDs because
the tool returns empty data.

Switch the registration site at crates/zeroclaw-runtime/src/tools/mod.rs
to SqliteSessionBackend. Both backends implement the SessionBackend
trait with the same new(&Path) signature, so this is a one-line swap
plus a comment update.

Closes zeroclaw-labs#5769.
@singlerider singlerider added bug Something isn't working gateway Auto scope: src/gateway/** changed. labels May 5, 2026
@singlerider singlerider self-assigned this May 5, 2026
@singlerider singlerider added tool Auto scope: src/tools/** changed. risk: high Auto risk: security/runtime/gateway/tools/workflows. size: XS Auto size: <=80 non-doc changed lines. labels May 5, 2026
The original PR swapped the runtime tools to SqliteSessionBackend
without touching the channel orchestrator, which still hardcoded the
JSONL SessionStore. That trades one half-blindness for another:
sessions written by channels (Telegram, Slack, Discord, ...) become
invisible to the agent's sessions_list / sessions_history tools.

Introduce zeroclaw_infra::make_session_backend(workspace_dir, &str)
that picks JSONL or SQLite based on [channels].session_backend (which
the schema already exposes; nothing was reading it). Both call sites
(channel orchestrator session_store, runtime tool registration) now
go through this factory, so the configured backend is the single
source of truth and channel + WS sessions both surface in the same
store.

The orchestrator's session_store field switches from
Option<Arc<SessionStore>> to Option<Arc<dyn SessionBackend>>. The
mtime-based hydration sort is replaced with the trait's
list_sessions_with_metadata() last_activity field, which both
backends already populate, so there is no SessionStore-specific
method on the hot path.

Closes zeroclaw-labs#5769
@github-actions github-actions Bot removed gateway Auto scope: src/gateway/** changed. tool Auto scope: src/tools/** changed. labels May 5, 2026
@singlerider singlerider added this to the v0.7.5 milestone May 5, 2026
@singlerider singlerider changed the title fix(runtime/tools): use SQLite backend for session tools fix(runtime, channels): unify session backend behind one factory May 5, 2026
@singlerider singlerider marked this pull request as ready for review May 5, 2026 06:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working risk: high Auto risk: security/runtime/gateway/tools/workflows. size: XS Auto size: <=80 non-doc changed lines.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Session tools (sessions_list/sessions_history) use JSONL backend instead of SQLite — returns empty for gateway sessions

1 participant