1bd0b8ed41
An external-process provider is an agent CLI Hermes drives over stdio rather than an HTTP endpoint. Three things about it were spelled out for one vendor, and each was a hard stop for any other: * ``resolve_provider()`` gates on ``PROVIDER_REGISTRY``. Its auto-extend from ``providers/`` covered api-key providers only, so an external-process profile never entered it and ``hermes -m <that provider>`` died with "Unknown provider" before a client was ever built. * ``resolve_runtime_provider()`` keyed the external-process branch on the literal ``"copilot-acp"``, so anything else silently fell through to the OpenRouter default instead of its own runtime. * ``resolve_external_process_provider_credentials()`` hardcoded the binary (``copilot``), the argv (``--acp --stdio``), the env var names and the placeholder api_key — so a third-party provider would have been handed another vendor's CLI. Now the profile carries what only the provider knows — ``process_command``, ``process_args``, ``process_command_env_vars``, ``process_args_env_var`` — and the three core paths key on ``auth_type == "external_process"`` instead of a name. copilot-acp's values move into its profile verbatim, so ``HERMES_COPILOT_ACP_COMMAND`` / ``COPILOT_CLI_PATH`` / ``HERMES_COPILOT_ACP_ARGS`` and its ``copilot-acp`` api_key placeholder behave exactly as before; the new tests assert that alongside the out-of-tree case at every step. The error for a missing binary now names the provider and its own env override instead of telling every user to install GitHub Copilot CLI. Co-Authored-By: Junie <junie@jetbrains.com>
55 lines
2.0 KiB
Python
55 lines
2.0 KiB
Python
"""GitHub Copilot ACP provider profile.
|
|
|
|
copilot-acp does not speak OpenAI-over-HTTP: it drives an external ACP
|
|
subprocess over stdio. The profile therefore supplies its own client through
|
|
:meth:`ProviderProfile.create_client` instead of letting the core build an
|
|
``openai.OpenAI``. That hook is the registration seam — this profile is its
|
|
in-tree consumer, and an out-of-tree ACP provider registered from
|
|
``~/.hermes/plugins/model-providers/`` or a pip entry point uses the exact same
|
|
three lines without touching core.
|
|
"""
|
|
|
|
from typing import Any
|
|
|
|
from providers import register_provider
|
|
from providers.base import ProviderProfile
|
|
|
|
|
|
class CopilotACPProfile(ProviderProfile):
|
|
"""GitHub Copilot ACP — external process, no REST models endpoint."""
|
|
|
|
def create_client(self, **client_kwargs: Any) -> Any:
|
|
"""Build the ACP stdio shim rather than an HTTP client."""
|
|
from agent.copilot_acp_client import CopilotACPClient
|
|
|
|
return CopilotACPClient(**client_kwargs)
|
|
|
|
def fetch_models(
|
|
self,
|
|
*,
|
|
api_key: str | None = None,
|
|
base_url: str | None = None,
|
|
timeout: float = 8.0,
|
|
) -> list[str] | None:
|
|
"""Model listing is handled by the ACP subprocess."""
|
|
return None
|
|
|
|
|
|
copilot_acp = CopilotACPProfile(
|
|
name="copilot-acp",
|
|
aliases=("github-copilot-acp", "copilot-acp-agent"),
|
|
api_mode="chat_completions", # ACP subprocess uses chat_completions routing
|
|
env_vars=(), # Managed by ACP subprocess
|
|
base_url="acp://copilot", # ACP internal scheme
|
|
auth_type="external_process",
|
|
# How to launch the CLI. Previously hardcoded in
|
|
# hermes_cli/auth.py::resolve_external_process_provider_credentials; the env
|
|
# var names are unchanged, so existing setups keep working.
|
|
process_command="copilot",
|
|
process_args=("--acp", "--stdio"),
|
|
process_command_env_vars=("HERMES_COPILOT_ACP_COMMAND", "COPILOT_CLI_PATH"),
|
|
process_args_env_var="HERMES_COPILOT_ACP_ARGS",
|
|
)
|
|
|
|
register_provider(copilot_acp)
|