Coverage for agentos/cli.py: 0%

187 statements  

« 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. 

3 

4v1.14.5: Full-featured CLI for init, run, deploy, list, and config management. 

5""" 

6 

7import argparse 

8import asyncio 

9import json 

10import logging 

11import os 

12import sys 

13from pathlib import Path 

14from typing import Optional 

15 

16logger = logging.getLogger(__name__) 

17 

18 

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) 

25 

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") 

33 

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") 

40 

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") 

46 

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") 

50 

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") 

57 

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") 

64 

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") 

70 

71 # ---- version ---- 

72 sub.add_parser("version", help="Show version") 

73 

74 args = parser.parse_args() 

75 handler = CLIHandler() 

76 

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() 

93 

94 

95class CLIHandler: 

96 def cmd_init(self, args): 

97 target = Path(args.dir).resolve() / args.name 

98 target.mkdir(parents=True, exist_ok=True) 

99 

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 } 

153 

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) 

158 

159 print(f"✓ Created {args.template} project '{args.name}' at {target}") 

160 print(f" cd {target} && agentos run agent.yaml -p 'Hello!'") 

161 

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) 

167 

168 try: 

169 from agentos import Agent 

170 import yaml 

171 

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 

182 

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) 

191 

192 except Exception as e: 

193 print(f"Error: {e}", file=sys.stderr) 

194 sys.exit(1) 

195 

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) 

201 

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)") 

211 

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() 

217 

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'.") 

231 

232 async def cmd_marketplace(self, args): 

233 from agentos.marketplace import MarketplaceManager, MarketSearchQuery 

234 manager = MarketplaceManager() 

235 

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}") 

250 

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" 

255 

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}") 

275 

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...") 

296 

297 def cmd_version(self): 

298 from agentos import __version__ 

299 print(f"AgentOS v{__version__}") 

300 

301 

302if __name__ == "__main__": 

303 main()