feat(plugins): Tier-2 plugin capability layer (scoped ctx.messages/ctx.engine)#294
Merged
Conversation
- Assert moduleRef.get is called in the reply delegation test. - Add test proving manifest.sessions absent defaults to wildcard allow-all. - Reword ModuleRef constructor comment to clarify it avoids (not causes) the PluginLoaderService → SessionService → EngineFactory cycle.
- Capture and assert `{ continue: true }` from the group-message guard so a
future regression returning `{ continue: false }` is caught immediately.
- Add test for the `source !== 'Engine'` guard: overrides `source` to `'API'`
via spread, asserts reply is not called and result is `{ continue: true }`.
…CapabilityError, no orphan row)
This was referenced Jun 17, 2026
rmyndharis
pushed a commit
that referenced
this pull request
Jun 18, 2026
Ports the translation feature onto the Tier-2 capability layer (#294): the framework-agnostic core/ (coordinator, command parser, reply formatter, ports) is reused unchanged, with ChatGateway/ConfigStore implemented over ctx.messages / ctx.engine / ctx.storage and per-group state in plugin KV storage. Registered disabled by default; enable via POST /plugins/translation/enable. Supersedes the core-module approach in #278 now that the plugin send-capability exists.
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
Adds a Tier-2 plugin capability layer so extension plugins can act safely — the foundation for moving bot-shaped features (auto-reply, translation) out of core. Replaces the stubbed
PluginContext.getServicewith curated, scoped capabilities.This is Tier-2 of the engine-decoupling / pluggable-architecture effort (#265). It unblocks #278 (auto-translation) to be ported from a core module into a real extension plugin. MCP (#256) and a Baileys engine belong to the Tier-1 boot-time tier (a follow-up).
What's included
HookManagerre-entrancy guard (AsyncLocalStorage) — a plugin that sends from inside a hook can't recurse into the same event (synchronous re-entry).ctx.messages—sendText/reply, routed throughMessageServiceso persistence and the normal send pipeline are preserved.ctx.engine— read-only scoped queries (getGroupInfo/getContacts/getContactById/checkNumberExists/getChats).sessionsscope — enforced at the facade before any service/engine resolution; default['*'].auto-replyreference extension plugin — first-party, registered disabled by default; enable viaPOST /plugins/auto-reply/enableto validate the layer live.Design notes
ModuleRef+ a runtimerequireof the class token to avoid a provider/module-load cycle (PluginLoaderService → SessionService → EngineFactory → PluginLoaderService). A static import ofMessageService/SessionServicecorruptsMessageService's constructor paramtype metadata at boot — this was caught by the e2e boot gate during development, hence the dedicated e2e check.ctx.messagesorctx.enginecall throwsPluginCapabilityError(no orphaned pending DB row), consistent across both surfaces.sendTextfires themessage:sendinghook + anti-ban typing;replyis intentionally leaner (neither).Breaking change
PluginContext.getServiceis removed (it was a stub returningundefined; zero real consumers). Out-of-tree plugins relying on it must migrate toctx.messages/ctx.engine.Known limitation (documented)
message:sentecho loop is not guarded (a per-plugin send rate-limiter is deferred to the untrusted/sandbox tier).Tests