superqode 0.1.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- superqode/__init__.py +33 -0
- superqode/acp/__init__.py +23 -0
- superqode/acp/client.py +913 -0
- superqode/acp/permission_screen.py +457 -0
- superqode/acp/types.py +480 -0
- superqode/acp_discovery.py +856 -0
- superqode/agent/__init__.py +22 -0
- superqode/agent/edit_strategies.py +334 -0
- superqode/agent/loop.py +892 -0
- superqode/agent/qe_report_templates.py +39 -0
- superqode/agent/system_prompts.py +353 -0
- superqode/agent_output.py +721 -0
- superqode/agent_stream.py +953 -0
- superqode/agents/__init__.py +59 -0
- superqode/agents/acp_registry.py +305 -0
- superqode/agents/client.py +249 -0
- superqode/agents/data/augmentcode.com.toml +51 -0
- superqode/agents/data/cagent.dev.toml +51 -0
- superqode/agents/data/claude.com.toml +60 -0
- superqode/agents/data/codeassistant.dev.toml +51 -0
- superqode/agents/data/codex.openai.com.toml +57 -0
- superqode/agents/data/fastagent.ai.toml +66 -0
- superqode/agents/data/geminicli.com.toml +77 -0
- superqode/agents/data/goose.block.xyz.toml +54 -0
- superqode/agents/data/junie.jetbrains.com.toml +56 -0
- superqode/agents/data/kimi.moonshot.cn.toml +57 -0
- superqode/agents/data/llmlingagent.dev.toml +51 -0
- superqode/agents/data/molt.bot.toml +49 -0
- superqode/agents/data/opencode.ai.toml +60 -0
- superqode/agents/data/stakpak.dev.toml +51 -0
- superqode/agents/data/vtcode.dev.toml +51 -0
- superqode/agents/discovery.py +266 -0
- superqode/agents/messaging.py +160 -0
- superqode/agents/persona.py +166 -0
- superqode/agents/registry.py +421 -0
- superqode/agents/schema.py +72 -0
- superqode/agents/unified.py +367 -0
- superqode/app/__init__.py +111 -0
- superqode/app/constants.py +314 -0
- superqode/app/css.py +366 -0
- superqode/app/models.py +118 -0
- superqode/app/suggester.py +125 -0
- superqode/app/widgets.py +1591 -0
- superqode/app_enhanced.py +399 -0
- superqode/app_main.py +17187 -0
- superqode/approval.py +312 -0
- superqode/atomic.py +296 -0
- superqode/commands/__init__.py +1 -0
- superqode/commands/acp.py +965 -0
- superqode/commands/agents.py +180 -0
- superqode/commands/auth.py +278 -0
- superqode/commands/config.py +374 -0
- superqode/commands/init.py +826 -0
- superqode/commands/providers.py +819 -0
- superqode/commands/qe.py +1145 -0
- superqode/commands/roles.py +380 -0
- superqode/commands/serve.py +172 -0
- superqode/commands/suggestions.py +127 -0
- superqode/commands/superqe.py +460 -0
- superqode/config/__init__.py +51 -0
- superqode/config/loader.py +812 -0
- superqode/config/schema.py +498 -0
- superqode/core/__init__.py +111 -0
- superqode/core/roles.py +281 -0
- superqode/danger.py +386 -0
- superqode/data/superqode-template.yaml +1522 -0
- superqode/design_system.py +1080 -0
- superqode/dialogs/__init__.py +6 -0
- superqode/dialogs/base.py +39 -0
- superqode/dialogs/model.py +130 -0
- superqode/dialogs/provider.py +870 -0
- superqode/diff_view.py +919 -0
- superqode/enterprise.py +21 -0
- superqode/evaluation/__init__.py +25 -0
- superqode/evaluation/adapters.py +93 -0
- superqode/evaluation/behaviors.py +89 -0
- superqode/evaluation/engine.py +209 -0
- superqode/evaluation/scenarios.py +96 -0
- superqode/execution/__init__.py +36 -0
- superqode/execution/linter.py +538 -0
- superqode/execution/modes.py +347 -0
- superqode/execution/resolver.py +283 -0
- superqode/execution/runner.py +642 -0
- superqode/file_explorer.py +811 -0
- superqode/file_viewer.py +471 -0
- superqode/flash.py +183 -0
- superqode/guidance/__init__.py +58 -0
- superqode/guidance/config.py +203 -0
- superqode/guidance/prompts.py +71 -0
- superqode/harness/__init__.py +54 -0
- superqode/harness/accelerator.py +291 -0
- superqode/harness/config.py +319 -0
- superqode/harness/validator.py +147 -0
- superqode/history.py +279 -0
- superqode/integrations/superopt_runner.py +124 -0
- superqode/logging/__init__.py +49 -0
- superqode/logging/adapters.py +219 -0
- superqode/logging/formatter.py +923 -0
- superqode/logging/integration.py +341 -0
- superqode/logging/sinks.py +170 -0
- superqode/logging/unified_log.py +417 -0
- superqode/lsp/__init__.py +26 -0
- superqode/lsp/client.py +544 -0
- superqode/main.py +1069 -0
- superqode/mcp/__init__.py +89 -0
- superqode/mcp/auth_storage.py +380 -0
- superqode/mcp/client.py +1236 -0
- superqode/mcp/config.py +319 -0
- superqode/mcp/integration.py +337 -0
- superqode/mcp/oauth.py +436 -0
- superqode/mcp/oauth_callback.py +385 -0
- superqode/mcp/types.py +290 -0
- superqode/memory/__init__.py +31 -0
- superqode/memory/feedback.py +342 -0
- superqode/memory/store.py +522 -0
- superqode/notifications.py +369 -0
- superqode/optimization/__init__.py +5 -0
- superqode/optimization/config.py +33 -0
- superqode/permissions/__init__.py +25 -0
- superqode/permissions/rules.py +488 -0
- superqode/plan.py +323 -0
- superqode/providers/__init__.py +33 -0
- superqode/providers/gateway/__init__.py +165 -0
- superqode/providers/gateway/base.py +228 -0
- superqode/providers/gateway/litellm_gateway.py +1170 -0
- superqode/providers/gateway/openresponses_gateway.py +436 -0
- superqode/providers/health.py +297 -0
- superqode/providers/huggingface/__init__.py +74 -0
- superqode/providers/huggingface/downloader.py +472 -0
- superqode/providers/huggingface/endpoints.py +442 -0
- superqode/providers/huggingface/hub.py +531 -0
- superqode/providers/huggingface/inference.py +394 -0
- superqode/providers/huggingface/transformers_runner.py +516 -0
- superqode/providers/local/__init__.py +100 -0
- superqode/providers/local/base.py +438 -0
- superqode/providers/local/discovery.py +418 -0
- superqode/providers/local/lmstudio.py +256 -0
- superqode/providers/local/mlx.py +457 -0
- superqode/providers/local/ollama.py +486 -0
- superqode/providers/local/sglang.py +268 -0
- superqode/providers/local/tgi.py +260 -0
- superqode/providers/local/tool_support.py +477 -0
- superqode/providers/local/vllm.py +258 -0
- superqode/providers/manager.py +1338 -0
- superqode/providers/models.py +1016 -0
- superqode/providers/models_dev.py +578 -0
- superqode/providers/openresponses/__init__.py +87 -0
- superqode/providers/openresponses/converters/__init__.py +17 -0
- superqode/providers/openresponses/converters/messages.py +343 -0
- superqode/providers/openresponses/converters/tools.py +268 -0
- superqode/providers/openresponses/schema/__init__.py +56 -0
- superqode/providers/openresponses/schema/models.py +585 -0
- superqode/providers/openresponses/streaming/__init__.py +5 -0
- superqode/providers/openresponses/streaming/parser.py +338 -0
- superqode/providers/openresponses/tools/__init__.py +21 -0
- superqode/providers/openresponses/tools/apply_patch.py +352 -0
- superqode/providers/openresponses/tools/code_interpreter.py +290 -0
- superqode/providers/openresponses/tools/file_search.py +333 -0
- superqode/providers/openresponses/tools/mcp_adapter.py +252 -0
- superqode/providers/registry.py +716 -0
- superqode/providers/usage.py +332 -0
- superqode/pure_mode.py +384 -0
- superqode/qr/__init__.py +23 -0
- superqode/qr/dashboard.py +781 -0
- superqode/qr/generator.py +1018 -0
- superqode/qr/templates.py +135 -0
- superqode/safety/__init__.py +41 -0
- superqode/safety/sandbox.py +413 -0
- superqode/safety/warnings.py +256 -0
- superqode/server/__init__.py +33 -0
- superqode/server/lsp_server.py +775 -0
- superqode/server/web.py +250 -0
- superqode/session/__init__.py +25 -0
- superqode/session/persistence.py +580 -0
- superqode/session/sharing.py +477 -0
- superqode/session.py +475 -0
- superqode/sidebar.py +2991 -0
- superqode/stream_view.py +648 -0
- superqode/styles/__init__.py +3 -0
- superqode/superqe/__init__.py +184 -0
- superqode/superqe/acp_runner.py +1064 -0
- superqode/superqe/constitution/__init__.py +62 -0
- superqode/superqe/constitution/evaluator.py +308 -0
- superqode/superqe/constitution/loader.py +432 -0
- superqode/superqe/constitution/schema.py +250 -0
- superqode/superqe/events.py +591 -0
- superqode/superqe/frameworks/__init__.py +65 -0
- superqode/superqe/frameworks/base.py +234 -0
- superqode/superqe/frameworks/e2e.py +263 -0
- superqode/superqe/frameworks/executor.py +237 -0
- superqode/superqe/frameworks/javascript.py +409 -0
- superqode/superqe/frameworks/python.py +373 -0
- superqode/superqe/frameworks/registry.py +92 -0
- superqode/superqe/mcp_tools/__init__.py +47 -0
- superqode/superqe/mcp_tools/core_tools.py +418 -0
- superqode/superqe/mcp_tools/registry.py +230 -0
- superqode/superqe/mcp_tools/testing_tools.py +167 -0
- superqode/superqe/noise.py +89 -0
- superqode/superqe/orchestrator.py +778 -0
- superqode/superqe/roles.py +609 -0
- superqode/superqe/session.py +713 -0
- superqode/superqe/skills/__init__.py +57 -0
- superqode/superqe/skills/base.py +106 -0
- superqode/superqe/skills/core_skills.py +899 -0
- superqode/superqe/skills/registry.py +90 -0
- superqode/superqe/verifier.py +101 -0
- superqode/superqe_cli.py +76 -0
- superqode/tool_call.py +358 -0
- superqode/tools/__init__.py +93 -0
- superqode/tools/agent_tools.py +496 -0
- superqode/tools/base.py +324 -0
- superqode/tools/batch_tool.py +133 -0
- superqode/tools/diagnostics.py +311 -0
- superqode/tools/edit_tools.py +653 -0
- superqode/tools/enhanced_base.py +515 -0
- superqode/tools/file_tools.py +269 -0
- superqode/tools/file_tracking.py +45 -0
- superqode/tools/lsp_tools.py +610 -0
- superqode/tools/network_tools.py +350 -0
- superqode/tools/permissions.py +400 -0
- superqode/tools/question_tool.py +324 -0
- superqode/tools/search_tools.py +598 -0
- superqode/tools/shell_tools.py +259 -0
- superqode/tools/todo_tools.py +121 -0
- superqode/tools/validation.py +80 -0
- superqode/tools/web_tools.py +639 -0
- superqode/tui.py +1152 -0
- superqode/tui_integration.py +875 -0
- superqode/tui_widgets/__init__.py +27 -0
- superqode/tui_widgets/widgets/__init__.py +18 -0
- superqode/tui_widgets/widgets/progress.py +185 -0
- superqode/tui_widgets/widgets/tool_display.py +188 -0
- superqode/undo_manager.py +574 -0
- superqode/utils/__init__.py +5 -0
- superqode/utils/error_handling.py +323 -0
- superqode/utils/fuzzy.py +257 -0
- superqode/widgets/__init__.py +477 -0
- superqode/widgets/agent_collab.py +390 -0
- superqode/widgets/agent_store.py +936 -0
- superqode/widgets/agent_switcher.py +395 -0
- superqode/widgets/animation_manager.py +284 -0
- superqode/widgets/code_context.py +356 -0
- superqode/widgets/command_palette.py +412 -0
- superqode/widgets/connection_status.py +537 -0
- superqode/widgets/conversation_history.py +470 -0
- superqode/widgets/diff_indicator.py +155 -0
- superqode/widgets/enhanced_status_bar.py +385 -0
- superqode/widgets/enhanced_toast.py +476 -0
- superqode/widgets/file_browser.py +809 -0
- superqode/widgets/file_reference.py +585 -0
- superqode/widgets/issue_timeline.py +340 -0
- superqode/widgets/leader_key.py +264 -0
- superqode/widgets/mode_switcher.py +445 -0
- superqode/widgets/model_picker.py +234 -0
- superqode/widgets/permission_preview.py +1205 -0
- superqode/widgets/prompt.py +358 -0
- superqode/widgets/provider_connect.py +725 -0
- superqode/widgets/pty_shell.py +587 -0
- superqode/widgets/qe_dashboard.py +321 -0
- superqode/widgets/resizable_sidebar.py +377 -0
- superqode/widgets/response_changes.py +218 -0
- superqode/widgets/response_display.py +528 -0
- superqode/widgets/rich_tool_display.py +613 -0
- superqode/widgets/sidebar_panels.py +1180 -0
- superqode/widgets/slash_complete.py +356 -0
- superqode/widgets/split_view.py +612 -0
- superqode/widgets/status_bar.py +273 -0
- superqode/widgets/superqode_display.py +786 -0
- superqode/widgets/thinking_display.py +815 -0
- superqode/widgets/throbber.py +87 -0
- superqode/widgets/toast.py +206 -0
- superqode/widgets/unified_output.py +1073 -0
- superqode/workspace/__init__.py +75 -0
- superqode/workspace/artifacts.py +472 -0
- superqode/workspace/coordinator.py +353 -0
- superqode/workspace/diff_tracker.py +429 -0
- superqode/workspace/git_guard.py +373 -0
- superqode/workspace/git_snapshot.py +526 -0
- superqode/workspace/manager.py +750 -0
- superqode/workspace/snapshot.py +357 -0
- superqode/workspace/watcher.py +535 -0
- superqode/workspace/worktree.py +440 -0
- superqode-0.1.5.dist-info/METADATA +204 -0
- superqode-0.1.5.dist-info/RECORD +288 -0
- superqode-0.1.5.dist-info/WHEEL +5 -0
- superqode-0.1.5.dist-info/entry_points.txt +3 -0
- superqode-0.1.5.dist-info/licenses/LICENSE +648 -0
- superqode-0.1.5.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,856 @@
|
|
|
1
|
+
"""
|
|
2
|
+
SuperQode ACP Agent Discovery - Auto-Discover Available Agents.
|
|
3
|
+
|
|
4
|
+
Automatically discovers ACP-compatible agents installed on the system
|
|
5
|
+
and provides a unified interface for connecting to them.
|
|
6
|
+
|
|
7
|
+
Supported Agents (14 Official ACP Agents):
|
|
8
|
+
- Gemini CLI (gemini) - Google's reference ACP implementation
|
|
9
|
+
- Claude Code (claude-code-acp) - Anthropic's Claude via Zed SDK adapter
|
|
10
|
+
- Codex (codex-acp) - OpenAI's code generation agent
|
|
11
|
+
- JetBrains Junie (junie) - JetBrains' AI agent for IDE ecosystem
|
|
12
|
+
- Goose (goose acp) - Square's open-source agent
|
|
13
|
+
- Kimi CLI (kimi) - CLI AI agent with ACP support
|
|
14
|
+
- OpenCode (opencode acp) - Open-source coding agent
|
|
15
|
+
- Stakpak (stakpak) - ACP-compatible code assistance agent
|
|
16
|
+
- VT Code (vtcode) - Versatile coding agent
|
|
17
|
+
- Augment Code (auggie) - Agentic capabilities for code analysis
|
|
18
|
+
- Code Assistant (code-assistant) - AI coding assistant in Rust
|
|
19
|
+
- cagent (cagent) - Multi-agent runtime orchestration
|
|
20
|
+
- fast-agent (fast-agent) - Sophisticated agent workflows
|
|
21
|
+
- LLMling-Agent (llmling-agent) - LLM-powered agent framework
|
|
22
|
+
|
|
23
|
+
Features:
|
|
24
|
+
- Auto-detection of installed agents
|
|
25
|
+
- Version checking
|
|
26
|
+
- Capability discovery
|
|
27
|
+
- Model listing
|
|
28
|
+
- Health checking
|
|
29
|
+
|
|
30
|
+
Usage:
|
|
31
|
+
from superqode.acp_discovery import ACPDiscovery
|
|
32
|
+
|
|
33
|
+
discovery = ACPDiscovery()
|
|
34
|
+
agents = await discovery.discover_all()
|
|
35
|
+
|
|
36
|
+
for agent in agents:
|
|
37
|
+
print(f"{agent.name}: {agent.status}")
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
from __future__ import annotations
|
|
41
|
+
|
|
42
|
+
import asyncio
|
|
43
|
+
import json
|
|
44
|
+
import os
|
|
45
|
+
import shutil
|
|
46
|
+
import subprocess
|
|
47
|
+
from dataclasses import dataclass, field
|
|
48
|
+
from enum import Enum, auto
|
|
49
|
+
from pathlib import Path
|
|
50
|
+
from typing import Any, Callable, Dict, List, Optional, Tuple
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
# ============================================================================
|
|
54
|
+
# ENUMS
|
|
55
|
+
# ============================================================================
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class AgentStatus(Enum):
|
|
59
|
+
"""Agent availability status."""
|
|
60
|
+
|
|
61
|
+
AVAILABLE = auto() # Installed and ready
|
|
62
|
+
NOT_INSTALLED = auto() # Not found on system
|
|
63
|
+
NOT_CONFIGURED = auto() # Installed but needs setup (API key, etc)
|
|
64
|
+
ERROR = auto() # Error checking status
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class ConnectionType(Enum):
|
|
68
|
+
"""Agent connection type."""
|
|
69
|
+
|
|
70
|
+
ACP = "acp" # Agent Client Protocol
|
|
71
|
+
BYOK = "byok" # Bring Your Own Key (direct API)
|
|
72
|
+
LOCAL = "local" # Local model
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
# ============================================================================
|
|
76
|
+
# DATA CLASSES
|
|
77
|
+
# ============================================================================
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
@dataclass
|
|
81
|
+
class AgentCapability:
|
|
82
|
+
"""An agent capability."""
|
|
83
|
+
|
|
84
|
+
name: str
|
|
85
|
+
supported: bool = True
|
|
86
|
+
version: str = ""
|
|
87
|
+
notes: str = ""
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@dataclass
|
|
91
|
+
class AgentModel:
|
|
92
|
+
"""An available model for an agent."""
|
|
93
|
+
|
|
94
|
+
id: str
|
|
95
|
+
name: str
|
|
96
|
+
provider: str = ""
|
|
97
|
+
is_free: bool = False
|
|
98
|
+
description: str = ""
|
|
99
|
+
context_window: int = 0
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
@dataclass
|
|
103
|
+
class DiscoveredAgent:
|
|
104
|
+
"""Information about a discovered agent."""
|
|
105
|
+
|
|
106
|
+
# Identity
|
|
107
|
+
name: str # Display name
|
|
108
|
+
short_name: str # Short identifier
|
|
109
|
+
command: List[str] # Command to run ACP
|
|
110
|
+
|
|
111
|
+
# Status
|
|
112
|
+
status: AgentStatus = AgentStatus.NOT_INSTALLED
|
|
113
|
+
version: str = ""
|
|
114
|
+
error_message: str = ""
|
|
115
|
+
|
|
116
|
+
# Connection
|
|
117
|
+
connection_type: ConnectionType = ConnectionType.ACP
|
|
118
|
+
requires_api_key: bool = False
|
|
119
|
+
api_key_env_vars: List[str] = field(default_factory=list)
|
|
120
|
+
has_api_key: bool = False
|
|
121
|
+
|
|
122
|
+
# Capabilities
|
|
123
|
+
capabilities: List[AgentCapability] = field(default_factory=list)
|
|
124
|
+
models: List[AgentModel] = field(default_factory=list)
|
|
125
|
+
|
|
126
|
+
# Metadata
|
|
127
|
+
icon: str = "🤖"
|
|
128
|
+
color: str = "#a855f7"
|
|
129
|
+
website: str = ""
|
|
130
|
+
description: str = ""
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
# ============================================================================
|
|
134
|
+
# AGENT DEFINITIONS
|
|
135
|
+
# ============================================================================
|
|
136
|
+
|
|
137
|
+
KNOWN_AGENTS: List[Dict[str, Any]] = [
|
|
138
|
+
# =========================================================================
|
|
139
|
+
# 1. Gemini CLI - Google's Reference ACP Implementation
|
|
140
|
+
# =========================================================================
|
|
141
|
+
{
|
|
142
|
+
"name": "Gemini CLI",
|
|
143
|
+
"short_name": "gemini",
|
|
144
|
+
"command": ["gemini", "--experimental-acp"],
|
|
145
|
+
"alt_commands": [
|
|
146
|
+
["npx", "-y", "@google/gemini-cli", "--experimental-acp"],
|
|
147
|
+
["gemini-cli", "--experimental-acp"],
|
|
148
|
+
],
|
|
149
|
+
"icon": "✨",
|
|
150
|
+
"color": "#4285f4",
|
|
151
|
+
"description": "Google's reference ACP implementation showing full potential of agent integration",
|
|
152
|
+
"website": "https://github.com/google-gemini/gemini-cli",
|
|
153
|
+
"requires_api_key": True,
|
|
154
|
+
"api_key_env_vars": ["GEMINI_API_KEY", "GOOGLE_API_KEY"],
|
|
155
|
+
"check_command": ["gemini", "--version"],
|
|
156
|
+
},
|
|
157
|
+
# =========================================================================
|
|
158
|
+
# 2. Claude Code - Anthropic's Claude via Zed SDK Adapter
|
|
159
|
+
# =========================================================================
|
|
160
|
+
{
|
|
161
|
+
"name": "Claude Code",
|
|
162
|
+
"short_name": "claude-code",
|
|
163
|
+
"command": ["claude", "--acp"],
|
|
164
|
+
"alt_commands": [
|
|
165
|
+
["npx", "-y", "@anthropic-ai/claude-code", "--acp"],
|
|
166
|
+
["claude-code-acp"],
|
|
167
|
+
["npx", "@anthropic-ai/claude-code-acp"],
|
|
168
|
+
],
|
|
169
|
+
"icon": "🧡",
|
|
170
|
+
"color": "#d97706",
|
|
171
|
+
"description": "Anthropic's Claude integrated through Zed's SDK adapter",
|
|
172
|
+
"website": "https://claude.ai/code",
|
|
173
|
+
"requires_api_key": True,
|
|
174
|
+
"api_key_env_vars": ["ANTHROPIC_API_KEY"],
|
|
175
|
+
"check_command": ["claude", "--version"],
|
|
176
|
+
},
|
|
177
|
+
# =========================================================================
|
|
178
|
+
# 3. Codex - OpenAI's Code Generation Agent
|
|
179
|
+
# =========================================================================
|
|
180
|
+
{
|
|
181
|
+
"name": "Codex",
|
|
182
|
+
"short_name": "codex",
|
|
183
|
+
"command": ["codex", "--acp"],
|
|
184
|
+
"alt_commands": [
|
|
185
|
+
["npx", "-y", "@openai/codex", "--acp"],
|
|
186
|
+
["npx", "@openai/codex-acp"],
|
|
187
|
+
],
|
|
188
|
+
"icon": "📜",
|
|
189
|
+
"color": "#10b981",
|
|
190
|
+
"description": "OpenAI's code generation agent with streaming terminal output",
|
|
191
|
+
"website": "https://github.com/openai/codex",
|
|
192
|
+
"requires_api_key": True,
|
|
193
|
+
"api_key_env_vars": ["OPENAI_API_KEY", "CODEX_API_KEY"],
|
|
194
|
+
"check_command": ["codex", "--version"],
|
|
195
|
+
},
|
|
196
|
+
# =========================================================================
|
|
197
|
+
# 4. JetBrains Junie - JetBrains AI Agent
|
|
198
|
+
# =========================================================================
|
|
199
|
+
{
|
|
200
|
+
"name": "JetBrains Junie",
|
|
201
|
+
"short_name": "junie",
|
|
202
|
+
"command": ["junie", "--acp"],
|
|
203
|
+
"alt_commands": [
|
|
204
|
+
["npx", "-y", "@jetbrains/junie", "--acp"],
|
|
205
|
+
],
|
|
206
|
+
"icon": "🧠",
|
|
207
|
+
"color": "#fe315d",
|
|
208
|
+
"description": "JetBrains' AI agent with ACP support across their entire IDE ecosystem",
|
|
209
|
+
"website": "https://www.jetbrains.com/junie/",
|
|
210
|
+
"requires_api_key": False, # Uses JetBrains account
|
|
211
|
+
"api_key_env_vars": ["JETBRAINS_API_KEY"],
|
|
212
|
+
"check_command": ["junie", "--version"],
|
|
213
|
+
},
|
|
214
|
+
# =========================================================================
|
|
215
|
+
# 5. Goose - Square's Open-Source Agent
|
|
216
|
+
# =========================================================================
|
|
217
|
+
{
|
|
218
|
+
"name": "Goose",
|
|
219
|
+
"short_name": "goose",
|
|
220
|
+
"command": ["goose", "mcp"],
|
|
221
|
+
"alt_commands": [
|
|
222
|
+
["goose", "acp"],
|
|
223
|
+
["goose", "--acp"],
|
|
224
|
+
],
|
|
225
|
+
"icon": "🦆",
|
|
226
|
+
"color": "#8b5cf6",
|
|
227
|
+
"description": "Square's open-source agent with native ACP implementation",
|
|
228
|
+
"website": "https://github.com/block/goose",
|
|
229
|
+
"requires_api_key": True,
|
|
230
|
+
"api_key_env_vars": ["OPENAI_API_KEY", "ANTHROPIC_API_KEY", "GOOGLE_API_KEY"],
|
|
231
|
+
"check_command": ["goose", "--version"],
|
|
232
|
+
},
|
|
233
|
+
# =========================================================================
|
|
234
|
+
# 6. Kimi CLI - CLI AI Agent with ACP
|
|
235
|
+
# =========================================================================
|
|
236
|
+
{
|
|
237
|
+
"name": "Kimi CLI",
|
|
238
|
+
"short_name": "kimi",
|
|
239
|
+
"command": ["kimi", "--acp"],
|
|
240
|
+
"alt_commands": [
|
|
241
|
+
["npx", "-y", "@anthropic-ai/kimi-cli", "--acp"],
|
|
242
|
+
["kimi-cli", "--acp"],
|
|
243
|
+
],
|
|
244
|
+
"icon": "🌙",
|
|
245
|
+
"color": "#5b21b6",
|
|
246
|
+
"description": "CLI AI agent implementing ACP with support for various development workflows",
|
|
247
|
+
"website": "https://github.com/anthropics/kimi-cli",
|
|
248
|
+
"requires_api_key": True,
|
|
249
|
+
"api_key_env_vars": ["MOONSHOT_API_KEY", "KIMI_API_KEY"],
|
|
250
|
+
"check_command": ["kimi", "--version"],
|
|
251
|
+
},
|
|
252
|
+
# =========================================================================
|
|
253
|
+
# 7. OpenCode - Open-Source Coding Agent
|
|
254
|
+
# =========================================================================
|
|
255
|
+
{
|
|
256
|
+
"name": "OpenCode",
|
|
257
|
+
"short_name": "opencode",
|
|
258
|
+
"command": ["opencode", "acp"],
|
|
259
|
+
"alt_commands": [
|
|
260
|
+
["opencode", "--acp"],
|
|
261
|
+
],
|
|
262
|
+
"icon": "🌿",
|
|
263
|
+
"color": "#22c55e",
|
|
264
|
+
"description": "Open-source coding agent with ACP implementation for flexible integration",
|
|
265
|
+
"website": "https://github.com/opencode-ai/opencode",
|
|
266
|
+
"requires_api_key": False, # Uses cloud with free tier
|
|
267
|
+
"api_key_env_vars": ["OPENAI_API_KEY", "ANTHROPIC_API_KEY"],
|
|
268
|
+
"check_command": ["opencode", "--version"],
|
|
269
|
+
},
|
|
270
|
+
# =========================================================================
|
|
271
|
+
# 8. Stakpak - ACP-Compatible Code Assistance
|
|
272
|
+
# =========================================================================
|
|
273
|
+
{
|
|
274
|
+
"name": "Stakpak",
|
|
275
|
+
"short_name": "stakpak",
|
|
276
|
+
"command": ["stakpak", "--acp"],
|
|
277
|
+
"alt_commands": [
|
|
278
|
+
["npx", "-y", "stakpak", "--acp"],
|
|
279
|
+
],
|
|
280
|
+
"icon": "📦",
|
|
281
|
+
"color": "#0ea5e9",
|
|
282
|
+
"description": "ACP-compatible agent for comprehensive code assistance and collaboration",
|
|
283
|
+
"website": "https://stakpak.dev",
|
|
284
|
+
"requires_api_key": True,
|
|
285
|
+
"api_key_env_vars": ["STAKPAK_API_KEY", "OPENAI_API_KEY"],
|
|
286
|
+
"check_command": ["stakpak", "--version"],
|
|
287
|
+
},
|
|
288
|
+
# =========================================================================
|
|
289
|
+
# 9. VT Code - Versatile Coding Agent
|
|
290
|
+
# =========================================================================
|
|
291
|
+
{
|
|
292
|
+
"name": "VT Code",
|
|
293
|
+
"short_name": "vtcode",
|
|
294
|
+
"command": ["vtcode", "--acp"],
|
|
295
|
+
"alt_commands": [
|
|
296
|
+
["vt-code", "--acp"],
|
|
297
|
+
["npx", "-y", "vtcode", "--acp"],
|
|
298
|
+
],
|
|
299
|
+
"icon": "⚡",
|
|
300
|
+
"color": "#f59e0b",
|
|
301
|
+
"description": "Versatile coding agent implementing ACP for seamless integration",
|
|
302
|
+
"website": "https://vtcode.dev",
|
|
303
|
+
"requires_api_key": True,
|
|
304
|
+
"api_key_env_vars": ["VTCODE_API_KEY", "OPENAI_API_KEY"],
|
|
305
|
+
"check_command": ["vtcode", "--version"],
|
|
306
|
+
},
|
|
307
|
+
# =========================================================================
|
|
308
|
+
# 10. Augment Code (Auggie) - Agentic Code Capabilities
|
|
309
|
+
# =========================================================================
|
|
310
|
+
{
|
|
311
|
+
"name": "Augment Code",
|
|
312
|
+
"short_name": "auggie",
|
|
313
|
+
"command": ["auggie", "--acp"],
|
|
314
|
+
"alt_commands": [
|
|
315
|
+
["augment", "--acp"],
|
|
316
|
+
["npx", "-y", "@anthropic-ai/auggie", "--acp"],
|
|
317
|
+
],
|
|
318
|
+
"icon": "🔮",
|
|
319
|
+
"color": "#ec4899",
|
|
320
|
+
"description": "Powerful agentic capabilities to analyze code, make changes, and execute tools",
|
|
321
|
+
"website": "https://www.augmentcode.com",
|
|
322
|
+
"requires_api_key": True,
|
|
323
|
+
"api_key_env_vars": ["AUGMENT_API_KEY"],
|
|
324
|
+
"check_command": ["auggie", "--version"],
|
|
325
|
+
},
|
|
326
|
+
# =========================================================================
|
|
327
|
+
# 11. Code Assistant - AI Coding Assistant in Rust
|
|
328
|
+
# =========================================================================
|
|
329
|
+
{
|
|
330
|
+
"name": "Code Assistant",
|
|
331
|
+
"short_name": "code-assistant",
|
|
332
|
+
"command": ["code-assistant", "--acp"],
|
|
333
|
+
"alt_commands": [
|
|
334
|
+
["ca", "--acp"],
|
|
335
|
+
],
|
|
336
|
+
"icon": "🦀",
|
|
337
|
+
"color": "#f97316",
|
|
338
|
+
"description": "AI coding assistant built in Rust for autonomous code analysis and modification",
|
|
339
|
+
"website": "https://github.com/anthropics/code-assistant",
|
|
340
|
+
"requires_api_key": True,
|
|
341
|
+
"api_key_env_vars": ["OPENAI_API_KEY", "ANTHROPIC_API_KEY"],
|
|
342
|
+
"check_command": ["code-assistant", "--version"],
|
|
343
|
+
},
|
|
344
|
+
# =========================================================================
|
|
345
|
+
# 12. cagent - Multi-Agent Runtime
|
|
346
|
+
# =========================================================================
|
|
347
|
+
{
|
|
348
|
+
"name": "cagent",
|
|
349
|
+
"short_name": "cagent",
|
|
350
|
+
"command": ["cagent", "--acp"],
|
|
351
|
+
"alt_commands": [
|
|
352
|
+
["npx", "-y", "cagent", "--acp"],
|
|
353
|
+
],
|
|
354
|
+
"icon": "🤖",
|
|
355
|
+
"color": "#6366f1",
|
|
356
|
+
"description": "Powerful, easy-to-use, customizable multi-agent runtime that orchestrates AI agents",
|
|
357
|
+
"website": "https://github.com/anthropics/cagent",
|
|
358
|
+
"requires_api_key": True,
|
|
359
|
+
"api_key_env_vars": ["OPENAI_API_KEY", "ANTHROPIC_API_KEY"],
|
|
360
|
+
"check_command": ["cagent", "--version"],
|
|
361
|
+
},
|
|
362
|
+
# =========================================================================
|
|
363
|
+
# 13. fast-agent - Sophisticated Agent Workflows
|
|
364
|
+
# =========================================================================
|
|
365
|
+
{
|
|
366
|
+
"name": "fast-agent",
|
|
367
|
+
"short_name": "fast-agent",
|
|
368
|
+
"command": ["fast-agent", "--acp"],
|
|
369
|
+
"alt_commands": [
|
|
370
|
+
["fastagent", "--acp"],
|
|
371
|
+
["npx", "-y", "fast-agent", "--acp"],
|
|
372
|
+
],
|
|
373
|
+
"icon": "🚀",
|
|
374
|
+
"color": "#14b8a6",
|
|
375
|
+
"description": "Create and interact with sophisticated Agents and Workflows in minutes",
|
|
376
|
+
"website": "https://github.com/anthropics/fast-agent",
|
|
377
|
+
"requires_api_key": True,
|
|
378
|
+
"api_key_env_vars": ["OPENAI_API_KEY", "ANTHROPIC_API_KEY"],
|
|
379
|
+
"check_command": ["fast-agent", "--version"],
|
|
380
|
+
},
|
|
381
|
+
# =========================================================================
|
|
382
|
+
# 14. LLMling-Agent - LLM-Powered Agent Framework
|
|
383
|
+
# =========================================================================
|
|
384
|
+
{
|
|
385
|
+
"name": "LLMling-Agent",
|
|
386
|
+
"short_name": "llmling-agent",
|
|
387
|
+
"command": ["llmling-agent", "--acp"],
|
|
388
|
+
"alt_commands": [
|
|
389
|
+
["llmling", "--acp"],
|
|
390
|
+
["pip", "run", "llmling-agent", "--acp"],
|
|
391
|
+
],
|
|
392
|
+
"icon": "🔗",
|
|
393
|
+
"color": "#a855f7",
|
|
394
|
+
"description": "Framework for creating and managing LLM-powered agents with structured interactions",
|
|
395
|
+
"website": "https://github.com/anthropics/llmling-agent",
|
|
396
|
+
"requires_api_key": True,
|
|
397
|
+
"api_key_env_vars": ["OPENAI_API_KEY", "ANTHROPIC_API_KEY"],
|
|
398
|
+
"check_command": ["llmling-agent", "--version"],
|
|
399
|
+
},
|
|
400
|
+
]
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
# ============================================================================
|
|
404
|
+
# ACP DISCOVERY
|
|
405
|
+
# ============================================================================
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
class ACPDiscovery:
|
|
409
|
+
"""
|
|
410
|
+
Discovers ACP-compatible agents on the system.
|
|
411
|
+
"""
|
|
412
|
+
|
|
413
|
+
def __init__(self):
|
|
414
|
+
self._agents: Dict[str, DiscoveredAgent] = {}
|
|
415
|
+
self._discovered = False
|
|
416
|
+
|
|
417
|
+
# ========================================================================
|
|
418
|
+
# DISCOVERY
|
|
419
|
+
# ========================================================================
|
|
420
|
+
|
|
421
|
+
async def discover_all(self, force: bool = False) -> List[DiscoveredAgent]:
|
|
422
|
+
"""
|
|
423
|
+
Discover all available ACP agents.
|
|
424
|
+
|
|
425
|
+
Returns list of discovered agents.
|
|
426
|
+
"""
|
|
427
|
+
if self._discovered and not force:
|
|
428
|
+
return list(self._agents.values())
|
|
429
|
+
|
|
430
|
+
# Run checks in parallel
|
|
431
|
+
tasks = [self._check_agent(agent_def) for agent_def in KNOWN_AGENTS]
|
|
432
|
+
agents = await asyncio.gather(*tasks)
|
|
433
|
+
|
|
434
|
+
# Store results
|
|
435
|
+
self._agents.clear()
|
|
436
|
+
for agent in agents:
|
|
437
|
+
self._agents[agent.short_name] = agent
|
|
438
|
+
|
|
439
|
+
self._discovered = True
|
|
440
|
+
return agents
|
|
441
|
+
|
|
442
|
+
async def _check_agent(self, agent_def: Dict[str, Any]) -> DiscoveredAgent:
|
|
443
|
+
"""Check if an agent is available."""
|
|
444
|
+
agent = DiscoveredAgent(
|
|
445
|
+
name=agent_def["name"],
|
|
446
|
+
short_name=agent_def["short_name"],
|
|
447
|
+
command=agent_def["command"],
|
|
448
|
+
icon=agent_def.get("icon", "🤖"),
|
|
449
|
+
color=agent_def.get("color", "#a855f7"),
|
|
450
|
+
description=agent_def.get("description", ""),
|
|
451
|
+
website=agent_def.get("website", ""),
|
|
452
|
+
requires_api_key=agent_def.get("requires_api_key", False),
|
|
453
|
+
api_key_env_vars=agent_def.get("api_key_env_vars", []),
|
|
454
|
+
)
|
|
455
|
+
|
|
456
|
+
try:
|
|
457
|
+
# Check if command exists
|
|
458
|
+
cmd = agent_def.get("check_command", agent_def["command"])
|
|
459
|
+
|
|
460
|
+
# Try main command first
|
|
461
|
+
is_available, version = await self._check_command(cmd)
|
|
462
|
+
|
|
463
|
+
# Try alternative commands if main fails
|
|
464
|
+
if not is_available and "alt_commands" in agent_def:
|
|
465
|
+
for alt_cmd in agent_def["alt_commands"]:
|
|
466
|
+
is_available, version = await self._check_command(alt_cmd)
|
|
467
|
+
if is_available:
|
|
468
|
+
agent.command = alt_cmd
|
|
469
|
+
break
|
|
470
|
+
|
|
471
|
+
if is_available:
|
|
472
|
+
agent.status = AgentStatus.AVAILABLE
|
|
473
|
+
agent.version = version
|
|
474
|
+
|
|
475
|
+
# Check for API key
|
|
476
|
+
if agent.requires_api_key:
|
|
477
|
+
agent.has_api_key = any(os.environ.get(var) for var in agent.api_key_env_vars)
|
|
478
|
+
if not agent.has_api_key:
|
|
479
|
+
agent.status = AgentStatus.NOT_CONFIGURED
|
|
480
|
+
agent.error_message = (
|
|
481
|
+
f"Missing API key. Set one of: {', '.join(agent.api_key_env_vars)}"
|
|
482
|
+
)
|
|
483
|
+
|
|
484
|
+
# Get capabilities and models
|
|
485
|
+
agent.capabilities = await self._get_capabilities(agent)
|
|
486
|
+
agent.models = await self._get_models(agent)
|
|
487
|
+
|
|
488
|
+
else:
|
|
489
|
+
agent.status = AgentStatus.NOT_INSTALLED
|
|
490
|
+
|
|
491
|
+
except Exception as e:
|
|
492
|
+
agent.status = AgentStatus.ERROR
|
|
493
|
+
agent.error_message = str(e)
|
|
494
|
+
|
|
495
|
+
return agent
|
|
496
|
+
|
|
497
|
+
async def _check_command(self, cmd: List[str]) -> Tuple[bool, str]:
|
|
498
|
+
"""
|
|
499
|
+
Check if a command exists and get its version.
|
|
500
|
+
|
|
501
|
+
Returns (is_available, version).
|
|
502
|
+
"""
|
|
503
|
+
try:
|
|
504
|
+
# First check if the base command exists
|
|
505
|
+
base_cmd = cmd[0]
|
|
506
|
+
if not shutil.which(base_cmd) and base_cmd != "npx":
|
|
507
|
+
return (False, "")
|
|
508
|
+
|
|
509
|
+
# Try to get version
|
|
510
|
+
loop = asyncio.get_event_loop()
|
|
511
|
+
|
|
512
|
+
def run_check():
|
|
513
|
+
result = subprocess.run(
|
|
514
|
+
cmd,
|
|
515
|
+
capture_output=True,
|
|
516
|
+
text=True,
|
|
517
|
+
timeout=10,
|
|
518
|
+
)
|
|
519
|
+
return result
|
|
520
|
+
|
|
521
|
+
result = await loop.run_in_executor(None, run_check)
|
|
522
|
+
|
|
523
|
+
if result.returncode == 0:
|
|
524
|
+
# Try to extract version from output
|
|
525
|
+
version = ""
|
|
526
|
+
for line in (result.stdout + result.stderr).split("\n"):
|
|
527
|
+
line = line.strip()
|
|
528
|
+
if line and ("version" in line.lower() or line[0].isdigit()):
|
|
529
|
+
version = line
|
|
530
|
+
break
|
|
531
|
+
|
|
532
|
+
return (True, version or "installed")
|
|
533
|
+
|
|
534
|
+
# Command exists but returned error - might still be usable
|
|
535
|
+
return (shutil.which(base_cmd) is not None or base_cmd == "npx", "")
|
|
536
|
+
|
|
537
|
+
except subprocess.TimeoutExpired:
|
|
538
|
+
return (True, "timeout")
|
|
539
|
+
except Exception:
|
|
540
|
+
return (False, "")
|
|
541
|
+
|
|
542
|
+
async def _get_capabilities(self, agent: DiscoveredAgent) -> List[AgentCapability]:
|
|
543
|
+
"""Get agent capabilities via ACP handshake."""
|
|
544
|
+
# Standard ACP capabilities
|
|
545
|
+
capabilities = [
|
|
546
|
+
AgentCapability(name="file_read", supported=True),
|
|
547
|
+
AgentCapability(name="file_write", supported=True),
|
|
548
|
+
AgentCapability(name="shell", supported=True),
|
|
549
|
+
AgentCapability(name="search", supported=True),
|
|
550
|
+
]
|
|
551
|
+
|
|
552
|
+
# TODO: Actually query agent for capabilities
|
|
553
|
+
# This would involve starting the ACP process and doing handshake
|
|
554
|
+
|
|
555
|
+
return capabilities
|
|
556
|
+
|
|
557
|
+
async def _get_models(self, agent: DiscoveredAgent) -> List[AgentModel]:
|
|
558
|
+
"""Get available models for an agent."""
|
|
559
|
+
# Predefined models based on agent type
|
|
560
|
+
models_map = {
|
|
561
|
+
# Gemini CLI - Google's models
|
|
562
|
+
"gemini": [
|
|
563
|
+
AgentModel(
|
|
564
|
+
id="gemini-2.5-pro",
|
|
565
|
+
name="Gemini 2.5 Pro",
|
|
566
|
+
provider="google",
|
|
567
|
+
description="Latest Gemini Pro with 2M context",
|
|
568
|
+
context_window=2000000,
|
|
569
|
+
),
|
|
570
|
+
AgentModel(
|
|
571
|
+
id="gemini-2.5-flash",
|
|
572
|
+
name="Gemini 2.5 Flash",
|
|
573
|
+
provider="google",
|
|
574
|
+
description="Fast Gemini with 1M context",
|
|
575
|
+
context_window=1000000,
|
|
576
|
+
),
|
|
577
|
+
AgentModel(
|
|
578
|
+
id="gemini-2.0-flash",
|
|
579
|
+
name="Gemini 2.0 Flash",
|
|
580
|
+
provider="google",
|
|
581
|
+
description="Previous generation flash model",
|
|
582
|
+
context_window=1000000,
|
|
583
|
+
),
|
|
584
|
+
AgentModel(
|
|
585
|
+
id="gemini-2.0-flash-thinking",
|
|
586
|
+
name="Gemini 2.0 Flash Thinking",
|
|
587
|
+
provider="google",
|
|
588
|
+
description="Flash model with extended thinking",
|
|
589
|
+
context_window=1000000,
|
|
590
|
+
),
|
|
591
|
+
AgentModel(
|
|
592
|
+
id="gemini-exp-1206",
|
|
593
|
+
name="Gemini Experimental",
|
|
594
|
+
provider="google",
|
|
595
|
+
description="Experimental Gemini model",
|
|
596
|
+
context_window=2000000,
|
|
597
|
+
),
|
|
598
|
+
],
|
|
599
|
+
# Claude Code - Anthropic's models
|
|
600
|
+
"claude-code": [
|
|
601
|
+
AgentModel(
|
|
602
|
+
id="claude-sonnet-4-20250514",
|
|
603
|
+
name="Claude Sonnet 4",
|
|
604
|
+
provider="anthropic",
|
|
605
|
+
description="Latest Claude Sonnet",
|
|
606
|
+
),
|
|
607
|
+
AgentModel(
|
|
608
|
+
id="claude-opus-4-20250514",
|
|
609
|
+
name="Claude Opus 4",
|
|
610
|
+
provider="anthropic",
|
|
611
|
+
description="Most capable Claude model",
|
|
612
|
+
),
|
|
613
|
+
AgentModel(
|
|
614
|
+
id="claude-3-5-sonnet-20241022",
|
|
615
|
+
name="Claude 3.5 Sonnet",
|
|
616
|
+
provider="anthropic",
|
|
617
|
+
description="Previous generation Sonnet",
|
|
618
|
+
),
|
|
619
|
+
],
|
|
620
|
+
# Codex - OpenAI's models
|
|
621
|
+
"codex": [
|
|
622
|
+
AgentModel(
|
|
623
|
+
id="o3", name="O3", provider="openai", description="Latest reasoning model"
|
|
624
|
+
),
|
|
625
|
+
AgentModel(
|
|
626
|
+
id="o3-mini", name="O3 Mini", provider="openai", description="Fast reasoning"
|
|
627
|
+
),
|
|
628
|
+
AgentModel(id="o1", name="O1", provider="openai", description="Advanced reasoning"),
|
|
629
|
+
AgentModel(id="o1-mini", name="O1 Mini", provider="openai", description="Fast O1"),
|
|
630
|
+
AgentModel(
|
|
631
|
+
id="gpt-4.1", name="GPT-4.1", provider="openai", description="Latest GPT"
|
|
632
|
+
),
|
|
633
|
+
AgentModel(
|
|
634
|
+
id="gpt-4o", name="GPT-4o", provider="openai", description="Multimodal GPT"
|
|
635
|
+
),
|
|
636
|
+
],
|
|
637
|
+
# JetBrains Junie
|
|
638
|
+
"junie": [
|
|
639
|
+
AgentModel(id="auto", name="Auto", description="Automatic model selection"),
|
|
640
|
+
AgentModel(id="junie-pro", name="Junie Pro", description="JetBrains Pro model"),
|
|
641
|
+
],
|
|
642
|
+
# Goose - Square's agent
|
|
643
|
+
"goose": [
|
|
644
|
+
AgentModel(id="auto", name="Auto", description="Automatic model selection"),
|
|
645
|
+
AgentModel(id="claude-3-5-sonnet", name="Claude 3.5 Sonnet", provider="anthropic"),
|
|
646
|
+
AgentModel(id="gpt-4o", name="GPT-4o", provider="openai"),
|
|
647
|
+
AgentModel(id="gemini-2.5-pro", name="Gemini 2.5 Pro", provider="google"),
|
|
648
|
+
],
|
|
649
|
+
# Kimi CLI
|
|
650
|
+
"kimi": [
|
|
651
|
+
AgentModel(
|
|
652
|
+
id="moonshot-v1-128k",
|
|
653
|
+
name="Moonshot V1 128K",
|
|
654
|
+
provider="moonshot",
|
|
655
|
+
context_window=128000,
|
|
656
|
+
),
|
|
657
|
+
AgentModel(
|
|
658
|
+
id="moonshot-v1-32k",
|
|
659
|
+
name="Moonshot V1 32K",
|
|
660
|
+
provider="moonshot",
|
|
661
|
+
context_window=32000,
|
|
662
|
+
),
|
|
663
|
+
AgentModel(
|
|
664
|
+
id="moonshot-v1-8k",
|
|
665
|
+
name="Moonshot V1 8K",
|
|
666
|
+
provider="moonshot",
|
|
667
|
+
context_window=8000,
|
|
668
|
+
),
|
|
669
|
+
],
|
|
670
|
+
# OpenCode
|
|
671
|
+
"opencode": [
|
|
672
|
+
AgentModel(
|
|
673
|
+
id="auto", name="Auto", is_free=True, description="Automatic model selection"
|
|
674
|
+
),
|
|
675
|
+
AgentModel(id="claude-3-5-sonnet", name="Claude 3.5 Sonnet", is_free=True),
|
|
676
|
+
AgentModel(id="gpt-4o", name="GPT-4o", is_free=True),
|
|
677
|
+
AgentModel(id="gemini-2.5-pro", name="Gemini 2.5 Pro", is_free=True),
|
|
678
|
+
],
|
|
679
|
+
# Stakpak
|
|
680
|
+
"stakpak": [
|
|
681
|
+
AgentModel(id="auto", name="Auto", description="Automatic model selection"),
|
|
682
|
+
AgentModel(
|
|
683
|
+
id="stakpak-pro", name="Stakpak Pro", description="Enhanced capabilities"
|
|
684
|
+
),
|
|
685
|
+
],
|
|
686
|
+
# VT Code
|
|
687
|
+
"vtcode": [
|
|
688
|
+
AgentModel(id="auto", name="Auto", description="Automatic model selection"),
|
|
689
|
+
AgentModel(
|
|
690
|
+
id="vtcode-pro", name="VT Code Pro", description="Enhanced capabilities"
|
|
691
|
+
),
|
|
692
|
+
],
|
|
693
|
+
# Augment Code (Auggie)
|
|
694
|
+
"auggie": [
|
|
695
|
+
AgentModel(id="auto", name="Auto", description="Automatic model selection"),
|
|
696
|
+
AgentModel(id="auggie-pro", name="Auggie Pro", description="Enhanced capabilities"),
|
|
697
|
+
],
|
|
698
|
+
# Code Assistant
|
|
699
|
+
"code-assistant": [
|
|
700
|
+
AgentModel(id="auto", name="Auto", description="Automatic model selection"),
|
|
701
|
+
AgentModel(id="claude-3-5-sonnet", name="Claude 3.5 Sonnet", provider="anthropic"),
|
|
702
|
+
AgentModel(id="gpt-4o", name="GPT-4o", provider="openai"),
|
|
703
|
+
],
|
|
704
|
+
# cagent
|
|
705
|
+
"cagent": [
|
|
706
|
+
AgentModel(id="auto", name="Auto", description="Automatic model selection"),
|
|
707
|
+
AgentModel(id="claude-3-5-sonnet", name="Claude 3.5 Sonnet", provider="anthropic"),
|
|
708
|
+
AgentModel(id="gpt-4o", name="GPT-4o", provider="openai"),
|
|
709
|
+
],
|
|
710
|
+
# fast-agent
|
|
711
|
+
"fast-agent": [
|
|
712
|
+
AgentModel(id="auto", name="Auto", description="Automatic model selection"),
|
|
713
|
+
AgentModel(id="claude-3-5-sonnet", name="Claude 3.5 Sonnet", provider="anthropic"),
|
|
714
|
+
AgentModel(id="gpt-4o", name="GPT-4o", provider="openai"),
|
|
715
|
+
],
|
|
716
|
+
# LLMling-Agent
|
|
717
|
+
"llmling-agent": [
|
|
718
|
+
AgentModel(id="auto", name="Auto", description="Automatic model selection"),
|
|
719
|
+
AgentModel(id="claude-3-5-sonnet", name="Claude 3.5 Sonnet", provider="anthropic"),
|
|
720
|
+
AgentModel(id="gpt-4o", name="GPT-4o", provider="openai"),
|
|
721
|
+
],
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
return models_map.get(agent.short_name, [])
|
|
725
|
+
|
|
726
|
+
# ========================================================================
|
|
727
|
+
# QUERIES
|
|
728
|
+
# ========================================================================
|
|
729
|
+
|
|
730
|
+
def get_agent(self, short_name: str) -> Optional[DiscoveredAgent]:
|
|
731
|
+
"""Get a specific agent by short name."""
|
|
732
|
+
return self._agents.get(short_name)
|
|
733
|
+
|
|
734
|
+
def get_available_agents(self) -> List[DiscoveredAgent]:
|
|
735
|
+
"""Get list of available (ready to use) agents."""
|
|
736
|
+
return [a for a in self._agents.values() if a.status == AgentStatus.AVAILABLE]
|
|
737
|
+
|
|
738
|
+
def get_all_agents(self) -> List[DiscoveredAgent]:
|
|
739
|
+
"""Get all known agents."""
|
|
740
|
+
return list(self._agents.values())
|
|
741
|
+
|
|
742
|
+
# ========================================================================
|
|
743
|
+
# HEALTH CHECK
|
|
744
|
+
# ========================================================================
|
|
745
|
+
|
|
746
|
+
async def health_check(self, short_name: str) -> Tuple[bool, str]:
|
|
747
|
+
"""
|
|
748
|
+
Perform a health check on an agent.
|
|
749
|
+
|
|
750
|
+
Returns (is_healthy, message).
|
|
751
|
+
"""
|
|
752
|
+
agent = self._agents.get(short_name)
|
|
753
|
+
if not agent:
|
|
754
|
+
return (False, "Agent not found")
|
|
755
|
+
|
|
756
|
+
if agent.status == AgentStatus.NOT_INSTALLED:
|
|
757
|
+
return (False, "Agent not installed")
|
|
758
|
+
|
|
759
|
+
if agent.status == AgentStatus.NOT_CONFIGURED:
|
|
760
|
+
return (False, agent.error_message or "Agent not configured")
|
|
761
|
+
|
|
762
|
+
try:
|
|
763
|
+
# Try to start ACP and do minimal handshake
|
|
764
|
+
loop = asyncio.get_event_loop()
|
|
765
|
+
|
|
766
|
+
def test_acp():
|
|
767
|
+
process = subprocess.Popen(
|
|
768
|
+
agent.command,
|
|
769
|
+
stdin=subprocess.PIPE,
|
|
770
|
+
stdout=subprocess.PIPE,
|
|
771
|
+
stderr=subprocess.PIPE,
|
|
772
|
+
text=True,
|
|
773
|
+
)
|
|
774
|
+
|
|
775
|
+
# Send minimal hello request
|
|
776
|
+
request = json.dumps(
|
|
777
|
+
{
|
|
778
|
+
"jsonrpc": "2.0",
|
|
779
|
+
"method": "hello",
|
|
780
|
+
"id": 1,
|
|
781
|
+
"params": {},
|
|
782
|
+
}
|
|
783
|
+
)
|
|
784
|
+
|
|
785
|
+
try:
|
|
786
|
+
stdout, stderr = process.communicate(request + "\n", timeout=5)
|
|
787
|
+
process.terminate()
|
|
788
|
+
return "success" in stdout.lower() or "result" in stdout.lower()
|
|
789
|
+
except subprocess.TimeoutExpired:
|
|
790
|
+
process.kill()
|
|
791
|
+
return False
|
|
792
|
+
|
|
793
|
+
is_healthy = await loop.run_in_executor(None, test_acp)
|
|
794
|
+
|
|
795
|
+
if is_healthy:
|
|
796
|
+
return (True, "Agent is healthy")
|
|
797
|
+
else:
|
|
798
|
+
return (False, "Agent did not respond to handshake")
|
|
799
|
+
|
|
800
|
+
except Exception as e:
|
|
801
|
+
return (False, str(e))
|
|
802
|
+
|
|
803
|
+
|
|
804
|
+
# ============================================================================
|
|
805
|
+
# QUICK ACCESS FUNCTIONS
|
|
806
|
+
# ============================================================================
|
|
807
|
+
|
|
808
|
+
_discovery: Optional[ACPDiscovery] = None
|
|
809
|
+
|
|
810
|
+
|
|
811
|
+
async def discover_agents() -> List[DiscoveredAgent]:
|
|
812
|
+
"""Quick function to discover all agents."""
|
|
813
|
+
global _discovery
|
|
814
|
+
if _discovery is None:
|
|
815
|
+
_discovery = ACPDiscovery()
|
|
816
|
+
return await _discovery.discover_all()
|
|
817
|
+
|
|
818
|
+
|
|
819
|
+
async def get_available_agents() -> List[DiscoveredAgent]:
|
|
820
|
+
"""Quick function to get available agents."""
|
|
821
|
+
global _discovery
|
|
822
|
+
if _discovery is None:
|
|
823
|
+
_discovery = ACPDiscovery()
|
|
824
|
+
await _discovery.discover_all()
|
|
825
|
+
return _discovery.get_available_agents()
|
|
826
|
+
|
|
827
|
+
|
|
828
|
+
def get_discovery() -> ACPDiscovery:
|
|
829
|
+
"""Get the global discovery instance."""
|
|
830
|
+
global _discovery
|
|
831
|
+
if _discovery is None:
|
|
832
|
+
_discovery = ACPDiscovery()
|
|
833
|
+
return _discovery
|
|
834
|
+
|
|
835
|
+
|
|
836
|
+
# ============================================================================
|
|
837
|
+
# EXPORTS
|
|
838
|
+
# ============================================================================
|
|
839
|
+
|
|
840
|
+
__all__ = [
|
|
841
|
+
# Enums
|
|
842
|
+
"AgentStatus",
|
|
843
|
+
"ConnectionType",
|
|
844
|
+
# Data classes
|
|
845
|
+
"AgentCapability",
|
|
846
|
+
"AgentModel",
|
|
847
|
+
"DiscoveredAgent",
|
|
848
|
+
# Classes
|
|
849
|
+
"ACPDiscovery",
|
|
850
|
+
# Functions
|
|
851
|
+
"discover_agents",
|
|
852
|
+
"get_available_agents",
|
|
853
|
+
"get_discovery",
|
|
854
|
+
# Constants
|
|
855
|
+
"KNOWN_AGENTS",
|
|
856
|
+
]
|