This page is the working companion to the Script Execution reference. It runs a small fireworks script through the same kernel pipeline that powers ExecuteScriptRequest on Code nodes β€” but inline as an interactive markdown cell, so you can see the script source, the progress messages, and the rendered output side by side.

What you'll observe

When this page loads, the script in the cell below runs once, end-to-end. While it runs:

sequenceDiagram participant Cell as Markdown cell participant Activity as Activity hub<br/>(this page's kernel session) participant Executor as Executor child hub<br/>(internal) Cell->>Activity: SubmitCodeRequest Activity->>Executor: forward Activity-->>Cell: ack loop while script runs Executor->>Activity: DataChangeRequest (snapshot) Activity-->>Cell: live tick (visible in browser dev tools as activity-log updates) end Executor->>Activity: SubmitCodeResponse + return value Activity-->>Cell: render area updates with fireworks

Because the activity hub is forwarding to an internal executor, the activity hub's action block stays free during execution β€” and so each Log.LogInformation call gets pushed to subscribers within milliseconds of being emitted, instead of being batched into a single end-of-run flush.

Live demo

Log.LogInformation("Loading fuse...");
System.Threading.Thread.Sleep(80);
Log.LogInformation("Lighting...");
System.Threading.Thread.Sleep(80);
Log.LogInformation("3... 2... 1...");
System.Threading.Thread.Sleep(80);
Log.LogInformation("Boom!");
MeshWeaver.Layout.Controls.Html(
    "<div style='font-size:48px;text-align:center;animation:pulse 1s infinite'>" +
    "πŸŽ† πŸŽ‡ πŸŽ† πŸŽ‡ πŸŽ†" +
    "</div>")

Pulling in a NuGet library

#r "nuget:..." directives work the same as in dotnet-script and the old Polyglot Notebooks: the kernel resolves the package via NuGet, downloads it (cached after the first hit), and adds it as a Roslyn MetadataReference for the script. Transitive dependencies are loaded on demand via an AssemblyLoadContext probing hook.

#r "nuget:MathNet.Numerics, 5.0.0"
using MathNet.Numerics;

// erf(1) β‰ˆ 0.8427 β€” the canonical first-row value from any error-function table.
var erfOne = SpecialFunctions.Erf(1.0);
Log.LogInformation("MathNet.Numerics resolved. erf(1) = {Value:F6}", erfOne);

MeshWeaver.Layout.Controls.Markdown(
    $"**MathNet.Numerics** (loaded via `#r \"nuget:...\"`):\n\n" +
    $"- `SpecialFunctions.Erf(1.0)` = `{erfOne:F6}`\n" +
    $"- (canonical value: `0.842701`)")

The first time this page loads on a clean cache, the kernel takes ~5–10 seconds to download and unpack MathNet.Numerics (and its System.Buffers / System.Memory transitives). Subsequent loads hit the global packages folder and complete in a fraction of a second.

This is exactly the path the integration test ScriptExecutionInUserHomeTest.NuGetDirective_DownloadsPackage_AndScriptUsesIt exercises end-to-end, so any regression in the NuGet directive pipeline shows up in CI.

The --render Fireworks flag tells the markdown renderer to (a) execute the cell on page load and (b) display the cell's return value in a layout area named Fireworks (the area immediately below the cell). The four Log.LogInformation calls land on the kernel session's activity log; the final Controls.Html(...) becomes the rendered fireworks.

Two things to call out

Where activities live for "real" runs

The interactive markdown cell above runs on the page's transient kernel session. For ExecuteScriptRequest on a real Code node β€” the typical authoring pattern β€” each click creates a new MeshNode at {partitionRoot}/_Activity/{guid} (the user's home), with the originating Code node tracked on MainNode and ActivityLog.HubPath. The Code node remembers when it was last executed (LastExecutedAt); each historical run lives as a sibling under the user's _Activity namespace. Browse them via your home's activity feed or via "View activity history" on the Code node page.

Doing this from your own code or an MCP agent

The same pipeline is available three ways. See Script Execution for full details, rules of thumb, and progress-emission conventions:

Cancelling a long-running script

Per the Activity Control Plane, cancellation is a content patch, not a separate message. The user clicks "Cancel" β†’ the click handler patches RequestedStatus = Cancelled on the activity β†’ the activity hub's watcher dispatches the internal cancel β†’ the script's Ct trips β†’ status flips to Cancelled.

For the script itself to be cancellable mid-flight, pass Ct into every cancellable async call:

Log.LogInformation("Phase 1: pulling source data…");
await Mesh.GetWorkspace()
    .GetMeshNodeStream("rbuergi/source-feed")
    .Where(n => (n?.Content as FeedContent)?.Status == FeedStatus.Ready)
    .FirstAsync()                              // ← not .Take(1): empty must FAULT
    .ObserveCompletion(                        // ← never Rx's ToTask: forbidden repo-wide
        ex => Log.LogWarning(ex, "source-feed watch faulted AFTER the wait settled"),
        Ct);                                   // ← cancellable
Log.LogInformation("Phase 2: crunching numbers…");
await MyOwnWork(Ct);                           // ← your own async step, cancellable
Log.LogInformation("Phase 3: rendering report…");
return MeshWeaver.Layout.Controls.Markdown("Done.");

If the user cancels at "Phase 2", the wait inside MyOwnWork throws OperationCanceledException, the script unwinds, and the executor flips the activity to Cancelled (KernelExecutor distinguishes OperationCanceledException from a genuine fault, which flips to Failed) β€” so the πŸŽ† fireworks never appear.

Ct matters precisely because without it the script only observes cancellation at await resume points. That is fine for short awaits and useless for a 30-second Task.Delay β€” which will run to completion after the user has already pressed Cancel.

The Activity Overview's Cancel button (and the running-activities stripe on any Code node) wire this exact patch β€” you don't need to do anything special on the UI side beyond rendering an existing layout area.

Reconnecting…
The server was updated. Reloading the page to pick up the latest version.