import json
import os
import requests
import sys
from pathlib import Path
def load_config():
config_path = Path.home() / ".aicommit.json"
if not config_path.exists():
print(f"Config file not found at {config_path}")
sys.exit(1)
with open(config_path, 'r') as f:
return json.load(f)
def get_openrouter_api_key():
config = load_config()
for provider in config.get('providers', []):
if 'OpenRouter' in str(provider):
provider_data = list(provider.values())[0] if 'api_key' in provider_data:
return provider_data['api_key']
elif isinstance(provider, dict) and provider.get('provider') in ['openrouter', 'simple_free_openrouter']:
if 'api_key' in provider:
return provider['api_key']
print("No OpenRouter API key found in config")
sys.exit(1)
def get_free_models(api_key):
headers = {
"Authorization": f"Bearer {api_key}",
"HTTP-Referer": "https://suenot.github.io/aicommit/",
"X-Title": "aicommit"
}
response = requests.get("https://openrouter.ai/api/v1/models", headers=headers)
if not response.ok:
print(f"API request failed: {response.status_code} - {response.text}")
sys.exit(1)
models_data = response.json()
free_models = []
all_models = []
for model in models_data.get('data', []):
model_id = model.get('id')
if not model_id:
continue
model_size = "Unknown"
for size_pattern in ["253b", "235b", "200b", "124b", "70b", "80b", "90b", "72b", "65b",
"40b", "32b", "30b", "24b", "20b", "16b", "14b", "13b", "12b", "11b",
"10b", "9b", "8b", "7b", "6b", "5b", "4b", "3b", "2b", "1b"]:
if size_pattern.lower() in model_id.lower():
model_size = size_pattern.upper()
break
all_models.append({
'id': model_id,
'name': model.get('name', ''),
'size': model_size,
'context_length': model.get('context_length', 0),
'pricing': {
'prompt': model.get('pricing', {}).get('prompt', 0),
'completion': model.get('pricing', {}).get('completion', 0)
},
'free': model.get('free', False),
'free_tokens': model.get('free_tokens', 0)
})
is_free = False
if ":free" in model_id:
is_free = True
elif model.get('free', False):
is_free = True
elif model.get('free_tokens', 0) > 0:
is_free = True
elif model.get('pricing', {}).get('prompt', 1) == 0 and model.get('pricing', {}).get('completion', 1) == 0:
is_free = True
if is_free:
free_models.append({
'id': model_id,
'name': model.get('name', ''),
'size': model_size,
'context_length': model.get('context_length', 0),
'free_tokens': model.get('free_tokens', 0)
})
return free_models, all_models
def main():
try:
api_key = get_openrouter_api_key()
free_models, all_models = get_free_models(api_key)
output_dir = Path('openrouter_models')
output_dir.mkdir(exist_ok=True)
with open(output_dir / 'free_models.json', 'w') as f:
json.dump(free_models, f, indent=2)
with open(output_dir / 'all_models.json', 'w') as f:
json.dump(all_models, f, indent=2)
with open(output_dir / 'free_models.txt', 'w') as f:
f.write("OpenRouter Free Models:\n\n")
sorted_models = sorted(free_models,
key=lambda x: (0 if x.get('size', 'Unknown') == 'Unknown' else
int(x.get('size', '0B').lower().replace('b', ''))),
reverse=True)
for model in sorted_models:
f.write(f"ID: {model.get('id')}\n")
f.write(f"Name: {model.get('name', 'Unknown')}\n")
f.write(f"Size: {model.get('size', 'Unknown')}\n")
f.write(f"Context Length: {model.get('context_length')}\n")
f.write(f"Free Tokens: {model.get('free_tokens', 0)}\n")
f.write("-" * 50 + "\n\n")
print(f"Found {len(free_models)} free models out of {len(all_models)} total models")
print(f"Results saved to {output_dir} directory")
print("\nTop 10 Free Models (by size):")
for i, model in enumerate(sorted(free_models,
key=lambda x: (0 if x.get('size', 'Unknown') == 'Unknown' else
int(x.get('size', '0B').lower().replace('b', ''))),
reverse=True)[:10]):
print(f"{i+1}. {model['id']} ({model.get('size', 'Unknown')})")
except Exception as e:
print(f"Error: {e}")
sys.exit(1)
if __name__ == "__main__":
main()