Description
opencode-plugin-mempalace v1.2.1 registers a hook on 'chat.message' (see dist/index.js line ~123):
'chat.message': async ({ sessionID }) => {
if (stateManager.incrementAndCheck(sessionID)) {
// ... mine
}
},
But opencode never publishes a chat.message event. The actual published event types are documented at https://opencode.ai/docs/plugins and confirmed by inspecting ~/.local/share/opencode/log/*.log (each bus publish is logged as service=bus type=<name> publishing):
message.updated
message.part.updated
message.part.delta
message.removed
session.created / session.idle / session.updated / session.status / session.deleted / session.diff
file.watcher.updated
command.executed
permission.asked / permission.replied
tool.execute.before / tool.execute.after
- etc.
chat.message is nowhere in the canonical event taxonomy or in any opencode log.
Impact
The stateManager.incrementAndCheck() call inside the 'chat.message' hook never executes. Therefore:
stateManager.counts stays at 0 for every session.
- On
session.idle, the event: handler checks stateManager.hasPendingMessages(sessionID), which returns false (count === 0).
- The mining branch is skipped.
- The plugin never writes a drawer for the in-progress session.
The plugin appears to work end-to-end — it loads, initializes mempalace, the MCP server connects, the LLM responds — but zero conversation drawers land because the increment path is dead.
Reproduction
# Baseline drawer count
mempalace status | head -3
# Open opencode in any directory
opencode
# Have a normal conversation (a few turns)
# Exit cleanly (so SIGINT/SIGTERM flushDirtySessions doesn't fire — though
# it can't help either because the counter is still 0)
# Recount
mempalace status | head -3
# → identical to baseline
Also confirm by grepping the opencode log: grep "chat.message" ~/.local/share/opencode/log/*.log returns no publishing lines, only the plugin's subscribing line.
Suggested Fix
Move the increment into the event: catch-all handler and listen for message.updated:
event: async ({ event }) => {
if (event.type === 'message.updated') {
const sessionID = event.properties?.sessionID
|| event.properties?.info?.sessionID
|| event.properties?.info?.id;
if (sessionID) stateManager.incrementAndCheck(sessionID);
}
// ... existing session.idle handling
},
event.properties.sessionID is populated at the top level for message.updated events (verified by writing a debug plugin that dumps Object.keys(event.properties) — observed keys are ['sessionID', 'info'] with info being the Message object that also carries sessionID).
The existing 15-message threshold absorbs the per-token streaming chatter (one increment per assistant message update, not per delta).
The dead chat.message hook below can either be removed or left in place — it's harmless.
Patch
We're carrying this as a downstream patch in the mempalace fork at https://github.com/techempower-org/memorypalace/blob/main/examples/opencode/option-k-plugin-message-updated.patch — happy to upstream as a PR if useful.
Environment
- opencode-plugin-mempalace 1.2.1
- opencode-ai 1.15.7 (Linux x64)
- mempalace 3.3.5 (running daemon-routed via palace-daemon)
- Node 22.x
Related
Description
opencode-plugin-mempalacev1.2.1 registers a hook on'chat.message'(seedist/index.jsline ~123):But opencode never publishes a
chat.messageevent. The actual published event types are documented at https://opencode.ai/docs/plugins and confirmed by inspecting~/.local/share/opencode/log/*.log(each bus publish is logged asservice=bus type=<name> publishing):message.updatedmessage.part.updatedmessage.part.deltamessage.removedsession.created/session.idle/session.updated/session.status/session.deleted/session.difffile.watcher.updatedcommand.executedpermission.asked/permission.repliedtool.execute.before/tool.execute.afterchat.messageis nowhere in the canonical event taxonomy or in any opencode log.Impact
The
stateManager.incrementAndCheck()call inside the'chat.message'hook never executes. Therefore:stateManager.countsstays at 0 for every session.session.idle, theevent:handler checksstateManager.hasPendingMessages(sessionID), which returns false (count === 0).The plugin appears to work end-to-end — it loads, initializes mempalace, the MCP server connects, the LLM responds — but zero conversation drawers land because the increment path is dead.
Reproduction
Also confirm by grepping the opencode log:
grep "chat.message" ~/.local/share/opencode/log/*.logreturns nopublishinglines, only the plugin'ssubscribingline.Suggested Fix
Move the increment into the
event:catch-all handler and listen formessage.updated:event.properties.sessionIDis populated at the top level formessage.updatedevents (verified by writing a debug plugin that dumpsObject.keys(event.properties)— observed keys are['sessionID', 'info']withinfobeing the Message object that also carriessessionID).The existing 15-message threshold absorbs the per-token streaming chatter (one increment per assistant message update, not per delta).
The dead
chat.messagehook below can either be removed or left in place — it's harmless.Patch
We're carrying this as a downstream patch in the mempalace fork at https://github.com/techempower-org/memorypalace/blob/main/examples/opencode/option-k-plugin-message-updated.patch — happy to upstream as a PR if useful.
Environment
Related