meshagent-cli 0.0.30__py3-none-any.whl → 0.0.31__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/api_keys.py CHANGED
@@ -56,16 +56,72 @@ async def show(*, project_id: str = None, api_key_id: str):
56
56
 
57
57
 
58
58
  @app.async_command("activate")
59
- async def activate(api_key_id: str, project_id: str = None,):
59
+ async def activate(
60
+ api_key_id: str | None = typer.Argument(None),
61
+ project_id: str = None,
62
+ interactive: bool = typer.Option(
63
+ False,
64
+ "-i",
65
+ "--interactive",
66
+ help="Interactively select or create an api key",
67
+ ),
68
+ ):
60
69
  client = await get_client()
61
70
  try:
62
71
  project_id = await resolve_project_id(project_id)
72
+ if interactive:
73
+ response = await client.list_project_api_keys(project_id=project_id)
74
+ api_keys = response["keys"]
75
+
76
+ if not api_keys:
77
+ if typer.confirm(
78
+ "There are no API keys. Would you like to create one?",
79
+ default=True,
80
+ ):
81
+ name = typer.prompt("API key name")
82
+ created = await client.create_project_api_key(
83
+ project_id=project_id,
84
+ name=name,
85
+ description="",
86
+ )
87
+ api_key_id = created["id"]
88
+ else:
89
+ raise typer.Exit(code=0)
90
+ else:
91
+ for idx, key in enumerate(api_keys, start=1):
92
+ print(f"[{idx}] {key['name']} ({key['id']})")
93
+ new_key_index = len(api_keys) + 1
94
+ print(f"[{new_key_index}] Create a new api key")
95
+ exit_index = new_key_index + 1
96
+ print(f"[{exit_index}] Exit")
97
+
98
+ choice = typer.prompt("Select an api key", type=int)
99
+ if choice == exit_index:
100
+ return
101
+ elif choice == new_key_index:
102
+ name = typer.prompt("API key name")
103
+ created = await client.create_project_api_key(
104
+ project_id=project_id,
105
+ name=name,
106
+ description="",
107
+ )
108
+ api_key_id = created["id"]
109
+ elif 1 <= choice <= len(api_keys):
110
+ api_key_id = api_keys[choice - 1]["id"]
111
+ else:
112
+ print("[red]Invalid selection[/red]")
113
+ raise typer.Exit(code=1)
114
+
115
+ if api_key_id is None and not interactive:
116
+ print("[red]api_key_id required[/red]")
117
+ raise typer.Exit(code=1)
118
+
63
119
  response = await client.list_project_api_keys(project_id=project_id)
64
120
  api_keys = response["keys"]
65
121
  for api_key in api_keys:
66
122
  if api_key["id"] == api_key_id:
67
123
  await set_active_api_key(project_id=project_id, api_key_id=api_key_id)
68
- return
124
+ return api_key_id
69
125
 
70
126
  print(f"[red]Invalid api key id or project id: {project_id}[/red]")
71
127
  raise typer.Exit(code=1)
meshagent/cli/auth.py CHANGED
@@ -16,7 +16,7 @@ async def login():
16
16
  print('You have been logged in, but you haven''t activated a project yet, list your projects with "meshagent project list" and then activate one with "meshagent project activate PROJECT_ID"')
17
17
 
18
18
  @app.async_command("logout")
19
- async def login():
19
+ async def logout():
20
20
  await auth_async.logout()
21
21
 
22
22
  @app.async_command("whoami")
meshagent/cli/call.py CHANGED
@@ -62,8 +62,9 @@ def is_local_url(url: str) -> bool:
62
62
 
63
63
 
64
64
  @app.async_command("schema")
65
- @app.async_command("tool")
65
+ @app.async_command("toolkit")
66
66
  @app.async_command("agent")
