rewrite method

  1. @override
Future<String> rewrite({
  1. required String instruction,
  2. required String text,
})
override

Asks the model to rewrite text according to instruction.

Plain text in, plain text out — no tool call, and nothing is executed as a result. Used to polish a generated changelog, where the model's job is editorial rather than deciding what the CLI does.

Throws AiException on transport or protocol failure.

Implementation

@override
Future<String> rewrite({
  required String instruction,
  required String text,
}) async {
  final body = await post(
    '${config.baseUrl}/chat/completions',
    {
      'model': config.model,
      'max_tokens': config.maxTokens,
      'messages': [
        {'role': 'system', 'content': instruction},
        {'role': 'user', 'content': text},
      ],
    },
    {
      'Content-Type': 'application/json',
      if (config.hasApiKey) 'Authorization': 'Bearer ${config.apiKey}',
    },
  );

  final choices = body['choices'];
  if (choices is! List || choices.isEmpty) {
    throw AiException('$name returned no choices');
  }
  // Shape first: reading a field off a non-map choice would surface as a raw
  // Dart type error rather than "this endpoint sent something unexpected".
  final choice = choices.first;
  if (choice is! Map) {
    throw AiException('$name returned a malformed choice');
  }
  if (choice['finish_reason'] == 'length') {
    throw AiException(
      'the reply was cut off by the token limit — raise `max-tokens` '
      '(currently ${config.maxTokens}) and try again',
    );
  }
  final message = choice['message'];
  if (message is! Map) {
    throw AiException('$name returned a malformed choice');
  }

  final content = message['content']?.toString().trim() ?? '';
  if (content.isEmpty) throw AiException('$name returned nothing to use');
  return content;
}