Advanced
Rienda is extended in JavaScript, without touching its source and without compiling anything. Two kinds of extension exist:
- A tool is a capability the model can invoke during a conversation, such as reading a project file or calling an internal API.
- A hook is your code running at a fixed point of a run, so you can inspect it, gate it, or change what happens.
Start with Tools and continue with
Hooks. Both pages share the same runtime and the same
ctx object, so everything you learn on the first applies to the second.
Nothing extra to install
The JavaScript engine is embedded in the binary. Rienda runs your scripts with
goja, a pure Go implementation of JavaScript,
so there is no Node.js, no npm, and no dependency to install: write an index.js
file, start a session, and it is there.
That also means the language you write is not the one your editor may assume. The engine implements ECMAScript 5.1 in full, plus some features of ECMAScript 6: the newer revision is still work in progress upstream, so treat ES5.1 as the language you can always rely on. In practice:
- Everything of ES5 works:
var, functions, prototypes, closures,Objectutilities,JSON, regular expressions,try/catch, and strict mode. - A good part of ES6 works:
letandconst, arrow functions, classes withextends, template literals, destructuring, default and rest parameters, the spread operator,for...of,Map,Set,Symbol,Promise, generators, getters and setters, and the additions to the standard library such asObject.entries,Object.assign,Array.prototype.includesandString.prototype.padStart. - Not everything does. There is no module loader, so
importandexportdo not exist and a script assignsmodule.exportsinstead. Async iteration (for await...of) and async generators are unsupported, and the engine does not provide the host globals a browser or Node.js would, such assetTimeout,fetch,URL,Buffer, orconsole: thectxobject is what replaces them.
When in doubt, write ES5-compatible code, which always runs. The example pages use nothing beyond what the engine supports.
How the runtime behaves
Four rules explain almost everything about writing an extension:
- One call, one fresh runtime. Every invocation of a tool or a hook starts with a clean engine, so nothing is remembered between calls. To keep something, write it to a file.
- No event loop. The runtime is synchronous:
setTimeout,setInterval,process, andrequiredo not exist, and nothing waits for a callback that would fire later. APromiseresolves only after your function has already returned, so a result you need must be produced by the code you return from directly. - No timeout. A tool or a hook runs until it returns or the run is interrupted, so you own the timeouts of anything slow you call.
ctxis the surface. Everything Rienda offers a script, from reading a file to asking the user a question, is a member of thectxobject. The Tools page documents it completely, and hooks receive the same one.