Skip to content

Commit f1b295f

Browse files
authored
Merge pull request #13 from zhujian0805/main
adding support of prompt, agent and MCP for opencode
2 parents 27f6702 + f5d8cc9 commit f1b295f

File tree

15 files changed

+593
-12
lines changed

15 files changed

+593
-12
lines changed

code_assistant_manager/agents/__init__.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
- Gemini: ~/.gemini/agents/
88
- Droid: ~/.factory/agents/
99
- CodeBuddy: ~/.codebuddy/agents/
10+
- OpenCode: ~/.config/opencode/agent/
1011
1112
Reference: https://github.com/iannuttall/claude-agents
1213
"""
@@ -18,9 +19,19 @@
1819
from .copilot import CopilotAgentHandler
1920
from .droid import DroidAgentHandler
2021
from .gemini import GeminiAgentHandler
21-
from .manager import VALID_APP_TYPES, AgentManager
22+
from .opencode import OpenCodeAgentHandler
23+
from .manager import VALID_APP_TYPES, AgentManager, AGENT_HANDLERS
2224
from .models import Agent, AgentRepo
2325

26+
27+
def get_handler(app_type: str) -> BaseAgentHandler:
28+
"""Get an agent handler instance for the specified app type."""
29+
handler_class = AGENT_HANDLERS.get(app_type)
30+
if not handler_class:
31+
raise ValueError(f"Unknown app type: {app_type}. Valid: {VALID_APP_TYPES}")
32+
return handler_class()
33+
34+
2435
__all__ = [
2536
"Agent",
2637
"AgentRepo",
@@ -32,5 +43,7 @@
3243
"DroidAgentHandler",
3344
"CodebuddyAgentHandler",
3445
"CopilotAgentHandler",
46+
"OpenCodeAgentHandler",
47+
"get_handler",
3548
"VALID_APP_TYPES",
3649
]

code_assistant_manager/agents/manager.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from .copilot import CopilotAgentHandler
1818
from .droid import DroidAgentHandler
1919
from .gemini import GeminiAgentHandler
20+
from .opencode import OpenCodeAgentHandler
2021
from .models import Agent, AgentRepo
2122

2223
logger = logging.getLogger(__name__)
@@ -66,6 +67,7 @@ def _load_builtin_agent_repos() -> List[Dict]:
6667
"droid": DroidAgentHandler,
6768
"codebuddy": CodebuddyAgentHandler,
6869
"copilot": CopilotAgentHandler,
70+
"opencode": OpenCodeAgentHandler,
6971
}
7072

7173
# Valid app types for agents
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
"""OpenCode agent handler."""
2+
3+
from pathlib import Path
4+
from typing import Optional
5+
6+
from .base import BaseAgentHandler
7+
8+
9+
class OpenCodeAgentHandler(BaseAgentHandler):
10+
"""Agent handler for OpenCode.
11+
12+
OpenCode agents are markdown files stored in:
13+
- Global: ~/.config/opencode/agent/
14+
- Project: .opencode/agent/
15+
"""
16+
17+
@property
18+
def app_name(self) -> str:
19+
return "opencode"
20+
21+
@property
22+
def _default_agents_dir(self) -> Path:
23+
return Path.home() / ".config" / "opencode" / "agent"

code_assistant_manager/cli/agents_commands.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
"claude",
3131
"--app",
3232
"-a",
33-
help="App type(s) to install to (claude, codex, gemini, droid, codebuddy, all). Comma-separated.",
33+
help="App type(s) to install to (claude, codex, gemini, droid, codebuddy, opencode, all). Comma-separated.",
3434
)
3535
FORCE_OPTION = typer.Option(False, "--force", "-f", help="Skip confirmation")
3636
OWNER_OPTION = typer.Option(..., "--owner", "-o", help="Repository owner")
@@ -43,20 +43,20 @@
4343
None,
4444
"--app",
4545
"-a",
46-
help="App type(s) to show (claude, codex, gemini, droid, codebuddy, all). Default shows all.",
46+
help="App type(s) to show (claude, codex, gemini, droid, codebuddy, opencode, all). Default shows all.",
4747
)
4848
APP_TYPE_OPTION_UNINSTALL = typer.Option(
4949
...,
5050
"--app",
5151
"-a",
52-
help="App type(s) to uninstall all agents from (claude, codex, gemini, droid, codebuddy, all). Comma-separated.",
52+
help="App type(s) to uninstall all agents from (claude, codex, gemini, droid, codebuddy, opencode, all). Comma-separated.",
5353
)
5454
from code_assistant_manager.plugins.fetch import parse_github_url
5555

5656
logger = logging.getLogger(__name__)
5757

5858
agent_app = typer.Typer(
59-
help="Manage agents for AI assistants (Claude, Codex, Gemini, Droid, CodeBuddy)",
59+
help="Manage agents for AI assistants (Claude, Codex, Gemini, Droid, CodeBuddy, OpenCode)",
6060
no_args_is_help=True,
6161
)
6262

code_assistant_manager/cli/prompts_commands.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
logger = logging.getLogger(__name__)
1313

1414
prompt_app = typer.Typer(
15-
help="Manage prompts for AI assistants (Claude, Codex, Gemini, Copilot, CodeBuddy)",
15+
help="Manage prompts for AI assistants (Claude, Codex, Gemini, Copilot, CodeBuddy, OpenCode)",
1616
no_args_is_help=True,
1717
)
1818

@@ -332,7 +332,7 @@ def remove_prompt(
332332
@prompt_app.command("import")
333333
def import_prompt(
334334
name: Optional[str] = typer.Argument(None, help="Name for the imported prompt (auto-generated if not provided)"),
335-
app: str = typer.Option(..., "--app", "-a", help=f"App to import from ({', '.join(VALID_APP_TYPES)})"),
335+
app: str = typer.Option(..., "--app", "-a", help=f"App to import from ({', '.join(VALID_APP_TYPES)}) - Note: opencode prompt = rules"),
336336
level: str = typer.Option("user", "--level", "-l", help="Level: user or project"),
337337
project_dir: Optional[Path] = typer.Option(None, "--project-dir", "-d", help="Project directory (for project level)"),
338338
description: Optional[str] = typer.Option(None, "--description", help="Description of the prompt"),
@@ -420,7 +420,7 @@ def import_prompt(
420420
@prompt_app.command("install")
421421
def install_prompt(
422422
name: str = typer.Argument(..., help="Prompt name to install"),
423-
app: str = typer.Option(..., "--app", "-a", help=f"Target app ({', '.join(VALID_APP_TYPES)})"),
423+
app: str = typer.Option(..., "--app", "-a", help=f"Target app ({', '.join(VALID_APP_TYPES)}) - Note: opencode prompt = rules"),
424424
level: str = typer.Option("user", "--level", "-l", help="Level: user or project"),
425425
project_dir: Optional[Path] = typer.Option(None, "--project-dir", "-d", help="Project directory (for project level)"),
426426
):
@@ -459,7 +459,7 @@ def install_prompt(
459459

460460
@prompt_app.command("uninstall")
461461
def uninstall_prompt(
462-
app: str = typer.Option(..., "--app", "-a", help=f"Target app ({', '.join(VALID_APP_TYPES)})"),
462+
app: str = typer.Option(..., "--app", "-a", help=f"Target app ({', '.join(VALID_APP_TYPES)}) - Note: opencode prompt = rules"),
463463
level: str = typer.Option("user", "--level", "-l", help="Level: user or project"),
464464
project_dir: Optional[Path] = typer.Option(None, "--project-dir", "-d", help="Project directory (for project level)"),
465465
force: bool = typer.Option(False, "--force", "-f", help="Skip confirmation"),

code_assistant_manager/mcp/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
GeminiMCPClient,
1818
IflowMCPClient,
1919
NeovateMCPClient,
20+
OpenCodeMCPClient,
2021
QoderCLIMCPClient,
2122
QwenMCPClient,
2223
ZedMCPClient,
@@ -40,4 +41,5 @@
4041
"ZedMCPClient",
4142
"QoderCLIMCPClient",
4243
"NeovateMCPClient",
44+
"OpenCodeMCPClient",
4345
]

code_assistant_manager/mcp/clients.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from .gemini import GeminiMCPClient
1111
from .iflow import IflowMCPClient
1212
from .neovate import NeovateMCPClient
13+
from .opencode import OpenCodeMCPClient
1314
from .qodercli import QoderCLIMCPClient
1415
from .qwen import QwenMCPClient
1516
from .zed import ZedMCPClient
@@ -25,6 +26,7 @@
2526
"GeminiMCPClient",
2627
"IflowMCPClient",
2728
"NeovateMCPClient",
29+
"OpenCodeMCPClient",
2830
"QoderCLIMCPClient",
2931
"QwenMCPClient",
3032
"ZedMCPClient",

code_assistant_manager/mcp/manager.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ def _initialize_clients(
2929
GeminiMCPClient,
3030
IflowMCPClient,
3131
NeovateMCPClient,
32+
OpenCodeMCPClient,
3233
QoderCLIMCPClient,
3334
QwenMCPClient,
3435
ZedMCPClient,
@@ -48,6 +49,7 @@ def _initialize_clients(
4849
"neovate": NeovateMCPClient(),
4950
"crush": CrushMCPClient(),
5051
"cursor-agent": CursorAgentMCPClient(),
52+
"opencode": OpenCodeMCPClient(),
5153
}
5254

5355
def get_client(self, tool_name: str):

0 commit comments

Comments
 (0)