Pure helpers for tool exposure resolution and filtering.
Tier 1a of the text-mode + PTC compute-tool plan
(Plans/text-mode-ptc-compute-tool.md).
Each tool may declare expose: :native | :ptc_lisp | :both. When the
field is missing/nil, the resolved value depends on the agent's mode
per the plan's "Tool Exposure Policy" table:
output: | ptc_transport: | default expose: |
|---|---|---|
:text | not :tool_call (or nil) | :native |
:text | :tool_call (combined) | :native |
:ptc_lisp | any | :ptc_lisp |
This module is intentionally side-effect-free: validation lives in
PtcRunner.SubAgent.Validator; runtime wiring (LLM request build,
Lisp analyzer inventory) is wired in Tier 2/3.
Summary
Types
Mode descriptor accepted by effective_expose/2 and filter_by_expose/3.
Functions
Resolve a tool's effective expose: value for the given agent mode.
Filter a tool collection to those whose effective expose: is in
allowed_set.
Types
Mode descriptor accepted by effective_expose/2 and filter_by_expose/3.
Either:
{output, ptc_transport}tuple —outputis:text | :ptc_lisp,ptc_transportis:content | :tool_call | nil.- A
PtcRunner.SubAgent.Definition.t()struct (the:outputand:ptc_transportfields are read).
Functions
@spec effective_expose(PtcRunner.Tool.t(), mode()) :: PtcRunner.Tool.expose_layer()
Resolve a tool's effective expose: value for the given agent mode.
If the tool has an explicit expose:, returns it unchanged. Otherwise
applies the per-mode default per "Tool Exposure Policy."
Examples
iex> tool = %PtcRunner.Tool{name: "x", expose: nil}
iex> PtcRunner.SubAgent.Exposure.effective_expose(tool, {:text, nil})
:native
iex> tool = %PtcRunner.Tool{name: "x", expose: nil}
iex> PtcRunner.SubAgent.Exposure.effective_expose(tool, {:text, :tool_call})
:native
iex> tool = %PtcRunner.Tool{name: "x", expose: nil}
iex> PtcRunner.SubAgent.Exposure.effective_expose(tool, {:ptc_lisp, :content})
:ptc_lisp
iex> tool = %PtcRunner.Tool{name: "x", expose: :both}
iex> PtcRunner.SubAgent.Exposure.effective_expose(tool, {:text, nil})
:both
@spec filter_by_expose( [PtcRunner.Tool.t()] | %{optional(String.t()) => PtcRunner.Tool.t()}, mode(), [ PtcRunner.Tool.expose_layer() ] ) :: [PtcRunner.Tool.t()]
Filter a tool collection to those whose effective expose: is in
allowed_set.
tools— list ofPtcRunner.Toolstructs OR a map ofname => PtcRunner.Tool. The output preserves the input shape's iteration order (lists keep order; maps are converted to a list of tools sorted by tool name, since map iteration order in Elixir is not guaranteed).allowed_set— list/MapSet of:native | :ptc_lisp | :both.
Returns a list of PtcRunner.Tool structs.
Examples
iex> a = %PtcRunner.Tool{name: "a", expose: :native}
iex> b = %PtcRunner.Tool{name: "b", expose: :both}
iex> c = %PtcRunner.Tool{name: "c", expose: :ptc_lisp}
iex> result = PtcRunner.SubAgent.Exposure.filter_by_expose(
...> [a, b, c], {:text, :tool_call}, [:native, :both]
...> )
iex> Enum.map(result, & &1.name)
["a", "b"]