Skip to main content

Module extension

Module extension 

Source
Expand description

Task 10C: trace wiring for extension-hosted providers (completing the Task 10 transport coverage). Mirrors the seams in trace::anthropic / trace::openai / trace::google with extension-specific honesty rules:

  • Trace only actual IPC. A record begins only after every routing gate has passed — provider existence, per-provider trust, trust-state readability, and the pre-IPC cancellation check — and immediately before the provider_stream/provider_complete call crosses the extension process boundary. Blocked, untrusted, unavailable, or cancelled-before-start requests emit no request-attempt record.
  • Wire is always None. JSON-RPC framing and serialization for the sidecar transport are owned by the extension process transport, not this routing layer — there is no buffer of exact bytes here, so no wire digest is ever claimed (same rule as the remote-broker paths).
  • Attempt rule (documented invariant): one outer extension turn is one transport attempt — one record per provider_stream call or per outer provider_complete/complete_provider_with_tools turn. The tool-loop helper may invoke provider.complete several times inside one turn; those interior tool-use iterations are not separate request attempts and are deliberately not counted as retries (they are successful calls, not failures — the attempt/retries invariant would be false for them). The record therefore never claims an interior call count.
  • Reserved static endpoint identity. The endpoint host is the RFC 2606-style reserved name extension.invalid with static paths /provider/stream / /provider/complete; the exact qualified plugin:provider/model identity travels in the validated model field. Plugin file paths, spawn commands, params, messages, tools, errors and credentials never enter a record.
  • Extension-controlled data is untrusted. Error text from the extension is replaced by the static code EXTENSION_PROVIDER_ERROR_CODE; stop reasons pass a closed mapping; usage numbers are accepted only as plain unsigned integers under known keys (never copied as raw values of any other shape).

Structs§

ExtensionAttempt
Per-turn trace state for one extension provider IPC invocation: the optional tracer, this turn’s monotonic clock, and the shared first-event cell. Every method is a no-op when tracing is disabled; nothing here can fail the request. Exactly one finish_* record is emitted — the tracer is taken on finish, so later calls can never double-emit.
FirstEventMark
Cheap cloneable handle the stream forwarder uses to mark the first model event (first TextDelta/ThinkingDelta/ToolUse/Usage). Set-once via compare-exchange; a None interior (tracing disabled) makes mark() a no-op with zero shared state.

Constants§

EXTENSION_COMPLETE_PATH
Static endpoint path for provider.complete IPC (including the tool-loop outer turn).
EXTENSION_ENDPOINT_HOST
Reserved, never-routable endpoint host for extension provider records. .invalid is an RFC 2606 reserved TLD — this can never collide with or leak a real network endpoint.
EXTENSION_PROVIDER_ERROR_CODE
The only failure code an extension-controlled error may produce in a trace record — extension error text is untrusted and never copied.
EXTENSION_STREAM_PATH
Static endpoint path for provider.stream IPC.

Functions§

begin_extension_tracer
Begin tracing one extension provider IPC turn. Returns None when tracing is disabled or the qualified identity is unrepresentable — tracing can never fail or alter the provider request.
extension_capability_losses
Capability-driven translation report for the extension route, structural only. Known losses today:
stop_reason_from_extension
Normalize an extension-reported stop reason through a closed mapping. Unknown values collapse to Other; the raw string is never stored.
usage_from_extension_value
Extract provider-reported usage from the extension’s free-shape usage value. Only plain unsigned integers under the known keys are accepted; anything else stays None — numbers are never fabricated and non-numeric extension content is never copied. Returns None when no metric parses.