RouteKitAI 0.1.0__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 (64) hide show
  1. routekitai/__init__.py +53 -0
  2. routekitai/cli/__init__.py +18 -0
  3. routekitai/cli/main.py +40 -0
  4. routekitai/cli/replay.py +80 -0
  5. routekitai/cli/run.py +95 -0
  6. routekitai/cli/serve.py +966 -0
  7. routekitai/cli/test_agent.py +178 -0
  8. routekitai/cli/trace.py +209 -0
  9. routekitai/cli/trace_analyze.py +120 -0
  10. routekitai/cli/trace_search.py +126 -0
  11. routekitai/core/__init__.py +58 -0
  12. routekitai/core/agent.py +325 -0
  13. routekitai/core/errors.py +49 -0
  14. routekitai/core/hooks.py +174 -0
  15. routekitai/core/memory.py +54 -0
  16. routekitai/core/message.py +132 -0
  17. routekitai/core/model.py +91 -0
  18. routekitai/core/policies.py +373 -0
  19. routekitai/core/policy.py +85 -0
  20. routekitai/core/policy_adapter.py +133 -0
  21. routekitai/core/runtime.py +1403 -0
  22. routekitai/core/tool.py +148 -0
  23. routekitai/core/tools.py +180 -0
  24. routekitai/evals/__init__.py +13 -0
  25. routekitai/evals/dataset.py +75 -0
  26. routekitai/evals/metrics.py +101 -0
  27. routekitai/evals/runner.py +184 -0
  28. routekitai/graphs/__init__.py +12 -0
  29. routekitai/graphs/executors.py +457 -0
  30. routekitai/graphs/graph.py +164 -0
  31. routekitai/memory/__init__.py +13 -0
  32. routekitai/memory/episodic.py +242 -0
  33. routekitai/memory/kv.py +34 -0
  34. routekitai/memory/retrieval.py +192 -0
  35. routekitai/memory/vector.py +700 -0
  36. routekitai/memory/working.py +66 -0
  37. routekitai/message.py +29 -0
  38. routekitai/model.py +48 -0
  39. routekitai/observability/__init__.py +21 -0
  40. routekitai/observability/analyzer.py +314 -0
  41. routekitai/observability/exporters/__init__.py +10 -0
  42. routekitai/observability/exporters/base.py +30 -0
  43. routekitai/observability/exporters/jsonl.py +81 -0
  44. routekitai/observability/exporters/otel.py +119 -0
  45. routekitai/observability/spans.py +111 -0
  46. routekitai/observability/streaming.py +117 -0
  47. routekitai/observability/trace.py +144 -0
  48. routekitai/providers/__init__.py +9 -0
  49. routekitai/providers/anthropic.py +227 -0
  50. routekitai/providers/azure_openai.py +243 -0
  51. routekitai/providers/local.py +196 -0
  52. routekitai/providers/openai.py +321 -0
  53. routekitai/py.typed +0 -0
  54. routekitai/sandbox/__init__.py +12 -0
  55. routekitai/sandbox/filesystem.py +131 -0
  56. routekitai/sandbox/network.py +142 -0
  57. routekitai/sandbox/permissions.py +70 -0
  58. routekitai/tool.py +33 -0
  59. routekitai-0.1.0.dist-info/METADATA +328 -0
  60. routekitai-0.1.0.dist-info/RECORD +64 -0
  61. routekitai-0.1.0.dist-info/WHEEL +5 -0
  62. routekitai-0.1.0.dist-info/entry_points.txt +2 -0
  63. routekitai-0.1.0.dist-info/licenses/LICENSE +21 -0
  64. routekitai-0.1.0.dist-info/top_level.txt +1 -0
