Repository navigation
Releases
v0.2.0 — search works on a stock profile
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 overlistSessions()+filterEvents(), primitives everysessionQuerybackend 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
maxScanparameter and config key bound the fallback scan; results carryengine/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.