AttractorEx stays framework-agnostic. AttractorExPhx is the explicit adapter layer that plugs Phoenix into the engine.
Why This Layer Exists
The repository now has three clearer boundaries:
AttractorExfor the standalone engine, HTTP service, and spec-facing runtime behavior.AttractorExPhxfor Phoenix-oriented integration code such as supervision-friendly server startup, Req-based HTTP access, and push delivery through Phoenix PubSub.AttractorPhoenixWebfor the UI and controller/liveview experience.
That split keeps lib/attractor_ex/ independent while making the integration path easy to find and test on its own.
Main Modules
Typical Usage
Start the engine HTTP API under a Phoenix supervision tree:
children = [
{AttractorExPhx.PubSub,
pubsub_server: MyApp.PubSub,
manager: MyApp.AttractorHTTP.Manager,
name: MyApp.AttractorPubSubBridge},
{AttractorExPhx.HTTPServer,
port: 4101,
ip: {127, 0, 0, 1},
manager: MyApp.AttractorHTTP.Manager,
registry: MyApp.AttractorHTTP.Registry,
name: MyApp.AttractorHTTPServer}
]Run a pipeline directly from a Phoenix controller or other process:
{:ok, result} = AttractorExPhx.run(dot_source, %{}, logs_root: "tmp/runs")Call the HTTP control plane from LiveView:
{:ok, %{"pipelines" => pipelines}} = AttractorExPhx.list_pipelines()
{:ok, %{"pipeline_id" => id}} = AttractorExPhx.create_pipeline(dot_source, %{})
{:ok, graph} = AttractorExPhx.get_pipeline_graph_json(id)The Phoenix dashboard in this repository also uses that same client contract to render
typed wait.human controls. Question metadata such as type, multiple, required,
and metadata.input_mode is translated into LiveView forms so operators can answer
single-select, multi-select, confirmation, yes/no, and freeform prompts directly from
the browser.
Subscribe a LiveView or other Phoenix process to live updates without polling:
{:ok, snapshot} =
AttractorExPhx.subscribe_pipeline(id,
pubsub_server: MyApp.PubSub,
bridge: MyApp.AttractorPubSubBridge
)
receive do
{:attractor_ex_event, %{"type" => type} = event} ->
IO.inspect({snapshot["status"], type, event})
endFor browser clients, this application also exposes a Phoenix Channel topic per pipeline:
- Connect to
/socket. - Join
attractor:pipeline:<pipeline_id>. - Read the initial
"snapshot"push. - Handle incremental
"pipeline_event"pushes.
Test Strategy
The adapter has its own test scope under test/attractor_ex_phx/ so the integration contract can be validated without depending on the LiveView UI tests to cover it indirectly.