meshagent-cli 0.0.37__py3-none-any.whl → 0.0.39__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 +126 -68
- 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 -35
- meshagent/cli/webhook.py +14 -5
- meshagent_cli-0.0.39.dist-info/METADATA +35 -0
- meshagent_cli-0.0.39.dist-info/RECORD +29 -0
- meshagent_cli-0.0.37.dist-info/METADATA +0 -28
- meshagent_cli-0.0.37.dist-info/RECORD +0 -29
- {meshagent_cli-0.0.37.dist-info → meshagent_cli-0.0.39.dist-info}/WHEEL +0 -0
- {meshagent_cli-0.0.37.dist-info → meshagent_cli-0.0.39.dist-info}/entry_points.txt +0 -0
- {meshagent_cli-0.0.37.dist-info → meshagent_cli-0.0.39.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,12 @@ 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
|
-
model=model
|
|
61
|
-
)
|
|
62
|
+
llm_adapter = OpenAIResponsesAdapter(model=model)
|
|
62
63
|
|
|
63
64
|
class CustomChatbot(BaseClass):
|
|
64
65
|
def __init__(self):
|
|
@@ -67,31 +68,35 @@ def build_chatbot(*,
|
|
|
67
68
|
name=agent_name,
|
|
68
69
|
requires=requirements,
|
|
69
70
|
toolkits=toolkits,
|
|
70
|
-
rules=rule if len(rule) > 0 else None
|
|
71
|
+
rules=rule if len(rule) > 0 else None,
|
|
71
72
|
)
|
|
72
|
-
|
|
73
|
+
|
|
73
74
|
async def get_thread_toolkits(self, *, thread_context, participant):
|
|
74
|
-
toolkits = await super().get_thread_toolkits(
|
|
75
|
-
|
|
75
|
+
toolkits = await super().get_thread_toolkits(
|
|
76
|
+
thread_context=thread_context, participant=participant
|
|
77
|
+
)
|
|
78
|
+
|
|
76
79
|
thread_toolkit = Toolkit(name="thread_toolkit", tools=[])
|
|
77
80
|
|
|
78
81
|
if local_shell:
|
|
79
|
-
thread_toolkit.tools.append(LocalShellTool())
|
|
82
|
+
thread_toolkit.tools.append(LocalShellTool())
|
|
80
83
|
|
|
81
|
-
if image_generation
|
|
82
|
-
|
|
84
|
+
if image_generation is not None:
|
|
83
85
|
print("adding openai image gen to thread", flush=True)
|
|
84
|
-
thread_toolkit.tools.append(
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
thread_toolkit.tools.append(
|
|
87
|
+
ChatBotThreadOpenAIImageGenerationTool(
|
|
88
|
+
model=image_generation,
|
|
89
|
+
thread_context=thread_context,
|
|
90
|
+
partial_images=3,
|
|
91
|
+
)
|
|
92
|
+
)
|
|
93
|
+
|
|
90
94
|
toolkits.append(thread_toolkit)
|
|
91
95
|
return toolkits
|
|
92
|
-
|
|
96
|
+
|
|
93
97
|
return CustomChatbot
|
|
94
98
|
|
|
99
|
+
|
|
95
100
|
@app.async_command("join")
|
|
96
101
|
async def make_call(
|
|
97
102
|
*,
|
|
@@ -101,15 +106,31 @@ async def make_call(
|
|
|
101
106
|
name: Annotated[str, typer.Option(..., help="Participant name")] = "cli",
|
|
102
107
|
role: str = "agent",
|
|
103
108
|
agent_name: Annotated[str, typer.Option(..., help="Name of the agent to call")],
|
|
104
|
-
token_path: Annotated[Optional[str], typer.Option()] = None,
|
|
105
|
-
|
|
109
|
+
token_path: Annotated[Optional[str], typer.Option()] = None,
|
|
106
110
|
rule: Annotated[List[str], typer.Option("--rule", "-r", help="a system rule")] = [],
|
|
107
|
-
toolkit: Annotated[
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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,
|
|
113
134
|
):
|
|
114
135
|
account_client = await get_client()
|
|
115
136
|
try:
|
|
@@ -117,70 +138,107 @@ async def make_call(
|
|
|
117
138
|
api_key_id = await resolve_api_key(project_id, api_key_id)
|
|
118
139
|
|
|
119
140
|
room = resolve_room(room)
|
|
120
|
-
jwt = await resolve_token_jwt(
|
|
121
|
-
|
|
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
|
+
|
|
122
150
|
print("[bold green]Connecting to room...[/bold green]", flush=True)
|
|
123
151
|
async with RoomClient(
|
|
124
152
|
protocol=WebSocketClientProtocol(
|
|
125
153
|
url=websocket_room_url(room_name=room, base_url=meshagent_base_url()),
|
|
126
|
-
token=jwt
|
|
154
|
+
token=jwt,
|
|
127
155
|
)
|
|
128
156
|
) as client:
|
|
129
|
-
|
|
130
157
|
requirements = []
|
|
131
|
-
|
|
132
|
-
toolkits = []
|
|
133
158
|
|
|
134
159
|
for t in toolkit:
|
|
135
160
|
requirements.append(RequiredToolkit(name=t))
|
|
136
|
-
|
|
161
|
+
|
|
137
162
|
for t in schema:
|
|
138
163
|
requirements.append(RequiredSchema(name=t))
|
|
139
164
|
|
|
140
|
-
CustomChatbot = build_chatbot(
|
|
141
|
-
|
|
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,
|
|
174
|
+
)
|
|
175
|
+
|
|
142
176
|
bot = CustomChatbot()
|
|
143
177
|
|
|
144
178
|
await bot.start(room=client)
|
|
145
179
|
try:
|
|
146
|
-
print(
|
|
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
|
+
)
|
|
147
184
|
await client.protocol.wait_for_close()
|
|
148
185
|
except KeyboardInterrupt:
|
|
149
186
|
await bot.stop()
|
|
150
|
-
|
|
187
|
+
|
|
151
188
|
finally:
|
|
152
189
|
await account_client.close()
|
|
153
190
|
|
|
154
191
|
|
|
155
|
-
|
|
156
192
|
@app.async_command("service")
|
|
157
193
|
async def service(
|
|
158
194
|
*,
|
|
159
195
|
room: Annotated[Optional[str], typer.Option()] = None,
|
|
160
|
-
|
|
161
196
|
agent_name: Annotated[str, typer.Option(..., help="Name of the agent to call")],
|
|
162
|
-
|
|
163
197
|
rule: Annotated[List[str], typer.Option("--rule", "-r", help="a system rule")] = [],
|
|
164
|
-
toolkit: Annotated[
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
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,
|
|
173
223
|
path: Annotated[str, typer.Option()] = "/agent",
|
|
174
224
|
):
|
|
175
|
-
|
|
176
225
|
room = resolve_room(room)
|
|
177
|
-
|
|
226
|
+
|
|
178
227
|
print("[bold green]Connecting to room...[/bold green]", flush=True)
|
|
179
228
|
|
|
180
|
-
service = ServiceHost(
|
|
181
|
-
|
|
182
|
-
|
|
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
|
+
),
|
|
183
242
|
)
|
|
184
|
-
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))
|
|
185
243
|
|
|
186
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
|
-
"
|
|
161
|
-
"MESHAGENT_SECRET"
|
|
167
|
+
"MESHAGENT_PROJECT_ID": project_id,
|
|
168
|
+
"MESHAGENT_KEY_ID": 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()
|