Provider Profile Contract

Copy Markdown View Source

CliSubprocessCore.ProviderProfile defines the contract every first-party built-in or external provider CLI profile must implement.

Behaviour Surface

@callback id() :: atom()
@callback capabilities() :: [atom()]
@callback build_invocation(keyword()) ::
            {:ok, CliSubprocessCore.Command.t()} | {:error, term()}
@callback init_parser_state(keyword()) :: term()
@callback decode_stdout(binary(), term()) ::
            {[CliSubprocessCore.Event.t()], term()}
@callback decode_stderr(binary(), term()) ::
            {[CliSubprocessCore.Event.t()], term()}
@callback handle_exit(term(), term()) ::
            {[CliSubprocessCore.Event.t()], term()}
@callback transport_options(keyword()) :: keyword()

Responsibilities

Each profile owns:

  • the normalized provider id
  • the capability list exposed to downstream consumers
  • CLI command construction for that provider across both CliSubprocessCore.Command.run/1 and CliSubprocessCore.Session
  • stdout parsing into normalized core events
  • stderr parsing into normalized core events
  • exit handling into normalized terminal events
  • transport option overrides needed by the provider CLI

The foundation explicitly keeps those responsibilities out of downstream repos.

Validation Helpers

The behaviour module provides two helper functions:

ensure_module/1 verifies that a module is loaded, declares the behaviour, and exports the required callbacks.

validate_invocation/1 verifies that the profile returned a valid CliSubprocessCore.Command struct.

That same invocation contract is reused by both:

Registry Integration

CliSubprocessCore.ProviderRegistry stores provider profile modules by id.

External preloads are supported at application boot:

config :cli_subprocess_core,
  built_in_profile_modules: [
    MyApp.ProviderProfiles.Example
  ]

That preload hook only affects the default registry boot list. It does not make the external profile a first-party built-in shipped by cli_subprocess_core.

Ad hoc registrations can also be added at runtime:

:ok =
  CliSubprocessCore.ProviderRegistry.register(
    MyApp.ProviderProfiles.Example
  )

Design Constraints

Provider profiles should emit only CliSubprocessCore.Event values containing CliSubprocessCore.Payload.* structs. They should not invent competing normalized payload families in downstream repos.

For a step-by-step implementation guide, see guides/custom-provider-profiles.md.