meshagent-cli 0.7.0__py3-none-any.whl → 0.21.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.
- meshagent/cli/agent.py +15 -11
- meshagent/cli/api_keys.py +4 -4
- meshagent/cli/async_typer.py +52 -4
- meshagent/cli/call.py +12 -8
- meshagent/cli/chatbot.py +1007 -129
- meshagent/cli/cli.py +21 -20
- meshagent/cli/cli_mcp.py +92 -28
- meshagent/cli/cli_secrets.py +10 -10
- meshagent/cli/common_options.py +19 -4
- meshagent/cli/containers.py +164 -16
- meshagent/cli/database.py +997 -0
- meshagent/cli/developer.py +3 -3
- meshagent/cli/exec.py +22 -6
- meshagent/cli/helper.py +62 -11
- meshagent/cli/helpers.py +66 -9
- meshagent/cli/host.py +37 -0
- meshagent/cli/mailbot.py +1004 -40
- meshagent/cli/mailboxes.py +223 -0
- meshagent/cli/meeting_transcriber.py +10 -4
- meshagent/cli/messaging.py +7 -7
- meshagent/cli/multi.py +402 -0
- meshagent/cli/oauth2.py +44 -21
- meshagent/cli/participant_token.py +5 -3
- meshagent/cli/port.py +70 -0
- meshagent/cli/queue.py +2 -2
- meshagent/cli/room.py +20 -212
- meshagent/cli/rooms.py +214 -0
- meshagent/cli/services.py +32 -23
- meshagent/cli/sessions.py +5 -5
- meshagent/cli/storage.py +5 -5
- meshagent/cli/task_runner.py +770 -0
- meshagent/cli/version.py +1 -1
- meshagent/cli/voicebot.py +502 -76
- meshagent/cli/webhook.py +7 -7
- meshagent/cli/worker.py +1327 -0
- {meshagent_cli-0.7.0.dist-info → meshagent_cli-0.21.0.dist-info}/METADATA +13 -13
- meshagent_cli-0.21.0.dist-info/RECORD +44 -0
- meshagent_cli-0.7.0.dist-info/RECORD +0 -36
- {meshagent_cli-0.7.0.dist-info → meshagent_cli-0.21.0.dist-info}/WHEEL +0 -0
- {meshagent_cli-0.7.0.dist-info → meshagent_cli-0.21.0.dist-info}/entry_points.txt +0 -0
- {meshagent_cli-0.7.0.dist-info → meshagent_cli-0.21.0.dist-info}/top_level.txt +0 -0
meshagent/cli/developer.py
CHANGED
|
@@ -14,13 +14,13 @@ from meshagent.api import (
|
|
|
14
14
|
)
|
|
15
15
|
from meshagent.api.helpers import meshagent_base_url, websocket_room_url
|
|
16
16
|
|
|
17
|
-
app = async_typer.AsyncTyper()
|
|
17
|
+
app = async_typer.AsyncTyper(help="Developer utilities for a room")
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
@app.async_command("watch")
|
|
20
|
+
@app.async_command("watch", help="Stream developer logs from a room")
|
|
21
21
|
async def watch_logs(
|
|
22
22
|
*,
|
|
23
|
-
project_id: ProjectIdOption
|
|
23
|
+
project_id: ProjectIdOption,
|
|
24
24
|
room: RoomOption,
|
|
25
25
|
):
|
|
26
26
|
"""
|
meshagent/cli/exec.py
CHANGED
|
@@ -82,13 +82,29 @@ def register(app: typer.Typer):
|
|
|
82
82
|
@app.async_command("exec")
|
|
83
83
|
async def exec_command(
|
|
84
84
|
*,
|
|
85
|
-
project_id: ProjectIdOption
|
|
85
|
+
project_id: ProjectIdOption,
|
|
86
86
|
room: RoomOption,
|
|
87
|
-
name: Annotated[
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
87
|
+
name: Annotated[
|
|
88
|
+
Optional[str], typer.Option(help="Optional exec session name")
|
|
89
|
+
] = None,
|
|
90
|
+
image: Annotated[
|
|
91
|
+
Optional[str],
|
|
92
|
+
typer.Option(help="Optional container image to use for the exec session"),
|
|
93
|
+
] = None,
|
|
94
|
+
command: Annotated[
|
|
95
|
+
list[str],
|
|
96
|
+
typer.Argument(..., help="Command to execute (omit when using `--tty`)"),
|
|
97
|
+
] = None,
|
|
98
|
+
tty: Annotated[
|
|
99
|
+
bool,
|
|
100
|
+
typer.Option(
|
|
101
|
+
"--tty/--no-tty",
|
|
102
|
+
help="Allocate an interactive TTY (requires a real terminal)",
|
|
103
|
+
),
|
|
104
|
+
] = False,
|
|
105
|
+
room_storage_path: Annotated[
|
|
106
|
+
str, typer.Option(help="Room storage mount path (default: /data)")
|
|
107
|
+
] = "/data",
|
|
92
108
|
):
|
|
93
109
|
"""Open an interactive websocket‑based TTY."""
|
|
94
110
|
client = await get_client()
|
meshagent/cli/helper.py
CHANGED
|
@@ -7,7 +7,7 @@ from typing import Optional
|
|
|
7
7
|
from meshagent.cli import auth_async
|
|
8
8
|
from meshagent.cli import async_typer
|
|
9
9
|
from meshagent.api.helpers import meshagent_base_url
|
|
10
|
-
from meshagent.api.client import Meshagent
|
|
10
|
+
from meshagent.api.client import Meshagent, RoomConnectionInfo
|
|
11
11
|
import os
|
|
12
12
|
from rich import print
|
|
13
13
|
|
|
@@ -29,11 +29,15 @@ def _save_settings(s: Settings):
|
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
def _load_settings():
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
try:
|
|
33
|
+
_ensure_cache_dir()
|
|
34
|
+
if SETTINGS_FILE.exists():
|
|
35
|
+
return Settings.model_validate_json(SETTINGS_FILE.read_text())
|
|
36
|
+
except OSError as ex:
|
|
37
|
+
if ex.errno == 30:
|
|
38
|
+
return Settings()
|
|
39
|
+
else:
|
|
40
|
+
raise
|
|
37
41
|
|
|
38
42
|
|
|
39
43
|
async def get_active_project():
|
|
@@ -68,16 +72,33 @@ async def get_active_api_key(project_id: str):
|
|
|
68
72
|
app = async_typer.AsyncTyper()
|
|
69
73
|
|
|
70
74
|
|
|
75
|
+
class CustomMeshagentClient(Meshagent):
|
|
76
|
+
async def connect_room(self, *, project_id: str, room: str) -> RoomConnectionInfo:
|
|
77
|
+
from urllib.parse import quote
|
|
78
|
+
|
|
79
|
+
jwt = os.getenv("MESHAGENT_SESSION_TOKEN")
|
|
80
|
+
|
|
81
|
+
if jwt is not None and room == os.getenv("MESHAGENT_ROOM"):
|
|
82
|
+
return RoomConnectionInfo(
|
|
83
|
+
jwt=jwt,
|
|
84
|
+
room_name=room,
|
|
85
|
+
project_id=os.getenv("MESHAGENT_PROJECT_ID"),
|
|
86
|
+
room_url=meshagent_base_url() + f"/rooms/{quote(room)}",
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
return await super().connect_room(project_id=project_id, room=room)
|
|
90
|
+
|
|
91
|
+
|
|
71
92
|
async def get_client():
|
|
72
93
|
key = os.getenv("MESHAGENT_API_KEY")
|
|
73
|
-
if key is not None:
|
|
74
|
-
return
|
|
94
|
+
if key is not None or os.getenv("MESHAGENT_SESSION_ID") is not None:
|
|
95
|
+
return CustomMeshagentClient(
|
|
75
96
|
base_url=meshagent_base_url(),
|
|
76
97
|
token=key,
|
|
77
98
|
)
|
|
78
99
|
else:
|
|
79
100
|
access_token = await auth_async.get_access_token()
|
|
80
|
-
return
|
|
101
|
+
return CustomMeshagentClient(
|
|
81
102
|
base_url=meshagent_base_url(),
|
|
82
103
|
token=access_token,
|
|
83
104
|
)
|
|
@@ -119,7 +140,7 @@ def resolve_room(room_name: Optional[str] = None):
|
|
|
119
140
|
|
|
120
141
|
async def resolve_project_id(project_id: Optional[str] = None):
|
|
121
142
|
if project_id is None:
|
|
122
|
-
project_id = await get_active_project()
|
|
143
|
+
project_id = os.getenv("MESHAGENT_PROJECT_ID") or await get_active_project()
|
|
123
144
|
|
|
124
145
|
if project_id is None:
|
|
125
146
|
print(
|
|
@@ -140,8 +161,38 @@ async def resolve_key(project_id: str | None, key: str | None):
|
|
|
140
161
|
|
|
141
162
|
if key is None:
|
|
142
163
|
print(
|
|
143
|
-
"[red]--key is required if
|
|
164
|
+
"[red]--key is required if MESHAGENT_API_KEY is not set. You can use meshagent api-key create to create a new api key."
|
|
144
165
|
)
|
|
145
166
|
raise typer.Exit(1)
|
|
146
167
|
|
|
147
168
|
return key
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def cleanup_args(args: list[str]):
|
|
172
|
+
out = []
|
|
173
|
+
i = 0
|
|
174
|
+
while i < len(args):
|
|
175
|
+
if args[i] == "--service-name":
|
|
176
|
+
i += 1
|
|
177
|
+
elif args[i] == "--service-title":
|
|
178
|
+
i += 1
|
|
179
|
+
elif args[i] == "--service-description":
|
|
180
|
+
i += 1
|
|
181
|
+
elif args[i] == "--project-id":
|
|
182
|
+
i += 1
|
|
183
|
+
elif args[i] == "--room":
|
|
184
|
+
i += 1
|
|
185
|
+
elif args[i].startswith("--service-name="):
|
|
186
|
+
pass
|
|
187
|
+
elif args[i].startswith("--service-title="):
|
|
188
|
+
pass
|
|
189
|
+
elif args[i].startswith("--service-description="):
|
|
190
|
+
pass
|
|
191
|
+
elif args[i].startswith("--project-id="):
|
|
192
|
+
pass
|
|
193
|
+
elif args[i].startswith("--room="):
|
|
194
|
+
pass
|
|
195
|
+
else:
|
|
196
|
+
out.append(args[i])
|
|
197
|
+
i += 1
|
|
198
|
+
return out
|
meshagent/cli/helpers.py
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
from meshagent.cli import async_typer
|
|
2
2
|
|
|
3
|
-
|
|
4
3
|
from meshagent.api import SchemaRegistry, SchemaRegistration
|
|
5
4
|
|
|
6
5
|
|
|
7
6
|
import logging
|
|
8
7
|
|
|
9
|
-
app = async_typer.AsyncTyper(help="
|
|
8
|
+
app = async_typer.AsyncTyper(help="Developer helper services")
|
|
10
9
|
|
|
11
10
|
|
|
12
|
-
@app.async_command("service")
|
|
11
|
+
@app.async_command("service", help="Run local helper HTTP services")
|
|
13
12
|
async def helpers_service():
|
|
14
|
-
|
|
13
|
+
"""Run local helper services (agents, schemas, toolkits)."""
|
|
14
|
+
from meshagent.agents.llmrunner import LLMTaskRunner, DynamicLLMTaskRunner
|
|
15
15
|
from meshagent.openai.tools import OpenAIResponsesAdapter
|
|
16
16
|
from meshagent.tools.storage import StorageToolkit
|
|
17
|
+
from meshagent.tools.database import DatabaseToolkitBuilder
|
|
17
18
|
from meshagent.api.services import ServiceHost
|
|
18
19
|
|
|
19
20
|
from meshagent.agents.schemas.gallery import gallery_schema
|
|
@@ -24,20 +25,53 @@ async def helpers_service():
|
|
|
24
25
|
)
|
|
25
26
|
from meshagent.agents.schemas.presentation import presentation_schema
|
|
26
27
|
from meshagent.agents import thread_schema
|
|
28
|
+
from meshagent.agents.widget_schema import widget_schema
|
|
27
29
|
|
|
28
30
|
logging.getLogger("openai").setLevel(logging.ERROR)
|
|
29
31
|
logging.getLogger("httpx").setLevel(logging.ERROR)
|
|
30
32
|
|
|
31
33
|
service = ServiceHost(port=9000)
|
|
32
34
|
|
|
35
|
+
@service.path("/runner")
|
|
36
|
+
class Runner(LLMTaskRunner):
|
|
37
|
+
def __init__(self, **kwargs):
|
|
38
|
+
super().__init__(
|
|
39
|
+
name="meshagent.runner",
|
|
40
|
+
title="Generic Task Runner",
|
|
41
|
+
description="an agent that will perform a task with the selected tools",
|
|
42
|
+
llm_adapter=OpenAIResponsesAdapter(model="gpt-5.2"),
|
|
43
|
+
supports_tools=True,
|
|
44
|
+
input_prompt=True,
|
|
45
|
+
output_schema={
|
|
46
|
+
"type": "object",
|
|
47
|
+
"required": ["result"],
|
|
48
|
+
"additionalProperties": False,
|
|
49
|
+
"properties": {"result": {"type": "string"}},
|
|
50
|
+
},
|
|
51
|
+
annotations={"meshagent.task-runner.attachment-format": "tar"},
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
def get_toolkit_builders(self):
|
|
55
|
+
from meshagent.tools.storage import StorageToolkitBuilder
|
|
56
|
+
from meshagent.openai.tools.responses_adapter import WebSearchToolkitBuilder
|
|
57
|
+
|
|
58
|
+
providers = [
|
|
59
|
+
WebSearchToolkitBuilder(),
|
|
60
|
+
StorageToolkitBuilder(),
|
|
61
|
+
DatabaseToolkitBuilder(),
|
|
62
|
+
*super().get_toolkit_builders(),
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
return providers
|
|
66
|
+
|
|
33
67
|
@service.path("/planner")
|
|
34
|
-
class Planner(
|
|
68
|
+
class Planner(LLMTaskRunner):
|
|
35
69
|
def __init__(self, **kwargs):
|
|
36
70
|
super().__init__(
|
|
37
71
|
name="meshagent.planner",
|
|
38
|
-
title="Generic Task Runner",
|
|
72
|
+
title="Generic Task Runner (Legacy)",
|
|
39
73
|
description="an agent that will perform a task with the selected tools",
|
|
40
|
-
llm_adapter=OpenAIResponsesAdapter(model="gpt-
|
|
74
|
+
llm_adapter=OpenAIResponsesAdapter(model="gpt-5.2"),
|
|
41
75
|
supports_tools=True,
|
|
42
76
|
input_prompt=True,
|
|
43
77
|
output_schema={
|
|
@@ -49,15 +83,27 @@ async def helpers_service():
|
|
|
49
83
|
)
|
|
50
84
|
|
|
51
85
|
@service.path("/schema_planner")
|
|
52
|
-
class DynamicPlanner(
|
|
86
|
+
class DynamicPlanner(DynamicLLMTaskRunner):
|
|
53
87
|
def __init__(self, **kwargs):
|
|
54
88
|
super().__init__(
|
|
55
89
|
name="meshagent.schema_planner",
|
|
56
90
|
title="Schema Task Runner",
|
|
57
91
|
description="an agent that can produces output that matches a schema",
|
|
58
|
-
llm_adapter=OpenAIResponsesAdapter(model="gpt-
|
|
92
|
+
llm_adapter=OpenAIResponsesAdapter(model="gpt-5.2"),
|
|
59
93
|
)
|
|
60
94
|
|
|
95
|
+
def get_toolkit_builders(self):
|
|
96
|
+
from meshagent.tools.storage import StorageToolkitBuilder
|
|
97
|
+
from meshagent.openai.tools.responses_adapter import WebSearchToolkitBuilder
|
|
98
|
+
|
|
99
|
+
providers = [
|
|
100
|
+
WebSearchToolkitBuilder(),
|
|
101
|
+
StorageToolkitBuilder(),
|
|
102
|
+
*super().get_toolkit_builders(),
|
|
103
|
+
]
|
|
104
|
+
|
|
105
|
+
return providers
|
|
106
|
+
|
|
61
107
|
@service.path("/schemas/document")
|
|
62
108
|
class DocumentSchemaRegistry(SchemaRegistry):
|
|
63
109
|
def __init__(self):
|
|
@@ -102,6 +148,17 @@ async def helpers_service():
|
|
|
102
148
|
schemas=[SchemaRegistration(name=name, schema=schema)],
|
|
103
149
|
)
|
|
104
150
|
|
|
151
|
+
@service.path("/schemas/widget")
|
|
152
|
+
class WidgetDocumentSchemaRegistry(SchemaRegistry):
|
|
153
|
+
def __init__(self):
|
|
154
|
+
name = "widget"
|
|
155
|
+
schema = widget_schema
|
|
156
|
+
super().__init__(
|
|
157
|
+
name=f"meshagent.schema.{name}",
|
|
158
|
+
validate_webhook_secret=False,
|
|
159
|
+
schemas=[SchemaRegistration(name=name, schema=schema)],
|
|
160
|
+
)
|
|
161
|
+
|
|
105
162
|
@service.path("/schemas/presentation")
|
|
106
163
|
class PresentationDocumentSchemaRegistry(SchemaRegistry):
|
|
107
164
|
def __init__(presentation):
|
meshagent/cli/host.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from meshagent.api.services import ServiceHost
|
|
2
|
+
from meshagent.api.specs.service import ServiceSpec
|
|
3
|
+
import asyncio
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
options = {"deferred": False}
|
|
7
|
+
services = {}
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def set_deferred(deferred: bool):
|
|
11
|
+
options["deferred"] = deferred
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def get_deferred() -> bool:
|
|
15
|
+
return options["deferred"]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def get_service(port: int, host: str) -> ServiceHost:
|
|
19
|
+
if port not in services:
|
|
20
|
+
services[port] = ServiceHost(host=host, port=port)
|
|
21
|
+
|
|
22
|
+
return services[port]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def service_specs() -> list[ServiceSpec]:
|
|
26
|
+
specs = []
|
|
27
|
+
for port, s in services.items():
|
|
28
|
+
specs.append(s.get_service_spec(image=""))
|
|
29
|
+
return specs
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
async def run_services():
|
|
33
|
+
tasks = []
|
|
34
|
+
for port, s in services.items():
|
|
35
|
+
tasks.append(s.run())
|
|
36
|
+
|
|
37
|
+
await asyncio.gather(*tasks)
|