Add OpenCode (anomalyco/opencode) as the sixth searchable backend#30
Open
tony wants to merge 7 commits into
Open
Add OpenCode (anomalyco/opencode) as the sixth searchable backend#30tony wants to merge 7 commits into
tony wants to merge 7 commits into
Conversation
why: Adding OpenCode (anomalyco/opencode, issue #29) as a searchable backend starts by teaching every agent-name surface that "opencode" exists. This commit is inert on its own — opencode is recognized but has no stores yet, so discovery and parsing are never reached — which isolates the literal change from the catalog/discovery/parser layers that follow. what: - Add "opencode" to the AgentName literal in stores.py, __init__.py, and mcp/_library.py, plus the AgentSelector literal and AGENT_CHOICES. - Add "opencode" to the five MCP model agent literals and the query registry's agent enum_values (and its docstring values line). - Mention OpenCode in the MCP server-instruction header and trigger scope. - Add "opencode" to the package description and keywords.
why: The catalogue is agentgrep's single source of truth for where agent data lives and what shape it takes. OpenCode gets one searchable store (its SQLite database) plus documentary descriptors for every other on-disk artifact, so the catalogue stays a complete inventory even for data agentgrep never searches. what: - Add _OPENCODE_OBSERVED_AT and the _OPENCODE_STORES tuple: opencode.db (PRIMARY_CHAT, searched, SQLite, adapter opencode.db_sqlite.v1) plus documentary rows for the legacy JSON layout, config, auth (PRIVATE credentials), snapshots, repos, logs, and tool output. - Splice _OPENCODE_STORES into CATALOG, bump catalog_version to 10, and advance captured_at to the OpenCode observation date. - Register opencode.db_sqlite.v1 in the MCP KNOWN_ADAPTERS tuple. - Add "opencode" to the test-side KNOWN_AGENTS so the catalogue invariants cover the new rows.
why: With OpenCode in the catalogue, discovery needs to resolve its XDG
data directory and enumerate the SQLite databases there. OpenCode keeps
its store at opencode.db (or opencode-<channel>.db) under
${XDG_DATA_HOME}/opencode, and OPENCODE_DB can relocate it.
what:
- Add discover_opencode_sources, resolving the data root via
resolve_env_root("XDG_DATA_HOME", ...) + the opencode segment and
discovering opencode*.db. When OPENCODE_DB points at an absolute file,
its parent directory becomes the search root (matching how OpenCode
replaces the default database location).
- Wire the "opencode" branch into discover_sources.
why: Discovered opencode.db files need an adapter to turn their relational rows into normalized search records. OpenCode keeps the prompt and reply text in part rows, so the parser joins each part up to its message (for role) and session (for title, working directory, and timestamp). what: - Add parse_opencode_db plus _opencode_json_object and _opencode_part_text helpers, reusing open_readonly_sqlite and sqlite_table_names. A single part -> message -> session join emits one record per text-bearing part: text/reasoning carry their text and subtask its prompt; kind is role-derived (user -> prompt, else history); the session title, model, and unix-ms timestamp are attached, with the working directory in metadata. Degrades gracefully when tables are missing or the database is unreadable. - Dispatch opencode.db_sqlite.v1 in iter_source_records and register it in ITER_SOURCE_RECORD_ADAPTERS.
why: The opencode backend needs the same test depth as the SQLite-based Grok backend — discovery across its layouts and the per-part parse behaviour — so regressions surface before release. what: - Add a helper that builds a minimal opencode.db (session/message/part) inline, following the Grok session_search test. - Cover discovery at the default ~/.local/share/opencode location, the XDG_DATA_HOME override (with a decoy), and the absolute OPENCODE_DB override, plus an end-to-end search asserting user->prompt and assistant->history with the model and working directory attached. - Add a NamedTuple + test_id parametrized parse matrix over part types: text/reasoning/subtask are searchable; tool, file, step markers, and empty text are skipped. Register "opencode" in the test-local AgentName.
why: Each backend gets a reference page documenting its layout and record schema, and the support matrix and agent lists must name OpenCode so readers can find it. what: - Add docs/backends/opencode.md: base path, env overrides, and the SQLite session/message/part schema with the searchable part types. - Add an OpenCode card and toctree entry to the backend index and an OpenCode section to the storage-catalogue dev page. - Name OpenCode in the README and docs landing agent lists. - Extend the backend-grid and coverage-grid doc tests to cover opencode.
why: Record the new OpenCode backend for the unreleased version so readers know agentgrep now searches anomalyco/opencode. what: - Add an "OpenCode backend (#29)" deliverable under What's new for the unreleased 0.1.0a8 section, describing the single SQLite store, the part-join read path, the env overrides, and the catalogued documentary stores.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
anomalyco/opencode, formerlysst/opencode) as an agentgrep backend, searchable from both the CLI and the MCP server.opencode.db) by joining its relationalsession → message → parttables — each text-bearing part becomes a record whosekindis role-derived (user → prompt, else history), with the session title, working directory, and the message model/timestamp attached. This makes OpenCode the structural sibling of the existing Grok/Claude/Cursor SQLite adapters, not the JSONL backends.${XDG_DATA_HOME:-~/.local/share}/opencode/opencode.db), honouring theOPENCODE_DBoverride (an absolute path is searched from its parent).auth.jsonis documented but never indexed.Implements #29.
Changes by area
Search core (
src/agentgrep/)store_catalog.py:_OPENCODE_STORES—opencode.db(primary chat, searched, SQLite) plus seven documentary rows; catalogue version bumped.__init__.py:discover_opencode_sources(XDG data root +OPENCODE_DBoverride) andparse_opencode_db, which joinspart → message → sessionand reusesopen_readonly_sqlite.stores.py/query/registry.py:opencodeadded to the agent-name literal and the queryagentenum.mcp/:opencodein the MCP agent literals and selectors,opencode.db_sqlite.v1registered inKNOWN_ADAPTERS, and OpenCode named in the server instructions.Docs
docs/backends/opencode.md: path layout, env overrides, and thesession/message/partschema.docs/backends/index.md,docs/dev/storage-catalog.md,README.md,docs/index.md: OpenCode added to the support matrix and agent lists.Tests
tests/test_agentgrep.py: discovery for the default,XDG_DATA_HOME, andOPENCODE_DBlayouts, an end-to-end search, and aNamedTuple+test_idparametrized parse matrix over part types, all driven by an inline-builtopencode.db.Design decisions
search_root, and ripgrep skips binary files — so a glob-discovered.db(which carries asearch_root) would be pruned before the parser runs. Discovering viafiles=("opencode.db",)gives the source nosearch_root, routing it straight todirect_source_matches, wheresource_kind == "sqlite"always parses. This mirrors how the Grok and Cursor SQLite stores are discovered.partrows and the role on themessage, so the parser joins part → message → session and deriveskindfrom the messagerole— consistent with every other backend.text,reasoning, andsubtaskparts carry searchable text; tool, file, snapshot, and step-marker parts are metadata and stay out of default search.session.directory: stored verbatim, so no hash/path decoding is needed; it is attached to each record's metadata.Verification
Search the live OpenCode store (the parser-backed
search, not rawgrep, is the surface for SQLite stores):$ uv run agentgrep search --agent opencode <term>Restrict to user prompts:
$ uv run agentgrep search --agent opencode --type prompts <term>Confirm no glob-based discovery remains for the SQLite store:
$ rg -n 'glob="opencode' src/agentgrep/store_catalog.pyTest plan
uv run ruff check ./uv run ruff format .— lint and format cleanuv run ty check— strict type checking passesuv run pytest --reruns 0— full suite green, including the new opencode testsjust build-docs— docs build clean (opencode backend page, support matrix, coverage grid)test_discover_opencode_sources_default_xdg_location/_honours_xdg_data_home/_honours_opencode_db_override— discovery across layoutstest_search_opencode_sessions— user→prompt, assistant→history with model and directorytest_parse_opencode_part— every part type maps correctly or is skippedagentgrep search --agent opencodereturns records from the liveopencode.dbCloses #29