1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
//! How a profiling pass hands its JSON Schema to the model (#5588).
//!
//! Why: a schema rendered as prose in the system turn is a request the model may
//! decline — #5588 was filed because the drift is observable as unparseable
//! output. `trusty_common::inference::ChatRequest::response_schema` constrains
//! the completion instead, but only where the provider can honour it: Bedrock's
//! Converse API has no schema parameter, and `tga profile --model bedrock/…` is
//! a documented invocation. Sending the field there would be
//! `InferenceError::UnsupportedCapability` before the socket opens, turning
//! every period of a Bedrock run into a skip.
//! What: [`deliver_schema`] picks one delivery per call — the real field when
//! the adapter supports structured output, the prose fallback when it does not
//! — so exactly one copy of the schema reaches the model either way.
//! [`sampling_temperature`] is the other per-provider fork both passes share:
//! whether the request may carry a `temperature` at all (#111).
//! Test: `schema_delivery_tests.rs`.
use Value;
use ;
/// The `temperature` one profiling pass may send to `model`.
///
/// Why (#111): Claude Sonnet 5 on Bedrock rejects any request that sets
/// `temperature`, so no `bedrock/…` request carries one, whatever the model.
/// Other providers keep the pass's fixed temperature.
/// What: `None` when `model` routes to Bedrock, by the same
/// [`ProviderId::from_slug_prefix`] rule `provider_for` routes on (Bedrock
/// always resolves at that stage); `Some(temperature)` otherwise.
/// Test: `bedrock_slugs_get_no_temperature`.
pub
/// Choose how one pass's schema reaches the model.
///
/// Why: both profiling passes (period review and narrative synthesis) face the
/// same fork, and a second copy of it would be the duplication #5588 is about.
/// The fallback rather than a refusal is tga's fail-open precedent: a provider
/// failure already leaves a period skipped or the narrative deterministic
/// (`PeriodReview::skipped`, `apply_fallback_narrative`) rather than aborting
/// the run, and a schema the provider cannot enforce is still a schema the model
/// can be asked to follow.
/// What: with `structured_output` true, returns `base_system` unchanged plus
/// `Some(StructuredOutput)` for the caller to put on
/// [`trusty_common::inference::ChatRequest::response_schema`]. With it false,
/// returns `base_system` with the schema appended as a fenced JSON block and
/// `None`. `strict` is left at [`StructuredOutput::new`]'s default — the passes
/// want the constraint, not best-effort JSON.
/// Test: `structured_provider_gets_the_field_and_a_clean_system_turn`,
/// `unsupported_provider_gets_the_prose_fallback`,
/// `the_schema_is_delivered_exactly_once`.
// ─── Unit tests ───────────────────────────────────────────────────────────────