meshagent-cli 0.35.3__tar.gz → 0.35.4__tar.gz
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-0.35.3 → meshagent_cli-0.35.4}/PKG-INFO +13 -13
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/chatbot.py +106 -39
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/cli.py +6 -6
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/containers.py +5 -62
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/helper.py +55 -17
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/helper_test.py +20 -5
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/image.py +457 -148
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/image_test.py +359 -290
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/process_test.py +169 -4
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/task_runner.py +1 -1
- meshagent_cli-0.35.4/meshagent/cli/version.py +1 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/worker.py +0 -1
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent_cli.egg-info/PKG-INFO +13 -13
- meshagent_cli-0.35.4/meshagent_cli.egg-info/requires.txt +29 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/pyproject.toml +12 -12
- meshagent_cli-0.35.3/meshagent/cli/version.py +0 -1
- meshagent_cli-0.35.3/meshagent_cli.egg-info/requires.txt +0 -29
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/README.md +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/__init__.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/agent.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/api_keys.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/async_typer.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/auth.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/auth_async.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/call.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/cli_mcp.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/cli_secrets.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/cli_test.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/codex.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/common_options.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/containers_test.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/database.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/developer.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/developer_test.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/helpers.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/host.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/mailbot.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/mailboxes.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/meeting_transcriber.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/memory.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/memory_test.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/messaging.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/multi.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/oauth2.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/oci_archive.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/oci_archive_test.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/participant_token.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/port.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/port_test.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/process.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/projects.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/queue.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/queue_test.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/room.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/room_services.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/rooms.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/routes.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/scheduled_tasks.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/scheduled_tasks_test.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/services.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/services_test.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/sessions.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/sessions_test.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/storage.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/storage_test.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/sync.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/sync_test.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/test.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/tui/__init__.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/tui/setup.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/tui/setup_splash_frames.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/tui/setup_test.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/voicebot.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/webhook.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/webserver.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent/cli/webserver_test.py +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent_cli.egg-info/SOURCES.txt +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent_cli.egg-info/dependency_links.txt +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent_cli.egg-info/entry_points.txt +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/meshagent_cli.egg-info/top_level.txt +0 -0
- {meshagent_cli-0.35.3 → meshagent_cli-0.35.4}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: meshagent-cli
|
|
3
|
-
Version: 0.35.
|
|
3
|
+
Version: 0.35.4
|
|
4
4
|
Summary: CLI for Meshagent
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Project-URL: Documentation, https://docs.meshagent.com
|
|
@@ -19,21 +19,21 @@ Requires-Dist: rich~=14.3.0
|
|
|
19
19
|
Requires-Dist: textual<2.0,>=0.50
|
|
20
20
|
Requires-Dist: prompt-toolkit~=3.0.52
|
|
21
21
|
Provides-Extra: all
|
|
22
|
-
Requires-Dist: meshagent-agents[all]~=0.35.
|
|
23
|
-
Requires-Dist: meshagent-api[all]~=0.35.
|
|
24
|
-
Requires-Dist: meshagent-computers~=0.35.
|
|
25
|
-
Requires-Dist: meshagent-openai~=0.35.
|
|
26
|
-
Requires-Dist: meshagent-anthropic~=0.35.
|
|
27
|
-
Requires-Dist: meshagent-codex~=0.35.
|
|
28
|
-
Requires-Dist: meshagent-mcp~=0.35.
|
|
29
|
-
Requires-Dist: meshagent-tools~=0.35.
|
|
22
|
+
Requires-Dist: meshagent-agents[all]~=0.35.4; extra == "all"
|
|
23
|
+
Requires-Dist: meshagent-api[all]~=0.35.4; extra == "all"
|
|
24
|
+
Requires-Dist: meshagent-computers~=0.35.4; extra == "all"
|
|
25
|
+
Requires-Dist: meshagent-openai~=0.35.4; extra == "all"
|
|
26
|
+
Requires-Dist: meshagent-anthropic~=0.35.4; extra == "all"
|
|
27
|
+
Requires-Dist: meshagent-codex~=0.35.4; extra == "all"
|
|
28
|
+
Requires-Dist: meshagent-mcp~=0.35.4; extra == "all"
|
|
29
|
+
Requires-Dist: meshagent-tools~=0.35.4; extra == "all"
|
|
30
30
|
Requires-Dist: supabase-auth~=2.28.0; extra == "all"
|
|
31
31
|
Requires-Dist: prompt-toolkit~=3.0.52; extra == "all"
|
|
32
32
|
Provides-Extra: mcp-service
|
|
33
|
-
Requires-Dist: meshagent-agents[all]~=0.35.
|
|
34
|
-
Requires-Dist: meshagent-api~=0.35.
|
|
35
|
-
Requires-Dist: meshagent-mcp~=0.35.
|
|
36
|
-
Requires-Dist: meshagent-tools~=0.35.
|
|
33
|
+
Requires-Dist: meshagent-agents[all]~=0.35.4; extra == "mcp-service"
|
|
34
|
+
Requires-Dist: meshagent-api~=0.35.4; extra == "mcp-service"
|
|
35
|
+
Requires-Dist: meshagent-mcp~=0.35.4; extra == "mcp-service"
|
|
36
|
+
Requires-Dist: meshagent-tools~=0.35.4; extra == "mcp-service"
|
|
37
37
|
Requires-Dist: supabase-auth~=2.28.0; extra == "mcp-service"
|
|
38
38
|
|
|
39
39
|
# [Meshagent](https://www.meshagent.com)
|
|
@@ -9,6 +9,7 @@ from meshagent.tools import (
|
|
|
9
9
|
WebFetchTool,
|
|
10
10
|
WebFetchToolkitBuilder,
|
|
11
11
|
ContainerShellTool,
|
|
12
|
+
ContainerToolkit,
|
|
12
13
|
MemoriesToolkit,
|
|
13
14
|
)
|
|
14
15
|
from meshagent.tools.storage import (
|
|
@@ -52,6 +53,7 @@ from meshagent.api import (
|
|
|
52
53
|
from meshagent.api.helpers import meshagent_base_url, websocket_room_url
|
|
53
54
|
from meshagent.cli import async_typer
|
|
54
55
|
from meshagent.cli.helper import (
|
|
56
|
+
build_shell_tool,
|
|
55
57
|
build_shell_toolkit_builder,
|
|
56
58
|
cleanup_args,
|
|
57
59
|
cleanup_args_strip_options,
|
|
@@ -186,6 +188,14 @@ ShellSetEnvOption = Annotated[
|
|
|
186
188
|
),
|
|
187
189
|
]
|
|
188
190
|
|
|
191
|
+
RequireAdvancedShellOption = Annotated[
|
|
192
|
+
Optional[bool],
|
|
193
|
+
typer.Option(
|
|
194
|
+
"--require-advanced-shell",
|
|
195
|
+
help=("Enable the managed container toolkit with start/list/stop/run tools."),
|
|
196
|
+
),
|
|
197
|
+
]
|
|
198
|
+
|
|
189
199
|
WORKING_DIR_HELP = "The default working directory for shell commands"
|
|
190
200
|
|
|
191
201
|
WorkingDirOption = Annotated[
|
|
@@ -527,6 +537,20 @@ def _set_shell_env_vars(*, set_env: Optional[list[str]]) -> dict[str, str]:
|
|
|
527
537
|
return env
|
|
528
538
|
|
|
529
539
|
|
|
540
|
+
def _build_shell_tool_env(
|
|
541
|
+
*,
|
|
542
|
+
base_env: dict[str, str],
|
|
543
|
+
delegate_shell_token: Optional[bool],
|
|
544
|
+
room: RoomClient,
|
|
545
|
+
) -> dict[str, str]:
|
|
546
|
+
env = dict(base_env)
|
|
547
|
+
if delegate_shell_token:
|
|
548
|
+
env["MESHAGENT_TOKEN"] = room.protocol.token
|
|
549
|
+
env["OPENAI_API_KEY"] = room.protocol.token
|
|
550
|
+
env["ANTHROPIC_API_KEY"] = room.protocol.token
|
|
551
|
+
return env
|
|
552
|
+
|
|
553
|
+
|
|
530
554
|
def _resolve_working_dir_option(
|
|
531
555
|
*,
|
|
532
556
|
working_dir: Optional[str],
|
|
@@ -565,6 +589,7 @@ def build_chatbot(
|
|
|
565
589
|
require_image_generation: Optional[str] = None,
|
|
566
590
|
require_local_shell: Optional[str] = None,
|
|
567
591
|
require_shell: Optional[bool] = None,
|
|
592
|
+
require_advanced_shell: Optional[bool] = None,
|
|
568
593
|
require_apply_patch: Optional[str] = None,
|
|
569
594
|
require_computer_use: Optional[str] = None,
|
|
570
595
|
starting_url: Optional[str] = None,
|
|
@@ -707,16 +732,16 @@ def build_chatbot(
|
|
|
707
732
|
)
|
|
708
733
|
|
|
709
734
|
self.shell_tool = None
|
|
735
|
+
self.advanced_shell_toolkit = None
|
|
710
736
|
|
|
711
737
|
async def start(self, *, room: RoomClient):
|
|
712
738
|
await super().start(room=room)
|
|
713
739
|
|
|
714
|
-
env =
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
env["ANTHROPIC_API_KEY"] = self.room.protocol.token
|
|
740
|
+
env = _build_shell_tool_env(
|
|
741
|
+
base_env=base_shell_env,
|
|
742
|
+
delegate_shell_token=delegate_shell_token,
|
|
743
|
+
room=room,
|
|
744
|
+
)
|
|
720
745
|
|
|
721
746
|
if require_shell:
|
|
722
747
|
if supports_openai_shell:
|
|
@@ -733,6 +758,7 @@ def build_chatbot(
|
|
|
733
758
|
shell_kwargs = {
|
|
734
759
|
"image": resolved_shell_image,
|
|
735
760
|
"name": "shell",
|
|
761
|
+
"working_dir": working_dir,
|
|
736
762
|
"env": env,
|
|
737
763
|
}
|
|
738
764
|
if shell_tool_mounts is not None:
|
|
@@ -740,10 +766,28 @@ def build_chatbot(
|
|
|
740
766
|
|
|
741
767
|
self.shell_tool = ContainerShellTool(**shell_kwargs)
|
|
742
768
|
|
|
769
|
+
if require_advanced_shell:
|
|
770
|
+
self.advanced_shell_toolkit = ContainerToolkit(
|
|
771
|
+
working_dir=working_dir,
|
|
772
|
+
default_image=resolved_shell_image,
|
|
773
|
+
mounts=shell_tool_mounts,
|
|
774
|
+
env=env or None,
|
|
775
|
+
)
|
|
776
|
+
|
|
743
777
|
if room_rules_path is not None:
|
|
744
778
|
for p in room_rules_path:
|
|
745
779
|
await self._load_room_rules(path=p)
|
|
746
780
|
|
|
781
|
+
async def stop(self) -> None:
|
|
782
|
+
room = self._room
|
|
783
|
+
try:
|
|
784
|
+
if self.advanced_shell_toolkit is not None and room is not None:
|
|
785
|
+
await self.advanced_shell_toolkit.stop_all(room=room)
|
|
786
|
+
finally:
|
|
787
|
+
self.advanced_shell_toolkit = None
|
|
788
|
+
self.shell_tool = None
|
|
789
|
+
await super().stop()
|
|
790
|
+
|
|
747
791
|
async def init_session(self):
|
|
748
792
|
from meshagent.cli.helper import init_context_from_spec
|
|
749
793
|
|
|
@@ -854,6 +898,8 @@ def build_chatbot(
|
|
|
854
898
|
|
|
855
899
|
if self.shell_tool is not None:
|
|
856
900
|
add_tool(toolkit_name=self.shell_tool.name, tool=self.shell_tool)
|
|
901
|
+
if self.advanced_shell_toolkit is not None:
|
|
902
|
+
add_toolkit(self.advanced_shell_toolkit)
|
|
857
903
|
if require_mcp:
|
|
858
904
|
raise Exception(
|
|
859
905
|
"mcp tool cannot be required by cli currently, use 'optional' instead"
|
|
@@ -991,7 +1037,7 @@ def build_chatbot(
|
|
|
991
1037
|
shell_builder_kwargs["mounts"] = shell_tool_mounts
|
|
992
1038
|
providers.append(
|
|
993
1039
|
build_shell_toolkit_builder(
|
|
994
|
-
|
|
1040
|
+
llm_participant=llm_participant,
|
|
995
1041
|
**shell_builder_kwargs,
|
|
996
1042
|
)
|
|
997
1043
|
)
|
|
@@ -1044,6 +1090,7 @@ def build_process_agent(
|
|
|
1044
1090
|
require_image_generation: Optional[str] = None,
|
|
1045
1091
|
require_local_shell: Optional[str] = None,
|
|
1046
1092
|
require_shell: Optional[bool] = None,
|
|
1093
|
+
require_advanced_shell: Optional[bool] = None,
|
|
1047
1094
|
require_apply_patch: Optional[str] = None,
|
|
1048
1095
|
require_computer_use: Optional[str] = None,
|
|
1049
1096
|
starting_url: Optional[str] = None,
|
|
@@ -1117,9 +1164,6 @@ def build_process_agent(
|
|
|
1117
1164
|
|
|
1118
1165
|
is_claude_model = model.startswith("claude-")
|
|
1119
1166
|
supports_openai_tools = llm_participant is None and not is_claude_model
|
|
1120
|
-
supports_openai_shell = supports_openai_shell_tool(
|
|
1121
|
-
model=model, llm_participant=llm_participant
|
|
1122
|
-
)
|
|
1123
1167
|
base_shell_env = _copy_shell_env_vars(copy_env=shell_copy_env)
|
|
1124
1168
|
base_shell_env.update(_set_shell_env_vars(set_env=shell_set_env))
|
|
1125
1169
|
resolved_shell_image = resolve_shell_image(shell_image)
|
|
@@ -1192,7 +1236,8 @@ def build_process_agent(
|
|
|
1192
1236
|
self._mail_channels: list[MailChannel] = []
|
|
1193
1237
|
self._queue_channels: list[QueueChannel] = []
|
|
1194
1238
|
self._toolkit_channels: list[ToolkitChannel] = []
|
|
1195
|
-
self.
|
|
1239
|
+
self._shell_env: dict[str, str] = dict(base_shell_env)
|
|
1240
|
+
self._advanced_shell_toolkit: ContainerToolkit | None = None
|
|
1196
1241
|
self._resolved_threading_mode: str | None = None
|
|
1197
1242
|
if threading_mode != "none":
|
|
1198
1243
|
self._resolved_threading_mode = threading_mode
|
|
@@ -1272,32 +1317,22 @@ def build_process_agent(
|
|
|
1272
1317
|
try:
|
|
1273
1318
|
await self.install_requirements()
|
|
1274
1319
|
|
|
1275
|
-
env =
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1320
|
+
env = _build_shell_tool_env(
|
|
1321
|
+
base_env=base_shell_env,
|
|
1322
|
+
delegate_shell_token=delegate_shell_token,
|
|
1323
|
+
room=room,
|
|
1324
|
+
)
|
|
1280
1325
|
|
|
1281
1326
|
if require_shell:
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
self._shell_tool = ShellTool(**shell_kwargs)
|
|
1292
|
-
else:
|
|
1293
|
-
shell_kwargs = {
|
|
1294
|
-
"image": resolved_shell_image,
|
|
1295
|
-
"name": "shell",
|
|
1296
|
-
"env": env,
|
|
1297
|
-
}
|
|
1298
|
-
if shell_tool_mounts is not None:
|
|
1299
|
-
shell_kwargs["mounts"] = shell_tool_mounts
|
|
1300
|
-
self._shell_tool = ContainerShellTool(**shell_kwargs)
|
|
1327
|
+
self._shell_env = env
|
|
1328
|
+
|
|
1329
|
+
if require_advanced_shell:
|
|
1330
|
+
self._advanced_shell_toolkit = ContainerToolkit(
|
|
1331
|
+
working_dir=working_dir,
|
|
1332
|
+
default_image=resolved_shell_image,
|
|
1333
|
+
mounts=shell_tool_mounts,
|
|
1334
|
+
env=env or None,
|
|
1335
|
+
)
|
|
1301
1336
|
|
|
1302
1337
|
if room_rules_path is not None:
|
|
1303
1338
|
for room_rules_file in room_rules_path:
|
|
@@ -1330,6 +1365,7 @@ def build_process_agent(
|
|
|
1330
1365
|
self._mail_channels = []
|
|
1331
1366
|
self._queue_channels = []
|
|
1332
1367
|
self._toolkit_channels = []
|
|
1368
|
+
self._advanced_shell_toolkit = None
|
|
1333
1369
|
self._room = None
|
|
1334
1370
|
raise
|
|
1335
1371
|
|
|
@@ -1342,7 +1378,14 @@ def build_process_agent(
|
|
|
1342
1378
|
self._mail_channels = []
|
|
1343
1379
|
self._queue_channels = []
|
|
1344
1380
|
self._toolkit_channels = []
|
|
1345
|
-
|
|
1381
|
+
room = self._room
|
|
1382
|
+
try:
|
|
1383
|
+
if self._advanced_shell_toolkit is not None and room is not None:
|
|
1384
|
+
await self._advanced_shell_toolkit.stop_all(room=room)
|
|
1385
|
+
finally:
|
|
1386
|
+
self._advanced_shell_toolkit = None
|
|
1387
|
+
self._shell_env = dict(base_shell_env)
|
|
1388
|
+
await super().stop()
|
|
1346
1389
|
|
|
1347
1390
|
async def init_session(self) -> AgentSessionContext:
|
|
1348
1391
|
from meshagent.cli.helper import init_context_from_spec
|
|
@@ -1447,7 +1490,7 @@ def build_process_agent(
|
|
|
1447
1490
|
shell_builder_kwargs["mounts"] = shell_tool_mounts
|
|
1448
1491
|
providers.append(
|
|
1449
1492
|
build_shell_toolkit_builder(
|
|
1450
|
-
|
|
1493
|
+
llm_participant=llm_participant,
|
|
1451
1494
|
**shell_builder_kwargs,
|
|
1452
1495
|
)
|
|
1453
1496
|
)
|
|
@@ -1524,8 +1567,22 @@ def build_process_agent(
|
|
|
1524
1567
|
),
|
|
1525
1568
|
)
|
|
1526
1569
|
|
|
1527
|
-
if
|
|
1528
|
-
|
|
1570
|
+
if require_shell:
|
|
1571
|
+
shell_config = ShellConfig(name="shell")
|
|
1572
|
+
add_tool(
|
|
1573
|
+
toolkit_name=shell_config.name,
|
|
1574
|
+
tool=build_shell_tool(
|
|
1575
|
+
model=model,
|
|
1576
|
+
llm_participant=llm_participant,
|
|
1577
|
+
config=shell_config,
|
|
1578
|
+
working_dir=working_dir,
|
|
1579
|
+
image=resolved_shell_image,
|
|
1580
|
+
mounts=shell_tool_mounts,
|
|
1581
|
+
env=self._shell_env,
|
|
1582
|
+
),
|
|
1583
|
+
)
|
|
1584
|
+
if self._advanced_shell_toolkit is not None:
|
|
1585
|
+
add_toolkit(self._advanced_shell_toolkit)
|
|
1529
1586
|
|
|
1530
1587
|
if require_mcp:
|
|
1531
1588
|
raise Exception(
|
|
@@ -1851,6 +1908,7 @@ async def join(
|
|
|
1851
1908
|
Optional[bool],
|
|
1852
1909
|
typer.Option(..., help="Enable function shell tool calling"),
|
|
1853
1910
|
] = False,
|
|
1911
|
+
require_advanced_shell: RequireAdvancedShellOption = False,
|
|
1854
1912
|
require_apply_patch: Annotated[
|
|
1855
1913
|
Optional[bool],
|
|
1856
1914
|
typer.Option(..., help="Enable apply patch tool calling"),
|
|
@@ -2056,6 +2114,7 @@ async def join(
|
|
|
2056
2114
|
require_web_fetch=require_web_fetch,
|
|
2057
2115
|
require_local_shell=require_local_shell,
|
|
2058
2116
|
require_shell=require_shell,
|
|
2117
|
+
require_advanced_shell=require_advanced_shell,
|
|
2059
2118
|
require_image_generation=require_image_generation,
|
|
2060
2119
|
require_mcp=require_mcp,
|
|
2061
2120
|
require_storage=require_storage,
|
|
@@ -2244,6 +2303,7 @@ async def service(
|
|
|
2244
2303
|
Optional[bool],
|
|
2245
2304
|
typer.Option(..., help="Enable function shell tool calling"),
|
|
2246
2305
|
] = False,
|
|
2306
|
+
require_advanced_shell: RequireAdvancedShellOption = False,
|
|
2247
2307
|
require_apply_patch: Annotated[
|
|
2248
2308
|
Optional[bool], typer.Option(..., help="Enable apply patch tool")
|
|
2249
2309
|
] = False,
|
|
@@ -2434,6 +2494,7 @@ async def service(
|
|
|
2434
2494
|
require_web_search=require_web_search,
|
|
2435
2495
|
require_web_fetch=require_web_fetch,
|
|
2436
2496
|
require_shell=require_shell,
|
|
2497
|
+
require_advanced_shell=require_advanced_shell,
|
|
2437
2498
|
require_apply_patch=require_apply_patch,
|
|
2438
2499
|
require_local_shell=require_local_shell,
|
|
2439
2500
|
require_image_generation=require_image_generation,
|
|
@@ -2596,6 +2657,7 @@ async def spec(
|
|
|
2596
2657
|
Optional[bool],
|
|
2597
2658
|
typer.Option(..., help="Enable function shell tool calling"),
|
|
2598
2659
|
] = False,
|
|
2660
|
+
require_advanced_shell: RequireAdvancedShellOption = False,
|
|
2599
2661
|
require_apply_patch: Annotated[
|
|
2600
2662
|
Optional[bool], typer.Option(..., help="Enable apply patch tool")
|
|
2601
2663
|
] = False,
|
|
@@ -2776,6 +2838,7 @@ async def spec(
|
|
|
2776
2838
|
require_web_search=require_web_search,
|
|
2777
2839
|
require_web_fetch=require_web_fetch,
|
|
2778
2840
|
require_shell=require_shell,
|
|
2841
|
+
require_advanced_shell=require_advanced_shell,
|
|
2779
2842
|
require_apply_patch=require_apply_patch,
|
|
2780
2843
|
require_local_shell=require_local_shell,
|
|
2781
2844
|
require_image_generation=require_image_generation,
|
|
@@ -2958,6 +3021,7 @@ async def deploy(
|
|
|
2958
3021
|
Optional[bool],
|
|
2959
3022
|
typer.Option(..., help="Enable function shell tool calling"),
|
|
2960
3023
|
] = False,
|
|
3024
|
+
require_advanced_shell: RequireAdvancedShellOption = False,
|
|
2961
3025
|
require_apply_patch: Annotated[
|
|
2962
3026
|
Optional[bool], typer.Option(..., help="Enable apply patch tool")
|
|
2963
3027
|
] = False,
|
|
@@ -3145,6 +3209,7 @@ async def deploy(
|
|
|
3145
3209
|
require_web_search=require_web_search,
|
|
3146
3210
|
require_web_fetch=require_web_fetch,
|
|
3147
3211
|
require_shell=require_shell,
|
|
3212
|
+
require_advanced_shell=require_advanced_shell,
|
|
3148
3213
|
require_apply_patch=require_apply_patch,
|
|
3149
3214
|
require_local_shell=require_local_shell,
|
|
3150
3215
|
require_image_generation=require_image_generation,
|
|
@@ -4824,6 +4889,7 @@ async def run(
|
|
|
4824
4889
|
Optional[bool],
|
|
4825
4890
|
typer.Option(..., help="Enable function shell tool calling"),
|
|
4826
4891
|
] = False,
|
|
4892
|
+
require_advanced_shell: RequireAdvancedShellOption = False,
|
|
4827
4893
|
require_apply_patch: Annotated[
|
|
4828
4894
|
Optional[bool],
|
|
4829
4895
|
typer.Option(..., help="Enable apply patch tool calling"),
|
|
@@ -5053,6 +5119,7 @@ async def run(
|
|
|
5053
5119
|
require_web_fetch=require_web_fetch,
|
|
5054
5120
|
require_local_shell=require_local_shell,
|
|
5055
5121
|
require_shell=require_shell,
|
|
5122
|
+
require_advanced_shell=require_advanced_shell,
|
|
5056
5123
|
require_image_generation=require_image_generation,
|
|
5057
5124
|
require_mcp=require_mcp,
|
|
5058
5125
|
require_storage=require_storage,
|
|
@@ -86,18 +86,18 @@ app.add_typer(routes.app, name="route")
|
|
|
86
86
|
app.add_typer(scheduled_tasks.app, name="scheduled-task")
|
|
87
87
|
app.add_typer(meeting_transcriber.app, name="meeting-transcriber")
|
|
88
88
|
app.add_typer(port.app, name="port")
|
|
89
|
-
app.add_typer(webserver.app, name="webserver")
|
|
90
|
-
app.add_typer(codex.app, name="codex")
|
|
89
|
+
app.add_typer(webserver.app, name="webserver", hidden=True)
|
|
90
|
+
app.add_typer(codex.app, name="codex", hidden=True)
|
|
91
91
|
if not os.getenv("MESHAGENT_CLI_BUILD"):
|
|
92
92
|
app.add_typer(test.app, name="test", hidden=True)
|
|
93
93
|
|
|
94
94
|
app.add_typer(multi.app, name="multi")
|
|
95
95
|
app.add_typer(voicebot.app, name="voicebot")
|
|
96
|
-
app.add_typer(chatbot.app, name="chatbot")
|
|
96
|
+
app.add_typer(chatbot.app, name="chatbot", hidden=True)
|
|
97
97
|
app.add_typer(process.app, name="process")
|
|
98
|
-
app.add_typer(mailbot.app, name="mailbot")
|
|
99
|
-
app.add_typer(task_runner.app, name="task-runner")
|
|
100
|
-
app.add_typer(worker.app, name="worker")
|
|
98
|
+
app.add_typer(mailbot.app, name="mailbot", hidden=True)
|
|
99
|
+
app.add_typer(task_runner.app, name="task-runner", hidden=True)
|
|
100
|
+
app.add_typer(worker.app, name="worker", hidden=True)
|
|
101
101
|
|
|
102
102
|
app.add_typer(room.app, name="room")
|
|
103
103
|
app.add_typer(image.app, name="image")
|
|
@@ -605,7 +605,6 @@ async def exec_container(
|
|
|
605
605
|
Optional[str],
|
|
606
606
|
typer.Option(..., help="Command to execute in the container (quoted string)"),
|
|
607
607
|
] = None,
|
|
608
|
-
tty: Annotated[bool, typer.Option(..., help="Allocate a TTY")] = False,
|
|
609
608
|
):
|
|
610
609
|
account_client, client = await _with_client(
|
|
611
610
|
project_id=project_id,
|
|
@@ -614,16 +613,13 @@ async def exec_container(
|
|
|
614
613
|
result = 1
|
|
615
614
|
|
|
616
615
|
try:
|
|
617
|
-
import termios
|
|
618
616
|
import shlex
|
|
619
617
|
|
|
620
|
-
from contextlib import contextmanager
|
|
621
|
-
|
|
622
618
|
parsed_command = shlex.split(command) if command else None
|
|
623
619
|
container = await client.containers.exec(
|
|
624
620
|
container_id=container_id,
|
|
625
621
|
command=parsed_command,
|
|
626
|
-
tty=
|
|
622
|
+
tty=False,
|
|
627
623
|
)
|
|
628
624
|
|
|
629
625
|
async def write_all(fd, data: bytes) -> None:
|
|
@@ -650,17 +646,6 @@ async def exec_container(
|
|
|
650
646
|
async for output in container.stdout():
|
|
651
647
|
await write_all(sys.stdout.fileno(), output)
|
|
652
648
|
|
|
653
|
-
@contextmanager
|
|
654
|
-
def raw_mode(fd: int):
|
|
655
|
-
import tty
|
|
656
|
-
|
|
657
|
-
old = termios.tcgetattr(fd)
|
|
658
|
-
try:
|
|
659
|
-
tty.setraw(fd) # immediate bytes
|
|
660
|
-
yield
|
|
661
|
-
finally:
|
|
662
|
-
termios.tcsetattr(fd, termios.TCSADRAIN, old)
|
|
663
|
-
|
|
664
649
|
async def read_piped_stdin(bufsize: int = 1024):
|
|
665
650
|
while True:
|
|
666
651
|
chunk = await asyncio.to_thread(sys.stdin.buffer.read, bufsize)
|
|
@@ -671,53 +656,11 @@ async def exec_container(
|
|
|
671
656
|
|
|
672
657
|
await container.write(chunk)
|
|
673
658
|
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
if not sys.stdin.isatty():
|
|
677
|
-
while True:
|
|
678
|
-
chunk = sys.stdin.buffer.read(bufsize)
|
|
679
|
-
if not chunk:
|
|
680
|
-
return
|
|
681
|
-
await container.write(chunk)
|
|
682
|
-
return
|
|
683
|
-
|
|
684
|
-
fd = sys.stdin.fileno()
|
|
685
|
-
|
|
686
|
-
# Make reads non-blocking so we never hang shutdown
|
|
687
|
-
prev_blocking = os.get_blocking(fd)
|
|
688
|
-
os.set_blocking(fd, False)
|
|
689
|
-
|
|
690
|
-
try:
|
|
691
|
-
with raw_mode(fd):
|
|
692
|
-
while True:
|
|
693
|
-
try:
|
|
694
|
-
chunk = os.read(fd, bufsize)
|
|
695
|
-
except BlockingIOError:
|
|
696
|
-
# nothing typed yet
|
|
697
|
-
await asyncio.sleep(0.01)
|
|
698
|
-
continue
|
|
699
|
-
|
|
700
|
-
if chunk == b"":
|
|
701
|
-
return
|
|
702
|
-
|
|
703
|
-
# optional: allow Ctrl-C to exit
|
|
704
|
-
if chunk == b"\x03":
|
|
705
|
-
return
|
|
706
|
-
|
|
707
|
-
await container.write(chunk)
|
|
708
|
-
finally:
|
|
709
|
-
os.set_blocking(fd, prev_blocking)
|
|
710
|
-
|
|
711
|
-
if not tty and not sys.stdin.isatty():
|
|
712
|
-
await asyncio.gather(read_stdout(), read_stderr(), read_piped_stdin())
|
|
713
|
-
else:
|
|
714
|
-
if not sys.stdin.isatty():
|
|
715
|
-
print("[red]TTY requested but not a TTY[/red]")
|
|
716
|
-
raise typer.Exit(-1)
|
|
717
|
-
|
|
718
|
-
reader = asyncio.create_task(read_stdin())
|
|
659
|
+
if sys.stdin.isatty():
|
|
660
|
+
await container.close_stdin()
|
|
719
661
|
await asyncio.gather(read_stdout(), read_stderr())
|
|
720
|
-
|
|
662
|
+
else:
|
|
663
|
+
await asyncio.gather(read_stdout(), read_stderr(), read_piped_stdin())
|
|
721
664
|
|
|
722
665
|
result = await container.result
|
|
723
666
|
finally:
|
|
@@ -21,8 +21,13 @@ from meshagent.api.specs.service import (
|
|
|
21
21
|
from meshagent.agents.context import AgentSessionContext
|
|
22
22
|
from meshagent.api.client import Meshagent, RoomConnectionInfo
|
|
23
23
|
from meshagent.cli import async_typer, auth_async
|
|
24
|
-
from meshagent.openai.tools.responses_adapter import ShellConfig,
|
|
25
|
-
from meshagent.tools import
|
|
24
|
+
from meshagent.openai.tools.responses_adapter import ShellConfig, ShellTool
|
|
25
|
+
from meshagent.tools import (
|
|
26
|
+
ContainerShellTool,
|
|
27
|
+
ProcessShellTool,
|
|
28
|
+
Toolkit,
|
|
29
|
+
ToolkitBuilder,
|
|
30
|
+
)
|
|
26
31
|
from meshagent.tools.container_shell import DEFAULT_CONTAINER_MOUNT_SPEC
|
|
27
32
|
from meshagent.tools.storage import (
|
|
28
33
|
StorageToolLocalMount,
|
|
@@ -64,16 +69,56 @@ def supports_openai_shell_tool(
|
|
|
64
69
|
return llm_participant is None and model.startswith("gpt-")
|
|
65
70
|
|
|
66
71
|
|
|
67
|
-
|
|
72
|
+
def build_shell_tool(
|
|
73
|
+
*,
|
|
74
|
+
model: str,
|
|
75
|
+
llm_participant: Optional[str] = None,
|
|
76
|
+
config: Optional[ShellConfig] = None,
|
|
77
|
+
working_dir: Optional[str] = None,
|
|
78
|
+
image: Optional[str] = DEFAULT_SHELL_IMAGE,
|
|
79
|
+
mounts: Optional[ContainerMountSpec] = DEFAULT_CONTAINER_MOUNT_SPEC,
|
|
80
|
+
env: Optional[dict[str, str]] = None,
|
|
81
|
+
) -> ShellTool | ContainerShellTool | ProcessShellTool:
|
|
82
|
+
if config is None:
|
|
83
|
+
config = ShellConfig(name="shell")
|
|
84
|
+
|
|
85
|
+
if supports_openai_shell_tool(model=model, llm_participant=llm_participant):
|
|
86
|
+
return ShellTool(
|
|
87
|
+
config=config,
|
|
88
|
+
working_dir=working_dir,
|
|
89
|
+
image=image,
|
|
90
|
+
mounts=mounts,
|
|
91
|
+
env=env,
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
if image is None:
|
|
95
|
+
return ProcessShellTool(
|
|
96
|
+
name=config.name,
|
|
97
|
+
working_dir=working_dir,
|
|
98
|
+
env=env,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
return ContainerShellTool(
|
|
102
|
+
name=config.name,
|
|
103
|
+
working_dir=working_dir,
|
|
104
|
+
image=image,
|
|
105
|
+
mounts=mounts,
|
|
106
|
+
env=env,
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class _RuntimeAwareShellToolkitBuilder(ToolkitBuilder):
|
|
68
111
|
def __init__(
|
|
69
112
|
self,
|
|
70
113
|
*,
|
|
114
|
+
llm_participant: Optional[str] = None,
|
|
71
115
|
working_dir: Optional[str] = None,
|
|
72
116
|
image: Optional[str] = DEFAULT_SHELL_IMAGE,
|
|
73
117
|
mounts: Optional[ContainerMountSpec] = DEFAULT_CONTAINER_MOUNT_SPEC,
|
|
74
118
|
env: Optional[dict[str, str]] = None,
|
|
75
119
|
) -> None:
|
|
76
120
|
super().__init__(name="shell", type=ShellConfig)
|
|
121
|
+
self.llm_participant = llm_participant
|
|
77
122
|
self.working_dir = working_dir
|
|
78
123
|
self.image = image
|
|
79
124
|
self.mounts = mounts
|
|
@@ -83,13 +128,13 @@ class _ContainerBackedShellToolkitBuilder(ToolkitBuilder):
|
|
|
83
128
|
self, *, room: RoomClient, model: str, config: ShellConfig
|
|
84
129
|
) -> Toolkit:
|
|
85
130
|
del room
|
|
86
|
-
del model
|
|
87
|
-
del config
|
|
88
131
|
return Toolkit(
|
|
89
132
|
name="shell",
|
|
90
133
|
tools=[
|
|
91
|
-
|
|
92
|
-
|
|
134
|
+
build_shell_tool(
|
|
135
|
+
model=model,
|
|
136
|
+
llm_participant=self.llm_participant,
|
|
137
|
+
config=config,
|
|
93
138
|
working_dir=self.working_dir,
|
|
94
139
|
image=self.image,
|
|
95
140
|
mounts=self.mounts,
|
|
@@ -101,21 +146,14 @@ class _ContainerBackedShellToolkitBuilder(ToolkitBuilder):
|
|
|
101
146
|
|
|
102
147
|
def build_shell_toolkit_builder(
|
|
103
148
|
*,
|
|
104
|
-
|
|
149
|
+
llm_participant: Optional[str] = None,
|
|
105
150
|
working_dir: Optional[str] = None,
|
|
106
151
|
image: Optional[str] = DEFAULT_SHELL_IMAGE,
|
|
107
152
|
mounts: Optional[ContainerMountSpec] = DEFAULT_CONTAINER_MOUNT_SPEC,
|
|
108
153
|
env: Optional[dict[str, str]] = None,
|
|
109
154
|
) -> ToolkitBuilder:
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
working_dir=working_dir,
|
|
113
|
-
image=image,
|
|
114
|
-
mounts=mounts,
|
|
115
|
-
env=env,
|
|
116
|
-
)
|
|
117
|
-
|
|
118
|
-
return _ContainerBackedShellToolkitBuilder(
|
|
155
|
+
return _RuntimeAwareShellToolkitBuilder(
|
|
156
|
+
llm_participant=llm_participant,
|
|
119
157
|
working_dir=working_dir,
|
|
120
158
|
image=image,
|
|
121
159
|
mounts=mounts,
|