meshagent-cli 0.0.36__py3-none-any.whl → 0.0.38__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 -1
- meshagent/cli/agent.py +139 -70
- meshagent/cli/api_keys.py +27 -9
- meshagent/cli/auth.py +9 -4
- meshagent/cli/auth_async.py +40 -17
- meshagent/cli/call.py +45 -36
- meshagent/cli/chatbot.py +127 -73
- meshagent/cli/cli.py +32 -19
- meshagent/cli/cli_mcp.py +183 -79
- meshagent/cli/cli_secrets.py +50 -20
- meshagent/cli/developer.py +19 -9
- meshagent/cli/helper.py +59 -39
- meshagent/cli/messaging.py +54 -31
- meshagent/cli/otel.py +36 -32
- meshagent/cli/participant_token.py +21 -12
- meshagent/cli/projects.py +3 -2
- meshagent/cli/services.py +50 -29
- meshagent/cli/sessions.py +9 -3
- meshagent/cli/storage.py +222 -94
- meshagent/cli/tty.py +24 -28
- meshagent/cli/version.py +1 -1
- meshagent/cli/voicebot.py +57 -34
- meshagent/cli/webhook.py +14 -5
- meshagent_cli-0.0.38.dist-info/METADATA +35 -0
- meshagent_cli-0.0.38.dist-info/RECORD +29 -0
- meshagent_cli-0.0.36.dist-info/METADATA +0 -28
- meshagent_cli-0.0.36.dist-info/RECORD +0 -29
- {meshagent_cli-0.0.36.dist-info → meshagent_cli-0.0.38.dist-info}/WHEEL +0 -0
- {meshagent_cli-0.0.36.dist-info → meshagent_cli-0.0.38.dist-info}/entry_points.txt +0 -0
- {meshagent_cli-0.0.36.dist-info → meshagent_cli-0.0.38.dist-info}/top_level.txt +0 -0
meshagent/cli/call.py
CHANGED
|
@@ -1,35 +1,37 @@
|
|
|
1
|
-
|
|
2
1
|
import typer
|
|
3
2
|
from rich import print
|
|
4
3
|
from typing import Annotated, Optional
|
|
5
4
|
import json
|
|
6
5
|
import aiohttp
|
|
7
|
-
from meshagent.api import
|
|
6
|
+
from meshagent.api import (
|
|
7
|
+
RoomClient,
|
|
8
|
+
ParticipantToken,
|
|
9
|
+
WebSocketClientProtocol,
|
|
10
|
+
ParticipantGrant,
|
|
11
|
+
)
|
|
8
12
|
from meshagent.api.helpers import meshagent_base_url, websocket_room_url
|
|
9
13
|
from meshagent.api.services import send_webhook
|
|
10
14
|
from meshagent.cli import async_typer
|
|
11
|
-
from meshagent.cli.helper import get_client,
|
|
12
|
-
from meshagent.cli.helper import
|
|
13
|
-
|
|
14
|
-
app = async_typer.AsyncTyper()
|
|
15
|
-
|
|
15
|
+
from meshagent.cli.helper import get_client, resolve_project_id
|
|
16
|
+
from meshagent.cli.helper import resolve_api_key
|
|
16
17
|
from urllib.parse import urlparse
|
|
17
18
|
from pathlib import PurePath
|
|
18
19
|
import socket
|
|
19
20
|
import ipaddress
|
|
20
21
|
|
|
22
|
+
app = async_typer.AsyncTyper()
|
|
23
|
+
|
|
21
24
|
PRIVATE_NETS = (
|
|
22
25
|
ipaddress.ip_network("10.0.0.0/8"),
|
|
23
26
|
ipaddress.ip_network("172.16.0.0/12"),
|
|
24
27
|
ipaddress.ip_network("192.168.0.0/16"),
|
|
25
|
-
ipaddress.ip_network("169.254.0.0/16"),
|
|
26
|
-
ipaddress.ip_network("fc00::/7"),
|
|
27
|
-
ipaddress.ip_network("fe80::/10"),
|
|
28
|
+
ipaddress.ip_network("169.254.0.0/16"), # IPv4 link-local
|
|
29
|
+
ipaddress.ip_network("fc00::/7"), # IPv6 unique-local
|
|
30
|
+
ipaddress.ip_network("fe80::/10"), # IPv6 link-local
|
|
28
31
|
)
|
|
29
32
|
|
|
30
33
|
|
|
31
34
|
def is_local_url(url: str) -> bool:
|
|
32
|
-
|
|
33
35
|
"""
|
|
34
36
|
Return True if *url* points to the local machine or a private-LAN host.
|
|
35
37
|
"""
|
|
@@ -42,14 +44,14 @@ def is_local_url(url: str) -> bool:
|
|
|
42
44
|
|
|
43
45
|
# 2. Quick loop-back check on hostname literal
|
|
44
46
|
hostname = parsed.hostname
|
|
45
|
-
if hostname in {"localhost", None}:
|
|
47
|
+
if hostname in {"localhost", None}: # None ⇒ something like "http:///path"
|
|
46
48
|
return True
|
|
47
49
|
|
|
48
50
|
try:
|
|
49
51
|
# Accept both direct IP literals and DNS names
|
|
50
52
|
addr_info = socket.getaddrinfo(hostname, None)
|
|
51
53
|
except socket.gaierror:
|
|
52
|
-
return False
|
|
54
|
+
return False # Unresolvable host ⇒ treat as non-local (or raise)
|
|
53
55
|
|
|
54
56
|
for *_, sockaddr in addr_info:
|
|
55
57
|
ip_str = sockaddr[0]
|
|
@@ -75,7 +77,9 @@ async def make_call(
|
|
|
75
77
|
local: Optional[bool] = None,
|
|
76
78
|
agent_name: Annotated[str, typer.Option(..., help="Name of the agent to call")],
|
|
77
79
|
url: Annotated[str, typer.Option(..., help="URL the agent should call")],
|
|
78
|
-
arguments: Annotated[
|
|
80
|
+
arguments: Annotated[
|
|
81
|
+
str, typer.Option(..., help="JSON string with arguments for the call")
|
|
82
|
+
] = {},
|
|
79
83
|
):
|
|
80
84
|
"""
|
|
81
85
|
Instruct an agent to 'call' a given URL with specific arguments.
|
|
@@ -84,46 +88,51 @@ async def make_call(
|
|
|
84
88
|
try:
|
|
85
89
|
project_id = await resolve_project_id(project_id=project_id)
|
|
86
90
|
api_key_id = await resolve_api_key(project_id, api_key_id)
|
|
87
|
-
|
|
88
|
-
key = (
|
|
91
|
+
|
|
92
|
+
key = (
|
|
93
|
+
await account_client.decrypt_project_api_key(
|
|
94
|
+
project_id=project_id, id=api_key_id
|
|
95
|
+
)
|
|
96
|
+
)["token"]
|
|
89
97
|
|
|
90
98
|
token = ParticipantToken(
|
|
91
|
-
name=name,
|
|
92
|
-
project_id=project_id,
|
|
93
|
-
api_key_id=api_key_id
|
|
99
|
+
name=name, project_id=project_id, api_key_id=api_key_id
|
|
94
100
|
)
|
|
95
101
|
token.add_role_grant(role=role)
|
|
96
102
|
token.add_room_grant(room)
|
|
97
103
|
token.grants.append(ParticipantGrant(name="tunnel_ports", scope="9000"))
|
|
98
104
|
|
|
99
|
-
if local
|
|
105
|
+
if local is None:
|
|
100
106
|
local = is_local_url(url)
|
|
101
|
-
|
|
107
|
+
|
|
102
108
|
if local:
|
|
103
109
|
async with aiohttp.ClientSession() as session:
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
"
|
|
108
|
-
"
|
|
109
|
-
"
|
|
110
|
-
"arguments" : arguments,
|
|
110
|
+
event = "room.call"
|
|
111
|
+
data = {
|
|
112
|
+
"room_url": websocket_room_url(room_name=room),
|
|
113
|
+
"room_name": room,
|
|
114
|
+
"token": token.to_jwt(token=key),
|
|
115
|
+
"arguments": arguments,
|
|
111
116
|
}
|
|
112
|
-
|
|
113
|
-
await send_webhook(
|
|
117
|
+
|
|
118
|
+
await send_webhook(
|
|
119
|
+
session=session, url=url, event=event, data=data, secret=None
|
|
120
|
+
)
|
|
114
121
|
else:
|
|
115
122
|
print("[bold green]Connecting to room...[/bold green]")
|
|
116
123
|
async with RoomClient(
|
|
117
|
-
protocol=WebSocketClientProtocol(
|
|
118
|
-
|
|
124
|
+
protocol=WebSocketClientProtocol(
|
|
125
|
+
url=websocket_room_url(
|
|
126
|
+
room_name=room, base_url=meshagent_base_url()
|
|
127
|
+
),
|
|
128
|
+
token=token.to_jwt(token=key),
|
|
129
|
+
)
|
|
119
130
|
) as client:
|
|
120
131
|
print("[bold green]Making agent call...[/bold green]")
|
|
121
132
|
await client.agents.make_call(
|
|
122
|
-
name=agent_name,
|
|
123
|
-
url=url,
|
|
124
|
-
arguments=json.loads(arguments)
|
|
133
|
+
name=agent_name, url=url, arguments=json.loads(arguments)
|
|
125
134
|
)
|
|
126
135
|
print("[bold cyan]Call request sent successfully.[/bold cyan]")
|
|
127
|
-
|
|
136
|
+
|
|
128
137
|
finally:
|
|
129
138
|
await account_client.close()
|
meshagent/cli/chatbot.py
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
|
|
2
1
|
import typer
|
|
3
2
|
from rich import print
|
|
4
3
|
from typing import Annotated, Optional
|
|
5
4
|
from meshagent.tools import Toolkit
|
|
6
|
-
from meshagent.api import RoomClient,
|
|
5
|
+
from meshagent.api import RoomClient, WebSocketClientProtocol
|
|
7
6
|
from meshagent.api.helpers import meshagent_base_url, websocket_room_url
|
|
8
7
|
from meshagent.cli import async_typer
|
|
9
|
-
from meshagent.cli.helper import
|
|
8
|
+
from meshagent.cli.helper import (
|
|
9
|
+
get_client,
|
|
10
|
+
resolve_project_id,
|
|
11
|
+
resolve_api_key,
|
|
12
|
+
resolve_token_jwt,
|
|
13
|
+
resolve_room,
|
|
14
|
+
)
|
|
10
15
|
from meshagent.agents.chat import ChatBot
|
|
11
16
|
from meshagent.openai import OpenAIResponsesAdapter
|
|
12
17
|
from meshagent.openai.tools.responses_adapter import LocalShellTool
|
|
@@ -21,24 +26,24 @@ from meshagent.api import RequiredToolkit, RequiredSchema
|
|
|
21
26
|
app = async_typer.AsyncTyper()
|
|
22
27
|
|
|
23
28
|
|
|
24
|
-
def build_chatbot(
|
|
29
|
+
def build_chatbot(
|
|
30
|
+
*,
|
|
25
31
|
model: str,
|
|
26
|
-
agent_name: str,
|
|
32
|
+
agent_name: str,
|
|
27
33
|
rule: List[str],
|
|
28
34
|
toolkit: List[str],
|
|
29
35
|
schema: List[str],
|
|
30
36
|
image_generation: Optional[str] = None,
|
|
31
37
|
local_shell: bool,
|
|
32
|
-
computer_use: bool
|
|
38
|
+
computer_use: bool,
|
|
33
39
|
):
|
|
34
|
-
|
|
35
40
|
requirements = []
|
|
36
|
-
|
|
41
|
+
|
|
37
42
|
toolkits = []
|
|
38
43
|
|
|
39
44
|
for t in toolkit:
|
|
40
45
|
requirements.append(RequiredToolkit(name=t))
|
|
41
|
-
|
|
46
|
+
|
|
42
47
|
for t in schema:
|
|
43
48
|
requirements.append(RequiredSchema(name=t))
|
|
44
49
|
|
|
@@ -49,16 +54,13 @@ def build_chatbot(*,
|
|
|
49
54
|
llm_adapter = OpenAIResponsesAdapter(
|
|
50
55
|
model=model,
|
|
51
56
|
response_options={
|
|
52
|
-
"reasoning" :
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
"truncation" : "auto"
|
|
56
|
-
}
|
|
57
|
+
"reasoning": {"generate_summary": "concise"},
|
|
58
|
+
"truncation": "auto",
|
|
59
|
+
},
|
|
57
60
|
)
|
|
58
61
|
else:
|
|
59
|
-
llm_adapter = OpenAIResponsesAdapter(
|
|
60
|
-
|
|
61
|
-
)
|
|
62
|
+
llm_adapter = OpenAIResponsesAdapter(model=model)
|
|
63
|
+
|
|
62
64
|
class CustomChatbot(BaseClass):
|
|
63
65
|
def __init__(self):
|
|
64
66
|
super().__init__(
|
|
@@ -66,31 +68,35 @@ def build_chatbot(*,
|
|
|
66
68
|
name=agent_name,
|
|
67
69
|
requires=requirements,
|
|
68
70
|
toolkits=toolkits,
|
|
69
|
-
rules=rule if len(rule) > 0 else None
|
|
71
|
+
rules=rule if len(rule) > 0 else None,
|
|
70
72
|
)
|
|
71
|
-
|
|
73
|
+
|
|
72
74
|
async def get_thread_toolkits(self, *, thread_context, participant):
|
|
73
|
-
toolkits = await super().get_thread_toolkits(
|
|
74
|
-
|
|
75
|
+
toolkits = await super().get_thread_toolkits(
|
|
76
|
+
thread_context=thread_context, participant=participant
|
|
77
|
+
)
|
|
78
|
+
|
|
75
79
|
thread_toolkit = Toolkit(name="thread_toolkit", tools=[])
|
|
76
80
|
|
|
77
81
|
if local_shell:
|
|
78
|
-
thread_toolkit.tools.append(LocalShellTool())
|
|
82
|
+
thread_toolkit.tools.append(LocalShellTool())
|
|
79
83
|
|
|
80
|
-
if image_generation
|
|
81
|
-
|
|
84
|
+
if image_generation is not None:
|
|
82
85
|
print("adding openai image gen to thread", flush=True)
|
|
83
|
-
thread_toolkit.tools.append(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
86
|
+
thread_toolkit.tools.append(
|
|
87
|
+
ChatBotThreadOpenAIImageGenerationTool(
|
|
88
|
+
model=image_generation,
|
|
89
|
+
thread_context=thread_context,
|
|
90
|
+
partial_images=3,
|
|
91
|
+
)
|
|
92
|
+
)
|
|
93
|
+
|
|
89
94
|
toolkits.append(thread_toolkit)
|
|
90
95
|
return toolkits
|
|
91
|
-
|
|
96
|
+
|
|
92
97
|
return CustomChatbot
|
|
93
98
|
|
|
99
|
+
|
|
94
100
|
@app.async_command("join")
|
|
95
101
|
async def make_call(
|
|
96
102
|
*,
|
|
@@ -100,15 +106,31 @@ async def make_call(
|
|
|
100
106
|
name: Annotated[str, typer.Option(..., help="Participant name")] = "cli",
|
|
101
107
|
role: str = "agent",
|
|
102
108
|
agent_name: Annotated[str, typer.Option(..., help="Name of the agent to call")],
|
|
103
|
-
token_path: Annotated[Optional[str], typer.Option()] = None,
|
|
104
|
-
|
|
109
|
+
token_path: Annotated[Optional[str], typer.Option()] = None,
|
|
105
110
|
rule: Annotated[List[str], typer.Option("--rule", "-r", help="a system rule")] = [],
|
|
106
|
-
toolkit: Annotated[
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
111
|
+
toolkit: Annotated[
|
|
112
|
+
List[str],
|
|
113
|
+
typer.Option("--toolkit", "-t", help="the name or url of a required toolkit"),
|
|
114
|
+
] = [],
|
|
115
|
+
schema: Annotated[
|
|
116
|
+
List[str],
|
|
117
|
+
typer.Option("--schema", "-s", help="the name or url of a required schema"),
|
|
118
|
+
] = [],
|
|
119
|
+
model: Annotated[
|
|
120
|
+
str, typer.Option(..., help="Name of the LLM model to use for the chatbot")
|
|
121
|
+
] = "gpt-4o",
|
|
122
|
+
image_generation: Annotated[
|
|
123
|
+
Optional[str], typer.Option(..., help="Name of an image gen model")
|
|
124
|
+
] = None,
|
|
125
|
+
computer_use: Annotated[
|
|
126
|
+
Optional[bool],
|
|
127
|
+
typer.Option(
|
|
128
|
+
..., help="Enable computer use (requires computer-use-preview model)"
|
|
129
|
+
),
|
|
130
|
+
] = False,
|
|
131
|
+
local_shell: Annotated[
|
|
132
|
+
Optional[bool], typer.Option(..., help="Enable local shell tool calling")
|
|
133
|
+
] = False,
|
|
112
134
|
):
|
|
113
135
|
account_client = await get_client()
|
|
114
136
|
try:
|
|
@@ -116,75 +138,107 @@ async def make_call(
|
|
|
116
138
|
api_key_id = await resolve_api_key(project_id, api_key_id)
|
|
117
139
|
|
|
118
140
|
room = resolve_room(room)
|
|
119
|
-
jwt = await resolve_token_jwt(
|
|
120
|
-
|
|
141
|
+
jwt = await resolve_token_jwt(
|
|
142
|
+
project_id=project_id,
|
|
143
|
+
api_key_id=api_key_id,
|
|
144
|
+
token_path=token_path,
|
|
145
|
+
name=name,
|
|
146
|
+
role=role,
|
|
147
|
+
room=room,
|
|
148
|
+
)
|
|
149
|
+
|
|
121
150
|
print("[bold green]Connecting to room...[/bold green]", flush=True)
|
|
122
151
|
async with RoomClient(
|
|
123
152
|
protocol=WebSocketClientProtocol(
|
|
124
153
|
url=websocket_room_url(room_name=room, base_url=meshagent_base_url()),
|
|
125
|
-
token=jwt
|
|
154
|
+
token=jwt,
|
|
126
155
|
)
|
|
127
156
|
) as client:
|
|
128
|
-
|
|
129
157
|
requirements = []
|
|
130
|
-
|
|
131
|
-
toolkits = []
|
|
132
158
|
|
|
133
159
|
for t in toolkit:
|
|
134
160
|
requirements.append(RequiredToolkit(name=t))
|
|
135
|
-
|
|
161
|
+
|
|
136
162
|
for t in schema:
|
|
137
163
|
requirements.append(RequiredSchema(name=t))
|
|
138
164
|
|
|
139
|
-
CustomChatbot = build_chatbot(
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
165
|
+
CustomChatbot = build_chatbot(
|
|
166
|
+
computer_use=computer_use,
|
|
167
|
+
model=model,
|
|
168
|
+
local_shell=local_shell,
|
|
169
|
+
agent_name=agent_name,
|
|
170
|
+
rule=rule,
|
|
171
|
+
toolkit=toolkit,
|
|
172
|
+
schema=schema,
|
|
173
|
+
image_generation=image_generation,
|
|
147
174
|
)
|
|
148
175
|
|
|
176
|
+
bot = CustomChatbot()
|
|
177
|
+
|
|
149
178
|
await bot.start(room=client)
|
|
150
179
|
try:
|
|
180
|
+
print(
|
|
181
|
+
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]",
|
|
182
|
+
flush=True,
|
|
183
|
+
)
|
|
151
184
|
await client.protocol.wait_for_close()
|
|
152
185
|
except KeyboardInterrupt:
|
|
153
186
|
await bot.stop()
|
|
154
|
-
|
|
187
|
+
|
|
155
188
|
finally:
|
|
156
189
|
await account_client.close()
|
|
157
190
|
|
|
158
191
|
|
|
159
|
-
|
|
160
192
|
@app.async_command("service")
|
|
161
193
|
async def service(
|
|
162
194
|
*,
|
|
163
195
|
room: Annotated[Optional[str], typer.Option()] = None,
|
|
164
|
-
|
|
165
196
|
agent_name: Annotated[str, typer.Option(..., help="Name of the agent to call")],
|
|
166
|
-
|
|
167
197
|
rule: Annotated[List[str], typer.Option("--rule", "-r", help="a system rule")] = [],
|
|
168
|
-
toolkit: Annotated[
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
198
|
+
toolkit: Annotated[
|
|
199
|
+
List[str],
|
|
200
|
+
typer.Option("--toolkit", "-t", help="the name or url of a required toolkit"),
|
|
201
|
+
] = [],
|
|
202
|
+
schema: Annotated[
|
|
203
|
+
List[str],
|
|
204
|
+
typer.Option("--schema", "-s", help="the name or url of a required schema"),
|
|
205
|
+
] = [],
|
|
206
|
+
model: Annotated[
|
|
207
|
+
str, typer.Option(..., help="Name of the LLM model to use for the chatbot")
|
|
208
|
+
] = "gpt-4o",
|
|
209
|
+
image_generation: Annotated[
|
|
210
|
+
Optional[str], typer.Option(..., help="Name of an image gen model")
|
|
211
|
+
] = None,
|
|
212
|
+
local_shell: Annotated[
|
|
213
|
+
Optional[bool], typer.Option(..., help="Enable local shell tool calling")
|
|
214
|
+
] = False,
|
|
215
|
+
computer_use: Annotated[
|
|
216
|
+
Optional[bool],
|
|
217
|
+
typer.Option(
|
|
218
|
+
..., help="Enable computer use (requires computer-use-preview model)"
|
|
219
|
+
),
|
|
220
|
+
] = False,
|
|
221
|
+
host: Annotated[Optional[str], typer.Option()] = None,
|
|
222
|
+
port: Annotated[Optional[int], typer.Option()] = None,
|
|
177
223
|
path: Annotated[str, typer.Option()] = "/agent",
|
|
178
224
|
):
|
|
179
|
-
|
|
180
225
|
room = resolve_room(room)
|
|
181
|
-
|
|
226
|
+
|
|
182
227
|
print("[bold green]Connecting to room...[/bold green]", flush=True)
|
|
183
228
|
|
|
184
|
-
service = ServiceHost(
|
|
185
|
-
|
|
186
|
-
|
|
229
|
+
service = ServiceHost(host=host, port=port)
|
|
230
|
+
service.add_path(
|
|
231
|
+
path=path,
|
|
232
|
+
cls=build_chatbot(
|
|
233
|
+
computer_use=computer_use,
|
|
234
|
+
model=model,
|
|
235
|
+
local_shell=local_shell,
|
|
236
|
+
agent_name=agent_name,
|
|
237
|
+
rule=rule,
|
|
238
|
+
toolkit=toolkit,
|
|
239
|
+
schema=schema,
|
|
240
|
+
image_generation=image_generation,
|
|
241
|
+
),
|
|
187
242
|
)
|
|
188
|
-
service.add_path(path=path, cls=build_chatbot(computer_use=computer_use, model=model, local_shell=local_shell, agent_name=agent_name, rule=rule, toolkit=toolkit, schema=schema, image_generation=image_generation))
|
|
189
243
|
|
|
190
244
|
await service.run()
|
meshagent/cli/cli.py
CHANGED
|
@@ -22,8 +22,16 @@ from meshagent.cli import tty
|
|
|
22
22
|
|
|
23
23
|
from meshagent.cli import otel
|
|
24
24
|
|
|
25
|
+
from art import tprint
|
|
26
|
+
|
|
25
27
|
import logging
|
|
26
28
|
|
|
29
|
+
import os
|
|
30
|
+
import sys
|
|
31
|
+
from pathlib import Path
|
|
32
|
+
from meshagent.cli.helper import get_client, resolve_project_id, resolve_api_key
|
|
33
|
+
|
|
34
|
+
|
|
27
35
|
otel.init(level=logging.INFO)
|
|
28
36
|
|
|
29
37
|
# Turn down OpenAI logs, they are a bit noisy
|
|
@@ -49,16 +57,11 @@ app.add_typer(chatbot.app, name="chatbot")
|
|
|
49
57
|
app.add_typer(voicebot.app, name="voicebot")
|
|
50
58
|
app.add_typer(tty.app, name="tty")
|
|
51
59
|
|
|
60
|
+
|
|
52
61
|
def _run_async(coro):
|
|
53
62
|
asyncio.run(coro)
|
|
54
63
|
|
|
55
64
|
|
|
56
|
-
import os, sys
|
|
57
|
-
from pathlib import Path
|
|
58
|
-
import typer
|
|
59
|
-
from meshagent.cli.helper import get_client, set_active_project, get_active_project, resolve_project_id, resolve_api_key
|
|
60
|
-
|
|
61
|
-
|
|
62
65
|
def detect_shell() -> str:
|
|
63
66
|
"""
|
|
64
67
|
Best-effort detection of the *current* interactive shell.
|
|
@@ -99,19 +102,19 @@ def detect_shell() -> str:
|
|
|
99
102
|
|
|
100
103
|
|
|
101
104
|
def _bash_like(name: str, value: str, unset: bool) -> str:
|
|
102
|
-
return f
|
|
105
|
+
return f"unset {name}" if unset else f'export {name}="{value}"'
|
|
103
106
|
|
|
104
107
|
|
|
105
108
|
def _fish(name: str, value: str, unset: bool) -> str:
|
|
106
|
-
return f
|
|
109
|
+
return f"set -e {name}" if unset else f'set -gx {name} "{value}"'
|
|
107
110
|
|
|
108
111
|
|
|
109
112
|
def _powershell(name: str, value: str, unset: bool) -> str:
|
|
110
|
-
return f
|
|
113
|
+
return f"Remove-Item Env:{name}" if unset else f'$Env:{name}="{value}"'
|
|
111
114
|
|
|
112
115
|
|
|
113
116
|
def _cmd(name: str, value: str, unset: bool) -> str:
|
|
114
|
-
return f
|
|
117
|
+
return f"set {name}=" if unset else f"set {name}={value}"
|
|
115
118
|
|
|
116
119
|
|
|
117
120
|
SHELL_RENDERERS = {
|
|
@@ -128,7 +131,8 @@ SHELL_RENDERERS = {
|
|
|
128
131
|
help="Generate commands to set meshagent environment variables.",
|
|
129
132
|
)
|
|
130
133
|
def env(
|
|
131
|
-
shell: Optional[str] = typer.Option(
|
|
134
|
+
shell: Optional[str] = typer.Option(
|
|
135
|
+
None,
|
|
132
136
|
"--shell",
|
|
133
137
|
case_sensitive=False,
|
|
134
138
|
help="bash | zsh | fish | powershell | cmd",
|
|
@@ -138,7 +142,7 @@ def env(
|
|
|
138
142
|
),
|
|
139
143
|
):
|
|
140
144
|
"""Print shell-specific exports/unsets for Docker environment variables."""
|
|
141
|
-
|
|
145
|
+
|
|
142
146
|
async def command():
|
|
143
147
|
nonlocal shell, unset
|
|
144
148
|
shell = (shell or detect_shell()).lower()
|
|
@@ -151,14 +155,18 @@ def env(
|
|
|
151
155
|
project_id = await resolve_project_id(project_id=None)
|
|
152
156
|
api_key_id = await resolve_api_key(project_id=project_id, api_key_id=None)
|
|
153
157
|
|
|
154
|
-
token = (
|
|
158
|
+
token = (
|
|
159
|
+
await client.decrypt_project_api_key(
|
|
160
|
+
project_id=project_id, id=api_key_id
|
|
161
|
+
)
|
|
162
|
+
)["token"]
|
|
155
163
|
finally:
|
|
156
164
|
await client.close()
|
|
157
165
|
|
|
158
166
|
vars = {
|
|
159
|
-
"MESHAGENT_PROJECT_ID"
|
|
160
|
-
"MESHAGENT_API_KEY"
|
|
161
|
-
"MESHAGENT_SECRET"
|
|
167
|
+
"MESHAGENT_PROJECT_ID": project_id,
|
|
168
|
+
"MESHAGENT_API_KEY": api_key_id,
|
|
169
|
+
"MESHAGENT_SECRET": token,
|
|
162
170
|
}
|
|
163
171
|
if shell not in SHELL_RENDERERS:
|
|
164
172
|
typer.echo(f"Unsupported shell '{shell}'.", err=True)
|
|
@@ -171,17 +179,21 @@ def env(
|
|
|
171
179
|
|
|
172
180
|
if not unset and shell in ("bash", "zsh"):
|
|
173
181
|
typer.echo(
|
|
174
|
-
|
|
175
|
-
|
|
182
|
+
"\n# Run this command to configure your current shell:\n"
|
|
183
|
+
'# eval "$(meshagent env)"'
|
|
176
184
|
)
|
|
177
|
-
|
|
185
|
+
|
|
178
186
|
_run_async(command())
|
|
179
187
|
|
|
188
|
+
|
|
180
189
|
@app.command("setup")
|
|
181
190
|
def setup_command():
|
|
182
191
|
"""Perform initial login and project/api key activation."""
|
|
183
192
|
|
|
184
193
|
async def runner():
|
|
194
|
+
print("\n", flush=True)
|
|
195
|
+
tprint("MeshAgent", "tarty10")
|
|
196
|
+
print("\n", flush=True)
|
|
185
197
|
await auth.login()
|
|
186
198
|
print("Activate a project...")
|
|
187
199
|
project_id = await projects.activate(None, interactive=True)
|
|
@@ -195,5 +207,6 @@ def setup_command():
|
|
|
195
207
|
|
|
196
208
|
_run_async(runner())
|
|
197
209
|
|
|
210
|
+
|
|
198
211
|
if __name__ == "__main__":
|
|
199
212
|
app()
|