meshagent-cli 0.6.1__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 +263 -0
- meshagent/cli/api_keys.py +102 -0
- meshagent/cli/async_typer.py +31 -0
- meshagent/cli/auth.py +30 -0
- meshagent/cli/auth_async.py +295 -0
- meshagent/cli/call.py +224 -0
- meshagent/cli/chatbot.py +311 -0
- meshagent/cli/cli.py +184 -0
- meshagent/cli/cli_mcp.py +344 -0
- meshagent/cli/cli_secrets.py +414 -0
- meshagent/cli/common_options.py +23 -0
- meshagent/cli/containers.py +577 -0
- meshagent/cli/developer.py +70 -0
- meshagent/cli/exec.py +381 -0
- meshagent/cli/helper.py +147 -0
- meshagent/cli/helpers.py +131 -0
- meshagent/cli/mailbot.py +260 -0
- meshagent/cli/meeting_transcriber.py +124 -0
- meshagent/cli/messaging.py +160 -0
- meshagent/cli/oauth2.py +189 -0
- meshagent/cli/participant_token.py +61 -0
- meshagent/cli/projects.py +105 -0
- meshagent/cli/queue.py +91 -0
- meshagent/cli/services.py +490 -0
- meshagent/cli/sessions.py +26 -0
- meshagent/cli/storage.py +813 -0
- meshagent/cli/version.py +1 -0
- meshagent/cli/voicebot.py +178 -0
- meshagent/cli/webhook.py +100 -0
- meshagent_cli-0.6.1.dist-info/METADATA +47 -0
- meshagent_cli-0.6.1.dist-info/RECORD +35 -0
- meshagent_cli-0.6.1.dist-info/WHEEL +5 -0
- meshagent_cli-0.6.1.dist-info/entry_points.txt +2 -0
- meshagent_cli-0.6.1.dist-info/top_level.txt +1 -0
meshagent/cli/chatbot.py
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
from rich import print
|
|
3
|
+
from typing import Annotated, Optional
|
|
4
|
+
from meshagent.tools.storage import StorageToolkitBuilder
|
|
5
|
+
from meshagent.cli.common_options import (
|
|
6
|
+
ProjectIdOption,
|
|
7
|
+
RoomOption,
|
|
8
|
+
)
|
|
9
|
+
from meshagent.api import (
|
|
10
|
+
RoomClient,
|
|
11
|
+
WebSocketClientProtocol,
|
|
12
|
+
ParticipantToken,
|
|
13
|
+
ApiScope,
|
|
14
|
+
)
|
|
15
|
+
from meshagent.api.helpers import meshagent_base_url, websocket_room_url
|
|
16
|
+
from meshagent.cli import async_typer
|
|
17
|
+
from meshagent.cli.helper import (
|
|
18
|
+
get_client,
|
|
19
|
+
resolve_project_id,
|
|
20
|
+
resolve_room,
|
|
21
|
+
resolve_key,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
from meshagent.openai import OpenAIResponsesAdapter
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
from typing import List
|
|
28
|
+
from pathlib import Path
|
|
29
|
+
|
|
30
|
+
from meshagent.openai.tools.responses_adapter import (
|
|
31
|
+
WebSearchToolkitBuilder,
|
|
32
|
+
MCPToolkitBuilder,
|
|
33
|
+
)
|
|
34
|
+
from meshagent.api import RequiredToolkit, RequiredSchema
|
|
35
|
+
from meshagent.api.services import ServiceHost
|
|
36
|
+
|
|
37
|
+
app = async_typer.AsyncTyper(help="Join a chatbot to a room")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def build_chatbot(
|
|
41
|
+
*,
|
|
42
|
+
model: str,
|
|
43
|
+
agent_name: str,
|
|
44
|
+
rule: List[str],
|
|
45
|
+
toolkit: List[str],
|
|
46
|
+
schema: List[str],
|
|
47
|
+
image_generation: Optional[str] = None,
|
|
48
|
+
local_shell: bool,
|
|
49
|
+
computer_use: bool,
|
|
50
|
+
web_search: bool,
|
|
51
|
+
mcp: bool,
|
|
52
|
+
storage: bool,
|
|
53
|
+
rules_file: Optional[str] = None,
|
|
54
|
+
):
|
|
55
|
+
from meshagent.agents.chat import ChatBot
|
|
56
|
+
|
|
57
|
+
from meshagent.agents.chat import (
|
|
58
|
+
ChatBotThreadOpenAIImageGenerationToolkitBuilder,
|
|
59
|
+
ChatBotThreadLocalShellToolkitBuilder,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
requirements = []
|
|
63
|
+
|
|
64
|
+
toolkits = []
|
|
65
|
+
|
|
66
|
+
for t in toolkit:
|
|
67
|
+
requirements.append(RequiredToolkit(name=t))
|
|
68
|
+
|
|
69
|
+
for t in schema:
|
|
70
|
+
requirements.append(RequiredSchema(name=t))
|
|
71
|
+
|
|
72
|
+
if rules_file is not None:
|
|
73
|
+
try:
|
|
74
|
+
with open(Path(rules_file).resolve(), "r") as f:
|
|
75
|
+
rule.extend(f.read().splitlines())
|
|
76
|
+
except FileNotFoundError:
|
|
77
|
+
print(f"[yellow]rules file not found at {rules_file}[/yellow]")
|
|
78
|
+
|
|
79
|
+
BaseClass = ChatBot
|
|
80
|
+
if computer_use:
|
|
81
|
+
from meshagent.computers.agent import ComputerAgent
|
|
82
|
+
|
|
83
|
+
if ComputerAgent is None:
|
|
84
|
+
raise RuntimeError(
|
|
85
|
+
"Computer use is enabled, but meshagent.computers is not installed."
|
|
86
|
+
)
|
|
87
|
+
BaseClass = ComputerAgent
|
|
88
|
+
llm_adapter = OpenAIResponsesAdapter(
|
|
89
|
+
model=model,
|
|
90
|
+
response_options={
|
|
91
|
+
"reasoning": {"generate_summary": "concise"},
|
|
92
|
+
"truncation": "auto",
|
|
93
|
+
},
|
|
94
|
+
)
|
|
95
|
+
else:
|
|
96
|
+
llm_adapter = OpenAIResponsesAdapter(
|
|
97
|
+
model=model,
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
class CustomChatbot(BaseClass):
|
|
101
|
+
def __init__(self):
|
|
102
|
+
super().__init__(
|
|
103
|
+
llm_adapter=llm_adapter,
|
|
104
|
+
name=agent_name,
|
|
105
|
+
requires=requirements,
|
|
106
|
+
toolkits=toolkits,
|
|
107
|
+
rules=rule if len(rule) > 0 else None,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
async def get_thread_toolkit_builders(self, *, thread_context, participant):
|
|
111
|
+
providers = []
|
|
112
|
+
|
|
113
|
+
if image_generation:
|
|
114
|
+
providers.append(
|
|
115
|
+
ChatBotThreadOpenAIImageGenerationToolkitBuilder(
|
|
116
|
+
thread_context=thread_context
|
|
117
|
+
)
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
if local_shell:
|
|
121
|
+
providers.append(
|
|
122
|
+
ChatBotThreadLocalShellToolkitBuilder(thread_context=thread_context)
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
if mcp:
|
|
126
|
+
providers.append(MCPToolkitBuilder())
|
|
127
|
+
|
|
128
|
+
if web_search:
|
|
129
|
+
providers.append(WebSearchToolkitBuilder())
|
|
130
|
+
|
|
131
|
+
if storage:
|
|
132
|
+
providers.append(StorageToolkitBuilder())
|
|
133
|
+
|
|
134
|
+
return providers
|
|
135
|
+
|
|
136
|
+
return CustomChatbot
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@app.async_command("join")
|
|
140
|
+
async def make_call(
|
|
141
|
+
*,
|
|
142
|
+
project_id: ProjectIdOption = None,
|
|
143
|
+
room: RoomOption,
|
|
144
|
+
role: str = "agent",
|
|
145
|
+
agent_name: Annotated[str, typer.Option(..., help="Name of the agent to call")],
|
|
146
|
+
rule: Annotated[List[str], typer.Option("--rule", "-r", help="a system rule")] = [],
|
|
147
|
+
rules_file: Optional[str] = None,
|
|
148
|
+
toolkit: Annotated[
|
|
149
|
+
List[str],
|
|
150
|
+
typer.Option("--toolkit", "-t", help="the name or url of a required toolkit"),
|
|
151
|
+
] = [],
|
|
152
|
+
schema: Annotated[
|
|
153
|
+
List[str],
|
|
154
|
+
typer.Option("--schema", "-s", help="the name or url of a required schema"),
|
|
155
|
+
] = [],
|
|
156
|
+
model: Annotated[
|
|
157
|
+
str, typer.Option(..., help="Name of the LLM model to use for the chatbot")
|
|
158
|
+
] = "gpt-5",
|
|
159
|
+
image_generation: Annotated[
|
|
160
|
+
Optional[str], typer.Option(..., help="Name of an image gen model")
|
|
161
|
+
] = None,
|
|
162
|
+
computer_use: Annotated[
|
|
163
|
+
Optional[bool],
|
|
164
|
+
typer.Option(
|
|
165
|
+
..., help="Enable computer use (requires computer-use-preview model)"
|
|
166
|
+
),
|
|
167
|
+
] = False,
|
|
168
|
+
local_shell: Annotated[
|
|
169
|
+
Optional[bool], typer.Option(..., help="Enable local shell tool calling")
|
|
170
|
+
] = False,
|
|
171
|
+
web_search: Annotated[
|
|
172
|
+
Optional[bool], typer.Option(..., help="Enable web search tool calling")
|
|
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,
|
|
184
|
+
):
|
|
185
|
+
key = await resolve_key(project_id=project_id, key=key)
|
|
186
|
+
account_client = await get_client()
|
|
187
|
+
try:
|
|
188
|
+
project_id = await resolve_project_id(project_id=project_id)
|
|
189
|
+
room = resolve_room(room)
|
|
190
|
+
|
|
191
|
+
token = ParticipantToken(
|
|
192
|
+
name=agent_name,
|
|
193
|
+
)
|
|
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
|
+
|
|
202
|
+
print("[bold green]Connecting to room...[/bold green]", flush=True)
|
|
203
|
+
async with RoomClient(
|
|
204
|
+
protocol=WebSocketClientProtocol(
|
|
205
|
+
url=websocket_room_url(room_name=room, base_url=meshagent_base_url()),
|
|
206
|
+
token=jwt,
|
|
207
|
+
)
|
|
208
|
+
) as client:
|
|
209
|
+
requirements = []
|
|
210
|
+
|
|
211
|
+
for t in toolkit:
|
|
212
|
+
requirements.append(RequiredToolkit(name=t))
|
|
213
|
+
|
|
214
|
+
for t in schema:
|
|
215
|
+
requirements.append(RequiredSchema(name=t))
|
|
216
|
+
|
|
217
|
+
CustomChatbot = build_chatbot(
|
|
218
|
+
computer_use=computer_use,
|
|
219
|
+
model=model,
|
|
220
|
+
local_shell=local_shell,
|
|
221
|
+
agent_name=agent_name,
|
|
222
|
+
rule=rule,
|
|
223
|
+
toolkit=toolkit,
|
|
224
|
+
schema=schema,
|
|
225
|
+
image_generation=image_generation,
|
|
226
|
+
web_search=web_search,
|
|
227
|
+
rules_file=rules_file,
|
|
228
|
+
mcp=mcp,
|
|
229
|
+
storage=storage,
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
bot = CustomChatbot()
|
|
233
|
+
|
|
234
|
+
await bot.start(room=client)
|
|
235
|
+
try:
|
|
236
|
+
print(
|
|
237
|
+
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]",
|
|
238
|
+
flush=True,
|
|
239
|
+
)
|
|
240
|
+
await client.protocol.wait_for_close()
|
|
241
|
+
except KeyboardInterrupt:
|
|
242
|
+
await bot.stop()
|
|
243
|
+
|
|
244
|
+
finally:
|
|
245
|
+
await account_client.close()
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
@app.async_command("service")
|
|
249
|
+
async def service(
|
|
250
|
+
*,
|
|
251
|
+
agent_name: Annotated[str, typer.Option(..., help="Name of the agent to call")],
|
|
252
|
+
rule: Annotated[List[str], typer.Option("--rule", "-r", help="a system rule")] = [],
|
|
253
|
+
rules_file: Optional[str] = None,
|
|
254
|
+
toolkit: Annotated[
|
|
255
|
+
List[str],
|
|
256
|
+
typer.Option("--toolkit", "-t", help="the name or url of a required toolkit"),
|
|
257
|
+
] = [],
|
|
258
|
+
schema: Annotated[
|
|
259
|
+
List[str],
|
|
260
|
+
typer.Option("--schema", "-s", help="the name or url of a required schema"),
|
|
261
|
+
] = [],
|
|
262
|
+
model: Annotated[
|
|
263
|
+
str, typer.Option(..., help="Name of the LLM model to use for the chatbot")
|
|
264
|
+
] = "gpt-5",
|
|
265
|
+
image_generation: Annotated[
|
|
266
|
+
Optional[str], typer.Option(..., help="Name of an image gen model")
|
|
267
|
+
] = None,
|
|
268
|
+
local_shell: Annotated[
|
|
269
|
+
Optional[bool], typer.Option(..., help="Enable local shell tool calling")
|
|
270
|
+
] = False,
|
|
271
|
+
computer_use: Annotated[
|
|
272
|
+
Optional[bool],
|
|
273
|
+
typer.Option(
|
|
274
|
+
..., help="Enable computer use (requires computer-use-preview model)"
|
|
275
|
+
),
|
|
276
|
+
] = False,
|
|
277
|
+
web_search: Annotated[
|
|
278
|
+
Optional[bool], typer.Option(..., help="Enable web search tool calling")
|
|
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,
|
|
286
|
+
host: Annotated[Optional[str], typer.Option()] = None,
|
|
287
|
+
port: Annotated[Optional[int], typer.Option()] = None,
|
|
288
|
+
path: Annotated[str, typer.Option()] = "/agent",
|
|
289
|
+
):
|
|
290
|
+
print("[bold green]Connecting to room...[/bold green]", flush=True)
|
|
291
|
+
|
|
292
|
+
service = ServiceHost(host=host, port=port)
|
|
293
|
+
service.add_path(
|
|
294
|
+
path=path,
|
|
295
|
+
cls=build_chatbot(
|
|
296
|
+
computer_use=computer_use,
|
|
297
|
+
model=model,
|
|
298
|
+
local_shell=local_shell,
|
|
299
|
+
agent_name=agent_name,
|
|
300
|
+
rule=rule,
|
|
301
|
+
toolkit=toolkit,
|
|
302
|
+
schema=schema,
|
|
303
|
+
web_search=web_search,
|
|
304
|
+
image_generation=image_generation,
|
|
305
|
+
rules_file=rules_file,
|
|
306
|
+
mcp=mcp,
|
|
307
|
+
storage=storage,
|
|
308
|
+
),
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
await service.run()
|
meshagent/cli/cli.py
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
import asyncio
|
|
3
|
+
|
|
4
|
+
from meshagent.cli import async_typer
|
|
5
|
+
|
|
6
|
+
from meshagent.cli import queue
|
|
7
|
+
from meshagent.cli import auth
|
|
8
|
+
from meshagent.cli import api_keys
|
|
9
|
+
from meshagent.cli import projects
|
|
10
|
+
from meshagent.cli import sessions
|
|
11
|
+
from meshagent.cli import participant_token
|
|
12
|
+
from meshagent.cli import agent
|
|
13
|
+
from meshagent.cli import messaging
|
|
14
|
+
from meshagent.cli import storage
|
|
15
|
+
from meshagent.cli import developer
|
|
16
|
+
from meshagent.cli import webhook
|
|
17
|
+
from meshagent.cli import services
|
|
18
|
+
from meshagent.cli import cli_secrets
|
|
19
|
+
from meshagent.cli import call
|
|
20
|
+
from meshagent.cli import cli_mcp
|
|
21
|
+
from meshagent.cli import chatbot
|
|
22
|
+
from meshagent.cli import voicebot
|
|
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
|
|
28
|
+
from meshagent.cli.exec import register as register_exec
|
|
29
|
+
from meshagent.cli.version import __version__
|
|
30
|
+
from meshagent.cli.helper import get_active_api_key
|
|
31
|
+
from meshagent.otel import otel_config
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
from art import tprint
|
|
35
|
+
|
|
36
|
+
import logging
|
|
37
|
+
|
|
38
|
+
import os
|
|
39
|
+
import sys
|
|
40
|
+
from pathlib import Path
|
|
41
|
+
|
|
42
|
+
otel_config(service_name="meshagent-cli")
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# Turn down OpenAI logs, they are a bit noisy
|
|
46
|
+
logging.getLogger("openai").setLevel(logging.ERROR)
|
|
47
|
+
logging.getLogger("httpx").setLevel(logging.ERROR)
|
|
48
|
+
|
|
49
|
+
app = async_typer.AsyncTyper(no_args_is_help=True)
|
|
50
|
+
app.add_typer(call.app, name="call")
|
|
51
|
+
app.add_typer(auth.app, name="auth")
|
|
52
|
+
app.add_typer(projects.app, name="project")
|
|
53
|
+
app.add_typer(api_keys.app, name="api-key")
|
|
54
|
+
app.add_typer(sessions.app, name="session")
|
|
55
|
+
app.add_typer(participant_token.app, name="participant-token")
|
|
56
|
+
app.add_typer(agent.app, name="agents")
|
|
57
|
+
app.add_typer(messaging.app, name="messaging")
|
|
58
|
+
app.add_typer(storage.app, name="storage")
|
|
59
|
+
app.add_typer(developer.app, name="developer")
|
|
60
|
+
app.add_typer(webhook.app, name="webhook")
|
|
61
|
+
app.add_typer(services.app, name="service")
|
|
62
|
+
app.add_typer(cli_secrets.app, name="secret")
|
|
63
|
+
app.add_typer(queue.app, name="queue")
|
|
64
|
+
app.add_typer(cli_mcp.app, name="mcp")
|
|
65
|
+
app.add_typer(chatbot.app, name="chatbot")
|
|
66
|
+
app.add_typer(voicebot.app, name="voicebot")
|
|
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")
|
|
72
|
+
|
|
73
|
+
register_exec(app)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _run_async(coro):
|
|
77
|
+
asyncio.run(coro)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def detect_shell() -> str:
|
|
81
|
+
"""
|
|
82
|
+
Best-effort detection of the *current* interactive shell.
|
|
83
|
+
|
|
84
|
+
Order of preference
|
|
85
|
+
1. Explicit --shell argument (handled by Typer)
|
|
86
|
+
2. Per-shell env vars set by the running shell
|
|
87
|
+
• BASH_VERSION / ZSH_VERSION / FISH_VERSION
|
|
88
|
+
3. $SHELL on POSIX (user’s login shell – still correct >90 % of the time)
|
|
89
|
+
4. Parent process on Windows (COMSPEC → cmd / powershell)
|
|
90
|
+
5. Safe default: 'bash'
|
|
91
|
+
"""
|
|
92
|
+
# Per-shell version variables (works even if login shell ≠ current shell)
|
|
93
|
+
for var, name in (
|
|
94
|
+
("ZSH_VERSION", "zsh"),
|
|
95
|
+
("BASH_VERSION", "bash"),
|
|
96
|
+
("FISH_VERSION", "fish"),
|
|
97
|
+
):
|
|
98
|
+
if var in os.environ:
|
|
99
|
+
return name
|
|
100
|
+
|
|
101
|
+
# POSIX fallback: login shell path
|
|
102
|
+
sh = os.environ.get("SHELL")
|
|
103
|
+
if sh:
|
|
104
|
+
return Path(sh).name.lower()
|
|
105
|
+
|
|
106
|
+
# Windows heuristics
|
|
107
|
+
if sys.platform == "win32":
|
|
108
|
+
comspec = Path(os.environ.get("COMSPEC", "")).name.lower()
|
|
109
|
+
if "powershell" in comspec:
|
|
110
|
+
return "powershell"
|
|
111
|
+
if "cmd" in comspec:
|
|
112
|
+
return "cmd"
|
|
113
|
+
return "powershell" # sensible default on modern Windows
|
|
114
|
+
|
|
115
|
+
# Last-ditch default
|
|
116
|
+
return "bash"
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def _bash_like(name: str, value: str, unset: bool) -> str:
|
|
120
|
+
return f"unset {name}" if unset else f'export {name}="{value}"'
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def _fish(name: str, value: str, unset: bool) -> str:
|
|
124
|
+
return f"set -e {name}" if unset else f'set -gx {name} "{value}"'
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def _powershell(name: str, value: str, unset: bool) -> str:
|
|
128
|
+
return f"Remove-Item Env:{name}" if unset else f'$Env:{name}="{value}"'
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def _cmd(name: str, value: str, unset: bool) -> str:
|
|
132
|
+
return f"set {name}=" if unset else f"set {name}={value}"
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
SHELL_RENDERERS = {
|
|
136
|
+
"bash": _bash_like,
|
|
137
|
+
"zsh": _bash_like,
|
|
138
|
+
"fish": _fish,
|
|
139
|
+
"powershell": _powershell,
|
|
140
|
+
"cmd": _cmd,
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
@app.command(
|
|
145
|
+
"version",
|
|
146
|
+
help="Print the version",
|
|
147
|
+
)
|
|
148
|
+
def version():
|
|
149
|
+
print(__version__)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
@app.command("setup")
|
|
153
|
+
def setup_command():
|
|
154
|
+
"""Perform initial login and project/api key activation."""
|
|
155
|
+
|
|
156
|
+
async def runner():
|
|
157
|
+
print("\n", flush=True)
|
|
158
|
+
tprint("MeshAgent", "tarty10")
|
|
159
|
+
print("\n", flush=True)
|
|
160
|
+
await auth.login()
|
|
161
|
+
print("Activate a project...")
|
|
162
|
+
project_id = await projects.activate(None, interactive=True)
|
|
163
|
+
if project_id is None:
|
|
164
|
+
print("You have choosen to not activate a project. Exiting.")
|
|
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
|
+
)
|
|
179
|
+
|
|
180
|
+
_run_async(runner())
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
if __name__ == "__main__":
|
|
184
|
+
app()
|