meshagent-cli 0.22.2__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.
Potentially problematic release.
This version of meshagent-cli might be problematic. Click here for more details.
- meshagent/cli/__init__.py +3 -0
- meshagent/cli/agent.py +273 -0
- meshagent/cli/api_keys.py +102 -0
- meshagent/cli/async_typer.py +79 -0
- meshagent/cli/auth.py +30 -0
- meshagent/cli/auth_async.py +295 -0
- meshagent/cli/call.py +215 -0
- meshagent/cli/chatbot.py +1983 -0
- meshagent/cli/cli.py +187 -0
- meshagent/cli/cli_mcp.py +408 -0
- meshagent/cli/cli_secrets.py +414 -0
- meshagent/cli/common_options.py +47 -0
- meshagent/cli/containers.py +725 -0
- meshagent/cli/database.py +997 -0
- meshagent/cli/developer.py +70 -0
- meshagent/cli/exec.py +397 -0
- meshagent/cli/helper.py +236 -0
- meshagent/cli/helpers.py +185 -0
- meshagent/cli/host.py +41 -0
- meshagent/cli/mailbot.py +1295 -0
- meshagent/cli/mailboxes.py +223 -0
- meshagent/cli/meeting_transcriber.py +138 -0
- meshagent/cli/messaging.py +157 -0
- meshagent/cli/multi.py +357 -0
- meshagent/cli/oauth2.py +341 -0
- meshagent/cli/participant_token.py +63 -0
- meshagent/cli/port.py +70 -0
- meshagent/cli/projects.py +105 -0
- meshagent/cli/queue.py +91 -0
- meshagent/cli/room.py +26 -0
- meshagent/cli/rooms.py +214 -0
- meshagent/cli/services.py +722 -0
- meshagent/cli/sessions.py +26 -0
- meshagent/cli/storage.py +813 -0
- meshagent/cli/sync.py +434 -0
- meshagent/cli/task_runner.py +1317 -0
- meshagent/cli/version.py +1 -0
- meshagent/cli/voicebot.py +624 -0
- meshagent/cli/webhook.py +100 -0
- meshagent/cli/worker.py +1403 -0
- meshagent_cli-0.22.2.dist-info/METADATA +49 -0
- meshagent_cli-0.22.2.dist-info/RECORD +45 -0
- meshagent_cli-0.22.2.dist-info/WHEEL +5 -0
- meshagent_cli-0.22.2.dist-info/entry_points.txt +2 -0
- meshagent_cli-0.22.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
# meshagent/cli/mailboxes.py
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Annotated, Optional
|
|
6
|
+
|
|
7
|
+
import typer
|
|
8
|
+
from aiohttp import ClientResponseError
|
|
9
|
+
from rich import print
|
|
10
|
+
|
|
11
|
+
from meshagent.cli import async_typer
|
|
12
|
+
from meshagent.cli.common_options import ProjectIdOption, OutputFormatOption
|
|
13
|
+
from meshagent.cli.helper import get_client, print_json_table, resolve_project_id
|
|
14
|
+
|
|
15
|
+
app = async_typer.AsyncTyper(help="Manage mailboxes for your project")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@app.async_command("create")
|
|
19
|
+
async def mailbox_create(
|
|
20
|
+
*,
|
|
21
|
+
project_id: ProjectIdOption,
|
|
22
|
+
address: Annotated[
|
|
23
|
+
str,
|
|
24
|
+
typer.Option(
|
|
25
|
+
"--address",
|
|
26
|
+
"-a",
|
|
27
|
+
help="Mailbox email address (unique per project)",
|
|
28
|
+
),
|
|
29
|
+
],
|
|
30
|
+
room: Annotated[
|
|
31
|
+
str,
|
|
32
|
+
typer.Option(
|
|
33
|
+
"--room",
|
|
34
|
+
"-r",
|
|
35
|
+
help="Room name to route inbound mail into",
|
|
36
|
+
),
|
|
37
|
+
],
|
|
38
|
+
queue: Annotated[
|
|
39
|
+
str,
|
|
40
|
+
typer.Option(
|
|
41
|
+
"--queue",
|
|
42
|
+
"-q",
|
|
43
|
+
help="Queue name to deliver inbound messages to",
|
|
44
|
+
),
|
|
45
|
+
],
|
|
46
|
+
public: Annotated[
|
|
47
|
+
bool,
|
|
48
|
+
typer.Option(
|
|
49
|
+
"--public",
|
|
50
|
+
help="Queue name to deliver inbound messages to",
|
|
51
|
+
),
|
|
52
|
+
] = False,
|
|
53
|
+
):
|
|
54
|
+
"""Create a mailbox attached to the project."""
|
|
55
|
+
client = await get_client()
|
|
56
|
+
try:
|
|
57
|
+
project_id = await resolve_project_id(project_id)
|
|
58
|
+
|
|
59
|
+
try:
|
|
60
|
+
await client.create_mailbox(
|
|
61
|
+
project_id=project_id,
|
|
62
|
+
address=address,
|
|
63
|
+
room=room,
|
|
64
|
+
queue=queue,
|
|
65
|
+
public=public,
|
|
66
|
+
)
|
|
67
|
+
except ClientResponseError as exc:
|
|
68
|
+
# Common patterns: 409 conflict on duplicate address, 400 validation, etc.
|
|
69
|
+
if exc.status == 409:
|
|
70
|
+
print(f"[red]Mailbox address already in use:[/] {address}")
|
|
71
|
+
raise typer.Exit(code=1)
|
|
72
|
+
raise
|
|
73
|
+
else:
|
|
74
|
+
print(f"[green]Created mailbox:[/] {address}")
|
|
75
|
+
finally:
|
|
76
|
+
await client.close()
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@app.async_command("update")
|
|
80
|
+
async def mailbox_update(
|
|
81
|
+
*,
|
|
82
|
+
project_id: ProjectIdOption,
|
|
83
|
+
address: Annotated[
|
|
84
|
+
str,
|
|
85
|
+
typer.Argument(help="Mailbox email address to update"),
|
|
86
|
+
],
|
|
87
|
+
room: Annotated[
|
|
88
|
+
Optional[str],
|
|
89
|
+
typer.Option(
|
|
90
|
+
"--room",
|
|
91
|
+
"-r",
|
|
92
|
+
help="Room name to route inbound mail into",
|
|
93
|
+
),
|
|
94
|
+
] = None,
|
|
95
|
+
queue: Annotated[
|
|
96
|
+
Optional[str],
|
|
97
|
+
typer.Option(
|
|
98
|
+
"--queue",
|
|
99
|
+
"-q",
|
|
100
|
+
help="Queue name to deliver inbound messages to",
|
|
101
|
+
),
|
|
102
|
+
] = None,
|
|
103
|
+
public: Annotated[
|
|
104
|
+
bool,
|
|
105
|
+
typer.Option(
|
|
106
|
+
"--public",
|
|
107
|
+
help="Queue name to deliver inbound messages to",
|
|
108
|
+
),
|
|
109
|
+
] = False,
|
|
110
|
+
):
|
|
111
|
+
"""Update a mailbox routing configuration."""
|
|
112
|
+
client = await get_client()
|
|
113
|
+
try:
|
|
114
|
+
project_id = await resolve_project_id(project_id)
|
|
115
|
+
|
|
116
|
+
# Keep parity with other CLIs: allow partial update by reading existing first
|
|
117
|
+
if room is None or queue is None:
|
|
118
|
+
try:
|
|
119
|
+
mb = await client.get_mailbox(project_id=project_id, address=address)
|
|
120
|
+
except ClientResponseError as exc:
|
|
121
|
+
if exc.status == 404:
|
|
122
|
+
print(f"[red]Mailbox not found:[/] {address}")
|
|
123
|
+
raise typer.Exit(code=1)
|
|
124
|
+
raise
|
|
125
|
+
room = room or mb.room
|
|
126
|
+
queue = queue or mb.queue
|
|
127
|
+
|
|
128
|
+
try:
|
|
129
|
+
await client.update_mailbox(
|
|
130
|
+
project_id=project_id,
|
|
131
|
+
address=address,
|
|
132
|
+
room=room,
|
|
133
|
+
queue=queue,
|
|
134
|
+
public=public,
|
|
135
|
+
)
|
|
136
|
+
except ClientResponseError as exc:
|
|
137
|
+
if exc.status == 404:
|
|
138
|
+
print(f"[red]Mailbox not found:[/] {address}")
|
|
139
|
+
raise typer.Exit(code=1)
|
|
140
|
+
raise
|
|
141
|
+
else:
|
|
142
|
+
print(f"[green]Updated mailbox:[/] {address}")
|
|
143
|
+
finally:
|
|
144
|
+
await client.close()
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
@app.async_command("show")
|
|
148
|
+
async def mailbox_show(
|
|
149
|
+
*,
|
|
150
|
+
project_id: ProjectIdOption,
|
|
151
|
+
address: Annotated[str, typer.Argument(help="Mailbox address to show")],
|
|
152
|
+
):
|
|
153
|
+
"""Show mailbox details."""
|
|
154
|
+
client = await get_client()
|
|
155
|
+
try:
|
|
156
|
+
project_id = await resolve_project_id(project_id)
|
|
157
|
+
try:
|
|
158
|
+
mb = await client.get_mailbox(project_id=project_id, address=address)
|
|
159
|
+
except ClientResponseError as exc:
|
|
160
|
+
if exc.status == 404:
|
|
161
|
+
print(f"[red]Mailbox not found:[/] {address}")
|
|
162
|
+
raise typer.Exit(code=1)
|
|
163
|
+
raise
|
|
164
|
+
print(mb.model_dump(mode="json"))
|
|
165
|
+
finally:
|
|
166
|
+
await client.close()
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
@app.async_command("list")
|
|
170
|
+
async def mailbox_list(
|
|
171
|
+
*,
|
|
172
|
+
project_id: ProjectIdOption,
|
|
173
|
+
o: OutputFormatOption = "table",
|
|
174
|
+
):
|
|
175
|
+
"""List mailboxes for the project."""
|
|
176
|
+
client = await get_client()
|
|
177
|
+
try:
|
|
178
|
+
project_id = await resolve_project_id(project_id)
|
|
179
|
+
mailboxes = await client.list_mailboxes(project_id=project_id)
|
|
180
|
+
|
|
181
|
+
if o == "json":
|
|
182
|
+
# Keep your existing conventions: wrap in an object.
|
|
183
|
+
print({"mailboxes": [mb.model_dump(mode="json") for mb in mailboxes]})
|
|
184
|
+
else:
|
|
185
|
+
print_json_table(
|
|
186
|
+
[
|
|
187
|
+
{
|
|
188
|
+
"address": mb.address,
|
|
189
|
+
"room": mb.room,
|
|
190
|
+
"queue": mb.queue,
|
|
191
|
+
"public": mb.public,
|
|
192
|
+
}
|
|
193
|
+
for mb in mailboxes
|
|
194
|
+
],
|
|
195
|
+
"address",
|
|
196
|
+
"room",
|
|
197
|
+
"queue",
|
|
198
|
+
)
|
|
199
|
+
finally:
|
|
200
|
+
await client.close()
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
@app.async_command("delete")
|
|
204
|
+
async def mailbox_delete(
|
|
205
|
+
*,
|
|
206
|
+
project_id: ProjectIdOption,
|
|
207
|
+
address: Annotated[str, typer.Argument(help="Mailbox address to delete")],
|
|
208
|
+
):
|
|
209
|
+
"""Delete a mailbox."""
|
|
210
|
+
client = await get_client()
|
|
211
|
+
try:
|
|
212
|
+
project_id = await resolve_project_id(project_id)
|
|
213
|
+
try:
|
|
214
|
+
await client.delete_mailbox(project_id=project_id, address=address)
|
|
215
|
+
except ClientResponseError as exc:
|
|
216
|
+
if exc.status == 404:
|
|
217
|
+
print(f"[red]Mailbox not found:[/] {address}")
|
|
218
|
+
raise typer.Exit(code=1)
|
|
219
|
+
raise
|
|
220
|
+
else:
|
|
221
|
+
print(f"[green]Mailbox deleted:[/] {address}")
|
|
222
|
+
finally:
|
|
223
|
+
await client.close()
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
from rich import print
|
|
3
|
+
from typing import Annotated, Optional
|
|
4
|
+
from meshagent.cli.common_options import ProjectIdOption, RoomOption
|
|
5
|
+
from meshagent.api import RoomClient, WebSocketClientProtocol, RoomException
|
|
6
|
+
from meshagent.api.helpers import meshagent_base_url, websocket_room_url
|
|
7
|
+
from meshagent.cli import async_typer
|
|
8
|
+
from meshagent.api import ParticipantToken, ApiScope
|
|
9
|
+
from meshagent.cli.helper import (
|
|
10
|
+
get_client,
|
|
11
|
+
resolve_project_id,
|
|
12
|
+
resolve_room,
|
|
13
|
+
resolve_key,
|
|
14
|
+
)
|
|
15
|
+
import os
|
|
16
|
+
from meshagent.api import RequiredSchema
|
|
17
|
+
from meshagent.api.services import ServiceHost
|
|
18
|
+
|
|
19
|
+
app = async_typer.AsyncTyper(help="Join a meeting transcriber to a room")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@app.async_command("join")
|
|
23
|
+
async def join(
|
|
24
|
+
*,
|
|
25
|
+
project_id: ProjectIdOption,
|
|
26
|
+
room: RoomOption,
|
|
27
|
+
agent_name: Annotated[
|
|
28
|
+
Optional[str], typer.Option(..., help="Name of the agent")
|
|
29
|
+
] = None,
|
|
30
|
+
key: Annotated[
|
|
31
|
+
str,
|
|
32
|
+
typer.Option("--key", help="an api key to sign the token with"),
|
|
33
|
+
] = None,
|
|
34
|
+
):
|
|
35
|
+
try:
|
|
36
|
+
from meshagent.livekit.agents.meeting_transcriber import MeetingTranscriber
|
|
37
|
+
except ImportError:
|
|
38
|
+
|
|
39
|
+
class MeetingTranscriber:
|
|
40
|
+
def __init__(self, **kwargs):
|
|
41
|
+
raise RoomException(
|
|
42
|
+
"meshagent.livekit module not found, transcribers are not available"
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
key = await resolve_key(project_id=project_id, key=key)
|
|
46
|
+
|
|
47
|
+
account_client = await get_client()
|
|
48
|
+
try:
|
|
49
|
+
project_id = await resolve_project_id(project_id=project_id)
|
|
50
|
+
room = resolve_room(room)
|
|
51
|
+
|
|
52
|
+
jwt = os.getenv("MESHAGENT_TOKEN")
|
|
53
|
+
if jwt is None:
|
|
54
|
+
if agent_name is None:
|
|
55
|
+
print(
|
|
56
|
+
"[bold red]--agent-name must be specified when the MESHAGENT_TOKEN environment variable is not set[/bold red]"
|
|
57
|
+
)
|
|
58
|
+
raise typer.Exit(1)
|
|
59
|
+
|
|
60
|
+
token = ParticipantToken(
|
|
61
|
+
name=agent_name,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
token.add_api_grant(ApiScope.agent_default())
|
|
65
|
+
|
|
66
|
+
token.add_role_grant(role="agent")
|
|
67
|
+
token.add_room_grant(room)
|
|
68
|
+
|
|
69
|
+
jwt = token.to_jwt(api_key=key)
|
|
70
|
+
|
|
71
|
+
print("[bold green]Connecting to room...[/bold green]", flush=True)
|
|
72
|
+
async with RoomClient(
|
|
73
|
+
protocol=WebSocketClientProtocol(
|
|
74
|
+
url=websocket_room_url(room_name=room, base_url=meshagent_base_url()),
|
|
75
|
+
token=jwt,
|
|
76
|
+
)
|
|
77
|
+
) as client:
|
|
78
|
+
requirements = []
|
|
79
|
+
|
|
80
|
+
requirements.append(RequiredSchema(name="transcript"))
|
|
81
|
+
|
|
82
|
+
bot = MeetingTranscriber(
|
|
83
|
+
requires=requirements,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
await bot.start(room=client)
|
|
87
|
+
|
|
88
|
+
try:
|
|
89
|
+
print(
|
|
90
|
+
f"[bold green]Open the studio to interact with your agent: {meshagent_base_url().replace('api.', 'studio.')}/projects/{project_id}/rooms/{client.room_name}[/bold green]",
|
|
91
|
+
flush=True,
|
|
92
|
+
)
|
|
93
|
+
await client.protocol.wait_for_close()
|
|
94
|
+
except KeyboardInterrupt:
|
|
95
|
+
await bot.stop()
|
|
96
|
+
|
|
97
|
+
finally:
|
|
98
|
+
await account_client.close()
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
@app.async_command("service")
|
|
102
|
+
async def service(
|
|
103
|
+
*,
|
|
104
|
+
agent_name: Annotated[str, typer.Option(..., help="Name of the agent")],
|
|
105
|
+
host: Annotated[
|
|
106
|
+
Optional[str], typer.Option(help="Host to bind the service on")
|
|
107
|
+
] = None,
|
|
108
|
+
port: Annotated[
|
|
109
|
+
Optional[int], typer.Option(help="Port to bind the service on")
|
|
110
|
+
] = None,
|
|
111
|
+
path: Annotated[
|
|
112
|
+
str, typer.Option(help="HTTP path to mount the service at")
|
|
113
|
+
] = "/agent",
|
|
114
|
+
):
|
|
115
|
+
try:
|
|
116
|
+
from meshagent.livekit.agents.meeting_transcriber import MeetingTranscriber
|
|
117
|
+
except ImportError:
|
|
118
|
+
|
|
119
|
+
class MeetingTranscriber:
|
|
120
|
+
def __init__(self, **kwargs):
|
|
121
|
+
raise RoomException(
|
|
122
|
+
"meshagent.livekit module not found, voicebots are not available"
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
requirements = []
|
|
126
|
+
|
|
127
|
+
requirements.append(RequiredSchema(name="transcript"))
|
|
128
|
+
|
|
129
|
+
service = ServiceHost(host=host, port=port)
|
|
130
|
+
|
|
131
|
+
@service.path(path=path)
|
|
132
|
+
class CustomMeetingTranscriber(MeetingTranscriber):
|
|
133
|
+
def __init__(self):
|
|
134
|
+
super().__init__(
|
|
135
|
+
requires=requirements,
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
await service.run()
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
from rich import print
|
|
3
|
+
from typing import Annotated
|
|
4
|
+
from meshagent.cli.common_options import (
|
|
5
|
+
ProjectIdOption,
|
|
6
|
+
RoomOption,
|
|
7
|
+
)
|
|
8
|
+
import json
|
|
9
|
+
|
|
10
|
+
from meshagent.api import RoomClient, WebSocketClientProtocol
|
|
11
|
+
from meshagent.api.helpers import meshagent_base_url, websocket_room_url
|
|
12
|
+
from meshagent.cli import async_typer
|
|
13
|
+
from meshagent.cli.helper import (
|
|
14
|
+
get_client,
|
|
15
|
+
resolve_project_id,
|
|
16
|
+
resolve_room,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
app = async_typer.AsyncTyper(help="Send and receive messages in a room")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@app.async_command("list", help="List messaging-enabled participants")
|
|
23
|
+
async def messaging_list_participants_command(
|
|
24
|
+
*,
|
|
25
|
+
project_id: ProjectIdOption,
|
|
26
|
+
room: RoomOption,
|
|
27
|
+
):
|
|
28
|
+
"""
|
|
29
|
+
List all messaging-enabled participants in the room.
|
|
30
|
+
"""
|
|
31
|
+
account_client = await get_client()
|
|
32
|
+
try:
|
|
33
|
+
# Resolve project_id if not provided
|
|
34
|
+
project_id = await resolve_project_id(project_id=project_id)
|
|
35
|
+
|
|
36
|
+
room = resolve_room(room)
|
|
37
|
+
|
|
38
|
+
connection = await account_client.connect_room(project_id=project_id, room=room)
|
|
39
|
+
|
|
40
|
+
print("[bold green]Connecting to room...[/bold green]")
|
|
41
|
+
async with RoomClient(
|
|
42
|
+
protocol=WebSocketClientProtocol(
|
|
43
|
+
url=websocket_room_url(room_name=room, base_url=meshagent_base_url()),
|
|
44
|
+
token=connection.jwt,
|
|
45
|
+
)
|
|
46
|
+
) as client:
|
|
47
|
+
# Must enable before we can see who else is enabled
|
|
48
|
+
await client.messaging.enable()
|
|
49
|
+
|
|
50
|
+
participants = client.messaging.get_participants()
|
|
51
|
+
output = []
|
|
52
|
+
for p in participants:
|
|
53
|
+
output.append({"id": p.id, "role": p.role, "attributes": p._attributes})
|
|
54
|
+
|
|
55
|
+
print(json.dumps(output, indent=2))
|
|
56
|
+
|
|
57
|
+
await client.messaging.stop()
|
|
58
|
+
|
|
59
|
+
finally:
|
|
60
|
+
await account_client.close()
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@app.async_command("send", help="Send a direct message to a participant")
|
|
64
|
+
async def messaging_send_command(
|
|
65
|
+
*,
|
|
66
|
+
project_id: ProjectIdOption,
|
|
67
|
+
room: RoomOption,
|
|
68
|
+
to_participant_id: Annotated[
|
|
69
|
+
str, typer.Option(..., help="Participant ID to send a message to")
|
|
70
|
+
],
|
|
71
|
+
type: Annotated[str, typer.Option(..., help="type of the message to send")],
|
|
72
|
+
data: Annotated[str, typer.Option(..., help="JSON message to send")],
|
|
73
|
+
):
|
|
74
|
+
"""
|
|
75
|
+
Send a direct message to a single participant in the room.
|
|
76
|
+
"""
|
|
77
|
+
account_client = await get_client()
|
|
78
|
+
try:
|
|
79
|
+
# Resolve project_id if not provided
|
|
80
|
+
project_id = await resolve_project_id(project_id=project_id)
|
|
81
|
+
room = resolve_room(room)
|
|
82
|
+
|
|
83
|
+
connection = await account_client.connect_room(project_id=project_id, room=room)
|
|
84
|
+
|
|
85
|
+
print("[bold green]Connecting to room...[/bold green]")
|
|
86
|
+
async with RoomClient(
|
|
87
|
+
protocol=WebSocketClientProtocol(
|
|
88
|
+
url=websocket_room_url(room_name=room, base_url=meshagent_base_url()),
|
|
89
|
+
token=connection.jwt,
|
|
90
|
+
)
|
|
91
|
+
) as client:
|
|
92
|
+
# Create and enable messaging
|
|
93
|
+
await client.messaging.enable()
|
|
94
|
+
|
|
95
|
+
# Find the participant we want to message
|
|
96
|
+
participant = None
|
|
97
|
+
for p in client.messaging.get_participants():
|
|
98
|
+
if p.id == to_participant_id:
|
|
99
|
+
participant = p
|
|
100
|
+
break
|
|
101
|
+
|
|
102
|
+
if participant is None:
|
|
103
|
+
print(
|
|
104
|
+
f"[bold red]Participant with ID {to_participant_id} not found or not messaging-enabled.[/bold red]"
|
|
105
|
+
)
|
|
106
|
+
else:
|
|
107
|
+
# Send the message
|
|
108
|
+
await client.messaging.send_message(
|
|
109
|
+
to=participant,
|
|
110
|
+
type=type,
|
|
111
|
+
message=json.loads(data),
|
|
112
|
+
attachment=None,
|
|
113
|
+
)
|
|
114
|
+
print("[bold cyan]Message sent successfully.[/bold cyan]")
|
|
115
|
+
|
|
116
|
+
await client.messaging.stop()
|
|
117
|
+
finally:
|
|
118
|
+
await account_client.close()
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
@app.async_command("broadcast", help="Broadcast a message to all participants")
|
|
122
|
+
async def messaging_broadcast_command(
|
|
123
|
+
*,
|
|
124
|
+
project_id: ProjectIdOption,
|
|
125
|
+
room: RoomOption,
|
|
126
|
+
data: Annotated[str, typer.Option(..., help="JSON message to broadcast")],
|
|
127
|
+
):
|
|
128
|
+
"""
|
|
129
|
+
Broadcast a message to all messaging-enabled participants in the room.
|
|
130
|
+
"""
|
|
131
|
+
account_client = await get_client()
|
|
132
|
+
try:
|
|
133
|
+
# Resolve project_id if not provided
|
|
134
|
+
project_id = await resolve_project_id(project_id=project_id)
|
|
135
|
+
|
|
136
|
+
room = resolve_room(room)
|
|
137
|
+
connection = await account_client.connect_room(project_id=project_id, room=room)
|
|
138
|
+
|
|
139
|
+
print("[bold green]Connecting to room...[/bold green]")
|
|
140
|
+
async with RoomClient(
|
|
141
|
+
protocol=WebSocketClientProtocol(
|
|
142
|
+
url=websocket_room_url(room_name=room, base_url=meshagent_base_url()),
|
|
143
|
+
token=connection.jwt,
|
|
144
|
+
)
|
|
145
|
+
) as client:
|
|
146
|
+
# Create and enable messaging
|
|
147
|
+
await client.messaging.enable()
|
|
148
|
+
|
|
149
|
+
# Broadcast the message
|
|
150
|
+
await client.messaging.broadcast_message(
|
|
151
|
+
type="chat.broadcast", message=json.loads(data), attachment=None
|
|
152
|
+
)
|
|
153
|
+
print("[bold cyan]Broadcast message sent successfully.[/bold cyan]")
|
|
154
|
+
|
|
155
|
+
await client.messaging.stop()
|
|
156
|
+
finally:
|
|
157
|
+
await account_client.close()
|