Skip to content

fix(group-translate,voice-transcription): honor per-session config via signature-cached rebuild - #39

Merged
rmyndharis merged 1 commit into
mainfrom
fix/per-session-config-followup
Jul 18, 2026
Merged

fix(group-translate,voice-transcription): honor per-session config via signature-cached rebuild#39
rmyndharis merged 1 commit into
mainfrom
fix/per-session-config-followup

Conversation

@rmyndharis

Copy link
Copy Markdown
Owner

Summary

Follow-up to #38 for the two remaining stateful-coordinator plugins (group-translate, voice-transcription) that had the same per-session config-caching bug, plus a documentation note for gsheets-logger.

Problem

PR #38 fixed after-hours, chat-flow, and faq-bot — three plugins whose hook read a config snapshot cached at onEnable, ignoring per-session overrides (the host resolves ctx.config per-session inside a hook but returns the base * config at lifecycle time).

Two more plugins have the same bug but couldn't use the same simple fix: they cache a stateful coordinator (not just config values) built from the client that holds a circuit breaker. A naive per-event rebuild would reset the breaker on every message, defeating its purpose (a down backend would be hammered on every incoming message instead of being skipped after the threshold).

A third plugin (gsheets-logger) has the same caching pattern but is not fixable without an architecture change: it holds a single buffer mixing rows from every session, so per-session spreadsheet routing can't work without splitting the buffer by session.

Changes

group-translate — config-signature caching

  • Recompute a configSignature (JSON of the coordinator-affecting fields: libretranslateUrl, apiKey, timeoutMs, commandPrefix, minLength, maxLength, denyReply) per event.
  • Rebuild the coordinator only when the signature changes. An unchanged config reuses the existing coordinator, preserving the LibreTranslate client's circuit breaker across messages.
  • A per-session override that changes any of those fields triggers a rebuild on the next hook fire.

voice-transcription — config-signature caching + permission fix

  • Same pattern: configSignature over sttBaseUrl, apiKey, model, language, timeoutMs, delivery config, chatDelivery, enabledMessageTypes, maxSizeBytes, maxPerHour, provider. Rebuild only on signature change.
  • Bundled: declared messages:send in the manifest (v1.0.1 → v1.0.2). The chatDelivery feature calls ctx.messages.sendText/reply, both gated by messages:send, but the manifest only declared net:fetch. Enabling chatDelivery: 'self'/'reply' threw PluginCapabilityError on every send (default 'off' masked it).

gsheets-logger — documentation

  • README Compatibility section now documents that per-session spreadsheet routing is not supported (single buffer + single Sheets client built from base config). Rows from every session land in one configured sheet. Workaround: one instance per session.

Tests

  • group-translate/index.test.ts (new): coordinator reused for unchanged config (breaker preserved), rebuilt for changed config (override honored).
  • voice-transcription/index.test.ts: same two-sided regression test.

Verification

  • npm run typecheck — clean
  • npm run catalog:check — up to date
  • npm test401/401 pass (was 399; +2 regression tests)

…a signature-cached rebuild

Same class of bug as PR #38 but for stateful-coordinator plugins: the hook
read a coordinator cached at onEnable, ignoring per-session overrides. Fix
by recomputing a config signature per event and rebuilding only when it
changes — preserving the client circuit breaker across messages for an
unchanged backend.

- group-translate: configSignature over libretranslateUrl/apiKey/timeout/
  prefix/minLength/maxLength/denyReply; rebuild only on signature change
- voice-transcription: configSignature over sttBaseUrl/apiKey/model/language/
  timeout/delivery/chatDelivery/enabledTypes/maxSize/maxPerHour/provider;
  rebuild only on signature change. Bundled with the messages:send permission
  fix (chatDelivery was throwing PluginCapabilityError at runtime)
- gsheets-logger: README documents per-session spreadsheet routing is not
  supported (single-buffer single-sink design; not fixable without refactor)
- Regression tests per coordinator plugin: coordinator reused for unchanged
  config (breaker preserved), rebuilt for changed config (override honored)

typecheck clean; 401/401 tests pass.
@rmyndharis
rmyndharis merged commit fecbd45 into main Jul 18, 2026
1 check passed
@rmyndharis
rmyndharis deleted the fix/per-session-config-followup branch July 18, 2026 12:49
rmyndharis added a commit that referenced this pull request Jul 18, 2026
…nslate 1.0.6, voice-transcription 1.0.2

Cut PATCH releases for the five plugins with per-session config-honor fixes:

- after-hours 0.1.3 — per-event config re-parse (PR #38)
- faq-bot 0.1.7 — per-event config re-parse (PR #38)
- chat-flow 1.0.6 — per-event config re-parse (PR #38)
- group-translate 1.0.6 — config-signature cached rebuild (PR #39)
- voice-transcription 1.0.2 — messages:send permission + config-signature
  cached rebuild (PR #39)
rmyndharis added a commit that referenced this pull request Jul 18, 2026
…spec (#40)

Make per-session config support explicit and discoverable at three layers:

1. PLUGIN-STANDARD.md (spec) — expand the Per-session config section with
   the author requirement (re-read ctx.config inside the hook, not a
   cached snapshot), the two correct patterns (per-event re-parse for
   plain config; config-signature caching for stateful coordinators), an
   explicit anti-pattern callout (cache-at-enable breaks overrides, the
   source of PRs #38/#39), and a documentation requirement for READMEs.

2. Root README — add a 'Per-session config support' matrix table after
   the plugin catalog so operators can see at a glance which plugins
   honor per-session overrides (✅/⚠️/❌) and the caveat for each.

3. Each plugin README — add a '### Per-session config' subsection under
   Compatibility with the support tier (full / caveat / not supported),
   the fields that may be overridden, and any workaround (e.g. one
   instance per session for multi-backend isolation or single-sink
   designs). gsheets-logger's existing note is aligned to the same
   heading format.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant