File size: 6,070 Bytes
9abace2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
"""

CLI Main Entry Point

Part of SOVEREIGN PYTHON LLM ENGINE



Command-line interface for running agents, tools, and MCP server.

"""

import asyncio
import sys
from pathlib import Path
import argparse

# Sovereign node key gate — must pass before model routing activates
from sovereign.node_key import require_node_key


def main():
    """Main CLI entry point"""
    require_node_key()
    parser = argparse.ArgumentParser(
        prog="sovereign-engine",
        description="Sovereign Python LLM Engine - Provider-neutral agent runtime"
    )

    subparsers = parser.add_subparsers(dest="command", help="Commands")

    # Agent command
    agent_parser = subparsers.add_parser("agent", help="Run ReAct or MCTS agent")
    agent_parser.add_argument("--type", choices=["react", "mcts"], default="react", help="Agent type")
    agent_parser.add_argument("--task", required=True, help="Task description")
    agent_parser.add_argument("--model", default="anthropic.claude-3-5-sonnet-20241022-v2:0", help="Model ID")
    agent_parser.add_argument("--max-steps", type=int, default=10, help="Max steps")

    # Tool command
    tool_parser = subparsers.add_parser("tool", help="Execute a tool")
    tool_parser.add_argument("--name", required=True, help="Tool name")
    tool_parser.add_argument("--args", help="Tool arguments (JSON)")

    # MCP server command
    mcp_parser = subparsers.add_parser("mcp", help="Run MCP server")
    mcp_parser.add_argument("--transport", choices=["stdio", "http", "ws"], default="stdio", help="Transport")
    mcp_parser.add_argument("--host", default="127.0.0.1", help="Host (HTTP/WS only)")
    mcp_parser.add_argument("--port", type=int, default=8000, help="Port (HTTP/WS only)")

    # RAG command
    rag_parser = subparsers.add_parser("rag", help="Run RAG query")
    rag_parser.add_argument("--query", required=True, help="Query string")
    rag_parser.add_argument("--top-k", type=int, default=5, help="Top K results")

    # Version command
    version_parser = subparsers.add_parser("version", help="Show version")

    args = parser.parse_args()

    if args.command == "agent":
        asyncio.run(run_agent(args))
    elif args.command == "tool":
        asyncio.run(run_tool(args))
    elif args.command == "mcp":
        asyncio.run(run_mcp(args))
    elif args.command == "rag":
        asyncio.run(run_rag(args))
    elif args.command == "version":
        print("Sovereign Engine v1.0.0")
    else:
        parser.print_help()


async def run_agent(args):
    """Run agent"""
    from ..agents.react import ReActAgent, ReActConfig
    from ..tools.registry import ToolRegistry
    from ..tools.approval import ApprovalEngine
    from ..core.evidence import WORMLedger
    from ..runtime.providers.bedrock import BedrockProvider
    from ..models.entities import Task

    print(f"Running {args.type} agent...")
    print(f"Task: {args.task}")
    print(f"Model: {args.model}")

    # Initialize components
    registry = ToolRegistry()
    approval = ApprovalEngine()
    ledger = WORMLedger(Path("evidence.worm"))

    # Initialize model
    model = BedrockProvider(region="us-east-1")

    # Create agent
    if args.type == "react":
        config = ReActConfig(max_steps=args.max_steps)
        agent = ReActAgent(model, registry, approval, ledger, config)

        # Run task
        task = Task(task_id="cli-task", description=args.task)
        result = await agent.run(task)

        print("\n=== RESULT ===")
        print(result)
    else:
        print("MCTS agent not yet wired to CLI")


async def run_tool(args):
    """Execute tool"""
    import json
    from ..tools.registry import ToolRegistry

    print(f"Executing tool: {args.name}")

    registry = ToolRegistry()
    tool = registry.get(args.name)

    if not tool:
        print(f"Error: Tool not found: {args.name}")
        sys.exit(1)

    # Parse arguments
    if args.args:
        tool_args = json.loads(args.args)
    else:
        tool_args = {}

    # Execute
    result = await tool.handler(**tool_args)

    print("\n=== RESULT ===")
    print(result)


async def run_mcp(args):
    """Run MCP server"""
    from ..mcp.server import MCPServer
    from ..mcp.transport import StdioTransport, HTTPTransport, WebSocketTransport
    from ..tools.registry import ToolRegistry
    from ..tools.approval import ApprovalEngine

    print(f"Starting MCP server ({args.transport} transport)...")

    # Initialize components
    registry = ToolRegistry()
    approval = ApprovalEngine()

    # Create server
    server = MCPServer(registry, approval)

    # Select transport
    if args.transport == "stdio":
        transport = StdioTransport(server)
        await transport.run()
    elif args.transport == "http":
        transport = HTTPTransport(server, args.host, args.port)
        await transport.run()
    elif args.transport == "ws":
        transport = WebSocketTransport(server, args.host, args.port)
        await transport.run()


async def run_rag(args):
    """Run RAG query"""
    from ..retrieval.rag import RAGPipeline, RAGConfig
    from ..retrieval.parallel import ParallelRetriever, ParallelRetrieverConfig
    from ..tools.embeddings.encode import EmbeddingsTool
    from ..runtime.providers.bedrock import BedrockProvider

    print(f"RAG Query: {args.query}")

    # Initialize components
    model = BedrockProvider()
    embeddings = EmbeddingsTool(provider="openai")

    # Create retriever (would need vector store)
    retriever_config = ParallelRetrieverConfig()
    retriever = ParallelRetriever({}, config=retriever_config)

    # Create RAG pipeline
    rag_config = RAGConfig(top_k=args.top_k)
    pipeline = RAGPipeline(model, retriever, embeddings, config=rag_config)

    # Query
    result = await pipeline.query(args.query)

    print("\n=== ANSWER ===")
    print(result)


if __name__ == "__main__":
    main()