From d43077afa9db9824e1c7392353706d93de6189b7 Mon Sep 17 00:00:00 2001 From: Evan Date: Fri, 24 Apr 2026 00:02:33 +0900 Subject: [PATCH] fix(providers): remove ~anthropic, skip ~ prefixes in sync script (#69) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(providers): remove ~anthropic, skip ~ prefixes in sync script OpenRouter uses ~ prefixes for internal auto-routing aliases (e.g. ~anthropic). These are not real providers — they already route through openrouter.toml. The generated ~anthropic.toml was confusing (looked like a stale backup) and redundant with the existing openrouter provider. - Delete providers/~anthropic.toml - Skip provider IDs starting with ~ in sync-pricing.py --create-missing * fix(providers): remove morph, aider, kwaipilot - morph: specialized code-editing/patching tool, not a general LLM provider - aider: CLI meta-tool wrapper (base_url empty), redundant with claude-code/codex-cli/gemini-cli/qwen-code - kwaipilot: Kwai internal coding assistant routed via OpenRouter, niche * fix(sync): add morph/aider/kwaipilot to SKIP_PROVIDERS to prevent re-creation * feat(sync): merge OpenRouter-only providers into openrouter.toml Instead of generating standalone .toml files that just wrap the OpenRouter endpoint, merge their models directly into openrouter.toml with the standard 'openrouter/{provider}/{model}' ID convention. - Add _build_model_fields() and _model_lines() helpers to deduplicate model rendering between standalone and merged paths - Add merge_into_openrouter() that appends new models idempotently - generate_provider_toml() now only runs for providers in PROVIDER_API - --create-missing routes OpenRouter-only providers to merge_into_openrouter * fix(providers): remove 14 OpenRouter-only standalone files These providers have no direct public API and all route through openrouter.ai/api/v1. Per the new sync-pricing.py policy, their models will be merged into openrouter.toml on the next CI run instead of living in separate files that just wrap the OpenRouter endpoint. Removed: allenai, deepcogito, essentialai, inclusionai, inflection, liquid, meituan, nex-agi, nousresearch, prime-intellect, relace, switchpoint, tngtech, writer * fix(providers): remove 7 niche providers with no driver support No dedicated LLM driver code exists for these providers — they rely purely on OpenAI-compatible passthrough with no special handling. Removing them reduces registry noise; users can still reach them via openrouter.toml if needed. Removed: microsoft, ibm-granite, xiaomi, upstage, inception, aion-labs, arcee-ai * fix(providers): remove ai21, chutes, venice All three use ApiFormat::OpenAI with no special handling — pure passthrough. No registry entry needed; users can reach them via openrouter.toml or by adding a custom provider. * docs(providers): rewrite README with full provider catalog and inclusion criteria - List all 46 providers grouped by category with descriptions - Document why each provider exists (direct API, unique endpoint, dedicated driver, local, CLI) - Add inclusion criteria section explaining when to create standalone files vs merging into openrouter.toml - Document sync script routing logic - Update model counts: 49→46 providers, 339→232 models * docs: add comprehensive READMEs for all registry sections + deepinfra provider - agents/README.md: 32 agents across 7 categories with capability field reference - channels/README.md: 44 channels across 5 categories with protocol reference table - hands/README.md: 18 hands across 5 categories with HAND.toml format guide - mcp/README.md: 33 MCP servers across 5 categories with transport/auth format - plugins/README.md: 12 plugins with hook protocol documentation - skills/README.md: 60 skills across 9 categories with SKILL.md format guide - providers/deepinfra.toml: add DeepInfra serverless inference (5 models) --- README.md | 6 +- agents/README.md | 189 +++++++++++++++++++----- channels/README.md | 145 +++++++++++++++++- hands/README.md | 261 +++++++++++++++++++++------------ mcp/README.md | 164 +++++++++++++++------ plugins/README.md | 113 +++++++++----- providers/README.md | 167 ++++++++++++++++++--- providers/ai21.toml | 48 ------ providers/aider.toml | 35 ----- providers/aion-labs.toml | 48 ------ providers/allenai.toml | 50 ------- providers/arcee-ai.toml | 78 ---------- providers/chutes.toml | 76 ---------- providers/deepcogito.toml | 18 --- providers/deepinfra.toml | 69 +++++++++ providers/essentialai.toml | 18 --- providers/ibm-granite.toml | 18 --- providers/inception.toml | 18 --- providers/inclusionai.toml | 18 --- providers/inflection.toml | 28 ---- providers/kwaipilot.toml | 18 --- providers/liquid.toml | 38 ----- providers/meituan.toml | 18 --- providers/microsoft.toml | 28 ---- providers/morph.toml | 28 ---- providers/nex-agi.toml | 18 --- providers/nousresearch.toml | 68 --------- providers/prime-intellect.toml | 18 --- providers/relace.toml | 28 ---- providers/switchpoint.toml | 18 --- providers/tngtech.toml | 18 --- providers/upstage.toml | 18 --- providers/venice.toml | 49 ------- providers/writer.toml | 18 --- providers/xiaomi.toml | 38 ----- providers/~anthropic.toml | 18 --- scripts/sync-pricing.py | 166 +++++++++++++++------ skills/README.md | 189 +++++++++++++++++++----- 38 files changed, 1146 insertions(+), 1215 deletions(-) delete mode 100644 providers/ai21.toml delete mode 100644 providers/aider.toml delete mode 100644 providers/aion-labs.toml delete mode 100644 providers/allenai.toml delete mode 100644 providers/arcee-ai.toml delete mode 100644 providers/chutes.toml delete mode 100644 providers/deepcogito.toml create mode 100644 providers/deepinfra.toml delete mode 100644 providers/essentialai.toml delete mode 100644 providers/ibm-granite.toml delete mode 100644 providers/inception.toml delete mode 100644 providers/inclusionai.toml delete mode 100644 providers/inflection.toml delete mode 100644 providers/kwaipilot.toml delete mode 100644 providers/liquid.toml delete mode 100644 providers/meituan.toml delete mode 100644 providers/microsoft.toml delete mode 100644 providers/morph.toml delete mode 100644 providers/nex-agi.toml delete mode 100644 providers/nousresearch.toml delete mode 100644 providers/prime-intellect.toml delete mode 100644 providers/relace.toml delete mode 100644 providers/switchpoint.toml delete mode 100644 providers/tngtech.toml delete mode 100644 providers/upstage.toml delete mode 100644 providers/venice.toml delete mode 100644 providers/writer.toml delete mode 100644 providers/xiaomi.toml delete mode 100644 providers/~anthropic.toml diff --git a/README.md b/README.md index 9c6e666..4cb6bc0 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,8 @@ This repository is the **single source of truth** for all installable content de | [Hands](#hands) | 14 | User-facing "apps" — agent + tools + settings + dashboard | | [Agents](#agents) | 32 | Autonomous agent definitions with model config and tools | | [MCP Servers](#mcp-servers) | 25 | MCP server connections (GitHub, Slack, DBs, etc.) | -| [Providers](#providers) | 49 | LLM provider & model metadata with pricing | -| [Models](#providers) | 339 | Individual model definitions across all providers | +| [Providers](#providers) | 46 | LLM provider & model metadata with pricing | +| [Models](#providers) | 232 | Individual model definitions across all providers | | [Aliases](#aliases) | 70 | Short names mapped to canonical model IDs | | [Plugins](#plugins) | 10 | Memory, guardrails, and conversation plugins | | [Skills](#skills) | 2 | Reusable prompt templates and Python scripts | @@ -44,7 +44,7 @@ librefang-registry/ ├── providers/ # LLM provider & model metadata │ ├── anthropic.toml │ ├── openai.toml -│ └── ... (49 providers, 339 models) +│ └── ... (46 providers, 232 models) ├── plugins/ # Memory, guardrails, and utility plugins │ ├── episodic-memory/ │ ├── guardrails/ diff --git a/agents/README.md b/agents/README.md index 08d21fc..2b4b20b 100644 --- a/agents/README.md +++ b/agents/README.md @@ -1,63 +1,178 @@ -# Agents +# Agents Registry -Autonomous agent definitions for LibreFang. Each agent is a directory containing an `agent.toml` manifest. +Agent templates for LibreFang. Each entry is a ready-to-install agent definition with a pre-configured system prompt, model settings, capability declarations, and routing aliases. -## Structure +These are the reference agents shipped with the registry. You can install them as-is, override individual fields (model, system_prompt, tools) after installation, or use them as `base` templates inside a Hand. + +## File Format + +Each agent lives in its own subdirectory containing a single `agent.toml`: ``` agents/ -├── hello-world/agent.toml -├── researcher/agent.toml -├── coder/agent.toml +├── coder/ +│ └── agent.toml +├── orchestrator/ +│ └── agent.toml └── ... ``` -## agent.toml Format +### agent.toml format ```toml -name = "agent-name" # Must match directory name -version = "0.1.0" -description = "What this agent does" -author = "author-name" -module = "builtin:chat" # Runtime module - -[model] -provider = "default" -model = "default" -max_tokens = 4096 -temperature = 0.7 -system_prompt = """Behavioral instructions for the agent.""" +name = "coder" # must match directory name +version = "0.4.3-beta3-20260314" +description = "Expert software engineer. Reads, writes, and analyzes code." +author = "librefang" +module = "builtin:chat" # runtime module — builtin:chat for all current agents [metadata.routing] -aliases = ["exact match phrases"] -weak_aliases = ["keyword hints"] +aliases = ["write code", "fix bug", "implement feature"] # exact activation phrases +weak_aliases = ["refactor", "patch", "code change"] # keyword hints + +[model] +provider = "default" # default = use LibreFang's configured primary provider +model = "default" +api_key_env = "GEMINI_API_KEY" # optional override: use this key env var +max_tokens = 8192 +temperature = 0.3 +system_prompt = """You are Coder, an expert software engineer...""" + +[[fallback_models]] # optional: try these providers on failure +provider = "default" +model = "default" +api_key_env = "GROQ_API_KEY" + +[schedule] # optional: continuous or cron activation +continuous = { check_interval_secs = 120 } [resources] -max_llm_tokens_per_hour = 100000 +max_llm_tokens_per_hour = 200000 +max_concurrent_tools = 10 [capabilities] -tools = ["web_search", "file_read"] -network = ["*"] +tools = ["file_read", "file_write", "file_list", "shell_exec", "web_search", "web_fetch", + "memory_store", "memory_recall"] +network = ["*"] # "*" = all, or list specific domains memory_read = ["*"] -memory_write = ["self.*"] +memory_write = ["self.*"] # "self.*" = own namespace only +shell = ["cargo *", "rustc *", "git *", "npm *", "python *"] # shell command allowlist agent_spawn = false +agent_message = [] # agents this agent may message + +[i18n.zh] +name = "编码工程师" +description = "资深软件工程师:阅读、编写与分析代码。" ``` -## Current Agents (33) +## Installing and Using Agents -| Agent | Description | -|-------|-------------| -| assistant | Default conversational assistant | -| researcher | Deep research with web search | -| coder | Code generation and editing | -| hello-world | Friendly greeting agent for new users | -| ... | See each directory for details | +```bash +# List all available agent templates +librefang catalog agents + +# Install an agent from the registry +librefang agent install coder + +# Install with a custom name +librefang agent install coder --name my-coder + +# List installed agents +librefang agent list + +# Send a message to an installed agent +librefang agent message coder "Implement a binary search function in Rust" + +# Remove an agent +librefang agent remove my-coder +``` + +Agents can also be used as base templates in a Hand by setting `base = "coder"` in `HAND.toml`. + +## All Agents (33 total) + +### Development + +| Name | Description | Key Tools | +|------|-------------|-----------| +| architect | System architect. Designs software architectures, evaluates trade-offs, creates technical specifications. | file_read, file_write, web_search, web_fetch | +| code-reviewer | Senior code reviewer. Reviews PRs, identifies issues, suggests improvements with production standards. | file_read, shell_exec, web_search | +| coder | Expert software engineer. Reads, writes, and analyzes code. | file_read, file_write, shell_exec, web_search | +| debugger | Expert debugger. Traces bugs, analyzes stack traces, performs root cause analysis. | file_read, shell_exec, web_search | +| devops-lead | DevOps lead. Manages CI/CD, infrastructure, deployments, monitoring, and incident response. | shell_exec, file_read, web_search | +| ops | DevOps agent. Monitors systems, runs diagnostics, manages deployments. | shell_exec, file_read, web_search | +| test-engineer | Quality assurance engineer. Designs test strategies, writes tests, validates correctness. | file_read, file_write, shell_exec | + +### Research and Analysis + +| Name | Description | Key Tools | +|------|-------------|-----------| +| academic-researcher | Academic research agent. Searches scholarly papers, summarizes findings, and generates literature reviews. | web_search, web_fetch, file_write | +| analyst | Data analyst. Processes data, generates insights, creates reports. | file_read, web_search, web_fetch | +| data-scientist | Data scientist. Analyzes datasets, builds models, creates visualizations, performs statistical analysis. | file_read, file_write, shell_exec | +| researcher | Research agent. Fetches web content and synthesizes information. | web_search, web_fetch, memory_store | + +### Writing and Documentation + +| Name | Description | Key Tools | +|------|-------------|-----------| +| doc-writer | Technical writer. Creates documentation, README files, API docs, tutorials, and architecture guides. | file_read, file_write, web_fetch | +| writer | Content writer. Creates documentation, articles, and technical writing. | file_read, file_write, web_search | + +### Orchestration + +| Name | Description | Key Capabilities | +|------|-------------|-----------------| +| orchestrator | Meta-agent that decomposes complex tasks, delegates to specialist agents, and synthesizes results. | agent_spawn, agent_send, agent_list, agent_kill | +| planner | Project planner. Creates project plans, breaks down epics, estimates effort, identifies risks and dependencies. | file_read, file_write, web_search | + +### Business and Operations + +| Name | Description | Key Tools | +|------|-------------|-----------| +| customer-support | Customer support agent for ticket handling, issue resolution, and customer communication. | memory_store, memory_recall, web_search | +| email-assistant | Email triage, drafting, scheduling, and inbox management agent. | memory_store, memory_recall, file_write | +| legal-assistant | Legal assistant agent for contract review, legal research, compliance checking, and document drafting. | file_read, file_write, web_search | +| meeting-assistant | Meeting notes, action items, agenda preparation, and follow-up tracking agent. | memory_store, memory_recall, file_write | +| recruiter | Recruiting agent for resume screening, candidate outreach, job description writing, and hiring pipeline management. | web_search, file_read, memory_store | +| sales-assistant | Sales assistant agent for CRM updates, outreach drafting, pipeline management, and deal tracking. | memory_store, memory_recall, web_search | +| security-auditor | Security specialist. Reviews code for vulnerabilities, checks configurations, performs threat modeling. | file_read, shell_exec, web_search | + +### Personal Productivity + +| Name | Description | Key Tools | +|------|-------------|-----------| +| assistant | General-purpose assistant agent. The default agent for everyday tasks, questions, and conversations. | file_read, file_write, web_search, memory_store | +| health-tracker | Wellness tracking agent for health metrics, medication reminders, fitness goals, and lifestyle habits. | memory_store, memory_recall, file_write | +| hello-world | A friendly greeting agent that can read files, search the web, and answer everyday questions. | file_read, web_search, web_fetch | +| home-automation | Smart home control agent for IoT device management, automation rules, and home monitoring. | shell_exec, memory_store, web_fetch | +| personal-finance | Personal finance agent for budget tracking, expense analysis, savings goals, and financial planning. | file_read, memory_store, web_search | +| recipe-assistant | Cooking assistant that helps with recipes, meal plans, ingredient substitutions, and portion adjustments. | web_search, memory_recall, file_write | +| social-media | Social media content creation, scheduling, and engagement strategy agent. | web_fetch, web_search, file_write | +| translator | Multi-language translation agent for document translation, localization, and cross-cultural communication. | file_read, file_write, web_fetch | +| travel-planner | Trip planning agent for itinerary creation, booking research, budget estimation, and travel logistics. | web_search, web_fetch, memory_store | +| tutor | Teaching and explanation agent for learning, tutoring, and educational content creation. | web_search, memory_recall, file_write | + +## Capability Reference + +| Capability field | Values | Effect | +|-----------------|--------|--------| +| `tools` | list of tool names | Which built-in tools the agent may invoke | +| `network` | `["*"]` or domain list | Outbound HTTP domain allowlist | +| `memory_read` | `["*"]` or namespace list | Which memory namespaces the agent can read | +| `memory_write` | `["self.*"]` or `["*"]` | Which memory namespaces the agent can write | +| `shell` | glob patterns | Shell command allowlist (e.g. `"cargo *"`) | +| `agent_spawn` | `true` / `false` | Whether the agent can spawn child agents | +| `agent_message` | `["*"]` or agent name list | Which agents this agent may send messages to | ## Adding a New Agent -1. Create `agents//agent.toml` -2. Ensure `name` matches the directory name -3. Run `python scripts/validate.py` -4. Submit a PR +1. Create `agents//agent.toml` — `name` must match the directory name. +2. Set `module = "builtin:chat"` unless you have a custom runtime module. +3. Write a focused `system_prompt` — clear role definition, methodology, and constraints. +4. Declare only the tools and capabilities the agent actually needs. +5. Add `[metadata.routing]` aliases so the router can activate the agent by intent. +6. Run `python scripts/validate.py`. +7. Submit a PR. See [CONTRIBUTING.md](../CONTRIBUTING.md) for the full guide. diff --git a/channels/README.md b/channels/README.md index d482207..87f88e3 100644 --- a/channels/README.md +++ b/channels/README.md @@ -1,7 +1,146 @@ # Channel Adapters Registry -This directory contains TOML metadata files for all supported LibreFang channel adapters. +Channel adapters connect LibreFang agents to external messaging platforms. Each adapter in this directory is a flat `.toml` file describing the platform, its communication protocol, and any credentials required to operate. -Each `.toml` file describes a single channel adapter including its name, description, category, protocol, and relevant links. These files are used by the LibreFang registry to discover and display available channel integrations. +Once a channel is configured, agents can receive messages from and send messages to that platform without any code changes — the adapter handles protocol translation. -See `../templates/channel.toml` for the file format template. +## File Format + +Each channel is a single `.toml` file. The filename (without `.toml`) must match the `id` field. + +```toml +id = "telegram" +name = "Telegram" +description = "Telegram Bot API adapter for sending and receiving messages" +category = "messaging" # messaging | enterprise | social | developer | iot +tags = ["popular"] +icon = "lucide:smartphone" +protocol = "bot-api" # see Protocol Reference below + +[i18n.zh] +name = "Telegram" +description = "Telegram Bot API 适配器,收发消息" + +[metadata] +url = "https://telegram.org" +docs = "https://core.telegram.org/bots/api" +``` + +## Protocol Reference + +| Protocol | Description | +|----------|-------------| +| `bot-api` | Platform-specific bot HTTP API (e.g. Telegram Bot API) | +| `websocket` | Long-lived WebSocket connection (e.g. Slack RTM, Discord Gateway) | +| `webhook` | Agent receives POST requests from the platform | +| `rest-api` | Polling or push via generic HTTP REST | +| `imap` | Email protocols (IMAP for receive, SMTP for send) | +| `irc` | Internet Relay Chat protocol | +| `matrix` | Matrix client-server API | +| `mqtt` | MQTT pub/sub protocol for IoT messaging | +| `xmpp` | Extensible Messaging and Presence Protocol | + +## Configuring a Channel + +```bash +# List all available channel adapters +librefang catalog channels + +# Install a channel adapter +librefang channel install telegram + +# Configure credentials for a channel +librefang channel configure telegram + +# Attach a channel to an agent +librefang channel attach telegram --agent assistant + +# List configured channels +librefang channel list + +# Remove a channel +librefang channel remove telegram +``` + +## All Channel Adapters (45 total) + +### Messaging + +| ID | Name | Protocol | Description | +|----|------|----------|-------------| +| discord | Discord | websocket | Discord bot adapter for sending and receiving messages in Discord servers and channels | +| email | Email | imap | Email adapter for sending and receiving messages via SMTP and IMAP protocols | +| irc | IRC | irc | IRC adapter for connecting to Internet Relay Chat networks and channels | +| keybase | Keybase | rest-api | Keybase adapter for encrypted messaging via the Keybase chat API | +| line | LINE | webhook | LINE Messaging API adapter for sending and receiving messages on the LINE platform | +| matrix | Matrix | matrix | Matrix adapter for decentralized messaging via the Matrix client-server API | +| messenger | Facebook Messenger | webhook | Facebook Messenger adapter for sending and receiving messages via the Messenger Platform | +| nostr | Nostr | websocket | Nostr adapter for publishing and reading events on the Nostr decentralized protocol | +| qq | QQ | websocket | QQ bot adapter for messaging within Tencent QQ groups and channels | +| signal | Signal | rest-api | Signal adapter for secure end-to-end encrypted messaging via Signal CLI | +| telegram | Telegram | bot-api | Telegram Bot API adapter for sending and receiving messages | +| threema | Threema | rest-api | Threema Gateway adapter for secure messaging via the Threema platform | +| viber | Viber | webhook | Viber bot adapter for sending and receiving messages via the Viber Bot API | +| wechat | WeChat | rest-api | WeChat Official Account adapter for messaging on the WeChat platform | +| whatsapp | WhatsApp | rest-api | WhatsApp Business API adapter for sending and receiving messages on WhatsApp | +| xmpp | XMPP | xmpp | XMPP adapter for messaging via the Extensible Messaging and Presence Protocol | + +### Enterprise + +| ID | Name | Protocol | Description | +|----|------|----------|-------------| +| dingtalk | DingTalk | webhook | DingTalk bot adapter for sending messages to DingTalk groups and conversations | +| feishu | Feishu (Lark) | webhook | Feishu (Lark) bot adapter for messaging within the Feishu collaboration platform | +| flock | Flock | webhook | Flock bot adapter for team messaging and notifications in Flock workspaces | +| google_chat | Google Chat | webhook | Google Chat adapter for sending messages and cards to Google Workspace conversations | +| guilded | Guilded | websocket | Guilded bot adapter for messaging in Guilded servers and channels | +| mattermost | Mattermost | websocket | Mattermost adapter for team messaging and notifications in Mattermost workspaces | +| pumble | Pumble | webhook | Pumble adapter for team messaging and notifications in Pumble workspaces | +| rocketchat | Rocket.Chat | rest-api | Rocket.Chat adapter for messaging in self-hosted Rocket.Chat instances | +| slack | Slack | websocket | Slack bot adapter for sending and receiving messages in Slack workspaces | +| teams | Microsoft Teams | webhook | Microsoft Teams adapter for messaging and notifications in Teams channels | +| twist | Twist | rest-api | Twist adapter for async team communication in Twist workspaces | +| webex | Cisco Webex | webhook | Cisco Webex adapter for messaging and notifications in Webex spaces | +| wecom | WeCom (WeChat Work) | webhook | WeCom (WeChat Work) adapter for enterprise messaging within WeCom organizations | +| zulip | Zulip | rest-api | Zulip adapter for topic-based team messaging in Zulip organizations | + +### Social + +| ID | Name | Protocol | Description | +|----|------|----------|-------------| +| bluesky | Bluesky | rest-api | Bluesky AT Protocol adapter for posting and reading from the decentralized social network | +| linkedin | LinkedIn | rest-api | LinkedIn adapter for posting updates and messages via the LinkedIn API | +| mastodon | Mastodon | rest-api | Mastodon adapter for posting toots and reading timelines on Mastodon instances | +| reddit | Reddit | rest-api | Reddit adapter for posting and reading content via the Reddit API | +| twitch | Twitch | irc | Twitch adapter for reading and sending messages in Twitch stream chats | + +### Developer + +| ID | Name | Protocol | Description | +|----|------|----------|-------------| +| discourse | Discourse | rest-api | Discourse forum adapter for posting topics and replies via the Discourse API | +| gitter | Gitter | rest-api | Gitter adapter for developer chat rooms linked to GitHub repositories | +| revolt | Revolt | websocket | Revolt adapter for messaging in the open-source Revolt chat platform | +| webhook | Webhook | webhook | Generic webhook adapter for sending and receiving messages via HTTP callbacks | + +### IoT / Self-Hosted + +| ID | Name | Protocol | Description | +|----|------|----------|-------------| +| gotify | Gotify | rest-api | Gotify adapter for sending push notifications to a self-hosted Gotify server | +| mqtt | MQTT | mqtt | MQTT adapter for publishing and subscribing to messages on MQTT brokers | +| mumble | Mumble | websocket | Mumble adapter for text messaging in Mumble voice communication servers | +| nextcloud | Nextcloud Talk | rest-api | Nextcloud Talk adapter for messaging within self-hosted Nextcloud instances | +| ntfy | ntfy | rest-api | ntfy adapter for sending push notifications via the ntfy pub-sub service | + +## Adding a New Channel Adapter + +1. Create `channels/.toml` — the filename must match the `id` field. +2. Set `category` to one of: `messaging`, `enterprise`, `social`, `developer`, `iot`. +3. Set `protocol` to the appropriate value from the Protocol Reference table above. +4. Add `[metadata]` with `url` and `docs` links. +5. Add `[i18n.*]` blocks for supported locales. +6. Run `python scripts/validate.py`. +7. Submit a PR. + +See [CONTRIBUTING.md](../CONTRIBUTING.md) for the full guide. diff --git a/hands/README.md b/hands/README.md index d69db98..e977b6e 100644 --- a/hands/README.md +++ b/hands/README.md @@ -1,130 +1,197 @@ -# Hands +# Hands Registry -Hand definitions for LibreFang. Hands are pre-packaged capability bundles that compose **agents**, **tools**, **skills**, **MCP servers**, **workflows**, and **plugins** into a working application. +Hands are pre-packaged capability bundles that compose agents, tools, skills, MCP servers, and plugins into a working application. Installing a hand gives you a complete, ready-to-use workflow — not just a single agent. > "You have many hands helping you." -## Structure +A hand can contain one agent (single-agent) or multiple coordinated agents (multi-agent). Each agent in a multi-agent hand can have its own role-specific skills, model config, and capability restrictions. + +## File Format + +Each hand lives in its own subdirectory: ``` hands/ +├── researcher/ +│ ├── HAND.toml # required: hand definition +│ └── SKILL.md # optional: shared reference knowledge for all agents ├── devteam/ -│ ├── HAND.toml # Hand definition -│ ├── SKILL-pm.md # Per-agent reference knowledge (PM) -│ ├── SKILL-engineer.md # Per-agent reference knowledge (Engineer) -│ └── SKILL-qa.md # Per-agent reference knowledge (QA) -├── browser/ │ ├── HAND.toml -│ └── SKILL.md # Shared reference knowledge (all agents) -└── ... +│ ├── SKILL-pm.md # optional: role-specific knowledge for PM agent +│ ├── SKILL-engineer.md # optional: role-specific knowledge for Engineer agent +│ └── SKILL-qa.md # optional: role-specific knowledge for QA agent ``` -## Composition Model - -A hand composes registry resources — it doesn't reinvent them: - -| Resource | How to compose | Example | -|----------|----------------|---------| -| **Agent templates** | `base = "coder"` on `[agents.*]` | Inherit prompt, model config, fallbacks from `agents/coder/agent.toml` | -| **Tools** | `tools = [...]` at hand level | All agents get these built-in tools | -| **Skills** | `skills = [...]` at hand level | Skill allowlist (empty = all) | -| **MCP servers** | `mcp_servers = [...]` at hand level | Agent interacts via MCP tools, not hardcoded API calls | -| **Workflows** | `workflow_run` tool in agent prompts | Agent calls `workflow_run bug-triage` at runtime | -| **Plugins** | `allowed_plugins = [...]` at hand level | Plugin allowlist (empty = all) | -| **Per-agent skills** | `SKILL-{role}.md` files | Different reference knowledge per agent role | -| **Per-agent capabilities** | `[agents.*.capabilities]` | Fine-grained shell/network/memory per agent | - -## HAND.toml Format +### HAND.toml format ```toml -id = "hand-id" -name = "Hand Name" -description = "What this hand does" -category = "development" -icon = "🔧" +id = "researcher" +version = "1.1.1" +name = "Researcher Hand" +description = "Autonomous deep researcher — exhaustive investigation, cross-referencing, fact-checking, and structured reports" +category = "productivity" # productivity | development | data | content | communication +icon = "lucide:flask-conical" -# ─── Resource composition ──────────────────────────────────── -tools = ["shell_exec", "file_read", "web_fetch", "workflow_run"] -mcp_servers = ["github", "sentry"] -skills = [] # empty = all -allowed_plugins = ["todo-tracker"] +# Tools available to all agents in this hand +tools = [ + "shell_exec", "file_read", "file_write", "web_fetch", "web_search", + "memory_store", "memory_recall", "knowledge_query", "event_publish", +] -# ─── Requirements ──────────────────────────────────────────── -[[requires]] -key = "git" -requirement_type = "binary" -check_value = "git" +# MCP servers all agents can use +mcp_servers = ["github"] -# ─── Settings ──────────────────────────────────────────────── -[[settings]] -key = "repo_url" -setting_type = "text" -default = "" +# Skills allowlist (empty = all available) +skills = [] -# ─── Agents ────────────────────────────────────────────────── +# Plugin allowlist +allowed_plugins = ["todo-tracker", "auto-summarizer"] -# Multi-agent with base template inheritance: -[agents.main] -coordinator = true -base = "planner" # inherits from agents/planner/agent.toml -invoke_hint = "Task coordination" - -[agents.main.model] -system_prompt = """Custom prompt for this hand...""" - -[agents.main.capabilities] -shell = ["gh *", "git *"] # preserved by kernel (not overwritten) - -# Single-agent (legacy): -# [agent] -# name = "my-agent" -# system_prompt = """...""" - -# ─── Routing ───────────────────────────────────────────────── +# ─── Routing ────────────────────────────────────────────────────────────────── [routing] -aliases = ["activate phrases"] -weak_aliases = ["keyword hints"] +aliases = ["deep research", "investigate", "fact check"] # exact activation phrases +weak_aliases = ["research", "look into"] # keyword hints -# ─── Dashboard ─────────────────────────────────────────────── +# ─── Configurable settings ──────────────────────────────────────────────────── +[[settings]] +key = "research_depth" +label = "Research Depth" +description = "How exhaustive each investigation should be" +setting_type = "select" # select | toggle | text +default = "thorough" + +[[settings.options]] +value = "quick" +label = "Quick (5-10 sources, 1 pass)" + +[[settings.options]] +value = "thorough" +label = "Thorough (20-30 sources, cross-referenced)" + +# ─── Single-agent definition ────────────────────────────────────────────────── +[agent] +name = "researcher" +base = "researcher" # inherits from agents/researcher/agent.toml + +[agent.model] +system_prompt = """Custom prompt override...""" + +# ─── Multi-agent definition (alternative to [agent]) ───────────────────────── +[agents.pm] +coordinator = true +base = "planner" # inherits from agents/planner/agent.toml +invoke_hint = "Task coordination and issue triage" + +[agents.engineer] +base = "coder" +invoke_hint = "Implementation" + +[agents.qa] +base = "test-engineer" +invoke_hint = "Quality assurance and validation" + +# ─── Dashboard metrics ──────────────────────────────────────────────────────── [dashboard] [[dashboard.metrics]] -label = "Tasks Done" -memory_key = "metric_key" +label = "Reports Written" +memory_key = "metric_reports_written" format = "number" -# ─── i18n ──────────────────────────────────────────────────── +# ─── i18n ───────────────────────────────────────────────────────────────────── [i18n.zh] -name = "中文名" -description = "中文描述" +name = "研究员" +description = "自主深度研究员 — 详尽调查、交叉核实、事实核查与结构化报告" ``` -## Current Hands (15) +## Installing and Using Hands -| Hand | Category | Agents | Description | -|------|----------|--------|-------------| -| analytics | data | multi | Data analytics, visualization, and automated reporting | -| apitester | development | single | API testing, endpoint discovery, and load testing | -| browser | productivity | single | Web navigation, form filling, and multi-step web tasks | -| clip | content | multi | Long-form video to short clips with captions | -| collector | data | multi | Intelligence collection and change detection | -| **devteam** | **development** | **multi** | **Autonomous dev team — PM + Engineer + QA with base templates** | -| devops | development | multi | CI/CD management, monitoring, and incident response | -| lead | data | multi | Lead generation, enrichment, and scoring | -| linkedin | communication | multi | LinkedIn content creation and networking | -| predictor | data | single | Signal collection and calibrated predictions | -| reddit | communication | multi | Subreddit monitoring and content posting | -| researcher | productivity | multi | Deep research, fact-checking, and reports | -| strategist | productivity | multi | Market research and competitive analysis | -| trader | data | multi | Market intelligence and risk management | -| twitter | communication | multi | Twitter/X content creation and scheduling | +```bash +# List all available hands +librefang catalog hands + +# Install a hand +librefang hand install researcher + +# Install with a specific agent name +librefang hand install researcher --name my-researcher + +# List installed hands +librefang hand list + +# Remove a hand +librefang hand remove my-researcher +``` + +## All Hands (18 total) + +### Productivity + +| ID | Name | Category | Description | +|----|------|----------|-------------| +| researcher | Researcher Hand | productivity | Autonomous deep researcher — exhaustive investigation, cross-referencing, fact-checking, and structured reports | +| strategist | Strategist Hand | productivity | Autonomous strategy analyst — market research, competitive analysis, business planning, and strategic recommendations | +| wiki | Wiki Hand | productivity | LLM-maintained personal knowledge base — builds an Obsidian-compatible wiki from raw sources with provenance tracking | +| browser | Browser Hand | productivity | Autonomous web browser — navigates sites, fills forms, clicks buttons, and completes multi-step web tasks | + +### Development + +| ID | Name | Category | Description | +|----|------|----------|-------------| +| devteam | Dev Team | development | Autonomous software development team — PM triages issues, Engineer implements, QA validates | +| devops | DevOps Hand | development | Autonomous DevOps engineer — CI/CD management, infrastructure monitoring, deployment automation, and incident response | +| apitester | API Tester Hand | development | Autonomous API testing agent — endpoint discovery, request validation, load testing, and regression detection | + +### Data + +| ID | Name | Category | Description | +|----|------|----------|-------------| +| analytics | Analytics Hand | data | Autonomous data analytics agent — data collection, analysis, visualization, dashboards, and automated reporting | +| collector | Collector Hand | data | Autonomous intelligence collector — monitors any target continuously with change detection and knowledge graphs | +| lead | Lead Hand | data | Autonomous lead generation — discovers, enriches, and delivers qualified leads on a schedule | +| predictor | Predictor Hand | data | Autonomous future predictor — collects signals, builds reasoning chains, makes calibrated predictions, and tracks accuracy | +| trader | Trading Hand | data | Autonomous market intelligence and trading engine — multi-signal analysis, adversarial bull/bear reasoning, and strict risk management | + +### Content + +| ID | Name | Category | Description | +|----|------|----------|-------------| +| clip | Clip Hand | content | Turns long-form video into viral short clips with captions and thumbnails | +| creator | Creator Hand | content | AI media studio — generates images, videos, music, and speech from text prompts | + +### Communication + +| ID | Name | Category | Description | +|----|------|----------|-------------| +| linkedin | LinkedIn Hand | communication | Autonomous LinkedIn manager — profile optimization, content creation, networking, and professional engagement | +| reddit | Reddit Hand | communication | Autonomous Reddit manager — monitors subreddits, posts content, replies to threads, and tracks engagement | +| twitter | Twitter Hand | communication | Autonomous Twitter/X manager — content creation, scheduled posting, engagement, and performance tracking | + +### Data (additional) + +| ID | Name | Category | Description | +|----|------|----------|-------------| +| clip | Clip Hand | content | Turns long-form video into viral short clips with captions and thumbnails | + +## Resource Composition Summary + +| Resource | How to compose | Notes | +|----------|----------------|-------| +| Agent templates | `base = "coder"` on `[agents.*]` | Inherits prompt, model config, fallbacks from `agents/coder/agent.toml` | +| Tools | `tools = [...]` at hand level | All agents in the hand share these built-in tools | +| Skills | `skills = [...]` at hand level | Empty list means all available skills are allowed | +| MCP servers | `mcp_servers = [...]` at hand level | Agent interacts via MCP tools, not hardcoded API calls | +| Plugins | `allowed_plugins = [...]` at hand level | Empty list means all installed plugins are allowed | +| Per-agent knowledge | `SKILL-{role}.md` files | Different reference prompts per agent role | +| Per-agent capabilities | `[agents.*.capabilities]` | Fine-grained shell / network / memory per agent | ## Adding a New Hand -1. Create `hands//HAND.toml` -2. Add `SKILL.md` (shared) or `SKILL-{role}.md` (per-agent) for reference knowledge -3. Use `base = "agent-name"` to inherit from existing agent templates in `agents/` -4. Set `mcp_servers`, `skills`, `allowed_plugins` for resource composition -5. Ensure `id` matches the directory name -6. Submit a PR +1. Create `hands//HAND.toml` with at least `id`, `name`, `description`, and `category`. +2. Add `SKILL.md` (shared) or `SKILL-{role}.md` (per-agent) files for reference knowledge. +3. Use `base = "agent-name"` in each `[agents.*]` block to inherit from existing agent templates. +4. Specify `mcp_servers`, `skills`, and `allowed_plugins` for resource composition. +5. Ensure `id` matches the directory name. +6. Run `python scripts/validate.py`. +7. Submit a PR. See [CONTRIBUTING.md](../CONTRIBUTING.md) for the full guide. diff --git a/mcp/README.md b/mcp/README.md index 558765d..3bc0abf 100644 --- a/mcp/README.md +++ b/mcp/README.md @@ -1,70 +1,148 @@ -# MCP Servers +# MCP Servers Registry -MCP (Model Context Protocol) server templates for LibreFang. Each entry connects LibreFang to an external service (GitHub, Slack, databases, etc.). +MCP (Model Context Protocol) servers connect LibreFang agents to external services. Each entry in this directory is a single `.toml` file describing an MCP server: how to launch it, what credentials it requires, and which category of functionality it provides. -## Structure +When an agent has an MCP server attached, the server's tools appear automatically in the agent's tool list alongside built-in tools like `file_read` and `web_search`. -``` -mcp/ -├── github.toml -├── slack.toml -├── postgresql.toml -└── ... -``` +## File Format -## MCP Server TOML Format +Each MCP server is a flat `.toml` file. The filename (without `.toml`) must match the `id` field. ```toml -id = "service-id" # Must match filename (without .toml) -name = "Service Name" -description = "What this MCP server provides" -category = "devtools" # devtools | communication | storage | monitoring | data -icon = "🐙" -tags = ["relevant", "tags"] +id = "github" # must match filename +name = "GitHub" +description = "Access GitHub repos, issues, PRs, and organizations" +category = "devtools" # devtools | data | cloud | communication | productivity | ai +icon = "lucide:github" +tags = ["git", "vcs", "code"] -[transport] # MCP server transport config -type = "stdio" # "stdio" or "sse" +[transport] +type = "stdio" # stdio | sse command = "npx" -args = ["-y", "@pkg/mcp-server"] +args = ["-y", "@modelcontextprotocol/server-github@2025.4.8"] -[[required_env]] # Required environment variables -name = "SERVICE_API_KEY" -label = "API Key" -help = "How to obtain this key" +[[required_env]] # repeat block for each required credential +name = "GITHUB_PERSONAL_ACCESS_TOKEN" +label = "GitHub Personal Access Token" +help = "A fine-grained or classic PAT with repo and read:org scopes" is_secret = true -get_url = "https://..." +get_url = "https://github.com/settings/tokens" -[oauth] # Optional: OAuth config +[oauth] # optional: OAuth flow config provider = "github" -scopes = ["repo"] -auth_url = "https://..." -token_url = "https://..." +scopes = ["repo", "read:org"] +auth_url = "https://github.com/login/oauth/authorize" +token_url = "https://github.com/login/oauth/access_token" [health_check] interval_secs = 60 unhealthy_threshold = 3 setup_instructions = """ -Step-by-step setup guide for users. +1. Go to https://github.com/settings/tokens and create a Personal Access Token. +2. Paste the token into the GITHUB_PERSONAL_ACCESS_TOKEN field. +3. Alternatively, use the OAuth flow to authorize LibreFang directly. """ + +[i18n.zh] +name = "GitHub" +description = "通过官方 MCP 服务器访问 GitHub 仓库、Issue、Pull Request 与组织。" ``` -## Current MCP Servers (25) +## Installing an MCP Server -| MCP Server | Category | Service | -|------------|----------|---------| -| github | devtools | GitHub repos, issues, PRs | -| slack | communication | Slack messaging | -| notion | productivity | Notion pages and databases | -| postgresql | storage | PostgreSQL database | -| ... | | See each file for details | +```bash +# List all available MCP servers +librefang catalog mcp + +# Install an MCP server and attach it to an agent +librefang mcp install github +librefang mcp attach github --agent coder + +# Or specify the agent when installing +librefang mcp install github --agent coder + +# Set required credentials +librefang config set-env GITHUB_PERSONAL_ACCESS_TOKEN ghp_xxx + +# List attached MCP servers for an agent +librefang mcp list --agent coder + +# Remove an MCP server from an agent +librefang mcp detach github --agent coder +``` + +## All MCP Servers (33 total) + +### Development Tools (devtools) + +| ID | Name | Transport | Credentials Required | Description | +|----|------|-----------|---------------------|-------------| +| bitbucket | Bitbucket | stdio (npx) | `BITBUCKET_*` | Access Bitbucket repositories, pull requests, and pipelines | +| fetch | Fetch | stdio (npx) | none | Fetch any web URL and receive its content as clean Markdown | +| filesystem | Filesystem | stdio (npx) | none | Read, write, search, and manage local files | +| git | Git | stdio (npx) | none | Inspect local Git repos — commits, diffs, branches, blame | +| github | GitHub | stdio (npx) | `GITHUB_PERSONAL_ACCESS_TOKEN` | Access GitHub repos, issues, PRs, and organizations | +| gitlab | GitLab | stdio (npx) | `GITLAB_*` | Access GitLab projects, MRs, issues, and CI/CD pipelines | +| jira | Jira | stdio (npx) | `JIRA_*` | Access Jira issues, projects, boards, and sprints | +| linear | Linear | stdio (npx) | `LINEAR_API_KEY` | Manage Linear issues, projects, cycles, and teams | +| puppeteer | Puppeteer | stdio (npx) | none | Control headless Chrome — navigate, screenshot, scrape | +| sentry | Sentry | stdio (npx) | `SENTRY_AUTH_TOKEN` | Monitor Sentry error tracking, issues, and releases | + +### Data + +| ID | Name | Transport | Credentials Required | Description | +|----|------|-----------|---------------------|-------------| +| elasticsearch | Elasticsearch | stdio (npx) | `ELASTICSEARCH_*` | Search and manage Elasticsearch indices and documents | +| google-maps | Google Maps | stdio (npx) | `GOOGLE_MAPS_API_KEY` | Geocoding, directions, distance matrix, and place search | +| mongodb | MongoDB | stdio (npx) | `MONGODB_CONNECTION_STRING` | Query and manage MongoDB databases and collections | +| postgresql | PostgreSQL | stdio (npx) | `POSTGRES_CONNECTION_STRING` | Query and manage PostgreSQL databases | +| redis | Redis | stdio (npx) | `REDIS_URL` | Access and manage Redis key-value stores | +| sqlite-mcp | SQLite | stdio (npx) | none | Query and manage local SQLite databases | + +### Cloud + +| ID | Name | Transport | Credentials Required | Description | +|----|------|-----------|---------------------|-------------| +| aws | AWS | stdio (npx) | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` | Manage S3, EC2, Lambda, and other AWS resources | +| azure-mcp | Azure | stdio (npx) | `AZURE_*` | Manage Azure VMs, Storage, and App Services | +| gcp-mcp | GCP | stdio (npx) | `GOOGLE_APPLICATION_CREDENTIALS` | Manage GCP Compute, Cloud Storage, and BigQuery | + +### Communication + +| ID | Name | Transport | Credentials Required | Description | +|----|------|-----------|---------------------|-------------| +| discord-mcp | Discord | stdio (npx) | `DISCORD_TOKEN` | Access Discord servers, channels, and messages | +| slack | Slack | stdio (npx) | `SLACK_BOT_TOKEN` | Access Slack channels, messages, and users | +| teams-mcp | Microsoft Teams | stdio (npx) | `TEAMS_*` | Access Teams channels, chats, and messages | + +### Productivity + +| ID | Name | Transport | Credentials Required | Description | +|----|------|-----------|---------------------|-------------| +| dropbox | Dropbox | stdio (npx) | `DROPBOX_ACCESS_TOKEN` | Access and manage Dropbox files and folders | +| gmail | Gmail | stdio (npx) | `GMAIL_*` | Read, send, and manage Gmail messages and drafts | +| google-calendar | Google Calendar | stdio (npx) | `GOOGLE_*` | Manage Google Calendar events and availability | +| google-drive | Google Drive | stdio (npx) | `GOOGLE_*` | Browse, search, and read files from Google Drive | +| notion | Notion | stdio (npx) | `NOTION_API_KEY` | Access and manage Notion pages, databases, and blocks | +| time | Time | stdio (npx) | none | Get current time, convert timezones, calculate differences | +| todoist | Todoist | stdio (npx) | `TODOIST_API_TOKEN` | Manage Todoist tasks, projects, and labels | + +### AI + +| ID | Name | Transport | Credentials Required | Description | +|----|------|-----------|---------------------|-------------| +| brave-search | Brave Search | stdio (npx) | `BRAVE_API_KEY` | Perform web searches using the Brave Search API | +| exa-search | Exa Search | stdio (npx) | `EXA_API_KEY` | AI-powered neural search and web content retrieval | +| memory | Memory | stdio (npx) | none | Persistent knowledge graph for facts and relationships across sessions | +| sequential-thinking | Sequential Thinking | stdio (npx) | none | Structured multi-step reasoning with revisable thought chains | ## Adding a New MCP Server -1. Create `mcp/.toml` -2. Ensure `id` matches the filename -3. Test the MCP server command locally -4. Run `python scripts/validate.py` -5. Submit a PR +1. Create `mcp/.toml` — the filename must match the `id` field. +2. Test the transport command locally: run `npx -y ` and verify it starts without errors. +3. List all `[[required_env]]` entries so the UI can prompt users for credentials. +4. Run `python scripts/validate.py`. +5. Submit a PR. See [CONTRIBUTING.md](../CONTRIBUTING.md) for the full guide. diff --git a/plugins/README.md b/plugins/README.md index c2e725e..a2e29a2 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -1,71 +1,114 @@ -# Plugins +# Plugins Registry -Plugin packages for LibreFang. Plugins extend agent behavior through lifecycle hooks -- they can inject memories, modify context, or perform side effects during conversations. +Plugins extend agent behavior through lifecycle hooks. They can inject memories into context before a turn, perform side-effect processing after a turn, or do both. Unlike skills (which add knowledge) or MCP servers (which add tools), plugins run as Python scripts that intercept the agent loop. -## Structure +## File Format + +Each plugin lives in its own subdirectory: ``` plugins/ └── / - ├── plugin.toml # Plugin manifest + ├── plugin.toml # required: plugin manifest ├── hooks/ - │ ├── ingest.py # Called on user message - │ └── after_turn.py # Called after each turn - └── requirements.txt # Python dependencies + │ ├── ingest.py # called on each incoming user message + │ └── after_turn.py # called after each completed agent turn + └── requirements.txt # Python dependencies (prefer stdlib-only) ``` -## plugin.toml Format +### plugin.toml format ```toml -name = "plugin-name" # Must match directory name +name = "episodic-memory" # must match directory name version = "0.1.0" -description = "What this plugin does" -author = "author-name" +description = "Episode-based memory segmentation and recall for cross-conversation context continuity" +author = "librefang" [hooks] -ingest = "hooks/ingest.py" # Receives user message, can return memories -after_turn = "hooks/after_turn.py" # Post-turn processing +ingest = "hooks/ingest.py" # optional +after_turn = "hooks/after_turn.py" # optional + +[i18n.zh] +name = "情景记忆" +description = "基于情景的记忆分段与召回,实现跨会话的上下文延续。" ``` ## Hook Protocol -Hooks communicate via stdin/stdout JSON: +Hooks communicate with the agent runtime via stdin/stdout JSON lines. ### ingest hook +Receives the incoming user message and returns zero or more memory objects to inject into the agent's context for this turn: + ``` -stdin: {"type": "ingest", "agent_id": "...", "message": "user message"} -stdout: {"type": "ingest_result", "memories": [{"content": "..."}]} +stdin: {"type": "ingest", "agent_id": "abc123", "session_id": "...", "message": "user message text"} +stdout: {"type": "ingest_result", "memories": [{"content": "Relevant fact from earlier session"}]} ``` ### after_turn hook +Receives the full turn transcript after the agent responds. Used for persistence (saving summaries, updating profiles, appending logs): + ``` -stdin: {"type": "after_turn", "agent_id": "...", "messages": [...]} +stdin: {"type": "after_turn", "agent_id": "abc123", "session_id": "...", "messages": [...]} stdout: {"type": "ok"} ``` -## Current Plugins (10) +## Installing and Using Plugins -| Plugin | Hooks | Description | -|--------|-------|-------------| -| auto-summarizer | ingest, after_turn | Running conversation summary for long context compression | -| context-decay | ingest, after_turn | Time-based memory decay with relevance scoring for natural forgetting | -| conversation-logger | after_turn | Logs conversations to JSONL files for auditing and analytics | -| episodic-memory | ingest, after_turn | Episode-based conversation segmentation and cross-session recall | -| guardrails | ingest | Safety filter detecting PII, prompt injection, and credential exposure | -| keyword-memory | ingest | Extracts keywords and named entities as contextual memories | -| sentiment-tracker | ingest | Analyzes user sentiment and injects emotional context | -| todo-tracker | ingest, after_turn | Detects, persists, and recalls action items from conversations | -| topic-memory | ingest, after_turn | Topic-aware keyword clustering with cross-conversation context recall | -| user-profile | ingest, after_turn | Persistent user profiling from conversation patterns for personalization | +```bash +# List all available plugins +librefang catalog plugins + +# Install a plugin globally +librefang plugin install episodic-memory + +# Enable a plugin for a specific agent +librefang plugin enable episodic-memory --agent coder + +# Disable a plugin for an agent +librefang plugin disable episodic-memory --agent coder + +# List plugins active for an agent +librefang plugin list --agent coder +``` + +Hands can also declare an `allowed_plugins` list in `HAND.toml`, which restricts which installed plugins are active within that hand. + +## All Plugins (12 total) + +| Name | Version | Hooks | Description | +|------|---------|-------|-------------| +| auto-summarizer | 0.1.0 | ingest, after_turn | Maintains a running conversation summary to help agents handle long conversations without losing context | +| context-decay | 0.1.0 | ingest, after_turn | Time-based memory decay with relevance scoring for natural context forgetting | +| conversation-logger | 0.1.0 | after_turn | Logs all conversations to JSONL files for auditing, analytics, and debugging | +| episodic-memory | 0.1.0 | ingest, after_turn | Episode-based memory segmentation and recall for cross-conversation context continuity | +| guardrails | 0.1.0 | ingest | Safety filter that detects potentially harmful content patterns and injects warnings into agent context | +| keyword-memory | 0.1.0 | ingest | Extracts keywords and named entities from user messages and returns them as contextual memories | +| mempalace-indexer | 0.3.0 | ingest, after_turn | Auto-indexes conversations into MemPalace and recalls relevant memories — no API keys, no cloud | +| sentiment-tracker | 0.1.0 | ingest | Analyzes user message sentiment and injects emotional context so agents can respond with appropriate tone | +| todo-tracker | 0.1.0 | ingest, after_turn | Detects action items and tasks mentioned in conversations, persists them, and recalls them as context | +| topic-memory | 0.1.0 | ingest, after_turn | Topic-aware memory recall with keyword clustering for cross-conversation context | +| user-profile | 0.1.0 | ingest, after_turn | Persistent user profiling from conversation patterns for personalized agent responses | + +Note: the `guardrails` and `mempalace-indexer` plugins have no `after_turn` hook; `conversation-logger` has no `ingest` hook. + +## Hook Execution Order + +For each agent turn, the runtime executes hooks in this order: + +1. All `ingest` hooks run (in plugin installation order) — memories are collected and merged +2. Agent turn executes with the injected context +3. All `after_turn` hooks run (in plugin installation order) ## Adding a New Plugin -1. Create `plugins//plugin.toml` -2. Add hook scripts in `hooks/` -3. List dependencies in `requirements.txt` (prefer stdlib-only) -4. Run `python scripts/validate.py` -5. Submit a PR +1. Create `plugins//plugin.toml` with `name`, `version`, `description`, and `[hooks]`. +2. Add hook scripts under `hooks/` for each declared hook. +3. Keep hooks fast (under 500 ms) — they run synchronously on every turn. +4. List Python dependencies in `requirements.txt`; prefer standard library where possible. +5. Run `python scripts/validate.py`. +6. Submit a PR. See [CONTRIBUTING.md](../CONTRIBUTING.md) for the full guide. diff --git a/providers/README.md b/providers/README.md index 8569f28..d57ed4c 100644 --- a/providers/README.md +++ b/providers/README.md @@ -1,16 +1,123 @@ # Providers -LLM provider and model metadata for LibreFang. Each provider file defines the provider's API configuration and all available models with pricing, context windows, and capability flags. +LLM provider and model metadata for LibreFang. Each `.toml` file defines one provider's API configuration and all its available models with pricing, context windows, and capability flags. -## Structure +**Current state: 46 providers, 232+ models** -``` -providers/ -├── anthropic.toml -├── openai.toml -├── groq.toml -└── ... (46 providers, 220+ models) -``` +--- + +## Provider Categories + +### Frontier / Major Cloud APIs + +| ID | Display Name | Base URL | API Key Env | Models | Description | +|----|-------------|----------|-------------|--------|-------------| +| `anthropic` | Anthropic | `https://api.anthropic.com` | `ANTHROPIC_API_KEY` | 7 | Claude family (Haiku / Sonnet / Opus); native Anthropic wire protocol, not OpenAI-compatible | +| `openai` | OpenAI | `https://api.openai.com/v1` | `OPENAI_API_KEY` | 15 | GPT-4.x, o-series reasoning, image generation, TTS; also the fallback for codex-cli | +| `gemini` | Google Gemini | `https://generativelanguage.googleapis.com` | `GEMINI_API_KEY` | 6 | Gemini 2.x family; native Google GenerativeLanguage protocol | +| `xai` | xAI | `https://api.x.ai/v1` | `XAI_API_KEY` | 7 | Grok-3 family from Elon Musk's xAI | +| `mistral` | Mistral AI | `https://api.mistral.ai/v1` | `MISTRAL_API_KEY` | 3 | Mistral Large / Small / Codestral; European frontier models | +| `cohere` | Cohere | `https://api.cohere.com/v2` | `COHERE_API_KEY` | 4 | Command R+ family; strong RAG and tool-use models | +| `deepseek` | DeepSeek | `https://api.deepseek.com/v1` | `DEEPSEEK_API_KEY` | 2 | DeepSeek-V3 (chat) + R1 (reasoning); extremely cost-effective | +| `meta-llama` | Meta Llama | `https://api.llama.com/v1` | `LLAMA_API_KEY` | 4 | Official Meta Llama API — direct access to Llama 3.x | +| `perplexity` | Perplexity AI | `https://api.perplexity.ai` | `PERPLEXITY_API_KEY` | 4 | Sonar family with live web search built in | + +### Fast Inference / Compute Clouds + +| ID | Display Name | Base URL | API Key Env | Models | Description | +|----|-------------|----------|-------------|--------|-------------| +| `groq` | Groq | `https://api.groq.com/openai/v1` | `GROQ_API_KEY` | 3 | GroqChip hardware; ~10× faster than GPU inference for supported models | +| `cerebras` | Cerebras | `https://api.cerebras.ai/v1` | `CEREBRAS_API_KEY` | 4 | Wafer-scale chip inference; best-in-class throughput for Llama | +| `sambanova` | SambaNova | `https://api.sambanova.ai/v1` | `SAMBANOVA_API_KEY` | 3 | Reconfigurable Dataflow Unit (RDU) inference; fast Llama variants | +| `fireworks` | Fireworks AI | `https://api.fireworks.ai/inference/v1` | `FIREWORKS_API_KEY` | 5 | Serverless open-model hosting; fast cold-start | +| `together` | Together AI | `https://api.together.xyz/v1` | `TOGETHER_API_KEY` | 8 | Open-model hosting (Llama, Qwen, Mistral) + fine-tuning API | +| `nvidia-nim` | NVIDIA NIM | `https://integrate.api.nvidia.com/v1` | `NVIDIA_API_KEY` | 26 | NVIDIA NIM microservices; largest model selection in registry | +| `replicate` | Replicate | `https://api.replicate.com/v1` | `REPLICATE_API_TOKEN` | 3 | Run any model as a serverless API; image + video + LLM | +| `huggingface` | Hugging Face | `https://api-inference.huggingface.co/v1` | `HF_API_KEY` | 3 | HF Serverless Inference API for hosted open models | + +### Cloud Platform / Enterprise + +| ID | Display Name | Base URL | API Key Env | Models | Description | +|----|-------------|----------|-------------|--------|-------------| +| `bedrock` | AWS Bedrock | `https://bedrock-runtime.us-east-1.amazonaws.com` | `AWS_ACCESS_KEY_ID` | 11 | AWS-managed models (Claude, Llama, Mistral, Nova); IAM auth | +| `vertex-ai` | Google Cloud Vertex AI | `https://us-central1-aiplatform.googleapis.com` | `GOOGLE_APPLICATION_CREDENTIALS` | 6 | GCP-hosted Gemini + third-party models; service account JSON auth | +| `github-copilot` | GitHub Copilot | `https://api.githubcopilot.com` | `GITHUB_TOKEN` | 1 | Uses `ApiFormat::Copilot` — proprietary protocol, not OpenAI-compatible; requires GitHub PAT with Copilot access | + +### Aggregators / Routers + +| ID | Display Name | Base URL | API Key Env | Models | Description | +|----|-------------|----------|-------------|--------|-------------| +| `openrouter` | OpenRouter | `https://openrouter.ai/api/v1` | `OPENROUTER_API_KEY` | 18+ | Meta-provider routing to 300+ models; also receives models from OpenRouter-only providers via sync script | +| `siliconflow` | SiliconFlow | `https://api.siliconflow.cn/v1` | `SILICONFLOW_API_KEY` | dynamic | 硅基流动 — Chinese open-model hosting; models discovered at runtime, not hardcoded in TOML | + +### Chinese Providers + +| ID | Display Name | Base URL | API Key Env | Models | Description | +|----|-------------|----------|-------------|--------|-------------| +| `qwen` | Qwen (Alibaba) | `https://dashscope.aliyuncs.com/compatible-mode/v1` | `DASHSCOPE_API_KEY` | 9 | Qwen3 family by Alibaba; multi-region support (`intl` / `us`) via `[provider.regions]` | +| `moonshot` | Moonshot (Kimi) | `https://api.moonshot.ai/v1` | `MOONSHOT_API_KEY` | 5 | Kimi general chat models (moonshot-v1-8k/32k/128k) | +| `minimax` | MiniMax | `https://api.minimax.io/v1` | `MINIMAX_API_KEY` | 8 | MiniMax M-series; strong Chinese + multilingual models | +| `zhipu` | Zhipu AI (GLM) | `https://open.bigmodel.cn/api/paas/v4` | `ZHIPU_API_KEY` | 6 | GLM-4 family by Zhipu AI (智谱); general chat + vision | +| `zai` | Z.AI | `https://api.z.ai/api/paas/v4` | `ZHIPU_API_KEY` | 2 | Z.AI general models; shares API key with zhipu | +| `baichuan` | Baichuan (百川) | `https://api.baichuan-ai.com/v1` | `BAICHUAN_API_KEY` | 2 | Baichuan4 family; strong Chinese-language performance | +| `volcengine` | Volcano Engine (Doubao) | `https://ark.cn-beijing.volces.com/api/v3` | `VOLCENGINE_API_KEY` | 8 | ByteDance Doubao models; Ark platform | +| `stepfun` | Stepfun (阶跃星辰) | `https://api.stepfun.com/v1` | `STEPFUN_API_KEY` | 4 | Step-2 family; strong long-context and reasoning | +| `tencent` | Tencent | `https://api.hunyuan.cloud.tencent.com/v1` | `HUNYUAN_API_KEY` | 1 | Hunyuan models by Tencent | +| `qianfan` | Baidu Qianfan | `https://qianfan.baidubce.com/v2` | `QIANFAN_API_KEY` | 3 | ERNIE family by Baidu; Qianfan platform | + +### Coding-Specific Endpoints + +Separate `base_url` for coding workloads — not just model aliases. Same API key as the general counterpart. + +| ID | Display Name | Base URL | API Key Env | Models | vs. General | +|----|-------------|----------|-------------|--------|-------------| +| `kimi_coding` | Kimi for Code | `https://api.kimi.com/coding` | `KIMI_API_KEY` | 1 | vs `moonshot`: `api.moonshot.ai/v1` | +| `alibaba-coding-plan` | Alibaba Coding Plan (Intl) | `https://coding-intl.dashscope.aliyuncs.com/v1` | `ALIBABA_CODING_PLAN_API_KEY` | 9 | vs `qwen`: `dashscope.aliyuncs.com`; aggregates models from multiple vendors (MiniMax, GLM, Kimi) | +| `volcengine_coding` | Volcano Engine Coding Plan | `https://ark.cn-beijing.volces.com/api/coding/v3` | `VOLCENGINE_API_KEY` | dynamic | vs `volcengine`: `/api/v3`; models discovered at runtime | +| `zhipu_coding` | Zhipu Coding (CodeGeeX) | `https://open.bigmodel.cn/api/coding/paas/v4` | `ZHIPU_API_KEY` | 1 | vs `zhipu`: `/api/paas/v4`; CodeGeeX-4 coding model | +| `zai_coding` | Z.AI Coding | `https://api.z.ai/api/coding/paas/v4` | `ZHIPU_API_KEY` | 2 | vs `zai`: `/api/paas/v4`; GLM coding variants | + +### CLI-Based Providers (No API Key) + +Route through a locally-installed CLI tool. `key_required = false`, `base_url` is empty. Cost is $0. + +| ID | Display Name | CLI Binary | Models | ApiFormat | Description | +|----|-------------|-----------|--------|-----------|-------------| +| `claude-code` | Claude Code | `claude` | 3 | `ClaudeCode` | Anthropic's official CLI; routes through Claude API with OAuth | +| `codex-cli` | Codex CLI | `codex` | 6 | `CodexCli` | OpenAI Codex CLI; also serves as fallback for `openai` provider | +| `gemini-cli` | Gemini CLI | `gemini` | 2 | `GeminiCli` | Google Gemini CLI; also serves as fallback for `gemini` provider | +| `qwen-code` | Qwen Code | `qwen-code` | 3 | `QwenCode` | Alibaba Qwen coding CLI | + +### Local / Self-Hosted + +| ID | Display Name | Default Base URL | API Key Env | Notes | +|----|-------------|-----------------|-------------|-------| +| `ollama` | Ollama | `http://localhost:11434/v1` | `OLLAMA_API_KEY` | No key required; models discovered dynamically at runtime via `/api/tags` | +| `lmstudio` | LM Studio | `http://localhost:1234/v1` | `LMSTUDIO_API_KEY` | No key required; GUI app for running GGUF models locally | +| `vllm` | vLLM | `http://localhost:8000/v1` | `VLLM_API_KEY` | No key required; high-throughput inference server for production self-hosting | + +### Special / Niche + +| ID | Display Name | Base URL | API Key Env | Notes | +|----|-------------|----------|-------------|-------| +| `chatgpt` | ChatGPT (Session Auth) | `https://chatgpt.com/backend-api` | `CHATGPT_SESSION_TOKEN` | Session cookie auth, not an API key. Exposes GPT-5.x Codex models (gpt-5.1-codex etc.) that are unavailable via the standard OpenAI API | +| `elevenlabs` | ElevenLabs | `https://api.elevenlabs.io/v1` | `ELEVENLABS_API_KEY` | TTS / voice generation only — has a dedicated `elevenlabs.rs` driver in librefang-runtime. No chat models; appears in the provider list for media capability routing | + +--- + +## Inclusion Criteria + +A provider gets its own `.toml` file when it meets **at least one** of: + +1. Has a **direct public API** not accessible via OpenRouter +2. Has a **unique endpoint** for a specific workload (e.g. coding plan endpoints) +3. Has a **dedicated driver** (`ApiFormat` beyond generic `OpenAI`) +4. Is a **local/self-hosted** runtime +5. Is a **CLI-based** provider + +Providers that only route through `openrouter.ai/api/v1` with `OPENROUTER_API_KEY` are **not** given standalone files — their models are merged into `openrouter.toml` by the sync script. See [scripts/sync-pricing.py](../scripts/sync-pricing.py). + +--- ## Provider TOML Format @@ -39,26 +146,52 @@ aliases = ["short-name"] ## Tier Definitions | Tier | Description | Examples | -|------|-------------|----------| +|------|-------------|---------| | `frontier` | Most capable, cutting-edge | Claude Opus, GPT-4.1 | | `smart` | Smart, cost-effective | Claude Sonnet, Gemini 2.5 Flash | | `balanced` | Balanced speed/cost | GPT-4.1 Mini, Llama 3.3 70B | | `fast` | Fastest, cheapest | GPT-4o Mini, Claude Haiku | | `local` | Local models, zero cost | Ollama, vLLM, LM Studio | +--- + +## Sync Script + +`scripts/sync-pricing.py` runs daily via CI to keep model pricing current. + +```bash +python scripts/sync-pricing.py # Update prices only +python scripts/sync-pricing.py --create-missing # Also add new providers +python scripts/sync-pricing.py --dry-run --create-missing # Preview changes +``` + +**`--create-missing` routing logic:** + +| Condition | Action | +|-----------|--------| +| Provider in `PROVIDER_API` map (has direct API) | Create standalone `.toml` | +| Provider not in `PROVIDER_API` (OpenRouter-only) | Merge into `openrouter.toml` with `openrouter/{provider}/{model}` IDs | +| Provider in `SKIP_PROVIDERS` (morph, aider, kwaipilot, …) | Skip entirely | +| Provider ID starts with `~` (OpenRouter internal routing alias) | Skip entirely | + +--- + ## Validation ```bash -python scripts/validate.py +python scripts/validate.py # Warn on issues +python scripts/validate.py --strict # Treat warnings as errors ``` Checks: required fields, valid tiers, non-negative costs, no duplicate model IDs. -## Adding or Updating a Model +## Adding or Updating a Provider -1. Edit or create the provider file in `providers/` -2. Use exact API model IDs and verify pricing from official sources -3. Run `python scripts/validate.py` -4. Submit a PR +1. Check inclusion criteria above — if OpenRouter-only, don't create a new file +2. Create or edit the `.toml` in `providers/` +3. Use exact API model IDs; verify pricing from official sources +4. Run `python scripts/validate.py` +5. Update the table in this README +6. Submit a PR -See [CONTRIBUTING.md](../CONTRIBUTING.md) for the full guide and pricing source links. +See [CONTRIBUTING.md](../CONTRIBUTING.md) for the full guide. diff --git a/providers/ai21.toml b/providers/ai21.toml deleted file mode 100644 index d451204..0000000 --- a/providers/ai21.toml +++ /dev/null @@ -1,48 +0,0 @@ -# AI21 Labs — https://ai21.com -# Models: 3 - -[provider] -id = "ai21" -display_name = "AI21 Labs" -api_key_env = "AI21_API_KEY" -base_url = "https://api.ai21.com/studio/v1" -key_required = true - -[[models]] -id = "jamba-1.5-large" -display_name = "Jamba 1.5 Large" -tier = "smart" -context_window = 256000 -max_output_tokens = 4096 -input_cost_per_m = 2.0 -output_cost_per_m = 8.0 -supports_tools = true -supports_vision = false -supports_streaming = true -aliases = ["jamba"] - -[[models]] -id = "jamba-1.5-mini" -display_name = "Jamba 1.5 Mini" -tier = "fast" -context_window = 256000 -max_output_tokens = 4096 -input_cost_per_m = 0.20 -output_cost_per_m = 0.40 -supports_tools = true -supports_vision = false -supports_streaming = true -aliases = [] - -[[models]] -id = "jamba-instruct" -display_name = "Jamba Instruct" -tier = "balanced" -context_window = 256000 -max_output_tokens = 4096 -input_cost_per_m = 0.50 -output_cost_per_m = 0.70 -supports_tools = true -supports_vision = false -supports_streaming = true -aliases = [] diff --git a/providers/aider.toml b/providers/aider.toml deleted file mode 100644 index 62a273f..0000000 --- a/providers/aider.toml +++ /dev/null @@ -1,35 +0,0 @@ -[provider] -id = "aider" -display_name = "Aider" -api_key_env = "" -base_url = "" -key_required = false - -[[models]] -id = "aider/sonnet" -display_name = "Claude Sonnet via Aider" -provider = "aider" -tier = "smart" -context_window = 200000 -max_output_tokens = 64000 -input_cost_per_m = 0.0 -output_cost_per_m = 0.0 -supports_tools = false -supports_vision = false -supports_streaming = false -supports_thinking = true -aliases = ["aider-sonnet"] - -[[models]] -id = "aider/gpt-4o" -display_name = "GPT-4o via Aider" -provider = "aider" -tier = "smart" -context_window = 128000 -max_output_tokens = 16384 -input_cost_per_m = 0.0 -output_cost_per_m = 0.0 -supports_tools = false -supports_vision = false -supports_streaming = false -aliases = ["aider-gpt-4o"] diff --git a/providers/aion-labs.toml b/providers/aion-labs.toml deleted file mode 100644 index f15bf9e..0000000 --- a/providers/aion-labs.toml +++ /dev/null @@ -1,48 +0,0 @@ -# aion-labs — auto-generated from OpenRouter API - -[provider] -id = "aion-labs" -display_name = "Aion Labs" -api_key_env = "AION_LABS_API_KEY" -base_url = "https://api.aionlabs.ai/v1" -key_required = true - -[[models]] -id = "aion-1.0" -display_name = "AionLabs: Aion-1.0" -tier = "frontier" -context_window = 131072 -max_output_tokens = 32768 -input_cost_per_m = 4.0 -output_cost_per_m = 8.0 -supports_streaming = true - -[[models]] -id = "aion-1.0-mini" -display_name = "AionLabs: Aion-1.0-Mini" -tier = "smart" -context_window = 131072 -max_output_tokens = 32768 -input_cost_per_m = 0.7 -output_cost_per_m = 1.4 -supports_streaming = true - -[[models]] -id = "aion-2.0" -display_name = "AionLabs: Aion-2.0" -tier = "smart" -context_window = 131072 -max_output_tokens = 32768 -input_cost_per_m = 0.8 -output_cost_per_m = 1.6 -supports_streaming = true - -[[models]] -id = "aion-rp-llama-3.1-8b" -display_name = "AionLabs: Aion-RP 1.0 (8B)" -tier = "smart" -context_window = 32768 -max_output_tokens = 32768 -input_cost_per_m = 0.8 -output_cost_per_m = 1.6 -supports_streaming = true diff --git a/providers/allenai.toml b/providers/allenai.toml deleted file mode 100644 index 8350f4c..0000000 --- a/providers/allenai.toml +++ /dev/null @@ -1,50 +0,0 @@ -# allenai — auto-generated from OpenRouter API - -[provider] -id = "allenai" -display_name = "Allenai" -api_key_env = "OPENROUTER_API_KEY" -base_url = "https://openrouter.ai/api/v1" -key_required = true - -[[models]] -id = "olmo-2-0325-32b-instruct" -display_name = "AllenAI: Olmo 2 32B Instruct" -tier = "fast" -context_window = 128000 -max_output_tokens = 16384 -input_cost_per_m = 0.05 -output_cost_per_m = 0.2 -supports_streaming = true - -[[models]] -id = "olmo-3-32b-think" -display_name = "AllenAI: Olmo 3 32B Think" -tier = "fast" -context_window = 65536 -max_output_tokens = 65536 -input_cost_per_m = 0.15 -output_cost_per_m = 0.5 -supports_streaming = true -supports_thinking = true - -[[models]] -id = "olmo-3.1-32b-instruct" -display_name = "AllenAI: Olmo 3.1 32B Instruct" -tier = "fast" -context_window = 65536 -max_output_tokens = 16384 -input_cost_per_m = 0.2 -output_cost_per_m = 0.6 -supports_streaming = true - -[[models]] -id = "olmo-3.1-32b-think" -display_name = "AllenAI: Olmo 3.1 32B Think" -tier = "fast" -context_window = 65536 -max_output_tokens = 65536 -input_cost_per_m = 0.15 -output_cost_per_m = 0.5 -supports_streaming = true -supports_thinking = true diff --git a/providers/arcee-ai.toml b/providers/arcee-ai.toml deleted file mode 100644 index 8510e8a..0000000 --- a/providers/arcee-ai.toml +++ /dev/null @@ -1,78 +0,0 @@ -# arcee-ai — auto-generated from OpenRouter API - -[provider] -id = "arcee-ai" -display_name = "Arcee Ai" -api_key_env = "ARCEE_API_KEY" -base_url = "https://api.arcee.ai/v1" -key_required = true - -[[models]] -id = "coder-large" -display_name = "Arcee AI: Coder Large" -tier = "smart" -context_window = 32768 -max_output_tokens = 8192 -input_cost_per_m = 0.5 -output_cost_per_m = 0.8 -supports_streaming = true - -[[models]] -id = "maestro-reasoning" -display_name = "Arcee AI: Maestro Reasoning" -tier = "smart" -context_window = 131072 -max_output_tokens = 32000 -input_cost_per_m = 0.9 -output_cost_per_m = 3.3 -supports_streaming = true - -[[models]] -id = "spotlight" -display_name = "Arcee AI: Spotlight" -tier = "fast" -context_window = 131072 -max_output_tokens = 65537 -input_cost_per_m = 0.18 -output_cost_per_m = 0.18 -supports_streaming = true - -[[models]] -id = "trinity-large-preview:free" -display_name = "Arcee AI: Trinity Large Preview (free)" -tier = "fast" -context_window = 131000 -max_output_tokens = 16384 -input_cost_per_m = 0.0 -output_cost_per_m = 0.0 -supports_streaming = true - -[[models]] -id = "trinity-large-thinking" -display_name = "Arcee AI: Trinity Large Thinking" -tier = "fast" -context_window = 262144 -max_output_tokens = 262144 -input_cost_per_m = 0.22 -output_cost_per_m = 0.85 -supports_streaming = true - -[[models]] -id = "trinity-mini" -display_name = "Arcee AI: Trinity Mini" -tier = "fast" -context_window = 131072 -max_output_tokens = 131072 -input_cost_per_m = 0.045 -output_cost_per_m = 0.15 -supports_streaming = true - -[[models]] -id = "virtuoso-large" -display_name = "Arcee AI: Virtuoso Large" -tier = "smart" -context_window = 131072 -max_output_tokens = 64000 -input_cost_per_m = 0.75 -output_cost_per_m = 1.2 -supports_streaming = true diff --git a/providers/chutes.toml b/providers/chutes.toml deleted file mode 100644 index 8c9057f..0000000 --- a/providers/chutes.toml +++ /dev/null @@ -1,76 +0,0 @@ -# Chutes.ai — https://chutes.ai -# Models: 5 - -[provider] -id = "chutes" -display_name = "Chutes.ai" -api_key_env = "CHUTES_API_KEY" -base_url = "https://llm.chutes.ai/v1" -key_required = true - -[[models]] -id = "chutes/deepseek-ai/DeepSeek-V3" -display_name = "DeepSeek V3 (Chutes)" -tier = "smart" -context_window = 128000 -max_output_tokens = 8192 -input_cost_per_m = 0.25 -output_cost_per_m = 0.35 -supports_tools = true -supports_vision = false -supports_streaming = true -aliases = ["chutes-deepseek-v3"] - -[[models]] -id = "chutes/deepseek-ai/DeepSeek-R1" -display_name = "DeepSeek R1 (Chutes)" -tier = "smart" -context_window = 128000 -max_output_tokens = 8192 -input_cost_per_m = 0.55 -output_cost_per_m = 2.19 -supports_tools = false -supports_vision = false -supports_streaming = true -supports_thinking = true -aliases = ["chutes-deepseek-r1"] - -[[models]] -id = "chutes/meta-llama/Llama-4-Maverick-17B-128E-Instruct" -display_name = "Llama 4 Maverick (Chutes)" -tier = "balanced" -context_window = 128000 -max_output_tokens = 8192 -input_cost_per_m = 0.20 -output_cost_per_m = 0.30 -supports_tools = true -supports_vision = false -supports_streaming = true -aliases = ["chutes-llama-maverick"] - -[[models]] -id = "chutes/Qwen/Qwen3-235B-A22B" -display_name = "Qwen3 235B (Chutes)" -tier = "smart" -context_window = 128000 -max_output_tokens = 8192 -input_cost_per_m = 0.25 -output_cost_per_m = 0.35 -supports_tools = true -supports_vision = false -supports_streaming = true -supports_thinking = true -aliases = ["chutes-qwen3"] - -[[models]] -id = "chutes/meta-llama/Llama-3.3-70B-Instruct" -display_name = "Llama 3.3 70B (Chutes)" -tier = "balanced" -context_window = 128000 -max_output_tokens = 8192 -input_cost_per_m = 0.10 -output_cost_per_m = 0.15 -supports_tools = true -supports_vision = false -supports_streaming = true -aliases = ["chutes-llama-70b"] diff --git a/providers/deepcogito.toml b/providers/deepcogito.toml deleted file mode 100644 index 4c6479d..0000000 --- a/providers/deepcogito.toml +++ /dev/null @@ -1,18 +0,0 @@ -# deepcogito — auto-generated from OpenRouter API - -[provider] -id = "deepcogito" -display_name = "Deepcogito" -api_key_env = "OPENROUTER_API_KEY" -base_url = "https://openrouter.ai/api/v1" -key_required = true - -[[models]] -id = "cogito-v2.1-671b" -display_name = "Deep Cogito: Cogito v2.1 671B" -tier = "smart" -context_window = 128000 -max_output_tokens = 16384 -input_cost_per_m = 1.25 -output_cost_per_m = 1.25 -supports_streaming = true diff --git a/providers/deepinfra.toml b/providers/deepinfra.toml new file mode 100644 index 0000000..4ee7bf6 --- /dev/null +++ b/providers/deepinfra.toml @@ -0,0 +1,69 @@ +# DeepInfra — https://deepinfra.com +# Serverless open-model inference (Llama, Mistral, Qwen, etc.) + +[provider] +id = "deepinfra" +display_name = "DeepInfra" +api_key_env = "DEEPINFRA_API_KEY" +base_url = "https://api.deepinfra.com/v1/openai" +key_required = true + +[[models]] +id = "meta-llama/Meta-Llama-3.1-8B-Instruct" +display_name = "Llama 3.1 8B Instruct" +tier = "fast" +context_window = 128000 +max_output_tokens = 8192 +input_cost_per_m = 0.06 +output_cost_per_m = 0.06 +supports_tools = true +supports_vision = false +supports_streaming = true + +[[models]] +id = "meta-llama/Meta-Llama-3.1-70B-Instruct" +display_name = "Llama 3.1 70B Instruct" +tier = "balanced" +context_window = 128000 +max_output_tokens = 8192 +input_cost_per_m = 0.35 +output_cost_per_m = 0.4 +supports_tools = true +supports_vision = false +supports_streaming = true + +[[models]] +id = "meta-llama/Meta-Llama-3.1-405B-Instruct" +display_name = "Llama 3.1 405B Instruct" +tier = "smart" +context_window = 128000 +max_output_tokens = 8192 +input_cost_per_m = 0.8 +output_cost_per_m = 0.8 +supports_tools = true +supports_vision = false +supports_streaming = true + +[[models]] +id = "mistralai/Mistral-7B-Instruct-v0.3" +display_name = "Mistral 7B Instruct v0.3" +tier = "fast" +context_window = 32768 +max_output_tokens = 8192 +input_cost_per_m = 0.07 +output_cost_per_m = 0.07 +supports_tools = true +supports_vision = false +supports_streaming = true + +[[models]] +id = "Qwen/Qwen2.5-72B-Instruct" +display_name = "Qwen 2.5 72B Instruct" +tier = "balanced" +context_window = 32768 +max_output_tokens = 8192 +input_cost_per_m = 0.35 +output_cost_per_m = 0.4 +supports_tools = true +supports_vision = false +supports_streaming = true diff --git a/providers/essentialai.toml b/providers/essentialai.toml deleted file mode 100644 index 4fc46d9..0000000 --- a/providers/essentialai.toml +++ /dev/null @@ -1,18 +0,0 @@ -# essentialai — auto-generated from OpenRouter API - -[provider] -id = "essentialai" -display_name = "Essentialai" -api_key_env = "OPENROUTER_API_KEY" -base_url = "https://openrouter.ai/api/v1" -key_required = true - -[[models]] -id = "rnj-1-instruct" -display_name = "EssentialAI: Rnj 1 Instruct" -tier = "fast" -context_window = 32768 -max_output_tokens = 8192 -input_cost_per_m = 0.15 -output_cost_per_m = 0.15 -supports_streaming = true diff --git a/providers/ibm-granite.toml b/providers/ibm-granite.toml deleted file mode 100644 index 58658e2..0000000 --- a/providers/ibm-granite.toml +++ /dev/null @@ -1,18 +0,0 @@ -# ibm-granite — auto-generated from OpenRouter API - -[provider] -id = "ibm-granite" -display_name = "Ibm Granite" -api_key_env = "WATSONX_API_KEY" -base_url = "https://us-south.ml.cloud.ibm.com/ml/v1" -key_required = true - -[[models]] -id = "granite-4.0-h-micro" -display_name = "IBM: Granite 4.0 Micro" -tier = "fast" -context_window = 131000 -max_output_tokens = 16384 -input_cost_per_m = 0.017 -output_cost_per_m = 0.11 -supports_streaming = true diff --git a/providers/inception.toml b/providers/inception.toml deleted file mode 100644 index 973ba13..0000000 --- a/providers/inception.toml +++ /dev/null @@ -1,18 +0,0 @@ -# inception — auto-generated from OpenRouter API - -[provider] -id = "inception" -display_name = "Inception" -api_key_env = "INCEPTION_API_KEY" -base_url = "https://api.inceptionlabs.ai/v1" -key_required = true - -[[models]] -id = "mercury-2" -display_name = "Inception: Mercury 2" -tier = "fast" -context_window = 128000 -max_output_tokens = 50000 -input_cost_per_m = 0.25 -output_cost_per_m = 0.75 -supports_streaming = true diff --git a/providers/inclusionai.toml b/providers/inclusionai.toml deleted file mode 100644 index 33ede01..0000000 --- a/providers/inclusionai.toml +++ /dev/null @@ -1,18 +0,0 @@ -# inclusionai — auto-generated from OpenRouter API - -[provider] -id = "inclusionai" -display_name = "Inclusionai" -api_key_env = "OPENROUTER_API_KEY" -base_url = "https://openrouter.ai/api/v1" -key_required = true - -[[models]] -id = "ling-2.6-flash:free" -display_name = "inclusionAI: Ling-2.6-flash (free)" -tier = "fast" -context_window = 262144 -max_output_tokens = 32768 -input_cost_per_m = 0.0 -output_cost_per_m = 0.0 -supports_streaming = true diff --git a/providers/inflection.toml b/providers/inflection.toml deleted file mode 100644 index 5c5fc4b..0000000 --- a/providers/inflection.toml +++ /dev/null @@ -1,28 +0,0 @@ -# inflection — auto-generated from OpenRouter API - -[provider] -id = "inflection" -display_name = "Inflection" -api_key_env = "OPENROUTER_API_KEY" -base_url = "https://openrouter.ai/api/v1" -key_required = true - -[[models]] -id = "inflection-3-pi" -display_name = "Inflection: Inflection 3 Pi" -tier = "smart" -context_window = 8000 -max_output_tokens = 1024 -input_cost_per_m = 2.5 -output_cost_per_m = 10.0 -supports_streaming = true - -[[models]] -id = "inflection-3-productivity" -display_name = "Inflection: Inflection 3 Productivity" -tier = "smart" -context_window = 8000 -max_output_tokens = 1024 -input_cost_per_m = 2.5 -output_cost_per_m = 10.0 -supports_streaming = true diff --git a/providers/kwaipilot.toml b/providers/kwaipilot.toml deleted file mode 100644 index dea658b..0000000 --- a/providers/kwaipilot.toml +++ /dev/null @@ -1,18 +0,0 @@ -# kwaipilot — auto-generated from OpenRouter API - -[provider] -id = "kwaipilot" -display_name = "Kwaipilot" -api_key_env = "OPENROUTER_API_KEY" -base_url = "https://openrouter.ai/api/v1" -key_required = true - -[[models]] -id = "kat-coder-pro-v2" -display_name = "Kwaipilot: KAT-Coder-Pro V2" -tier = "fast" -context_window = 256000 -max_output_tokens = 80000 -input_cost_per_m = 0.3 -output_cost_per_m = 1.2 -supports_streaming = true diff --git a/providers/liquid.toml b/providers/liquid.toml deleted file mode 100644 index 5912db2..0000000 --- a/providers/liquid.toml +++ /dev/null @@ -1,38 +0,0 @@ -# liquid — auto-generated from OpenRouter API - -[provider] -id = "liquid" -display_name = "Liquid" -api_key_env = "OPENROUTER_API_KEY" -base_url = "https://openrouter.ai/api/v1" -key_required = true - -[[models]] -id = "lfm-2-24b-a2b" -display_name = "LiquidAI: LFM2-24B-A2B" -tier = "fast" -context_window = 32768 -max_output_tokens = 8192 -input_cost_per_m = 0.03 -output_cost_per_m = 0.12 -supports_streaming = true - -[[models]] -id = "lfm-2.5-1.2b-instruct:free" -display_name = "LiquidAI: LFM2.5-1.2B-Instruct (free)" -tier = "fast" -context_window = 32768 -max_output_tokens = 8192 -input_cost_per_m = 0.0 -output_cost_per_m = 0.0 -supports_streaming = true - -[[models]] -id = "lfm-2.5-1.2b-thinking:free" -display_name = "LiquidAI: LFM2.5-1.2B-Thinking (free)" -tier = "fast" -context_window = 32768 -max_output_tokens = 8192 -input_cost_per_m = 0.0 -output_cost_per_m = 0.0 -supports_streaming = true diff --git a/providers/meituan.toml b/providers/meituan.toml deleted file mode 100644 index 07f5e10..0000000 --- a/providers/meituan.toml +++ /dev/null @@ -1,18 +0,0 @@ -# meituan — auto-generated from OpenRouter API - -[provider] -id = "meituan" -display_name = "Meituan" -api_key_env = "OPENROUTER_API_KEY" -base_url = "https://openrouter.ai/api/v1" -key_required = true - -[[models]] -id = "longcat-flash-chat" -display_name = "Meituan: LongCat Flash Chat" -tier = "fast" -context_window = 131072 -max_output_tokens = 131072 -input_cost_per_m = 0.2 -output_cost_per_m = 0.8 -supports_streaming = true diff --git a/providers/microsoft.toml b/providers/microsoft.toml deleted file mode 100644 index 117888a..0000000 --- a/providers/microsoft.toml +++ /dev/null @@ -1,28 +0,0 @@ -# microsoft — auto-generated from OpenRouter API - -[provider] -id = "microsoft" -display_name = "Microsoft" -api_key_env = "GITHUB_TOKEN" -base_url = "https://models.inference.ai.azure.com" -key_required = true - -[[models]] -id = "phi-4" -display_name = "Microsoft: Phi 4" -tier = "fast" -context_window = 16384 -max_output_tokens = 16384 -input_cost_per_m = 0.065 -output_cost_per_m = 0.14 -supports_streaming = true - -[[models]] -id = "wizardlm-2-8x22b" -display_name = "WizardLM-2 8x22B" -tier = "smart" -context_window = 65535 -max_output_tokens = 8000 -input_cost_per_m = 0.62 -output_cost_per_m = 0.62 -supports_streaming = true diff --git a/providers/morph.toml b/providers/morph.toml deleted file mode 100644 index c8245df..0000000 --- a/providers/morph.toml +++ /dev/null @@ -1,28 +0,0 @@ -# morph — auto-generated from OpenRouter API - -[provider] -id = "morph" -display_name = "Morph" -api_key_env = "MORPH_API_KEY" -base_url = "https://api.morphllm.com/v1" -key_required = true - -[[models]] -id = "morph-v3-fast" -display_name = "Morph: Morph V3 Fast" -tier = "smart" -context_window = 81920 -max_output_tokens = 38000 -input_cost_per_m = 0.8 -output_cost_per_m = 1.2 -supports_streaming = true - -[[models]] -id = "morph-v3-large" -display_name = "Morph: Morph V3 Large" -tier = "smart" -context_window = 262144 -max_output_tokens = 131072 -input_cost_per_m = 0.9 -output_cost_per_m = 1.9 -supports_streaming = true diff --git a/providers/nex-agi.toml b/providers/nex-agi.toml deleted file mode 100644 index ed681c9..0000000 --- a/providers/nex-agi.toml +++ /dev/null @@ -1,18 +0,0 @@ -# nex-agi — auto-generated from OpenRouter API - -[provider] -id = "nex-agi" -display_name = "Nex Agi" -api_key_env = "OPENROUTER_API_KEY" -base_url = "https://openrouter.ai/api/v1" -key_required = true - -[[models]] -id = "deepseek-v3.1-nex-n1" -display_name = "Nex AGI: DeepSeek V3.1 Nex N1" -tier = "fast" -context_window = 131072 -max_output_tokens = 163840 -input_cost_per_m = 0.135 -output_cost_per_m = 0.5 -supports_streaming = true diff --git a/providers/nousresearch.toml b/providers/nousresearch.toml deleted file mode 100644 index aaab52c..0000000 --- a/providers/nousresearch.toml +++ /dev/null @@ -1,68 +0,0 @@ -# nousresearch — auto-generated from OpenRouter API - -[provider] -id = "nousresearch" -display_name = "Nousresearch" -api_key_env = "OPENROUTER_API_KEY" -base_url = "https://openrouter.ai/api/v1" -key_required = true - -[[models]] -id = "hermes-2-pro-llama-3-8b" -display_name = "NousResearch: Hermes 2 Pro - Llama-3 8B" -tier = "fast" -context_window = 8192 -max_output_tokens = 8192 -input_cost_per_m = 0.14 -output_cost_per_m = 0.14 -supports_streaming = true - -[[models]] -id = "hermes-3-llama-3.1-405b" -display_name = "Nous: Hermes 3 405B Instruct" -tier = "smart" -context_window = 131072 -max_output_tokens = 16384 -input_cost_per_m = 1.0 -output_cost_per_m = 1.0 -supports_streaming = true - -[[models]] -id = "hermes-3-llama-3.1-405b:free" -display_name = "Nous: Hermes 3 405B Instruct (free)" -tier = "fast" -context_window = 131072 -max_output_tokens = 16384 -input_cost_per_m = 0.0 -output_cost_per_m = 0.0 -supports_streaming = true - -[[models]] -id = "hermes-3-llama-3.1-70b" -display_name = "Nous: Hermes 3 70B Instruct" -tier = "fast" -context_window = 131072 -max_output_tokens = 16384 -input_cost_per_m = 0.3 -output_cost_per_m = 0.3 -supports_streaming = true - -[[models]] -id = "hermes-4-405b" -display_name = "Nous: Hermes 4 405B" -tier = "smart" -context_window = 131072 -max_output_tokens = 16384 -input_cost_per_m = 1.0 -output_cost_per_m = 3.0 -supports_streaming = true - -[[models]] -id = "hermes-4-70b" -display_name = "Nous: Hermes 4 70B" -tier = "fast" -context_window = 131072 -max_output_tokens = 16384 -input_cost_per_m = 0.13 -output_cost_per_m = 0.4 -supports_streaming = true diff --git a/providers/prime-intellect.toml b/providers/prime-intellect.toml deleted file mode 100644 index 0799d9e..0000000 --- a/providers/prime-intellect.toml +++ /dev/null @@ -1,18 +0,0 @@ -# prime-intellect — auto-generated from OpenRouter API - -[provider] -id = "prime-intellect" -display_name = "Prime Intellect" -api_key_env = "OPENROUTER_API_KEY" -base_url = "https://openrouter.ai/api/v1" -key_required = true - -[[models]] -id = "intellect-3" -display_name = "Prime Intellect: INTELLECT-3" -tier = "fast" -context_window = 131072 -max_output_tokens = 131072 -input_cost_per_m = 0.2 -output_cost_per_m = 1.1 -supports_streaming = true diff --git a/providers/relace.toml b/providers/relace.toml deleted file mode 100644 index 7224915..0000000 --- a/providers/relace.toml +++ /dev/null @@ -1,28 +0,0 @@ -# relace — auto-generated from OpenRouter API - -[provider] -id = "relace" -display_name = "Relace" -api_key_env = "OPENROUTER_API_KEY" -base_url = "https://openrouter.ai/api/v1" -key_required = true - -[[models]] -id = "relace-apply-3" -display_name = "Relace: Relace Apply 3" -tier = "smart" -context_window = 256000 -max_output_tokens = 128000 -input_cost_per_m = 0.85 -output_cost_per_m = 1.25 -supports_streaming = true - -[[models]] -id = "relace-search" -display_name = "Relace: Relace Search" -tier = "smart" -context_window = 256000 -max_output_tokens = 128000 -input_cost_per_m = 1.0 -output_cost_per_m = 3.0 -supports_streaming = true diff --git a/providers/switchpoint.toml b/providers/switchpoint.toml deleted file mode 100644 index cda8660..0000000 --- a/providers/switchpoint.toml +++ /dev/null @@ -1,18 +0,0 @@ -# switchpoint — auto-generated from OpenRouter API - -[provider] -id = "switchpoint" -display_name = "Switchpoint" -api_key_env = "OPENROUTER_API_KEY" -base_url = "https://openrouter.ai/api/v1" -key_required = true - -[[models]] -id = "router" -display_name = "Switchpoint Router" -tier = "smart" -context_window = 131072 -max_output_tokens = 16384 -input_cost_per_m = 0.85 -output_cost_per_m = 3.4 -supports_streaming = true diff --git a/providers/tngtech.toml b/providers/tngtech.toml deleted file mode 100644 index 15b9e5b..0000000 --- a/providers/tngtech.toml +++ /dev/null @@ -1,18 +0,0 @@ -# tngtech — auto-generated from OpenRouter API - -[provider] -id = "tngtech" -display_name = "Tngtech" -api_key_env = "OPENROUTER_API_KEY" -base_url = "https://openrouter.ai/api/v1" -key_required = true - -[[models]] -id = "deepseek-r1t2-chimera" -display_name = "TNG: DeepSeek R1T2 Chimera" -tier = "fast" -context_window = 163840 -max_output_tokens = 163840 -input_cost_per_m = 0.3 -output_cost_per_m = 1.1 -supports_streaming = true diff --git a/providers/upstage.toml b/providers/upstage.toml deleted file mode 100644 index 6c31405..0000000 --- a/providers/upstage.toml +++ /dev/null @@ -1,18 +0,0 @@ -# upstage — auto-generated from OpenRouter API - -[provider] -id = "upstage" -display_name = "Upstage" -api_key_env = "UPSTAGE_API_KEY" -base_url = "https://api.upstage.ai/v1" -key_required = true - -[[models]] -id = "solar-pro-3" -display_name = "Upstage: Solar Pro 3" -tier = "fast" -context_window = 128000 -max_output_tokens = 16384 -input_cost_per_m = 0.15 -output_cost_per_m = 0.6 -supports_streaming = true diff --git a/providers/venice.toml b/providers/venice.toml deleted file mode 100644 index c6cb2d0..0000000 --- a/providers/venice.toml +++ /dev/null @@ -1,49 +0,0 @@ -# Venice.ai — https://venice.ai -# Models: 3 - -[provider] -id = "venice" -display_name = "Venice.ai" -api_key_env = "VENICE_API_KEY" -base_url = "https://api.venice.ai/api/v1" -key_required = true - -[[models]] -id = "venice-uncensored" -display_name = "Venice Uncensored" -tier = "fast" -context_window = 32000 -max_output_tokens = 8192 -input_cost_per_m = 0.20 -output_cost_per_m = 0.90 -supports_tools = true -supports_vision = false -supports_streaming = true -aliases = ["venice"] - -[[models]] -id = "llama-3.3-70b" -display_name = "Llama 3.3 70B (Venice)" -tier = "balanced" -context_window = 128000 -max_output_tokens = 8192 -input_cost_per_m = 0.1 -output_cost_per_m = 0.32 -supports_tools = true -supports_vision = false -supports_streaming = true -aliases = [] - -[[models]] -id = "qwen3-235b-a22b-instruct-2507" -display_name = "Qwen3 235B A22B (Venice)" -tier = "smart" -context_window = 128000 -max_output_tokens = 8192 -input_cost_per_m = 0.20 -output_cost_per_m = 0.90 -supports_tools = true -supports_vision = false -supports_streaming = true -supports_thinking = true -aliases = [] diff --git a/providers/writer.toml b/providers/writer.toml deleted file mode 100644 index 16cd9ed..0000000 --- a/providers/writer.toml +++ /dev/null @@ -1,18 +0,0 @@ -# writer — auto-generated from OpenRouter API - -[provider] -id = "writer" -display_name = "Writer" -api_key_env = "OPENROUTER_API_KEY" -base_url = "https://openrouter.ai/api/v1" -key_required = true - -[[models]] -id = "palmyra-x5" -display_name = "Writer: Palmyra X5" -tier = "smart" -context_window = 1040000 -max_output_tokens = 8192 -input_cost_per_m = 0.6 -output_cost_per_m = 6.0 -supports_streaming = true diff --git a/providers/xiaomi.toml b/providers/xiaomi.toml deleted file mode 100644 index 7287e03..0000000 --- a/providers/xiaomi.toml +++ /dev/null @@ -1,38 +0,0 @@ -# xiaomi — auto-generated from OpenRouter API - -[provider] -id = "xiaomi" -display_name = "Xiaomi" -api_key_env = "XIAOMI_ACCESS_KEY_ID" -base_url = "https://cnbj3-cloud-ml.api.xiaomi.net" -key_required = true - -[[models]] -id = "mimo-v2-flash" -display_name = "Xiaomi: MiMo-V2-Flash" -tier = "fast" -context_window = 262144 -max_output_tokens = 65536 -input_cost_per_m = 0.09 -output_cost_per_m = 0.29 -supports_streaming = true - -[[models]] -id = "mimo-v2-omni" -display_name = "Xiaomi: MiMo-V2-Omni" -tier = "fast" -context_window = 262144 -max_output_tokens = 65536 -input_cost_per_m = 0.4 -output_cost_per_m = 2.0 -supports_streaming = true - -[[models]] -id = "mimo-v2-pro" -display_name = "Xiaomi: MiMo-V2-Pro" -tier = "smart" -context_window = 1048576 -max_output_tokens = 131072 -input_cost_per_m = 1.0 -output_cost_per_m = 3.0 -supports_streaming = true diff --git a/providers/~anthropic.toml b/providers/~anthropic.toml deleted file mode 100644 index 60871da..0000000 --- a/providers/~anthropic.toml +++ /dev/null @@ -1,18 +0,0 @@ -# ~anthropic — auto-generated from OpenRouter API - -[provider] -id = "~anthropic" -display_name = "~Anthropic" -api_key_env = "OPENROUTER_API_KEY" -base_url = "https://openrouter.ai/api/v1" -key_required = true - -[[models]] -id = "claude-opus-latest" -display_name = "Anthropic: Claude Opus Latest" -tier = "frontier" -context_window = 1000000 -max_output_tokens = 128000 -input_cost_per_m = 5.0 -output_cost_per_m = 25.0 -supports_streaming = true diff --git a/scripts/sync-pricing.py b/scripts/sync-pricing.py index 0a2cfb4..4268190 100644 --- a/scripts/sync-pricing.py +++ b/scripts/sync-pricing.py @@ -34,6 +34,8 @@ PROVIDER_ALIAS = { SKIP_PROVIDERS = { "sao10k", "thedrummer", "undi95", "gryphe", "cognitivecomputations", "anthracite-org", "alpindale", "alfredpros", "mancer", + # Specialized coding tools / CLI wrappers — not general LLM providers + "morph", "aider", "kwaipilot", } # Skip creating NEW provider files for these — they overlap with hand-written @@ -139,8 +141,102 @@ def update_toml_prices(toml_path, models_by_id, dry_run=False): return updated +def _build_model_fields(provider_id, m, model_id_prefix=""): + """Extract and normalise fields for a single OpenRouter model entry. + + Returns a dict of fields, or None if pricing is missing. + The caller supplies *model_id_prefix* (e.g. "openrouter/kwaipilot/") so + the same helper works for both standalone files and openrouter.toml merges. + """ + raw_id = m["id"].split("/")[-1] if "/" in m["id"] else m["id"] + model_id = f"{model_id_prefix}{raw_id}" + display = m.get("name", raw_id) + ctx = m.get("context_length", 0) + max_out = m.get("top_provider", {}).get("max_completion_tokens", 0) + inp, outp = parse_pricing(m) + if inp is None: + return None + + supports_tools = "tool_use" in str(m.get("supported_parameters", [])) + supports_vision = "vision" in str(m.get("architecture", {}).get("modality", "")) + + if inp == 0 and outp == 0: + tier = "fast" + elif inp < 0.5: + tier = "fast" + elif inp < 3.0: + tier = "smart" + else: + tier = "frontier" + + if not max_out: + max_out = min(ctx // 4, 16384) if ctx > 0 else 4096 + + return dict( + model_id=model_id, display=display, tier=tier, + ctx=ctx, max_out=max_out, inp=inp, outp=outp, + supports_tools=supports_tools, supports_vision=supports_vision, + ) + + +def _model_lines(f): + """Render a model-fields dict as TOML [[models]] lines.""" + lines = [ + "[[models]]", + f'id = "{f["model_id"]}"', + f'display_name = "{f["display"]}"', + f'tier = "{f["tier"]}"', + f'context_window = {f["ctx"]}', + f'max_output_tokens = {f["max_out"]}', + f'input_cost_per_m = {f["inp"]}', + f'output_cost_per_m = {f["outp"]}', + ] + if f["supports_tools"]: + lines.append("supports_tools = true") + if f["supports_vision"]: + lines.append("supports_vision = true") + lines.append("supports_streaming = true") + lines.append("") + return lines + + +def merge_into_openrouter(provider_id, models, dry_run=False): + """Append models from an OpenRouter-only provider into openrouter.toml. + + Model IDs get the prefix "openrouter/{provider_id}/" so they stay + unambiguous and match the existing openrouter.toml convention. + Already-present IDs are skipped to keep the operation idempotent. + """ + openrouter_path = PROVIDERS_DIR / "openrouter.toml" + if not openrouter_path.exists(): + return 0 + + existing = openrouter_path.read_text() + existing_ids = set(re.findall(r'^id\s*=\s*"([^"]+)"', existing, re.MULTILINE)) + + new_lines = [] + for m in sorted(models, key=lambda x: x.get("id", "")): + prefix = f"openrouter/{provider_id}/" + f = _build_model_fields(provider_id, m, model_id_prefix=prefix) + if f is None or f["model_id"] in existing_ids: + continue + # Append provider name to display so provenance is clear in the UI + f["display"] = f'{f["display"]} (OpenRouter)' + new_lines.extend(_model_lines(f)) + + if not new_lines: + return 0 + + count = sum(1 for l in new_lines if l == "[[models]]") + print(f" openrouter.toml: +{count} models from {provider_id}") + if not dry_run: + with open(openrouter_path, "a") as fh: + fh.write("\n" + "\n".join(new_lines)) + return count + + def generate_provider_toml(provider_id, models, dry_run=False): - """Generate a new provider TOML file from OpenRouter data.""" + """Generate a new standalone provider TOML file (direct-API providers only).""" our_name = PROVIDER_ALIAS.get(provider_id, provider_id) toml_path = PROVIDERS_DIR / f"{our_name}.toml" @@ -150,13 +246,11 @@ def generate_provider_toml(provider_id, models, dry_run=False): if our_name in SKIP_DUPLICATES: return 0 - # Check if provider has a known public API - if our_name in PROVIDER_API: - base_url, env_key = PROVIDER_API[our_name] - else: - # No known public API — route through OpenRouter - base_url = "https://openrouter.ai/api/v1" - env_key = "OPENROUTER_API_KEY" + if our_name not in PROVIDER_API: + # No direct public API — caller should use merge_into_openrouter instead. + return 0 + + base_url, env_key = PROVIDER_API[our_name] key_required = "true" lines = [ @@ -173,45 +267,10 @@ def generate_provider_toml(provider_id, models, dry_run=False): count = 0 for m in sorted(models, key=lambda x: x.get("id", "")): - model_id = m["id"].split("/")[-1] if "/" in m["id"] else m["id"] - display = m.get("name", model_id) - ctx = m.get("context_length", 0) - max_out = m.get("top_provider", {}).get("max_completion_tokens", 0) - inp, outp = parse_pricing(m) - if inp is None: + f = _build_model_fields(provider_id, m) + if f is None: continue - - supports_tools = "tool_use" in str(m.get("supported_parameters", [])) - supports_vision = "vision" in str(m.get("architecture", {}).get("modality", "")) - - # Infer tier from pricing - if inp == 0 and outp == 0: - tier = "fast" - elif inp < 0.5: - tier = "fast" - elif inp < 3.0: - tier = "smart" - else: - tier = "frontier" - - # Default max_output_tokens if not provided - if not max_out: - max_out = min(ctx // 4, 16384) if ctx > 0 else 4096 - - lines.append("[[models]]") - lines.append(f'id = "{model_id}"') - lines.append(f'display_name = "{display}"') - lines.append(f'tier = "{tier}"') - lines.append(f"context_window = {ctx}") - lines.append(f"max_output_tokens = {max_out}") - lines.append(f"input_cost_per_m = {inp}") - lines.append(f"output_cost_per_m = {outp}") - if supports_tools: - lines.append("supports_tools = true") - if supports_vision: - lines.append("supports_vision = true") - lines.append("supports_streaming = true") - lines.append("") + lines.extend(_model_lines(f)) count += 1 if count == 0: @@ -257,10 +316,21 @@ def main(): for provider_id, models in sorted(by_provider.items()): if provider_id in SKIP_PROVIDERS: continue + # Skip OpenRouter internal auto-routing aliases (e.g. "~anthropic") + # These are not real providers — they map to openrouter.toml. + if provider_id.startswith("~"): + continue our_name = PROVIDER_ALIAS.get(provider_id, provider_id) - if not (PROVIDERS_DIR / f"{our_name}.toml").exists(): + if (PROVIDERS_DIR / f"{our_name}.toml").exists(): + continue + if our_name in PROVIDER_API: + # Provider has a known direct API — create a standalone file. count = generate_provider_toml(provider_id, models, dry_run=dry_run) - total_created += count + else: + # No direct API — merge models into openrouter.toml instead of + # creating a new file that just wraps the OpenRouter endpoint. + count = merge_into_openrouter(provider_id, models, dry_run=dry_run) + total_created += count action = "Would" if dry_run else "Done:" print(f"\n{action} updated {total_updated} prices, created {total_created} new model entries") diff --git a/skills/README.md b/skills/README.md index 58fec75..6a5795a 100644 --- a/skills/README.md +++ b/skills/README.md @@ -1,52 +1,41 @@ -# Skills +# Skills Registry -Reusable skill definitions for LibreFang agents. A skill is either a prompt -template or a code script that an agent can invoke to perform a specific task. +Skills are reusable expertise modules that can be attached to any agent. Each skill carries a system prompt that injects domain knowledge, best practices, and behavioral guidelines into an agent's context at conversation time. Skills are composable — a single agent can load multiple skills simultaneously. -## File Convention +## File Format -Every skill directory **must** contain a `SKILL.md` (the entry point). -A `skill.toml` is **optional** and only needed for structured metadata that -does not fit in Markdown frontmatter (runtime, input schema, version, tags). +A skill lives in its own subdirectory. The only required file is `SKILL.md`. An optional `skill.toml` provides structured metadata when `[runtime]`, `[input]` schema, or explicit versioning is needed. ``` skills/ -├── docker/ -│ └── SKILL.md # Prompt-only expert — no skill.toml needed -├── custom-skill-prompt/ -│ ├── SKILL.md # Prompt body + name/description -│ └── skill.toml # Runtime + input schema -└── custom-skill-python/ - ├── SKILL.md # Overview (prompt body unused) - ├── skill.toml # Runtime = python, entry = main.py +├── rust-expert/ +│ └── SKILL.md # required: frontmatter + prompt body +├── meeting-agenda/ +│ ├── SKILL.md # required: frontmatter + prompt body +│ └── skill.toml # optional: runtime type, input schema, version +└── code-runner/ + ├── SKILL.md # overview (prompt body unused for script skills) + ├── skill.toml # runtime = python, entry = main.py └── main.py ``` -### `SKILL.md` (required) - -The source of truth for the skill's prompt and identity. Must start with YAML -frontmatter containing at least `name` and `description`: +### SKILL.md format ```markdown --- -name: docker -description: Docker expert for containers, Compose, and Dockerfiles. +name: rust-expert +description: "Rust programming expert for ownership, lifetimes, async/await, traits, and unsafe code" --- +# Rust Programming Expertise -You are a Docker specialist. You help users build, run, debug, and optimize -containers... +You are an expert Rust developer with deep understanding of the ownership system... ``` -This format is compatible with Claude Code skills, so a `SKILL.md` authored -here can be dropped into other tools without modification. +The frontmatter must contain `name` and `description`. The Markdown body becomes the injected prompt. -### `skill.toml` (optional) +### skill.toml format (optional) -Add one only when you need to declare any of: - -- `[runtime]` — `promptonly` / `python` / `node` / `shell` (default is `promptonly`) -- `[input]` — typed input parameter schema -- `version`, `author`, `tags` — structured metadata +Only required when you need `[runtime]`, `[input]` schema, or structured metadata beyond what frontmatter supports: ```toml [skill] @@ -56,27 +45,147 @@ description = "Generate a structured meeting agenda from a topic and duration." tags = ["meeting", "productivity"] [runtime] -type = "promptonly" +type = "promptonly" # promptonly | python | node | shell [input] topic = { type = "string", description = "The meeting topic", required = true } duration_minutes = { type = "string", description = "Duration in minutes", required = true } ``` -**Consistency rule:** if both files exist, `skill.name` and `skill.description` -in `skill.toml` must match the `name` and `description` in `SKILL.md`'s -frontmatter. The validator enforces this to prevent drift. +If both files exist, `skill.name` and `skill.description` in `skill.toml` must match the frontmatter in `SKILL.md`. The validator enforces this to prevent drift. -**Do not duplicate the prompt body in TOML.** The prompt lives in `SKILL.md`; -`skill.toml` is for metadata the prompt cannot express. - -## Testing Skills Locally +## Installing and Using Skills ```bash -librefang skill test ./skills/custom-skill-prompt \ +# List all available skills in the registry +librefang catalog skills + +# Attach a skill to an agent +librefang skill attach rust-expert + +# Attach multiple skills +librefang skill attach rust-expert security-audit + +# Detach a skill +librefang skill detach rust-expert + +# Test a skill locally with sample input +librefang skill test ./skills/meeting-agenda \ --input '{"topic": "Q1 planning", "duration_minutes": "30"}' ``` +## All Skills (61 total) + +### Programming Languages + +| Name | Description | +|------|-------------| +| css-expert | CSS expert for flexbox, grid, animations, responsive design, and modern layout techniques | +| golang-expert | Go programming expert for goroutines, channels, interfaces, modules, and concurrency patterns | +| python-expert | Python expert for stdlib, packaging, type hints, async/await, and performance optimization | +| rust-expert | Rust programming expert for ownership, lifetimes, async/await, traits, and unsafe code | +| typescript-expert | TypeScript expert for type system, generics, utility types, and strict mode patterns | +| wasm-expert | WebAssembly expert for WASI, component model, Rust/C compilation, and browser integration | + +### Web Frameworks and APIs + +| Name | Description | +|------|-------------| +| graphql-expert | GraphQL expert for schema design, resolvers, subscriptions, and performance optimization | +| nextjs-expert | Next.js expert for App Router, SSR/SSG, API routes, middleware, and deployment | +| oauth-expert | OAuth 2.0 and OpenID Connect expert for authorization flows, PKCE, and token management | +| openapi-expert | OpenAPI/Swagger expert for API specification design, validation, and code generation | +| react-expert | React expert for hooks, state management, Server Components, and performance optimization | + +### Databases + +| Name | Description | +|------|-------------| +| elasticsearch | Elasticsearch expert for queries, mappings, aggregations, index management, and cluster operations | +| mongodb | MongoDB operations expert for queries, aggregation pipelines, indexes, and schema design | +| postgres-expert | PostgreSQL expert for query optimization, indexing, extensions, and database administration | +| redis-expert | Redis expert for data structures, caching patterns, Lua scripting, and cluster operations | +| sql-analyst | SQL query expert for optimization, schema design, and data analysis | +| sqlite-expert | SQLite expert for WAL mode, query optimization, embedded patterns, and advanced features | +| vector-db | Vector database expert for embeddings, similarity search, RAG patterns, and indexing strategies | + +### Cloud and Infrastructure + +| Name | Description | +|------|-------------| +| ansible | Ansible automation expert for playbooks, roles, inventories, and infrastructure management | +| aws | AWS cloud services expert for EC2, S3, Lambda, IAM, and AWS CLI | +| azure | Microsoft Azure expert for az CLI, AKS, App Service, and cloud infrastructure | +| docker | Docker expert for containers, Compose, Dockerfiles, and debugging | +| gcp | Google Cloud Platform expert for gcloud CLI, GKE, Cloud Run, and managed services | +| helm | Helm chart expert for Kubernetes package management, templating, and dependency management | +| kubernetes | Kubernetes operations expert for kubectl, pods, deployments, and debugging | +| nginx | Nginx configuration expert for reverse proxy, load balancing, TLS, and performance tuning | +| terraform | Terraform IaC expert for providers, modules, state management, and planning | + +### DevOps and CI/CD + +| Name | Description | +|------|-------------| +| ci-cd | CI/CD pipeline expert for GitHub Actions, GitLab CI, Jenkins, and deployment automation | +| git-expert | Git operations expert for branching, rebasing, conflicts, and workflows | +| github | GitHub operations expert for PRs, issues, code review, Actions, and gh CLI | +| linux-networking | Linux networking expert for iptables, nftables, routing, DNS, and network troubleshooting | +| prometheus | Prometheus monitoring expert for PromQL, alerting rules, Grafana dashboards, and observability | +| sentry | Sentry error tracking and debugging specialist | +| shell-scripting | Shell scripting expert for Bash, POSIX compliance, error handling, and automation | +| sysadmin | System administration expert for Linux, macOS, Windows, services, and monitoring | + +### Security + +| Name | Description | +|------|-------------| +| compliance | Compliance expert for SOC 2, GDPR, HIPAA, PCI-DSS, and security frameworks | +| crypto-expert | Cryptography expert for TLS, symmetric/asymmetric encryption, hashing, and key management | +| security-audit | Security audit expert for OWASP Top 10, CVE analysis, code review, and penetration testing methodology | + +### AI and Machine Learning + +| Name | Description | +|------|-------------| +| llm-finetuning | LLM fine-tuning expert for LoRA, QLoRA, dataset preparation, and training optimization | +| ml-engineer | Machine learning engineer expert for PyTorch, scikit-learn, model evaluation, and MLOps | +| prompt-engineer | Prompt engineering expert for chain-of-thought, few-shot learning, evaluation, and LLM optimization | +| web-search | Web search and research specialist for finding and synthesizing information | + +### Productivity Tools + +| Name | Description | +|------|-------------| +| confluence | Confluence wiki expert for page structure, spaces, macros, and content organization | +| figma-expert | Figma design expert for components, auto-layout, design systems, and developer handoff | +| jira | Jira project management expert for issues, sprints, workflows, and reporting | +| linear-tools | Linear project management expert for issues, cycles, projects, and workflow automation | +| notion | Notion workspace management and content creation specialist | +| pdf-reader | PDF content extraction and analysis specialist | +| slack-tools | Slack workspace management and automation specialist | + +### Writing and Communication + +| Name | Description | +|------|-------------| +| email-writer | Professional email writing expert for tone, structure, clarity, and business communication | +| presentation | Presentation expert for slide structure, storytelling, visual design, and audience engagement | +| technical-writer | Technical writing expert for API docs, READMEs, ADRs, and developer documentation | +| writing-coach | Writing improvement specialist for grammar, style, clarity, and structure | + +### Engineering Practice + +| Name | Description | +|------|-------------| +| api-tester | API testing expert for curl, REST, GraphQL, authentication, and debugging | +| code-reviewer | Code review specialist focused on patterns, bugs, security, and performance | +| data-analyst | Data analysis expert for statistics, visualization, pandas, and exploration | +| data-pipeline | Data pipeline expert for ETL, Apache Spark, Airflow, dbt, and data quality | +| interview-prep | Technical interview preparation expert for algorithms, system design, and behavioral questions | +| project-manager | Project management expert for Agile, estimation, risk management, and stakeholder communication | +| regex-expert | Regular expression expert for crafting, debugging, and explaining patterns | + ## Adding a New Skill 1. Create `skills//SKILL.md` with frontmatter (`name`, `description`) and the prompt body.