( sweepConfig: SweepConfigFile, options: CliOptions, )
| 1573 | // ============================================================================ |
| 1574 | |
| 1575 | async function runSweep( |
| 1576 | sweepConfig: SweepConfigFile, |
| 1577 | options: CliOptions, |
| 1578 | ): Promise<VendorSweepResult[]> { |
| 1579 | const allResults: VendorSweepResult[] = []; |
| 1580 | const maxTokens = sweepConfig.maxTokens ?? 128; |
| 1581 | const globalDelay = sweepConfig.delayMs ?? options.delay; |
| 1582 | |
| 1583 | for (const [vendorName, vendorConfig] of Object.entries(sweepConfig.vendors)) { |
| 1584 | const access = vendorConfig.access; |
| 1585 | |
| 1586 | // Filter by --dialect CLI arg |
| 1587 | if (options.dialect && access.dialect !== options.dialect) |
| 1588 | continue; |
| 1589 | |
| 1590 | console.log(`\n${COLORS.bright}${COLORS.cyan}=== ${vendorName.toUpperCase()} (${access.dialect}) ===${COLORS.reset}\n`); |
| 1591 | |
| 1592 | // 1. List models for this vendor |
| 1593 | let models: ModelDescriptionSchema[]; |
| 1594 | try { |
| 1595 | models = await listModelsRunDispatch(access); |
| 1596 | // print first...last |
| 1597 | console.log(` Found ${COLORS.bright}${models.length}${COLORS.reset} models: ${models.length > 2 ? models[0].id + ' ... ' + models[models.length - 1].id : models.map(m => m.id).join(', ')}`); |
| 1598 | } catch (error: any) { |
| 1599 | console.log(` ${COLORS.red}Failed to list models: ${error.message}${COLORS.reset}`); |
| 1600 | continue; |
| 1601 | } |
| 1602 | |
| 1603 | if (models.length === 0) { |
| 1604 | console.log(` ${COLORS.yellow}No models found, skipping${COLORS.reset}`); |
| 1605 | continue; |
| 1606 | } |
| 1607 | |
| 1608 | // 2. Filter out symlink models (unless --include-symlinks) |
| 1609 | if (!options.includeSymlinks) { |
| 1610 | const beforeCount = models.length; |
| 1611 | models = models.filter(m => !m.label.includes('🔗')); |
| 1612 | if (models.length < beforeCount) |
| 1613 | console.log(` Excluded ${beforeCount - models.length} symlink models`); |
| 1614 | } |
| 1615 | |
| 1616 | // 2b. Filter out duplicate models with idVariant (keep base model, or first variant if no base) |
| 1617 | { |
| 1618 | // const beforeCount = models.length; |
| 1619 | // Sort so base models (no idVariant) come before variants |
| 1620 | models.sort((a, b) => (a.idVariant ? 1 : 0) - (b.idVariant ? 1 : 0)); |
| 1621 | const seenIds = new Set<string>(); |
| 1622 | const excludedVariants: string[] = []; |
| 1623 | models = models.filter(m => { |
| 1624 | if (seenIds.has(m.id)) { |
| 1625 | if (m.idVariant) excludedVariants.push(`${m.id}::${m.idVariant}`); |
| 1626 | return false; |
| 1627 | } |
| 1628 | seenIds.add(m.id); |
| 1629 | return true; |
| 1630 | }); |
| 1631 | if (excludedVariants.length > 0) |
| 1632 | console.log(` Excluded ${excludedVariants.length} variant models: ${COLORS.dim}${excludedVariants.join(', ')}${COLORS.reset}`); |
no test coverage detected