meshagent-cli 0.0.37__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 +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.38.dist-info/METADATA +35 -0
- meshagent_cli-0.0.38.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.38.dist-info}/WHEEL +0 -0
- {meshagent_cli-0.0.37.dist-info → meshagent_cli-0.0.38.dist-info}/entry_points.txt +0 -0
- {meshagent_cli-0.0.37.dist-info → meshagent_cli-0.0.38.dist-info}/top_level.txt +0 -0
meshagent/cli/helper.py
CHANGED
|
@@ -5,7 +5,7 @@ from pydantic import BaseModel
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
from typing import Optional
|
|
7
7
|
|
|
8
|
-
from meshagent.cli import auth_async
|
|
8
|
+
from meshagent.cli import auth_async
|
|
9
9
|
from meshagent.cli import async_typer
|
|
10
10
|
from meshagent.api.helpers import meshagent_base_url
|
|
11
11
|
from meshagent.api.accounts_client import AccountsClient
|
|
@@ -15,27 +15,32 @@ import os
|
|
|
15
15
|
|
|
16
16
|
SETTINGS_FILE = Path.home() / ".meshagent" / "project.json"
|
|
17
17
|
|
|
18
|
+
|
|
18
19
|
def _ensure_cache_dir():
|
|
19
20
|
SETTINGS_FILE.parent.mkdir(parents=True, exist_ok=True)
|
|
20
21
|
|
|
22
|
+
|
|
21
23
|
class Settings(BaseModel):
|
|
22
24
|
active_project: Optional[str] = None
|
|
23
25
|
active_api_keys: Optional[dict] = {}
|
|
24
26
|
|
|
27
|
+
|
|
25
28
|
def _save_settings(s: Settings):
|
|
26
29
|
_ensure_cache_dir()
|
|
27
30
|
SETTINGS_FILE.write_text(s.model_dump_json())
|
|
28
|
-
|
|
31
|
+
|
|
32
|
+
|
|
29
33
|
def _load_settings():
|
|
30
34
|
_ensure_cache_dir()
|
|
31
35
|
if SETTINGS_FILE.exists():
|
|
32
36
|
return Settings.model_validate_json(SETTINGS_FILE.read_text())
|
|
33
|
-
|
|
37
|
+
|
|
34
38
|
return Settings()
|
|
35
39
|
|
|
40
|
+
|
|
36
41
|
async def get_active_project():
|
|
37
42
|
settings = _load_settings()
|
|
38
|
-
if settings
|
|
43
|
+
if settings is None:
|
|
39
44
|
return None
|
|
40
45
|
return settings.active_project
|
|
41
46
|
|
|
@@ -45,9 +50,10 @@ async def set_active_project(project_id: str | None):
|
|
|
45
50
|
settings.active_project = project_id
|
|
46
51
|
_save_settings(settings)
|
|
47
52
|
|
|
53
|
+
|
|
48
54
|
async def get_active_api_key(project_id: str):
|
|
49
55
|
settings = _load_settings()
|
|
50
|
-
if settings
|
|
56
|
+
if settings is None:
|
|
51
57
|
return None
|
|
52
58
|
return settings.active_api_keys.get(project_id, None)
|
|
53
59
|
|
|
@@ -60,12 +66,13 @@ async def set_active_api_key(project_id: str, api_key_id: str | None):
|
|
|
60
66
|
|
|
61
67
|
app = async_typer.AsyncTyper()
|
|
62
68
|
|
|
69
|
+
|
|
63
70
|
async def get_client():
|
|
64
71
|
access_token = await auth_async.get_access_token()
|
|
65
72
|
return AccountsClient(base_url=meshagent_base_url(), token=access_token)
|
|
66
73
|
|
|
74
|
+
|
|
67
75
|
def print_json_table(records: list, *cols):
|
|
68
|
-
|
|
69
76
|
if not records:
|
|
70
77
|
raise SystemExit("No rows to print")
|
|
71
78
|
|
|
@@ -75,7 +82,7 @@ def print_json_table(records: list, *cols):
|
|
|
75
82
|
if len(cols) > 0:
|
|
76
83
|
# use the keys of the first object as column order
|
|
77
84
|
for col in cols:
|
|
78
|
-
table.add_column(col.title())
|
|
85
|
+
table.add_column(col.title()) # "id" → "Id"
|
|
79
86
|
|
|
80
87
|
for row in records:
|
|
81
88
|
table.add_row(*(str(row.get(col, "")) for col in cols))
|
|
@@ -83,7 +90,7 @@ def print_json_table(records: list, *cols):
|
|
|
83
90
|
else:
|
|
84
91
|
# use the keys of the first object as column order
|
|
85
92
|
for col in records[0]:
|
|
86
|
-
table.add_column(col.title())
|
|
93
|
+
table.add_column(col.title()) # "id" → "Id"
|
|
87
94
|
|
|
88
95
|
for row in records:
|
|
89
96
|
table.add_row(*(str(row.get(col, "")) for col in records[0]))
|
|
@@ -93,60 +100,74 @@ def print_json_table(records: list, *cols):
|
|
|
93
100
|
|
|
94
101
|
|
|
95
102
|
def resolve_room(room_name: Optional[str] = None):
|
|
96
|
-
if room_name
|
|
103
|
+
if room_name is None:
|
|
97
104
|
room_name = os.getenv("MESHAGENT_ROOM")
|
|
98
|
-
|
|
105
|
+
|
|
99
106
|
return room_name
|
|
100
107
|
|
|
108
|
+
|
|
101
109
|
async def resolve_project_id(project_id: Optional[str] = None):
|
|
102
|
-
if project_id
|
|
110
|
+
if project_id is None:
|
|
103
111
|
project_id = await get_active_project()
|
|
104
|
-
|
|
105
|
-
if project_id
|
|
106
|
-
print(
|
|
112
|
+
|
|
113
|
+
if project_id is None:
|
|
114
|
+
print(
|
|
115
|
+
"[red]Project ID not specified, activate a project or pass a project on the command line[/red]"
|
|
116
|
+
)
|
|
107
117
|
raise typer.Exit(code=1)
|
|
108
|
-
|
|
118
|
+
|
|
109
119
|
return project_id
|
|
110
|
-
|
|
120
|
+
|
|
121
|
+
|
|
111
122
|
async def resolve_api_key(project_id: str, api_key_id: Optional[str] = None):
|
|
112
|
-
if api_key_id
|
|
123
|
+
if api_key_id is None:
|
|
113
124
|
api_key_id = await get_active_api_key(project_id=project_id)
|
|
114
|
-
|
|
115
|
-
if api_key_id
|
|
116
|
-
print(
|
|
125
|
+
|
|
126
|
+
if api_key_id is None:
|
|
127
|
+
print(
|
|
128
|
+
"[red]API Key ID not specified, activate an api key or pass an api key id on the command line[/red]"
|
|
129
|
+
)
|
|
117
130
|
raise typer.Exit(code=1)
|
|
118
|
-
|
|
119
|
-
return api_key_id
|
|
120
|
-
|
|
121
131
|
|
|
122
|
-
|
|
123
|
-
jwt = None
|
|
132
|
+
return api_key_id
|
|
124
133
|
|
|
125
|
-
if api_key_id == None:
|
|
126
|
-
|
|
127
|
-
if token_path != None:
|
|
128
134
|
|
|
129
|
-
|
|
135
|
+
async def resolve_token_jwt(
|
|
136
|
+
*,
|
|
137
|
+
project_id: str,
|
|
138
|
+
api_key_id: Optional[str] = None,
|
|
139
|
+
token_path: Optional[str] = None,
|
|
140
|
+
name: Optional[str] = None,
|
|
141
|
+
role: Optional[str] = None,
|
|
142
|
+
room: Optional[str] = None,
|
|
143
|
+
) -> str:
|
|
144
|
+
jwt = None
|
|
130
145
|
|
|
131
|
-
|
|
146
|
+
if api_key_id is None:
|
|
147
|
+
if token_path is not None:
|
|
148
|
+
if token_path is None:
|
|
149
|
+
token_path = os.getenv(
|
|
150
|
+
"MESHAGENT_TOKEN_PATH",
|
|
151
|
+
(Path.home() / ".meshagent" / "token").as_posix(),
|
|
152
|
+
)
|
|
132
153
|
|
|
133
154
|
p = Path(token_path)
|
|
134
155
|
jwt = p.read_text().strip()
|
|
135
|
-
|
|
136
|
-
else:
|
|
137
156
|
|
|
157
|
+
else:
|
|
138
158
|
jwt = os.getenv("MESHAGENT_TOKEN", None)
|
|
139
159
|
|
|
140
|
-
if jwt
|
|
141
|
-
|
|
160
|
+
if jwt is None:
|
|
142
161
|
account_client = await get_client()
|
|
143
162
|
try:
|
|
144
|
-
key = (
|
|
163
|
+
key = (
|
|
164
|
+
await account_client.decrypt_project_api_key(
|
|
165
|
+
project_id=project_id, id=api_key_id
|
|
166
|
+
)
|
|
167
|
+
)["token"]
|
|
145
168
|
|
|
146
169
|
token = ParticipantToken(
|
|
147
|
-
name=name,
|
|
148
|
-
project_id=project_id,
|
|
149
|
-
api_key_id=api_key_id
|
|
170
|
+
name=name, project_id=project_id, api_key_id=api_key_id
|
|
150
171
|
)
|
|
151
172
|
|
|
152
173
|
token.add_role_grant(role=role)
|
|
@@ -154,7 +175,6 @@ async def resolve_token_jwt(*, project_id: str, api_key_id: Optional[str] = None
|
|
|
154
175
|
|
|
155
176
|
jwt = token.to_jwt(token=key)
|
|
156
177
|
finally:
|
|
157
|
-
|
|
158
178
|
await account_client.close()
|
|
159
179
|
|
|
160
180
|
return jwt
|
meshagent/cli/messaging.py
CHANGED
|
@@ -3,10 +3,16 @@ from rich import print
|
|
|
3
3
|
from typing import Annotated, Optional
|
|
4
4
|
import json
|
|
5
5
|
|
|
6
|
-
from meshagent.api import RoomClient,
|
|
6
|
+
from meshagent.api import RoomClient, WebSocketClientProtocol
|
|
7
7
|
from meshagent.api.helpers import meshagent_base_url, websocket_room_url
|
|
8
8
|
from meshagent.cli import async_typer
|
|
9
|
-
from meshagent.cli.helper import
|
|
9
|
+
from meshagent.cli.helper import (
|
|
10
|
+
get_client,
|
|
11
|
+
resolve_project_id,
|
|
12
|
+
resolve_api_key,
|
|
13
|
+
resolve_token_jwt,
|
|
14
|
+
resolve_room,
|
|
15
|
+
)
|
|
10
16
|
|
|
11
17
|
app = async_typer.AsyncTyper()
|
|
12
18
|
|
|
@@ -16,10 +22,10 @@ async def messaging_list_participants_command(
|
|
|
16
22
|
*,
|
|
17
23
|
project_id: str = None,
|
|
18
24
|
room: Annotated[Optional[str], typer.Option()] = None,
|
|
19
|
-
token_path: Annotated[Optional[str], typer.Option()] = None,
|
|
25
|
+
token_path: Annotated[Optional[str], typer.Option()] = None,
|
|
20
26
|
api_key_id: Annotated[Optional[str], typer.Option()] = None,
|
|
21
27
|
name: Annotated[str, typer.Option()] = "cli",
|
|
22
|
-
role: str = "user"
|
|
28
|
+
role: str = "user",
|
|
23
29
|
):
|
|
24
30
|
"""
|
|
25
31
|
List all messaging-enabled participants in the room.
|
|
@@ -29,19 +35,25 @@ async def messaging_list_participants_command(
|
|
|
29
35
|
# Resolve project_id if not provided
|
|
30
36
|
project_id = await resolve_project_id(project_id=project_id)
|
|
31
37
|
api_key_id = await resolve_api_key(project_id, api_key_id)
|
|
32
|
-
|
|
38
|
+
|
|
33
39
|
room = resolve_room(room)
|
|
34
|
-
|
|
35
|
-
jwt = await resolve_token_jwt(
|
|
40
|
+
|
|
41
|
+
jwt = await resolve_token_jwt(
|
|
42
|
+
project_id=project_id,
|
|
43
|
+
api_key_id=api_key_id,
|
|
44
|
+
token_path=token_path,
|
|
45
|
+
name=name,
|
|
46
|
+
role=role,
|
|
47
|
+
room=room,
|
|
48
|
+
)
|
|
36
49
|
|
|
37
50
|
print("[bold green]Connecting to room...[/bold green]")
|
|
38
51
|
async with RoomClient(
|
|
39
52
|
protocol=WebSocketClientProtocol(
|
|
40
53
|
url=websocket_room_url(room_name=room, base_url=meshagent_base_url()),
|
|
41
|
-
token=jwt
|
|
54
|
+
token=jwt,
|
|
42
55
|
)
|
|
43
56
|
) as client:
|
|
44
|
-
|
|
45
57
|
# Must enable before we can see who else is enabled
|
|
46
58
|
await client.messaging.enable()
|
|
47
59
|
await client.messaging.start()
|
|
@@ -49,11 +61,7 @@ async def messaging_list_participants_command(
|
|
|
49
61
|
participants = client.messaging.get_participants()
|
|
50
62
|
output = []
|
|
51
63
|
for p in participants:
|
|
52
|
-
output.append({
|
|
53
|
-
"id": p.id,
|
|
54
|
-
"role": p.role,
|
|
55
|
-
"attributes": p._attributes
|
|
56
|
-
})
|
|
64
|
+
output.append({"id": p.id, "role": p.role, "attributes": p._attributes})
|
|
57
65
|
|
|
58
66
|
print(json.dumps(output, indent=2))
|
|
59
67
|
|
|
@@ -68,11 +76,13 @@ async def messaging_send_command(
|
|
|
68
76
|
*,
|
|
69
77
|
project_id: str = None,
|
|
70
78
|
room: Annotated[Optional[str], typer.Option()] = None,
|
|
71
|
-
token_path: Annotated[Optional[str], typer.Option()] = None,
|
|
79
|
+
token_path: Annotated[Optional[str], typer.Option()] = None,
|
|
72
80
|
api_key_id: Annotated[Optional[str], typer.Option()] = None,
|
|
73
81
|
name: Annotated[str, typer.Option()] = "cli",
|
|
74
82
|
role: str = "user",
|
|
75
|
-
to_participant_id: Annotated[
|
|
83
|
+
to_participant_id: Annotated[
|
|
84
|
+
str, typer.Option(..., help="Participant ID to send a message to")
|
|
85
|
+
],
|
|
76
86
|
data: Annotated[str, typer.Option(..., help="JSON message to send")],
|
|
77
87
|
):
|
|
78
88
|
"""
|
|
@@ -83,16 +93,23 @@ async def messaging_send_command(
|
|
|
83
93
|
# Resolve project_id if not provided
|
|
84
94
|
project_id = await resolve_project_id(project_id=project_id)
|
|
85
95
|
api_key_id = await resolve_api_key(project_id, api_key_id)
|
|
86
|
-
|
|
96
|
+
|
|
87
97
|
room = resolve_room(room)
|
|
88
|
-
|
|
89
|
-
jwt = await resolve_token_jwt(
|
|
98
|
+
|
|
99
|
+
jwt = await resolve_token_jwt(
|
|
100
|
+
project_id=project_id,
|
|
101
|
+
api_key_id=api_key_id,
|
|
102
|
+
token_path=token_path,
|
|
103
|
+
name=name,
|
|
104
|
+
role=role,
|
|
105
|
+
room=room,
|
|
106
|
+
)
|
|
90
107
|
|
|
91
108
|
print("[bold green]Connecting to room...[/bold green]")
|
|
92
109
|
async with RoomClient(
|
|
93
110
|
protocol=WebSocketClientProtocol(
|
|
94
111
|
url=websocket_room_url(room_name=room, base_url=meshagent_base_url()),
|
|
95
|
-
token=jwt
|
|
112
|
+
token=jwt,
|
|
96
113
|
)
|
|
97
114
|
) as client:
|
|
98
115
|
# Create and enable messaging
|
|
@@ -105,16 +122,18 @@ async def messaging_send_command(
|
|
|
105
122
|
if p.id == to_participant_id:
|
|
106
123
|
participant = p
|
|
107
124
|
break
|
|
108
|
-
|
|
125
|
+
|
|
109
126
|
if participant is None:
|
|
110
|
-
print(
|
|
127
|
+
print(
|
|
128
|
+
f"[bold red]Participant with ID {to_participant_id} not found or not messaging-enabled.[/bold red]"
|
|
129
|
+
)
|
|
111
130
|
else:
|
|
112
131
|
# Send the message
|
|
113
132
|
await client.messaging.send_message(
|
|
114
133
|
to=participant,
|
|
115
134
|
type="chat.message",
|
|
116
135
|
message=json.loads(data),
|
|
117
|
-
attachment=None
|
|
136
|
+
attachment=None,
|
|
118
137
|
)
|
|
119
138
|
print("[bold cyan]Message sent successfully.[/bold cyan]")
|
|
120
139
|
|
|
@@ -123,17 +142,16 @@ async def messaging_send_command(
|
|
|
123
142
|
await account_client.close()
|
|
124
143
|
|
|
125
144
|
|
|
126
|
-
|
|
127
145
|
@app.async_command("broadcast")
|
|
128
146
|
async def messaging_broadcast_command(
|
|
129
147
|
*,
|
|
130
148
|
project_id: str = None,
|
|
131
149
|
room: Annotated[Optional[str], typer.Option()] = None,
|
|
132
|
-
token_path: Annotated[Optional[str], typer.Option()] = None,
|
|
150
|
+
token_path: Annotated[Optional[str], typer.Option()] = None,
|
|
133
151
|
api_key_id: Annotated[Optional[str], typer.Option()] = None,
|
|
134
152
|
name: Annotated[str, typer.Option()] = "cli",
|
|
135
153
|
role: str = "user",
|
|
136
|
-
data: Annotated[str, typer.Option(..., help="JSON message to broadcast")]
|
|
154
|
+
data: Annotated[str, typer.Option(..., help="JSON message to broadcast")],
|
|
137
155
|
):
|
|
138
156
|
"""
|
|
139
157
|
Broadcast a message to all messaging-enabled participants in the room.
|
|
@@ -145,13 +163,20 @@ async def messaging_broadcast_command(
|
|
|
145
163
|
api_key_id = await resolve_api_key(project_id, api_key_id)
|
|
146
164
|
|
|
147
165
|
room = resolve_room(room)
|
|
148
|
-
jwt = await resolve_token_jwt(
|
|
166
|
+
jwt = await resolve_token_jwt(
|
|
167
|
+
project_id=project_id,
|
|
168
|
+
api_key_id=api_key_id,
|
|
169
|
+
token_path=token_path,
|
|
170
|
+
name=name,
|
|
171
|
+
role=role,
|
|
172
|
+
room=room,
|
|
173
|
+
)
|
|
149
174
|
|
|
150
175
|
print("[bold green]Connecting to room...[/bold green]")
|
|
151
176
|
async with RoomClient(
|
|
152
177
|
protocol=WebSocketClientProtocol(
|
|
153
178
|
url=websocket_room_url(room_name=room, base_url=meshagent_base_url()),
|
|
154
|
-
token=jwt
|
|
179
|
+
token=jwt,
|
|
155
180
|
)
|
|
156
181
|
) as client:
|
|
157
182
|
# Create and enable messaging
|
|
@@ -160,9 +185,7 @@ async def messaging_broadcast_command(
|
|
|
160
185
|
|
|
161
186
|
# Broadcast the message
|
|
162
187
|
await client.messaging.broadcast_message(
|
|
163
|
-
type="chat.broadcast",
|
|
164
|
-
message=json.loads(data),
|
|
165
|
-
attachment=None
|
|
188
|
+
type="chat.broadcast", message=json.loads(data), attachment=None
|
|
166
189
|
)
|
|
167
190
|
print("[bold cyan]Broadcast message sent successfully.[/bold cyan]")
|
|
168
191
|
|
meshagent/cli/otel.py
CHANGED
|
@@ -8,8 +8,11 @@ from opentelemetry import metrics
|
|
|
8
8
|
from opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter
|
|
9
9
|
from opentelemetry.sdk._logs.export import ConsoleLogExporter
|
|
10
10
|
from opentelemetry.sdk.metrics import MeterProvider
|
|
11
|
-
from opentelemetry.sdk.metrics.export import
|
|
12
|
-
|
|
11
|
+
from opentelemetry.sdk.metrics.export import (
|
|
12
|
+
PeriodicExportingMetricReader,
|
|
13
|
+
ConsoleMetricExporter,
|
|
14
|
+
)
|
|
15
|
+
from opentelemetry import _logs
|
|
13
16
|
from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler
|
|
14
17
|
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
|
|
15
18
|
from opentelemetry.exporter.otlp.proto.http._log_exporter import OTLPLogExporter
|
|
@@ -19,6 +22,7 @@ import logging
|
|
|
19
22
|
|
|
20
23
|
import os
|
|
21
24
|
|
|
25
|
+
|
|
22
26
|
def _call_once(fn):
|
|
23
27
|
called = False
|
|
24
28
|
result = None
|
|
@@ -29,6 +33,7 @@ def _call_once(fn):
|
|
|
29
33
|
result = fn(*args, **kwargs)
|
|
30
34
|
called = True
|
|
31
35
|
return result
|
|
36
|
+
|
|
32
37
|
return wrapper
|
|
33
38
|
|
|
34
39
|
|
|
@@ -36,13 +41,13 @@ attributes = {
|
|
|
36
41
|
SERVICE_NAME: "room-server",
|
|
37
42
|
}
|
|
38
43
|
|
|
39
|
-
if os.getenv("MESHAGENT_PROJECT_ID")
|
|
44
|
+
if os.getenv("MESHAGENT_PROJECT_ID") is not None:
|
|
40
45
|
attributes["project"] = os.getenv("MESHAGENT_PROJECT_ID")
|
|
41
46
|
|
|
42
|
-
if os.getenv("MESHAGENT_SESSION_ID")
|
|
47
|
+
if os.getenv("MESHAGENT_SESSION_ID") is not None:
|
|
43
48
|
attributes["session"] = os.getenv("MESHAGENT_SESSION_ID")
|
|
44
49
|
|
|
45
|
-
if os.getenv("MESHAGENT_ROOM")
|
|
50
|
+
if os.getenv("MESHAGENT_ROOM") is not None:
|
|
46
51
|
attributes["room"] = os.getenv("MESHAGENT_ROOM")
|
|
47
52
|
|
|
48
53
|
resource = Resource.create(attributes=attributes)
|
|
@@ -53,66 +58,65 @@ meter_provider = None
|
|
|
53
58
|
|
|
54
59
|
add_console_exporters = False
|
|
55
60
|
|
|
56
|
-
otel_endpoint = os.getenv("OTEL_ENDPOINT")
|
|
57
|
-
|
|
58
|
-
if otel_endpoint != None:
|
|
61
|
+
otel_endpoint = os.getenv("OTEL_ENDPOINT")
|
|
59
62
|
|
|
63
|
+
if otel_endpoint is not None:
|
|
60
64
|
otel_logs_endpoint = otel_endpoint + "/v1/logs"
|
|
61
65
|
otel_traces_endpoint = otel_endpoint + "/v1/traces"
|
|
62
66
|
otel_metrics_endpoint = otel_endpoint + "/v1/metrics"
|
|
63
|
-
|
|
64
|
-
if otel_logs_endpoint
|
|
67
|
+
|
|
68
|
+
if otel_logs_endpoint is not None:
|
|
65
69
|
logs_exporter = OTLPLogExporter(
|
|
66
70
|
endpoint=otel_logs_endpoint,
|
|
67
71
|
)
|
|
68
72
|
logger_provider = LoggerProvider(resource=resource)
|
|
69
|
-
_logs.set_logger_provider(logger_provider)
|
|
70
|
-
|
|
71
|
-
logger_provider.add_log_record_processor(
|
|
72
|
-
BatchLogRecordProcessor(logs_exporter)
|
|
73
|
-
)
|
|
73
|
+
_logs.set_logger_provider(logger_provider)
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
logger_provider.add_log_record_processor(BatchLogRecordProcessor(ConsoleLogExporter()))
|
|
75
|
+
logger_provider.add_log_record_processor(BatchLogRecordProcessor(logs_exporter))
|
|
77
76
|
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
if add_console_exporters:
|
|
78
|
+
logger_provider.add_log_record_processor(
|
|
79
|
+
BatchLogRecordProcessor(ConsoleLogExporter())
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
if otel_traces_endpoint is not None:
|
|
80
83
|
tracer_provider = TracerProvider(resource=resource)
|
|
81
84
|
processor = BatchSpanProcessor(OTLPSpanExporter(endpoint=otel_traces_endpoint))
|
|
82
85
|
tracer_provider.add_span_processor(processor)
|
|
83
|
-
if add_console_exporters:
|
|
84
|
-
tracer_provider.add_span_processor(
|
|
86
|
+
if add_console_exporters:
|
|
87
|
+
tracer_provider.add_span_processor(
|
|
88
|
+
BatchSpanProcessor(ConsoleSpanExporter())
|
|
89
|
+
)
|
|
85
90
|
trace.set_tracer_provider(tracer_provider)
|
|
86
91
|
|
|
87
|
-
if otel_metrics_endpoint
|
|
92
|
+
if otel_metrics_endpoint is not None:
|
|
88
93
|
reader = PeriodicExportingMetricReader(
|
|
89
94
|
exporter=OTLPMetricExporter(
|
|
90
95
|
endpoint=otel_metrics_endpoint,
|
|
91
|
-
|
|
96
|
+
preferred_temporality={
|
|
92
97
|
Counter: AggregationTemporality.DELTA,
|
|
93
98
|
Histogram: AggregationTemporality.DELTA,
|
|
94
99
|
},
|
|
95
100
|
),
|
|
96
|
-
export_interval_millis=1000
|
|
101
|
+
export_interval_millis=1000,
|
|
97
102
|
)
|
|
98
|
-
|
|
103
|
+
|
|
99
104
|
readers = [
|
|
100
105
|
reader,
|
|
101
106
|
]
|
|
102
107
|
if add_console_exporters:
|
|
103
|
-
readers.append(PeriodicExportingMetricReader(
|
|
104
|
-
|
|
105
|
-
))
|
|
106
|
-
|
|
108
|
+
readers.append(PeriodicExportingMetricReader(ConsoleMetricExporter()))
|
|
109
|
+
|
|
107
110
|
meter_provider = MeterProvider(resource=resource, metric_readers=readers)
|
|
108
111
|
metrics.set_meter_provider(meter_provider)
|
|
109
112
|
|
|
113
|
+
|
|
110
114
|
@_call_once
|
|
111
115
|
def init(level):
|
|
112
|
-
if logger_provider
|
|
116
|
+
if logger_provider is not None:
|
|
113
117
|
logging_handler = LoggingHandler(level=level, logger_provider=logger_provider)
|
|
114
|
-
root = logging.getLogger()
|
|
115
|
-
root.setLevel(level)
|
|
118
|
+
root = logging.getLogger()
|
|
119
|
+
root.setLevel(level)
|
|
116
120
|
root.addHandler(logging_handler)
|
|
117
121
|
else:
|
|
118
122
|
logging.basicConfig(level=level)
|
|
@@ -1,40 +1,49 @@
|
|
|
1
1
|
import typer
|
|
2
2
|
from rich import print
|
|
3
3
|
from typing import Annotated, Optional
|
|
4
|
-
from meshagent.api import
|
|
5
|
-
from meshagent.cli.helper import
|
|
4
|
+
from meshagent.api import ParticipantToken
|
|
5
|
+
from meshagent.cli.helper import resolve_project_id, resolve_api_key
|
|
6
6
|
from meshagent.cli import async_typer
|
|
7
|
-
from meshagent.cli.helper import get_client
|
|
7
|
+
from meshagent.cli.helper import get_client
|
|
8
8
|
import pathlib
|
|
9
9
|
|
|
10
10
|
app = async_typer.AsyncTyper()
|
|
11
11
|
|
|
12
|
+
|
|
12
13
|
@app.async_command("generate")
|
|
13
|
-
async def generate(
|
|
14
|
+
async def generate(
|
|
15
|
+
*,
|
|
16
|
+
project_id: str = None,
|
|
17
|
+
token_path: Annotated[str, typer.Option()],
|
|
18
|
+
room: Annotated[str, typer.Option()],
|
|
19
|
+
api_key_id: Annotated[Optional[str], typer.Option()] = None,
|
|
20
|
+
name: Annotated[str, typer.Option()],
|
|
21
|
+
role: str = "agent",
|
|
22
|
+
):
|
|
14
23
|
client = await get_client()
|
|
15
24
|
try:
|
|
16
25
|
project_id = await resolve_project_id(project_id=project_id)
|
|
17
26
|
api_key_id = await resolve_api_key(project_id=project_id, api_key_id=api_key_id)
|
|
18
27
|
|
|
19
|
-
key = (
|
|
28
|
+
key = (
|
|
29
|
+
await client.decrypt_project_api_key(project_id=project_id, id=api_key_id)
|
|
30
|
+
)["token"]
|
|
20
31
|
|
|
21
32
|
token = ParticipantToken(
|
|
22
|
-
name=name,
|
|
23
|
-
project_id=project_id,
|
|
24
|
-
api_key_id=api_key_id
|
|
33
|
+
name=name, project_id=project_id, api_key_id=api_key_id
|
|
25
34
|
)
|
|
26
35
|
|
|
27
36
|
token.add_role_grant(role=role)
|
|
28
37
|
|
|
29
38
|
token.add_room_grant(room)
|
|
30
39
|
|
|
31
|
-
if token_path
|
|
32
|
-
|
|
40
|
+
if token_path is None:
|
|
33
41
|
print(token.to_jwt(token=key))
|
|
34
42
|
|
|
35
43
|
else:
|
|
44
|
+
pathlib.Path(token_path).expanduser().resolve().write_text(
|
|
45
|
+
token.to_jwt(token=key)
|
|
46
|
+
)
|
|
36
47
|
|
|
37
|
-
pathlib.Path(token_path).expanduser().resolve().write_text(token.to_jwt(token=key))
|
|
38
|
-
|
|
39
48
|
finally:
|
|
40
49
|
await client.close()
|
meshagent/cli/projects.py
CHANGED
|
@@ -16,10 +16,11 @@ async def create(name: str):
|
|
|
16
16
|
client = await get_client()
|
|
17
17
|
try:
|
|
18
18
|
result = await client.create_project(name)
|
|
19
|
-
print(f"[green]Project created:[/] {result[
|
|
19
|
+
print(f"[green]Project created:[/] {result['id']}")
|
|
20
20
|
finally:
|
|
21
21
|
await client.close()
|
|
22
22
|
|
|
23
|
+
|
|
23
24
|
@app.async_command("list")
|
|
24
25
|
async def list():
|
|
25
26
|
client = await get_client()
|
|
@@ -32,6 +33,7 @@ async def list():
|
|
|
32
33
|
print_json_table(projects["projects"], "id", "name")
|
|
33
34
|
await client.close()
|
|
34
35
|
|
|
36
|
+
|
|
35
37
|
@app.async_command("activate")
|
|
36
38
|
async def activate(
|
|
37
39
|
project_id: str | None = typer.Argument(None),
|
|
@@ -95,4 +97,3 @@ async def activate(
|
|
|
95
97
|
raise typer.Exit(code=1)
|
|
96
98
|
finally:
|
|
97
99
|
await client.close()
|
|
98
|
-
|