Powered by AppSignal & Oban Pro

Lesson 02 Livebook: Founder Runtime

livebooks/02_founder_runtime.livemd

Lesson 02 Livebook: Founder Runtime

Lesson 2 keeps the same founder behavior, but places it behind a runtime boundary.

Mix.install([
  {:founder_runtime, path: "../02_founder_runtime"}
])

Application.ensure_all_started(:founder_runtime)

Helpers

defmodule Lesson02Helpers do
  alias FounderRuntime.StudioJido

  def unique_agent_id(prefix) do
    "#{prefix}-#{System.unique_integer([:positive])}"
  end

  def safe_stop(agent_id) do
    case StudioJido.whereis(agent_id) do
      nil -> :ok
      _pid -> StudioJido.stop_agent(agent_id)
    end
  end

  def wait_until(fun, attempts \\ 20)

  def wait_until(fun, attempts) when attempts > 0 do
    case fun.() do
      nil ->
        Process.sleep(50)
        wait_until(fun, attempts - 1)

      value ->
        value
    end
  end

  def wait_until(_fun, 0) do
    raise "condition was not met before the timeout"
  end
end

Send Signals Into A Running Founder

alias FounderRuntime.{FounderAgent, StudioJido}
alias Jido.AgentServer
alias Jido.Signal

founder_id = Lesson02Helpers.unique_agent_id("founder")
{:ok, pid} = StudioJido.start_agent(FounderAgent, id: founder_id)

{:ok, _submitted_agent} =
  AgentServer.call(
    pid,
    Signal.new!(
      "studio.idea_submitted",
      %{
        name: "Orbit Cafe",
        genre: "cozy sim",
        hook: "Run a coffee shop on a drifting station"
      },
      source: "/livebook"
    )
  )

{:ok, _greenlit_agent} =
  AgentServer.call(
    pid,
    Signal.new!("studio.idea_greenlit", %{name: "Orbit Cafe"}, source: "/livebook")
  )

:ok =
  AgentServer.cast(
    pid,
    Signal.new!("studio.milestone_planned", %{milestone: "build a playable prototype"},
      source: "/livebook"
    )
  )

runtime_state =
  Lesson02Helpers.wait_until(fn ->
    {:ok, state} = AgentServer.state(pid)

    if state.agent.state.next_milestone == "build a playable prototype" do
      state
    end
  end)

Lesson02Helpers.safe_stop(founder_id)

%{
  listed_agents: StudioJido.list_agents(),
  founder_state: runtime_state.agent.state
}