Skip to content

Bug: plugin subscribes to 'chat.message' which opencode never publishes — counter never increments, plugin never mines #4

@jphein

Description

@jphein

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:

  1. stateManager.counts stays at 0 for every session.
  2. On session.idle, the event: handler checks stateManager.hasPendingMessages(sessionID), which returns false (count === 0).
  3. The mining branch is skipped.
  4. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions