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>
82 lines
2.4 KiB
Dart
82 lines
2.4 KiB
Dart
import 'package:halkyon_llm/halkyon_llm.dart';
|
|
import 'package:halkyon_llm/testing.dart';
|
|
import 'package:test/test.dart';
|
|
|
|
final _endpoint = LlmEndpoint(
|
|
protocol: LlmProtocol.openai,
|
|
model: 'm',
|
|
apiKey: 'k',
|
|
);
|
|
final _request = LlmRequest(
|
|
messages: [
|
|
LlmMessage.user([const LlmText('?')]),
|
|
],
|
|
maxOutputTokens: 10,
|
|
);
|
|
|
|
void main() {
|
|
group('FakeLlmClient', () {
|
|
test('answers with the text scripted, in pieces, and keeps what it was '
|
|
'sent', () async {
|
|
final client = FakeLlmClient()..replyText('Hallo Welt');
|
|
final events = await client.send(_endpoint, _request).toList();
|
|
expect(
|
|
events.whereType<LlmTextDelta>().map((delta) => delta.text).join(),
|
|
'Hallo Welt',
|
|
);
|
|
expect((events.last as LlmFinished).message.text, 'Hallo Welt');
|
|
expect(client.sent.single, (_endpoint, _request));
|
|
expect(client.allReplied, isTrue);
|
|
});
|
|
|
|
test('fails as scripted, with what was counted', () {
|
|
final client = FakeLlmClient()
|
|
..fail(
|
|
LlmFailureKind.rateLimited,
|
|
usage: const LlmUsage(inputTokens: 5, outputTokens: 0),
|
|
);
|
|
expect(
|
|
client.send(_endpoint, _request).toList(),
|
|
throwsA(
|
|
isA<LlmFailure>()
|
|
.having((f) => f.kind, 'kind', LlmFailureKind.rateLimited)
|
|
.having((f) => f.usage.inputTokens, 'input', 5),
|
|
),
|
|
);
|
|
});
|
|
|
|
test('counts answers cancelled before they ended', () async {
|
|
final client = FakeLlmClient()..replyText('Hallo Welt');
|
|
await client.send(_endpoint, _request).first;
|
|
expect(client.cancelled, 1);
|
|
});
|
|
|
|
test('refuses a request nothing was scripted for', () {
|
|
expect(
|
|
() => FakeLlmClient().send(_endpoint, _request),
|
|
throwsStateError,
|
|
);
|
|
});
|
|
|
|
test("refuses an effort the endpoint's host takes not, as HTTP's does", () {
|
|
final client = FakeLlmClient()..replyText('Hallo');
|
|
expect(
|
|
() => client.send(
|
|
LlmEndpoint(
|
|
protocol: LlmProtocol.openai,
|
|
model: 'm',
|
|
apiKey: 'k',
|
|
baseUrl: 'https://api.mistral.ai/v1',
|
|
),
|
|
LlmRequest(
|
|
messages: _request.messages,
|
|
maxOutputTokens: 10,
|
|
effort: LlmEffort.low,
|
|
),
|
|
),
|
|
throwsArgumentError,
|
|
);
|
|
expect(client.sent, isEmpty);
|
|
});
|
|
});
|
|
}
|