Prepare the optional Complexity custom runtime
Keep COMPLEXITY_CUSTOM_RUNTIME_ENABLED=0 unless the selected host passes the containment checks. This is the default in the root Compose configuration.
The runtime adds custom React views to the existing displayOpenUI tool as version 4. Native versions 1–3 remain supported. Tool selection, chat permission, and group grants still apply.
Prepare the backend
The supported target is Linux x86_64 with glibc, Python 3.10 or newer, and libseccomp.so.2. The packaged policy accepts exactly libseccomp 2.5.4 or 2.5.5 with the matching policy hashes. A version number alone does not establish readiness.
From mailGen/msmicroservices-architexture/, prepare the selected source:
pnpm build
pnpm complexity:runtime:prepare
pnpm build copies the vendored assets into dist/lib/complexity/custom-runtime/assets/. It does not prepare Python. The shared backend build does not require the optional Python runtime.
pnpm complexity:runtime:prepare explicitly runs /usr/bin/python3. It creates dist/lib/complexity/custom-runtime/python/ from the packaged, hash-checked QuickJS wheel. Preparation uses no downloads or pip installation. A wheel or native-extension hash mismatch stops preparation.
Prepare inside the target host or container that will run ComplexityService. Keep the generated environment and assets readable by the unprivileged child. Do not substitute an arbitrary interpreter or wheel.
Enable only after containment checks
Keep the flag disabled until the selected host passes the packaged containment checks. Set COMPLEXITY_CUSTOM_RUNTIME_ENABLED=1 only for that checked deployment.
At ComplexityService startup, the backend first probes runtime v1. After a successful v1 probe, it probes v2 secret-completion updates. A successful v2 probe enables secretCompletion and v2 authoring. If v2 reports unavailable, authoring retains v1 without trusted secret entry. Existing v1 outputs keep their exact v1 runtime package.
The startup probe runs before authoring becomes available. It checks asset hashes, the accepted policy, and current kernel state. The child must run without root privileges, with restricted system calls and only standard input, output, and error descriptors.
A root Node parent launches the child and kernel observer with an unprivileged identity. The observer checks the actual child process. A child readiness message alone is insufficient.
If preparation or the startup probe fails, custom authoring stays unavailable. The optional probe does not stop native chat startup. Unsupported hosts retain native views and readable custom-output fallback content.
See deployment requirements before enabling the runtime in a release.
Runtime boundaries and limits
The Node parent coordinates a separate Python process with QuickJS. Generated source runs there, not in the browser. The guest cannot open files, make outbound connections, or access the application DOM. Trusted browser components render only checked frames.
The fixed library set includes React 18.3.1. The approved host surface is div, span, button, svg, circle, canvas, and state. It is not an unrestricted React or browser environment.
| Resource | Limit |
|---|---|
| Original source | 12,000 UTF-16 code units |
| Guest heap | 32 MiB |
| Process address space | 128 MiB |
| Cumulative process CPU time | 1 second soft limit, 2 seconds hard limit |
| QuickJS interruption target | 250 ms per evaluation phase, not a universal deadline |
| Independent parent watchdog | 1,500 ms per pending request |
| Process lifetime | 60 seconds |
| Concurrent child processes | 8 per coordinator process, 2 per owner |
| Requests in flight | 1 per session |
The parent watchdog kills the child process group independently of guest execution. Expiry or a failed session does not automatically retry generation.
Custom canvas frames allow at most 128 circle commands in a 512 × 256 coordinate space. They cannot load external images or execute drawing scripts. See custom-view controls for user behavior.
Host actions and the separate draft gate
Custom-runtime readiness enables custom views only. It does not enable mailbox writes. Host actions require a ready, approved host implementation and current backend capabilities for the exact completed output.
Trusted action buttons sit outside the generated guest tree. Guest callbacks cannot execute mailbox actions. Each host click checks current permissions, selected tools, mailbox ownership, output identity, and revisions. Mount, preview, reload, and reconnect do not execute actions.
ComplexityService calls configureUiDraftActions(true) at startup. Draft actions also require complexity.ui_action_intents and fresh tool and mailbox authorization. This gate is independent of COMPLEXITY_CUSTOM_RUNTIME_ENABLED and the v1/v2 probes. configureUiDraftActions(false) disables draft capabilities.
Without the ledger, an authorized openMail action can use the read-only path. Intent status then returns UI_ACTION_INTENT_NOT_FOUND. Database errors are failures, not proof that the table is absent.
A host action does not start another chat decision turn. The canonical draft writer calls its writer model and consumes quota. A normal successful save needs no extra approval. Only a proposal that requires review uses the trusted host Apply/cancel flow. Apply uses the stored proposal and a version-bound canonical baseline. It does not rerun the writer. Cancellation does not delete a draft.
See draft review and recovery and the ledger deployment procedure.