Coverage for agentos/cli.py: 0%
187 statements
« prev ^ index » next coverage.py v7.14.3, created at 2026-07-02 09:59 +0800
« prev ^ index » next coverage.py v7.14.3, created at 2026-07-02 09:59 +0800
1"""
2AgentOS CLI — Command-line interface for agent management.
4v1.14.5: Full-featured CLI for init, run, deploy, list, and config management.
5"""
7import argparse
8import asyncio
9import json
10import logging
11import os
12import sys
13from pathlib import Path
14from typing import Optional
16logger = logging.getLogger(__name__)
19def main():
20 parser = argparse.ArgumentParser(
21 prog="agentos",
22 description="AgentOS — Production Multi-Agent Framework CLI",
23 )
24 sub = parser.add_subparsers(dest="command", required=True)
26 # ---- init ----
27 p_init = sub.add_parser("init", help="Initialize a new agent project")
28 p_init.add_argument("name", help="Project name")
29 p_init.add_argument("--template", "-t", default="default",
30 choices=["default", "chat", "research", "coding", "pipeline"],
31 help="Project template")
32 p_init.add_argument("--dir", "-d", default=".", help="Target directory")
34 # ---- run ----
35 p_run = sub.add_parser("run", help="Run an agent or workflow")
36 p_run.add_argument("target", help="Agent config file (.yaml) or workflow file")
37 p_run.add_argument("--prompt", "-p", help="Prompt to send to agent")
38 p_run.add_argument("--stream", "-s", action="store_true", help="Stream output")
39 p_run.add_argument("--model", "-m", help="Override model")
41 # ---- deploy ----
42 p_deploy = sub.add_parser("deploy", help="Deploy agent to cluster")
43 p_deploy.add_argument("config", help="Agent config file")
44 p_deploy.add_argument("--workers", "-w", type=int, default=1, help="Number of workers")
45 p_deploy.add_argument("--ray", action="store_true", help="Deploy via Ray cluster")
47 # ---- list ----
48 p_list = sub.add_parser("list", help="List running agents")
49 p_list.add_argument("--format", "-f", choices=["table", "json"], default="table")
51 # ---- marketplace ----
52 p_market = sub.add_parser("marketplace", help="Agent marketplace commands")
53 m_sub = p_market.add_subparsers(dest="market_cmd", required=True)
54 m_sub.add_parser("search", help="Search marketplace").add_argument("query", nargs="?", default="")
55 m_sub.add_parser("install", help="Install a template").add_argument("template_id")
56 m_sub.add_parser("featured", help="Show featured templates")
58 # ---- config ----
59 p_config = sub.add_parser("config", help="Manage agent configuration")
60 c_sub = p_config.add_subparsers(dest="config_cmd", required=True)
61 c_sub.add_parser("show", help="Show current config")
62 c_sub.add_parser("set", help="Set a config value").add_argument("key")
63 c_sub.add_parser("list-models", help="List available models")
65 # ---- serve (API) ----
66 p_serve = sub.add_parser("serve", help="Start AgentOS API server")
67 p_serve.add_argument("--host", default="0.0.0.0", help="Host to bind")
68 p_serve.add_argument("--port", "-p", type=int, default=8000, help="Port")
69 p_serve.add_argument("--reload", action="store_true", help="Auto-reload on changes")
71 # ---- version ----
72 sub.add_parser("version", help="Show version")
74 args = parser.parse_args()
75 handler = CLIHandler()
77 if args.command == "init":
78 handler.cmd_init(args)
79 elif args.command == "run":
80 asyncio.run(handler.cmd_run(args))
81 elif args.command == "deploy":
82 asyncio.run(handler.cmd_deploy(args))
83 elif args.command == "list":
84 asyncio.run(handler.cmd_list(args))
85 elif args.command == "marketplace":
86 asyncio.run(handler.cmd_marketplace(args))
87 elif args.command == "config":
88 handler.cmd_config(args)
89 elif args.command == "serve":
90 handler.cmd_serve(args)
91 elif args.command == "version":
92 handler.cmd_version()
95class CLIHandler:
96 def cmd_init(self, args):
97 target = Path(args.dir).resolve() / args.name
98 target.mkdir(parents=True, exist_ok=True)
100 templates = {
101 "default": {
102 "agent.yaml": "name: {name}\ntype: default\nmodel: gpt-4o\n",
103 "main.py": (
104 "from agentos import Agent, OpenAIModel\n\n"
105 "agent = Agent(\n"
106 " model=OpenAIModel('gpt-4o'),\n"
107 " system_prompt='You are a helpful assistant.',\n"
108 ")\n\n"
109 "async def main():\n"
110 " result = await agent.run('Hello!')\n"
111 " print(result)\n\n"
112 "if __name__ == '__main__':\n"
113 " import asyncio\n"
114 " asyncio.run(main())\n"
115 ),
116 },
117 "chat": {
118 "agent.yaml": "name: {name}\ntype: chat\nmodel: gpt-4o\nmemory: enabled\n",
119 "main.py": (
120 "from agentos import Agent, OpenAIModel\n"
121 "from agentos.memory.consolidation import ReflectionEngine\n\n"
122 "agent = Agent(\n"
123 " model=OpenAIModel('gpt-4o'),\n"
124 " memory=ReflectionEngine(),\n"
125 ")\n"
126 ),
127 },
128 "research": {
129 "agent.yaml": "name: {name}\ntype: research\nmodel: gpt-4o\ntools: [web_search, arxiv]\n",
130 "main.py": (
131 "from agentos import Agent, Swarm\n\n"
132 "researcher = Agent(model='gpt-4o', name='Researcher')\n"
133 "writer = Agent(model='gpt-4o', name='Writer')\n"
134 "swarm = Swarm(agents=[researcher, writer])\n"
135 ),
136 },
137 "coding": {
138 "agent.yaml": "name: {name}\ntype: coding\nmodel: claude-3-opus\n",
139 },
140 "pipeline": {
141 "agent.yaml": "name: {name}\ntype: pipeline\nworkflow: workflow.yaml\n",
142 "workflow.yaml": (
143 "name: {name}-pipeline\n"
144 "version: '1.0'\n"
145 "steps:\n"
146 " - id: process\n"
147 " type: task\n"
148 " agent: default\n"
149 " task: 'Process input'\n"
150 ),
151 },
152 }
154 tmpl = templates.get(args.template, templates["default"])
155 for filename, content in tmpl.items():
156 formatted = content.format(name=args.name)
157 (target / filename).write_text(formatted)
159 print(f"✓ Created {args.template} project '{args.name}' at {target}")
160 print(f" cd {target} && agentos run agent.yaml -p 'Hello!'")
162 async def cmd_run(self, args):
163 target = Path(args.target)
164 if not target.exists():
165 print(f"Error: '{target}' not found")
166 sys.exit(1)
168 try:
169 from agentos import Agent
170 import yaml
172 if target.suffix in (".yaml", ".yml"):
173 config = yaml.safe_load(target.read_text())
174 agent = Agent.from_config(config)
175 else:
176 # Workflow file
177 from agentos.workflow import WorkflowParser, WorkflowEngine
178 wf = WorkflowParser.parse_file(target)
179 ctx = await WorkflowEngine().execute(wf)
180 print(json.dumps(ctx.variables, indent=2, default=str))
181 return
183 prompt = args.prompt or "Tell me about yourself."
184 if args.stream:
185 async for chunk in agent.stream(prompt):
186 print(chunk, end="", flush=True)
187 print()
188 else:
189 result = await agent.run(prompt)
190 print(result)
192 except Exception as e:
193 print(f"Error: {e}", file=sys.stderr)
194 sys.exit(1)
196 async def cmd_deploy(self, args):
197 config_path = Path(args.config)
198 if not config_path.exists():
199 print(f"Error: config '{config_path}' not found")
200 sys.exit(1)
202 if args.ray:
203 from agentos.orchestration.distributed import RayAgentActor, PlacementStrategy
204 import ray
205 ray.init()
206 actor = RayAgentActor.options(num_cpus=args.workers).remote(config_path)
207 print(f"✓ Deployed {args.workers} workers to Ray cluster")
208 else:
209 print(f"✓ Deploying {args.workers} workers via local mode")
210 print(" (Install 'ray' for distributed deployment)")
212 async def cmd_list(self, args):
213 try:
214 from agentos.protocols.registry import AgentRegistry
215 registry = AgentRegistry()
216 agents = await registry.list_agents()
218 if args.format == "json":
219 print(json.dumps([a.__dict__ for a in agents], indent=2, default=str))
220 else:
221 if not agents:
222 print("No agents registered.")
223 return
224 print(f"{'ID':20} {'Capabilities':30} {'Status'}")
225 print("-" * 65)
226 for a in agents:
227 caps = ", ".join(a.capabilities[:3])
228 print(f"{a.agent_id:20} {caps:30} {'online' if a.healthy else 'offline'}")
229 except Exception as e:
230 print("No running agents found. Start an agent first with 'agentos serve' or 'agentos run'.")
232 async def cmd_marketplace(self, args):
233 from agentos.marketplace import MarketplaceManager, MarketSearchQuery
234 manager = MarketplaceManager()
236 if args.market_cmd == "search":
237 results = await manager.search(MarketSearchQuery(keywords=args.query or ""))
238 if not results:
239 print("No templates found.")
240 return
241 for r in results[:10]:
242 print(f" {r.template.name:30} ★{r.template.rating:.1f} {r.template.description[:60]}")
243 elif args.market_cmd == "install":
244 path = await manager.install(args.template_id)
245 print(f"✓ Installed to {path}")
246 elif args.market_cmd == "featured":
247 featured = await manager.get_featured(10)
248 for tpl in featured:
249 print(f" {tpl.name:30} {tpl.downloads:>6} downloads ★{tpl.rating:.1f}")
251 def cmd_config(self, args):
252 config_dir = Path.home() / ".agentos"
253 config_dir.mkdir(exist_ok=True)
254 config_file = config_dir / "config.json"
256 if args.config_cmd == "show":
257 if config_file.exists():
258 print(config_file.read_text())
259 else:
260 print(json.dumps({"model": "gpt-4o", "workspace": str(Path.home() / "agentos")}, indent=2))
261 elif args.config_cmd == "set":
262 key, _, value = args.key.partition("=")
263 if not value:
264 print("Usage: agentos config set KEY=VALUE")
265 return
266 cfg = json.loads(config_file.read_text()) if config_file.exists() else {}
267 cfg[key] = value
268 config_file.write_text(json.dumps(cfg, indent=2))
269 print(f"✓ Set {key}={value}")
270 elif args.config_cmd == "list-models":
271 models = ["gpt-4o", "gpt-4-turbo", "claude-3-opus", "claude-3-sonnet",
272 "gemini-1.5-pro", "llama-3-70b", "mixtral-8x7b"]
273 for m in models:
274 print(f" {m}")
276 def cmd_serve(self, args):
277 print(f"Starting AgentOS API server on http://{args.host}:{args.port}")
278 print("API docs: http://{args.host}:{args.port}/docs")
279 try:
280 from agentos.api.server import serve
281 import uvicorn
282 uvicorn.run("agentos.api.server:app", host=args.host, port=args.port, reload=args.reload)
283 except ImportError:
284 print("Install API dependencies: pip install nexus-agentos[api]")
285 print("Module 'agentos.api.server' not available yet — running stub.")
286 import http.server
287 server = http.server.HTTPServer(
288 (args.host, args.port),
289 lambda *a: None,
290 )
291 print(f" Stub server on {args.host}:{args.port}")
292 try:
293 server.serve_forever()
294 except KeyboardInterrupt:
295 print("\nShutting down...")
297 def cmd_version(self):
298 from agentos import __version__
299 print(f"AgentOS v{__version__}")
302if __name__ == "__main__":
303 main()