projectAssistantRecord function

TrajectoryAssistantRecord projectAssistantRecord({
  1. required MessageRecord record,
  2. required AssistantMessage message,
  3. required int index,
  4. required String recordId,
  5. required int turn,
  6. required int step,
  7. DateTime? previousTime,
  8. TrajectoryRequestDetail? requestDetail,
})

Projects an assistant message record into a fully-populated message row.

Wall-clock timing degrades to what the record carries: the completion time is exact, while the request start falls back to the previous ledger record's stamp (TS durationSeconds(node.time, recordedStart ?? prevAbsTime)); TTFT needs the streaming event stream and stays null.

Implementation

TrajectoryAssistantRecord projectAssistantRecord({
  required MessageRecord record,
  required AssistantMessage message,
  required int index,
  required String recordId,
  required int turn,
  required int step,
  DateTime? previousTime,
  TrajectoryRequestDetail? requestDetail,
}) {
  final failed =
      message.stopReason == StopReason.error ||
      message.stopReason == StopReason.aborted;
  final output = textOfBlocks(message.content);
  final thinking = thinkingOfBlocks(message.content);
  final sourceBlocks = [
    for (final block in message.content) trajectorySourceBlock(block),
  ];
  return TrajectoryAssistantRecord(
    index: index,
    recordId: recordId,
    messageId: record.id,
    turn: turn,
    step: step,
    provider: message.provider,
    model: message.model,
    usage: message.usage,
    inputTokens: message.usage.input,
    cacheReadTokens: message.usage.cacheRead,
    cacheWriteTokens: message.usage.cacheWrite,
    outputTokens: message.usage.output,
    reasoningTokens: message.usage.reasoning,
    completedTime: message.timestamp,
    sourceBlocks: sourceBlocks,
    outputBlocks: sourceBlocks,
    displayText: assistantDisplayText(message.content),
    outputDetail: output.isEmpty ? null : output,
    thinkingDetail: thinking.isEmpty ? null : thinking,
    timeSeconds: trajectoryDurationSeconds(message.timestamp, previousTime),
    isError: failed,
    errorMessage: message.errorMessage,
    requestDetail: requestDetail,
  );
}