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.
Files changed (288) hide show
  1. superqode/__init__.py +33 -0
  2. superqode/acp/__init__.py +23 -0
  3. superqode/acp/client.py +913 -0
  4. superqode/acp/permission_screen.py +457 -0
  5. superqode/acp/types.py +480 -0
  6. superqode/acp_discovery.py +856 -0
  7. superqode/agent/__init__.py +22 -0
  8. superqode/agent/edit_strategies.py +334 -0
  9. superqode/agent/loop.py +892 -0
  10. superqode/agent/qe_report_templates.py +39 -0
  11. superqode/agent/system_prompts.py +353 -0
  12. superqode/agent_output.py +721 -0
  13. superqode/agent_stream.py +953 -0
  14. superqode/agents/__init__.py +59 -0
  15. superqode/agents/acp_registry.py +305 -0
  16. superqode/agents/client.py +249 -0
  17. superqode/agents/data/augmentcode.com.toml +51 -0
  18. superqode/agents/data/cagent.dev.toml +51 -0
  19. superqode/agents/data/claude.com.toml +60 -0
  20. superqode/agents/data/codeassistant.dev.toml +51 -0
  21. superqode/agents/data/codex.openai.com.toml +57 -0
  22. superqode/agents/data/fastagent.ai.toml +66 -0
  23. superqode/agents/data/geminicli.com.toml +77 -0
  24. superqode/agents/data/goose.block.xyz.toml +54 -0
  25. superqode/agents/data/junie.jetbrains.com.toml +56 -0
  26. superqode/agents/data/kimi.moonshot.cn.toml +57 -0
  27. superqode/agents/data/llmlingagent.dev.toml +51 -0
  28. superqode/agents/data/molt.bot.toml +49 -0
  29. superqode/agents/data/opencode.ai.toml +60 -0
  30. superqode/agents/data/stakpak.dev.toml +51 -0
  31. superqode/agents/data/vtcode.dev.toml +51 -0
  32. superqode/agents/discovery.py +266 -0
  33. superqode/agents/messaging.py +160 -0
  34. superqode/agents/persona.py +166 -0
  35. superqode/agents/registry.py +421 -0
  36. superqode/agents/schema.py +72 -0
  37. superqode/agents/unified.py +367 -0
  38. superqode/app/__init__.py +111 -0
  39. superqode/app/constants.py +314 -0
  40. superqode/app/css.py +366 -0
  41. superqode/app/models.py +118 -0
  42. superqode/app/suggester.py +125 -0
  43. superqode/app/widgets.py +1591 -0
  44. superqode/app_enhanced.py +399 -0
  45. superqode/app_main.py +17187 -0
  46. superqode/approval.py +312 -0
  47. superqode/atomic.py +296 -0
  48. superqode/commands/__init__.py +1 -0
  49. superqode/commands/acp.py +965 -0
  50. superqode/commands/agents.py +180 -0
  51. superqode/commands/auth.py +278 -0
  52. superqode/commands/config.py +374 -0
  53. superqode/commands/init.py +826 -0
  54. superqode/commands/providers.py +819 -0
  55. superqode/commands/qe.py +1145 -0
  56. superqode/commands/roles.py +380 -0
  57. superqode/commands/serve.py +172 -0
  58. superqode/commands/suggestions.py +127 -0
  59. superqode/commands/superqe.py +460 -0
  60. superqode/config/__init__.py +51 -0
  61. superqode/config/loader.py +812 -0
  62. superqode/config/schema.py +498 -0
  63. superqode/core/__init__.py +111 -0
  64. superqode/core/roles.py +281 -0
  65. superqode/danger.py +386 -0
  66. superqode/data/superqode-template.yaml +1522 -0
  67. superqode/design_system.py +1080 -0
  68. superqode/dialogs/__init__.py +6 -0
  69. superqode/dialogs/base.py +39 -0
  70. superqode/dialogs/model.py +130 -0
  71. superqode/dialogs/provider.py +870 -0
  72. superqode/diff_view.py +919 -0
  73. superqode/enterprise.py +21 -0
  74. superqode/evaluation/__init__.py +25 -0
  75. superqode/evaluation/adapters.py +93 -0
  76. superqode/evaluation/behaviors.py +89 -0
  77. superqode/evaluation/engine.py +209 -0
  78. superqode/evaluation/scenarios.py +96 -0
  79. superqode/execution/__init__.py +36 -0
  80. superqode/execution/linter.py +538 -0
  81. superqode/execution/modes.py +347 -0
  82. superqode/execution/resolver.py +283 -0
  83. superqode/execution/runner.py +642 -0
  84. superqode/file_explorer.py +811 -0
  85. superqode/file_viewer.py +471 -0
  86. superqode/flash.py +183 -0
  87. superqode/guidance/__init__.py +58 -0
  88. superqode/guidance/config.py +203 -0
  89. superqode/guidance/prompts.py +71 -0
  90. superqode/harness/__init__.py +54 -0
  91. superqode/harness/accelerator.py +291 -0
  92. superqode/harness/config.py +319 -0
  93. superqode/harness/validator.py +147 -0
  94. superqode/history.py +279 -0
  95. superqode/integrations/superopt_runner.py +124 -0
  96. superqode/logging/__init__.py +49 -0
  97. superqode/logging/adapters.py +219 -0
  98. superqode/logging/formatter.py +923 -0
  99. superqode/logging/integration.py +341 -0
  100. superqode/logging/sinks.py +170 -0
  101. superqode/logging/unified_log.py +417 -0
  102. superqode/lsp/__init__.py +26 -0
  103. superqode/lsp/client.py +544 -0
  104. superqode/main.py +1069 -0
  105. superqode/mcp/__init__.py +89 -0
  106. superqode/mcp/auth_storage.py +380 -0
  107. superqode/mcp/client.py +1236 -0
  108. superqode/mcp/config.py +319 -0
  109. superqode/mcp/integration.py +337 -0
  110. superqode/mcp/oauth.py +436 -0
  111. superqode/mcp/oauth_callback.py +385 -0
  112. superqode/mcp/types.py +290 -0
  113. superqode/memory/__init__.py +31 -0
  114. superqode/memory/feedback.py +342 -0
  115. superqode/memory/store.py +522 -0
  116. superqode/notifications.py +369 -0
  117. superqode/optimization/__init__.py +5 -0
  118. superqode/optimization/config.py +33 -0
  119. superqode/permissions/__init__.py +25 -0
  120. superqode/permissions/rules.py +488 -0
  121. superqode/plan.py +323 -0
  122. superqode/providers/__init__.py +33 -0
  123. superqode/providers/gateway/__init__.py +165 -0
  124. superqode/providers/gateway/base.py +228 -0
  125. superqode/providers/gateway/litellm_gateway.py +1170 -0
  126. superqode/providers/gateway/openresponses_gateway.py +436 -0
  127. superqode/providers/health.py +297 -0
  128. superqode/providers/huggingface/__init__.py +74 -0
  129. superqode/providers/huggingface/downloader.py +472 -0
  130. superqode/providers/huggingface/endpoints.py +442 -0
  131. superqode/providers/huggingface/hub.py +531 -0
  132. superqode/providers/huggingface/inference.py +394 -0
  133. superqode/providers/huggingface/transformers_runner.py +516 -0
  134. superqode/providers/local/__init__.py +100 -0
  135. superqode/providers/local/base.py +438 -0
  136. superqode/providers/local/discovery.py +418 -0
  137. superqode/providers/local/lmstudio.py +256 -0
  138. superqode/providers/local/mlx.py +457 -0
  139. superqode/providers/local/ollama.py +486 -0
  140. superqode/providers/local/sglang.py +268 -0
  141. superqode/providers/local/tgi.py +260 -0
  142. superqode/providers/local/tool_support.py +477 -0
  143. superqode/providers/local/vllm.py +258 -0
  144. superqode/providers/manager.py +1338 -0
  145. superqode/providers/models.py +1016 -0
  146. superqode/providers/models_dev.py +578 -0
  147. superqode/providers/openresponses/__init__.py +87 -0
  148. superqode/providers/openresponses/converters/__init__.py +17 -0
  149. superqode/providers/openresponses/converters/messages.py +343 -0
  150. superqode/providers/openresponses/converters/tools.py +268 -0
  151. superqode/providers/openresponses/schema/__init__.py +56 -0
  152. superqode/providers/openresponses/schema/models.py +585 -0
  153. superqode/providers/openresponses/streaming/__init__.py +5 -0
  154. superqode/providers/openresponses/streaming/parser.py +338 -0
  155. superqode/providers/openresponses/tools/__init__.py +21 -0
  156. superqode/providers/openresponses/tools/apply_patch.py +352 -0
  157. superqode/providers/openresponses/tools/code_interpreter.py +290 -0
  158. superqode/providers/openresponses/tools/file_search.py +333 -0
  159. superqode/providers/openresponses/tools/mcp_adapter.py +252 -0
  160. superqode/providers/registry.py +716 -0
  161. superqode/providers/usage.py +332 -0
  162. superqode/pure_mode.py +384 -0
  163. superqode/qr/__init__.py +23 -0
  164. superqode/qr/dashboard.py +781 -0
  165. superqode/qr/generator.py +1018 -0
  166. superqode/qr/templates.py +135 -0
  167. superqode/safety/__init__.py +41 -0
  168. superqode/safety/sandbox.py +413 -0
  169. superqode/safety/warnings.py +256 -0
  170. superqode/server/__init__.py +33 -0
  171. superqode/server/lsp_server.py +775 -0
  172. superqode/server/web.py +250 -0
  173. superqode/session/__init__.py +25 -0
  174. superqode/session/persistence.py +580 -0
  175. superqode/session/sharing.py +477 -0
  176. superqode/session.py +475 -0
  177. superqode/sidebar.py +2991 -0
  178. superqode/stream_view.py +648 -0
  179. superqode/styles/__init__.py +3 -0
  180. superqode/superqe/__init__.py +184 -0
  181. superqode/superqe/acp_runner.py +1064 -0
  182. superqode/superqe/constitution/__init__.py +62 -0
  183. superqode/superqe/constitution/evaluator.py +308 -0
  184. superqode/superqe/constitution/loader.py +432 -0
  185. superqode/superqe/constitution/schema.py +250 -0
  186. superqode/superqe/events.py +591 -0
  187. superqode/superqe/frameworks/__init__.py +65 -0
  188. superqode/superqe/frameworks/base.py +234 -0
  189. superqode/superqe/frameworks/e2e.py +263 -0
  190. superqode/superqe/frameworks/executor.py +237 -0
  191. superqode/superqe/frameworks/javascript.py +409 -0
  192. superqode/superqe/frameworks/python.py +373 -0
  193. superqode/superqe/frameworks/registry.py +92 -0
  194. superqode/superqe/mcp_tools/__init__.py +47 -0
  195. superqode/superqe/mcp_tools/core_tools.py +418 -0
  196. superqode/superqe/mcp_tools/registry.py +230 -0
  197. superqode/superqe/mcp_tools/testing_tools.py +167 -0
  198. superqode/superqe/noise.py +89 -0
  199. superqode/superqe/orchestrator.py +778 -0
  200. superqode/superqe/roles.py +609 -0
  201. superqode/superqe/session.py +713 -0
  202. superqode/superqe/skills/__init__.py +57 -0
  203. superqode/superqe/skills/base.py +106 -0
  204. superqode/superqe/skills/core_skills.py +899 -0
  205. superqode/superqe/skills/registry.py +90 -0
  206. superqode/superqe/verifier.py +101 -0
  207. superqode/superqe_cli.py +76 -0
  208. superqode/tool_call.py +358 -0
  209. superqode/tools/__init__.py +93 -0
  210. superqode/tools/agent_tools.py +496 -0
  211. superqode/tools/base.py +324 -0
  212. superqode/tools/batch_tool.py +133 -0
  213. superqode/tools/diagnostics.py +311 -0
  214. superqode/tools/edit_tools.py +653 -0
  215. superqode/tools/enhanced_base.py +515 -0
  216. superqode/tools/file_tools.py +269 -0
  217. superqode/tools/file_tracking.py +45 -0
  218. superqode/tools/lsp_tools.py +610 -0
  219. superqode/tools/network_tools.py +350 -0
  220. superqode/tools/permissions.py +400 -0
  221. superqode/tools/question_tool.py +324 -0
  222. superqode/tools/search_tools.py +598 -0
  223. superqode/tools/shell_tools.py +259 -0
  224. superqode/tools/todo_tools.py +121 -0
  225. superqode/tools/validation.py +80 -0
  226. superqode/tools/web_tools.py +639 -0
  227. superqode/tui.py +1152 -0
  228. superqode/tui_integration.py +875 -0
  229. superqode/tui_widgets/__init__.py +27 -0
  230. superqode/tui_widgets/widgets/__init__.py +18 -0
  231. superqode/tui_widgets/widgets/progress.py +185 -0
  232. superqode/tui_widgets/widgets/tool_display.py +188 -0
  233. superqode/undo_manager.py +574 -0
  234. superqode/utils/__init__.py +5 -0
  235. superqode/utils/error_handling.py +323 -0
  236. superqode/utils/fuzzy.py +257 -0
  237. superqode/widgets/__init__.py +477 -0
  238. superqode/widgets/agent_collab.py +390 -0
  239. superqode/widgets/agent_store.py +936 -0
  240. superqode/widgets/agent_switcher.py +395 -0
  241. superqode/widgets/animation_manager.py +284 -0
  242. superqode/widgets/code_context.py +356 -0
  243. superqode/widgets/command_palette.py +412 -0
  244. superqode/widgets/connection_status.py +537 -0
  245. superqode/widgets/conversation_history.py +470 -0
  246. superqode/widgets/diff_indicator.py +155 -0
  247. superqode/widgets/enhanced_status_bar.py +385 -0
  248. superqode/widgets/enhanced_toast.py +476 -0
  249. superqode/widgets/file_browser.py +809 -0
  250. superqode/widgets/file_reference.py +585 -0
  251. superqode/widgets/issue_timeline.py +340 -0
  252. superqode/widgets/leader_key.py +264 -0
  253. superqode/widgets/mode_switcher.py +445 -0
  254. superqode/widgets/model_picker.py +234 -0
  255. superqode/widgets/permission_preview.py +1205 -0
  256. superqode/widgets/prompt.py +358 -0
  257. superqode/widgets/provider_connect.py +725 -0
  258. superqode/widgets/pty_shell.py +587 -0
  259. superqode/widgets/qe_dashboard.py +321 -0
  260. superqode/widgets/resizable_sidebar.py +377 -0
  261. superqode/widgets/response_changes.py +218 -0
  262. superqode/widgets/response_display.py +528 -0
  263. superqode/widgets/rich_tool_display.py +613 -0
  264. superqode/widgets/sidebar_panels.py +1180 -0
  265. superqode/widgets/slash_complete.py +356 -0
  266. superqode/widgets/split_view.py +612 -0
  267. superqode/widgets/status_bar.py +273 -0
  268. superqode/widgets/superqode_display.py +786 -0
  269. superqode/widgets/thinking_display.py +815 -0
  270. superqode/widgets/throbber.py +87 -0
  271. superqode/widgets/toast.py +206 -0
  272. superqode/widgets/unified_output.py +1073 -0
  273. superqode/workspace/__init__.py +75 -0
  274. superqode/workspace/artifacts.py +472 -0
  275. superqode/workspace/coordinator.py +353 -0
  276. superqode/workspace/diff_tracker.py +429 -0
  277. superqode/workspace/git_guard.py +373 -0
  278. superqode/workspace/git_snapshot.py +526 -0
  279. superqode/workspace/manager.py +750 -0
  280. superqode/workspace/snapshot.py +357 -0
  281. superqode/workspace/watcher.py +535 -0
  282. superqode/workspace/worktree.py +440 -0
  283. superqode-0.1.5.dist-info/METADATA +204 -0
  284. superqode-0.1.5.dist-info/RECORD +288 -0
  285. superqode-0.1.5.dist-info/WHEEL +5 -0
  286. superqode-0.1.5.dist-info/entry_points.txt +3 -0
  287. superqode-0.1.5.dist-info/licenses/LICENSE +648 -0
  288. 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
+ ]