buildProviderQueueChain function
List<ChainEntry>
buildProviderQueueChain(
- List<
ProviderQueueEntry> entries, { - required Map<
String, String> secrets, - StreamFunction streamFactory()?,
- List<
String> ? skipped,
Builds the ChainEntry list for a resolved queue: one model per entry
(catalog defaults + the entry's overrides), a single key stack per
entry from its apiKeyEnv (the _2/_3 stack convention rides along
free), and the catalog stream factory bound per key.
Entries with no configured key are SKIPPED (the roles precedent) and
reported in skipped; a queue that skips everything throws
ConfigException.
Implementation
List<ChainEntry> buildProviderQueueChain(
List<ProviderQueueEntry> entries, {
required Map<String, String> secrets,
StreamFunction Function(String kind, String apiKey)? streamFactory,
List<String>? skipped,
}) {
final skipped_ = skipped ?? <String>[];
final factory = streamFactory ?? providerStreamFunction;
final chain = <ChainEntry>[];
for (final entry in entries) {
final keyEnv = entry.apiKeyEnv;
if (keyEnv == null) {
throw ConfigException(
'queue entry ${entry.label} has no apiKeyEnv — keys never ride in '
'the queue blob; name the env var holding the key',
);
}
final stack = collectKeyStack(secrets, keyEnv);
if (stack.isEmpty) {
skipped_.add('${entry.label} (missing API key: set $keyEnv)');
continue;
}
final ring = ApiKeyRing(baseName: keyEnv, credentials: stack);
final spec = catalogProvider(
queueKindCatalogName(entry.providerType, entry.baseUrl),
)!;
final inner = factory(spec.kind, stack.first.value);
chain.add(
ChainEntry(
model: buildCatalogModel(
spec.name,
entry.model,
baseUrl: entry.baseUrl,
contextWindow: entry.contextWindow,
maxTokens: entry.maxTokens,
),
keyRing: ring,
streamForKey: (apiKey) =>
inner, // single entry-bound adapter; the key is baked in
),
);
}
if (chain.isEmpty) {
throw ConfigException(
'the provider queue has no usable entry: ${skipped_.join('; ')}',
);
}
return chain;
}