Skip to content

Add structured plugin command events - #5043

Merged
gabek merged 1 commit into
developfrom
gek/plugin-command-events
Jul 13, 2026
Merged

gabek merged 1 commit into
developfrom
gek/plugin-command-events

Conversation

@gabek

@gabek gabek commented Jul 12, 2026

Copy link
Copy Markdown
Member

Plugin command tables now use the accepted chat message path for matching, arguments, moderator gates, and cooldowns.

  • Match every registered command declaration, so duplicate commands in different plugins all run.
  • Keep unknown, moderator-denied, and cooldown-limited invocations silent.
  • Deliver a targeted, reserved chat.command event without adding a plugin permission.
  • Keep command messages available to ordinary chat handlers, including !help and !commands.
  • Preserve the built-in aggregated help response while allowing plugins to add their own responses.
  • Prune expired per-user cooldown entries and reset cooldown state when a plugin reloads.
  • Update the wire contract snapshot and rebuild both embedded language engines.

A matching plugin receives this internal payload:

{
  "message": {"id": "m1", "body": "!up one two", "user": {"id": "u1"}},
  "command": "uptime",
  "invokedAs": "up",
  "args": ["one", "two"],
  "argString": "one two"
}

The paired SDK change is owncast/plugin-sdk#3.

Testing included the plugin and pluginhost Go suites, direct matching and cooldown coverage, the host-runtime tests, and the complete JavaScript and Python mod-commands scenarios.

Required checklist

Do not remove this section. These checkboxes are required and validated.

  • I have personally tested these changes and verified they work as intended.
  • I understand the code I'm submitting and can explain how it works if asked.
  • I included a screenshot, logs, example payload to demonstrate the change, or it really doesn't need it.
  • This is a frontend change and it supports translations, or it's not a frontend change.
  • The code has been run through the proper linters and/or formatters for the language.
  • There is an issue discussing this change and it's assigned to me.

Copilot AI review requested due to automatic review settings July 12, 2026 20:50

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a structured, host-routed plugin command dispatch path so plugin-declared chat commands are matched by the host, gated (mod-only), cooldown-managed per user, and delivered as a reserved chat.command event while preserving existing chat message delivery and the aggregated built-in !help response.

Changes:

  • Introduces host-side command matching/dispatch (chat.command) with alias support, moderator gating, and per-user cooldown tracking.
  • Extends the plugin wire types to include CommandInfo, CommandEvent, and clientId on HostChatMessage, updating the contract snapshot and related tests.
  • Updates pluginhost event flow so accepted chat messages still notify ordinary chat handlers and additionally trigger command dispatch.

Reviewed changes

Copilot reviewed 13 out of 15 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
services/plugins/shared_engine_test.go Extends shared-engine tests to verify command registration and targeted command dispatch behavior.
services/plugins/plugin-contract.json Updates the wire contract snapshot with new command/event types and clientId on chat messages.
services/plugins/manifest.go Removes local CommandInfo and updates manifest commentary to reflect host-side command routing.
services/plugins/manager.go Adds per-plugin cooldown state fields and clarifies command registration semantics during load.
services/plugins/hostfns.go Defines CommandInfo, CommandEvent, and adds clientId to HostChatMessage for the plugin wire layer.
services/plugins/help.go Centralizes default command prefix and !help/!commands alias handling.
services/plugins/events.go Reserves and documents the new chat.command event type.
services/plugins/dispatcher_test.go Ensures reserved event type coverage includes chat.command.
services/plugins/contract_test.go Updates contract test messaging and adds an UPDATE_CONTRACT regeneration path.
services/plugins/commands.go Implements command matching, gating, cooldown pruning, and targeted chat.command delivery.
services/plugins/commands_test.go Adds unit tests for matching, duplicate dispatch, moderator gating, and cooldown behavior.
pluginhost/pluginhost.go Updates help responder comment to reflect continued chat delivery plus command dispatch.
pluginhost/pluginevents.go Runs command dispatch after notifying chat.message.received subscribers for accepted messages.

Comment thread services/plugins/commands.go
@cypress

cypress Bot commented Jul 12, 2026 •

Copy link
Copy Markdown

Owncast Web Frontend    Run #33264

Run Properties:  status check passed Passed #33264  •  git commit 03c125ba46: feat(plugins): route declared chat commands
Project Owncast Web Frontend
Branch Review gek/plugin-command-events
Run status status check passed Passed #33264
Run duration 05m 45s
Commit git commit 03c125ba46: feat(plugins): route declared chat commands
Committer Gabe Kangas
View all properties for this run ↗︎

Test results
Tests that failed  Failures 0
Tests that were flaky  Flaky 0
Tests that did not run due to a developer annotating a test with .skip  Pending 0
Tests that did not run due to a failure in a mocha hook  Skipped 0
Tests that passed  Passing 131
View all changes introduced in this branch ↗︎

@gabek
gabek force-pushed the gek/plugin-command-events branch from 3bf37e2 to 93c189d Compare July 12, 2026 21:03
@gabek

gabek commented Jul 12, 2026

Copy link
Copy Markdown
Member Author

The Windows Go job has failed twice in the existing TestManager_Install_ReloadsRunningInstanceOnUpdate test with the same .ocpkg rename file-lock error. Ubuntu passes. This change does not touch the install, reload, package-close, rename, or remove paths used by that test, so I am treating it as the existing Windows file-lock flake rather than changing unrelated lifecycle code here.

@gabek
gabek force-pushed the gek/plugin-command-events branch from 93c189d to 03c125b Compare July 12, 2026 21:15
@gabek
gabek merged commit 230b9b9 into develop Jul 13, 2026
21 checks passed
@gabek
gabek deleted the gek/plugin-command-events branch July 13, 2026 01:23
@gabek gabek mentioned this pull request Jul 13, 2026
5 of 6 tasks
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.

2 participants