| 1 | """POST /api/plugins/_a0_connector/v1/capabilities.""" |
| 2 | from __future__ import annotations |
| 3 | |
| 4 | import importlib.util |
| 5 | import sys |
| 6 | |
| 7 | from helpers.api import Request, Response |
| 8 | import plugins._a0_connector.api.v1.base as connector_base |
| 9 | from plugins._a0_connector.helpers.version import agent_zero_version |
| 10 | |
| 11 | |
| 12 | _BASE_FEATURES = [ |
| 13 | "chat_create", |
| 14 | "chats_list", |
| 15 | "chat_get", |
| 16 | "chat_reset", |
| 17 | "chat_delete", |
| 18 | "pause", |
| 19 | "nudge", |
| 20 | "message_send", |
| 21 | "message_queue", |
| 22 | "log_tail", |
| 23 | "projects", |
| 24 | "text_editor_remote", |
| 25 | "code_execution_remote", |
| 26 | "computer_use_remote", |
| 27 | "browser_host_remote", |
| 28 | "connector_browser_op", |
| 29 | "remote_file_tree", |
| 30 | "token_status", |
| 31 | "launcher_gateway", |
| 32 | "launcher_gateway_file_write", |
| 33 | ] |
| 34 | |
| 35 | _OPTIONAL_FEATURES: dict[str, tuple[str, ...]] = { |
| 36 | "settings_get": ("helpers.settings", "helpers.subagents"), |
| 37 | "settings_set": ("helpers.settings", "helpers.subagents"), |
| 38 | "agent_profile_set": ("api.agent_profile_set",), |
| 39 | "agent_editor": ("plugins._agent_editor.api.agent_editor",), |
| 40 | "agents_list": ("helpers.subagents",), |
| 41 | "skills_list": ("helpers.skills", "helpers.files", "helpers.projects", "helpers.runtime"), |
| 42 | "skills_activate": ("helpers.skills", "helpers.persist_chat"), |
| 43 | "skills_delete": ("helpers.skills", "helpers.files", "helpers.projects", "helpers.runtime"), |
| 44 | "installed_plugins": ("helpers.plugins",), |
| 45 | "model_presets": ("plugins._model_config.helpers.model_config",), |
| 46 | "model_switcher": ("plugins._model_config.helpers.model_config",), |
| 47 | "browser_runtime_config": ("plugins._browser.helpers.config", "helpers.plugins"), |
| 48 | "compact_chat": ( |
| 49 | "plugins._chat_compaction.helpers.compactor", |
| 50 | "plugins._model_config.helpers.model_config", |
| 51 | ), |
| 52 | } |
| 53 | |
| 54 | |
| 55 | def _module_available(module_name: str) -> bool: |
| 56 | if module_name in sys.modules: |
| 57 | return True |
| 58 | |
| 59 | try: |
| 60 | return importlib.util.find_spec(module_name) is not None |
| 61 | except (AttributeError, ModuleNotFoundError, ValueError): |
| 62 | return False |
| 63 | |
| 64 | |
| 65 | def _feature_available(feature: str) -> bool: |
| 66 | required = _OPTIONAL_FEATURES.get(feature, ()) |
| 67 | return all(_module_available(module_name) for module_name in required) |
| 68 | |
| 69 | |
| 70 | def _feature_list() -> list[str]: |
| 71 | features = list(_BASE_FEATURES) |
| 72 | for feature in _OPTIONAL_FEATURES: |
| 73 | if _feature_available(feature): |
| 74 | features.append(feature) |
| 75 | return features |
| 76 | |
| 77 | |
| 78 | class Capabilities(connector_base.PublicConnectorApiHandler): |
| 79 | """Return the connector discovery contract for current Agent Zero.""" |
| 80 | |
| 81 | async def process(self, input: dict, request: Request) -> dict | Response: |
| 82 | from helpers import login |
| 83 | |
| 84 | return { |
| 85 | "protocol": "a0-connector.v1", |
| 86 | "version": "0.1.0", |
| 87 | "agent_zero_version": agent_zero_version(), |
| 88 | "auth": ["session"], |
| 89 | "auth_required": bool(login.is_login_required()), |
| 90 | "transports": ["http", "websocket"], |
| 91 | "streaming": True, |
| 92 | "websocket_namespace": "/ws", |
| 93 | "websocket_handlers": ["plugins/_a0_connector/ws_connector"], |
| 94 | "attachments": { |
| 95 | "mode": "path_or_url", |
| 96 | "http_upload": "base64_to_file", |
| 97 | "max_files": 20, |
| 98 | }, |
| 99 | "features": _feature_list(), |
| 100 | } |