diff --git a/.github/workflows/build_registry.py b/.github/workflows/build_registry.py index 1267244..bfc3185 100644 --- a/.github/workflows/build_registry.py +++ b/.github/workflows/build_registry.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -"""Build aggregated registry.json from individual agent and extension directories.""" +"""Build aggregated registry.json from individual agent directories.""" import json import os @@ -268,11 +268,9 @@ def validate_icon_monochrome(content: str) -> list[str]: reported_colors.add(style_stroke.group(1).strip()) # Check that currentColor is actually used (icons without fill default to black) - has_current_color = bool(re.search(r'currentColor', content, re.IGNORECASE)) + has_current_color = bool(re.search(r"currentColor", content, re.IGNORECASE)) if not has_current_color: - errors.append( - 'Icon must use currentColor for fills/strokes to support theming' - ) + errors.append("Icon must use currentColor for fills/strokes to support theming") # Deduplicate errors return list(dict.fromkeys(errors)) @@ -475,7 +473,7 @@ def process_entry( base_url: str, seen_ids: dict, ) -> tuple[dict | None, list[str]]: - """Process a single agent or extension entry. Returns (entry, errors).""" + """Process a single registry entry. Returns (entry, errors).""" entry_path = entry_dir / entry_file # Parse JSON with error handling @@ -485,7 +483,7 @@ def process_entry( except json.JSONDecodeError as e: return None, [f"{entry_dir.name}/{entry_file} is invalid JSON: {e}"] - # Validate entry (uses same schema for both agents and extensions) + # Validate entry validation_errors = validate_agent(entry, entry_dir.name, schema) if validation_errors: return None, [f"{entry_dir.name}/{entry_file} validation failed:"] + [ @@ -502,7 +500,7 @@ def process_entry( f" - {e}" for e in version_errors ] - # Check for duplicate IDs (across both agents and extensions) + # Check for duplicate IDs entry_id = entry["id"] if entry_id in seen_ids: return None, [ @@ -532,15 +530,14 @@ def process_entry( def build_registry(): - """Build registry.json from agent and extension directories.""" + """Build registry.json from agent directories.""" registry_dir = Path(__file__).parent.parent.parent base_url = get_base_url() agents = [] - extensions = [] seen_ids = {} has_errors = False - # Load schema for validation (used for both agents and extensions) + # Load schema for validation schema = load_schema(registry_dir) if schema and not HAS_JSONSCHEMA: print("Warning: jsonschema not installed, skipping schema validation") @@ -551,56 +548,32 @@ def build_registry(): continue agent_json_path = entry_dir / "agent.json" - extension_json_path = entry_dir / "extension.json" - - has_agent = agent_json_path.exists() - has_extension = extension_json_path.exists() - if has_agent and has_extension: - print(f"Error: {entry_dir.name}/ has both agent.json and extension.json") - has_errors = True + if not agent_json_path.exists(): + print(f"Warning: {entry_dir.name}/ has no agent.json, skipping") continue - if not has_agent and not has_extension: - print( - f"Warning: {entry_dir.name}/ has no agent.json or extension.json, skipping" - ) + entry, errors = process_entry( + entry_dir, "agent.json", "agent", schema, base_url, seen_ids + ) + if errors: + for error in errors: + print(f"Error: {error}") + has_errors = True continue - - if has_agent: - entry, errors = process_entry( - entry_dir, "agent.json", "agent", schema, base_url, seen_ids - ) - if errors: - for error in errors: - print(f"Error: {error}") - has_errors = True - continue - agents.append(entry) - print(f"Added agent: {entry['id']} v{entry['version']}") - else: - entry, errors = process_entry( - entry_dir, "extension.json", "extension", schema, base_url, seen_ids - ) - if errors: - for error in errors: - print(f"Error: {error}") - has_errors = True - continue - extensions.append(entry) - print(f"Added extension: {entry['id']} v{entry['version']}") + agents.append(entry) + print(f"Added agent: {entry['id']} v{entry['version']}") if has_errors: print("\nBuild failed due to validation errors") sys.exit(1) - if not agents and not extensions: - print("\nWarning: No agents or extensions found") + if not agents: + print("\nWarning: No agents found") registry = { "version": REGISTRY_VERSION, "agents": agents, - "extensions": extensions, } # Create dist directory @@ -618,15 +591,14 @@ def build_registry(): jetbrains_registry = { "version": REGISTRY_VERSION, "agents": [a for a in agents if a["id"] not in JETBRAINS_EXCLUDE_IDS], - "extensions": extensions, } jetbrains_output_path = dist_dir / "registry-for-jetbrains.json" with open(jetbrains_output_path, "w") as f: json.dump(jetbrains_registry, f, indent=2) f.write("\n") - # Copy icons to dist (for both agents and extensions) - for entry in agents + extensions: + # Copy icons to dist + for entry in agents: entry_id = entry["id"] icon_src = registry_dir / entry_id / "icon.svg" if icon_src.exists(): @@ -641,9 +613,11 @@ def build_registry(): schema_dst.write_bytes(schema_src.read_bytes()) jetbrains_agent_count = len(jetbrains_registry["agents"]) - print(f"\nBuilt dist/ with {len(agents)} agents and {len(extensions)} extensions") + print(f"\nBuilt dist/ with {len(agents)} agents") print(f" registry.json: {len(agents)} agents") - print(f" registry-for-jetbrains.json: {jetbrains_agent_count} agents (excluded: {', '.join(JETBRAINS_EXCLUDE_IDS)})") + print( + f" registry-for-jetbrains.json: {jetbrains_agent_count} agents (excluded: {', '.join(JETBRAINS_EXCLUDE_IDS)})" + ) if __name__ == "__main__": diff --git a/AGENTS.md b/AGENTS.md index 0497e7f..f0fe28d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -14,25 +14,24 @@ python .github/workflows/build_registry.py ## Architecture -This is a registry of ACP (Agent Client Protocol) agents and extensions. The structure is: +This is a registry of ACP (Agent Client Protocol) agents. The structure is: ``` / ├── agent.json # Agent metadata and distribution info -├── extension.json # OR extension metadata (same schema as agent.json) └── icon.svg # Icon: 16x16 SVG, monochrome with currentColor (optional) ``` -Each directory contains either `agent.json` (for agents) or `extension.json` (for extensions), but not both. Extensions use the same schema as agents (`agent.schema.json`). - **Build process** (`.github/workflows/build_registry.py`): -1. Scans directories for `agent.json` or `extension.json` files + +1. Scans directories for `agent.json` files 2. Validates against `agent.schema.json` (JSON Schema) 3. Validates icons (16x16 SVG, monochrome with `currentColor`) -4. Aggregates into `dist/registry.json` with separate `agents` and `extensions` arrays +4. Aggregates into `dist/registry.json` 5. Copies icons to `dist/.svg` **CI/CD** (`.github/workflows/build-registry.yml`): + - PRs: Runs validation only - Push to main: Validates, then publishes versioned + `latest` GitHub releases @@ -53,6 +52,7 @@ Set `SKIP_URL_VALIDATION=1` to bypass URL checks during local development. ### Automated Updates Agent versions are automatically updated via `.github/workflows/update-versions.yml`: + - **Schedule:** Runs hourly (cron: `0 * * * *`) - **Scope:** Checks all agents in root and `_not_yet_unsupported/` - **Supported distributions:** `npx` (npm), `uvx` (PyPI), `binary` (GitHub releases) @@ -78,6 +78,7 @@ To update agents manually: 2. **For GitHub binaries** (`binary` distribution): Check latest release at `https://api.github.com/repos///releases/latest` Update `agent.json`: + - Update the `version` field - Update version in all distribution URLs (use replace-all for consistency) - For npm: update `package` field (e.g., `@google/gemini-cli@0.22.5`) @@ -96,6 +97,7 @@ Run build to validate: `uv run --with jsonschema .github/workflows/build_registr ## Icon Requirements Icons must be: + - **SVG format** (only `.svg` files accepted) - **16x16 dimensions** (via width/height attributes or viewBox) - **Monochrome using `currentColor`** - all fills and strokes must use `currentColor` or `none` @@ -103,6 +105,7 @@ Icons must be: Using `currentColor` enables icons to adapt to different themes (light/dark mode) automatically. **Valid example:** + ```svg @@ -110,6 +113,7 @@ Using `currentColor` enables icons to adapt to different themes (light/dark mode ``` **Invalid patterns:** + - Hardcoded colors: `fill="#FF5500"`, `fill="red"`, `stroke="rgb(0,0,0)"` - Missing currentColor: `fill` or `stroke` without `currentColor` @@ -118,6 +122,7 @@ Using `currentColor` enables icons to adapt to different themes (light/dark mode Agents must support ACP authentication. The CI verifies auth via `.github/workflows/verify_agents.py --auth-check`. **Requirements:** + - Return `authMethods` array in `initialize` response - At least one method must have type `"agent"` or `"terminal"` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 39a4241..1ae20ce 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Contributing to the ACP Registry -## Adding a New Agent or Extension +## Adding a New Agent 1. **Fork this repository** @@ -12,9 +12,7 @@ The directory name must match your entry's `id` field. -3. **Create `agent.json` or `extension.json`** - - Use `agent.json` for agents, `extension.json` for extensions. Both use the same schema. +3. **Create `agent.json`** ```json { @@ -40,6 +38,7 @@ - **Monochrome using `currentColor`** - enables theme support (light/dark mode) Example: + ```svg @@ -126,21 +125,21 @@ Supported platforms: `darwin-aarch64`, `darwin-x86_64`, `linux-aarch64`, `linux- ## Required Fields -| Field | Type | Description | -|-------|------|-------------| -| `id` | string | Unique identifier (lowercase, hyphens allowed) | -| `name` | string | Display name | -| `version` | string | Semantic version | -| `description` | string | Brief description | -| `distribution` | object | At least one distribution method | +| Field | Type | Description | +| -------------- | ------ | ---------------------------------------------- | +| `id` | string | Unique identifier (lowercase, hyphens allowed) | +| `name` | string | Display name | +| `version` | string | Semantic version | +| `description` | string | Brief description | +| `distribution` | object | At least one distribution method | ## Optional Fields -| Field | Type | Description | -|-------|------|-------------| -| `repository` | string | Source code URL | -| `authors` | array | List of author names/emails | -| `license` | string | SPDX license identifier | +| Field | Type | Description | +| ------------ | ------ | --------------------------- | +| `repository` | string | Source code URL | +| `authors` | array | List of author names/emails | +| `license` | string | SPDX license identifier | ## Automatic Version Updates @@ -154,9 +153,9 @@ You don't need to submit a PR for version bumps. ## Manual Updates -To manually update your agent or extension (e.g., changing description, adding platforms): +To manually update your agent (e.g., changing description, adding platforms): -1. Fork and update the `agent.json` or `extension.json` file +1. Fork and update the `agent.json` file 2. Submit a Pull Request 3. CI will validate and merge will trigger a new registry release @@ -173,7 +172,7 @@ Entries are validated against the [JSON Schema](agent.schema.json). - Must be lowercase letters, digits, and hyphens only - Must start with a letter - Must match the directory name -- Must be unique across all agents and extensions +- Must be unique across all agents ### Version Validation @@ -183,11 +182,13 @@ Entries are validated against the [JSON Schema](agent.schema.json). ### Distribution Validation **Structure:** + - At least one distribution method required (`binary`, `npx`, or `uvx`) - Binary distributions require `archive` and `cmd` fields per platform - Package distributions (`npx`, `uvx`) require `package` field **Platforms** (for binary): + - `darwin-aarch64`, `darwin-x86_64` - `linux-aarch64`, `linux-x86_64` - `windows-aarch64`, `windows-x86_64` @@ -201,12 +202,14 @@ Entries are validated against the [JSON Schema](agent.schema.json). - Missing OS families will produce a warning but will not fail validation **Version matching:** + - Distribution versions must match the entry's `version` field - Binary URLs containing version (e.g., `/download/v1.0.0/`) are checked - npm package versions (`@scope/pkg@1.0.0`) are checked - PyPI package versions (`pkg==1.0.0` or `pkg@1.0.0`) are checked **No `latest` allowed:** + - Binary URLs must not contain `/latest/` - npm packages must not use `@latest` - PyPI packages must not use `@latest` @@ -239,6 +242,7 @@ python3 .github/workflows/verify_agents.py --auth-check ``` **What gets checked:** + - Agent must return `authMethods` in the `initialize` response - At least one method must have `type: "agent"` or `type: "terminal"` - See [AUTHENTICATION.md](AUTHENTICATION.md) for implementation details diff --git a/FORMAT.md b/FORMAT.md index 86bf667..74d95cc 100644 --- a/FORMAT.md +++ b/FORMAT.md @@ -1,16 +1,15 @@ # Registry Format -The registry contains both agents and extensions: +The registry contains agents: ```json { "version": "1.0.0", - "agents": [...], - "extensions": [...] + "agents": [...] } ``` -Each entry (agent or extension) has the same structure: +Each agent has the following structure: ```json { @@ -46,7 +45,7 @@ Each entry (agent or extension) has the same structure: ## Distribution Types | Type | Description | Command | -|----------|-------------------------------|------------------------| +| -------- | ----------------------------- | ---------------------- | | `binary` | Platform-specific executables | Download, extract, run | | `npx` | npm packages | `npx [args]` | | `uvx` | PyPI packages via uv | `uvx [args]` | diff --git a/README.md b/README.md index 7461d40..289635e 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,12 @@ > ⚠️ **Work in Progress**: This registry is under active development. Format and contents may change. -A registry of agents and extensions implementing the [Agent Client Protocol, ACP](https://github.com/agentclientprotocol/agent-client-protocol). +A registry of agents implementing the [Agent Client Protocol, ACP](https://github.com/agentclientprotocol/agent-client-protocol). -> **Authentication Required**: This registry maintains a curated list of **agents that support user authentication**. -> -> Users must be able to authenticate themselves with agents to use them. -> All agents are verified via CI to ensure they return valid `authMethods` in the ACP handshake. +> **Authentication Required**: This registry maintains a curated list of **agents that support user authentication**. +> +> Users must be able to authenticate themselves with agents to use them. +> All agents are verified via CI to ensure they return valid `authMethods` in the ACP handshake. > See [AUTHENTICATION.md](AUTHENTICATION.md) for implementation details and the [ACP auth methods proposal](https://github.com/agentclientprotocol/agent-client-protocol/blob/main/docs/rfds/auth-methods.mdx) for the specification. ## Included Agents @@ -36,7 +36,7 @@ https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json See [FORMAT.md](FORMAT.md) for the registry schema, distribution types, and platform targets. -## Adding an Agent or Extension +## Adding an Agent See [CONTRIBUTING.md](CONTRIBUTING.md) for instructions. diff --git a/registry.schema.json b/registry.schema.json index 05043ba..dbd3a7f 100644 --- a/registry.schema.json +++ b/registry.schema.json @@ -2,9 +2,9 @@ "$schema": "http://json-schema.org/draft-07/schema#", "$id": "https://cdn.agentclientprotocol.com/registry/v1/latest/registry.schema.json", "title": "ACP Agent Registry", - "description": "Schema for the aggregated ACP agent and extension registry index", + "description": "Schema for the aggregated ACP agent registry index", "type": "object", - "required": ["version", "agents", "extensions"], + "required": ["version", "agents"], "properties": { "version": { "type": "string", @@ -17,13 +17,6 @@ "items": { "$ref": "agent.schema.json" } - }, - "extensions": { - "type": "array", - "description": "List of registered extensions", - "items": { - "$ref": "agent.schema.json" - } } }, "additionalProperties": false