From fc92ff0cbe8af3ba01b94efb1da7b14fe9b4d2b4 Mon Sep 17 00:00:00 2001 From: Evan Hu Date: Thu, 26 Mar 2026 14:03:25 +0900 Subject: [PATCH 1/2] feat: convert schema.toml to machine-parseable format Replace comment-based documentation format with structured TOML that can be deserialized into the RegistrySchema Rust type. All 6 content types (provider, agent, hand, integration, skill, plugin) preserved with every field, description, enum option, and nested section. --- schema.toml | 1028 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 849 insertions(+), 179 deletions(-) diff --git a/schema.toml b/schema.toml index f4cef7a..6d6fe89 100644 --- a/schema.toml +++ b/schema.toml @@ -1,207 +1,877 @@ -# LibreFang Registry Schema Reference -# ==================================== -# This file documents all available fields and their types for each content type. -# It is NOT a real definition — it exists purely as documentation. +# LibreFang Registry Schema +# ========================= +# Machine-parseable schema definition for all registry content types. +# Consumed by the RegistrySchema Rust type (librefang-types). # ═══════════════════════════════════════════════════════════════════════════════ -# PROVIDER / MODEL SCHEMA (providers/*.toml) +# PROVIDER / MODEL SCHEMA # ═══════════════════════════════════════════════════════════════════════════════ [provider] -id = "provider-id" # Required: unique provider identifier (lowercase, hyphenated) -display_name = "Provider Name" # Required: human-readable display name -api_key_env = "PROVIDER_API_KEY" # Required: environment variable name for the API key -base_url = "https://api.example.com" # Required: default API base URL -key_required = true # Required: whether an API key is needed (false for local providers) - -[[models]] -id = "model-id" # Required: unique model identifier (API model ID) -display_name = "Human Name" # Required: human-readable display name -tier = "smart" # Required: one of "frontier", "smart", "balanced", "fast", "local" -# frontier — cutting-edge, most capable (e.g. Claude Opus, GPT-4.1) -# smart — smart, cost-effective (e.g. Claude Sonnet, Gemini 2.5 Flash) -# balanced — balanced speed/cost -# fast — fastest, cheapest for simple tasks -# local — local models (Ollama, vLLM, LM Studio) -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) -aliases = ["alias1", "alias2"] # Optional: alternative names for this model +description = "LLM provider configuration" +file_pattern = "providers/*.toml" + +[provider.fields.id] +type = "string" +required = true +description = "Unique provider identifier (lowercase, hyphenated)" +example = "anthropic" + +[provider.fields.display_name] +type = "string" +required = true +description = "Human-readable display name" +example = "Anthropic" + +[provider.fields.api_key_env] +type = "string" +required = true +description = "Environment variable name for the API key" +example = "PROVIDER_API_KEY" + +[provider.fields.base_url] +type = "string" +required = true +description = "Default API base URL" +example = "https://api.example.com" + +[provider.fields.key_required] +type = "bool" +required = true +description = "Whether an API key is needed (false for local providers)" +example = true + +# --- Provider: nested [[models]] section --- + +[provider.sections.models] +description = "Model entries" +repeatable = true + +[provider.sections.models.fields.id] +type = "string" +required = true +description = "Unique model identifier (API model ID)" +example = "claude-sonnet-4-20250514" + +[provider.sections.models.fields.display_name] +type = "string" +required = true +description = "Human-readable display name" +example = "Claude Sonnet" + +[provider.sections.models.fields.tier] +type = "string" +required = true +description = "Capability tier: frontier (cutting-edge, most capable), smart (cost-effective), balanced (speed/cost), fast (cheapest for simple tasks), local (Ollama, vLLM, LM Studio)" +options = ["frontier", "smart", "balanced", "fast", "local"] +example = "smart" + +[provider.sections.models.fields.context_window] +type = "number" +required = true +description = "Maximum input tokens" +example = 128000 + +[provider.sections.models.fields.max_output_tokens] +type = "number" +required = true +description = "Maximum output tokens" +example = 16384 + +[provider.sections.models.fields.input_cost_per_m] +type = "number" +required = true +description = "USD per million input tokens (0.0 for free/local)" +example = 2.5 + +[provider.sections.models.fields.output_cost_per_m] +type = "number" +required = true +description = "USD per million output tokens (0.0 for free/local)" +example = 10.0 + +[provider.sections.models.fields.last_verified] +type = "string" +required = false +description = "ISO date when pricing was last verified against official sources" +example = "2025-03-15" + +[provider.sections.models.fields.supports_tools] +type = "bool" +required = false +description = "Tool/function calling support" +default = false + +[provider.sections.models.fields.supports_vision] +type = "bool" +required = false +description = "Vision/image input support" +default = false + +[provider.sections.models.fields.supports_streaming] +type = "bool" +required = false +description = "Streaming response support" +default = true + +[provider.sections.models.fields.aliases] +type = "array" +required = false +description = "Alternative names for this model" +item_type = "string" +example = ["alias1", "alias2"] # ═══════════════════════════════════════════════════════════════════════════════ -# AGENT SCHEMA (agents//agent.toml) +# AGENT SCHEMA # ═══════════════════════════════════════════════════════════════════════════════ -# Top-level fields: -# name = "agent-name" # Required: agent identifier, must match directory name -# version = "0.1.0" # Optional: semver version string -# description = "What this agent does" # Required: one-sentence description -# author = "author-name" # Optional: author or organization -# module = "builtin:chat" # Required: runtime module (builtin:chat, builtin:tool, etc.) -# -# [model] # Agent's LLM configuration -# provider = "default" # Optional: provider ID or "default" -# model = "default" # Optional: model ID or "default" -# max_tokens = 4096 # Optional: max response tokens -# temperature = 0.7 # Optional: sampling temperature (0.0–2.0) -# system_prompt = "..." # Required: behavioral instructions for the agent -# -# [metadata.routing] # Optional: routing configuration -# aliases = ["exact match phrases"] # Phrases that route directly to this agent -# weak_aliases = ["partial match keywords"] # Keywords that suggest this agent -# -# [resources] # Optional: resource limits -# max_llm_tokens_per_hour = 100000 # Token budget per hour -# -# [capabilities] # Optional: agent permissions -# tools = ["tool1", "tool2"] # List of allowed tool names -# network = ["*"] # Network access patterns ("*" = unrestricted) -# memory_read = ["*"] # Memory read permissions -# memory_write = ["self.*"] # Memory write permissions -# agent_spawn = false # Whether this agent can spawn sub-agents +[agent] +description = "Agent configuration" +file_pattern = "agents//agent.toml" + +[agent.fields.name] +type = "string" +required = true +description = "Agent identifier, must match directory name" +example = "agent-name" + +[agent.fields.version] +type = "string" +required = false +description = "Semver version string" +example = "0.1.0" + +[agent.fields.description] +type = "string" +required = true +description = "One-sentence description of what this agent does" +example = "What this agent does" + +[agent.fields.author] +type = "string" +required = false +description = "Author or organization" +example = "author-name" + +[agent.fields.module] +type = "string" +required = true +description = "Runtime module (builtin:chat, builtin:tool, etc.)" +example = "builtin:chat" + +# --- Agent: [model] section --- + +[agent.sections.model] +description = "Agent's LLM configuration" +repeatable = false + +[agent.sections.model.fields.provider] +type = "string" +required = false +description = "Provider ID or \"default\"" +example = "default" + +[agent.sections.model.fields.model] +type = "string" +required = false +description = "Model ID or \"default\"" +example = "default" + +[agent.sections.model.fields.max_tokens] +type = "number" +required = false +description = "Max response tokens" +example = 4096 + +[agent.sections.model.fields.temperature] +type = "number" +required = false +description = "Sampling temperature (0.0-2.0)" +example = 0.7 + +[agent.sections.model.fields.system_prompt] +type = "string" +required = true +description = "Behavioral instructions for the agent" + +# --- Agent: [metadata.routing] section --- + +[agent.sections.metadata] +description = "Agent metadata" +repeatable = false + +[agent.sections.metadata.sections.routing] +description = "Routing configuration" +repeatable = false + +[agent.sections.metadata.sections.routing.fields.aliases] +type = "array" +required = false +description = "Phrases that route directly to this agent" +item_type = "string" +example = ["exact match phrases"] + +[agent.sections.metadata.sections.routing.fields.weak_aliases] +type = "array" +required = false +description = "Keywords that suggest this agent" +item_type = "string" +example = ["partial match keywords"] + +# --- Agent: [resources] section --- + +[agent.sections.resources] +description = "Resource limits" +repeatable = false + +[agent.sections.resources.fields.max_llm_tokens_per_hour] +type = "number" +required = false +description = "Token budget per hour" +example = 100000 + +# --- Agent: [capabilities] section --- + +[agent.sections.capabilities] +description = "Agent permissions" +repeatable = false + +[agent.sections.capabilities.fields.tools] +type = "array" +required = false +description = "List of allowed tool names" +item_type = "string" +example = ["tool1", "tool2"] + +[agent.sections.capabilities.fields.network] +type = "array" +required = false +description = "Network access patterns (\"*\" = unrestricted)" +item_type = "string" +example = ["*"] + +[agent.sections.capabilities.fields.memory_read] +type = "array" +required = false +description = "Memory read permissions" +item_type = "string" +example = ["*"] + +[agent.sections.capabilities.fields.memory_write] +type = "array" +required = false +description = "Memory write permissions" +item_type = "string" +example = ["self.*"] + +[agent.sections.capabilities.fields.agent_spawn] +type = "bool" +required = false +description = "Whether this agent can spawn sub-agents" +default = false # ═══════════════════════════════════════════════════════════════════════════════ -# HAND SCHEMA (hands//HAND.toml) +# HAND SCHEMA # ═══════════════════════════════════════════════════════════════════════════════ -# Top-level fields: -# id = "hand-id" # Required: unique identifier, must match directory name -# name = "Hand Name" # Required: human-readable display name -# description = "What this hand does" # Required: one-sentence description -# category = "productivity" # Required: one of "communication", "content", "data", -# # "development", "devops", "finance", "productivity", -# # "research", "social" -# icon = "🌐" # Optional: emoji icon -# tools = ["tool1", "tool2"] # Required: list of tool names this hand uses -# -# [routing] # Optional: routing configuration -# aliases = ["activate phrases"] -# weak_aliases = ["keyword hints"] -# -# [[requires]] # Optional: external dependencies (repeatable) -# key = "python3" # Unique dependency key -# label = "Python 3" # Human-readable label -# requirement_type = "binary" # "binary", "package", "service" -# check_value = "python3" # Binary name or check command -# optional = false # Whether the dependency is optional -# description = "Why this is needed" -# [requires.install] # Platform-specific install instructions -# macos = "brew install python3" -# windows = "winget install Python.Python.3.12" -# linux_apt = "sudo apt install python3" -# manual_url = "https://..." -# -# [[settings]] # Optional: user-configurable settings (repeatable) -# key = "setting_key" # Unique setting key -# label = "Setting Label" # Human-readable label -# description = "What this controls" -# setting_type = "toggle" # "toggle", "select", "text", "number" -# default = "true" # Default value as string -# [[settings.options]] # For "select" type: available options -# value = "option1" -# label = "Option Label" -# -# [agent] # Required: the agent that powers this hand -# name = "hand-agent-name" -# description = "Agent description" -# module = "builtin:chat" -# provider = "default" -# model = "default" -# max_tokens = 16384 -# temperature = 0.3 -# max_iterations = 60 -# system_prompt = "..." # Detailed behavioral prompt -# -# [dashboard] # Optional: dashboard metrics -# [[dashboard.metrics]] -# label = "Metric Name" -# memory_key = "metric_memory_key" -# format = "number" # "number", "currency", "percentage" -# -# [metadata] # Optional: operational metadata -# frequency = "continuous" # "continuous", "on-demand", "scheduled" -# token_consumption = "low" # "low", "medium", "high" -# default_active = true # Whether active by default +[hand] +description = "Hand configuration (a hand is a user-facing capability backed by an agent)" +file_pattern = "hands//HAND.toml" + +[hand.fields.id] +type = "string" +required = true +description = "Unique identifier, must match directory name" +example = "hand-id" + +[hand.fields.name] +type = "string" +required = true +description = "Human-readable display name" +example = "Hand Name" + +[hand.fields.description] +type = "string" +required = true +description = "One-sentence description of what this hand does" +example = "What this hand does" + +[hand.fields.category] +type = "string" +required = true +description = "Hand category" +options = ["communication", "content", "data", "development", "devops", "finance", "productivity", "research", "social"] +example = "productivity" + +[hand.fields.icon] +type = "string" +required = false +description = "Emoji icon" + +[hand.fields.tools] +type = "array" +required = true +description = "List of tool names this hand uses" +item_type = "string" +example = ["tool1", "tool2"] + +# --- Hand: [routing] section --- + +[hand.sections.routing] +description = "Routing configuration" +repeatable = false + +[hand.sections.routing.fields.aliases] +type = "array" +required = false +description = "Phrases that activate this hand" +item_type = "string" +example = ["activate phrases"] + +[hand.sections.routing.fields.weak_aliases] +type = "array" +required = false +description = "Keyword hints for routing" +item_type = "string" +example = ["keyword hints"] + +# --- Hand: [[requires]] section --- + +[hand.sections.requires] +description = "External dependencies" +repeatable = true + +[hand.sections.requires.fields.key] +type = "string" +required = true +description = "Unique dependency key" +example = "python3" + +[hand.sections.requires.fields.label] +type = "string" +required = true +description = "Human-readable label" +example = "Python 3" + +[hand.sections.requires.fields.requirement_type] +type = "string" +required = true +description = "Type of requirement" +options = ["binary", "package", "service"] +example = "binary" + +[hand.sections.requires.fields.check_value] +type = "string" +required = true +description = "Binary name or check command" +example = "python3" + +[hand.sections.requires.fields.optional] +type = "bool" +required = false +description = "Whether the dependency is optional" +default = false + +[hand.sections.requires.fields.description] +type = "string" +required = false +description = "Why this dependency is needed" + +# --- Hand: [[requires]] -> [install] nested section --- + +[hand.sections.requires.sections.install] +description = "Platform-specific install instructions" +repeatable = false + +[hand.sections.requires.sections.install.fields.macos] +type = "string" +required = false +description = "macOS install command" +example = "brew install python3" + +[hand.sections.requires.sections.install.fields.windows] +type = "string" +required = false +description = "Windows install command" +example = "winget install Python.Python.3.12" + +[hand.sections.requires.sections.install.fields.linux_apt] +type = "string" +required = false +description = "Linux (apt) install command" +example = "sudo apt install python3" + +[hand.sections.requires.sections.install.fields.manual_url] +type = "string" +required = false +description = "URL for manual installation instructions" +example = "https://..." + +# --- Hand: [[settings]] section --- + +[hand.sections.settings] +description = "User-configurable settings" +repeatable = true + +[hand.sections.settings.fields.key] +type = "string" +required = true +description = "Unique setting key" +example = "setting_key" + +[hand.sections.settings.fields.label] +type = "string" +required = true +description = "Human-readable label" +example = "Setting Label" + +[hand.sections.settings.fields.description] +type = "string" +required = false +description = "What this setting controls" + +[hand.sections.settings.fields.setting_type] +type = "string" +required = true +description = "Setting input type" +options = ["toggle", "select", "text", "number"] +example = "toggle" + +[hand.sections.settings.fields.default] +type = "string" +required = false +description = "Default value as string" +example = "true" + +# --- Hand: [[settings]] -> [[options]] nested section --- + +[hand.sections.settings.sections.options] +description = "Available options for select-type settings" +repeatable = true + +[hand.sections.settings.sections.options.fields.value] +type = "string" +required = true +description = "Option value" +example = "option1" + +[hand.sections.settings.sections.options.fields.label] +type = "string" +required = true +description = "Option display label" +example = "Option Label" + +# --- Hand: [agent] section --- + +[hand.sections.agent] +description = "The agent that powers this hand" +repeatable = false + +[hand.sections.agent.fields.name] +type = "string" +required = true +description = "Agent name" +example = "hand-agent-name" + +[hand.sections.agent.fields.description] +type = "string" +required = false +description = "Agent description" + +[hand.sections.agent.fields.module] +type = "string" +required = true +description = "Runtime module" +example = "builtin:chat" + +[hand.sections.agent.fields.provider] +type = "string" +required = false +description = "Provider ID" +example = "default" + +[hand.sections.agent.fields.model] +type = "string" +required = false +description = "Model ID" +example = "default" + +[hand.sections.agent.fields.max_tokens] +type = "number" +required = false +description = "Max response tokens" +example = 16384 + +[hand.sections.agent.fields.temperature] +type = "number" +required = false +description = "Sampling temperature" +example = 0.3 + +[hand.sections.agent.fields.max_iterations] +type = "number" +required = false +description = "Maximum tool-use iterations" +example = 60 + +[hand.sections.agent.fields.system_prompt] +type = "string" +required = true +description = "Detailed behavioral prompt for the agent" + +# --- Hand: [dashboard] section --- + +[hand.sections.dashboard] +description = "Dashboard metrics configuration" +repeatable = false + +# --- Hand: [dashboard] -> [[metrics]] nested section --- + +[hand.sections.dashboard.sections.metrics] +description = "Dashboard metric entries" +repeatable = true + +[hand.sections.dashboard.sections.metrics.fields.label] +type = "string" +required = true +description = "Metric display name" +example = "Metric Name" + +[hand.sections.dashboard.sections.metrics.fields.memory_key] +type = "string" +required = true +description = "Memory key to read the metric value from" +example = "metric_memory_key" + +[hand.sections.dashboard.sections.metrics.fields.format] +type = "string" +required = true +description = "Display format for the metric value" +options = ["number", "currency", "percentage"] +example = "number" + +# --- Hand: [metadata] section --- + +[hand.sections.metadata] +description = "Operational metadata" +repeatable = false + +[hand.sections.metadata.fields.frequency] +type = "string" +required = false +description = "How often this hand runs" +options = ["continuous", "on-demand", "scheduled"] +example = "continuous" + +[hand.sections.metadata.fields.token_consumption] +type = "string" +required = false +description = "Expected token usage level" +options = ["low", "medium", "high"] +example = "low" + +[hand.sections.metadata.fields.default_active] +type = "bool" +required = false +description = "Whether this hand is active by default" +default = true # ═══════════════════════════════════════════════════════════════════════════════ -# INTEGRATION SCHEMA (integrations/.toml) +# INTEGRATION SCHEMA # ═══════════════════════════════════════════════════════════════════════════════ -# Top-level fields: -# id = "integration-id" # Required: unique identifier, must match filename -# name = "Service Name" # Required: human-readable display name -# description = "What this provides" # Optional: one-sentence description -# category = "devtools" # Optional: "devtools", "communication", "storage", -# # "monitoring", "data", "productivity" -# icon = "🐙" # Optional: emoji icon -# tags = ["tag1", "tag2"] # Optional: searchable tags -# -# [transport] # Required: MCP server transport configuration -# type = "stdio" # "stdio" or "sse" -# command = "npx" # Command to launch the MCP server -# args = ["-y", "@pkg/server"] # Command arguments -# -# [[required_env]] # Optional: required environment variables (repeatable) -# name = "SERVICE_API_KEY" # Environment variable name -# label = "API Key" # Human-readable label -# help = "How to get this" # Help text -# is_secret = true # Whether this is a secret value -# get_url = "https://..." # URL where user can get the value -# -# [oauth] # Optional: OAuth configuration -# provider = "github" -# scopes = ["repo", "read:org"] -# auth_url = "https://..." -# token_url = "https://..." -# -# [health_check] # Optional: health check configuration -# interval_secs = 60 -# unhealthy_threshold = 3 -# -# setup_instructions = "..." # Optional: multi-line setup guide +[integration] +description = "External service integration via MCP server" +file_pattern = "integrations/.toml" + +[integration.fields.id] +type = "string" +required = true +description = "Unique identifier, must match filename" +example = "integration-id" + +[integration.fields.name] +type = "string" +required = true +description = "Human-readable display name" +example = "Service Name" + +[integration.fields.description] +type = "string" +required = false +description = "One-sentence description of what this integration provides" + +[integration.fields.category] +type = "string" +required = false +description = "Integration category" +options = ["devtools", "communication", "storage", "monitoring", "data", "productivity"] +example = "devtools" + +[integration.fields.icon] +type = "string" +required = false +description = "Emoji icon" + +[integration.fields.tags] +type = "array" +required = false +description = "Searchable tags" +item_type = "string" +example = ["tag1", "tag2"] + +[integration.fields.setup_instructions] +type = "string" +required = false +description = "Multi-line setup guide" + +# --- Integration: [transport] section --- + +[integration.sections.transport] +description = "MCP server transport configuration" +repeatable = false + +[integration.sections.transport.fields.type] +type = "string" +required = true +description = "Transport type" +options = ["stdio", "sse"] +example = "stdio" + +[integration.sections.transport.fields.command] +type = "string" +required = true +description = "Command to launch the MCP server" +example = "npx" + +[integration.sections.transport.fields.args] +type = "array" +required = false +description = "Command arguments" +item_type = "string" +example = ["-y", "@pkg/server"] + +# --- Integration: [[required_env]] section --- + +[integration.sections.required_env] +description = "Required environment variables" +repeatable = true + +[integration.sections.required_env.fields.name] +type = "string" +required = true +description = "Environment variable name" +example = "SERVICE_API_KEY" + +[integration.sections.required_env.fields.label] +type = "string" +required = true +description = "Human-readable label" +example = "API Key" + +[integration.sections.required_env.fields.help] +type = "string" +required = false +description = "Help text explaining how to get this value" + +[integration.sections.required_env.fields.is_secret] +type = "bool" +required = false +description = "Whether this is a secret value" +default = true + +[integration.sections.required_env.fields.get_url] +type = "string" +required = false +description = "URL where user can obtain the value" +example = "https://..." + +# --- Integration: [oauth] section --- + +[integration.sections.oauth] +description = "OAuth configuration" +repeatable = false + +[integration.sections.oauth.fields.provider] +type = "string" +required = true +description = "OAuth provider identifier" +example = "github" + +[integration.sections.oauth.fields.scopes] +type = "array" +required = false +description = "OAuth scopes to request" +item_type = "string" +example = ["repo", "read:org"] + +[integration.sections.oauth.fields.auth_url] +type = "string" +required = false +description = "OAuth authorization URL" +example = "https://..." + +[integration.sections.oauth.fields.token_url] +type = "string" +required = false +description = "OAuth token exchange URL" +example = "https://..." + +# --- Integration: [health_check] section --- + +[integration.sections.health_check] +description = "Health check configuration" +repeatable = false + +[integration.sections.health_check.fields.interval_secs] +type = "number" +required = false +description = "Health check interval in seconds" +example = 60 + +[integration.sections.health_check.fields.unhealthy_threshold] +type = "number" +required = false +description = "Number of consecutive failures before marking unhealthy" +example = 3 # ═══════════════════════════════════════════════════════════════════════════════ -# SKILL SCHEMA (skills//skill.toml) +# SKILL SCHEMA # ═══════════════════════════════════════════════════════════════════════════════ -# [skill] # Required: skill metadata -# name = "skill-name" # Required: skill identifier, must match directory name -# version = "0.1.0" # Optional: semver version -# description = "What this skill does" # Optional: one-sentence description -# author = "author-name" # Optional: author -# tags = ["tag1", "tag2"] # Optional: searchable tags -# -# [runtime] # Required: execution runtime -# type = "promptonly" # Required: "promptonly", "python", "node", "shell" -# entry = "main.py" # Required for non-promptonly: entry point file -# -# [input] # Optional: input parameter definitions -# param_name = { type = "string", description = "...", required = true } -# -# [prompt] # Required for promptonly: prompt template -# template = "Use {{param_name}} in the template" +[skill] +description = "Reusable skill definition (prompt template or script)" +file_pattern = "skills//skill.toml" + +# --- Skill: [skill] section (metadata) --- +# Note: the top-level "skill" content type contains a [skill] section for metadata. +# In the TOML file, these fields live directly under [skill]. + +[skill.sections.skill] +description = "Skill metadata" +repeatable = false + +[skill.sections.skill.fields.name] +type = "string" +required = true +description = "Skill identifier, must match directory name" +example = "skill-name" + +[skill.sections.skill.fields.version] +type = "string" +required = false +description = "Semver version string" +example = "0.1.0" + +[skill.sections.skill.fields.description] +type = "string" +required = false +description = "One-sentence description of what this skill does" + +[skill.sections.skill.fields.author] +type = "string" +required = false +description = "Author or organization" +example = "author-name" + +[skill.sections.skill.fields.tags] +type = "array" +required = false +description = "Searchable tags" +item_type = "string" +example = ["tag1", "tag2"] + +# --- Skill: [runtime] section --- + +[skill.sections.runtime] +description = "Execution runtime configuration" +repeatable = false + +[skill.sections.runtime.fields.type] +type = "string" +required = true +description = "Runtime type" +options = ["promptonly", "python", "node", "shell"] +example = "promptonly" + +[skill.sections.runtime.fields.entry] +type = "string" +required = false +description = "Entry point file (required for non-promptonly runtimes)" +example = "main.py" + +# --- Skill: [input] section --- + +[skill.sections.input] +description = "Input parameter definitions (each field is a parameter with type, description, required)" +repeatable = false + +# Note: input fields are dynamic — each key is a parameter name with an object value +# containing type, description, and required. This section uses a convention where +# individual parameters are defined as fields. + +# --- Skill: [prompt] section --- + +[skill.sections.prompt] +description = "Prompt template (required for promptonly runtime)" +repeatable = false + +[skill.sections.prompt.fields.template] +type = "string" +required = true +description = "Prompt template string, supports {{param_name}} placeholders" +example = "Use {{param_name}} in the template" # ═══════════════════════════════════════════════════════════════════════════════ -# PLUGIN SCHEMA (plugins//plugin.toml) +# PLUGIN SCHEMA # ═══════════════════════════════════════════════════════════════════════════════ -# Top-level fields: -# name = "plugin-name" # Required: plugin identifier, must match directory name -# version = "0.1.0" # Required: semver version -# description = "What this plugin does" # Required: one-sentence description -# author = "author-name" # Optional: author -# -# [hooks] # Required: hook entry points -# ingest = "hooks/ingest.py" # Optional: called when user message is received -# after_turn = "hooks/after_turn.py" # Optional: called after each conversation turn -# +[plugin] +description = "Plugin that extends agent behavior via lifecycle hooks" +file_pattern = "plugins//plugin.toml" + +[plugin.fields.name] +type = "string" +required = true +description = "Plugin identifier, must match directory name" +example = "plugin-name" + +[plugin.fields.version] +type = "string" +required = true +description = "Semver version string" +example = "0.1.0" + +[plugin.fields.description] +type = "string" +required = true +description = "One-sentence description of what this plugin does" + +[plugin.fields.author] +type = "string" +required = false +description = "Author or organization" +example = "author-name" + +# --- Plugin: [hooks] section --- # Hook scripts communicate via stdin/stdout JSON: -# ingest receives: {"type": "ingest", "agent_id": "...", "message": "..."} -# ingest returns: {"type": "ingest_result", "memories": [{"content": "..."}]} +# ingest receives: {"type": "ingest", "agent_id": "...", "message": "..."} +# ingest returns: {"type": "ingest_result", "memories": [{"content": "..."}]} # after_turn receives: {"type": "after_turn", "agent_id": "...", "messages": [...]} # after_turn returns: {"type": "ok"} + +[plugin.sections.hooks] +description = "Hook entry points — scripts invoked at specific lifecycle events" +repeatable = false + +[plugin.sections.hooks.fields.ingest] +type = "string" +required = false +description = "Script called when a user message is received" +example = "hooks/ingest.py" + +[plugin.sections.hooks.fields.after_turn] +type = "string" +required = false +description = "Script called after each conversation turn" +example = "hooks/after_turn.py" From 1b9245e5231262a8010da35e6cd9f7ebe16862ae Mon Sep 17 00:00:00 2001 From: Evan Hu Date: Wed, 1 Apr 2026 00:52:32 +0900 Subject: [PATCH 2/2] fix: format options arrays in schema.toml for taplo compliance --- schema.toml | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/schema.toml b/schema.toml index 6d6fe89..95a6ba6 100644 --- a/schema.toml +++ b/schema.toml @@ -300,7 +300,17 @@ example = "What this hand does" type = "string" required = true description = "Hand category" -options = ["communication", "content", "data", "development", "devops", "finance", "productivity", "research", "social"] +options = [ + "communication", + "content", + "data", + "development", + "devops", + "finance", + "productivity", + "research", + "social", +] example = "productivity" [hand.fields.icon] @@ -605,7 +615,14 @@ description = "One-sentence description of what this integration provides" type = "string" required = false description = "Integration category" -options = ["devtools", "communication", "storage", "monitoring", "data", "productivity"] +options = [ + "devtools", + "communication", + "storage", + "monitoring", + "data", + "productivity", +] example = "devtools" [integration.fields.icon]