Home View
The home view shows all mounted namespaces as cards. Each card displays the namespace prefix, badges for API and Engine status, and a method count. The sidebar provides persistent navigation.
System Namespace: Dogfooding
The woodglue UI is a consumer of its own system namespace. Every view -- namespace listing, runs, triggers, method docs -- calls system.* methods via JSON-RPC. The system namespace is mounted and exposed the same way as any user namespace.
// main.js -- Every UI action goes through system.* RPC calls
async function loadNamespaces() {
const list = await rpcCall("system.list_namespaces");
// ...
}
async function loadRuns(prefix, statusFilter = null) {
if (statusFilter === "running") {
return await rpcCall("system.active_runs", { namespace: prefix });
}
return await rpcCall("system.recent_runs", { namespace: prefix, limit: 30 });
}
async function loadRunDetail(prefix, runId) {
return await rpcCall("system.inspect_run", { namespace: prefix, run_id: runId });
}
async function loadTriggers(prefix) {
return await rpcCall("system.list_triggers", { namespace: prefix });
}The system namespace exposes 12 methods organized in three groups: introspection (list_namespaces, list_methods, describe_method), engine management (recent_runs, active_runs, inspect_run, load_io, child_runs), and trigger control (list_triggers, fire_trigger, activate_trigger, deactivate_trigger).
The system namespace is built using the same Namespace / Method / NamespaceNode primitives as any other namespace. It registers each function as a tagged API method. The Pydantic models define the return types, which the UI's doc view renders automatically.
# system_api.py -- System namespace built with the same primitives as user namespaces
"""
System namespace: server introspection and engine management.
Builds a Namespace with introspection methods (list_namespaces, list_methods,
describe_method) plus engine/trigger facade methods, all tagged ["api"].
Always mounted as the `system` prefix with `expose_api=True`.
"""
class NamespaceInfo(BaseModel):
prefix: str
expose_api: bool
run_engine: bool
method_count: int
has_cache: bool
class MethodInfo(BaseModel):
nsref: str
tags: list[str]
has_cache: bool
has_triggers: bool
doc_teaser: str | None = None
# ...full detail fields populated by describe_methodMethod Documentation
Method documentation is auto-generated from Python type annotations. The view shows parameters (name, type, required), return type, and referenced Pydantic models with their field schemas. This is the list_namespaces method -- returning NamespaceInfo[].
The fire_trigger method shows a more complex signature: namespace, name, and optional payload. It returns DagRunResult with run_id, status, outputs, failed_node, and error fields. The UI's 'fire' button on trigger cards calls this method directly.
inspect_run returns a full DagRun model with nodes dict, I/O payloads, and timing data. This powers the DAG graph visualization view.
User-defined methods get the same documentation treatment. cached_hello takes name (str) and age (int), returns HelloOut with eman, ega, and stamp fields -- all derived from Python type hints.
Engine & DAG Runs
The gref_hello namespace has run_engine=True, showing triggers at the top (with a 'fire' button) and a scrollable list of DAG runs below. Each run shows the DAG nsref, short ID, timestamp, and duration. Status filter tabs (all/running/completed/failed) let you narrow the view.
Clicking a run opens the DAG graph view. Nodes are positioned by topological layer with SVG edges. A status legend shows node states (completed, running, failed, pending, skipped). The breadcrumb trail (woodglue > gref_hello > run_id) provides navigation context.
Node Inspection
Clicking a DAG node opens a detail panel on the right showing status, role (source/sink), start and finish timestamps, and a 'Load I/O' button. This calls system.load_io to fetch the actual input and output payloads recorded during execution.
// Clicking "Load I/O" triggers this RPC call:
const result = await rpcCall("system.load_io", {
namespace: prefix,
run_id: run.run_id,
node_labels: [label],
});
// The response contains the actual JSON
// payloads passed to and returned from the node:
// Input: { "name": "jon", "age": 20 }
// Output: { "eman": "noj", "ega": -20,
// "stamp": "2026-05-04..." }After loading, the panel shows the actual JSON input and output for the node. The input matches the trigger's configured payload, and the output shows the cached_hello function's result with reversed name and negated age.
API-Only Namespaces
The hello namespace has run_engine=False -- it only exposes API methods (hello, pydantic_hello) without any engine, triggers, or DAG runs. The view is simpler: just the method list in the sidebar. This shows how woodglue supports both compute-only and engine-backed namespaces.
Arrow keys or j/k to navigate