plato-sdk-v2 2.7.6__py3-none-any.whl → 2.7.8__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.
- plato/cli/__init__.py +5 -0
- plato/cli/agent.py +1209 -0
- plato/cli/audit_ui.py +316 -0
- plato/cli/chronos.py +817 -0
- plato/cli/main.py +193 -0
- plato/cli/pm.py +1204 -0
- plato/cli/proxy.py +222 -0
- plato/cli/sandbox.py +808 -0
- plato/cli/utils.py +200 -0
- plato/cli/verify.py +690 -0
- plato/cli/world.py +250 -0
- plato/v1/cli/pm.py +4 -1
- plato/v2/__init__.py +2 -0
- plato/v2/models.py +42 -0
- plato/v2/sync/__init__.py +6 -0
- plato/v2/sync/client.py +6 -3
- plato/v2/sync/sandbox.py +1462 -0
- {plato_sdk_v2-2.7.6.dist-info → plato_sdk_v2-2.7.8.dist-info}/METADATA +1 -1
- {plato_sdk_v2-2.7.6.dist-info → plato_sdk_v2-2.7.8.dist-info}/RECORD +21 -9
- {plato_sdk_v2-2.7.6.dist-info → plato_sdk_v2-2.7.8.dist-info}/entry_points.txt +1 -1
- {plato_sdk_v2-2.7.6.dist-info → plato_sdk_v2-2.7.8.dist-info}/WHEEL +0 -0
plato/cli/main.py
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"""Plato CLI - Main entry point."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import platform
|
|
5
|
+
import shutil
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
import typer
|
|
9
|
+
from dotenv import load_dotenv
|
|
10
|
+
|
|
11
|
+
from plato.cli.agent import agent_app
|
|
12
|
+
from plato.cli.chronos import chronos_app
|
|
13
|
+
from plato.cli.pm import pm_app
|
|
14
|
+
from plato.cli.sandbox import sandbox_app
|
|
15
|
+
from plato.cli.utils import console
|
|
16
|
+
from plato.cli.world import world_app
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _find_bundled_cli() -> str | None:
|
|
20
|
+
"""
|
|
21
|
+
Find the Plato Go CLI binary.
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
Path to the CLI binary if found, None otherwise.
|
|
25
|
+
"""
|
|
26
|
+
# Check locations in order of preference
|
|
27
|
+
search_paths = []
|
|
28
|
+
|
|
29
|
+
# 1. Bundled in package (plato-cli) - go up from cli/ to v1/
|
|
30
|
+
binary_name = "plato-cli.exe" if platform.system().lower() == "windows" else "plato-cli"
|
|
31
|
+
package_dir = Path(__file__).resolve().parent.parent # v1/
|
|
32
|
+
bin_dir = package_dir / "bin"
|
|
33
|
+
search_paths.append(bin_dir / binary_name)
|
|
34
|
+
|
|
35
|
+
# 2. plato-client/cli/bin/plato (development location)
|
|
36
|
+
# Navigate from python-sdk/plato/v1/cli/main.py to plato-client/cli/bin/plato
|
|
37
|
+
plato_client_dir = package_dir.parent.parent.parent # Go up to plato-client
|
|
38
|
+
go_binary_name = "plato.exe" if platform.system().lower() == "windows" else "plato"
|
|
39
|
+
search_paths.append(plato_client_dir / "cli" / "bin" / go_binary_name)
|
|
40
|
+
|
|
41
|
+
# 3. Check PATH for 'plato-cli' only (not 'plato' to avoid finding Python entry point)
|
|
42
|
+
which_result = shutil.which(binary_name)
|
|
43
|
+
if which_result:
|
|
44
|
+
search_paths.append(Path(which_result))
|
|
45
|
+
|
|
46
|
+
# Return first found executable that is NOT the Python entry point
|
|
47
|
+
python_entry_point = shutil.which("plato") # This is the Python CLI
|
|
48
|
+
for path in search_paths:
|
|
49
|
+
if path.exists() and os.access(path, os.X_OK):
|
|
50
|
+
# Skip if this is the Python entry point (would cause infinite recursion)
|
|
51
|
+
if python_entry_point and str(path.resolve()) == str(Path(python_entry_point).resolve()):
|
|
52
|
+
continue
|
|
53
|
+
return str(path)
|
|
54
|
+
|
|
55
|
+
return None
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
# Load environment variables
|
|
59
|
+
load_dotenv()
|
|
60
|
+
load_dotenv(dotenv_path=os.path.join(os.path.expanduser("~"), ".env"))
|
|
61
|
+
load_dotenv(dotenv_path=os.path.join(os.path.dirname(__file__), ".env"))
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
# =============================================================================
|
|
65
|
+
# MAIN APP
|
|
66
|
+
# =============================================================================
|
|
67
|
+
|
|
68
|
+
app = typer.Typer(help="[bold blue]Plato CLI[/bold blue] - Manage Plato environments and simulators.")
|
|
69
|
+
|
|
70
|
+
# Register sub-apps
|
|
71
|
+
app.add_typer(sandbox_app, name="sandbox")
|
|
72
|
+
app.add_typer(pm_app, name="pm")
|
|
73
|
+
app.add_typer(agent_app, name="agent")
|
|
74
|
+
app.add_typer(world_app, name="world")
|
|
75
|
+
app.add_typer(chronos_app, name="chronos")
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
# =============================================================================
|
|
79
|
+
# TOP-LEVEL COMMANDS
|
|
80
|
+
# =============================================================================
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@app.command(context_settings={"allow_extra_args": True, "ignore_unknown_options": True})
|
|
84
|
+
def hub(
|
|
85
|
+
ctx: typer.Context,
|
|
86
|
+
):
|
|
87
|
+
"""Launch the Plato Hub CLI (interactive TUI for managing simulators).
|
|
88
|
+
|
|
89
|
+
Opens the Go-based Plato CLI which provides an interactive terminal UI for
|
|
90
|
+
browsing simulators, launching environments, and managing VMs. Any additional
|
|
91
|
+
arguments are passed through to the Go CLI.
|
|
92
|
+
|
|
93
|
+
Common subcommands: 'clone <service>', 'credentials', or no args for interactive mode.
|
|
94
|
+
"""
|
|
95
|
+
# Find the bundled CLI binary
|
|
96
|
+
plato_bin = _find_bundled_cli()
|
|
97
|
+
|
|
98
|
+
if not plato_bin:
|
|
99
|
+
console.print("[red]❌ Plato CLI binary not found in package[/red]")
|
|
100
|
+
console.print("\n[yellow]The bundled CLI binary was not found in this installation.[/yellow]")
|
|
101
|
+
console.print("This indicates an installation issue with the plato-sdk package.")
|
|
102
|
+
console.print("\n[yellow]💡 Try reinstalling the package:[/yellow]")
|
|
103
|
+
console.print(" pip install --upgrade --force-reinstall plato-sdk")
|
|
104
|
+
console.print("\n[dim]If the issue persists, please report it at:[/dim]")
|
|
105
|
+
console.print("[dim]https://github.com/plato-app/plato-client/issues[/dim]")
|
|
106
|
+
raise typer.Exit(1)
|
|
107
|
+
|
|
108
|
+
# Get any additional arguments passed after 'hub'
|
|
109
|
+
args = ctx.args if hasattr(ctx, "args") else []
|
|
110
|
+
|
|
111
|
+
try:
|
|
112
|
+
# Launch the Go CLI, passing through all arguments
|
|
113
|
+
# Use execvp to replace the current process so the TUI works properly
|
|
114
|
+
os.execvp(plato_bin, [plato_bin] + args)
|
|
115
|
+
except Exception as e:
|
|
116
|
+
console.print(f"[red]❌ Failed to launch Plato Hub: {e}[/red]")
|
|
117
|
+
raise typer.Exit(1) from e
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
@app.command()
|
|
121
|
+
def clone(
|
|
122
|
+
service: str = typer.Argument(..., help="Service name to clone (e.g., espocrm)"),
|
|
123
|
+
):
|
|
124
|
+
"""Clone a service repository from Plato Hub (Gitea).
|
|
125
|
+
|
|
126
|
+
Clones the simulator source code to your local machine for development or review.
|
|
127
|
+
|
|
128
|
+
Arguments:
|
|
129
|
+
service: Service name to clone (e.g., 'espocrm', 'gitea')
|
|
130
|
+
"""
|
|
131
|
+
plato_bin = _find_bundled_cli()
|
|
132
|
+
if not plato_bin:
|
|
133
|
+
console.print("[red]❌ Plato CLI binary not found[/red]")
|
|
134
|
+
console.print("[yellow]Cannot clone without the Go CLI binary.[/yellow]")
|
|
135
|
+
raise typer.Exit(1)
|
|
136
|
+
|
|
137
|
+
try:
|
|
138
|
+
os.execvp(plato_bin, [plato_bin, "clone", service])
|
|
139
|
+
except Exception as e:
|
|
140
|
+
console.print(f"[red]❌ Failed to clone: {e}[/red]")
|
|
141
|
+
raise typer.Exit(1) from e
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
@app.command()
|
|
145
|
+
def credentials():
|
|
146
|
+
"""Display your Plato Hub (Gitea) credentials.
|
|
147
|
+
|
|
148
|
+
Shows the username and password needed to access Plato's Gitea repositories
|
|
149
|
+
for cloning and pushing simulator code.
|
|
150
|
+
"""
|
|
151
|
+
plato_bin = _find_bundled_cli()
|
|
152
|
+
if not plato_bin:
|
|
153
|
+
console.print("[red]❌ Plato CLI binary not found[/red]")
|
|
154
|
+
console.print("[yellow]Cannot show credentials without the Go CLI binary.[/yellow]")
|
|
155
|
+
raise typer.Exit(1)
|
|
156
|
+
|
|
157
|
+
try:
|
|
158
|
+
os.execvp(plato_bin, [plato_bin, "credentials"])
|
|
159
|
+
except Exception as e:
|
|
160
|
+
console.print(f"[red]❌ Failed to get credentials: {e}[/red]")
|
|
161
|
+
raise typer.Exit(1) from e
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
@app.command(
|
|
165
|
+
context_settings={"allow_extra_args": True, "ignore_unknown_options": True},
|
|
166
|
+
help="Explore simulation APIs (list, info, endpoints, spec)",
|
|
167
|
+
)
|
|
168
|
+
def sims(ctx: typer.Context):
|
|
169
|
+
"""Explore simulation APIs - list sims, view endpoints, get OpenAPI specs."""
|
|
170
|
+
from plato.sims import cli as sims_cli
|
|
171
|
+
|
|
172
|
+
# Pass all arguments to the sims CLI
|
|
173
|
+
sims_cli.main(ctx.args)
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
# =============================================================================
|
|
177
|
+
# ENTRY POINT
|
|
178
|
+
# =============================================================================
|
|
179
|
+
|
|
180
|
+
# force bump to v36
|
|
181
|
+
# TEST/MOCK: This comment marks test-related code. Used for verification in release workflow.
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def main():
|
|
185
|
+
"""Main entry point for the Plato CLI."""
|
|
186
|
+
app()
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
# Backward compatibility
|
|
190
|
+
cli = main
|
|
191
|
+
|
|
192
|
+
if __name__ == "__main__":
|
|
193
|
+
main()
|