meshagent-cli 0.5.18__py3-none-any.whl → 0.6.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.
Potentially problematic release.
This version of meshagent-cli might be problematic. Click here for more details.
- meshagent/cli/agent.py +11 -62
- meshagent/cli/api_keys.py +46 -93
- meshagent/cli/auth_async.py +225 -68
- meshagent/cli/call.py +82 -19
- meshagent/cli/chatbot.py +83 -49
- meshagent/cli/cli.py +26 -70
- meshagent/cli/cli_mcp.py +61 -27
- meshagent/cli/cli_secrets.py +1 -1
- meshagent/cli/common_options.py +2 -10
- meshagent/cli/containers.py +577 -0
- meshagent/cli/developer.py +7 -25
- meshagent/cli/exec.py +162 -76
- meshagent/cli/helper.py +35 -67
- meshagent/cli/helpers.py +131 -0
- meshagent/cli/mailbot.py +31 -26
- meshagent/cli/meeting_transcriber.py +124 -0
- meshagent/cli/messaging.py +12 -51
- meshagent/cli/oauth2.py +189 -0
- meshagent/cli/participant_token.py +32 -21
- meshagent/cli/queue.py +6 -37
- meshagent/cli/services.py +300 -335
- meshagent/cli/storage.py +24 -89
- meshagent/cli/version.py +1 -1
- meshagent/cli/voicebot.py +39 -28
- meshagent/cli/webhook.py +3 -3
- {meshagent_cli-0.5.18.dist-info → meshagent_cli-0.6.0.dist-info}/METADATA +17 -11
- meshagent_cli-0.6.0.dist-info/RECORD +35 -0
- meshagent/cli/otel.py +0 -122
- meshagent_cli-0.5.18.dist-info/RECORD +0 -32
- {meshagent_cli-0.5.18.dist-info → meshagent_cli-0.6.0.dist-info}/WHEEL +0 -0
- {meshagent_cli-0.5.18.dist-info → meshagent_cli-0.6.0.dist-info}/entry_points.txt +0 -0
- {meshagent_cli-0.5.18.dist-info → meshagent_cli-0.6.0.dist-info}/top_level.txt +0 -0
meshagent/cli/chatbot.py
CHANGED
|
@@ -1,36 +1,38 @@
|
|
|
1
1
|
import typer
|
|
2
2
|
from rich import print
|
|
3
3
|
from typing import Annotated, Optional
|
|
4
|
+
from meshagent.tools.storage import StorageToolkitBuilder
|
|
4
5
|
from meshagent.cli.common_options import (
|
|
5
6
|
ProjectIdOption,
|
|
6
|
-
ApiKeyIdOption,
|
|
7
7
|
RoomOption,
|
|
8
8
|
)
|
|
9
|
-
from meshagent.
|
|
10
|
-
|
|
9
|
+
from meshagent.api import (
|
|
10
|
+
RoomClient,
|
|
11
|
+
WebSocketClientProtocol,
|
|
12
|
+
ParticipantToken,
|
|
13
|
+
ApiScope,
|
|
14
|
+
)
|
|
11
15
|
from meshagent.api.helpers import meshagent_base_url, websocket_room_url
|
|
12
16
|
from meshagent.cli import async_typer
|
|
13
17
|
from meshagent.cli.helper import (
|
|
14
18
|
get_client,
|
|
15
19
|
resolve_project_id,
|
|
16
|
-
resolve_api_key,
|
|
17
|
-
resolve_token_jwt,
|
|
18
20
|
resolve_room,
|
|
21
|
+
resolve_key,
|
|
19
22
|
)
|
|
20
|
-
|
|
23
|
+
|
|
21
24
|
from meshagent.openai import OpenAIResponsesAdapter
|
|
22
|
-
|
|
23
|
-
from meshagent.computers.agent import ComputerAgent
|
|
24
|
-
from meshagent.agents.chat import (
|
|
25
|
-
ChatBotThreadOpenAIImageGenerationTool,
|
|
26
|
-
ChatBotThreadLocalShellTool,
|
|
27
|
-
)
|
|
25
|
+
|
|
28
26
|
|
|
29
27
|
from typing import List
|
|
30
28
|
from pathlib import Path
|
|
31
29
|
|
|
32
|
-
from meshagent.openai.tools.responses_adapter import
|
|
30
|
+
from meshagent.openai.tools.responses_adapter import (
|
|
31
|
+
WebSearchToolkitBuilder,
|
|
32
|
+
MCPToolkitBuilder,
|
|
33
|
+
)
|
|
33
34
|
from meshagent.api import RequiredToolkit, RequiredSchema
|
|
35
|
+
from meshagent.api.services import ServiceHost
|
|
34
36
|
|
|
35
37
|
app = async_typer.AsyncTyper(help="Join a chatbot to a room")
|
|
36
38
|
|
|
@@ -46,8 +48,17 @@ def build_chatbot(
|
|
|
46
48
|
local_shell: bool,
|
|
47
49
|
computer_use: bool,
|
|
48
50
|
web_search: bool,
|
|
51
|
+
mcp: bool,
|
|
52
|
+
storage: bool,
|
|
49
53
|
rules_file: Optional[str] = None,
|
|
50
54
|
):
|
|
55
|
+
from meshagent.agents.chat import ChatBot
|
|
56
|
+
|
|
57
|
+
from meshagent.agents.chat import (
|
|
58
|
+
ChatBotThreadOpenAIImageGenerationToolkitBuilder,
|
|
59
|
+
ChatBotThreadLocalShellToolkitBuilder,
|
|
60
|
+
)
|
|
61
|
+
|
|
51
62
|
requirements = []
|
|
52
63
|
|
|
53
64
|
toolkits = []
|
|
@@ -67,8 +78,13 @@ def build_chatbot(
|
|
|
67
78
|
|
|
68
79
|
BaseClass = ChatBot
|
|
69
80
|
if computer_use:
|
|
70
|
-
|
|
81
|
+
from meshagent.computers.agent import ComputerAgent
|
|
71
82
|
|
|
83
|
+
if ComputerAgent is None:
|
|
84
|
+
raise RuntimeError(
|
|
85
|
+
"Computer use is enabled, but meshagent.computers is not installed."
|
|
86
|
+
)
|
|
87
|
+
BaseClass = ComputerAgent
|
|
72
88
|
llm_adapter = OpenAIResponsesAdapter(
|
|
73
89
|
model=model,
|
|
74
90
|
response_options={
|
|
@@ -77,7 +93,9 @@ def build_chatbot(
|
|
|
77
93
|
},
|
|
78
94
|
)
|
|
79
95
|
else:
|
|
80
|
-
llm_adapter = OpenAIResponsesAdapter(
|
|
96
|
+
llm_adapter = OpenAIResponsesAdapter(
|
|
97
|
+
model=model,
|
|
98
|
+
)
|
|
81
99
|
|
|
82
100
|
class CustomChatbot(BaseClass):
|
|
83
101
|
def __init__(self):
|
|
@@ -89,33 +107,31 @@ def build_chatbot(
|
|
|
89
107
|
rules=rule if len(rule) > 0 else None,
|
|
90
108
|
)
|
|
91
109
|
|
|
92
|
-
async def
|
|
93
|
-
|
|
94
|
-
thread_context=thread_context, participant=participant
|
|
95
|
-
)
|
|
110
|
+
async def get_thread_toolkit_builders(self, *, thread_context, participant):
|
|
111
|
+
providers = []
|
|
96
112
|
|
|
97
|
-
|
|
113
|
+
if image_generation:
|
|
114
|
+
providers.append(
|
|
115
|
+
ChatBotThreadOpenAIImageGenerationToolkitBuilder(
|
|
116
|
+
thread_context=thread_context
|
|
117
|
+
)
|
|
118
|
+
)
|
|
98
119
|
|
|
99
120
|
if local_shell:
|
|
100
|
-
|
|
101
|
-
|
|
121
|
+
providers.append(
|
|
122
|
+
ChatBotThreadLocalShellToolkitBuilder(thread_context=thread_context)
|
|
102
123
|
)
|
|
103
124
|
|
|
104
|
-
if
|
|
105
|
-
|
|
106
|
-
thread_toolkit.tools.append(
|
|
107
|
-
ChatBotThreadOpenAIImageGenerationTool(
|
|
108
|
-
model=image_generation,
|
|
109
|
-
thread_context=thread_context,
|
|
110
|
-
partial_images=3,
|
|
111
|
-
)
|
|
112
|
-
)
|
|
125
|
+
if mcp:
|
|
126
|
+
providers.append(MCPToolkitBuilder())
|
|
113
127
|
|
|
114
128
|
if web_search:
|
|
115
|
-
|
|
129
|
+
providers.append(WebSearchToolkitBuilder())
|
|
130
|
+
|
|
131
|
+
if storage:
|
|
132
|
+
providers.append(StorageToolkitBuilder())
|
|
116
133
|
|
|
117
|
-
|
|
118
|
-
return toolkits
|
|
134
|
+
return providers
|
|
119
135
|
|
|
120
136
|
return CustomChatbot
|
|
121
137
|
|
|
@@ -124,11 +140,9 @@ def build_chatbot(
|
|
|
124
140
|
async def make_call(
|
|
125
141
|
*,
|
|
126
142
|
project_id: ProjectIdOption = None,
|
|
127
|
-
room: RoomOption
|
|
128
|
-
api_key_id: ApiKeyIdOption = None,
|
|
143
|
+
room: RoomOption,
|
|
129
144
|
role: str = "agent",
|
|
130
145
|
agent_name: Annotated[str, typer.Option(..., help="Name of the agent to call")],
|
|
131
|
-
token_path: Annotated[Optional[str], typer.Option()] = None,
|
|
132
146
|
rule: Annotated[List[str], typer.Option("--rule", "-r", help="a system rule")] = [],
|
|
133
147
|
rules_file: Optional[str] = None,
|
|
134
148
|
toolkit: Annotated[
|
|
@@ -141,7 +155,7 @@ async def make_call(
|
|
|
141
155
|
] = [],
|
|
142
156
|
model: Annotated[
|
|
143
157
|
str, typer.Option(..., help="Name of the LLM model to use for the chatbot")
|
|
144
|
-
] = "gpt-
|
|
158
|
+
] = "gpt-5",
|
|
145
159
|
image_generation: Annotated[
|
|
146
160
|
Optional[str], typer.Option(..., help="Name of an image gen model")
|
|
147
161
|
] = None,
|
|
@@ -157,21 +171,34 @@ async def make_call(
|
|
|
157
171
|
web_search: Annotated[
|
|
158
172
|
Optional[bool], typer.Option(..., help="Enable web search tool calling")
|
|
159
173
|
] = False,
|
|
174
|
+
mcp: Annotated[
|
|
175
|
+
Optional[bool], typer.Option(..., help="Enable mcp tool calling")
|
|
176
|
+
] = False,
|
|
177
|
+
storage: Annotated[
|
|
178
|
+
Optional[bool], typer.Option(..., help="Enable storage toolkit")
|
|
179
|
+
] = False,
|
|
180
|
+
key: Annotated[
|
|
181
|
+
str,
|
|
182
|
+
typer.Option("--key", help="an api key to sign the token with"),
|
|
183
|
+
] = None,
|
|
160
184
|
):
|
|
185
|
+
key = await resolve_key(project_id=project_id, key=key)
|
|
161
186
|
account_client = await get_client()
|
|
162
187
|
try:
|
|
163
188
|
project_id = await resolve_project_id(project_id=project_id)
|
|
164
|
-
api_key_id = await resolve_api_key(project_id, api_key_id)
|
|
165
189
|
room = resolve_room(room)
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
api_key_id=api_key_id,
|
|
169
|
-
token_path=token_path,
|
|
190
|
+
|
|
191
|
+
token = ParticipantToken(
|
|
170
192
|
name=agent_name,
|
|
171
|
-
role=role,
|
|
172
|
-
room=room,
|
|
173
193
|
)
|
|
174
194
|
|
|
195
|
+
token.add_api_grant(ApiScope.agent_default())
|
|
196
|
+
|
|
197
|
+
token.add_role_grant(role=role)
|
|
198
|
+
token.add_room_grant(room)
|
|
199
|
+
|
|
200
|
+
jwt = token.to_jwt(api_key=key)
|
|
201
|
+
|
|
175
202
|
print("[bold green]Connecting to room...[/bold green]", flush=True)
|
|
176
203
|
async with RoomClient(
|
|
177
204
|
protocol=WebSocketClientProtocol(
|
|
@@ -198,6 +225,8 @@ async def make_call(
|
|
|
198
225
|
image_generation=image_generation,
|
|
199
226
|
web_search=web_search,
|
|
200
227
|
rules_file=rules_file,
|
|
228
|
+
mcp=mcp,
|
|
229
|
+
storage=storage,
|
|
201
230
|
)
|
|
202
231
|
|
|
203
232
|
bot = CustomChatbot()
|
|
@@ -219,7 +248,6 @@ async def make_call(
|
|
|
219
248
|
@app.async_command("service")
|
|
220
249
|
async def service(
|
|
221
250
|
*,
|
|
222
|
-
room: RoomOption = None,
|
|
223
251
|
agent_name: Annotated[str, typer.Option(..., help="Name of the agent to call")],
|
|
224
252
|
rule: Annotated[List[str], typer.Option("--rule", "-r", help="a system rule")] = [],
|
|
225
253
|
rules_file: Optional[str] = None,
|
|
@@ -233,7 +261,7 @@ async def service(
|
|
|
233
261
|
] = [],
|
|
234
262
|
model: Annotated[
|
|
235
263
|
str, typer.Option(..., help="Name of the LLM model to use for the chatbot")
|
|
236
|
-
] = "gpt-
|
|
264
|
+
] = "gpt-5",
|
|
237
265
|
image_generation: Annotated[
|
|
238
266
|
Optional[str], typer.Option(..., help="Name of an image gen model")
|
|
239
267
|
] = None,
|
|
@@ -249,12 +277,16 @@ async def service(
|
|
|
249
277
|
web_search: Annotated[
|
|
250
278
|
Optional[bool], typer.Option(..., help="Enable web search tool calling")
|
|
251
279
|
] = False,
|
|
280
|
+
mcp: Annotated[
|
|
281
|
+
Optional[bool], typer.Option(..., help="Enable mcp tool calling")
|
|
282
|
+
] = False,
|
|
283
|
+
storage: Annotated[
|
|
284
|
+
Optional[bool], typer.Option(..., help="Enable storage toolkit")
|
|
285
|
+
] = False,
|
|
252
286
|
host: Annotated[Optional[str], typer.Option()] = None,
|
|
253
287
|
port: Annotated[Optional[int], typer.Option()] = None,
|
|
254
288
|
path: Annotated[str, typer.Option()] = "/agent",
|
|
255
289
|
):
|
|
256
|
-
room = resolve_room(room)
|
|
257
|
-
|
|
258
290
|
print("[bold green]Connecting to room...[/bold green]", flush=True)
|
|
259
291
|
|
|
260
292
|
service = ServiceHost(host=host, port=port)
|
|
@@ -271,6 +303,8 @@ async def service(
|
|
|
271
303
|
web_search=web_search,
|
|
272
304
|
image_generation=image_generation,
|
|
273
305
|
rules_file=rules_file,
|
|
306
|
+
mcp=mcp,
|
|
307
|
+
storage=storage,
|
|
274
308
|
),
|
|
275
309
|
)
|
|
276
310
|
|
meshagent/cli/cli.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import typer
|
|
2
2
|
import asyncio
|
|
3
|
-
from typing import Optional
|
|
4
3
|
|
|
5
4
|
from meshagent.cli import async_typer
|
|
6
5
|
|
|
@@ -22,10 +21,15 @@ from meshagent.cli import cli_mcp
|
|
|
22
21
|
from meshagent.cli import chatbot
|
|
23
22
|
from meshagent.cli import voicebot
|
|
24
23
|
from meshagent.cli import mailbot
|
|
24
|
+
from meshagent.cli import containers
|
|
25
|
+
from meshagent.cli import oauth2
|
|
26
|
+
from meshagent.cli import helpers
|
|
27
|
+
from meshagent.cli import meeting_transcriber
|
|
25
28
|
from meshagent.cli.exec import register as register_exec
|
|
26
29
|
from meshagent.cli.version import __version__
|
|
30
|
+
from meshagent.cli.helper import get_active_api_key
|
|
31
|
+
from meshagent.otel import otel_config
|
|
27
32
|
|
|
28
|
-
from meshagent.cli import otel
|
|
29
33
|
|
|
30
34
|
from art import tprint
|
|
31
35
|
|
|
@@ -34,16 +38,15 @@ import logging
|
|
|
34
38
|
import os
|
|
35
39
|
import sys
|
|
36
40
|
from pathlib import Path
|
|
37
|
-
from meshagent.cli.helper import get_client, resolve_project_id, resolve_api_key
|
|
38
41
|
|
|
42
|
+
otel_config(service_name="meshagent-cli")
|
|
39
43
|
|
|
40
|
-
otel.init(level=logging.INFO)
|
|
41
44
|
|
|
42
45
|
# Turn down OpenAI logs, they are a bit noisy
|
|
43
46
|
logging.getLogger("openai").setLevel(logging.ERROR)
|
|
44
47
|
logging.getLogger("httpx").setLevel(logging.ERROR)
|
|
45
48
|
|
|
46
|
-
app = async_typer.AsyncTyper()
|
|
49
|
+
app = async_typer.AsyncTyper(no_args_is_help=True)
|
|
47
50
|
app.add_typer(call.app, name="call")
|
|
48
51
|
app.add_typer(auth.app, name="auth")
|
|
49
52
|
app.add_typer(projects.app, name="project")
|
|
@@ -62,6 +65,10 @@ app.add_typer(cli_mcp.app, name="mcp")
|
|
|
62
65
|
app.add_typer(chatbot.app, name="chatbot")
|
|
63
66
|
app.add_typer(voicebot.app, name="voicebot")
|
|
64
67
|
app.add_typer(mailbot.app, name="mailbot")
|
|
68
|
+
app.add_typer(containers.app, name="container")
|
|
69
|
+
app.add_typer(oauth2.app, name="oauth2")
|
|
70
|
+
app.add_typer(helpers.app, name="helpers")
|
|
71
|
+
app.add_typer(meeting_transcriber.app, name="meeting-transcriber")
|
|
65
72
|
|
|
66
73
|
register_exec(app)
|
|
67
74
|
|
|
@@ -142,66 +149,6 @@ def version():
|
|
|
142
149
|
print(__version__)
|
|
143
150
|
|
|
144
151
|
|
|
145
|
-
@app.command(
|
|
146
|
-
"env",
|
|
147
|
-
help="Generate shell commands to set meshagent environment variables.",
|
|
148
|
-
)
|
|
149
|
-
def env(
|
|
150
|
-
shell: Optional[str] = typer.Option(
|
|
151
|
-
None,
|
|
152
|
-
"--shell",
|
|
153
|
-
case_sensitive=False,
|
|
154
|
-
help="bash | zsh | fish | powershell | cmd",
|
|
155
|
-
),
|
|
156
|
-
unset: bool = typer.Option(
|
|
157
|
-
False, "--unset", help="Output commands to unset the variables."
|
|
158
|
-
),
|
|
159
|
-
):
|
|
160
|
-
"""Print shell-specific exports/unsets for Docker environment variables."""
|
|
161
|
-
|
|
162
|
-
async def command():
|
|
163
|
-
nonlocal shell, unset
|
|
164
|
-
shell = (shell or detect_shell()).lower()
|
|
165
|
-
if shell not in SHELL_RENDERERS:
|
|
166
|
-
typer.echo(f"Unsupported shell '{shell}'.", err=True)
|
|
167
|
-
raise typer.Exit(code=1)
|
|
168
|
-
|
|
169
|
-
client = await get_client()
|
|
170
|
-
try:
|
|
171
|
-
project_id = await resolve_project_id(project_id=None)
|
|
172
|
-
api_key_id = await resolve_api_key(project_id=project_id, api_key_id=None)
|
|
173
|
-
|
|
174
|
-
token = (
|
|
175
|
-
await client.decrypt_project_api_key(
|
|
176
|
-
project_id=project_id, id=api_key_id
|
|
177
|
-
)
|
|
178
|
-
)["token"]
|
|
179
|
-
finally:
|
|
180
|
-
await client.close()
|
|
181
|
-
|
|
182
|
-
vars = {
|
|
183
|
-
"MESHAGENT_PROJECT_ID": project_id,
|
|
184
|
-
"MESHAGENT_KEY_ID": api_key_id,
|
|
185
|
-
"MESHAGENT_SECRET": token,
|
|
186
|
-
}
|
|
187
|
-
if shell not in SHELL_RENDERERS:
|
|
188
|
-
typer.echo(f"Unsupported shell '{shell}'.", err=True)
|
|
189
|
-
raise typer.Exit(code=1)
|
|
190
|
-
|
|
191
|
-
render = SHELL_RENDERERS[shell]
|
|
192
|
-
|
|
193
|
-
for name, value in vars.items():
|
|
194
|
-
typer.echo(render(name, value, unset))
|
|
195
|
-
|
|
196
|
-
if not unset and shell in ("bash", "zsh"):
|
|
197
|
-
typer.echo(
|
|
198
|
-
"\n# Run this command to configure your current shell:\n"
|
|
199
|
-
'# eval "$(meshagent env)"'
|
|
200
|
-
)
|
|
201
|
-
|
|
202
|
-
_run_async(command())
|
|
203
|
-
|
|
204
|
-
|
|
205
152
|
@app.command("setup")
|
|
206
153
|
def setup_command():
|
|
207
154
|
"""Perform initial login and project/api key activation."""
|
|
@@ -215,11 +162,20 @@ def setup_command():
|
|
|
215
162
|
project_id = await projects.activate(None, interactive=True)
|
|
216
163
|
if project_id is None:
|
|
217
164
|
print("You have choosen to not activate a project. Exiting.")
|
|
218
|
-
if
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
165
|
+
if (
|
|
166
|
+
project_id is not None
|
|
167
|
+
and await get_active_api_key(project_id=project_id) is None
|
|
168
|
+
):
|
|
169
|
+
if typer.confirm(
|
|
170
|
+
"You do not have an active api key for this project. Would you like to create and activate a new api key?",
|
|
171
|
+
default=True,
|
|
172
|
+
):
|
|
173
|
+
name = typer.prompt(
|
|
174
|
+
"Enter a name for your API Key (must be a unique name):"
|
|
175
|
+
)
|
|
176
|
+
await api_keys.create(
|
|
177
|
+
project_id=None, activate=True, silent=True, name=name
|
|
178
|
+
)
|
|
223
179
|
|
|
224
180
|
_run_async(runner())
|
|
225
181
|
|
meshagent/cli/cli_mcp.py
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
from mcp.client.session import ClientSession
|
|
2
|
-
from mcp.client.sse import sse_client
|
|
3
|
-
from mcp.client.stdio import stdio_client, StdioServerParameters
|
|
4
|
-
|
|
5
1
|
import typer
|
|
6
2
|
from rich import print
|
|
7
3
|
from typing import Annotated, Optional, List
|
|
8
|
-
from meshagent.cli.common_options import ProjectIdOption,
|
|
4
|
+
from meshagent.cli.common_options import ProjectIdOption, RoomOption
|
|
9
5
|
|
|
10
6
|
from meshagent.api.helpers import meshagent_base_url, websocket_room_url
|
|
11
7
|
from meshagent.api import RoomClient, WebSocketClientProtocol, RoomException
|
|
@@ -13,21 +9,32 @@ from meshagent.cli import async_typer
|
|
|
13
9
|
from meshagent.cli.helper import (
|
|
14
10
|
get_client,
|
|
15
11
|
resolve_project_id,
|
|
16
|
-
resolve_api_key,
|
|
17
|
-
resolve_token_jwt,
|
|
18
12
|
resolve_room,
|
|
13
|
+
resolve_key,
|
|
19
14
|
)
|
|
20
15
|
|
|
21
16
|
from meshagent.tools.hosting import RemoteToolkit
|
|
22
17
|
|
|
23
|
-
from meshagent.mcp import MCPToolkit
|
|
24
18
|
|
|
25
19
|
from meshagent.api.services import ServiceHost
|
|
26
20
|
import os
|
|
27
21
|
|
|
28
|
-
from meshagent.cli.services import _kv_to_dict
|
|
29
22
|
import shlex
|
|
30
23
|
|
|
24
|
+
from meshagent.api import ParticipantToken, ApiScope
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _kv_to_dict(pairs: List[str]) -> dict[str, str]:
|
|
28
|
+
"""Convert ["A=1","B=2"] → {"A":"1","B":"2"}."""
|
|
29
|
+
out: dict[str, str] = {}
|
|
30
|
+
for p in pairs:
|
|
31
|
+
if "=" not in p:
|
|
32
|
+
raise typer.BadParameter(f"'{p}' must be KEY=VALUE")
|
|
33
|
+
k, v = p.split("=", 1)
|
|
34
|
+
out[k] = v
|
|
35
|
+
return out
|
|
36
|
+
|
|
37
|
+
|
|
31
38
|
app = async_typer.AsyncTyper()
|
|
32
39
|
|
|
33
40
|
|
|
@@ -36,30 +43,41 @@ async def sse(
|
|
|
36
43
|
*,
|
|
37
44
|
project_id: ProjectIdOption = None,
|
|
38
45
|
room: RoomOption,
|
|
39
|
-
token_path: Annotated[Optional[str], typer.Option()] = None,
|
|
40
|
-
api_key_id: ApiKeyIdOption = None,
|
|
41
46
|
name: Annotated[str, typer.Option(..., help="Participant name")] = "cli",
|
|
42
47
|
role: str = "tool",
|
|
43
48
|
url: Annotated[str, typer.Option()],
|
|
44
49
|
toolkit_name: Annotated[Optional[str], typer.Option()] = None,
|
|
50
|
+
key: Annotated[
|
|
51
|
+
str,
|
|
52
|
+
typer.Option("--key", help="an api key to sign the token with"),
|
|
53
|
+
] = None,
|
|
45
54
|
):
|
|
55
|
+
from mcp.client.session import ClientSession
|
|
56
|
+
from mcp.client.sse import sse_client
|
|
57
|
+
|
|
58
|
+
from meshagent.mcp import MCPToolkit
|
|
59
|
+
|
|
60
|
+
key = await resolve_key(project_id=project_id, key=key)
|
|
61
|
+
|
|
46
62
|
if toolkit_name is None:
|
|
47
63
|
toolkit_name = "mcp"
|
|
48
64
|
|
|
49
65
|
account_client = await get_client()
|
|
50
66
|
try:
|
|
51
67
|
project_id = await resolve_project_id(project_id=project_id)
|
|
52
|
-
api_key_id = await resolve_api_key(project_id, api_key_id)
|
|
53
68
|
room = resolve_room(room)
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
api_key_id=api_key_id,
|
|
57
|
-
token_path=token_path,
|
|
69
|
+
|
|
70
|
+
token = ParticipantToken(
|
|
58
71
|
name=name,
|
|
59
|
-
role=role,
|
|
60
|
-
room=room,
|
|
61
72
|
)
|
|
62
73
|
|
|
74
|
+
token.add_api_grant(ApiScope.agent_default())
|
|
75
|
+
|
|
76
|
+
token.add_role_grant(role=role)
|
|
77
|
+
token.add_room_grant(room)
|
|
78
|
+
|
|
79
|
+
jwt = token.to_jwt(api_key=key)
|
|
80
|
+
|
|
63
81
|
print("[bold green]Connecting to room...[/bold green]")
|
|
64
82
|
async with RoomClient(
|
|
65
83
|
protocol=WebSocketClientProtocol(
|
|
@@ -103,31 +121,42 @@ async def stdio(
|
|
|
103
121
|
*,
|
|
104
122
|
project_id: ProjectIdOption = None,
|
|
105
123
|
room: RoomOption,
|
|
106
|
-
token_path: Annotated[Optional[str], typer.Option()] = None,
|
|
107
|
-
api_key_id: ApiKeyIdOption = None,
|
|
108
124
|
name: Annotated[str, typer.Option(..., help="Participant name")] = "cli",
|
|
109
125
|
role: str = "tool",
|
|
110
126
|
command: Annotated[str, typer.Option()],
|
|
111
127
|
toolkit_name: Annotated[Optional[str], typer.Option()] = None,
|
|
112
128
|
env: Annotated[List[str], typer.Option("--env", "-e", help="KEY=VALUE")] = [],
|
|
129
|
+
key: Annotated[
|
|
130
|
+
str,
|
|
131
|
+
typer.Option("--key", help="an api key to sign the token with"),
|
|
132
|
+
] = None,
|
|
113
133
|
):
|
|
134
|
+
from mcp.client.session import ClientSession
|
|
135
|
+
from mcp.client.stdio import stdio_client, StdioServerParameters
|
|
136
|
+
|
|
137
|
+
from meshagent.mcp import MCPToolkit
|
|
138
|
+
|
|
139
|
+
key = await resolve_key(project_id=project_id, key=key)
|
|
140
|
+
|
|
114
141
|
if toolkit_name is None:
|
|
115
142
|
toolkit_name = "mcp"
|
|
116
143
|
|
|
117
144
|
account_client = await get_client()
|
|
118
145
|
try:
|
|
119
146
|
project_id = await resolve_project_id(project_id=project_id)
|
|
120
|
-
api_key_id = await resolve_api_key(project_id, api_key_id)
|
|
121
147
|
room = resolve_room(room)
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
api_key_id=api_key_id,
|
|
125
|
-
token_path=token_path,
|
|
148
|
+
|
|
149
|
+
token = ParticipantToken(
|
|
126
150
|
name=name,
|
|
127
|
-
role=role,
|
|
128
|
-
room=room,
|
|
129
151
|
)
|
|
130
152
|
|
|
153
|
+
token.add_api_grant(ApiScope.agent_default())
|
|
154
|
+
|
|
155
|
+
token.add_role_grant(role=role)
|
|
156
|
+
token.add_room_grant(room)
|
|
157
|
+
|
|
158
|
+
jwt = token.to_jwt(api_key=key)
|
|
159
|
+
|
|
131
160
|
print("[bold green]Connecting to room...[/bold green]")
|
|
132
161
|
async with RoomClient(
|
|
133
162
|
protocol=WebSocketClientProtocol(
|
|
@@ -253,6 +282,11 @@ async def stdio_service(
|
|
|
253
282
|
toolkit_name: Annotated[Optional[str], typer.Option()] = None,
|
|
254
283
|
env: Annotated[List[str], typer.Option("--env", "-e", help="KEY=VALUE")] = [],
|
|
255
284
|
):
|
|
285
|
+
from mcp.client.session import ClientSession
|
|
286
|
+
from mcp.client.stdio import stdio_client, StdioServerParameters
|
|
287
|
+
|
|
288
|
+
from meshagent.mcp import MCPToolkit
|
|
289
|
+
|
|
256
290
|
try:
|
|
257
291
|
parsed_command = shlex.split(command)
|
|
258
292
|
|
meshagent/cli/cli_secrets.py
CHANGED
|
@@ -8,7 +8,7 @@ from meshagent.cli.common_options import ProjectIdOption
|
|
|
8
8
|
|
|
9
9
|
from meshagent.cli import async_typer
|
|
10
10
|
from meshagent.cli.helper import get_client, print_json_table, resolve_project_id
|
|
11
|
-
from meshagent.api.
|
|
11
|
+
from meshagent.api.client import (
|
|
12
12
|
PullSecret,
|
|
13
13
|
KeysSecret,
|
|
14
14
|
SecretLike,
|
meshagent/cli/common_options.py
CHANGED
|
@@ -14,18 +14,10 @@ ProjectIdOption = Annotated[
|
|
|
14
14
|
),
|
|
15
15
|
]
|
|
16
16
|
|
|
17
|
-
ApiKeyIdOption = Annotated[
|
|
18
|
-
Optional[str],
|
|
19
|
-
typer.Option(
|
|
20
|
-
"--api-key-id",
|
|
21
|
-
help="A MeshAgent project API key id. If empty, the activated api key will be used.",
|
|
22
|
-
),
|
|
23
|
-
]
|
|
24
|
-
|
|
25
17
|
RoomOption = Annotated[
|
|
26
|
-
|
|
18
|
+
str,
|
|
27
19
|
typer.Option(
|
|
28
20
|
"--room",
|
|
29
|
-
help="Room name
|
|
21
|
+
help="Room name",
|
|
30
22
|
),
|
|
31
23
|
]
|