{"id":28629185,"url":"https://github.com/source-academy/conductor","last_synced_at":"2026-02-18T18:01:08.733Z","repository":{"id":248346128,"uuid":"828448807","full_name":"source-academy/conductor","owner":"source-academy","description":null,"archived":false,"fork":false,"pushed_at":"2026-01-22T17:35:10.000Z","size":344,"stargazers_count":0,"open_issues_count":1,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-23T10:34:02.596Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/source-academy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-07-14T07:20:43.000Z","updated_at":"2026-01-22T17:35:32.000Z","dependencies_parsed_at":"2025-01-16T09:35:30.796Z","dependency_job_id":"78628f7e-953b-4d09-8b4e-256325d6a185","html_url":"https://github.com/source-academy/conductor","commit_stats":null,"previous_names":["tsammeow/sa-conductor","source-academy/conductor"],"tags_count":23,"template":false,"template_full_name":null,"purl":"pkg:github/source-academy/conductor","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/source-academy%2Fconductor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/source-academy%2Fconductor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/source-academy%2Fconductor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/source-academy%2Fconductor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/source-academy","download_url":"https://codeload.github.com/source-academy/conductor/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/source-academy%2Fconductor/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29588776,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-18T16:55:40.614Z","status":"ssl_error","status_checked_at":"2026-02-18T16:55:37.558Z","response_time":162,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-12T11:41:18.757Z","updated_at":"2026-02-18T18:01:08.727Z","avatar_url":"https://github.com/source-academy.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# conductor\n\nSource Academy standard communication interface for languages\n\n## Terminology\n\n- Host: An environment from which Runners may be created, e.g. browser, CLI.\n- Runner: An environment where user code is run.\n- Evaluator: A program that processes user code and produces the result(s).\n- Channel: A named bidirectional data stream between a Host and a Runner.\n- Chunk: A piece of user code that is not associated with any file.\n  This is usually strings from REPL, but contents of files can also be treated as chunks if there is no distinction to be made.\n- Plugin: A program that provides additional functionality, loaded on demand;\n  it may receive communications and communicate on declared Channels.\n\n## Implementing a new language\n\nTo get started, use the `conductor-runner-example` template. It contains a basic evaluator that calls Javascript's `eval` on the provided chunks.\n\n### The IEvaluator interface\n\nTo implement a new language using Conductor, implement the `conductor/runner/types/IEvaluator` interface.\nThis allows Conductor to interact with the language's implementation in a standard manner.\n\nThe `conductor/runner/BasicEvaluator` abstract class provides a basic implementation of this interface;\nto use, implement `evaluateChunk` and override `evaluateFile` if needed.\n\n### The entry point\n\nAn entry point should be created; this is the file initially executed to start a Runner.\nIt should construct an instance of `Conduit`, and register the `RunnerPlugin` with an argument of the evaluator.\n`conductor/runner/util/initialise` can help with this (do `initialise(MyEvaluator)`).\n\nYour implementation should be bundled using this file as the bundler's entry point.\n\n### Language data\n\nThis is used by the host to locate your runner and execute it.\nIt should contain things like the path to your entry point, editor information, and other information about your language.\nConsult [`language-directory` repository](https://github.com/source-academy/language-directory) for more information.\n\n## Module interface\n\n### Data types\n\nSeveral standard data types are available for module-language interfacing.\nSome are passed directly as JS values, others as identifiers. See `conductor/types/DataType`.\nNote that all identifiers across data types must be unique - in other words, a raw identifier must be able to be mapped back to the correct data.\n\n| Data type    | Passed as  | Notes                                                         |\n| ------------ | ---------- | ------------------------------------------------------------- |\n| void         | none\\*     | The return type for functions with no return value            |\n| boolean      | JS value   |                                                               |\n| number       | JS value   | Per JS limitations, this is IEEE754 binary64 (`double` in C)  |\n| const string | JS value   | Strings are immutable                                         |\n| empty list   | none\\*     | The empty-list value                                          |\n| pair         | Identifier |                                                               |\n| array        | Identifier | Arrays are singly-typed                                       |\n| closure      | Identifier | Closures have fixed arity                                     |\n| opaque       | Identifier | For values that can manipulated only by modules (e.g. a Rune) |\n| list         | see notes  | Either a Pair (passed by identifier) or empty list (null\\*)   |\n\n\\* as a convention, `undefined` is passed as the JS value for void type, and `null` is passed as the JS value for empty list type,\nthough it is always better to check the data type to be retrieved using the `*_type` functions than to test for equality using the JS values.\nCurrently, an equality comparison with null is required to distinguish between a `Pair` and the empty list when accepting a parameter of the type List,\nthough it is hoped that an alternative can be found soon.\n\nNote that language implementations **are expected to verify that the types of arguments to external closures are correct**,\nas it is not possible for the data type to be retrieved from a raw Identifier.\n\n### Communication interface\n\nIn order to be language and evaluator-agnostic, modules will make no assumptions about the memory model of evaluators.\nThus, evaluators are responsible for providing functions to allow modules to read, manipulate, and create data.\n\nEach of the data types passed as identifier have functions to create an instance of that data type,\nas well as read and write data to it (or call it, in the case of closures). See `conductor/types/IDataHandler`.\n\n### Standard library\n\nA standard library of functions must be made available to modules. See `conductor/stdlib` for sample implementations.\n\n## Plugins\n\nPlugins provide additional functionality not provided by the base Conductor framework.\n\nA Plugin is a class that implements `IPlugin` and contains the static field `channelAttach`: an array that specifies\nthe name(s) of the `Channel`(s) this plugin will be communicating on.\n\nUpon registration of the Plugin with the Conduit, the class' constructor will be called with the following arguments:\n- the instance of the `Conduit` to attach to\n- an array of `Channel`s, corresponding to the entries in `channelAttach`, and\n- any additional arguments passed to the `registerPlugin` method \n\nMost Plugins will not require the first argument, the `Conduit` instance. This is provided for the ability to\nload other Plugins as needed, as well as to communicate between Plugins.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsource-academy%2Fconductor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsource-academy%2Fconductor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsource-academy%2Fconductor/lists"}