Repository navigation
feat: run the lich plugin in oh-my-pi, and resume its sessions - #258
Conversation
Four things, all oh-my-pi. **The plugin installs.** omp has no plugin CLI, so lich writes the released extension into omp's own `extensions/` directory, exactly as it writes opencode's module — the file being there is the install, and the marker line above it is the only record of the version, since omp keeps no plugin state to ask. Settings › lich plugin offers it beside the others. **The MCP server is registered.** omp takes no `--mcp-config` flag, and the only place it reads a server from is an `mcpServers` document beside the extensions, so the install merges a `lich` entry into it. Every other server and every key lich knows nothing about survive the round trip; a document lich cannot parse aborts the install rather than being replaced, before anything else is written. What it cannot preserve is the user's formatting — JSON has no comment to hide a marker in and no way to append, which is why Crush got a block in `crushrc` and omp gets a rewrite. **omp sessions resume.** `omp -r <id>` reopens a conversation, and omp files one JSONL per session, so `ResumeAvailable` has something to prove one still exists — which is exactly what opencode and Crush lack. The directory is resolved the way `omp config path` was measured to resolve it: `OMP_PROFILE` moves the whole thing and beats `PI_CODING_AGENT_DIR`. **The contract carries omp.** `docs/hooks/` gains its column in every mapping table and its case in the session-start fixtures — the payload was already accepted (`omp` has been in `providers.Registry` since it was added), but a contract that never named it left the plugin side guessing. Two gaps are the harness's own, and Settings says the first out loud: omp declares a tool-approval event that no real run was observed emitting, so a session waiting on permission shows a spinner rather than a bell; and `idle` dies with the in-process extension that would report it, as opencode's does.
|
Validated end to end against the real release ( 1. The install, run through this branch's own code path (
{
"mcpServers": {
"lich": { "args": ["mcp"], "command": "…/lich" },
"notes": { "command": "notes-server" }
},
"other": 1
}2. omp loads what lich wrote, and reports. Running omp against a stub listener on the coordinates lich injects — no The turn itself died on a deliberately invalid API key, and the reports still arrived — start and end of turn do not depend on the model call. 3. Resume, against the transcript that run actually wrote. One thing worth knowing for the manual check: Probes were disposable and are gone; nothing in the diff changed since the checks above. |
lich's half of oh-my-pi support. The plugin's half is omartelo/lich-plugin#18 — this needs a release carrying
omp/lich.jsbefore an install can succeed, since the install fetches that path at the latest tag.What
The plugin installs (
internal/agentplugin/omp.go). omp has no plugin CLI, so lich writes the released extension into omp's ownextensions/directory — the file being there is the install, and the marker line above it is the only record of the version, since omp keeps no plugin state to ask. Settings › lich plugin lists it beside the others; no UI change was needed, the row comes fromStatus().The MCP server is registered. omp takes no
--mcp-configflag, and the only place it reads a server from is anmcpServersdocument beside the extensions, so the install merges alichentry intomcp.json. Every other server and every key lich knows nothing about survive the round trip. A document lich cannot parse aborts the install before anything is written, rather than being replaced — overwriting one lich failed to understand would delete servers it cannot see.omp sessions resume.
omp -r <id>reopens a conversation, and omp files one JSONL per session — soResumeAvailablehas something to prove one still exists, which is exactly what opencode and Crush lack (both keep conversations in SQLite). Cards that ran omp now get the same "continue where it left off" prompt Claude Code and Codex cards get.The contract carries omp.
docs/hooks/gains its column in every mapping table and its case in the session-start fixtures.On the "blocker" the plugin side reported
The plugin PR reports that
provider: "omp"would be rejected with a 400 until omp is registered. It would not: the endpoint validates againstproviders.Known(internal/terminal/transport.go), andomphas been inproviders.Registrysince it was added. What was missing was only a fixture case naming it —docs/hooks/fixtures/session-start.jsonlis a sample of cases, not the provider list (claudehas no case of its own either). The case added here is now exercised by the real parser inTestHookFixturesMatchParsers, which is the proof.Measured, not guessed
Everything provider-specific was read off the binary on this machine (omp v17.3.0):
-r, --resume=<value>— resume by id.omp config path→~/.omp/agent; withOMP_PROFILE=work→~/.omp/profiles/work/agent; withPI_CODING_AGENT_DIR=/tmp/x→/tmp/x; with both, the profile wins. That precedence is pinned by a test, because getting it backwards means the install lands where omp is not reading and every restored card silently starts fresh.Known gaps, both the harness's own
waiting. omp declarestool_approval_requestedbut no real run was observed emitting it, and a report wired to an event name that never fires is one that silently never arrives. So a session waiting on permission shows a spinner rather than a bell — Settings says so (OMP_APPROVAL_HINT), following the precedent of the Crush hint, because a missing bell reads as a broken install.idle, for opencode's reason: the extension runs in-process, so what would report the CLI leaving dies with it.Test plan
gofmt -l .clean,go vet ./...cleango test ./internal/...green (1344),-raceonagentpluginandterminalgo build+go vetclean on eachbiome check,tsc --noEmit,vitest run(875) andvite buildgreenmcp.jsonkeeps its own servers and its unknown keys; an unparseable one is refused with nothing written; a 404 release leaves neither file behind;ompAgentDirprecedence;resumeArgsandResumeAvailablefor omp, including that omp never matches a Codex rollout