Repository navigation
Conversation
added 3 commits
October 8, 2026 11:22
Octop-harness plugins can now contribute channel kinds (kind: channel) that become first-class channels in the gateway and dashboard. - infra/gateway/plugin_channels.py: apply_plugin_channels() replays plugin channel registrations into octop_gateway.register_channel_kind (idempotent, first-wins, per-plugin failure isolation); plugin_channel_kinds() summarizes them for the dashboard catalogue. - server.py: apply plugin channel kinds right after load_installed() so kinds exist before gateway boot rebuilds DB channels. - api/routers/channels.py: kind validation now accepts plugin kinds (case-normalized) in create/patch/probe bodies, tolerant of harness releases without all_channels(); new GET /channels/plugin-kinds endpoint exposing the plugin channel catalogue. Tests: 8 cases in tests/unit/test_plugin_channels.py (7 run on released harness; the fixture end-to-end test auto-skips until the updated harness is installed).
…logue Fetch GET /channels/plugin-kinds once per mount and register each returned kind into the channel catalogue at runtime (keys, labels, icons, colors, per-kind config schema). Builtin kinds stay compile-time constants; registration is idempotent and builtin kinds always win. Kinds registered without a schema fall back to the drawer's existing raw-JSON editing path, so any kind:channel plugin is configurable without further frontend work. Fetch failure keeps a builtin-only catalogue (older backends without the endpoint).
This branch has not been deployed
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
Completes the plugin-channel story on the host side:
kind: channelplugins installed in Octop now become real channels — creatable, probeable, persistable, rebuildable, and fully manageable from the dashboard. This is the enabling infrastructure for the upstream Roadmap's Plugin marketplace: any third-party channel plugin, once installed, behaves like a builtin channel with zero core code changes.What's included
1. Boot bridge —
src/octop/infra/gateway/plugin_channels.py(new)apply_plugin_channels(registry=...): replays everyChannelRegistrationfrom the harnessPluginRegistryintooctop_gateway.register_channel_kind(). Idempotent (first-wins per kind), per-plugin failure isolation (a broken plugin logs and is skipped, never blocks boot).plugin_channel_kinds(): summarizes registered plugin kinds for the API/dashboard catalogue.server.pyimmediately afterplugin_manager.load_installed(), beforegateway.boot()rebuilds DB channel rows — so plugin channels are ready to rebuild exactly like builtins. Also safe to re-run on plugin reload.2. API —
src/octop/api/routers/channels.pykindin create/patch/probe bodies was a closedChannelKindenum (Pydantic would 422 any plugin kind). It is now a validated string: builtin kinds still accepted (case-normalized), plus any kind registered by an installed channel plugin — read live from the harness registry. Defensive: with harness releases that predateall_channels(), validation falls back to builtin-only instead of crashing.GET /channels/plugin-kindsendpoint (auth:current_user): returns the plugin channel catalogue (kind/label/icon/intro_url/fields/plugin_id) for UI consumption.3. Dashboard —
src/pages/Agent/Channels/*ChannelsPanelfetches/channels/plugin-kindsonce per mount and registers each kind into the catalogue at runtime (registerPluginChannelKind()inconstants.ts): card keys, display labels, icons, accent colors, and per-kind config form schemas. Builtins remain compile-time constants; registration is idempotent and builtin kinds always win.Test plan
uv run --extra dev pytest tests/unit/test_plugin_channels.py→ 7 passed, 1 skipped. Stub-based coverage of the bridge (registration, idempotency, first-wins, no-builtin-shadowing, summary, API validator) runs everywhere; the real-fixture end-to-end test auto-skips until the updated harness (octop-harness#52) is installed.tests/unit/test_plugins.py+test_plugin_manager.py+test_bundled_plugins_layout.py→ 35 passed;tests/integration/test_channels_api.py+tests/unit/db/test_repo_channels.py→ 14 passed.tsc -bclean;vitest src/pages/Agent/Channels→ 16 passed (existing suite unchanged).Compatibility & rollout
all_channelsis absent). No behavior change for existing users.Example: a minimal channel plugin
Install → restart → an "Acme IM" card appears in the dashboard channel grid, with a real token input in the drawer.