Public entrypoint for the Codex app-server client.
This module owns the long-lived session process, exposes the thread and turn
request helpers, broadcasts parsed server events to subscribers, and can
auto-reply to server-initiated requests through register_request_handler/2.
Summary
Functions
Queues replay-gap acknowledgement on the client generation that reported it.
Publishes active threads already loaded by the connected app server.
Builds normalized app-server initialization parameters with required client capabilities.
Calls one MCP tool in the active thread's server scope.
Returns a specification to start this module under a supervisor.
Injects model-visible history items without starting a turn.
Lists one page of a paginated thread's turns in the requested server order.
Reads the effective Codex configuration for a working directory.
Reads one MCP resource in the active thread's server scope.
Starts a turn and returns its initial protocol state without collecting its event stream.
Subscribes the caller to active-thread signals from shared Codex clients.
Unsubscribes the app-server connection from a remote thread.
Types
@type experimental_feature_enablement_set_response() :: %CodexEx.AppServer.Protocol.Generated.V2.ExperimentalFeatureEnablementSetResponse{ enablement: term() }
@type hooks_list_response() :: %CodexEx.AppServer.Protocol.Generated.V2.HooksListResponse{data: term()}
@type mcp_resource_read_response() :: %CodexEx.AppServer.Protocol.Generated.V2.McpResourceReadResponse{ contents: term() }
@type pending_model_list_request() :: %{ref: reference(), callers: [GenServer.from()]}
@type pending_request_map() :: %{optional(term()) => CodexEx.AppServer.Message.t()}
@type request_handler() :: (term() -> request_handler_reply())
@type request_handler_reply() :: CodexEx.AppServer.Message.supported_reply_payload() | {:ok, CodexEx.AppServer.Message.supported_reply_payload()} | {:error, term()}
@type request_result() :: {:ok, CodexEx.AppServer.Message.supported_reply_payload()} | {:error, term()}
@type request_timeout() :: timeout()
@type skills_list_response() :: %CodexEx.AppServer.Protocol.Generated.V2.SkillsListResponse{ data: term() }
@type state() :: %{ initialize_result: initialize_response(), model_list_cache: model_list_response() | nil, model_list_pending: pending_model_list_request() | nil, pending_requests: pending_request_map(), replay_gap: map() | nil, replay_gap_owners: MapSet.t(pid()), broadcasts_thread_activity?: boolean(), thread_activity_runner_id: binary() | nil, thread_activity_workspace_id: binary() | nil, request_handler: request_handler() | nil, session: CodexEx.AppServer.Session.t(), strict_protocol: boolean(), subscribers: subscriber_map() }
@type subscriber_map() :: %{optional(pid()) => subscriber()}
@type t() :: pid() | registered_name()
@type thread_list_response() :: %{ data: [CodexEx.AppServer.ThreadSnapshot.t()], next_cursor: term() }
@type thread_turns_page() :: %{ turns: [CodexEx.AppServer.Turn.t()], next_cursor: binary() | nil }
@type turn_interrupt_response() ::
%CodexEx.AppServer.Protocol.Generated.V2.TurnInterruptResponse{}
Functions
@spec acknowledge_replay_gap_async(pid(), pid(), non_neg_integer()) :: :ok
Queues replay-gap acknowledgement on the client generation that reported it.
Publishes active threads already loaded by the connected app server.
Builds normalized app-server initialization parameters with required client capabilities.
@spec call_mcp_tool(GenServer.server(), binary(), binary(), binary(), map()) :: {:ok, mcp_server_tool_call_response()} | {:error, term()}
Calls one MCP tool in the active thread's server scope.
Returns a specification to start this module under a supervisor.
See Supervisor.
@spec connect(keyword()) :: GenServer.on_start()
@spec fork_thread(t(), binary(), map()) :: {:ok, CodexEx.AppServer.Thread.t()} | {:error, term()}
@spec get_thread_goal(t(), binary()) :: {:ok, CodexEx.AppServer.ThreadGoal.t() | nil} | {:error, term()}
@spec initialize_result(t()) :: {:ok, initialize_response()} | {:error, {:client_call_failed, term()}}
Injects model-visible history items without starting a turn.
@spec list_experimental_features(t(), map()) :: {:ok, experimental_feature_list_response()} | {:error, {:client_call_failed, term()} | term()}
@spec list_hooks(t(), [binary()]) :: {:ok, hooks_list_response()} | {:error, {:client_call_failed, term()} | term()}
@spec list_models(t()) :: {:ok, model_list_response()} | {:error, {:client_call_failed, term()} | term()}
@spec list_skills(t(), map()) :: {:ok, skills_list_response()} | {:error, {:client_call_failed, term()} | term()}
@spec list_thread_turns(t(), binary(), keyword()) :: {:ok, thread_turns_page()} | {:error, term()}
Lists one page of a paginated thread's turns in the requested server order.
@spec list_threads(t(), map()) :: {:ok, thread_list_response()} | {:error, {:client_call_failed, term()} | term()}
@spec read_config(t(), binary() | nil) :: {:ok, config_read_response()} | {:error, term()}
Reads the effective Codex configuration for a working directory.
@spec read_mcp_resource(GenServer.server(), binary(), binary(), binary()) :: {:ok, mcp_resource_read_response()} | {:error, term()}
Reads one MCP resource in the active thread's server scope.
@spec read_thread(t(), binary(), keyword()) :: {:ok, CodexEx.AppServer.ThreadSnapshot.t()} | {:error, term()}
@spec reply_request(t(), term(), request_result(), timeout()) :: :ok | {:error, term()}
@spec revert_thread(t(), binary(), binary()) :: {:ok, CodexEx.AppServer.Thread.t()} | {:error, term()}
@spec rollback_thread(t(), binary(), non_neg_integer()) :: {:ok, CodexEx.AppServer.Thread.t()} | {:error, term()}
@spec set_experimental_feature_enablement(t(), map()) :: {:ok, experimental_feature_enablement_set_response()} | {:error, {:client_call_failed, term()} | term()}
@spec set_thread_goal(t(), binary(), map()) :: {:ok, CodexEx.AppServer.ThreadGoal.t()} | {:error, term()}
@spec start_link(keyword()) :: GenServer.on_start()
@spec start_review_request(t(), map(), timeout()) :: {:ok, CodexEx.AppServer.Turn.t()} | {:error, term()}
@spec start_thread(t(), map()) :: {:ok, CodexEx.AppServer.Thread.t()} | {:error, term()}
@spec start_turn(t(), binary(), [map()], map()) :: {:ok, CodexEx.AppServer.Turn.t()} | {:error, term()}
Starts a turn and returns its initial protocol state without collecting its event stream.
@spec start_turn_request(t(), map(), timeout()) :: {:ok, CodexEx.AppServer.Turn.t()} | {:error, term()}
@spec subscribe_thread_activity() :: :ok | {:error, :pubsub_not_configured | {:already_registered, pid()}}
Subscribes the caller to active-thread signals from shared Codex clients.
Requires a Phoenix.PubSub server configured as config :codex_ex, :pubsub.
@spec unarchive_thread(t(), binary()) :: {:ok, CodexEx.AppServer.Thread.t()} | {:error, term()}
Unsubscribes the app-server connection from a remote thread.