Skip to content

fix(state): index tool_name and tool_calls in FTS5, with repair + migration (salvages #16866)#16914

Merged
teknium1 merged 3 commits into
mainfrom
hermes/hermes-728f5f3e
Apr 28, 2026
Merged

fix(state): index tool_name and tool_calls in FTS5, with repair + migration (salvages #16866)#16914
teknium1 merged 3 commits into
mainfrom
hermes/hermes-728f5f3e

Conversation

@teknium1

Copy link
Copy Markdown
Contributor

Salvages @yes999zc's work on #16866 and fixes two gaps that blocked merging.

Summary

session_search now sees tool_name and tool_calls. Closes #16751.

Changes

  • Cherry-pick of @yes999zc's commit (authorship preserved): switches both FTS5 tables (messages_fts, messages_fts_trigram) from external-content to inline mode and concatenates content || tool_name || tool_calls in the insert/update triggers; widens the short-CJK LIKE fallback to cover tool_name and tool_calls.
  • Fix: delete-trigger regression. The original PR left the four delete paths passing old.content to FTS5's delete-command. With inline mode, FTS5 requires the content to match what was actually stored (the concatenation), so every DELETE FROM messages raised sqlite3.OperationalError: SQL logic error. Replaced with plain DELETE FROM messages_fts WHERE rowid = old.id on all four paths (regular + trigram, delete + update-delete).
  • Fix: add v11 migration. Existing DBs have the old external-content FTS tables and triggers. Because CREATE VIRTUAL TABLE IF NOT EXISTS and CREATE TRIGGER IF NOT EXISTS skip when the objects already exist, upgraders would have kept the broken behavior forever. Bumped SCHEMA_VERSION to 11 and added a migration that drops both FTS tables + all 6 old triggers, recreates them, and backfills from messages with the same concatenation expression.
  • 6 new regression tests + updates to 2 version-dependent assertions.

Validation

Before After
Search web_search on session with that tool_call 0 hits 1 hit
Search token inside tool_calls JSON args 0 hits 1 hit
Search tool_name column 0 hits 1 hit
DELETE FROM messages SQL logic error succeeds
Upgrade from v10 DB: old rows searchable on tool fields no yes (backfill)

scripts/run_tests.sh tests/test_hermes_state.py tests/tools/test_session_search.py tests/acp/test_session.py: 264/264 passing.

E2E script simulated a v10 DB with rows containing only tool-call tokens, opened via SessionDB (migration runs), confirmed the previously-invisible tokens are now found, new inserts index correctly, and DELETE no longer raises.

yes999zc and others added 3 commits April 28, 2026 01:24
The FTS5 virtual tables (messages_fts, messages_fts_trigram) previously
only indexed the content column via external content mode. Tool calls
and tool names stored in the tool_calls (JSON) and tool_name columns
were invisible to FTS5 search.

Root cause: FTS5 triggers only INSERTed new.content into the index.

Changes:
- Switch FTS5 tables from external content (content=messages) to inline
  mode so that trigger-inserted content is both indexed and stored
- Update all 6 FTS5 triggers to concatenate content, tool_name, and
  tool_calls when indexing new messages
- Extend the short-CJK LIKE fallback to also search tool_name and
  tool_calls columns

Closes: #16751
…-call indexing

Follow-up on top of the cherry-picked contributor commit for #16751:

1. Delete triggers: the original PR switched FTS5 from external to inline
   content mode and concatenated content || tool_name || tool_calls in
   the insert/update triggers, but left the delete triggers passing
   old.content to the FTS5 delete-command. FTS5 inline delete requires
   the content to match what was stored, so every DELETE on messages
   raised 'SQL logic error'. Replaced with plain DELETE FROM ... WHERE
   rowid = old.id on all four delete paths (normal + trigram, delete +
   update-delete).

2. v11 migration: existing DBs have the old external-content FTS tables
   and triggers. Because CREATE VIRTUAL TABLE IF NOT EXISTS / CREATE
   TRIGGER IF NOT EXISTS skip when the objects already exist, upgraders
   would have kept the broken behavior forever. Bumped SCHEMA_VERSION
   to 11 and added a migration that drops both FTS tables + all 6 old
   triggers, recreates them via FTS_SQL / FTS_TRIGRAM_SQL, and backfills
   from messages using the same concatenation expression.

3. Regression tests: 6 new tests cover INSERT / UPDATE / DELETE paths
   for tool_name + tool_calls indexing plus the full v10 -> v11 upgrade
   path on a hand-built legacy DB.
@teknium1 teknium1 merged commit efb7d27 into main Apr 28, 2026
11 of 12 checks passed
@teknium1 teknium1 deleted the hermes/hermes-728f5f3e branch April 28, 2026 08:33
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/agent Core agent loop, run_agent.py, prompt builder labels Apr 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent loop, run_agent.py, prompt builder P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

session_search does not index tool_calls or tool_name

3 participants