feat: comprehensive registry improvements

Community docs:
- CODE_OF_CONDUCT.md (Contributor Covenant v2.1)
- SECURITY.md (vulnerability reporting policy)
- CHANGELOG.md (initial release notes)
- CODEOWNERS (per-type review ownership)

GitHub config:
- Issue templates: bug-report, pricing-correction, documentation
- FUNDING.yml (GitHub Sponsors)

Validation enhancements:
- Cross-reference check: hand [[requires]] → integration existence
- Routing alias collisions as warnings (errors with --strict)
- --strict flag to promote warnings to errors
- --type filter to validate single content type
- CI: add taplo format check and lychee link check jobs

Developer experience:
- Makefile with validate, fmt, and scaffold targets
- Scaffold templates for all 5 content types
- .pre-commit-config.yaml (trailing whitespace, TOML check, validate)
- docs/content-guide.md (naming, descriptions, prompts, decision guide)

Content quality:
- schema.toml: add last_verified field for model pricing
- CONTRIBUTING.md: add pricing verification guide with source links
This commit is contained in:
Evan Hu committed 2026-03-21 02:46:04 +09:00
1 parent 6cc5c745be
commit a8b7c9d08b
20 files changed
+670 -18

No files matched your search

+1
View File
@@ -0,0 +1 @@
github: [librefang]
+49
View File
@@ -0,0 +1,49 @@
name: Bug Report
description: Report an issue with existing registry content (wrong data, broken config, etc.)
labels: ["bug"]
body:
- type: dropdown
id: content_type
attributes:
label: Content Type
description: What type of registry content has the issue?
options:
- Provider
- Agent
- Hand
- Integration (MCP server)
- Skill
- Plugin
validations:
required: true
- type: input
id: content_name
attributes:
label: Content Name
description: The name or ID of the affected content.
placeholder: e.g. openai, code-review-agent, github
validations:
required: true
- type: textarea
id: whats_wrong
attributes:
label: What's Wrong
description: Describe the issue you found.
placeholder: |
e.g. The integration command listed in the registry fails to install,
or the agent config references a model that doesn't exist.
validations:
required: true
- type: textarea
id: expected_vs_actual
attributes:
label: Expected vs Actual
description: What did you expect, and what actually happened?
placeholder: |
Expected: The provider config should list gpt-4o as a supported model.
Actual: gpt-4o is missing from the models array.
validations:
required: true
+23
View File
@@ -0,0 +1,23 @@
name: Documentation Issue
description: Report incorrect, incomplete, or missing documentation
labels: ["documentation"]
body:
- type: input
id: which_document
attributes:
label: Which Document
description: The file path or page where the issue exists.
placeholder: e.g. README.md, docs/contributing.md, providers/openai.toml
validations:
required: true
- type: textarea
id: whats_wrong
attributes:
label: What's Wrong or Missing
description: Describe the documentation issue.
placeholder: |
e.g. The contributing guide doesn't explain how to add a new provider,
or the README setup instructions are outdated.
validations:
required: true
@@ -0,0 +1,44 @@
name: Pricing Correction
description: Report outdated or incorrect model pricing
labels: ["pricing"]
body:
- type: input
id: provider
attributes:
label: Provider Name
description: Which provider's pricing needs correction?
placeholder: e.g. openai, anthropic, groq
validations:
required: true
- type: input
id: model_id
attributes:
label: Model ID
description: The canonical model identifier.
placeholder: e.g. gpt-4o, claude-sonnet-4-20250514
validations:
required: true
- type: input
id: current_pricing
attributes:
label: Current Pricing in Registry
description: What does the registry currently show?
placeholder: "e.g. Input: $5.00 / 1M tokens, Output: $15.00 / 1M tokens"
validations:
required: true
- type: textarea
id: correct_pricing
attributes:
label: Correct Pricing (with source)
description: |
Provide the correct pricing and a link to the official source
so we can verify the update.
placeholder: |
Input: $2.50 / 1M tokens
Output: $10.00 / 1M tokens
Source: https://openai.com/pricing
validations:
required: true
+27
View File
@@ -18,3 +18,30 @@ jobs:
- name: Validate registry
run: python scripts/validate.py
toml-format-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Install taplo
run: |
curl -fsSL https://github.com/tamasfe/taplo/releases/latest/download/taplo-full-linux-x86_64.gz \
| gunzip > /usr/local/bin/taplo
chmod +x /usr/local/bin/taplo
- name: Check TOML formatting
continue-on-error: true
run: taplo fmt --check **/*.toml
markdown-link-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Check markdown links
uses: lycheeverse/lychee-action@v2
with:
args: --verbose --no-progress '**/*.md'
fail: false
continue-on-error: true
+16
View File
@@ -0,0 +1,16 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-toml
- repo: local
hooks:
- id: validate-registry
name: Validate registry TOML files
entry: python3 scripts/validate.py
language: system
pass_filenames: false
always_run: true
+23
View File
@@ -0,0 +1,23 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/).
## [Unreleased]
## [1.0.0] - 2026-03-21
### Added
- 46 LLM providers with 220+ model definitions
- 33 agent definitions across diverse domains
- 14 hand definitions (communication, content, data, development, productivity)
- 25 MCP integration templates
- 2 skill examples (prompt-only and Python)
- 1 plugin example (echo-memory)
- Validation script with per-type and cross-type checks
- CI workflow for automated validation
- README documentation for every directory and subdirectory
- CONTRIBUTING guide with per-type examples and checklists
- Schema reference (schema.toml)
+12
View File
@@ -0,0 +1,12 @@
# LibreFang Registry — Code Owners
# Each line maps a path pattern to the team responsible for review.
providers/ @librefang/models
agents/ @librefang/agents
hands/ @librefang/agents
integrations/ @librefang/integrations
skills/ @librefang/agents
plugins/ @librefang/agents
scripts/ @librefang/core
.github/ @librefang/core
*.md @librefang/docs
+29
View File
@@ -0,0 +1,29 @@
# Code of Conduct
## Our Pledge
We pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to a positive environment:
- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
Examples of unacceptable behavior:
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information without explicit permission
- Other conduct which could reasonably be considered inappropriate
## Enforcement
Instances of unacceptable behavior may be reported to **team@librefang.dev**. All complaints will be reviewed and investigated promptly and fairly.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/), version 2.1.
+25
View File
@@ -222,6 +222,31 @@ aliases = ["short-name"]
- [ ] `context_window` and `max_output_tokens` are positive integers
- [ ] Boolean capability fields are correct
- [ ] Pricing verified from official source
- [ ] `last_verified` date included (ISO format, e.g. `2025-03-15`)
### Pricing Verification
**Always verify pricing from official sources before submitting.** Model pricing changes frequently and stale data leads to incorrect cost tracking for users.
When adding or updating model pricing:
1. Check the provider's official pricing page (see links below)
2. Record the exact `input_cost_per_m` and `output_cost_per_m` values in USD per million tokens
3. Include the `last_verified` field with today's date in ISO format (`YYYY-MM-DD`)
4. If a model is subscription-based (e.g. GitHub Copilot) or has no public per-token pricing, note this in your PR description
Common official pricing pages:
- **OpenAI**: https://openai.com/pricing
- **Anthropic**: https://docs.anthropic.com/en/docs/about-claude/models
- **Google Gemini**: https://ai.google.dev/pricing
- **DeepSeek**: https://platform.deepseek.com/api-docs/pricing
- **Mistral**: https://mistral.ai/technology/#pricing
- **Groq**: https://wow.groq.com/
- **xAI**: https://docs.x.ai/docs
- **Together**: https://www.together.ai/pricing
- **Fireworks**: https://fireworks.ai/pricing
- **OpenRouter**: https://openrouter.ai/models (per-model pricing listed)
## Where to Find Model Information
+105
View File
@@ -0,0 +1,105 @@
# LibreFang Registry — Development Tooling
# Usage: make help
.DEFAULT_GOAL := help
SHELL := /bin/bash
TEMPLATES_DIR := templates
AGENTS_DIR := agents
HANDS_DIR := hands
INTEGRATIONS_DIR := integrations
SKILLS_DIR := skills
PROVIDERS_DIR := providers
# ── Validation ────────────────────────────────────────────────────────────────
.PHONY: validate
validate: ## Run registry validation
python3 scripts/validate.py
.PHONY: validate-strict
validate-strict: ## Run validation treating warnings as errors
python3 scripts/validate.py --strict
# ── Formatting ────────────────────────────────────────────────────────────────
.PHONY: fmt
fmt: ## Format all TOML files with taplo (skips if not installed)
@if command -v taplo >/dev/null 2>&1; then \
echo "Formatting TOML files..."; \
find . -name '*.toml' -not -path './.git/*' -exec taplo fmt {} +; \
echo "Done."; \
else \
echo "taplo not found — skipping TOML formatting."; \
echo "Install: cargo install taplo-cli or brew install taplo"; \
fi
.PHONY: fmt-check
fmt-check: ## Check TOML formatting without modifying
@if command -v taplo >/dev/null 2>&1; then \
taplo fmt --check $$(find . -name '*.toml' -not -path './.git/*'); \
else \
echo "taplo not found — skipping format check."; \
echo "Install: cargo install taplo-cli or brew install taplo"; \
fi
# ── Scaffolding ───────────────────────────────────────────────────────────────
.PHONY: new-agent
new-agent: ## Scaffold a new agent (usage: make new-agent NAME=my-agent)
@if [ -z "$(NAME)" ]; then echo "ERROR: NAME is required. Usage: make new-agent NAME=my-agent"; exit 1; fi
@if [ -d "$(AGENTS_DIR)/$(NAME)" ]; then echo "ERROR: Agent '$(NAME)' already exists."; exit 1; fi
@mkdir -p "$(AGENTS_DIR)/$(NAME)"
@sed 's/{{NAME}}/$(NAME)/g' "$(TEMPLATES_DIR)/agent.toml" > "$(AGENTS_DIR)/$(NAME)/agent.toml"
@echo "Created $(AGENTS_DIR)/$(NAME)/agent.toml"
@echo "Next: edit the agent.toml to fill in TODO placeholders."
.PHONY: new-hand
new-hand: ## Scaffold a new hand (usage: make new-hand NAME=my-hand)
@if [ -z "$(NAME)" ]; then echo "ERROR: NAME is required. Usage: make new-hand NAME=my-hand"; exit 1; fi
@if [ -d "$(HANDS_DIR)/$(NAME)" ]; then echo "ERROR: Hand '$(NAME)' already exists."; exit 1; fi
@mkdir -p "$(HANDS_DIR)/$(NAME)"
@sed 's/{{NAME}}/$(NAME)/g' "$(TEMPLATES_DIR)/HAND.toml" > "$(HANDS_DIR)/$(NAME)/HAND.toml"
@echo "Created $(HANDS_DIR)/$(NAME)/HAND.toml"
@echo "Next: edit the HAND.toml to fill in TODO placeholders."
.PHONY: new-integration
new-integration: ## Scaffold a new integration (usage: make new-integration NAME=my-service)
@if [ -z "$(NAME)" ]; then echo "ERROR: NAME is required. Usage: make new-integration NAME=my-service"; exit 1; fi
@if [ -f "$(INTEGRATIONS_DIR)/$(NAME).toml" ]; then echo "ERROR: Integration '$(NAME)' already exists."; exit 1; fi
@sed 's/{{NAME}}/$(NAME)/g' "$(TEMPLATES_DIR)/integration.toml" > "$(INTEGRATIONS_DIR)/$(NAME).toml"
@echo "Created $(INTEGRATIONS_DIR)/$(NAME).toml"
@echo "Next: edit the file to fill in TODO placeholders."
.PHONY: new-skill
new-skill: ## Scaffold a new skill (usage: make new-skill NAME=my-skill)
@if [ -z "$(NAME)" ]; then echo "ERROR: NAME is required. Usage: make new-skill NAME=my-skill"; exit 1; fi
@if [ -d "$(SKILLS_DIR)/$(NAME)" ]; then echo "ERROR: Skill '$(NAME)' already exists."; exit 1; fi
@mkdir -p "$(SKILLS_DIR)/$(NAME)"
@sed 's/{{NAME}}/$(NAME)/g' "$(TEMPLATES_DIR)/skill.toml" > "$(SKILLS_DIR)/$(NAME)/skill.toml"
@echo "Created $(SKILLS_DIR)/$(NAME)/skill.toml"
@echo "Next: edit the skill.toml to fill in TODO placeholders."
.PHONY: new-provider
new-provider: ## Scaffold a new provider (usage: make new-provider NAME=my-provider)
@if [ -z "$(NAME)" ]; then echo "ERROR: NAME is required. Usage: make new-provider NAME=my-provider"; exit 1; fi
@if [ -f "$(PROVIDERS_DIR)/$(NAME).toml" ]; then echo "ERROR: Provider '$(NAME)' already exists."; exit 1; fi
@sed 's/{{NAME}}/$(NAME)/g' "$(TEMPLATES_DIR)/provider.toml" > "$(PROVIDERS_DIR)/$(NAME).toml"
@echo "Created $(PROVIDERS_DIR)/$(NAME).toml"
@echo "Next: edit the file to fill in TODO placeholders."
# ── Help ──────────────────────────────────────────────────────────────────────
.PHONY: help
help: ## Show this help
@echo "LibreFang Registry — Available targets:"
@echo ""
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \
awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-20s\033[0m %s\n", $$1, $$2}'
@echo ""
@echo "Scaffold examples:"
@echo " make new-agent NAME=my-agent"
@echo " make new-hand NAME=my-hand"
@echo " make new-integration NAME=my-service"
@echo " make new-skill NAME=my-skill"
@echo " make new-provider NAME=my-provider"
+34
View File
@@ -0,0 +1,34 @@
# Security Policy
## Scope
This repository contains TOML content definitions (agents, hands, integrations, skills, plugins, providers). Security concerns include:
- Malicious content in system prompts or descriptions
- Command injection in integration transport commands
- Integration URLs pointing to phishing or malicious sites
- Credential exposure in TOML files
## Reporting a Vulnerability
**Do NOT open a public issue for security vulnerabilities.**
Email **security@librefang.dev** with:
1. Description of the vulnerability
2. Affected file(s) and content type
3. Steps to reproduce or exploit
4. Suggested fix (if any)
## Response Timeline
- **Acknowledgment**: within 48 hours
- **Assessment**: within 5 business days
- **Fix**: dependent on severity, typically within 2 weeks
## Supported Versions
| Version | Supported |
|---------|-----------|
| main branch | Yes |
| Other branches | No |
+50
View File
@@ -0,0 +1,50 @@
# Content Guide
Guidelines for contributing content to the LibreFang Registry.
## Naming Conventions
- Use **lowercase, hyphenated** names: `my-agent`, `web-scraper`, `code-reviewer`.
- Agent/hand/skill directory names must match their `name`/`id` field in the TOML.
- Provider and integration filenames must match their `id` field.
## Writing Descriptions
- Keep descriptions to **1-2 sentences**. Lead with a verb.
- Good: "Analyzes pull requests and suggests improvements."
- Bad: "This is an agent that can be used to analyze pull requests."
## System Prompts (Agents & Hands)
- Start with a clear role statement: "You are X, responsible for Y."
- Include specific instructions on behavior, not vague aspirations.
- Define what the agent should **not** do (scope boundaries).
- List tools it should use and when.
- Aim for **100-500 words** for agents, up to 1000 for complex hands.
- Avoid repeating information already in the TOML metadata.
## Agent vs Hand vs Skill
| Type | Use When |
|------|----------|
| **Agent** | Conversational, general-purpose, stateless Q&A or analysis. |
| **Hand** | Multi-step workflow requiring tools (shell, files, APIs). Has settings, dashboard, requirements. |
| **Skill** | Single focused task with defined inputs/outputs. Prompt-only or a short script. |
- If it needs `shell_exec` or external tools, it is probably a **hand**.
- If it is a reusable prompt template with parameters, it is a **skill**.
- If it is a conversational assistant for a domain, it is an **agent**.
## Provider Entries
- Include all models the provider offers that support chat completions.
- Use accurate `input_cost_per_m` / `output_cost_per_m` (USD per million tokens).
- Set `tier` honestly: `frontier` is reserved for the most capable models.
- Always include `context_window` and `max_output_tokens` from official docs.
## General Tips
- Run `make validate` before submitting.
- Run `make fmt` if you have taplo installed to keep TOML formatting consistent.
- Check `schema.toml` for the full field reference.
- Test scaffold output: `make new-agent NAME=test-agent`, verify, then delete.
+1
View File
@@ -27,6 +27,7 @@ context_window = 128000 # Required: maximum input tokens
max_output_tokens = 16384 # Required: maximum output tokens
input_cost_per_m = 2.50 # Required: USD per million input tokens (0.0 for free/local)
output_cost_per_m = 10.0 # Required: USD per million output tokens (0.0 for free/local)
last_verified = "2025-03-15" # Optional: ISO date when pricing was last verified against official sources
supports_tools = true # Optional: tool/function calling support (default: false)
supports_vision = true # Optional: vision/image input support (default: false)
supports_streaming = true # Optional: streaming response support (default: true)
+95 -18
View File
@@ -3,6 +3,9 @@
Usage:
python scripts/validate.py
python scripts/validate.py --strict
python scripts/validate.py --type providers
python scripts/validate.py --strict --type agents
Validates:
- Provider TOML files (required fields, valid tiers, non-negative costs, no duplicates)
@@ -11,11 +14,13 @@ Validates:
- Integration TOML files (required fields: id, name, [transport])
- Skill TOML files (required fields: [skill].name, [runtime].type)
- aliases.toml parsing
- Cross-reference: hand [[requires]] integration references
- Routing alias collision detection (WARNING, ERROR with --strict)
Exit code 0 on success, 1 on any validation error.
"""
import os
import argparse
import sys
from pathlib import Path
@@ -42,6 +47,8 @@ REQUIRED_MODEL_FIELDS = {
"input_cost_per_m", "output_cost_per_m",
}
VALID_CONTENT_TYPES = {"providers", "agents", "hands", "integrations", "skills", "plugins", "aliases"}
def load_toml(filepath: Path) -> tuple[dict | None, str | None]:
"""Load a TOML file, return (data, error)."""
@@ -126,8 +133,14 @@ def validate_agent_file(filepath: Path) -> list[str]:
return errors
def validate_hand_file(filepath: Path) -> list[str]:
"""Validate a HAND.toml file."""
def validate_hand_file(filepath: Path, integration_ids: set[str]) -> list[str]:
"""Validate a HAND.toml file.
Args:
filepath: Path to the HAND.toml file.
integration_ids: Set of known integration IDs (filenames without .toml
from the integrations/ directory) for cross-reference validation.
"""
data, err = load_toml(filepath)
if err:
return [err]
@@ -152,6 +165,19 @@ def validate_hand_file(filepath: Path) -> list[str]:
if "agent" not in data:
errors.append(f"{rel}: Missing [agent] section")
# Cross-reference: check that [[requires]] with requirement_type = "integration"
# reference existing integration TOML files
requires_list = data.get("requires", [])
if isinstance(requires_list, list):
for req in requires_list:
if isinstance(req, dict) and req.get("requirement_type") == "integration":
req_key = req.get("key", "")
if req_key and req_key not in integration_ids:
errors.append(
f"{rel}: [[requires]] references integration '{req_key}' "
f"but no integrations/{req_key}.toml exists"
)
return errors
@@ -233,16 +259,52 @@ def validate_aliases_file(filepath: Path) -> list[str]:
return errors
def parse_args() -> argparse.Namespace:
"""Parse command-line arguments."""
parser = argparse.ArgumentParser(
description="Validate all TOML files in the LibreFang registry."
)
parser.add_argument(
"--strict",
action="store_true",
help="Treat all warnings as errors.",
)
parser.add_argument(
"--type",
choices=sorted(VALID_CONTENT_TYPES),
dest="content_type",
default=None,
help="Validate only the specified content type (e.g. providers, agents, hands).",
)
return parser.parse_args()
def should_validate(content_type: str, filter_type: str | None) -> bool:
"""Check whether a content type should be validated given the --type filter."""
if filter_type is None:
return True
return content_type == filter_type
def main():
args = parse_args()
script_dir = Path(__file__).resolve().parent
root = script_dir.parent
all_errors = []
stats = {}
# --- Collect integration IDs for cross-reference validation ---
integrations_dir = root / "integrations"
integration_ids: set[str] = set()
if integrations_dir.is_dir():
for fp in integrations_dir.glob("*.toml"):
integration_ids.add(fp.stem)
# --- Providers ---
providers_dir = root / "providers"
if providers_dir.is_dir():
if providers_dir.is_dir() and should_validate("providers", args.content_type):
toml_files = sorted(providers_dir.glob("*.toml"))
total_models = 0
global_model_ids = {}
@@ -273,7 +335,7 @@ def main():
# --- Agents ---
agents_dir = root / "agents"
if agents_dir.is_dir():
if agents_dir.is_dir() and should_validate("agents", args.content_type):
agent_dirs = sorted([d for d in agents_dir.iterdir() if d.is_dir() and not d.name.startswith(".")])
for d in agent_dirs:
agent_toml = d / "agent.toml"
@@ -285,19 +347,18 @@ def main():
# --- Hands ---
hands_dir = root / "hands"
if hands_dir.is_dir():
if hands_dir.is_dir() and should_validate("hands", args.content_type):
hand_dirs = sorted([d for d in hands_dir.iterdir() if d.is_dir() and not d.name.startswith(".")])
for d in hand_dirs:
hand_toml = d / "HAND.toml"
if hand_toml.exists():
all_errors.extend(validate_hand_file(hand_toml))
all_errors.extend(validate_hand_file(hand_toml, integration_ids))
else:
all_errors.append(f"hands/{d.name}: Missing HAND.toml")
stats["hands"] = len(hand_dirs)
# --- Integrations ---
integrations_dir = root / "integrations"
if integrations_dir.is_dir():
if integrations_dir.is_dir() and should_validate("integrations", args.content_type):
int_files = sorted(integrations_dir.glob("*.toml"))
for fp in int_files:
all_errors.extend(validate_integration_file(fp))
@@ -305,7 +366,7 @@ def main():
# --- Skills ---
skills_dir = root / "skills"
if skills_dir.is_dir():
if skills_dir.is_dir() and should_validate("skills", args.content_type):
skill_dirs = sorted([d for d in skills_dir.iterdir() if d.is_dir() and not d.name.startswith(".")])
for d in skill_dirs:
skill_toml = d / "skill.toml"
@@ -317,7 +378,7 @@ def main():
# --- Plugins ---
plugins_dir = root / "plugins"
if plugins_dir.is_dir():
if plugins_dir.is_dir() and should_validate("plugins", args.content_type):
plugin_dirs = sorted([d for d in plugins_dir.iterdir() if d.is_dir() and not d.name.startswith(".")])
for d in plugin_dirs:
plugin_toml = d / "plugin.toml"
@@ -342,14 +403,18 @@ def main():
stats["plugins"] = len(plugin_dirs)
# --- Aliases ---
all_errors.extend(validate_aliases_file(root / "aliases.toml"))
if should_validate("aliases", args.content_type):
all_errors.extend(validate_aliases_file(root / "aliases.toml"))
# --- Cross-type: duplicate routing aliases ---
# --- Cross-type: duplicate routing aliases (now treated as ERRORS) ---
# Only run this cross-type check when no --type filter is active,
# or when filtering to agents or hands specifically.
all_aliases = {} # alias -> (type, name)
warnings = []
alias_collisions = []
run_alias_check = args.content_type is None or args.content_type in ("agents", "hands")
# Collect agent routing aliases
if agents_dir.is_dir():
if run_alias_check and agents_dir.is_dir():
for d in sorted([d for d in agents_dir.iterdir() if d.is_dir() and not d.name.startswith(".")]):
data, _ = load_toml(d / "agent.toml")
if data:
@@ -358,12 +423,12 @@ def main():
key = alias.lower()
if key in all_aliases:
prev_type, prev_name = all_aliases[key]
warnings.append(f"Routing alias '{alias}' used by both {prev_type}/{prev_name} and agent/{d.name}")
alias_collisions.append(f"Routing alias '{alias}' used by both {prev_type}/{prev_name} and agent/{d.name}")
else:
all_aliases[key] = ("agent", d.name)
# Collect hand routing aliases
if hands_dir.is_dir():
if run_alias_check and hands_dir.is_dir():
for d in sorted([d for d in hands_dir.iterdir() if d.is_dir() and not d.name.startswith(".")]):
data, _ = load_toml(d / "HAND.toml")
if data:
@@ -372,13 +437,25 @@ def main():
key = alias.lower()
if key in all_aliases:
prev_type, prev_name = all_aliases[key]
warnings.append(f"Routing alias '{alias}' used by both {prev_type}/{prev_name} and hand/{d.name}")
alias_collisions.append(f"Routing alias '{alias}' used by both {prev_type}/{prev_name} and hand/{d.name}")
else:
all_aliases[key] = ("hand", d.name)
# --- Collect warnings ---
warnings = list(alias_collisions)
# --- In --strict mode, promote warnings to errors ---
if args.strict and warnings:
all_errors.extend(warnings)
warnings = []
# --- Report ---
print("=" * 60)
print("LibreFang Registry Validation")
if args.content_type:
print(f" Filter: --type {args.content_type}")
if args.strict:
print(" Mode: --strict (warnings are errors)")
print("=" * 60)
print()
+33
View File
@@ -0,0 +1,33 @@
id = "{{NAME}}"
name = "TODO: Display Name"
description = "TODO: One-sentence description of what this hand does."
category = "productivity" # communication | content | data | development | devops | finance | productivity | research | social
icon = "TODO"
tools = ["shell_exec", "file_read", "file_write", "file_list", "memory_store", "memory_recall"]
[routing]
aliases = ["TODO: activation phrases"]
weak_aliases = ["TODO: keyword hints"]
[agent]
name = "{{NAME}}-hand"
description = "TODO: Agent description"
module = "builtin:chat"
provider = "default"
model = "default"
max_tokens = 8192
temperature = 0.4
max_iterations = 30
system_prompt = """TODO: Write a detailed system prompt for the hand's agent.
Define:
- The hand's purpose and capabilities
- Step-by-step workflow it follows
- Tools it should use and how
- Output format and reporting
"""
[metadata]
frequency = "on-demand" # continuous | on-demand | scheduled
token_consumption = "medium" # low | medium | high
default_active = true
+32
View File
@@ -0,0 +1,32 @@
name = "{{NAME}}"
version = "0.1.0"
description = "TODO: One-sentence description of what this agent does."
author = "TODO"
module = "builtin:chat"
[metadata.routing]
aliases = ["TODO: exact match phrases"]
weak_aliases = ["TODO: partial match keywords"]
[model]
provider = "default"
model = "default"
max_tokens = 4096
temperature = 0.7
system_prompt = """TODO: Write a clear system prompt that defines:
- Who the agent is and its role
- What it should and should not do
- How it should format responses
- Any domain-specific instructions
Keep it focused and under 500 words."""
[resources]
max_llm_tokens_per_hour = 100000
[capabilities]
tools = ["web_search", "web_fetch", "memory_store", "memory_recall"]
network = ["*"]
memory_read = ["*"]
memory_write = ["self.*"]
agent_spawn = false
+29
View File
@@ -0,0 +1,29 @@
id = "{{NAME}}"
name = "TODO: Service Display Name"
description = "TODO: One-sentence description of this integration."
category = "devtools" # devtools | communication | storage | monitoring | data | productivity
icon = "TODO"
tags = ["TODO"]
[transport]
type = "stdio"
command = "npx"
args = ["-y", "TODO: @scope/mcp-server-package"]
[[required_env]]
name = "TODO_API_KEY"
label = "TODO: API Key"
help = "TODO: How to obtain this key"
is_secret = true
get_url = "https://example.com/settings"
[health_check]
interval_secs = 60
unhealthy_threshold = 3
setup_instructions = """
TODO: Step-by-step setup instructions.
1. Go to ...
2. Create an API key with ...
3. Paste the key above.
"""
+22
View File
@@ -0,0 +1,22 @@
# TODO: Provider Name — https://example.com
# Models: 1
[provider]
id = "{{NAME}}"
display_name = "TODO: Provider Display Name"
api_key_env = "TODO_API_KEY"
base_url = "https://api.example.com/v1"
key_required = true
[[models]]
id = "TODO-model-id"
display_name = "TODO: Model Display Name"
tier = "balanced" # frontier | smart | balanced | fast | local
context_window = 128000
max_output_tokens = 4096
input_cost_per_m = 0.0
output_cost_per_m = 0.0
supports_tools = true
supports_vision = false
supports_streaming = true
aliases = []
+20
View File
@@ -0,0 +1,20 @@
[skill]
name = "{{NAME}}"
version = "0.1.0"
description = "TODO: One-sentence description of what this skill does."
author = "TODO"
tags = ["TODO"]
[runtime]
type = "promptonly"
[input]
topic = { type = "string", description = "TODO: Describe this input parameter", required = true }
[prompt]
template = """TODO: Write the prompt template for this skill.
Use {{topic}} to reference input parameters.
Be specific about the desired output format and constraints.
"""