meshagent-cli 0.41.4__tar.gz → 0.41.5__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.41.4 → meshagent_cli-0.41.5}/PKG-INFO +16 -16
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/ask.py +173 -18
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/ask_test.py +230 -7
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/async_typer.py +26 -2
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/create.py +119 -18
- meshagent_cli-0.41.5/meshagent/cli/create_project_templates/python/contact-form/server.py +368 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/create_test.py +170 -1
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/doctor.py +20 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/image.py +942 -163
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/image_test.py +286 -10
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/local_settings.py +0 -9
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/local_settings_test.py +2 -2
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/process.py +3 -1
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/root_commands.py +9 -2
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/root_commands_test.py +69 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/services.py +66 -11
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/services_test.py +143 -0
- meshagent_cli-0.41.5/meshagent/cli/tui/deploy_room.py +1296 -0
- meshagent_cli-0.41.5/meshagent/cli/tui/deploy_room_test.py +61 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/tui/setup.py +41 -7
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/tui/setup_test.py +76 -0
- meshagent_cli-0.41.5/meshagent/cli/version.py +1 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent_cli.egg-info/PKG-INFO +16 -16
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent_cli.egg-info/SOURCES.txt +1 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent_cli.egg-info/requires.txt +15 -15
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/pyproject.toml +15 -15
- meshagent_cli-0.41.4/meshagent/cli/tui/deploy_room.py +0 -517
- meshagent_cli-0.41.4/meshagent/cli/tui/deploy_room_test.py +0 -19
- meshagent_cli-0.41.4/meshagent/cli/version.py +0 -1
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/LICENSE +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/README.md +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/__init__.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/agent.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/agent_cli_options_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/agent_package_cli.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/agent_package_cli_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/agents.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/agents_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/api_keys.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/api_keys_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/async_typer_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/auth.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/auth_async.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/auth_async_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/auth_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/call.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/chatbot.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/cli.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/cli_mcp.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/cli_secrets.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/cli_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/common_options.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/config.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/config_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/containers.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/containers_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/create_project_templates/__init__.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/create_project_templates/python/backend-agent/server.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/create_project_templates/python/webserver/server.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/dataset.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/dataset_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/developer.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/developer_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/doctor_dockerfiles/__init__.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/doctor_templates/__init__.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/doctor_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/feeds.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/helper.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/helper_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/helpers.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/host.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/launch.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/launch_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/llm.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/llm_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/mailbot.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/mailbot_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/mailboxes.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/meeting_transcriber.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/memory.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/memory_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/meshagent_images.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/meshagent_images_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/messaging.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/multi.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/oauth2.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/oauth2_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/oci_archive.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/oci_archive_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/participant_token.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/port.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/port_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/preamble_rules.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/preamble_rules_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/process_live_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/process_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/projects.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/projects_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/queue.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/queue_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/registry.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/registry_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/room.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/room_connect.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/room_connect_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/room_services.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/rooms.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/rooms_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/routes.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/scheduled_tasks.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/scheduled_tasks_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/sessions.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/sessions_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/storage.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/storage_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/subscriptions.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/sync.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/sync_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/task_runner.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/task_runner_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/tool_call_summary.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/tool_call_summary_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/tool_integrations.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/tool_integrations_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/tui/__init__.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/tui/auth_switch.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/tui/auth_switch_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/tui/create.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/tui/project_activate.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/tui/project_activate_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/tui/setup_splash_frames.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/voicebot.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/webhook.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/webserver.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/webserver_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/worker.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent/cli/worker_test.py +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent_cli.egg-info/dependency_links.txt +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent_cli.egg-info/entry_points.txt +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/meshagent_cli.egg-info/top_level.txt +0 -0
- {meshagent_cli-0.41.4 → meshagent_cli-0.41.5}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: meshagent-cli
|
|
3
|
-
Version: 0.41.
|
|
3
|
+
Version: 0.41.5
|
|
4
4
|
Summary: CLI for Meshagent
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Project-URL: Documentation, https://docs.meshagent.com
|
|
@@ -22,7 +22,7 @@ Requires-Dist: openpyxl~=3.1
|
|
|
22
22
|
Requires-Dist: xlsxwriter~=3.2
|
|
23
23
|
Requires-Dist: pathspec<2,>=1.0.3
|
|
24
24
|
Requires-Dist: zstandard~=0.25.0
|
|
25
|
-
Requires-Dist: meshagent-llm-proxy==0.41.
|
|
25
|
+
Requires-Dist: meshagent-llm-proxy==0.41.5
|
|
26
26
|
Requires-Dist: rich~=14.3.0
|
|
27
27
|
Requires-Dist: sounddevice~=0.5
|
|
28
28
|
Requires-Dist: textual<9.0,>=8.2.3
|
|
@@ -30,23 +30,23 @@ Requires-Dist: prompt-toolkit~=3.0.52
|
|
|
30
30
|
Requires-Dist: ascii-magic~=2.3
|
|
31
31
|
Requires-Dist: pillow~=11.3.0
|
|
32
32
|
Provides-Extra: all
|
|
33
|
-
Requires-Dist: meshagent-agents[all]==0.41.
|
|
34
|
-
Requires-Dist: meshagent-api[all]==0.41.
|
|
35
|
-
Requires-Dist: meshagent-commoncrawl==0.41.
|
|
36
|
-
Requires-Dist: meshagent-scrapy==0.41.
|
|
37
|
-
Requires-Dist: meshagent-computers==0.41.
|
|
38
|
-
Requires-Dist: meshagent-openai==0.41.
|
|
39
|
-
Requires-Dist: meshagent-anthropic==0.41.
|
|
40
|
-
Requires-Dist: meshagent-otel==0.41.
|
|
41
|
-
Requires-Dist: meshagent-mcp==0.41.
|
|
42
|
-
Requires-Dist: meshagent-tools==0.41.
|
|
33
|
+
Requires-Dist: meshagent-agents[all]==0.41.5; extra == "all"
|
|
34
|
+
Requires-Dist: meshagent-api[all]==0.41.5; extra == "all"
|
|
35
|
+
Requires-Dist: meshagent-commoncrawl==0.41.5; extra == "all"
|
|
36
|
+
Requires-Dist: meshagent-scrapy==0.41.5; extra == "all"
|
|
37
|
+
Requires-Dist: meshagent-computers==0.41.5; extra == "all"
|
|
38
|
+
Requires-Dist: meshagent-openai==0.41.5; extra == "all"
|
|
39
|
+
Requires-Dist: meshagent-anthropic==0.41.5; extra == "all"
|
|
40
|
+
Requires-Dist: meshagent-otel==0.41.5; extra == "all"
|
|
41
|
+
Requires-Dist: meshagent-mcp==0.41.5; extra == "all"
|
|
42
|
+
Requires-Dist: meshagent-tools==0.41.5; extra == "all"
|
|
43
43
|
Requires-Dist: supabase-auth~=2.28.0; extra == "all"
|
|
44
44
|
Requires-Dist: prompt-toolkit~=3.0.52; extra == "all"
|
|
45
45
|
Provides-Extra: mcp-service
|
|
46
|
-
Requires-Dist: meshagent-agents[all]==0.41.
|
|
47
|
-
Requires-Dist: meshagent-api==0.41.
|
|
48
|
-
Requires-Dist: meshagent-mcp==0.41.
|
|
49
|
-
Requires-Dist: meshagent-tools==0.41.
|
|
46
|
+
Requires-Dist: meshagent-agents[all]==0.41.5; extra == "mcp-service"
|
|
47
|
+
Requires-Dist: meshagent-api==0.41.5; extra == "mcp-service"
|
|
48
|
+
Requires-Dist: meshagent-mcp==0.41.5; extra == "mcp-service"
|
|
49
|
+
Requires-Dist: meshagent-tools==0.41.5; extra == "mcp-service"
|
|
50
50
|
Requires-Dist: supabase-auth~=2.28.0; extra == "mcp-service"
|
|
51
51
|
Dynamic: license-file
|
|
52
52
|
|
|
@@ -14,6 +14,7 @@ import time
|
|
|
14
14
|
import uuid
|
|
15
15
|
from collections.abc import Awaitable, Callable, Sequence
|
|
16
16
|
from dataclasses import dataclass
|
|
17
|
+
from importlib import resources
|
|
17
18
|
from typing import Annotated, Any, Literal, Protocol, runtime_checkable
|
|
18
19
|
|
|
19
20
|
import click
|
|
@@ -131,6 +132,7 @@ from meshagent.agents.process import (
|
|
|
131
132
|
from meshagent.api import Participant, RoomException
|
|
132
133
|
from meshagent.cli import async_typer, auth_async
|
|
133
134
|
from meshagent.cli.common_options import ProjectIdOption
|
|
135
|
+
from meshagent.cli.create import CREATE_TEMPLATE_PACKAGE
|
|
134
136
|
from meshagent.cli.helper import resolve_project_id
|
|
135
137
|
from meshagent.cli.preamble_rules import DEFAULT_PREAMBLE_RULE
|
|
136
138
|
from meshagent.cli.tool_call_summary import format_tool_call_summary
|
|
@@ -419,6 +421,9 @@ class _AskExternalThreadState(Protocol):
|
|
|
419
421
|
@property
|
|
420
422
|
def thread_status_text(self) -> str | None: ...
|
|
421
423
|
|
|
424
|
+
@property
|
|
425
|
+
def thread_status(self) -> AgentThreadStatus | None: ...
|
|
426
|
+
|
|
422
427
|
@property
|
|
423
428
|
def queued_message_labels(self) -> tuple[str, ...]: ...
|
|
424
429
|
|
|
@@ -471,6 +476,9 @@ class _AgentMessageChannelClient(Protocol):
|
|
|
471
476
|
@property
|
|
472
477
|
def thread_status_text(self) -> str | None: ...
|
|
473
478
|
|
|
479
|
+
@property
|
|
480
|
+
def thread_status(self) -> AgentThreadStatus | None: ...
|
|
481
|
+
|
|
474
482
|
@property
|
|
475
483
|
def queued_message_labels(self) -> tuple[str, ...]: ...
|
|
476
484
|
|
|
@@ -509,6 +517,44 @@ def _thread_status_text(status: object) -> str | None:
|
|
|
509
517
|
return normalized
|
|
510
518
|
|
|
511
519
|
|
|
520
|
+
def _format_grouped_status_digits(value: int) -> str:
|
|
521
|
+
text = str(value)
|
|
522
|
+
parts: list[str] = []
|
|
523
|
+
for index, char in enumerate(text):
|
|
524
|
+
if index > 0 and (len(text) - index) % 3 == 0:
|
|
525
|
+
parts.append(",")
|
|
526
|
+
parts.append(char)
|
|
527
|
+
return "".join(parts)
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
def _format_agent_thread_status_text(message: AgentThreadStatus) -> str | None:
|
|
531
|
+
text = _thread_status_text(message.status)
|
|
532
|
+
if text is None:
|
|
533
|
+
return None
|
|
534
|
+
if message.lines_added is not None or message.lines_removed is not None:
|
|
535
|
+
parts = [text]
|
|
536
|
+
if message.lines_added is not None:
|
|
537
|
+
parts.append(f"+{_format_grouped_status_digits(message.lines_added)}")
|
|
538
|
+
if message.lines_removed is not None:
|
|
539
|
+
parts.append(f"-{_format_grouped_status_digits(message.lines_removed)}")
|
|
540
|
+
return " ".join(parts)
|
|
541
|
+
if message.total_bytes is not None and message.total_bytes > 100:
|
|
542
|
+
return f"{text} {_format_grouped_status_digits(message.total_bytes)} bytes"
|
|
543
|
+
return text
|
|
544
|
+
|
|
545
|
+
|
|
546
|
+
def _ask_thread_status_feed_text(status: object) -> str | None:
|
|
547
|
+
if isinstance(status, AgentThreadStatus):
|
|
548
|
+
text = _format_agent_thread_status_text(status)
|
|
549
|
+
if text is None:
|
|
550
|
+
return None
|
|
551
|
+
return f"• {text}"
|
|
552
|
+
text = _thread_status_text(status)
|
|
553
|
+
if text is None:
|
|
554
|
+
return None
|
|
555
|
+
return f"• {text}"
|
|
556
|
+
|
|
557
|
+
|
|
512
558
|
def _agent_message_content_text(
|
|
513
559
|
content: list[AgentTextContent | AgentFileContent],
|
|
514
560
|
) -> str:
|
|
@@ -645,7 +691,7 @@ def _image_dataset_client_from_agent_client(
|
|
|
645
691
|
chat_client = client.client
|
|
646
692
|
if not isinstance(chat_client, MessagingChatClient):
|
|
647
693
|
return None
|
|
648
|
-
return ImageDatasetClient(chat_client.room)
|
|
694
|
+
return ImageDatasetClient(chat_client.room.datasets)
|
|
649
695
|
|
|
650
696
|
|
|
651
697
|
def _role_for_sender(
|
|
@@ -995,6 +1041,10 @@ class _AgentMessageSession:
|
|
|
995
1041
|
return self._thread_status_text
|
|
996
1042
|
return self._client.thread_status_text
|
|
997
1043
|
|
|
1044
|
+
@property
|
|
1045
|
+
def thread_status(self) -> AgentThreadStatus | None:
|
|
1046
|
+
return self._client.thread_status
|
|
1047
|
+
|
|
998
1048
|
@property
|
|
999
1049
|
def queued_message_labels(self) -> tuple[str, ...]:
|
|
1000
1050
|
return self._client.queued_message_labels
|
|
@@ -1378,10 +1428,14 @@ class _AskSession:
|
|
|
1378
1428
|
resolved_current_working_directory = os.path.abspath(
|
|
1379
1429
|
current_working_directory or os.getcwd()
|
|
1380
1430
|
)
|
|
1431
|
+
self._resource_stack = contextlib.ExitStack()
|
|
1432
|
+
create_samples_path = _enter_create_samples_path(self._resource_stack)
|
|
1433
|
+
self._create_samples_path = create_samples_path
|
|
1381
1434
|
self._current_working_directory = resolved_current_working_directory
|
|
1382
1435
|
self._toolkits = _build_ask_toolkits(
|
|
1383
1436
|
model=model,
|
|
1384
1437
|
current_working_directory=resolved_current_working_directory,
|
|
1438
|
+
create_samples_path=create_samples_path,
|
|
1385
1439
|
)
|
|
1386
1440
|
self._status_adapter = _StatusAwareLLMAdapter(delegate=llm_adapter)
|
|
1387
1441
|
self._process = LLMAgentProcess(
|
|
@@ -1391,6 +1445,7 @@ class _AskSession:
|
|
|
1391
1445
|
toolkits=self._toolkits,
|
|
1392
1446
|
turn_instructions_provider=_build_ask_turn_instructions_provider(
|
|
1393
1447
|
current_working_directory=resolved_current_working_directory,
|
|
1448
|
+
create_samples_path=create_samples_path,
|
|
1394
1449
|
interactive=interactive,
|
|
1395
1450
|
preamble_rule=preamble_rule,
|
|
1396
1451
|
),
|
|
@@ -1411,10 +1466,18 @@ class _AskSession:
|
|
|
1411
1466
|
def current_working_directory(self) -> str:
|
|
1412
1467
|
return self._current_working_directory
|
|
1413
1468
|
|
|
1469
|
+
@property
|
|
1470
|
+
def create_samples_path(self) -> str:
|
|
1471
|
+
return self._create_samples_path
|
|
1472
|
+
|
|
1414
1473
|
@property
|
|
1415
1474
|
def thread_status_text(self) -> str | None:
|
|
1416
1475
|
return self._session.thread_status_text
|
|
1417
1476
|
|
|
1477
|
+
@property
|
|
1478
|
+
def thread_status(self) -> AgentThreadStatus | None:
|
|
1479
|
+
return self._session.thread_status
|
|
1480
|
+
|
|
1418
1481
|
@property
|
|
1419
1482
|
def queued_message_labels(self) -> tuple[str, ...]:
|
|
1420
1483
|
return self._session.queued_message_labels
|
|
@@ -1437,10 +1500,13 @@ class _AskSession:
|
|
|
1437
1500
|
await self._supervisor.start()
|
|
1438
1501
|
|
|
1439
1502
|
async def stop(self) -> None:
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1503
|
+
try:
|
|
1504
|
+
self._status_adapter.set_status_callback(None)
|
|
1505
|
+
await self._session.close(close_client=False)
|
|
1506
|
+
await self._channel_client.close()
|
|
1507
|
+
await self._supervisor.stop()
|
|
1508
|
+
finally:
|
|
1509
|
+
self._resource_stack.close()
|
|
1444
1510
|
|
|
1445
1511
|
def _handle_adapter_status(self, status: str) -> None:
|
|
1446
1512
|
self._session.add_agent_message(
|
|
@@ -1566,10 +1632,19 @@ async def _resolve_ask_access_token() -> str | None:
|
|
|
1566
1632
|
return normalized_access_token
|
|
1567
1633
|
|
|
1568
1634
|
|
|
1635
|
+
def _enter_create_samples_path(resource_stack: contextlib.ExitStack) -> str:
|
|
1636
|
+
create_samples_resource = resources.files(CREATE_TEMPLATE_PACKAGE)
|
|
1637
|
+
create_samples_path = resource_stack.enter_context(
|
|
1638
|
+
resources.as_file(create_samples_resource)
|
|
1639
|
+
)
|
|
1640
|
+
return os.path.abspath(os.fspath(create_samples_path))
|
|
1641
|
+
|
|
1642
|
+
|
|
1569
1643
|
def _build_ask_toolkits(
|
|
1570
1644
|
*,
|
|
1571
1645
|
model: str,
|
|
1572
1646
|
current_working_directory: str,
|
|
1647
|
+
create_samples_path: str | None = None,
|
|
1573
1648
|
) -> list[Toolkit]:
|
|
1574
1649
|
from meshagent.anthropic.web_fetch import WebFetchTool as AnthropicWebFetchTool
|
|
1575
1650
|
from meshagent.anthropic.web_search import (
|
|
@@ -1578,13 +1653,23 @@ def _build_ask_toolkits(
|
|
|
1578
1653
|
from meshagent.openai.tools.responses_adapter import ApplyPatchTool, WebSearchTool
|
|
1579
1654
|
from meshagent.tools.web_toolkit import WebFetchTool
|
|
1580
1655
|
|
|
1581
|
-
|
|
1582
|
-
|
|
1656
|
+
storage_mounts = [
|
|
1657
|
+
StorageToolLocalMount(
|
|
1658
|
+
path=current_working_directory,
|
|
1659
|
+
local_path=current_working_directory,
|
|
1660
|
+
)
|
|
1661
|
+
]
|
|
1662
|
+
if create_samples_path is not None:
|
|
1663
|
+
storage_mounts.append(
|
|
1583
1664
|
StorageToolLocalMount(
|
|
1584
|
-
path=
|
|
1585
|
-
local_path=
|
|
1665
|
+
path=create_samples_path,
|
|
1666
|
+
local_path=create_samples_path,
|
|
1667
|
+
read_only=True,
|
|
1586
1668
|
)
|
|
1587
|
-
|
|
1669
|
+
)
|
|
1670
|
+
|
|
1671
|
+
storage_toolkit = StorageToolkit(
|
|
1672
|
+
mounts=storage_mounts,
|
|
1588
1673
|
)
|
|
1589
1674
|
toolkits: list[Toolkit] = [storage_toolkit]
|
|
1590
1675
|
|
|
@@ -1604,6 +1689,7 @@ def _build_ask_toolkits(
|
|
|
1604
1689
|
def _build_ask_instructions(
|
|
1605
1690
|
*,
|
|
1606
1691
|
current_working_directory: str,
|
|
1692
|
+
create_samples_path: str | None = None,
|
|
1607
1693
|
interactive: bool = True,
|
|
1608
1694
|
preamble_rule: bool = True,
|
|
1609
1695
|
) -> str:
|
|
@@ -1622,7 +1708,16 @@ def _build_ask_instructions(
|
|
|
1622
1708
|
),
|
|
1623
1709
|
(
|
|
1624
1710
|
"You can also use the meshagent cli to perform tasks. You can get "
|
|
1625
|
-
"help for the sdk and its subcommands with the --help flag."
|
|
1711
|
+
"help for the sdk and its subcommands with the --help flag. "
|
|
1712
|
+
"meshagent create has an interactive mode, and users generally "
|
|
1713
|
+
"want that mode when creating sample projects unless they ask for "
|
|
1714
|
+
"a fully scripted flow."
|
|
1715
|
+
),
|
|
1716
|
+
(
|
|
1717
|
+
"When discussing deployment, assume the user wants to deploy with "
|
|
1718
|
+
"meshagent and its built-in deployment flow. Do not recommend "
|
|
1719
|
+
"third-party deployment services unless the user asks for them or "
|
|
1720
|
+
"the project clearly requires one."
|
|
1626
1721
|
),
|
|
1627
1722
|
(
|
|
1628
1723
|
"The current working directory is "
|
|
@@ -1631,6 +1726,13 @@ def _build_ask_instructions(
|
|
|
1631
1726
|
"so read and write files there using that exact path."
|
|
1632
1727
|
),
|
|
1633
1728
|
]
|
|
1729
|
+
if create_samples_path is not None:
|
|
1730
|
+
sections.append(
|
|
1731
|
+
"The embedded meshagent create sample projects are mounted read-only "
|
|
1732
|
+
f"at {create_samples_path}. Grep and read those examples when "
|
|
1733
|
+
"answering questions about generated project structure, generated "
|
|
1734
|
+
"files, or MeshAgent sample code."
|
|
1735
|
+
)
|
|
1634
1736
|
if not interactive:
|
|
1635
1737
|
sections.append(
|
|
1636
1738
|
"You are not being run interactively. Return useful and actionable "
|
|
@@ -1644,11 +1746,13 @@ def _build_ask_instructions(
|
|
|
1644
1746
|
def _build_ask_turn_instructions_provider(
|
|
1645
1747
|
*,
|
|
1646
1748
|
current_working_directory: str,
|
|
1749
|
+
create_samples_path: str | None = None,
|
|
1647
1750
|
interactive: bool,
|
|
1648
1751
|
preamble_rule: bool = True,
|
|
1649
1752
|
) -> TurnInstructionsProvider:
|
|
1650
1753
|
instructions = _build_ask_instructions(
|
|
1651
1754
|
current_working_directory=current_working_directory,
|
|
1755
|
+
create_samples_path=create_samples_path,
|
|
1652
1756
|
interactive=interactive,
|
|
1653
1757
|
preamble_rule=preamble_rule,
|
|
1654
1758
|
)
|
|
@@ -1682,15 +1786,20 @@ def _is_cancelled_turn_error(error: Exception) -> bool:
|
|
|
1682
1786
|
return isinstance(error, RoomException) and error.code == "cancelled"
|
|
1683
1787
|
|
|
1684
1788
|
|
|
1789
|
+
_ASK_SUPPRESSED_LOGGER_NAMES = ("agent-process", "openai_agent")
|
|
1790
|
+
|
|
1791
|
+
|
|
1685
1792
|
@contextlib.contextmanager
|
|
1686
1793
|
def _suppress_ask_process_logs() -> Any:
|
|
1687
|
-
|
|
1688
|
-
previous_disabled = logger.disabled
|
|
1689
|
-
logger
|
|
1794
|
+
loggers = [logging.getLogger(name) for name in _ASK_SUPPRESSED_LOGGER_NAMES]
|
|
1795
|
+
previous_disabled = {logger: logger.disabled for logger in loggers}
|
|
1796
|
+
for logger in loggers:
|
|
1797
|
+
logger.disabled = True
|
|
1690
1798
|
try:
|
|
1691
1799
|
yield
|
|
1692
1800
|
finally:
|
|
1693
|
-
logger
|
|
1801
|
+
for logger, disabled in previous_disabled.items():
|
|
1802
|
+
logger.disabled = disabled
|
|
1694
1803
|
|
|
1695
1804
|
|
|
1696
1805
|
def _suppress_textual_debug_features() -> None:
|
|
@@ -2048,6 +2157,7 @@ async def _run_ask_tui(
|
|
|
2048
2157
|
self._pending_session_image_message_ids: set[str] = set()
|
|
2049
2158
|
self._external_thread_active = False
|
|
2050
2159
|
self._active_assistant_entry: _AskFeedEntry | None = None
|
|
2160
|
+
self._thread_status_entry_id = "__meshagent_ask_thread_status__"
|
|
2051
2161
|
self._status_text: str | None = None
|
|
2052
2162
|
self._usage_state: _AskUsageState | None = None
|
|
2053
2163
|
self._reasoning_parts: dict[str, list[str]] = {}
|
|
@@ -2772,7 +2882,7 @@ async def _run_ask_tui(
|
|
|
2772
2882
|
return
|
|
2773
2883
|
if isinstance(message, AgentThreadStatus):
|
|
2774
2884
|
self._sync_session_messages()
|
|
2775
|
-
self.
|
|
2885
|
+
self._set_thread_status_text(message)
|
|
2776
2886
|
return
|
|
2777
2887
|
if isinstance(message, AgentTextContentStarted):
|
|
2778
2888
|
await self._prepare_active_assistant_text_item(item_id=message.item_id)
|
|
@@ -3147,6 +3257,38 @@ async def _run_ask_tui(
|
|
|
3147
3257
|
self._render_status_line()
|
|
3148
3258
|
self._render_turn_queue()
|
|
3149
3259
|
|
|
3260
|
+
def _set_thread_status_text(self, status: object) -> None:
|
|
3261
|
+
if isinstance(status, AgentThreadStatus):
|
|
3262
|
+
self._status_text = _format_agent_thread_status_text(status)
|
|
3263
|
+
else:
|
|
3264
|
+
self._status_text = _thread_status_text(status)
|
|
3265
|
+
changed = self._set_thread_status_feed_entry(status)
|
|
3266
|
+
self._render_status_line()
|
|
3267
|
+
self._render_turn_queue()
|
|
3268
|
+
if changed:
|
|
3269
|
+
self._render_feed()
|
|
3270
|
+
self._scroll_to_end()
|
|
3271
|
+
|
|
3272
|
+
def _set_thread_status_feed_entry(self, status: object) -> bool:
|
|
3273
|
+
text = _ask_thread_status_feed_text(status)
|
|
3274
|
+
if text is None:
|
|
3275
|
+
for index, entry in enumerate(self._entries):
|
|
3276
|
+
if entry.message_id != self._thread_status_entry_id:
|
|
3277
|
+
continue
|
|
3278
|
+
del self._entries[index]
|
|
3279
|
+
if index < self._rendered_entry_count:
|
|
3280
|
+
self._reset_rendered_feed()
|
|
3281
|
+
return True
|
|
3282
|
+
return False
|
|
3283
|
+
return self._append_or_replace_feed_entry(
|
|
3284
|
+
_AskFeedEntry(
|
|
3285
|
+
role="event",
|
|
3286
|
+
text=text,
|
|
3287
|
+
pending=True,
|
|
3288
|
+
message_id=self._thread_status_entry_id,
|
|
3289
|
+
)
|
|
3290
|
+
)
|
|
3291
|
+
|
|
3150
3292
|
def _sync_external_thread_state(self) -> None:
|
|
3151
3293
|
session = self._session
|
|
3152
3294
|
if not isinstance(session, _AskExternalThreadState):
|
|
@@ -3167,7 +3309,12 @@ async def _run_ask_tui(
|
|
|
3167
3309
|
self._thread_generation = generation
|
|
3168
3310
|
self._reset_current_thread_feed()
|
|
3169
3311
|
|
|
3170
|
-
|
|
3312
|
+
thread_status = session.thread_status
|
|
3313
|
+
status = (
|
|
3314
|
+
_format_agent_thread_status_text(thread_status)
|
|
3315
|
+
if thread_status is not None
|
|
3316
|
+
else session.thread_status_text
|
|
3317
|
+
)
|
|
3171
3318
|
labels = list(session.queued_message_labels)
|
|
3172
3319
|
active = status is not None and status.strip() != ""
|
|
3173
3320
|
status_changed = active != self._external_thread_active
|
|
@@ -3179,10 +3326,18 @@ async def _run_ask_tui(
|
|
|
3179
3326
|
if status is not None and status.strip() != "":
|
|
3180
3327
|
status_changed = status_changed or status != self._status_text
|
|
3181
3328
|
self._status_text = status
|
|
3329
|
+
if self._set_thread_status_feed_entry(thread_status or status):
|
|
3330
|
+
self._render_feed()
|
|
3331
|
+
self._scroll_to_end()
|
|
3182
3332
|
else:
|
|
3183
3333
|
next_status = status if active else None
|
|
3184
3334
|
status_changed = status_changed or next_status != self._status_text
|
|
3185
3335
|
self._status_text = next_status
|
|
3336
|
+
if self._set_thread_status_feed_entry(
|
|
3337
|
+
thread_status if active else next_status
|
|
3338
|
+
):
|
|
3339
|
+
self._render_feed()
|
|
3340
|
+
self._scroll_to_end()
|
|
3186
3341
|
|
|
3187
3342
|
if status_changed:
|
|
3188
3343
|
self._render_status_line()
|
|
@@ -3718,7 +3873,7 @@ async def _run_ask_tui(
|
|
|
3718
3873
|
interactive=True,
|
|
3719
3874
|
preamble_rule=preamble_rule,
|
|
3720
3875
|
) as created_session:
|
|
3721
|
-
await _run_app(created_session
|
|
3876
|
+
await _run_app(created_session)
|
|
3722
3877
|
|
|
3723
3878
|
|
|
3724
3879
|
@app.async_command("ask", help="Send a one-shot LLM prompt.")
|