67
+ @app.async_command("tool")
67
68
  async def make_call(
68
69
  *,
69
70
  project_id: str = None,
meshagent/cli/cli.py CHANGED
@@ -1,4 +1,5 @@
1
1
  import typer
2
+ import asyncio
2
3
 
3
4
  from meshagent.cli import auth
4
5
  from meshagent.cli import api_keys
@@ -16,6 +17,7 @@ from meshagent.cli import call
16
17
  from meshagent.cli import cli_mcp
17
18
  from meshagent.cli import chatbot
18
19
  from meshagent.cli import voicebot
20
+ from meshagent.cli import tty
19
21
 
20
22
  app = typer.Typer()
21
23
  app.add_typer(call.app, name="call")
@@ -34,6 +36,28 @@ app.add_typer(cli_secrets.app, name="secret")
34
36
  app.add_typer(cli_mcp.app, name="mcp")
35
37
  app.add_typer(chatbot.app, name="chatbot")
36
38
  app.add_typer(voicebot.app, name="voicebot")
39
+ app.add_typer(tty.app, name="tty")
40
+
41
+ def _run_async(coro):
42
+ asyncio.run(coro)
43
+
44
+ @app.command("setup")
45
+ def setup_command():
46
+ """Perform initial login and project/api key activation."""
47
+
48
+ async def runner():
49
+ await auth.login()
50
+ print("Activate a project...")
51
+ project_id = await projects.activate(None, interactive=True)
52
+ if project_id is None:
53
+ print("You have choosen to not activate a project. Exiting.")
54
+ if project_id is not None:
55
+ print("Activate an api-key...")
56
+ api_key_id = await api_keys.activate(None, interactive=True)
57
+ if api_key_id is None:
58
+ print("You have choosen to not activate an api-key. Exiting.")
59
+
60
+ _run_async(runner())
37
61
 
38
62
  if __name__ == "__main__":
39
63
  app()
meshagent/cli/cli_mcp.py CHANGED
@@ -22,7 +22,6 @@ from meshagent.api.services import ServiceHost
22
22
  import os
23
23
 
24
24
  from meshagent.cli.services import _kv_to_dict
25
-
26
25
  import shlex
27
26
 
28
27
  app = async_typer.AsyncTyper()
@@ -107,10 +106,55 @@ async def stdio(*, project_id: str = None, room: Annotated[str, typer.Option()],
107
106
  finally:
108
107
  await account_client.close()
109
108
 
109
+ @app.async_command("http-proxy")
110
+ async def stdio_host(*, command: Annotated[str, typer.Option()], host: Annotated[Optional[str], typer.Option()] = None, port: Annotated[Optional[int], typer.Option()] = None, path: Annotated[Optional[str], typer.Option()] = None, name: Annotated[Optional[str], typer.Option()] = None, env: Annotated[List[str], typer.Option("--env", "-e", help="KEY=VALUE")] = []):
110
111
 
111
- @app.async_command("stdio-service")
112
- async def stdio_host(*, command: Annotated[str, typer.Option()], host: Annotated[Optional[str], typer.Option()] = None, port: Annotated[Optional[int], typer.Option()] = None, webhook_secret: Annotated[Optional[str], typer.Option()] = None, path: Annotated[Optional[str], typer.Option()] = None, toolkit_name: Annotated[Optional[str], typer.Option()] = None, env: Annotated[List[str], typer.Option("--env", "-e", help="KEY=VALUE")] = []):
112
+ from fastmcp import FastMCP, Client
113
+ from fastmcp.client.transports import StdioTransport
114
+
115
+ parsed_command = shlex.split(command)
116
+
117
+ # Create a client that connects to the original server
118
+ proxy_client = Client(
119
+ transport = StdioTransport(parsed_command[0], parsed_command[1:], _kv_to_dict(env)),
120
+ )
121
+
122
+ if name == None:
123
+ name = "Stdio-to-Streamable Http Proxy"
124
+
125
+ # Create a proxy server that connects to the client and exposes its capabilities
126
+ proxy = FastMCP.as_proxy(proxy_client, name=name)
127
+ if path == None:
128
+ path = "/mcp"
129
+
130
+ await proxy.run_async(transport='streamable-http', host=host, port=port, path=path)
131
+
132
+
133
+ @app.async_command("sse-proxy")
134
+ async def stdio_host(*, command: Annotated[str, typer.Option()], host: Annotated[Optional[str], typer.Option()] = None, port: Annotated[Optional[int], typer.Option()] = None, path: Annotated[Optional[str], typer.Option()] = None, name: Annotated[Optional[str], typer.Option()] = None, env: Annotated[List[str], typer.Option("--env", "-e", help="KEY=VALUE")] = []):
135
+
136
+ from fastmcp import FastMCP, Client
137
+ from fastmcp.client.transports import StdioTransport
138
+
139
+ parsed_command = shlex.split(command)
113
140
 
141
+ # Create a client that connects to the original server
142
+ proxy_client = Client(
143
+ transport = StdioTransport(parsed_command[0], parsed_command[1:], _kv_to_dict(env)),
144
+ )
145
+
146
+ if name == None:
147
+ name = "Stdio-to-SSE Proxy"
148
+
149
+ # Create a proxy server that connects to the client and exposes its capabilities
150
+ proxy = FastMCP.as_proxy(proxy_client, name=name)
151
+ if path == None:
152
+ path = "/sse"
153
+
154
+ await proxy.run_async(transport='sse', host=host, port=port, path=path)
155
+
156
+ @app.async_command("stdio-service")
157
+ async def stdio_host(*, command: Annotated[str, typer.Option()], host: Annotated[Optional[str], typer.Option()] = None, port: Annotated[Optional[int], typer.Option()] = None, webhook_secret: Annotated[Optional[str], typer.Option()] = None, path: Annotated[Optional[str], typer.Option()] = None, toolkit_name: Annotated[Optional[str], typer.Option()] = None, env: Annotated[List[str], typer.Option("--env", "-e", help="KEY=VALUE")] = []):
114
158
  try:
115
159
 
116
160
  parsed_command = shlex.split(command)
meshagent/cli/projects.py CHANGED
@@ -1,11 +1,25 @@
1
1
  import typer
2
2
  from rich import print
3
3
  from meshagent.cli import async_typer
4
- from meshagent.cli.helper import get_client, print_json_table, set_active_project, get_active_project
4
+ from meshagent.cli.helper import (
5
+ get_client,
6
+ print_json_table,
7
+ set_active_project,
8
+ get_active_project,
9
+ )
5
10
 
6
11
  app = async_typer.AsyncTyper()
7
12
 
8
13
 
14
+ @app.async_command("create")
15
+ async def create(name: str):
16
+ client = await get_client()
17
+ try:
18
+ result = await client.create_project(name)
19
+ print(f"[green]Project created:[/] {result["id"]}")
20
+ finally:
21
+ await client.close()
22
+
9
23
  @app.async_command("list")
10
24
  async def list():
11
25
  client = await get_client()
@@ -19,18 +33,66 @@ async def list():
19
33
  await client.close()
20
34
 
21
35
  @app.async_command("activate")
22
- async def activate(project_id: str):
36
+ async def activate(
37
+ project_id: str | None = typer.Argument(None),
38
+ interactive: bool = typer.Option(
39
+ False,
40
+ "-i",
41
+ "--interactive",
42
+ help="Interactively select or create a project",
43
+ ),
44
+ ):
23
45
  client = await get_client()
24
46
  try:
25
- projects = await client.list_projects()
26
- projects = projects["projects"]
27
- for project in projects:
28
- if project["id"] == project_id:
29
- await set_active_project(project_id=project_id)
30
- return
31
-
32
- print(f"[red]Invalid project id: {project_id}[/red]")
33
- raise typer.Exit(code=1)
47
+ if interactive:
48
+ response = await client.list_projects()
49
+ projects = response["projects"]
50
+
51
+ if not projects:
52
+ if typer.confirm(
53
+ "There are no projects. Would you like to create one?",
54
+ default=True,
55
+ ):
56
+ name = typer.prompt("Project name")
57
+ created = await client.create_project(name)
58
+ project_id = created["id"]
59
+ else:
60
+ raise typer.Exit(code=0)
61
+ else:
62
+ for idx, proj in enumerate(projects, start=1):
63
+ print(f"[{idx}] {proj['name']} ({proj['id']})")
64
+ new_project_index = len(projects) + 1
65
+ print(f"[{new_project_index}] Create a new project")
66
+ exit_index = new_project_index + 1
67
+ print(f"[{exit_index}] Exit")
68
+
69
+ choice = typer.prompt("Select a project", type=int)
70
+ if choice == exit_index:
71
+ return
72
+ elif choice == new_project_index:
73
+ name = typer.prompt("Project name")
74
+ # TODO: validate name
75
+ created = await client.create_project(name)
76
+ project_id = created["id"]
77
+ elif 1 <= choice <= len(projects):
78
+ project_id = projects[choice - 1]["id"]
79
+ else:
80
+ print("[red]Invalid selection[/red]")
81
+ raise typer.Exit(code=1)
82
+
83
+ if project_id is None and not interactive:
84
+ print("[red]project_id required[/red]")
85
+ raise typer.Exit(code=1)
86
+
87
+ if project_id is not None:
88
+ projects = (await client.list_projects())["projects"]
89
+ for project in projects:
90
+ if project["id"] == project_id:
91
+ await set_active_project(project_id=project_id)
92
+ return project_id
93
+
94
+ print(f"[red]Invalid project id: {project_id}[/red]")
95
+ raise typer.Exit(code=1)
34
96
  finally:
35
97
  await client.close()
36
98
 
meshagent/cli/services.py CHANGED
@@ -15,6 +15,7 @@ from meshagent.cli.helper import get_client, print_json_table, resolve_project_i
15
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
+ from meshagent.cloud.accounts import Services
18
19
 
19
20
  app = async_typer.AsyncTyper()
20
21
 
@@ -38,13 +39,14 @@ class PortSpec(pydantic.BaseModel):
38
39
  """
39
40
  CLI schema for --port.
40
41
  Example:
41
- --port num=8080 type=webserver liveness=/health path=path
42
+ --port num=8080 type=webserver liveness=/health path=/agent participant_name=myname
42
43
  """
43
44
 
44
45
  num: PositiveInt
45
46
  type: Literal["mcp.sse", "meshagent.callable", "http", "tcp"]
46
47
  liveness: str | None = None
47
48
  participant_name: str | None = None
49
+ path: str | None = None
48
50
 
49
51
 
50
52
  def _parse_port_spec(spec: str) -> PortSpec:
@@ -76,7 +78,7 @@ async def service_create(
76
78
  project_id: str = None,
77
79
  name: Annotated[str, typer.Option(help="Friendly service name")],
78
80
  image: Annotated[str, typer.Option(help="Container image reference")],
79
- role: Annotated[str, typer.Option(help="Service role (agent|tool)")],
81
+ role: Annotated[str, typer.Option(help="Service role (agent|tool)")] = None,
80
82
  pull_secret: Annotated[
81
83
  Optional[str],
82
84
  typer.Option("--pull-secret", help="Secret ID for registry"),
@@ -99,10 +101,10 @@ async def service_create(
99
101
  "-p",
100
102
  help=(
101
103
  "Repeatable. Example:\n"
102
- ' -p "num=8080 type=[mcp.sse | meshagent.callable | http | tcp] liveness=/health"'
104
+ ' -p "num=8080 type=[mcp.sse | meshagent.callable | http | tcp] liveness=/health path=/agent participant_name=myname"'
103
105
  ),
104
106
  ),
105
- ] = [],
107
+ ] = ...,
106
108
  ):
107
109
  """Create a service attached to the project."""
108
110
  client = await get_client()
@@ -117,6 +119,7 @@ async def service_create(
117
119
  type=ps.type,
118
120
  liveness_path=ps.liveness,
119
121
  participant_name=ps.participant_name,
122
+ path=ps.path,
120
123
  )
121
124
  for ps in port_specs
122
125
  } or None
