Skip to content

What is a Plugin?

Aarav Malani edited this page Jun 6, 2026 · 1 revision

For more information on the Conductor framework, see the Conductor documentation.

In abstract terms, a plugin is a "piece of software" that adds specific feature or functionality to the Conductor framework.

Terminology

(Excerpted from the Conductor documentation)

  • Host: An environment from which Runners may be created, e.g. browser, CLI.
  • Runner: An environment where user code is run.
  • Evaluator: A program that processes user code and produces the result(s).
  • Channel: A named bidirectional data stream between a Host and a Runner.
  • Plugin: A program that provides additional functionality, loaded on demand; it may receive communications and communicate on declared Channels.

As mentioned above, the host and runner are transceivers of data which communicate over channels. A host or runner can load and register a plugin. The plugins can then execute code within the environment (host/runner) it was registered on.

Plugins can also attach themselves to channels, so two plugins can communicate over a common channel. A common idiom for plugins is a runner plugin which performs a language-specific execution of data and a host plugin which displays the result.

sequenceDiagram
   participant Host
   box Channel
       participant Host Plugin
       participant Runner Plugin
   end
   participant Runner
   Runner->>Runner Plugin: Registers Plugin
   Runner Plugin->>Host: Request Host Plugin Load
   Host-->>Host Plugin: Registers Plugin
   Note over Host Plugin,Runner Plugin: On Execution Start
   Host Plugin->>Runner Plugin: Requests Execution
   Runner Plugin->>Runner: Requests Execution
   Runner-->>Runner Plugin: Returns Result
   Runner Plugin-->>Host Plugin: Serializes and Sends Result
   Host Plugin->>Host: Displays Result
Loading

Fig. 1: Example sequence diagram of a runner-host plugin pair performing an arbitrary execution

Code Format

In practice, a plugin is a class which implements the IPlugin interface. Each plugin class has a unique ID (e.g., "__runner_cse"). The plugins can attach themselves to channels using the static channelAttach field at initialisation.

An example class (adapted from src/runner/test/src/index.ts is)

import { CHANNEL_ID, RUNNER_ID, type TestMessage } from "@sourceacademy/common-test";
import { IPlugin, IChannel, IConduit } from "@sourceacademy/conductor/conduit";
export class TestPlugin implements IPlugin {
  readonly id: string = RUNNER_ID;
  static readonly channelAttach = [CHANNEL_ID];
  private readonly __testChannel: IChannel<TestMessage>;
  constructor(
    _conduit: IConduit,
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    [testChannel]: IChannel<any>[],
  ) {
    this.__testChannel = testChannel;
    this.__testChannel.subscribe(message => {
      console.log(message);
    });
    this.__testChannel.send("ping");
  }
}

As you can see, this plugin is designed to be registered by a runner. It requests a channel with id CHANNEL_ID, and receives it from the constructor. It then sends a "ping" message, and waits for a response

Clone this wiki locally