meshagent-cli 0.36.3__tar.gz → 0.37.0__tar.gz
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.
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/PKG-INFO +15 -13
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/agent.py +0 -1
- meshagent_cli-0.37.0/meshagent/cli/agent_package_cli.py +225 -0
- meshagent_cli-0.37.0/meshagent/cli/agent_package_cli_test.py +421 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/async_typer.py +69 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/async_typer_test.py +29 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/chatbot.py +843 -617
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/cli.py +5 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/cli_mcp.py +21 -11
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/codex.py +0 -18
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/database.py +205 -35
- meshagent_cli-0.37.0/meshagent/cli/database_test.py +22 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/helper.py +145 -66
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/helper_test.py +30 -30
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/host.py +2 -2
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/image.py +203 -429
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/image_test.py +186 -496
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/mailbot.py +224 -139
- meshagent_cli-0.37.0/meshagent/cli/mailbot_test.py +80 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/multi.py +2 -2
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/oci_archive.py +14 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/process.py +7 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/process_test.py +484 -133
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/room_connect.py +22 -4
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/room_connect_test.py +14 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/scheduled_tasks.py +2 -2
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/scheduled_tasks_test.py +46 -2
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/task_runner.py +338 -297
- meshagent_cli-0.37.0/meshagent/cli/task_runner_test.py +165 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/test.py +8 -4
- meshagent_cli-0.37.0/meshagent/cli/version.py +1 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/worker.py +248 -214
- meshagent_cli-0.37.0/meshagent/cli/worker_test.py +152 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent_cli.egg-info/PKG-INFO +15 -13
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent_cli.egg-info/SOURCES.txt +6 -0
- meshagent_cli-0.37.0/meshagent_cli.egg-info/requires.txt +32 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/pyproject.toml +14 -12
- meshagent_cli-0.36.3/meshagent/cli/version.py +0 -1
- meshagent_cli-0.36.3/meshagent_cli.egg-info/requires.txt +0 -30
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/README.md +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/__init__.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/api_keys.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/api_keys_test.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/auth.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/auth_async.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/auth_async_test.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/call.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/cli_secrets.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/cli_test.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/common_options.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/containers.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/containers_test.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/developer.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/developer_test.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/helpers.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/mailboxes.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/meeting_transcriber.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/memory.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/memory_test.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/messaging.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/oauth2.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/oauth2_test.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/oci_archive_test.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/participant_token.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/port.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/port_test.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/projects.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/queue.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/queue_test.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/room.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/room_services.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/rooms.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/rooms_test.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/root_commands.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/routes.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/services.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/services_test.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/sessions.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/sessions_test.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/storage.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/storage_test.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/sync.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/sync_test.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/tui/__init__.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/tui/setup.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/tui/setup_splash_frames.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/tui/setup_test.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/voicebot.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/webhook.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/webserver.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent/cli/webserver_test.py +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent_cli.egg-info/dependency_links.txt +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent_cli.egg-info/entry_points.txt +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/meshagent_cli.egg-info/top_level.txt +0 -0
- {meshagent_cli-0.36.3 → meshagent_cli-0.37.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: meshagent-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.37.0
|
|
4
4
|
Summary: CLI for Meshagent
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Project-URL: Documentation, https://docs.meshagent.com
|
|
@@ -9,10 +9,12 @@ Project-URL: Source, https://www.meshagent.com
|
|
|
9
9
|
Requires-Python: >=3.13
|
|
10
10
|
Description-Content-Type: text/markdown
|
|
11
11
|
Requires-Dist: typer~=0.21
|
|
12
|
+
Requires-Dist: aiofiles~=24.1
|
|
12
13
|
Requires-Dist: fastmcp~=2.8
|
|
13
14
|
Requires-Dist: opentelemetry-distro~=0.59b0
|
|
14
15
|
Requires-Dist: opentelemetry-exporter-otlp-proto-http~=1.33
|
|
15
16
|
Requires-Dist: art~=6.5
|
|
17
|
+
Requires-Dist: pyyaml~=6.0.2
|
|
16
18
|
Requires-Dist: pydantic-yaml~=1.5
|
|
17
19
|
Requires-Dist: pathspec<2,>=1.0.3
|
|
18
20
|
Requires-Dist: zstandard~=0.25.0
|
|
@@ -20,21 +22,21 @@ Requires-Dist: rich~=14.3.0
|
|
|
20
22
|
Requires-Dist: textual<2.0,>=0.50
|
|
21
23
|
Requires-Dist: prompt-toolkit~=3.0.52
|
|
22
24
|
Provides-Extra: all
|
|
23
|
-
Requires-Dist: meshagent-agents[all]~=0.
|
|
24
|
-
Requires-Dist: meshagent-api[all]~=0.
|
|
25
|
-
Requires-Dist: meshagent-computers~=0.
|
|
26
|
-
Requires-Dist: meshagent-openai~=0.
|
|
27
|
-
Requires-Dist: meshagent-anthropic~=0.
|
|
28
|
-
Requires-Dist: meshagent-codex~=0.
|
|
29
|
-
Requires-Dist: meshagent-mcp~=0.
|
|
30
|
-
Requires-Dist: meshagent-tools~=0.
|
|
25
|
+
Requires-Dist: meshagent-agents[all]~=0.37.0; extra == "all"
|
|
26
|
+
Requires-Dist: meshagent-api[all]~=0.37.0; extra == "all"
|
|
27
|
+
Requires-Dist: meshagent-computers~=0.37.0; extra == "all"
|
|
28
|
+
Requires-Dist: meshagent-openai~=0.37.0; extra == "all"
|
|
29
|
+
Requires-Dist: meshagent-anthropic~=0.37.0; extra == "all"
|
|
30
|
+
Requires-Dist: meshagent-codex~=0.37.0; extra == "all"
|
|
31
|
+
Requires-Dist: meshagent-mcp~=0.37.0; extra == "all"
|
|
32
|
+
Requires-Dist: meshagent-tools~=0.37.0; extra == "all"
|
|
31
33
|
Requires-Dist: supabase-auth~=2.28.0; extra == "all"
|
|
32
34
|
Requires-Dist: prompt-toolkit~=3.0.52; extra == "all"
|
|
33
35
|
Provides-Extra: mcp-service
|
|
34
|
-
Requires-Dist: meshagent-agents[all]~=0.
|
|
35
|
-
Requires-Dist: meshagent-api~=0.
|
|
36
|
-
Requires-Dist: meshagent-mcp~=0.
|
|
37
|
-
Requires-Dist: meshagent-tools~=0.
|
|
36
|
+
Requires-Dist: meshagent-agents[all]~=0.37.0; extra == "mcp-service"
|
|
37
|
+
Requires-Dist: meshagent-api~=0.37.0; extra == "mcp-service"
|
|
38
|
+
Requires-Dist: meshagent-mcp~=0.37.0; extra == "mcp-service"
|
|
39
|
+
Requires-Dist: meshagent-tools~=0.37.0; extra == "mcp-service"
|
|
38
40
|
Requires-Dist: supabase-auth~=2.28.0; extra == "mcp-service"
|
|
39
41
|
|
|
40
42
|
# [Meshagent](https://www.meshagent.com)
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import tempfile
|
|
5
|
+
|
|
6
|
+
import typer
|
|
7
|
+
from rich import print
|
|
8
|
+
from rich.text import Text
|
|
9
|
+
from typing import Annotated
|
|
10
|
+
|
|
11
|
+
from meshagent.agents import Package, deploy_package, run_package
|
|
12
|
+
import meshagent.agents.package as package_module
|
|
13
|
+
from meshagent.api import RoomClient, WebSocketClientProtocol
|
|
14
|
+
from meshagent.cli import async_typer
|
|
15
|
+
from meshagent.cli.common_options import ProjectIdOption, RoomOption
|
|
16
|
+
from meshagent.cli.containers import _stream_container_job_logs_and_wait_for_exit
|
|
17
|
+
from meshagent.cli.helper import get_client, resolve_project_id, resolve_room
|
|
18
|
+
from meshagent.cli.multi import import_from_path
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
app = async_typer.AsyncTyper(help="Build, run, and deploy packaged services.")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _load_package(*, module_path: str, export_name: str) -> Package:
|
|
25
|
+
resolved_module_path = Path(module_path).expanduser().resolve()
|
|
26
|
+
with package_module._agent_base_path_scope(resolved_module_path.parent):
|
|
27
|
+
module = import_from_path(str(resolved_module_path))
|
|
28
|
+
|
|
29
|
+
if export_name not in module.__dict__:
|
|
30
|
+
raise ImportError(f"{resolved_module_path} does not define {export_name}")
|
|
31
|
+
|
|
32
|
+
exported = module.__dict__[export_name]
|
|
33
|
+
if isinstance(exported, Package):
|
|
34
|
+
exported._bind_module_path(module_path=resolved_module_path)
|
|
35
|
+
exported._bind_module_export(
|
|
36
|
+
export_name=export_name,
|
|
37
|
+
export_is_factory=False,
|
|
38
|
+
)
|
|
39
|
+
return exported
|
|
40
|
+
|
|
41
|
+
if callable(exported):
|
|
42
|
+
built = exported()
|
|
43
|
+
if isinstance(built, Package):
|
|
44
|
+
built._bind_module_path(module_path=resolved_module_path)
|
|
45
|
+
built._bind_module_export(
|
|
46
|
+
export_name=export_name,
|
|
47
|
+
export_is_factory=True,
|
|
48
|
+
)
|
|
49
|
+
return built
|
|
50
|
+
raise TypeError(
|
|
51
|
+
f"{resolved_module_path}:{export_name} returned {type(built).__name__}, expected meshagent.agents.Package"
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
raise TypeError(
|
|
55
|
+
f"{resolved_module_path}:{export_name} is {type(exported).__name__}, expected meshagent.agents.Package or a zero-argument callable returning one"
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _print_packaged_files(*, package: Package) -> None:
|
|
60
|
+
module_path = package._resolved_runtime_module_path(module_path=None)
|
|
61
|
+
deploy_assets = package._resolve_deploy_assets()
|
|
62
|
+
with tempfile.TemporaryDirectory(prefix="meshagent-package-verbose-") as temp_dir:
|
|
63
|
+
_, runtime_assets = package._runtime_module_deploy_assets(
|
|
64
|
+
module_path=module_path,
|
|
65
|
+
temp_dir=Path(temp_dir),
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
file_entries = package._packaged_file_entries(
|
|
69
|
+
deploy_assets=deploy_assets,
|
|
70
|
+
runtime_assets=runtime_assets,
|
|
71
|
+
)
|
|
72
|
+
print(Text("Packaged files:", style="bold"))
|
|
73
|
+
if len(file_entries) == 0:
|
|
74
|
+
print(Text(" (none)", style="dim"))
|
|
75
|
+
return
|
|
76
|
+
|
|
77
|
+
for entry in file_entries:
|
|
78
|
+
print(
|
|
79
|
+
Text(
|
|
80
|
+
f" [{entry.category}] {entry.source} -> {entry.dest.as_posix()}",
|
|
81
|
+
)
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _verbose_status_printer(message: str) -> None:
|
|
86
|
+
print(Text(message, style="dim"))
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@app.async_command("deploy", help="Deploy a packaged service into a room.")
|
|
90
|
+
async def deploy(
|
|
91
|
+
*,
|
|
92
|
+
module: Annotated[
|
|
93
|
+
str, typer.Argument(help="Path to a Python file exporting a Package")
|
|
94
|
+
],
|
|
95
|
+
room: RoomOption,
|
|
96
|
+
project_id: ProjectIdOption,
|
|
97
|
+
name: Annotated[
|
|
98
|
+
str, typer.Option(help="Export name in the Python module")
|
|
99
|
+
] = "main",
|
|
100
|
+
builder_name: Annotated[
|
|
101
|
+
str | None,
|
|
102
|
+
typer.Option(
|
|
103
|
+
"--builder-name",
|
|
104
|
+
help="Optional reusable builder name for package image builds.",
|
|
105
|
+
),
|
|
106
|
+
] = None,
|
|
107
|
+
verbose: Annotated[
|
|
108
|
+
bool,
|
|
109
|
+
typer.Option(
|
|
110
|
+
"--verbose",
|
|
111
|
+
help="Print all files that will be added to the package.",
|
|
112
|
+
),
|
|
113
|
+
] = False,
|
|
114
|
+
) -> None:
|
|
115
|
+
try:
|
|
116
|
+
package = _load_package(module_path=module, export_name=name)
|
|
117
|
+
if verbose:
|
|
118
|
+
_print_packaged_files(package=package)
|
|
119
|
+
service_id = await deploy_package(
|
|
120
|
+
package=package,
|
|
121
|
+
room=room,
|
|
122
|
+
project_id=project_id,
|
|
123
|
+
builder_name=builder_name,
|
|
124
|
+
status_callback=_verbose_status_printer if verbose else None,
|
|
125
|
+
)
|
|
126
|
+
print(f"[green]Deployed service:[/] {service_id}")
|
|
127
|
+
except Exception as exc:
|
|
128
|
+
print(Text(str(exc), style="red"))
|
|
129
|
+
raise typer.Exit(1)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
@app.async_command("run", help="Run a packaged service container in a room.")
|
|
133
|
+
async def run(
|
|
134
|
+
*,
|
|
135
|
+
module: Annotated[
|
|
136
|
+
str, typer.Argument(help="Path to a Python file exporting a Package")
|
|
137
|
+
],
|
|
138
|
+
room: RoomOption,
|
|
139
|
+
project_id: ProjectIdOption,
|
|
140
|
+
name: Annotated[
|
|
141
|
+
str, typer.Option(help="Export name in the Python module")
|
|
142
|
+
] = "main",
|
|
143
|
+
builder_name: Annotated[
|
|
144
|
+
str | None,
|
|
145
|
+
typer.Option(
|
|
146
|
+
"--builder-name",
|
|
147
|
+
help="Optional reusable builder name for package image builds.",
|
|
148
|
+
),
|
|
149
|
+
] = None,
|
|
150
|
+
verbose: Annotated[
|
|
151
|
+
bool,
|
|
152
|
+
typer.Option(
|
|
153
|
+
"--verbose",
|
|
154
|
+
help="Print all files that will be added to the package.",
|
|
155
|
+
),
|
|
156
|
+
] = False,
|
|
157
|
+
) -> None:
|
|
158
|
+
try:
|
|
159
|
+
package = _load_package(module_path=module, export_name=name)
|
|
160
|
+
if verbose:
|
|
161
|
+
_print_packaged_files(package=package)
|
|
162
|
+
container_id = await run_package(
|
|
163
|
+
package=package,
|
|
164
|
+
room=room,
|
|
165
|
+
project_id=project_id,
|
|
166
|
+
builder_name=builder_name,
|
|
167
|
+
status_callback=_verbose_status_printer if verbose else None,
|
|
168
|
+
)
|
|
169
|
+
print(f"[green]Started container:[/] {container_id}")
|
|
170
|
+
account_client = await get_client()
|
|
171
|
+
try:
|
|
172
|
+
resolved_project_id = await resolve_project_id(project_id=project_id)
|
|
173
|
+
resolved_room = resolve_room(room)
|
|
174
|
+
if resolved_room is None:
|
|
175
|
+
raise ValueError("room is required")
|
|
176
|
+
connection = await account_client.connect_room(
|
|
177
|
+
project_id=resolved_project_id,
|
|
178
|
+
room=resolved_room,
|
|
179
|
+
)
|
|
180
|
+
async with RoomClient(
|
|
181
|
+
protocol=WebSocketClientProtocol(
|
|
182
|
+
url=connection.room_url,
|
|
183
|
+
token=connection.jwt,
|
|
184
|
+
)
|
|
185
|
+
) as client:
|
|
186
|
+
try:
|
|
187
|
+
exit_code = await _stream_container_job_logs_and_wait_for_exit(
|
|
188
|
+
client=client,
|
|
189
|
+
container_id=container_id,
|
|
190
|
+
)
|
|
191
|
+
except (KeyboardInterrupt, asyncio.CancelledError):
|
|
192
|
+
print(
|
|
193
|
+
"[bold yellow]Stopping and deleting container...[/bold yellow]"
|
|
194
|
+
)
|
|
195
|
+
try:
|
|
196
|
+
await client.containers.stop(
|
|
197
|
+
container_id=container_id,
|
|
198
|
+
force=True,
|
|
199
|
+
)
|
|
200
|
+
except Exception as exc:
|
|
201
|
+
print(
|
|
202
|
+
Text(
|
|
203
|
+
f"Unable to stop container before delete: {exc}",
|
|
204
|
+
style="yellow",
|
|
205
|
+
)
|
|
206
|
+
)
|
|
207
|
+
try:
|
|
208
|
+
await client.containers.delete(container_id=container_id)
|
|
209
|
+
except Exception as exc:
|
|
210
|
+
print(
|
|
211
|
+
Text(
|
|
212
|
+
f"Unable to delete container after interrupt: {exc}",
|
|
213
|
+
style="yellow",
|
|
214
|
+
)
|
|
215
|
+
)
|
|
216
|
+
raise typer.Exit(code=130)
|
|
217
|
+
if exit_code != 0:
|
|
218
|
+
raise typer.Exit(code=exit_code)
|
|
219
|
+
finally:
|
|
220
|
+
await account_client.close()
|
|
221
|
+
except Exception as exc:
|
|
222
|
+
if isinstance(exc, typer.Exit):
|
|
223
|
+
raise
|
|
224
|
+
print(Text(str(exc), style="red"))
|
|
225
|
+
raise typer.Exit(1)
|