Problem
ParameterMapper.parse_output() in src/celeste/parameters.py uses Any for its content parameter and return type. This was introduced as a pragmatic fix in #142 to bridge the type boundary between the generic Content type parameter on ModalityClient and the text-specific parse_output method.
While Any is accurate for the base implementation (it's an identity function), it loses type safety — callers and overrides get no static type checking on the content flowing through parse_output.
Root cause
ParameterMapper is not generic. It was originally designed with TextContent hardcoded in parse_output, because structured output parsing only applies to text. But now that _transform_output() is called at the base _predict() pipeline level (for all modalities), the parameter system needs to be content-type-agnostic.
Proposed fix
Make ParameterMapper generic on a Content type parameter, following the existing codebase convention (PEP 695 syntax, semantic names):
class ParameterMapper[Content](ABC):
def parse_output(self, content: Content, value: object | None) -> Content:
return content
Then propagate through the chain:
FieldMapper[Content](ParameterMapper[Content])
parameter_mappers() -> list[ParameterMapper[Content]] on ModalityClient
_transform_output(content: Content, ...) -> Content — no Any needed
Affected files
src/celeste/parameters.py — make ParameterMapper and FieldMapper generic
src/celeste/client.py — update parameter_mappers() return type
- 70+
ParameterMapper subclasses — add type parameter
- 40+
FieldMapper subclasses — add type parameter
- 7
parse_output overrides — change TextContent to Content
- All
parameter_mappers() implementations — update return type
Impact
Problem
ParameterMapper.parse_output()insrc/celeste/parameters.pyusesAnyfor its content parameter and return type. This was introduced as a pragmatic fix in #142 to bridge the type boundary between the genericContenttype parameter onModalityClientand the text-specificparse_outputmethod.While
Anyis accurate for the base implementation (it's an identity function), it loses type safety — callers and overrides get no static type checking on the content flowing throughparse_output.Root cause
ParameterMapperis not generic. It was originally designed withTextContenthardcoded inparse_output, because structured output parsing only applies to text. But now that_transform_output()is called at the base_predict()pipeline level (for all modalities), the parameter system needs to be content-type-agnostic.Proposed fix
Make
ParameterMappergeneric on aContenttype parameter, following the existing codebase convention (PEP 695 syntax, semantic names):Then propagate through the chain:
FieldMapper[Content](ParameterMapper[Content])parameter_mappers() -> list[ParameterMapper[Content]]onModalityClient_transform_output(content: Content, ...) -> Content— noAnyneededAffected files
src/celeste/parameters.py— makeParameterMapperandFieldMappergenericsrc/celeste/client.py— updateparameter_mappers()return typeParameterMappersubclasses — add type parameterFieldMappersubclasses — add type parameterparse_outputoverrides — changeTextContenttoContentparameter_mappers()implementations — update return typeImpact
Anypatch from Move _transform_output from provider _parse_content to base _predict pipeline #142 with proper end-to-end type safety