meshagent-cli 0.0.23__py3-none-any.whl → 0.0.25__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.

@@ -0,0 +1,78 @@
1
+
2
+ import typer
3
+ from rich import print
4
+ from typing import Annotated, Optional
5
+ import json
6
+ import aiohttp
7
+ from meshagent.api import RoomClient, ParticipantToken, WebSocketClientProtocol, RoomException
8
+ from meshagent.api.helpers import meshagent_base_url, websocket_room_url
9
+ from meshagent.api.services import send_webhook
10
+ from meshagent.cli import async_typer
11
+ from meshagent.cli.helper import get_client, print_json_table, set_active_project, resolve_project_id
12
+ from meshagent.cli.helper import set_active_project, get_active_project, resolve_project_id, resolve_api_key
13
+ from meshagent.agents.chat import ChatBot
14
+ from meshagent.openai import OpenAIResponsesAdapter
15
+ from typing import List
16
+
17
+ from meshagent.api import RequiredToolkit, RequiredSchema
18
+
19
+ app = async_typer.AsyncTyper()
20
+
21
+ @app.async_command("join")
22
+ async def make_call(
23
+ *,
24
+ project_id: str = None,
25
+ room: Annotated[str, typer.Option()],
26
+ api_key_id: Annotated[Optional[str], typer.Option()] = None,
27
+ name: Annotated[str, typer.Option(..., help="Participant name")] = "cli",
28
+ role: str = "agent",
29
+ agent_name: Annotated[str, typer.Option(..., help="Name of the agent to call")],
30
+ rule: Annotated[List[str], typer.Option("--rule", "-r", help="a system rule")] = [],
31
+ toolkit: Annotated[List[str], typer.Option("--toolkit", "-t", help="the name or url of a required toolkit")] = [],
32
+ schema: Annotated[List[str], typer.Option("--schema", "-s", help="the name or url of a required schema")] = []
33
+ ):
34
+ account_client = await get_client()
35
+ try:
36
+ project_id = await resolve_project_id(project_id=project_id)
37
+ api_key_id = await resolve_api_key(project_id, api_key_id)
38
+
39
+ key = (await account_client.decrypt_project_api_key(project_id=project_id, id=api_key_id))["token"]
40
+
41
+ token = ParticipantToken(
42
+ name=name,
43
+ project_id=project_id,
44
+ api_key_id=api_key_id
45
+ )
46
+ token.add_role_grant(role=role)
47
+ token.add_room_grant(room)
48
+
49
+
50
+ print("[bold green]Connecting to room...[/bold green]")
51
+ async with RoomClient(
52
+ protocol=WebSocketClientProtocol(url=websocket_room_url(room_name=room, base_url=meshagent_base_url()),
53
+ token=token.to_jwt(token=key))
54
+ ) as client:
55
+
56
+ requirements = []
57
+
58
+ for t in toolkit:
59
+ requirements.append(RequiredToolkit(name=t))
60
+
61
+ for t in schema:
62
+ requirements.append(RequiredSchema(name=t))
63
+
64
+ bot = ChatBot(
65
+ llm_adapter=OpenAIResponsesAdapter(),
66
+ name=agent_name,
67
+ requires=requirements,
68
+ rules=rule if len(rule) > 0 else None
69
+ )
70
+
71
+ await bot.start(room=client)
72
+ try:
73
+ await client.protocol.wait_for_close()
74
+ except KeyboardInterrupt:
75
+ await bot.stop()
76
+
77
+ finally:
78
+ await account_client.close()
meshagent/cli/cli.py CHANGED
@@ -14,6 +14,8 @@ from meshagent.cli import services
14
14
  from meshagent.cli import cli_secrets
15
15
  from meshagent.cli import call
16
16
  from meshagent.cli import cli_mcp
17
+ from meshagent.cli import chatbot
18
+ from meshagent.cli import voicebot
17
19
 
18
20
  app = typer.Typer()
19
21
  app.add_typer(call.app, name="call")
@@ -30,6 +32,8 @@ app.add_typer(webhook.app, name="webhook")
30
32
  app.add_typer(services.app, name="service")
31
33
  app.add_typer(cli_secrets.app, name="secret")
32
34
  app.add_typer(cli_mcp.app, name="mcp")
35
+ app.add_typer(chatbot.app, name="chatbot")
36
+ app.add_typer(voicebot.app, name="voicebot")
33
37
 
34
38
  if __name__ == "__main__":
35
39
  app()
