Total.js 5
TotalFusion is an extension of Total.js: the functions of a worker are registered as actions, so everything Total.js does with an action (validation, permissions, API routes, FlowStream, MCP) works with them. Nothing in the framework is modified.
// definitions/fusion.js
const fusion = REQUIRE('totalfusion');
exports.install = function() {
fusion.register({ python: { path: PATH.root('python'), workers: 2 } }).then(function(result) {
console.log('TotalFusion:', result.ids.join(', '));
});
};register is asynchronous (it reads the contracts with a short Python process) and resolves with { ids, errors, warnings }. require('totalfusion') works the same as REQUIRE('totalfusion').
Every function decorated with @action becomes a NEWACTION() named <module>/<function> (change it with prefix or @action(id=...)). Because they are normal actions they work with ACTION() and API routes (ROUTE('API /v1/ +count --> contract/count')). register also adds the modules with @startup to preload automatically.
- Validation first. Total.js validates
inputwith the contract before Python runs, so invalid data never reaches your function. Fields marked with*are required; an optional field with an invalid value is dropped by Total.js, not reported. - Query and params. Declare them in the contract like the input:
@action(input='a:Number', query='*page:Number', params='id:UID'). Python then receives an object with the sections that were declared, already validated and converted:{ 'input': {'a': 5}, 'query': {'page': 2}, 'params': {'id': '...'} }. Withoutqueryandparamsit receives the input alone, as before.ACTION('x', input).query({...}).params({...}), theAPIroutes and the MCP tools (arguments: { input, query, params }) all fill them. - Who may call.
permissions('admin,editor': any of them),user=True(only a logged in user),saandsugo toNEWACTION()as they are, so Total.js decides before Python is reached and answers401otherwise. An administrator (user.saoruser.su) always passes. Python does not see the user: if a function needs to know who calls, pass what it needs in the input. - MCP is opt-in. Only functions with
mcp=Trueare exposed to agents (CONF.$mcp = trueenables the endpoint). Everything else stays internal. - Errors. A Python
ValueErroris treated as the caller's mistake and its message reaches the client. Any other exception returnsThe action failed, and the real error goes toonerror(default:console.error), so paths, queries or secrets inside exception messages are not leaked. - Generators. A function that yields is a stream, not an action:
registerskips it with a warning. Call it withfusion.stream()orfusion.sse(). - Boot.
fusion.register({ warmup: true })loads the models before it resolves, andpreload: falseleaves the modules with@startupto load on their first call. - Schemas. Total.js splits the fields of a schema on commas even inside a
// comment, so'*text:String // Text, up to 2000 chars'declares a second field calledup to 2000 chars.registerreturns awarningslist for it: use parentheses or a new line. - MCP. Exposing an action as a tool uses the MCP router of Total.js 5 (
CONF.$mcp = true). The release 0.0.19 of thetotal5package in npm does not include it; the repository of Total.js 5 does (0.0.20-1 was tested). Actions and API routes work without it.
FlowStream#
TotalFusion has seven components for Flow: one for each runtime (Python, Rust, Go and WebAssembly) that calls a function with the data of each message, a Stream whose chunks are messages, Events that sends the events of the workers, and Stats. They use the same pool of workers as the rest of the application, and they were run in the designer of Flow 11.1. How to install and use them is in Flow.
Server-Sent Events#
A stream reaches the browser with fusion.sse($, stream). See Streaming.
Reload while you develop#
fusion.register({ ..., watch: DEBUG }) replaces the workers and reads the contracts again when the code changes. See Development.
An application to start from#
examples/totaljs-app is a complete Total.js 5 application with Python: an action, an API route, Server-Sent Events and reload on edit. It was run with a real npm install of total5.