@@ -159,7 +162,7 @@ async def service_test(
159
162
  api_key_id: Annotated[Optional[str], typer.Option()] = None,
160
163
  room: Annotated[str, typer.Option(help="A room name to test the service in (must not be currently running)")],
161
164
  name: Annotated[str, typer.Option(help="Friendly service name")],
162
- role: Annotated[str, typer.Option(help="Service role (agent|tool)")],
165
+ role: Annotated[str, typer.Option(help="Service role (agent|tool)")] = None,
163
166
  image: Annotated[str, typer.Option(help="Container image reference")],
164
167
  pull_secret: Annotated[
165
168
  Optional[str],
@@ -183,10 +186,10 @@ async def service_test(
183
186
  "-p",
184
187
  help=(
185
188
  "Repeatable. Example:\n"
186
- ' -p "num=8080 type=[mcp.sse | meshagent.callable | http | tcp] liveness=/health"'
189
+ ' -p "num=8080 type=[mcp.sse | meshagent.callable | http | tcp] liveness=/health path=/agent participant_name=myname"'
187
190
  ),
188
191
  ),
189
- ] = [],
192
+ ] = ...,
190
193
  timeout: Annotated[
191
194
  Optional[int],
192
195
  typer.Option("--timeout", help="The maximum time that this room should run (default 1hr)"),
@@ -195,7 +198,7 @@ async def service_test(
195
198
 
196
199
 
197
200
  """Create a service attached to the project."""
198
- client = await get_client()
201
+ my_client = await get_client()
199
202
  try:
200
203
  project_id = await resolve_project_id(project_id)
201
204
 
@@ -209,6 +212,7 @@ async def service_test(
209
212
  type=ps.type,
210
213
  liveness_path=ps.liveness,
211
214
  participant_name=ps.participant_name,
215
+ path=ps.path,
212
216
  )
213
217
  for ps in port_specs
214
218
  } or None
@@ -245,7 +249,7 @@ async def service_test(
245
249
 
246
250
  print("[bold green]Connecting to room...[/bold green]")
247
251
 
248
- key = (await client.decrypt_project_api_key(project_id=project_id, id=api_key_id))["token"]
252
+ key = (await my_client.decrypt_project_api_key(project_id=project_id, id=api_key_id))["token"]
249
253
 
250
254
  async with RoomClient(
251
255
  protocol=WebSocketClientProtocol(
@@ -254,11 +258,7 @@ async def service_test(
254
258
  )
255
259
  ) as client:
256
260
 
257
- print(f"[green]Started room: {room}[/green]")
258
- try:
259
- await client.protocol.wait_for_close()
260
- except KeyboardInterrupt:
261
- pass
261
+ print(f"[green]Your test room '{room}' has been started. It will time out after a few minutes if you do not join it.[/green]")
262
262
 
263
263
 
264
264
  except ClientResponseError as exc:
@@ -269,7 +269,7 @@ async def service_test(
269
269
 
270
270
 
271
271
  finally:
272
- await client.close()
272
+ await my_client.close()
273
273
 
274
274
 
275
275
 
@@ -292,7 +292,7 @@ async def service_show(
292
292
 
293
293
 
294
294
  @app.async_command("list")
295
- async def service_list(*, project_id: str = None):
295
+ async def service_list(*, project_id: str = None, o: Annotated[str, typer.Option(help="output format [json|table]")]):
296
296
  """List all services for the project."""
297
297
  client = await get_client()
298
298
  try:
@@ -300,18 +300,16 @@ async def service_list(*, project_id: str = None):
300
300
  services: list[Service] = await client.list_services(
301
301
  project_id=project_id
302
302
  ) # → List[Service]
303
- print_json_table(
304
- [svc.model_dump(mode="json") for svc in services],
305
- "id",
306
- "name",
307
- "role",
308
- "image",
309
- "command",
310
- "room_storage_path",
311
- "pull_secret",
312
- "environment_secrets",
313
- "ports",
314
- )
303
+
304
+ if o == "json":
305
+ print(Services(services=services).model_dump_json(indent=2))
306
+ else:
307
+ print_json_table(
308
+ [svc.model_dump(mode="json") for svc in services],
309
+ "id",
310
+ "name",
311
+ "image"
312
+ )
315
313
  finally:
316
314
  await client.close()
317
315
 
meshagent/cli/tty.py ADDED
@@ -0,0 +1,122 @@
1
+ import pathlib
2
+ import sys
3
+ import tty
4
+ import termios
5
+ from typing import Annotated, Optional
6
+
7
+ import asyncio
8
+ import typer
9
+ from rich import print
10
+ import aiohttp
11
+
12
+ from meshagent.api import RoomClient, ParticipantToken
13
+ from meshagent.cli import async_typer
14
+ from meshagent.cli.helper import (
15
+ get_client,
16
+ print_json_table,
17
+ set_active_project,
18
+ resolve_project_id,
19
+ resolve_api_key,
20
+ )
21
+
22
+ import os
23
+
24
+ app = async_typer.AsyncTyper()
25
+
26
+ @app.async_command("connect")
27
+ async def tty_command(
28
+ *,
29
+ project_id: str = None,
30
+ room: Annotated[str, typer.Option()],
31
+ api_key_id: Annotated[Optional[str], typer.Option()] = None,
32
+
33
+ ):
34
+ """Open an interactive websocket‑based TTY."""
35
+ 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=project_id, api_key_id=api_key_id)
39
+
40
+ key = (await client.decrypt_project_api_key(project_id=project_id, id=api_key_id))["token"]
41
+
42
+ token = ParticipantToken(
43
+ name="tty",
44
+ project_id=project_id,
45
+ api_key_id=api_key_id
46
+ )
47
+
48
+ token.add_role_grant(role="user")
49
+
50
+ token.add_room_grant(room)
51
+
52
+ ws_url = f"{os.getenv("MESHAGENT_API_URL").replace("http","ws",1)}/rooms/{room}/tty?token={token.to_jwt(token=key)}"
53
+
54
+ print(f"[bold green]Connecting to[/bold green] {room}")
55
+
56
+ # Save current terminal settings so we can restore them later.
57
+ old_tty_settings = termios.tcgetattr(sys.stdin)
58
+ try:
59
+ async with aiohttp.ClientSession() as session:
60
+
61
+ async with session.ws_connect(ws_url) as websocket:
62
+
63
+ print(f"[bold green]Connected to[/bold green] {room}")
64
+
65
+ tty.setraw(sys.stdin)
66
+
67
+ async def recv_from_websocket():
68
+ async for message in websocket:
69
+
70
+ if message.type == aiohttp.WSMsgType.CLOSE:
71
+ await websocket.close()
72
+
73
+ elif message.type == aiohttp.WSMsgType.ERROR:
74
+ await websocket.close()
75
+
76
+ data : bytes = message.data
77
+ sys.stdout.write(data.decode("utf-8"))
78
+ sys.stdout.flush()
79
+
80
+ async def send_to_websocket():
81
+ loop = asyncio.get_running_loop()
82
+
83
+ reader = asyncio.StreamReader()
84
+ protocol = asyncio.StreamReaderProtocol(reader)
85
+ await loop.connect_read_pipe(lambda: protocol, sys.stdin)
86
+
87
+ while True:
88
+ # Read one character at a time from stdin without blocking the event loop.
89
+
90
+
91
+ data = await reader.read(1)
92
+ if not data:
93
+ break
94
+
95
+ if websocket.closed:
96
+ break
97
+
98
+ if data == b'\x03':
99
+ print("<CTRL-C>\n")
100
+ break
101
+
102
+ if data:
103
+ await websocket.send_bytes(data)
104
+ else:
105
+ await websocket.close(code=1000)
106
+ break
107
+
108
+ done, pending = await asyncio.wait([
109
+ asyncio.create_task(recv_from_websocket()),
110
+ asyncio.create_task(send_to_websocket())
111
+ ], return_when=asyncio.FIRST_COMPLETED)
112
+
113
+ for task in pending:
114
+ task.cancel()
115
+
116
+ finally:
117
+ # Restore original terminal settings even if the coroutine is cancelled.
118
+ termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_tty_settings)
119
+
120
+ finally:
121
+
122
+ await client.close()
meshagent/cli/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.0.30"
1
+ __version__ = "0.0.31"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshagent-cli
3
- Version: 0.0.30
3
+ Version: 0.0.31
4
4
  Summary: CLI for Meshagent
5
5
  License-Expression: Apache-2.0
6
6
  Project-URL: Documentation, https://docs.meshagent.com
@@ -10,11 +10,12 @@ 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.30
14
- Requires-Dist: meshagent-agents~=0.0.30
15
- Requires-Dist: meshagent-tools~=0.0.30
16
- Requires-Dist: meshagent-mcp~=0.0.30
13
+ Requires-Dist: meshagent-api~=0.0.31
14
+ Requires-Dist: meshagent-agents~=0.0.31
15
+ Requires-Dist: meshagent-tools~=0.0.31
16
+ Requires-Dist: meshagent-mcp~=0.0.31
17
17
  Requires-Dist: supabase~=2.15.1
18
+ Requires-Dist: fastmcp~=2.8.1
18
19
 
19
20
  ### Meshagent CLI
20
21
 
@@ -1,27 +1,28 @@
1
1
  meshagent/cli/__init__.py,sha256=8zLGg-DfQhnDl2Ky0n-zXpN-8e-g7iR0AcaI4l4Vvpk,32
2
2
  meshagent/cli/agent.py,sha256=0VjwJkwZ-G637Mps3OtxxWIfjWbrirJ4TTq2Idvjtug,10023
3
- meshagent/cli/api_keys.py,sha256=okj-xbnl1twPgT2yBbZQY4xNqe57d_MeCWsE_Qhl12g,2393
3
+ meshagent/cli/api_keys.py,sha256=VZynVFCBwxcwJ6dtxcoqKB91B0_QsUfJTim4vUXGvKc,4550
4
4
  meshagent/cli/async_typer.py,sha256=GCeSefBDbpd-V4V8LrvHGUTBMth3HspVMfFa-HUZ0cg,898
5
- meshagent/cli/auth.py,sha256=24UrVTvrlDfmGeLrG7oT7jTwM77296bdKVQ_egc3IAo,766
5
+ meshagent/cli/auth.py,sha256=pZQwYTNWQOWTqpyDrkQLNKuidH-wn9GNE5yEJoxn3-g,767
6
6
  meshagent/cli/auth_async.py,sha256=LArKxTxQAPmItv0JaGkW3Ybutl6MVmb6_EeSjI18IbI,4001
7
- meshagent/cli/call.py,sha256=M8oMo-hsYIzQzMF0OMNdJuoYCjDwtYUtdV1hCwZs0co,4610
7
+ meshagent/cli/call.py,sha256=4v7_aeYHyWKJipU199CPyDJRKjXaIpcOw1MRj8MMKwU,4640
8
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=-H4DtUGXZeWT2P7P9_5hOLRDq_l9xr1NoRLW_vDToRo,7462
9
+ meshagent/cli/cli.py,sha256=jogOzdPS1u6TXURLq85x9vZDuiwcJ8Brn7joC8GymlE,2128
10
+ meshagent/cli/cli_mcp.py,sha256=p5xSw62wlZ4DNslMbdygSKwvPQTfYSsMFx0bY_m9S4o,9584
11
11
  meshagent/cli/cli_secrets.py,sha256=U0kdzN3zt7JIqzdRLynAjxdvAsI0enesBd_m7TeXjnQ,13629
12
12
  meshagent/cli/developer.py,sha256=5eoDr3kfi-IufA5d6OESqNr739Bdut_IFBtT3nq0xZU,3002
13
13
  meshagent/cli/helper.py,sha256=hcY6C5BqGnYmwFVIG7nS9NPIZXbdpOoEna-t0mYmHGY,4632
14
14
  meshagent/cli/messaging.py,sha256=cU6LIK6gwOveLo_x2x3iWW5rC4MhDpwp2hvehAkvybI,6068
15
15
  meshagent/cli/participant_token.py,sha256=uCGmlUgNOfarYGkDZpzreXwnv9AJrM76tu5Lt690vYU,1456
16
- meshagent/cli/projects.py,sha256=Tut8kRCVvgdWzlAR1Zqf0QxAi4sNfQEIHY9zxfS1nuI,1100
17
- meshagent/cli/services.py,sha256=5uVfW8LX8IJ_Y03bkaC7wYvuLJltlAhhqNonavgqHqs,11042
16
+ meshagent/cli/projects.py,sha256=EQfbO9_GQKkjlFcaSHQfIxqIxsmFR3FbH5Fd17I5IPk,3305
17
+ meshagent/cli/services.py,sha256=Vzax2He-MygHq-HVTyHBCDlRHUeW963tlrRezvUImuM,11277
18
18
  meshagent/cli/sessions.py,sha256=WWvuztYqRfthSq6ztwL_eQ_sz9JRc33jcN6p7YyM_Fs,782
19
19
  meshagent/cli/storage.py,sha256=BsagaJfThrUWqXFyAk9IvQtUuDAMckE2mffZ_peozMo,33555
20
- meshagent/cli/version.py,sha256=8ZeepqkW4DvpVeNm92mx0tIzgvVevS4NKWkTXXHuXNY,23
20
+ meshagent/cli/tty.py,sha256=F1-ZKEl-kfKSFPvwsX8S99E9xbq7WyApbZGLs5_I-Bw,4081
21
+ meshagent/cli/version.py,sha256=YRrMDApG1V6fNZdI4BA631DmsqtamSXgI1yu0tnt4h0,23
21
22
  meshagent/cli/voicebot.py,sha256=KnWg1OeIPqxn-jfubs6G5FdnNLyJD64RzV4bSlhtv5s,3419
22
23
  meshagent/cli/webhook.py,sha256=KBl8U1TcOX3z2uoyH4YMuUuw0vSVX7xpRxYvzxI5c-Y,2811
23
- meshagent_cli-0.0.30.dist-info/METADATA,sha256=2ayLTylFsycSeL1DgAzALrjcc5ZqkppkP8A4hHtV6cg,605
24
- meshagent_cli-0.0.30.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
25
- meshagent_cli-0.0.30.dist-info/entry_points.txt,sha256=WRcGGN4vMtvC5Pgl3uRFqsJiQXNoHuLLa-TCSY3gAhQ,52
26
- meshagent_cli-0.0.30.dist-info/top_level.txt,sha256=GlcXnHtRP6m7zlG3Df04M35OsHtNXy_DY09oFwWrH74,10
27
- meshagent_cli-0.0.30.dist-info/RECORD,,
24
+ meshagent_cli-0.0.31.dist-info/METADATA,sha256=WAbJaRSP-HJoKgnEv6wYzOzlUncCmrLC1ZZ53hVcZNA,635
25
+ meshagent_cli-0.0.31.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
26
+ meshagent_cli-0.0.31.dist-info/entry_points.txt,sha256=WRcGGN4vMtvC5Pgl3uRFqsJiQXNoHuLLa-TCSY3gAhQ,52
27
+ meshagent_cli-0.0.31.dist-info/top_level.txt,sha256=GlcXnHtRP6m7zlG3Df04M35OsHtNXy_DY09oFwWrH74,10
28
+ meshagent_cli-0.0.31.dist-info/RECORD,,