meshagent/cli/cli_mcp.py CHANGED
@@ -60,8 +60,6 @@ async def sse(*, project_id: str = None, room: Annotated[str, typer.Option()], t
60
60
  finally:
61
61
  await account_client.close()
62
62
 
63
-
64
-
65
63
  @app.async_command("stdio")
66
64
  async def stdio(*, project_id: str = None, room: Annotated[str, typer.Option()], token_path: Annotated[Optional[str], typer.Option()] = None, api_key_id: Annotated[Optional[str], typer.Option()] = None, name: Annotated[str, typer.Option(..., help="Participant name")] = "cli", role: str = "tool", command: Annotated[str, typer.Option()]):
67
65
  account_client = await get_client()
@@ -128,7 +126,7 @@ async def stdio_host(*, command: Annotated[str, typer.Option()], host: Annotat
128
126
 
129
127
  if host == None:
130
128
 
131
- host = "localhost"
129
+ host = "0.0.0.0"
132
130
 
133
131
  service_host = ServiceHost(
134
132
  host=host,
meshagent/cli/services.py CHANGED
@@ -11,8 +11,8 @@ from pydantic import PositiveInt
11
11
  import pydantic
12
12
  from typing import Literal
13
13
  from meshagent.cli import async_typer
14
- from meshagent.cli.helper import get_client, print_json_table, resolve_project_id
15
-
14
+ from meshagent.cli.helper import get_client, print_json_table, resolve_project_id, resolve_api_key
15
+ from meshagent.api import ParticipantToken, RoomClient, WebSocketClientProtocol, websocket_protocol, websocket_room_url, meshagent_base_url
16
16
  # Pydantic basemodels
17
17
  from meshagent.api.accounts_client import Service, Port
18
18
 
@@ -56,7 +56,7 @@ def _parse_port_spec(spec: str) -> PortSpec:
56
56
  kv: Dict[str, str] = {}
57
57
  for t in tokens:
58
58
  if "=" not in t:
59
- raise typer.BadParameter(f"expected key=value, got '{t}'")
59
+ raise typer.BadParameter(f"expected num=PORT_NUMBER type=meshagent.callable|mcp.sse liveness=OPTIONAL_PATH, got '{t}'")
60
60
  k, v = t.split("=", 1)
61
61
  kv[k] = v
62
62
  try:
@@ -76,6 +76,7 @@ async def service_create(
76
76
  project_id: str = None,
77
77
  name: Annotated[str, typer.Option(help="Friendly service name")],
78
78
  image: Annotated[str, typer.Option(help="Container image reference")],
79
+ role: Annotated[str, typer.Option(help="Service role (agent|tool)")],
79
80
  pull_secret: Annotated[
80
81
  Optional[str],
81
82
  typer.Option("--pull-secret", help="Secret ID for registry"),
@@ -124,6 +125,7 @@ async def service_create(
124
125
  id="",
125
126
  created_at=datetime.now(timezone.utc).isoformat(),
126
127
  name=name,
128
+ role=role,
127
129
  image=image,
128
130
  command=command,
129
131
  pull_secret=pull_secret,
@@ -150,6 +152,127 @@ async def service_create(
150
152
  await client.close()
151
153
 
152
154
 
155
+ @app.async_command("test")
156
+ async def service_test(
157
+ *,
158
+ project_id: str = None,
159
+ api_key_id: Annotated[Optional[str], typer.Option()] = None,
160
+ room: Annotated[str, typer.Option(help="A room name to test the service in (must not be currently running)")],
161
+ name: Annotated[str, typer.Option(help="Friendly service name")],
162
+ role: Annotated[str, typer.Option(help="Service role (agent|tool)")],
163
+ image: Annotated[str, typer.Option(help="Container image reference")],
164
+ pull_secret: Annotated[
165
+ Optional[str],
166
+ typer.Option("--pull-secret", help="Secret ID for registry"),
167
+ ] = None,
168
+ command: Annotated[
169
+ Optional[str],
170
+ typer.Option("--command", help="Override ENTRYPOINT/CMD"),
171
+ ] = None,
172
+ env: Annotated[List[str], typer.Option("--env", "-e", help="KEY=VALUE")] = [],
173
+ env_secret: Annotated[List[str], typer.Option("--env-secret")] = [],
174
+ runtime_secret: Annotated[List[str], typer.Option("--runtime-secret")] = [],
175
+ room_storage_path: Annotated[
176
+ Optional[str],
177
+ typer.Option("--mount", help="Path inside container to mount room storage"),
178
+ ] = None,
179
+ port: Annotated[
180
+ List[str],
181
+ typer.Option(
182
+ "--port",
183
+ "-p",
184
+ help=(
185
+ "Repeatable. Example:\n"
186
+ ' -p "num=8080 type=[mcp.sse | meshagent.callable | http | tcp] liveness=/health"'
187
+ ),
188
+ ),
189
+ ] = [],
190
+ timeout: Annotated[
191
+ Optional[int],
192
+ typer.Option("--timeout", help="The maximum time that this room should run (default 1hr)"),
193
+ ] = None,
194
+ ):
195
+
196
+
197
+ """Create a service attached to the project."""
198
+ client = await get_client()
199
+ try:
200
+ project_id = await resolve_project_id(project_id)
201
+
202
+ api_key_id = await resolve_api_key(project_id, api_key_id)
203
+
204
+ # ✅ validate / coerce port specs
205
+ port_specs: List[PortSpec] = [_parse_port_spec(s) for s in port]
206
+
207
+ ports_dict = {
208
+ ps.num: Port(
209
+ type=ps.type,
210
+ liveness=ps.liveness,
211
+ participant_name=ps.participant_name,
212
+ )
213
+ for ps in port_specs
214
+ } or None
215
+
216
+ service_obj = Service(
217
+ id="",
218
+ created_at=datetime.now(timezone.utc).isoformat(),
219
+ role=role,
220
+ name=name,
221
+ image=image,
222
+ command=command,
223
+ pull_secret=pull_secret,
224
+ room_storage_path=room_storage_path,
225
+ environment=_kv_to_dict(env),
226
+ environment_secrets=env_secret or None,
227
+ runtime_secrets=_kv_to_dict(runtime_secret),
228
+ ports=ports_dict,
229
+ )
230
+
231
+ try:
232
+ token = ParticipantToken(
233
+ name=name,
234
+ project_id=project_id,
235
+ api_key_id=api_key_id
236
+ )
237
+ token.add_role_grant("user")
238
+ token.add_room_grant(room)
239
+ token.extra_payload = {
240
+ "max_runtime_seconds" : timeout, # run for 1 hr max
241
+ "meshagent_dev_services" : [
242
+ service_obj.model_dump(mode="json")
243
+ ]
244
+ }
245
+
246
+ print("[bold green]Connecting to room...[/bold green]")
247
+
248
+ key = (await client.decrypt_project_api_key(project_id=project_id, id=api_key_id))["token"]
249
+
250
+ async with RoomClient(
251
+ protocol=WebSocketClientProtocol(
252
+ url=websocket_room_url(room_name=room, base_url=meshagent_base_url()),
253
+ token=token.to_jwt(token=key)
254
+ )
255
+ ) as client:
256
+
257
+ print(f"[green]Started room: {room}[/green]")
258
+ try:
259
+ await client.protocol.wait_for_close()
260
+ except KeyboardInterrupt:
261
+ pass
262
+
263
+
264
+ except ClientResponseError as exc:
265
+ if exc.status == 409:
266
+ print(f"[red]Room already in use: {room}[/red]")
267
+ raise typer.Exit(code=1)
268
+ raise
269
+
270
+
271
+ finally:
272
+ await client.close()
273
+
274
+
275
+
153
276
  @app.async_command("show")
154
277
  async def service_show(
155
278
  *,
@@ -181,6 +304,7 @@ async def service_list(*, project_id: str = None):
181
304
  [svc.model_dump(mode="json") for svc in services],
182
305
  "id",
183
306
  "name",
307
+ "role",
184
308
  "image",
185
309
  "command",
186
310
  "room_storage_path",
meshagent/cli/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.0.23"
1
+ __version__ = "0.0.25"
@@ -0,0 +1,80 @@
1
+
2
+ import typer
3
+ from rich import print
4
+ from typing import Annotated, Optional
5
+ import json
6
+ import aiohttp
7
+ from meshagent.api import RoomClient, ParticipantToken, WebSocketClientProtocol, RoomException
8
+ from meshagent.api.helpers import meshagent_base_url, websocket_room_url
9
+ from meshagent.api.services import send_webhook
10
+ from meshagent.cli import async_typer
11
+ from meshagent.cli.helper import get_client, print_json_table, set_active_project, resolve_project_id
12
+ from meshagent.cli.helper import set_active_project, get_active_project, resolve_project_id, resolve_api_key
13
+ from meshagent.livekit.agents.voice import Voicebot
14
+ from meshagent.openai import OpenAIResponsesAdapter
15
+ from typing import List
16
+
17
+ from meshagent.api import RequiredToolkit, RequiredSchema
18
+
19
+ app = async_typer.AsyncTyper()
20
+
21
+ @app.async_command("join")
22
+ async def make_call(
23
+ *,
24
+ project_id: str = None,
25
+ room: Annotated[str, typer.Option()],
26
+ api_key_id: Annotated[Optional[str], typer.Option()] = None,
27
+ name: Annotated[str, typer.Option(..., help="Participant name")] = "cli",
28
+ role: str = "agent",
29
+ agent_name: Annotated[str, typer.Option(..., help="Name of the agent to call")],
30
+ rule: Annotated[List[str], typer.Option("--rule", "-r", help="a system rule")] = [],
31
+ toolkit: Annotated[List[str], typer.Option("--toolkit", "-t", help="the name or url of a required toolkit")] = [],
32
+ schema: Annotated[List[str], typer.Option("--schema", "-s", help="the name or url of a required schema")] = [],
33
+ greeting: Annotated[Optional[str], typer.Option()] = None,
34
+ ):
35
+ account_client = await get_client()
36
+ try:
37
+ project_id = await resolve_project_id(project_id=project_id)
38
+ api_key_id = await resolve_api_key(project_id, api_key_id)
39
+
40
+ key = (await account_client.decrypt_project_api_key(project_id=project_id, id=api_key_id))["token"]
41
+
42
+ token = ParticipantToken(
43
+ name=name,
44
+ project_id=project_id,
45
+ api_key_id=api_key_id
46
+ )
47
+ token.add_role_grant(role=role)
48
+ token.add_room_grant(room)
49
+
50
+
51
+ print("[bold green]Connecting to room...[/bold green]")
52
+ async with RoomClient(
53
+ protocol=WebSocketClientProtocol(url=websocket_room_url(room_name=room, base_url=meshagent_base_url()),
54
+ token=token.to_jwt(token=key))
55
+ ) as client:
56
+
57
+ requirements = []
58
+
59
+ for t in toolkit:
60
+ requirements.append(RequiredToolkit(name=t))
61
+
62
+ for t in schema:
63
+ requirements.append(RequiredSchema(name=t))
64
+
65
+ bot = Voicebot(
66
+ greeting=greeting,
67
+ name=agent_name,
68
+ requires=requirements,
69
+ rules=rule if len(rule) > 0 else None
70
+ )
71
+
72
+ await bot.start(room=client)
73
+
74
+ try:
75
+ await client.protocol.wait_for_close()
76
+ except KeyboardInterrupt:
77
+ await bot.stop()
78
+
79
+ finally:
80
+ await account_client.close()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshagent-cli
3
- Version: 0.0.23
3
+ Version: 0.0.25
4
4
  Summary: CLI for Meshagent
5
5
  License-Expression: Apache-2.0
6
6
  Project-URL: Documentation, https://docs.meshagent.com
@@ -10,10 +10,10 @@ Requires-Python: >=3.12
10
10
  Description-Content-Type: text/markdown
11
11
  Requires-Dist: typer~=0.15.3
12
12
  Requires-Dist: pydantic-yaml~=1.4.0
13
- Requires-Dist: meshagent-api~=0.0.23
14
- Requires-Dist: meshagent-agents~=0.0.23
15
- Requires-Dist: meshagent-tools~=0.0.23
16
- Requires-Dist: meshagent-mcp~=0.0.23
13
+ Requires-Dist: meshagent-api~=0.0.25
14
+ Requires-Dist: meshagent-agents~=0.0.25
15
+ Requires-Dist: meshagent-tools~=0.0.25
16
+ Requires-Dist: meshagent-mcp~=0.0.25
17
17
  Requires-Dist: supabase~=2.15.1
18
18
 
19
19
  ### Meshagent CLI
@@ -5,21 +5,23 @@ meshagent/cli/async_typer.py,sha256=GCeSefBDbpd-V4V8LrvHGUTBMth3HspVMfFa-HUZ0cg,
5
5
  meshagent/cli/auth.py,sha256=24UrVTvrlDfmGeLrG7oT7jTwM77296bdKVQ_egc3IAo,766
6
6
  meshagent/cli/auth_async.py,sha256=LArKxTxQAPmItv0JaGkW3Ybutl6MVmb6_EeSjI18IbI,4001
7
7
  meshagent/cli/call.py,sha256=M8oMo-hsYIzQzMF0OMNdJuoYCjDwtYUtdV1hCwZs0co,4610
8
- meshagent/cli/cli.py,sha256=y1zXBLeb1xFDgAh9SwwpjBaOdNQe1gJO6Kdmgm5-gO4,1181
9
- meshagent/cli/cli_mcp.py,sha256=fYkRcWeTYRNTqAHRZzFDGDsXOWlfyUILMU-qrJXcOBU,6834
8
+ meshagent/cli/chatbot.py,sha256=ylW_jSvY1OWDs7LPsyEIz8-x_BaInnIgmpcQZqwOdmg,3016
9
+ meshagent/cli/cli.py,sha256=G7RAwd3LzS4LHpvyCD51XS0vjwR2Ml7feUfBP2VdwUs,1338
10
+ meshagent/cli/cli_mcp.py,sha256=rHU5rZFJMPiYRWMHvrQub15gIqAuLDS979Q-fMJJ2BU,6830
10
11
  meshagent/cli/cli_secrets.py,sha256=U0kdzN3zt7JIqzdRLynAjxdvAsI0enesBd_m7TeXjnQ,13629
11
12
  meshagent/cli/developer.py,sha256=5eoDr3kfi-IufA5d6OESqNr739Bdut_IFBtT3nq0xZU,3002
12
13
  meshagent/cli/helper.py,sha256=hcY6C5BqGnYmwFVIG7nS9NPIZXbdpOoEna-t0mYmHGY,4632
13
14
  meshagent/cli/messaging.py,sha256=cU6LIK6gwOveLo_x2x3iWW5rC4MhDpwp2hvehAkvybI,6068
14
15
  meshagent/cli/participant_token.py,sha256=uCGmlUgNOfarYGkDZpzreXwnv9AJrM76tu5Lt690vYU,1456
15
16
  meshagent/cli/projects.py,sha256=Tut8kRCVvgdWzlAR1Zqf0QxAi4sNfQEIHY9zxfS1nuI,1100
16
- meshagent/cli/services.py,sha256=p6s1IlKqVBCbI270IAjaoGc0sgVTHdHo0IZXm8CxYO4,6588
17
+ meshagent/cli/services.py,sha256=t-ipIpCbEq2TbNc6wm0cvxS2yj1iynx_KKi7PYYTkiQ,11032
17
18
  meshagent/cli/sessions.py,sha256=WWvuztYqRfthSq6ztwL_eQ_sz9JRc33jcN6p7YyM_Fs,782
18
19
  meshagent/cli/storage.py,sha256=BsagaJfThrUWqXFyAk9IvQtUuDAMckE2mffZ_peozMo,33555
19
- meshagent/cli/version.py,sha256=CO0VmekjZ_r8LBYVaUXTM3i08rEVwYKhjb9sy0X7vz0,23
20
+ meshagent/cli/version.py,sha256=ognSasPrsQjE8uJUk5Fcsl4caTERui00vZnmFlQnMoU,23
21
+ meshagent/cli/voicebot.py,sha256=SYFkh1tt_M438zBazsU9_yFodPwwAzIT5z3i-NgjG5E,3073
20
22
  meshagent/cli/webhook.py,sha256=KBl8U1TcOX3z2uoyH4YMuUuw0vSVX7xpRxYvzxI5c-Y,2811
21
- meshagent_cli-0.0.23.dist-info/METADATA,sha256=-RP4HkPhX8aaLsZzZUVJT8Htu31g0HsW_nTENIgNMg4,605
22
- meshagent_cli-0.0.23.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
23
- meshagent_cli-0.0.23.dist-info/entry_points.txt,sha256=WRcGGN4vMtvC5Pgl3uRFqsJiQXNoHuLLa-TCSY3gAhQ,52
24
- meshagent_cli-0.0.23.dist-info/top_level.txt,sha256=GlcXnHtRP6m7zlG3Df04M35OsHtNXy_DY09oFwWrH74,10
25
- meshagent_cli-0.0.23.dist-info/RECORD,,
23
+ meshagent_cli-0.0.25.dist-info/METADATA,sha256=3O7TWiNlUMRlvXmgaHnwwhCpv5IvcolV39MpnUei9Ns,605
24
+ meshagent_cli-0.0.25.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
25
+ meshagent_cli-0.0.25.dist-info/entry_points.txt,sha256=WRcGGN4vMtvC5Pgl3uRFqsJiQXNoHuLLa-TCSY3gAhQ,52
26
+ meshagent_cli-0.0.25.dist-info/top_level.txt,sha256=GlcXnHtRP6m7zlG3Df04M35OsHtNXy_DY09oFwWrH74,10
27
+ meshagent_cli-0.0.25.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.8.0)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5