Skip to content

Epic: ModelOutputThunk structural cleanup #909

Description

@ajbozarth

Status note: description rewritten on 2026-06-05 to reflect the post-#1197 design. The original April 2026 description is preserved in this issue's edit history. Discussion and design rationale: #1197.

Goal

Reshape ModelOutputThunk's internal layout to make the public surface explicit, the private surface coherent, and copy semantics structural rather than per-field.

Areas

# Area Issue Status
1 Raw provider responses → typed mot.raw namespace #1215 not started
2 telemetry_span / OTel ownership #1181 approved, awaiting merge — closes Area 2 on merge
3 Computation logistics → _call / _gen sub-objects #1216 not started
4 _thinking → public mot.thinking #1217 not started
5 Public error / generate_log surface #1191 folded in; design captured in #1191 comment

TL;DR

  • Area 1 (raw responses) — move backend _meta[...] keys (chat_response, oai_chat_response, etc.) onto a typed mot.raw: RawProviderResponse namespace. Migrate chat.py:_parse to switch on mot.raw.provider.
  • Area 2 (telemetry_span) — resolved by refactor(telemetry)!: move backend tracing onto plugin/hook pattern #1181 on merge; drops out of scope.
  • Area 3 (computation logistics) — split the seventeen private attrs into two internal sub-objects: mot._call (originating call, preserved across copies) and mot._gen (in-flight machinery, reset on copy). Add a guard that raises on copy-of-uncomputed-MOT.
  • Area 4 (_thinking) — promote to public mot.thinking with a property alias for _thinking through one deprecation cycle.
  • Area 5 (Soft-fail errors on ModelOutputThunk are only reachable via a private attribute #1191) — give MOT a public surface for errors and the generate log: expose mot.generate_log as a public property, and add a public mot.error channel so callers can detect a soft-failed thunk without reading private state.

Sequencing

  1. refactor(telemetry)!: move backend tracing onto plugin/hook pattern #1181 lands first. Independent, already approved. Closes Area 2 and adds _generation_id to Area 3's field set.
  2. Area 5 (Soft-fail errors on ModelOutputThunk are only reachable via a private attribute #1191). Smallest. Closes Soft-fail errors on ModelOutputThunk are only reachable via a private attribute #1191.
  3. Area 1 (refactor(core): consolidate backend raw responses onto mot.raw namespace #1215). No dependency on Areas 3/4/5.
  4. Area 4 (refactor(core): promote mot._thinking to public mot.thinking #1217). Independent. Same release as Area 1 is fine.
  5. Area 3 (refactor(core): split MOT internal state into _call / _gen sub-objects #1216). Largest internal rename. Lands last.

Coordinated, not in scope

Related bugs (discovered during audit, filed separately)

Cross-cutting constraints

  • _meta is CBlock surface, not just MOT surface. This epic does not change CBlock._meta; it only removes MOT's writes into the dict.
  • Public API is wider than field names suggest. mot._thinking, mot._meta[<keys>], and mot._generate_log are read by code outside base.py today; renames need property aliases for one minor release.
  • Streaming validation locks in current shape: cancel_generation(), mot._async_queue single-consumer semantics, and mot.cancelled are load-bearing for stream_with_chunking() (feat(stdlib): add stream_with_chunking() with per-chunk validation (#901) #942).
  • Mellea is pre-1.0 — DeprecationWarning aliases for one minor cycle, then remove.

Metadata

Metadata

Assignees

Labels

area/componentComponent type system, CBlock, @generative decorator, prompt templates, RichDocumentarea/samplingSamplingStrategy, SamplingResult, ModelOption, generation optionsarea/stdlibCore abstractions: Context, MOT, SamplingStrategy, formatters, serializationarea/streamingStreaming chunks, events, per-chunk validationenhancementNew feature or requestepicHigh level Epicp2Medium/low: minor bugs, niche features, polish, docs, tests, cleanup. Scoped, lower urgency.refactor

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions