assemble method

  1. @override
Future<StartupContextResult?> assemble({
  1. required String action,
  2. required StartupContextConfig config,
  3. String? timezone,
})
override

Assemble startup context for the given session action.

Returns null if startup context is disabled or the action doesn't trigger injection.

Implementation

@override
Future<StartupContextResult?> assemble({
  required String action,
  required StartupContextConfig config,
  String? timezone,
}) async {
  if (!shouldApply(action, config)) return null;

  final entries = <StartupContextEntry>[];
  int totalChars = 0;
  bool anyTruncated = false;

  for (final provider in _providers) {
    if (totalChars >= config.maxTotalChars) break;

    final rawEntries = await provider.loadEntries(
      config: config,
      timezone: timezone,
    );

    for (final entry in rawEntries) {
      final remaining = config.maxTotalChars - totalChars;
      if (remaining <= 0) break;

      final charLimit = config.maxFileChars.clamp(0, remaining);
      if (entry.content.length <= charLimit) {
        entries.add(entry);
        totalChars += entry.charCount;
      } else {
        final truncated = _truncateToLimit(entry.content, charLimit);
        entries.add(StartupContextEntry(
          source: entry.source,
          content: truncated,
          originalBytes: entry.originalBytes,
          truncated: true,
          sourceTimestamp: entry.sourceTimestamp,
        ));
        totalChars += truncated.length;
        anyTruncated = true;
      }
    }
  }

  if (entries.isEmpty) {
    return StartupContextResult(
      prelude: '',
      entries: const [],
      totalChars: 0,
      anyTruncated: false,
      triggerAction: action,
    );
  }

  final prelude = _assemblePrelude(entries, config);

  return StartupContextResult(
    prelude: prelude,
    entries: entries,
    totalChars: totalChars,
    anyTruncated: anyTruncated,
    triggerAction: action,
  );
}