meshagent-cli 0.21.0__py3-none-any.whl → 0.23.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.
- meshagent/cli/agent.py +8 -2
- meshagent/cli/call.py +15 -28
- meshagent/cli/chatbot.py +580 -76
- meshagent/cli/cli.py +3 -3
- meshagent/cli/helper.py +40 -2
- meshagent/cli/helpers.py +0 -3
- meshagent/cli/host.py +4 -0
- meshagent/cli/mailbot.py +137 -76
- meshagent/cli/meeting_transcriber.py +19 -11
- meshagent/cli/messaging.py +1 -4
- meshagent/cli/multi.py +53 -98
- meshagent/cli/oauth2.py +164 -35
- meshagent/cli/room.py +6 -2
- meshagent/cli/services.py +238 -15
- meshagent/cli/sync.py +434 -0
- meshagent/cli/task_runner.py +625 -78
- meshagent/cli/version.py +1 -1
- meshagent/cli/voicebot.py +54 -34
- meshagent/cli/worker.py +151 -75
- {meshagent_cli-0.21.0.dist-info → meshagent_cli-0.23.0.dist-info}/METADATA +13 -11
- meshagent_cli-0.23.0.dist-info/RECORD +45 -0
- {meshagent_cli-0.21.0.dist-info → meshagent_cli-0.23.0.dist-info}/WHEEL +1 -1
- meshagent_cli-0.21.0.dist-info/RECORD +0 -44
- {meshagent_cli-0.21.0.dist-info → meshagent_cli-0.23.0.dist-info}/entry_points.txt +0 -0
- {meshagent_cli-0.21.0.dist-info → meshagent_cli-0.23.0.dist-info}/top_level.txt +0 -0
meshagent/cli/multi.py
CHANGED
|
@@ -10,45 +10,54 @@ import click
|
|
|
10
10
|
import shlex
|
|
11
11
|
|
|
12
12
|
from rich import print
|
|
13
|
-
|
|
14
|
-
import
|
|
13
|
+
|
|
14
|
+
from meshagent.agents import Agent
|
|
15
15
|
|
|
16
16
|
from typer.main import get_command
|
|
17
17
|
|
|
18
|
+
from meshagent.cli.common_options import RoomOption
|
|
18
19
|
from meshagent.cli.helper import (
|
|
19
20
|
get_client,
|
|
20
21
|
resolve_project_id,
|
|
21
|
-
resolve_room,
|
|
22
|
-
resolve_key,
|
|
23
|
-
)
|
|
24
|
-
from meshagent.api import (
|
|
25
|
-
ParticipantToken,
|
|
26
|
-
ApiScope,
|
|
27
22
|
)
|
|
28
23
|
from aiohttp import ClientResponseError
|
|
29
24
|
import asyncio
|
|
30
25
|
|
|
31
|
-
from meshagent.api
|
|
26
|
+
from meshagent.api import RoomClient
|
|
27
|
+
|
|
28
|
+
from meshagent.api.helpers import meshagent_base_url, websocket_room_url
|
|
29
|
+
from meshagent.api.websocket_protocol import WebSocketClientProtocol
|
|
32
30
|
|
|
33
31
|
from meshagent.cli.chatbot import service as chatbot_service
|
|
34
32
|
from meshagent.cli.worker import service as worker_service
|
|
35
33
|
from meshagent.cli.mailbot import service as mailbot_service
|
|
36
34
|
from meshagent.cli.voicebot import service as voicebot_service
|
|
37
35
|
|
|
36
|
+
from meshagent.cli.chatbot import join as chatbot_join
|
|
37
|
+
from meshagent.cli.worker import join as worker_join
|
|
38
|
+
from meshagent.cli.mailbot import join as mailbot_join
|
|
39
|
+
from meshagent.cli.voicebot import join as voicebot_join
|
|
40
|
+
|
|
38
41
|
import yaml
|
|
39
42
|
|
|
40
43
|
|
|
41
44
|
app = async_typer.AsyncTyper(help="Connect agents and tools to a room")
|
|
42
45
|
|
|
43
|
-
|
|
46
|
+
cli_service = async_typer.AsyncTyper(help="Add agents to a team")
|
|
44
47
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
cli_service.command("chatbot")(chatbot_service)
|
|
49
|
+
cli_service.command("worker")(worker_service)
|
|
50
|
+
cli_service.command("mailbot")(mailbot_service)
|
|
51
|
+
cli_service.command("voicebot")(voicebot_service)
|
|
49
52
|
|
|
53
|
+
cli_join = async_typer.AsyncTyper(help="Add agents to a team")
|
|
54
|
+
cli_join.command("chatbot")(chatbot_join)
|
|
55
|
+
cli_join.command("worker")(worker_join)
|
|
56
|
+
cli_join.command("mailbot")(mailbot_join)
|
|
57
|
+
cli_join.command("voicebot")(voicebot_join)
|
|
50
58
|
|
|
51
|
-
|
|
59
|
+
|
|
60
|
+
@cli_service.async_command("python")
|
|
52
61
|
async def python(
|
|
53
62
|
*,
|
|
54
63
|
module: str,
|
|
@@ -120,7 +129,7 @@ def build_spec(
|
|
|
120
129
|
] = None,
|
|
121
130
|
):
|
|
122
131
|
for c in command.split(";"):
|
|
123
|
-
if execute_via_root(
|
|
132
|
+
if execute_via_root(cli_service, c, prog_name="meshagent") != 0:
|
|
124
133
|
print(f"[red]{c} failed[/red]")
|
|
125
134
|
raise typer.Exit(1)
|
|
126
135
|
|
|
@@ -271,7 +280,7 @@ async def host(
|
|
|
271
280
|
set_deferred(True)
|
|
272
281
|
|
|
273
282
|
for c in command.split(";"):
|
|
274
|
-
if execute_via_root(
|
|
283
|
+
if execute_via_root(cli_service, c, prog_name="meshagent") != 0:
|
|
275
284
|
print(f"[red]{c} failed[/red]")
|
|
276
285
|
raise typer.Exit(1)
|
|
277
286
|
|
|
@@ -306,12 +315,7 @@ async def join(
|
|
|
306
315
|
),
|
|
307
316
|
),
|
|
308
317
|
] = None,
|
|
309
|
-
room:
|
|
310
|
-
Optional[str],
|
|
311
|
-
typer.Option(
|
|
312
|
-
help="A room name to test the service in (must not be currently running)"
|
|
313
|
-
),
|
|
314
|
-
] = None,
|
|
318
|
+
room: RoomOption,
|
|
315
319
|
key: Annotated[
|
|
316
320
|
str,
|
|
317
321
|
typer.Option("--key", help="an api key to sign the token with"),
|
|
@@ -319,84 +323,35 @@ async def join(
|
|
|
319
323
|
):
|
|
320
324
|
set_deferred(True)
|
|
321
325
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
raise typer.Exit(1)
|
|
326
|
-
|
|
327
|
-
services_task = asyncio.create_task(run_services())
|
|
326
|
+
if room is None:
|
|
327
|
+
print("[bold red]--room is required[/bold red]")
|
|
328
|
+
raise typer.Exit(-1)
|
|
328
329
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
if port is None:
|
|
332
|
-
import socket
|
|
333
|
-
|
|
334
|
-
def find_free_port():
|
|
335
|
-
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
|
336
|
-
s.bind(("", 0)) # Bind to a free port provided by the host.
|
|
337
|
-
s.listen(1)
|
|
338
|
-
return s.getsockname()[1]
|
|
330
|
+
for c in command.split(";"):
|
|
331
|
+
execute_via_root(cli_join, c + f" --room={room}", prog_name="meshagent")
|
|
339
332
|
|
|
340
|
-
|
|
333
|
+
from meshagent.cli.host import agents
|
|
341
334
|
|
|
342
|
-
my_client = await get_client()
|
|
343
335
|
try:
|
|
344
|
-
project_id = await resolve_project_id(project_id)
|
|
345
|
-
room = resolve_room(room)
|
|
346
|
-
|
|
347
|
-
if room is None:
|
|
348
|
-
print("[bold red]Room was not set[/bold red]")
|
|
349
|
-
raise typer.Exit(1)
|
|
350
|
-
|
|
351
|
-
try:
|
|
352
|
-
parsed_key = parse_api_key(key)
|
|
353
|
-
token = ParticipantToken(
|
|
354
|
-
name="cli", project_id=project_id, api_key_id=parsed_key.id
|
|
355
|
-
)
|
|
356
|
-
token.add_api_grant(ApiScope.agent_default())
|
|
357
|
-
token.add_role_grant("user")
|
|
358
|
-
token.add_room_grant(room)
|
|
359
|
-
|
|
360
|
-
print("[bold green]Connecting to room...[/bold green]")
|
|
361
|
-
|
|
362
|
-
run_tasks = []
|
|
363
|
-
|
|
364
|
-
for spec in service_specs():
|
|
365
|
-
sys.stdout.write("\n")
|
|
366
|
-
|
|
367
|
-
for p in spec.ports:
|
|
368
|
-
print(f"[bold green]Connecting port {p.num}...[/bold green]")
|
|
369
|
-
|
|
370
|
-
for endpoint in p.endpoints:
|
|
371
|
-
print(
|
|
372
|
-
f"[bold green]Connecting endpoint {endpoint.path}...[/bold green]"
|
|
373
|
-
)
|
|
374
|
-
|
|
375
|
-
run_tasks.append(
|
|
376
|
-
asyncio.create_task(
|
|
377
|
-
_make_call(
|
|
378
|
-
room=room,
|
|
379
|
-
project_id=project_id,
|
|
380
|
-
participant_name=endpoint.meshagent.identity,
|
|
381
|
-
url=f"http://localhost:{p.num}{endpoint.path}",
|
|
382
|
-
arguments={},
|
|
383
|
-
key=key,
|
|
384
|
-
permissions=endpoint.meshagent.api,
|
|
385
|
-
)
|
|
386
|
-
)
|
|
387
|
-
)
|
|
388
|
-
|
|
389
|
-
await asyncio.gather(*run_tasks, services_task)
|
|
390
336
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
337
|
+
async def run_agent(agent: Agent, jwt: str):
|
|
338
|
+
nonlocal room
|
|
339
|
+
|
|
340
|
+
async with RoomClient(
|
|
341
|
+
protocol=WebSocketClientProtocol(
|
|
342
|
+
url=websocket_room_url(
|
|
343
|
+
room_name=room, base_url=meshagent_base_url()
|
|
344
|
+
),
|
|
345
|
+
token=jwt,
|
|
346
|
+
)
|
|
347
|
+
) as room:
|
|
348
|
+
await agent.start(room=room)
|
|
349
|
+
await room.protocol.wait_for_close()
|
|
350
|
+
await agent.stop()
|
|
351
|
+
|
|
352
|
+
await asyncio.gather(
|
|
353
|
+
*([asyncio.create_task(run_agent(agent, jwt)) for agent, jwt in agents])
|
|
354
|
+
)
|
|
400
355
|
|
|
401
|
-
|
|
402
|
-
|
|
356
|
+
except KeyboardInterrupt:
|
|
357
|
+
pass
|
meshagent/cli/oauth2.py
CHANGED
|
@@ -9,13 +9,29 @@ from meshagent.api import RoomClient, WebSocketClientProtocol
|
|
|
9
9
|
from meshagent.api.helpers import meshagent_base_url, websocket_room_url
|
|
10
10
|
from rich import print
|
|
11
11
|
from typing import Annotated, Optional
|
|
12
|
+
from pathlib import Path
|
|
12
13
|
import typer
|
|
13
14
|
import json
|
|
15
|
+
import sys
|
|
14
16
|
|
|
15
17
|
app = async_typer.AsyncTyper(help="OAuth2 test commands")
|
|
16
18
|
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
def _read_bytes(*, input_path: str) -> bytes:
|
|
21
|
+
if input_path == "-":
|
|
22
|
+
return sys.stdin.buffer.read()
|
|
23
|
+
return Path(input_path).expanduser().resolve().read_bytes()
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _write_bytes(*, output_path: str, data: bytes) -> None:
|
|
27
|
+
if output_path == "-":
|
|
28
|
+
sys.stdout.buffer.write(data)
|
|
29
|
+
sys.stdout.buffer.flush()
|
|
30
|
+
return
|
|
31
|
+
Path(output_path).expanduser().resolve().write_bytes(data)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@app.async_command("oauth")
|
|
19
35
|
async def oauth2(
|
|
20
36
|
*,
|
|
21
37
|
project_id: ProjectIdOption,
|
|
@@ -80,39 +96,157 @@ async def oauth2(
|
|
|
80
96
|
await account_client.close()
|
|
81
97
|
|
|
82
98
|
|
|
99
|
+
@app.async_command("request")
|
|
100
|
+
async def secret_request(
|
|
101
|
+
*,
|
|
102
|
+
project_id: ProjectIdOption,
|
|
103
|
+
room: RoomOption,
|
|
104
|
+
from_participant_id: Annotated[
|
|
105
|
+
str,
|
|
106
|
+
typer.Option(..., help="Participant ID to request the secret from"),
|
|
107
|
+
],
|
|
108
|
+
url: Annotated[str, typer.Option(..., help="Secret URL identifier")],
|
|
109
|
+
mime_type: Annotated[
|
|
110
|
+
str, typer.Option("--type", help="Secret MIME type")
|
|
111
|
+
] = "application/octet-stream",
|
|
112
|
+
delegate_to: Annotated[
|
|
113
|
+
Optional[str],
|
|
114
|
+
typer.Option(help="Delegate secret to this participant name"),
|
|
115
|
+
] = None,
|
|
116
|
+
timeout: Annotated[int, typer.Option(help="Timeout in seconds")] = 300,
|
|
117
|
+
out: Annotated[
|
|
118
|
+
str,
|
|
119
|
+
typer.Option(
|
|
120
|
+
"--out",
|
|
121
|
+
"-o",
|
|
122
|
+
help="Output file path, or '-' for stdout",
|
|
123
|
+
),
|
|
124
|
+
] = "-",
|
|
125
|
+
):
|
|
126
|
+
"""Request a secret from another participant."""
|
|
127
|
+
|
|
128
|
+
account_client = await get_client()
|
|
129
|
+
try:
|
|
130
|
+
project_id = await resolve_project_id(project_id=project_id)
|
|
131
|
+
jwt_consumer = await account_client.connect_room(
|
|
132
|
+
project_id=project_id, room=room
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
async with RoomClient(
|
|
136
|
+
protocol=WebSocketClientProtocol(
|
|
137
|
+
url=websocket_room_url(room_name=room, base_url=meshagent_base_url()),
|
|
138
|
+
token=jwt_consumer.jwt,
|
|
139
|
+
)
|
|
140
|
+
) as consumer:
|
|
141
|
+
typer.echo(
|
|
142
|
+
f"Requesting secret from participant {from_participant_id}...",
|
|
143
|
+
err=True,
|
|
144
|
+
)
|
|
145
|
+
secret = await consumer.secrets.request_secret(
|
|
146
|
+
url=url,
|
|
147
|
+
type=mime_type,
|
|
148
|
+
timeout=timeout,
|
|
149
|
+
from_participant_id=from_participant_id,
|
|
150
|
+
delegate_to=delegate_to,
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
_write_bytes(output_path=out, data=secret)
|
|
154
|
+
if out != "-":
|
|
155
|
+
typer.echo(f"Wrote {len(secret)} bytes to {out}", err=True)
|
|
156
|
+
|
|
157
|
+
finally:
|
|
158
|
+
await account_client.close()
|
|
159
|
+
|
|
160
|
+
|
|
83
161
|
@app.async_command("get")
|
|
84
|
-
async def
|
|
162
|
+
async def secret_get(
|
|
85
163
|
*,
|
|
86
164
|
project_id: ProjectIdOption,
|
|
87
165
|
room: RoomOption,
|
|
166
|
+
secret_id: Annotated[str, typer.Option(..., help="Secret ID")],
|
|
88
167
|
delegated_to: Annotated[
|
|
89
|
-
str,
|
|
90
|
-
|
|
91
|
-
client_id: Annotated[str, typer.Option(..., help="OAuth client ID")],
|
|
92
|
-
authorization_endpoint: Annotated[
|
|
93
|
-
str, typer.Option(..., help="OAuth authorization endpoint URL")
|
|
94
|
-
],
|
|
95
|
-
token_endpoint: Annotated[str, typer.Option(..., help="OAuth token endpoint URL")],
|
|
96
|
-
scopes: Annotated[
|
|
97
|
-
Optional[str], typer.Option(help="Comma-separated OAuth scopes")
|
|
168
|
+
Optional[str],
|
|
169
|
+
typer.Option(help="Fetch a secret delegated to this participant name"),
|
|
98
170
|
] = None,
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
171
|
+
out: Annotated[
|
|
172
|
+
str,
|
|
173
|
+
typer.Option(
|
|
174
|
+
"--out",
|
|
175
|
+
"-o",
|
|
176
|
+
help="Output file path, or '-' for stdout",
|
|
177
|
+
),
|
|
178
|
+
] = "-",
|
|
106
179
|
):
|
|
107
|
-
"""
|
|
108
|
-
Run an OAuth2 request test between two participants in the same room.
|
|
109
|
-
One will act as the consumer, the other as the provider.
|
|
110
|
-
"""
|
|
180
|
+
"""Get a stored secret by secret id."""
|
|
111
181
|
|
|
112
182
|
account_client = await get_client()
|
|
113
183
|
try:
|
|
114
184
|
project_id = await resolve_project_id(project_id=project_id)
|
|
185
|
+
jwt_consumer = await account_client.connect_room(
|
|
186
|
+
project_id=project_id, room=room
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
async with RoomClient(
|
|
190
|
+
protocol=WebSocketClientProtocol(
|
|
191
|
+
url=websocket_room_url(room_name=room, base_url=meshagent_base_url()),
|
|
192
|
+
token=jwt_consumer.jwt,
|
|
193
|
+
)
|
|
194
|
+
) as consumer:
|
|
195
|
+
resp = await consumer.secrets.get_secret(
|
|
196
|
+
secret_id=secret_id,
|
|
197
|
+
delegated_to=delegated_to,
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
if resp is None:
|
|
201
|
+
typer.echo("Secret not found", err=True)
|
|
202
|
+
raise typer.Exit(1)
|
|
203
|
+
|
|
204
|
+
typer.echo(
|
|
205
|
+
f"Got secret name={resp.name} mime_type={resp.mime_type} bytes={len(resp.data)}",
|
|
206
|
+
err=True,
|
|
207
|
+
)
|
|
208
|
+
_write_bytes(output_path=out, data=resp.data)
|
|
209
|
+
if out != "-":
|
|
210
|
+
typer.echo(f"Wrote {len(resp.data)} bytes to {out}", err=True)
|
|
211
|
+
|
|
212
|
+
finally:
|
|
213
|
+
await account_client.close()
|
|
115
214
|
|
|
215
|
+
|
|
216
|
+
@app.async_command("set")
|
|
217
|
+
async def secret_set(
|
|
218
|
+
*,
|
|
219
|
+
project_id: ProjectIdOption,
|
|
220
|
+
room: RoomOption,
|
|
221
|
+
secret_id: Annotated[str, typer.Option(..., help="Secret ID")],
|
|
222
|
+
mime_type: Annotated[
|
|
223
|
+
Optional[str],
|
|
224
|
+
typer.Option("--type", help="Secret MIME type"),
|
|
225
|
+
] = None,
|
|
226
|
+
name: Annotated[
|
|
227
|
+
Optional[str],
|
|
228
|
+
typer.Option(help="Optional secret name"),
|
|
229
|
+
] = None,
|
|
230
|
+
delegated_to: Annotated[
|
|
231
|
+
Optional[str],
|
|
232
|
+
typer.Option(help="Store a secret delegated to this participant name"),
|
|
233
|
+
] = None,
|
|
234
|
+
input_path: Annotated[
|
|
235
|
+
str,
|
|
236
|
+
typer.Option(
|
|
237
|
+
"--in",
|
|
238
|
+
"-i",
|
|
239
|
+
help="Input file path, or '-' for stdin",
|
|
240
|
+
),
|
|
241
|
+
] = "-",
|
|
242
|
+
):
|
|
243
|
+
"""Set/store a secret (bytes from stdin or file)."""
|
|
244
|
+
|
|
245
|
+
secret_bytes = _read_bytes(input_path=input_path)
|
|
246
|
+
|
|
247
|
+
account_client = await get_client()
|
|
248
|
+
try:
|
|
249
|
+
project_id = await resolve_project_id(project_id=project_id)
|
|
116
250
|
jwt_consumer = await account_client.connect_room(
|
|
117
251
|
project_id=project_id, room=room
|
|
118
252
|
)
|
|
@@ -123,20 +257,15 @@ async def get(
|
|
|
123
257
|
token=jwt_consumer.jwt,
|
|
124
258
|
)
|
|
125
259
|
) as consumer:
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
authorization_endpoint=authorization_endpoint,
|
|
131
|
-
token_endpoint=token_endpoint,
|
|
132
|
-
scopes=scopes.split(",") if scopes is not None else scopes,
|
|
133
|
-
client_secret=client_secret,
|
|
134
|
-
no_pkce=not pkce,
|
|
135
|
-
),
|
|
260
|
+
await consumer.secrets.set_secret(
|
|
261
|
+
secret_id=secret_id,
|
|
262
|
+
type=mime_type,
|
|
263
|
+
name=name,
|
|
136
264
|
delegated_to=delegated_to,
|
|
265
|
+
data=secret_bytes,
|
|
137
266
|
)
|
|
138
267
|
|
|
139
|
-
|
|
268
|
+
typer.echo(f"Stored {len(secret_bytes)} bytes", err=True)
|
|
140
269
|
|
|
141
270
|
finally:
|
|
142
271
|
await account_client.close()
|
|
@@ -166,7 +295,7 @@ async def list(
|
|
|
166
295
|
token=jwt_consumer.jwt,
|
|
167
296
|
)
|
|
168
297
|
) as consumer:
|
|
169
|
-
secrets = await consumer.secrets.
|
|
298
|
+
secrets = await consumer.secrets.list_secrets()
|
|
170
299
|
output = []
|
|
171
300
|
for s in secrets:
|
|
172
301
|
output.append(s.model_dump(mode="json"))
|
|
@@ -205,7 +334,7 @@ async def delete(
|
|
|
205
334
|
token=jwt_consumer.jwt,
|
|
206
335
|
)
|
|
207
336
|
) as consumer:
|
|
208
|
-
await consumer.secrets.
|
|
337
|
+
await consumer.secrets.delete_secret(id=id, delegated_to=delegated_to)
|
|
209
338
|
print("deleted secret")
|
|
210
339
|
|
|
211
340
|
finally:
|
meshagent/cli/room.py
CHANGED
|
@@ -5,13 +5,16 @@ from meshagent.cli import agent
|
|
|
5
5
|
from meshagent.cli import messaging
|
|
6
6
|
from meshagent.cli import storage
|
|
7
7
|
from meshagent.cli import developer
|
|
8
|
-
from meshagent.cli import
|
|
8
|
+
from meshagent.cli import oauth2
|
|
9
9
|
from meshagent.cli import containers
|
|
10
10
|
|
|
11
|
+
from meshagent.cli import sync
|
|
12
|
+
|
|
13
|
+
|
|
11
14
|
app = async_typer.AsyncTyper(help="Operate within a room")
|
|
12
15
|
|
|
13
16
|
app.add_typer(agent.app, name="agents", help="Interact with agents and toolkits")
|
|
14
|
-
app.add_typer(
|
|
17
|
+
app.add_typer(oauth2.app, name="secrets", help="Manage secrets for your project")
|
|
15
18
|
app.add_typer(queue.app, name="queue", help="Use queues in a room")
|
|
16
19
|
app.add_typer(messaging.app, name="messaging", help="Send and receive messages")
|
|
17
20
|
app.add_typer(storage.app, name="storage", help="Manage storage for a room")
|
|
@@ -20,3 +23,4 @@ app.add_typer(database.app, name="database", help="Manage database tables in a r
|
|
|
20
23
|
app.add_typer(
|
|
21
24
|
containers.app, name="container", help="Manage containers and images in a room"
|
|
22
25
|
)
|
|
26
|
+
app.add_typer(sync.app, name="sync")
|