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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
//! The API-agnostic request the engine hands to any [`Provider`](crate::Provider).
use ;
/// One provider-neutral sampling request (ADR-0007).
///
/// The loop builds exactly one of these and knows nothing about any wire. Per
/// ADR-0013 there is **no separate `system` field** — `messages` carries the whole
/// role-tagged stream (System/Developer included), and each wire hoists leading
/// System messages into its own top-level slot (e.g. Anthropic's `system`).
/// Provider-neutral sampling knobs — the **common core** only.
///
/// Wire-specific parameters (Anthropic `top_k`/`stop_sequences`/thinking budget,
/// OpenAI `frequency_penalty`, …) are the concern of each wire's request builder,
/// not this type, keeping [`ConversationRequest`] API-agnostic (ADR-0007). Grok
/// Build uses the same layering: a neutral core plus per-wire superset structs.
/// The default output-token budget for one sample.
///
/// A file-writing agent spends most of a turn inside one `tool_use` argument
/// blob, so this is not a "typical reply length" knob — it is the ceiling on
/// the largest single tool call the model can emit. Set it too low and the
/// wire truncates mid-call: the API returns the `tool_use` block with an
/// **empty** `input` (`{}`) and `stop_reason: "max_tokens"`, the typed decode
/// then reports a missing required field, and the model retries the same
/// oversized call forever. That is what 4096 did here.
///
/// 64k is the ceiling every current model this crate targets accepts, and the
/// value Claude Code escalates to when a turn truncates (`ESCALATED_MAX_TOKENS`,
/// `utils/context.ts:25`). Claude Code otherwise resolves a per-model
/// `{default, upperLimit}` pair (`utils/context.ts:149-208`) — 64k default for
/// opus-4-6, 32k for the sonnet-4-6 / 4.5 families — and its 8k
/// `CAPPED_DEFAULT_MAX_TOKENS` is **not** the shipped default: it is gated on
/// the `tengu_otk_slot_v1` slot-reservation experiment, which defaults to
/// *false* off first-party (`services/api/claude.ts:3394-3397`).
///
/// Not 128k, even though the current frontier models allow it: `upperLimit` is
/// per model, and Haiku 4.5 stops at 64k. 64k is the largest value that is
/// correct everywhere, and the gap is academic — a single tool call whose
/// arguments exceed 64k tokens is not a call worth completing.
///
/// This is a **ceiling on one response**, not a reservation: nothing is spent
/// unless the model generates it, so a generous value costs only the risk of a
/// long generation, never tokens.
///
/// The field itself cannot become `Option` to mean "let the API decide": the
/// Anthropic Messages API requires `max_tokens` on every request. opencode
/// encodes exactly that asymmetry — `max_tokens: Schema.Number` (required) for
/// Anthropic against `Schema.optional` for both OpenAI protocols — and always
/// sends a value, falling back to the model's declared output limit
/// (`protocols/anthropic-messages.ts:510,546`). A per-model table is the same
/// eventual answer here; one safe default is the honest v0.
pub const DEFAULT_MAX_TOKENS: u32 = 64_000;
/// A neutral reasoning-effort level, mapped per-wire (ADR-0007).
///
/// Grok Build proves this shape: one neutral enum with per-backend mappings
/// (`to_messages_api()` → Anthropic budget, `to_responses_api()` → OpenAI effort).
/// Tiers fragment per vendor/model generation (OpenAI `none…xhigh`, codex
/// `minimal…xhigh`, grok stores per-model allowed-effort lists), so the ladder
/// covers the observed union and `Other` passes vendor-specific strings
/// through verbatim (ADR-0007 amendment 2026-07-19). Wires surface the API's
/// own error on unsupported tiers — never silently clamp (silent clamping
/// would corrupt eval comparisons).
/// Where the wire should place prompt-cache breakpoints (ADR-0007).
///
/// A reserved seam: the actual `cache_control` placement (Anthropic: one marker on
/// the last message + ≤4 on system blocks) lives in the wire (Task 12).