Skip to content

Releases

v0.2.0 — search works on a stock profile

Choose a tag to compare

@YaoleWu YaoleWu released this 14 Aug 13:22

The bug

agent_session_search returned {"error": "session search is disabled…"} for every query on every default install, and always had.

It called sq.searchSessions() unconditionally. That method is real — it lives on @deepseek-ai/dsh-session-query-sqlite, the concrete sessionQuery backend in the stock dsh-base bundle. But dsh-base wires it path: ':memory:', openAt: 'never', and the engine throws SESSION_QUERY_SEARCH_DISABLED for exactly that setting. Content search is opt-in.

The call was inside a try/catch that returned the error as data, so nothing ever threw. The tool looked healthy and simply never found anything.

The fix

Two engines, picked at call time:

  • engine: "index" — the FTS5 index, when the deployment enables it.
  • engine: "scan" — a bounded newest-first scan over listSessions() + filterEvents(), primitives every sessionQuery backend has.

A failure that is not an unavailable index is still reported as an error, rather than reinterpreted as "no index" and answered with a slower scan of the same broken store.

Measured against a real 24-session corpus — a term matching nothing:

warm index scan
17 ms 3,042 ms

The index is worth having. It just cannot be the only path. To enable it, see Search on a stock profile.

Why the tests missed it

The unit fixture defined its own searchSessions stub. It faithfully verified that the plugin called a method the shipped service would refuse. A stub you write yourself will confirm your own misconception.

New tests/boot.test.mjs boots a real cordis Context, loads the harness's own session services, loads the package the way a profile does, and executes through the real tool registry. It also checks every sq.<method>() call site against the shipped service — unguarded calls must exist, guarded ones may be absent, and a guarded method must still be real on some shipped backend, so the fast path can't quietly become dead code. Verified to go red on the original bug.

Also

  • maxScan parameter and config key bound the fallback scan; results carry engine / scanned / truncated.
  • Snippets come from the matched event text via a literal, injection-safe highlighter mirroring the harness's own compileSessionTextFilter.
  • READMEs drop three claims that were not true: "indexed search, not a linear scan", "ranked by relevance", and an unfair characterisation of dsh-session-search — which searches Codex/Claude/PI/OpenCode sessions too, and is the better choice if you work across several agent CLIs.

27 unit + 21 boot assertions pass. Verified from a clean github: install of this tag.