feat(llm): a request carries how much the model thinks, in each provider's field

LlmRequest.effort (LlmEffort: low, medium, high, xhigh, max, Anthropic's
names) goes as Anthropic's output_config.effort, as reasoning.effort to
the Responses API and OpenRouter, and as reasoning_effort to OpenAI's chat
completions, Gemini and any other host. endpoint.efforts says which
levels a host takes (Gemini low to high, Mistral none); send refuses
another before anything goes, the fake client too. LlmEffort.outputCeiling
gives the room for output each level wants, as thinking counts towards
the ceiling (Halkyon Learn's ADR 0021, D63).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-10-26 14:53:48 +01:00
commit 0590a4b43d
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -157,6 +157,71 @@ void main() {
expect(body['user'], 'p_8Zq3');
});
group('the effort (D63)', () {
LlmRequest at(LlmEffort effort) => LlmRequest(
messages: _question.messages,
maxOutputTokens: 4096,
effort: effort,
);
test(
'goes as reasoning_effort to OpenAI, Gemini and any other host',
() async {
for (final endpoint in [_openAi, _gemini, _ollama]) {
final body = await _bodyFor(endpoint, at(LlmEffort.medium));
expect(body['reasoning_effort'], 'medium', reason: endpoint.host);
expect(body.keys, isNot(contains('reasoning')));
}
},
);
test('goes as reasoning.effort to OpenRouter', () async {
final body = await _bodyFor(_openRouter, at(LlmEffort.max));
expect(body['reasoning'], {'effort': 'max'});
expect(body.keys, isNot(contains('reasoning_effort')));
});
test('is left out without one', () async {
for (final endpoint in [_openAi, _gemini, _openRouter, _ollama]) {
final body = await _bodyFor(endpoint);
expect(
body.keys,
isNot(anyOf(contains('reasoning_effort'), contains('reasoning'))),
reason: endpoint.host,
);
}
});
test("is each host's levels: Gemini's low to high, Mistral's none, "
'every level elsewhere', () {
expect(_gemini.efforts, {
LlmEffort.low,
LlmEffort.medium,
LlmEffort.high,
});
expect(_mistral.efforts, isEmpty);
for (final endpoint in [_openAi, _openRouter, _ollama]) {
expect(
endpoint.efforts,
LlmEffort.values.toSet(),
reason: endpoint.host,
);
}
});
test('a level the host takes not is refused before anything goes', () {
final client = LlmClient(httpClient: replying(_documented['text']!));
expect(
() => client.send(_mistral, at(LlmEffort.low)),
throwsArgumentError,
);
expect(
() => client.send(_gemini, at(LlmEffort.xhigh)),
throwsArgumentError,
);
});
});
test(
'to any other host: what Ollama, vLLM and llama.cpp all take',
() async {