routekitai/__init__.py ADDED
@@ -0,0 +1,53 @@
1
+ """RouteKitAI: An agent development + orchestration framework."""
2
+
3
+ __version__ = "0.1.0"
4
+
5
+ # Import hooks first to ensure ToolFilter is defined before Agent
6
+ from routekitai.core import (
7
+ Agent,
8
+ Message,
9
+ MessageRole,
10
+ Model,
11
+ ModelError,
12
+ ModelResponse,
13
+ PolicyError,
14
+ RouteKitError,
15
+ RunResult,
16
+ Runtime,
17
+ StreamEvent,
18
+ Tool,
19
+ ToolCall,
20
+ ToolError,
21
+ Usage,
22
+ )
23
+ from routekitai.core import (
24
+ RuntimeError as RouteKitRuntimeError,
25
+ )
26
+ from routekitai.core.hooks import ToolFilter
27
+ from routekitai.core.policies import SupervisorPolicy
28
+
29
+ # Rebuild models to resolve forward references
30
+ # Runtime needs Agent, Agent needs ToolFilter, SupervisorPolicy needs Agent
31
+ Agent.model_rebuild()
32
+ Runtime.model_rebuild()
33
+ SupervisorPolicy.model_rebuild()
34
+
35
+ __all__ = [
36
+ "Agent",
37
+ "Message",
38
+ "MessageRole",
39
+ "Model",
40
+ "ModelResponse",
41
+ "RouteKitError",
42
+ "ModelError",
43
+ "ToolError",
44
+ "PolicyError",
45
+ "RouteKitRuntimeError",
46
+ "RunResult",
47
+ "Runtime",
48
+ "StreamEvent",
49
+ "Tool",
50
+ "ToolCall",
51
+ "ToolFilter",
52
+ "Usage",
53
+ ]
@@ -0,0 +1,18 @@
1
+ """CLI tools for RouteKit."""
2
+
3
+ # TODO: Implement CLI commands
4
+ try:
5
+ from routekitai.cli.replay import replay_command
6
+ from routekitai.cli.run import run as run_command
7
+ from routekitai.cli.test_agent import test_command
8
+ from routekitai.cli.trace import trace_command
9
+
10
+ __all__ = [
11
+ "run_command",
12
+ "trace_command",
13
+ "replay_command",
14
+ "test_command",
15
+ ]
16
+ except ImportError:
17
+ # Typer not installed, CLI not available
18
+ __all__ = []
routekitai/cli/main.py ADDED
@@ -0,0 +1,40 @@
1
+ """Main CLI entry point for RouteKit."""
2
+
3
+ import sys
4
+
5
+ try:
6
+ import typer
7
+ except ImportError:
8
+ print("Error: Typer and Rich are required for CLI. Install with: pip install 'routekit[dev]'")
9
+ sys.exit(1)
10
+
11
+ from routekitai.cli.replay import replay_command
12
+ from routekitai.cli.run import run as run_command
13
+ from routekitai.cli.serve import serve_command
14
+ from routekitai.cli.test_agent import test_command
15
+ from routekitai.cli.trace import trace_command
16
+ from routekitai.cli.trace_analyze import analyze_command
17
+ from routekitai.cli.trace_search import search_command
18
+
19
+ app = typer.Typer(
20
+ name="routekit",
21
+ help="RouteKit: An agent development + orchestration framework",
22
+ add_completion=False,
23
+ )
24
+
25
+ app.command(name="run")(run_command)
26
+ app.command(name="trace")(trace_command)
27
+ app.command(name="trace-analyze")(analyze_command)
28
+ app.command(name="trace-search")(search_command)
29
+ app.command(name="serve")(serve_command)
30
+ app.command(name="replay")(replay_command)
31
+ app.command(name="test-agent")(test_command)
32
+
33
+
34
+ def main() -> None:
35
+ """Main CLI entry point."""
36
+ app()
37
+
38
+
39
+ if __name__ == "__main__":
40
+ main()
@@ -0,0 +1,80 @@
1
+ """CLI command for replaying traces."""
2
+
3
+ import asyncio
4
+ from pathlib import Path
5
+
6
+ try:
7
+ import typer
8
+ from rich.console import Console
9
+ except ImportError as e:
10
+ raise ImportError("CLI dependencies not installed. Install with: pip install typer rich") from e
11
+
12
+ from routekitai.core.runtime import Runtime
13
+ from routekitai.observability.exporters.jsonl import JSONLExporter
14
+
15
+ app = typer.Typer(name="replay", help="Replay agent execution traces")
16
+ console = Console()
17
+
18
+
19
+ def replay_command(
20
+ trace_id: str = typer.Argument(..., help="Trace ID to replay"),
21
+ agent_name: str = typer.Option(..., "--agent", "-a", help="Agent name to use for replay"),
22
+ trace_dir: str | None = typer.Option(
23
+ None, "--trace-dir", "-t", help="Directory containing trace files"
24
+ ),
25
+ verify: bool = typer.Option(
26
+ True, "--verify/--no-verify", help="Verify outputs match original trace"
27
+ ),
28
+ ) -> None:
29
+ """Replay a trace with deterministic execution.
30
+
31
+ Examples:
32
+ routkitai replay abc123 --agent my_agent
33
+ routkitai replay abc123 --agent my_agent --no-verify
34
+ routkitai replay abc123 --agent my_agent --trace-dir ./custom_traces
35
+ """
36
+
37
+ async def _replay() -> None:
38
+ # Determine trace directory
39
+ if trace_dir is None:
40
+ trace_dir_path = Path(".routekit") / "traces"
41
+ else:
42
+ trace_dir_path = Path(trace_dir)
43
+
44
+ if not trace_dir_path.exists():
45
+ console.print(f"[red]Error: Trace directory not found: {trace_dir_path}[/red]")
46
+ raise typer.Exit(1)
47
+
48
+ console.print(f"[green]Replaying trace: {trace_id}[/green]")
49
+ console.print(f"[dim]Agent: {agent_name}[/dim]")
50
+ console.print(f"[dim]Trace dir: {trace_dir_path}[/dim]\n")
51
+
52
+ # Create runtime and replay
53
+ runtime = Runtime(trace_dir=trace_dir_path)
54
+ result = await runtime.replay(trace_id, agent_name, verify_output=verify)
55
+
56
+ console.print("\n[bold]Replay completed[/bold]")
57
+ console.print(f"[green]Output:[/green] {result.output.content}")
58
+ console.print(f"[dim]Trace ID: {result.trace_id}[/dim]")
59
+
60
+ if verify:
61
+ # Load original trace for comparison
62
+ exporter = JSONLExporter(output_dir=trace_dir_path)
63
+ original_trace = await exporter.load(trace_id)
64
+ if original_trace:
65
+ original_completed = original_trace.get_events_by_type("run_completed")
66
+ if original_completed:
67
+ original_result = original_completed[0].data.get("result", {})
68
+ original_output = original_result.get("output", {}).get("content", "")
69
+ if original_output != result.output.content:
70
+ console.print("\n[yellow]⚠ Warning: Output mismatch![/yellow]")
71
+ console.print(f"[dim] Original: {original_output}[/dim]")
72
+ console.print(f"[dim] Replay: {result.output.content}[/dim]")
73
+ else:
74
+ console.print("\n[green]✓ Output matches original trace[/green]")
75
+
76
+ asyncio.run(_replay())
77
+
78
+
79
+ if __name__ == "__main__" and app is not None:
80
+ app()
routekitai/cli/run.py ADDED
@@ -0,0 +1,95 @@
1
+ """CLI command for running agents."""
2
+
3
+ import asyncio
4
+ from pathlib import Path
5
+
6
+ try:
7
+ import typer
8
+ from rich.console import Console
9
+ from rich.markdown import Markdown
10
+ except ImportError as e:
11
+ raise ImportError("CLI dependencies not installed. Install with: pip install typer rich") from e
12
+
13
+ app = typer.Typer(name="run", help="Run an agent with a prompt or script")
14
+ console = Console()
15
+
16
+
17
+ async def _run_agent_from_script(script_path: Path) -> None:
18
+ """Run an agent from a Python script.
19
+
20
+ Args:
21
+ script_path: Path to Python script
22
+ """
23
+ import importlib.util
24
+ import sys
25
+
26
+ spec = importlib.util.spec_from_file_location("agent_script", script_path)
27
+ if spec is None or spec.loader is None:
28
+ console.print(f"[red]Error: Could not load script from {script_path}[/red]")
29
+ return
30
+
31
+ module = importlib.util.module_from_spec(spec)
32
+ sys.modules["agent_script"] = module
33
+ spec.loader.exec_module(module)
34
+
35
+ # Look for a main() function or agent definition
36
+ if hasattr(module, "main"):
37
+ if asyncio.iscoroutinefunction(module.main):
38
+ await module.main()
39
+ else:
40
+ module.main()
41
+ else:
42
+ console.print("[yellow]Warning: No main() function found in script[/yellow]")
43
+
44
+
45
+ @app.command()
46
+ def run(
47
+ prompt_or_script: str = typer.Argument(..., help="Prompt string or path to Python script"),
48
+ agent_name: str = typer.Option("default", "--agent", "-a", help="Agent name (if using script)"),
49
+ trace_dir: str | None = typer.Option(
50
+ None, "--trace-dir", "-t", help="Directory for trace files"
51
+ ),
52
+ output_format: str = typer.Option("text", "--format", "-f", help="Output format: text, json"),
53
+ ) -> None:
54
+ """Run an agent with a prompt or execute a Python script.
55
+
56
+ Examples:
57
+ routkitai run "What is 2+2?"
58
+ routkitai run agent_script.py
59
+ routkitai run "Hello" --agent my_agent --format json
60
+ """
61
+
62
+ script_path = Path(prompt_or_script)
63
+ is_script = script_path.exists() and script_path.suffix == ".py"
64
+
65
+ if is_script:
66
+ # Run as script
67
+ console.print(f"[green]Running script: {script_path}[/green]")
68
+ asyncio.run(_run_agent_from_script(script_path))
69
+ else:
70
+ # Run as prompt (requires agent to be registered)
71
+ console.print("[yellow]Note: Direct prompt execution requires a registered agent.[/yellow]")
72
+ console.print("[yellow]Consider using a script or the Python API instead.[/yellow]")
73
+ console.print(f"\n[dim]Prompt: {prompt_or_script}[/dim]")
74
+ console.print("[dim]Agent: {agent_name}[/dim]")
75
+ console.print("\n[blue]Example Python usage:[/blue]")
76
+ console.print(
77
+ Markdown(
78
+ f"""
79
+ ```python
80
+ from routkitai import Agent, Runtime
81
+ from routekitai.providers.local import FakeModel
82
+
83
+ model = FakeModel(name="test")
84
+ agent = Agent(name="my_agent", model=model)
85
+
86
+ result = await agent.run("{prompt_or_script}")
87
+ print(result.output.content)
88
+ ```
89
+ """
90
+ )
91
+ )
92
+
93
+
94
+ if __name__ == "__main__" and app is not None:
95
+ app()