meshagent-cli 0.45.6__tar.gz → 0.46.0__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.
Files changed (150) hide show
  1. {meshagent_cli-0.45.6/meshagent_cli.egg-info → meshagent_cli-0.46.0}/PKG-INFO +17 -17
  2. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/containers.py +5 -1
  3. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/containers_test.py +58 -6
  4. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/image.py +59 -93
  5. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/image_test.py +37 -89
  6. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/room_services.py +27 -4
  7. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/room_services_test.py +62 -2
  8. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/sessions.py +10 -1
  9. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/sessions_test.py +83 -0
  10. meshagent_cli-0.46.0/meshagent/cli/version.py +1 -0
  11. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0/meshagent_cli.egg-info}/PKG-INFO +17 -17
  12. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent_cli.egg-info/requires.txt +16 -16
  13. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/pyproject.toml +16 -16
  14. meshagent_cli-0.45.6/meshagent/cli/version.py +0 -1
  15. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/LICENSE +0 -0
  16. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/README.md +0 -0
  17. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/__init__.py +0 -0
  18. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/_filedrop.py +0 -0
  19. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/agent.py +0 -0
  20. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/agent_cli_options_test.py +0 -0
  21. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/agent_package_cli.py +0 -0
  22. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/agent_package_cli_test.py +0 -0
  23. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/agents.py +0 -0
  24. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/agents_test.py +0 -0
  25. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/ask.py +0 -0
  26. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/ask_test.py +0 -0
  27. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/async_typer.py +0 -0
  28. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/async_typer_test.py +0 -0
  29. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/auth.py +0 -0
  30. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/auth_async.py +0 -0
  31. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/auth_async_test.py +0 -0
  32. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/auth_test.py +0 -0
  33. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/call.py +0 -0
  34. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/chatbot.py +0 -0
  35. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/cli.py +0 -0
  36. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/cli_mcp.py +0 -0
  37. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/cli_test.py +0 -0
  38. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/common_options.py +0 -0
  39. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/config.py +0 -0
  40. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/config_test.py +0 -0
  41. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/create.py +0 -0
  42. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/create_project_templates/__init__.py +0 -0
  43. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/create_project_templates/python/backend-agent/server.py +0 -0
  44. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/create_project_templates/python/contact-form/server.py +0 -0
  45. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/create_project_templates/python/task-queue-dashboard/server.py +0 -0
  46. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/create_project_templates/python/webserver/server.py +0 -0
  47. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/create_test.py +0 -0
  48. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/dataset.py +0 -0
  49. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/dataset_test.py +0 -0
  50. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/developer.py +0 -0
  51. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/developer_test.py +0 -0
  52. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/doctor.py +0 -0
  53. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/doctor_dockerfiles/__init__.py +0 -0
  54. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/doctor_templates/__init__.py +0 -0
  55. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/doctor_test.py +0 -0
  56. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/feeds.py +0 -0
  57. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/helper.py +0 -0
  58. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/helper_test.py +0 -0
  59. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/helpers.py +0 -0
  60. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/host.py +0 -0
  61. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/iam.py +0 -0
  62. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/iam_test.py +0 -0
  63. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/launch.py +0 -0
  64. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/launch_test.py +0 -0
  65. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/llm.py +0 -0
  66. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/llm_test.py +0 -0
  67. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/local_settings.py +0 -0
  68. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/local_settings_test.py +0 -0
  69. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/mailbot.py +0 -0
  70. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/mailbot_test.py +0 -0
  71. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/mailboxes.py +0 -0
  72. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/meeting_transcriber.py +0 -0
  73. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/memory.py +0 -0
  74. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/memory_test.py +0 -0
  75. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/meshagent_images.py +0 -0
  76. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/meshagent_images_test.py +0 -0
  77. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/messaging.py +0 -0
  78. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/messaging_test.py +0 -0
  79. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/multi.py +0 -0
  80. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/oci_archive.py +0 -0
  81. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/oci_archive_test.py +0 -0
  82. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/participant_token.py +0 -0
  83. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/port.py +0 -0
  84. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/port_test.py +0 -0
  85. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/preamble_rules.py +0 -0
  86. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/preamble_rules_test.py +0 -0
  87. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/process.py +0 -0
  88. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/process_live_test.py +0 -0
  89. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/process_test.py +0 -0
  90. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/projects.py +0 -0
  91. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/projects_test.py +0 -0
  92. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/queue.py +0 -0
  93. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/queue_test.py +0 -0
  94. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/registry.py +0 -0
  95. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/registry_test.py +0 -0
  96. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/room.py +0 -0
  97. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/room_connect.py +0 -0
  98. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/room_connect_test.py +0 -0
  99. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/rooms.py +0 -0
  100. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/rooms_test.py +0 -0
  101. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/root_commands.py +0 -0
  102. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/root_commands_test.py +0 -0
  103. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/routes.py +0 -0
  104. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/scheduled_tasks.py +0 -0
  105. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/scheduled_tasks_test.py +0 -0
  106. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/secrets.py +0 -0
  107. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/secrets_test.py +0 -0
  108. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/service_accounts.py +0 -0
  109. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/service_accounts_test.py +0 -0
  110. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/services.py +0 -0
  111. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/services_test.py +0 -0
  112. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/storage.py +0 -0
  113. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/storage_test.py +0 -0
  114. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/subscriptions.py +0 -0
  115. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/sync.py +0 -0
  116. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/sync_test.py +0 -0
  117. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/task_runner.py +0 -0
  118. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/task_runner_test.py +0 -0
  119. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/test.py +0 -0
  120. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/testing.py +0 -0
  121. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/thread_inspect.py +0 -0
  122. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/thread_inspect_test.py +0 -0
  123. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/thread_sidebar.py +0 -0
  124. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/tool_call_summary.py +0 -0
  125. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/tool_call_summary_test.py +0 -0
  126. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/tool_integrations.py +0 -0
  127. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/tool_integrations_test.py +0 -0
  128. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/tui/__init__.py +0 -0
  129. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/tui/auth_switch.py +0 -0
  130. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/tui/auth_switch_test.py +0 -0
  131. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/tui/create.py +0 -0
  132. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/tui/deploy_room.py +0 -0
  133. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/tui/deploy_room_test.py +0 -0
  134. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/tui/project_activate.py +0 -0
  135. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/tui/project_activate_test.py +0 -0
  136. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/tui/setup.py +0 -0
  137. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/tui/setup_splash_frames.py +0 -0
  138. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/tui/setup_test.py +0 -0
  139. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/version_check.py +0 -0
  140. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/version_check_test.py +0 -0
  141. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/voicebot.py +0 -0
  142. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/webserver.py +0 -0
  143. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/webserver_test.py +0 -0
  144. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/worker.py +0 -0
  145. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent/cli/worker_test.py +0 -0
  146. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent_cli.egg-info/SOURCES.txt +0 -0
  147. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent_cli.egg-info/dependency_links.txt +0 -0
  148. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent_cli.egg-info/entry_points.txt +0 -0
  149. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/meshagent_cli.egg-info/top_level.txt +0 -0
  150. {meshagent_cli-0.45.6 → meshagent_cli-0.46.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshagent-cli
3
- Version: 0.45.6
3
+ Version: 0.46.0
4
4
  Summary: CLI for Meshagent
5
5
  License-Expression: Apache-2.0
6
6
  Project-URL: Documentation, https://docs.meshagent.com
@@ -22,8 +22,8 @@ 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.45.6
26
- Requires-Dist: meshagent-codex==0.45.6
25
+ Requires-Dist: meshagent-llm-proxy==0.46.0
26
+ Requires-Dist: meshagent-codex==0.46.0
27
27
  Requires-Dist: rich~=14.3.0
28
28
  Requires-Dist: sounddevice~=0.5
29
29
  Requires-Dist: textual<9.0,>=8.2.3
@@ -32,23 +32,23 @@ Requires-Dist: prompt-toolkit~=3.0.52
32
32
  Requires-Dist: ascii-magic~=2.3
33
33
  Requires-Dist: pillow~=11.3.0
34
34
  Provides-Extra: all
35
- Requires-Dist: meshagent-agents[all]==0.45.6; extra == "all"
36
- Requires-Dist: meshagent-api[all]==0.45.6; extra == "all"
37
- Requires-Dist: meshagent-commoncrawl==0.45.6; extra == "all"
38
- Requires-Dist: meshagent-scrapy==0.45.6; extra == "all"
39
- Requires-Dist: meshagent-computers==0.45.6; extra == "all"
40
- Requires-Dist: meshagent-openai==0.45.6; extra == "all"
41
- Requires-Dist: meshagent-anthropic==0.45.6; extra == "all"
42
- Requires-Dist: meshagent-otel==0.45.6; extra == "all"
43
- Requires-Dist: meshagent-mcp==0.45.6; extra == "all"
44
- Requires-Dist: meshagent-tools==0.45.6; extra == "all"
35
+ Requires-Dist: meshagent-agents[all]==0.46.0; extra == "all"
36
+ Requires-Dist: meshagent-api[all]==0.46.0; extra == "all"
37
+ Requires-Dist: meshagent-commoncrawl==0.46.0; extra == "all"
38
+ Requires-Dist: meshagent-scrapy==0.46.0; extra == "all"
39
+ Requires-Dist: meshagent-computers==0.46.0; extra == "all"
40
+ Requires-Dist: meshagent-openai==0.46.0; extra == "all"
41
+ Requires-Dist: meshagent-anthropic==0.46.0; extra == "all"
42
+ Requires-Dist: meshagent-otel==0.46.0; extra == "all"
43
+ Requires-Dist: meshagent-mcp==0.46.0; extra == "all"
44
+ Requires-Dist: meshagent-tools==0.46.0; extra == "all"
45
45
  Requires-Dist: supabase-auth~=2.28.0; extra == "all"
46
46
  Requires-Dist: prompt-toolkit~=3.0.52; extra == "all"
47
47
  Provides-Extra: mcp-service
48
- Requires-Dist: meshagent-agents[all]==0.45.6; extra == "mcp-service"
49
- Requires-Dist: meshagent-api==0.45.6; extra == "mcp-service"
50
- Requires-Dist: meshagent-mcp==0.45.6; extra == "mcp-service"
51
- Requires-Dist: meshagent-tools==0.45.6; extra == "mcp-service"
48
+ Requires-Dist: meshagent-agents[all]==0.46.0; extra == "mcp-service"
49
+ Requires-Dist: meshagent-api==0.46.0; extra == "mcp-service"
50
+ Requires-Dist: meshagent-mcp==0.46.0; extra == "mcp-service"
51
+ Requires-Dist: meshagent-tools==0.46.0; extra == "mcp-service"
52
52
  Requires-Dist: supabase-auth~=2.28.0; extra == "mcp-service"
53
53
  Dynamic: license-file
54
54
 
@@ -538,8 +538,12 @@ async def _with_client(
538
538
 
539
539
  connection = await account_client.connect_room(project_id=project_id, room=room)
540
540
 
541
+ room_url = connection.room_url
542
+ if os.getenv("MESHAGENT_ROOM_URL"):
543
+ room_url = websocket_room_url(room_name=room)
544
+
541
545
  proto = WebSocketClientProtocol(
542
- url=websocket_room_url(room_name=room),
546
+ url=room_url,
543
547
  token=connection.jwt,
544
548
  )
545
549
  client_cm = RoomClient(protocol_factory=proto.create_factory())
@@ -525,6 +525,7 @@ async def test_images_inspect_renders_detail_tables(
525
525
  async def test_with_client_uses_configured_websocket_room_url(
526
526
  monkeypatch: pytest.MonkeyPatch,
527
527
  ) -> None:
528
+ monkeypatch.delenv("MESHAGENT_ROOM_URL", raising=False)
528
529
  connection = SimpleNamespace(
529
530
  jwt="jwt-token",
530
531
  room_url="wss://room-router.meshagent.dev/custom/room-endpoint",
@@ -560,11 +561,6 @@ async def test_with_client_uses_configured_websocket_room_url(
560
561
  monkeypatch.setattr(containers, "get_client", _fake_get_client)
561
562
  monkeypatch.setattr(containers, "resolve_project_id", _fake_resolve_project_id)
562
563
  monkeypatch.setattr(containers, "resolve_room", lambda room: f"{room}-resolved")
563
- monkeypatch.setattr(
564
- containers,
565
- "websocket_room_url",
566
- lambda room_name: f"wss://configured-router/{room_name}",
567
- )
568
564
  monkeypatch.setattr(containers, "WebSocketClientProtocol", _FakeProtocol)
569
565
  monkeypatch.setattr(containers, "RoomClient", _FakeRoomClient)
570
566
 
@@ -579,7 +575,63 @@ async def test_with_client_uses_configured_websocket_room_url(
579
575
  ]
580
576
  assert protocol_calls == [
581
577
  {
582
- "url": "wss://configured-router/room-1-resolved",
578
+ "url": "wss://room-router.meshagent.dev/custom/room-endpoint",
579
+ "token": "jwt-token",
580
+ }
581
+ ]
582
+ assert isinstance(client, _FakeRoomClient)
583
+ assert client.enter_calls == 1
584
+
585
+
586
+ @pytest.mark.asyncio
587
+ async def test_with_client_allows_environment_room_url_override(
588
+ monkeypatch: pytest.MonkeyPatch,
589
+ ) -> None:
590
+ monkeypatch.setenv("MESHAGENT_ROOM_URL", "wss://override.meshagent.test")
591
+ connection = SimpleNamespace(
592
+ jwt="jwt-token",
593
+ room_url="wss://room-router.meshagent.dev/custom/room-endpoint",
594
+ )
595
+ account_client = _FakeConnectAccountClient(connection=connection)
596
+ protocol_calls: list[dict[str, str]] = []
597
+
598
+ class _FakeProtocol:
599
+ def __init__(self, *, url: str, token: str) -> None:
600
+ protocol_calls.append({"url": url, "token": token})
601
+
602
+ def create_factory(self):
603
+ return lambda: self
604
+
605
+ class _FakeRoomClient:
606
+ def __init__(self, *, protocol_factory) -> None:
607
+ self.protocol = protocol_factory()
608
+ self.enter_calls = 0
609
+
610
+ async def __aenter__(self) -> "_FakeRoomClient":
611
+ self.enter_calls += 1
612
+ return self
613
+
614
+ async def _fake_get_client() -> _FakeConnectAccountClient:
615
+ return account_client
616
+
617
+ async def _fake_resolve_project_id(*, project_id):
618
+ return project_id
619
+
620
+ monkeypatch.setattr(containers, "get_client", _fake_get_client)
621
+ monkeypatch.setattr(containers, "resolve_project_id", _fake_resolve_project_id)
622
+ monkeypatch.setattr(containers, "resolve_room", lambda room: room)
623
+ monkeypatch.setattr(containers, "WebSocketClientProtocol", _FakeProtocol)
624
+ monkeypatch.setattr(containers, "RoomClient", _FakeRoomClient)
625
+
626
+ returned_account_client, client = await containers._with_client(
627
+ project_id="project-1",
628
+ room="room-1",
629
+ )
630
+
631
+ assert returned_account_client is account_client
632
+ assert protocol_calls == [
633
+ {
634
+ "url": "wss://override.meshagent.test/rooms/room-1",
583
635
  "token": "jwt-token",
584
636
  }
585
637
  ]
@@ -15,14 +15,12 @@ from pathlib import Path, PurePosixPath
15
15
  from typing import Annotated, Literal, Optional, Protocol, TYPE_CHECKING
16
16
  from urllib.parse import urlparse
17
17
 
18
- from aiohttp import ClientTimeout
19
18
  import typer
20
19
  from pydantic import ValidationError
21
20
  from pydantic_yaml import parse_yaml_raw_as
22
21
  from rich import print
23
22
  import yaml
24
23
 
25
- from meshagent.api.http import new_client_session
26
24
  from meshagent.cli import async_typer
27
25
  from meshagent.cli.containers import (
28
26
  _drain_stream_plain,
@@ -70,6 +68,7 @@ from meshagent.api.room_server_client import (
70
68
  LogStream,
71
69
  PublishedBuildImage,
72
70
  RoomException,
71
+ ServicePortRuntimeState,
73
72
  ServiceRuntimeState,
74
73
  )
75
74
  from meshagent.api.room_ports import RESERVED_ROOM_SERVICE_PORTS
@@ -124,13 +123,11 @@ class _DeployDomainPromptHandler(Protocol):
124
123
 
125
124
  app = async_typer.AsyncTyper(help="Pack local directories as OCI images")
126
125
  _BUILD_CONTEXT_CHUNK_SIZE = 1024 * 1024
127
- _BUILD_CREATE_TIMEOUT_SECONDS = 120.0
128
126
  _BUILD_WAIT_TIMEOUT_SECONDS = 600.0
129
127
  _CLIENT_CLOSE_TIMEOUT_SECONDS = 2.0
130
128
  _DEFAULT_CONTEXT_MOUNT_PATH = "/context"
131
129
  _DEFAULT_REPOSITORY_TOKEN_TTL_SECONDS = 3600
132
130
  _DEPLOY_CACHE_CLEANUP_TIMEOUT_SECONDS = 30.0
133
- _DEPLOY_LIVENESS_REQUEST_TIMEOUT_SECONDS = 2.0
134
131
  _DEPLOY_SERVICE_APPLY_TIMEOUT_SECONDS = 60.0
135
132
  _DEPLOY_SERVICE_RESTART_TIMEOUT_SECONDS = 60.0
136
133
  _DEPLOY_WAIT_TIMEOUT_SECONDS = 300.0
@@ -350,7 +347,7 @@ def default_pack_architecture() -> str:
350
347
 
351
348
 
352
349
  def _meshagent_default_image_tag(*, image: str) -> str:
353
- if image == "meshagent/buildkit:default":
350
+ if image in {"meshagent/buildkit:default", "meshagent/playwright:default"}:
354
351
  return __version__
355
352
  return f"{__version__}-nydus"
356
353
 
@@ -3217,37 +3214,6 @@ def _resolve_domain_liveness_path(
3217
3214
  return service_port.liveness
3218
3215
 
3219
3216
 
3220
- def _build_domain_liveness_url(*, domain: str, liveness_path: str) -> str:
3221
- parsed = urlparse(domain if "://" in domain else f"https://{domain}")
3222
- scheme = parsed.scheme or "https"
3223
- netloc = parsed.netloc
3224
- base_path = parsed.path
3225
- if netloc == "":
3226
- netloc = parsed.path
3227
- base_path = ""
3228
- if base_path != "/" and base_path.endswith("/"):
3229
- base_path = base_path.rstrip("/")
3230
- return f"{scheme}://{netloc}{base_path}{liveness_path}"
3231
-
3232
-
3233
- async def _probe_liveness_url(*, url: str) -> bool:
3234
- try:
3235
- async with new_client_session(
3236
- timeout=ClientTimeout(total=_DEPLOY_LIVENESS_REQUEST_TIMEOUT_SECONDS)
3237
- ) as session:
3238
- async with session.get(
3239
- url,
3240
- headers={
3241
- "Accept": "*/*",
3242
- "User-Agent": f"meshagent-cli/{__version__}",
3243
- },
3244
- ) as resp:
3245
- status_code = resp.status
3246
- except Exception:
3247
- return False
3248
- return 200 <= status_code < 400 or status_code in {401, 403}
3249
-
3250
-
3251
3217
  async def _find_room_service_by_name(
3252
3218
  *,
3253
3219
  account_client,
@@ -3581,10 +3547,23 @@ async def _get_service_runtime_state(
3581
3547
  client: RoomClient,
3582
3548
  service_id: str,
3583
3549
  ) -> ServiceRuntimeState | None:
3584
- service_list = await client.services.list_with_state()
3550
+ service_list = await client.services.list()
3585
3551
  return service_list.service_states.get(service_id)
3586
3552
 
3587
3553
 
3554
+ def _find_service_liveness_port(
3555
+ *,
3556
+ state: ServiceRuntimeState,
3557
+ liveness_path: str | None,
3558
+ ) -> ServicePortRuntimeState | None:
3559
+ if liveness_path is None:
3560
+ return None
3561
+ for port in state.status.ports:
3562
+ if port.liveness == liveness_path:
3563
+ return port
3564
+ return None
3565
+
3566
+
3588
3567
  async def _drain_deploy_log_stream_tui(
3589
3568
  stream: LogStream,
3590
3569
  *,
@@ -3700,33 +3679,28 @@ async def _wait_for_deployed_service_live(
3700
3679
  log_handler: Callable[[str], Awaitable[None]] | None = None,
3701
3680
  ) -> None:
3702
3681
  active_logs: _ActiveDeployLogStream | None = None
3703
- liveness_url = (
3704
- _build_domain_liveness_url(domain=domain, liveness_path=liveness_path)
3705
- if domain is not None and liveness_path is not None
3706
- else None
3707
- )
3708
3682
 
3709
3683
  await _emit_deploy_status(
3710
3684
  status_handler,
3711
3685
  rich_message=f"[cyan]Waiting for service to go live:[/] {service_name} ({service_id})",
3712
3686
  plain_message=f"Waiting for service to go live: {service_name} ({service_id})",
3713
3687
  )
3714
- if domain is not None and liveness_url is not None:
3688
+ if liveness_path is not None:
3715
3689
  await _emit_deploy_status(
3716
3690
  status_handler,
3717
- rich_message=f"[cyan]Waiting for liveness URL:[/] {liveness_url}",
3718
- plain_message=f"Waiting for liveness URL: {liveness_url}",
3691
+ rich_message=f"[cyan]Waiting for service liveness:[/] {liveness_path}",
3692
+ plain_message=f"Waiting for service liveness: {liveness_path}",
3719
3693
  )
3720
3694
  elif domain is not None:
3721
3695
  await _emit_deploy_status(
3722
3696
  status_handler,
3723
3697
  rich_message=(
3724
3698
  f"[yellow]Route created for {domain}, but the service has no HTTP "
3725
- "liveness path to probe.[/]"
3699
+ "liveness path to check.[/]"
3726
3700
  ),
3727
3701
  plain_message=(
3728
3702
  f"Route created for {domain}, but the service has no HTTP "
3729
- "liveness path to probe."
3703
+ "liveness path to check."
3730
3704
  ),
3731
3705
  )
3732
3706
 
@@ -3804,7 +3778,7 @@ async def _wait_for_deployed_service_live(
3804
3778
  await asyncio.sleep(_DEPLOY_WAIT_POLL_INTERVAL_SECONDS)
3805
3779
  continue
3806
3780
 
3807
- if liveness_url is None:
3781
+ if liveness_path is None:
3808
3782
  await _emit_deploy_status(
3809
3783
  status_handler,
3810
3784
  rich_message=f"[green]Service is live:[/] {service_name} ({service_id})",
@@ -3812,11 +3786,15 @@ async def _wait_for_deployed_service_live(
3812
3786
  )
3813
3787
  return
3814
3788
 
3815
- if await _probe_liveness_url(url=liveness_url):
3789
+ liveness_port = _find_service_liveness_port(
3790
+ state=state,
3791
+ liveness_path=liveness_path,
3792
+ )
3793
+ if liveness_port is not None and liveness_port.liveness_status == "ready":
3816
3794
  await _emit_deploy_status(
3817
3795
  status_handler,
3818
- rich_message=f"[green]Liveness URL responded:[/] {liveness_url}",
3819
- plain_message=f"Liveness URL responded: {liveness_url}",
3796
+ rich_message=f"[green]Service liveness is ready:[/] {liveness_path}",
3797
+ plain_message=f"Service liveness is ready: {liveness_path}",
3820
3798
  )
3821
3799
  return
3822
3800
 
@@ -3942,26 +3920,20 @@ async def _run_image_pack_stage(
3942
3920
  )
3943
3921
  },
3944
3922
  )
3945
- try:
3946
- build_id = await asyncio.wait_for(
3947
- client.containers.build(
3948
- tags=[parsed_tag.value],
3949
- mount_path=_DEFAULT_CONTEXT_MOUNT_PATH,
3950
- context_path=_DEFAULT_CONTEXT_MOUNT_PATH,
3951
- dockerfile_path=_generated_pack_dockerfile_path(
3952
- mount_path=_DEFAULT_CONTEXT_MOUNT_PATH
3953
- ),
3954
- optimize_image=True,
3955
- private=False,
3956
- credentials=registry_credentials,
3957
- builder_name=_default_builder_name(client=client),
3958
- chunks=_iter_file_chunks(archive_path),
3959
- size=archive_size,
3960
- ),
3961
- timeout=_BUILD_CREATE_TIMEOUT_SECONDS,
3962
- )
3963
- except TimeoutError as exc:
3964
- raise RuntimeError("timed out starting image build") from exc
3923
+ build_id = await client.containers.build(
3924
+ tags=[parsed_tag.value],
3925
+ mount_path=_DEFAULT_CONTEXT_MOUNT_PATH,
3926
+ context_path=_DEFAULT_CONTEXT_MOUNT_PATH,
3927
+ dockerfile_path=_generated_pack_dockerfile_path(
3928
+ mount_path=_DEFAULT_CONTEXT_MOUNT_PATH
3929
+ ),
3930
+ optimize_image=True,
3931
+ private=False,
3932
+ credentials=registry_credentials,
3933
+ builder_name=_default_builder_name(client=client),
3934
+ chunks=_iter_file_chunks(archive_path),
3935
+ size=archive_size,
3936
+ )
3965
3937
  try:
3966
3938
  exit_code = await asyncio.wait_for(
3967
3939
  _stream_build_job_logs_and_wait_for_exit(
@@ -4056,28 +4028,22 @@ async def _run_image_build_stage(
4056
4028
  rich_message=f"[cyan]Uploading build context ({archive_size_text})...[/cyan]",
4057
4029
  plain_message=f"Uploading build context ({archive_size_text})...",
4058
4030
  )
4059
- try:
4060
- build_id = await asyncio.wait_for(
4061
- client.containers.build(
4062
- tags=tags,
4063
- mount_path=build_inputs.pack_spec.mount_path,
4064
- context_path=build_inputs.context_path,
4065
- dockerfile_path=build_inputs.dockerfile_path,
4066
- optimize_image=optimize,
4067
- private=private,
4068
- credentials=credentials,
4069
- builder_name=resolved_builder_name,
4070
- chunks=_iter_file_chunks_with_progress(
4071
- path=archive_path,
4072
- size=archive_size,
4073
- status_handler=status_handler,
4074
- ),
4075
- size=archive_size,
4076
- ),
4077
- timeout=_BUILD_CREATE_TIMEOUT_SECONDS,
4078
- )
4079
- except TimeoutError as exc:
4080
- raise RuntimeError("timed out starting image build") from exc
4031
+ build_id = await client.containers.build(
4032
+ tags=tags,
4033
+ mount_path=build_inputs.pack_spec.mount_path,
4034
+ context_path=build_inputs.context_path,
4035
+ dockerfile_path=build_inputs.dockerfile_path,
4036
+ optimize_image=optimize,
4037
+ private=private,
4038
+ credentials=credentials,
4039
+ builder_name=resolved_builder_name,
4040
+ chunks=_iter_file_chunks_with_progress(
4041
+ path=archive_path,
4042
+ size=archive_size,
4043
+ status_handler=status_handler,
4044
+ ),
4045
+ size=archive_size,
4046
+ )
4081
4047
  await _emit_deploy_status(
4082
4048
  status_handler,
4083
4049
  rich_message="[cyan]Starting image build...[/cyan]",
@@ -38,6 +38,8 @@ from meshagent.cli import cli, image
38
38
  from meshagent.api.room_server_client import (
39
39
  PublishedBuildImage,
40
40
  RoomException,
41
+ ServicePortRuntimeState,
42
+ ServiceRuntimeStatus,
41
43
  ServiceRuntimeState,
42
44
  )
43
45
  from meshagent.api.specs.service import (
@@ -787,9 +789,13 @@ def test_replace_meshagent_image_vars_uses_dev_prefix(monkeypatch) -> None:
787
789
  "us-central1-docker.pkg.dev/meshagent-life/meshagent-public/"
788
790
  f"buildkit:{image.__version__}"
789
791
  )
792
+ assert image.replace_meshagent_image_vars("meshagent/playwright:default") == (
793
+ "us-central1-docker.pkg.dev/meshagent-life/meshagent-public/"
794
+ f"playwright:{image.__version__}"
795
+ )
790
796
 
791
797
 
792
- def test_replace_meshagent_image_vars_uses_nydus_for_non_buildkit_defaults(
798
+ def test_replace_meshagent_image_vars_uses_nydus_for_non_exception_defaults(
793
799
  monkeypatch,
794
800
  ) -> None:
795
801
  monkeypatch.setattr(
@@ -2270,7 +2276,7 @@ def test_parse_meshagent_token_scope_supports_presets_and_json() -> None:
2270
2276
  user_default = image._parse_meshagent_token_scope(value="userDefault")
2271
2277
  custom = image._parse_meshagent_token_scope(value='{"queues":{"send":["jobs"]}}')
2272
2278
 
2273
- assert user_default.secrets is not None
2279
+ assert user_default.secrets is None
2274
2280
  assert user_default.admin is None
2275
2281
  assert custom.queues is not None
2276
2282
  assert custom.queues.send == ["jobs"]
@@ -2331,71 +2337,7 @@ async def test_validate_deploy_environment_secrets_requires_run_as() -> None:
2331
2337
 
2332
2338
 
2333
2339
  @pytest.mark.asyncio
2334
- @pytest.mark.parametrize("status_code", [200, 302, 401, 403])
2335
- async def test_probe_liveness_url_accepts_reachable_statuses(
2336
- monkeypatch: pytest.MonkeyPatch,
2337
- status_code: int,
2338
- ) -> None:
2339
- class _FakeResponse:
2340
- status = status_code
2341
-
2342
- async def __aenter__(self):
2343
- return self
2344
-
2345
- async def __aexit__(self, exc_type, exc, tb) -> None:
2346
- del exc_type, exc, tb
2347
-
2348
- class _FakeSession:
2349
- async def __aenter__(self):
2350
- return self
2351
-
2352
- async def __aexit__(self, exc_type, exc, tb) -> None:
2353
- del exc_type, exc, tb
2354
-
2355
- def get(self, *args, **kwargs):
2356
- del args, kwargs
2357
- return _FakeResponse()
2358
-
2359
- monkeypatch.setattr(
2360
- image, "new_client_session", lambda *args, **kwargs: _FakeSession()
2361
- )
2362
-
2363
- assert await image._probe_liveness_url(url="https://sheets.meshagent.dev/") is True
2364
-
2365
-
2366
- @pytest.mark.asyncio
2367
- async def test_probe_liveness_url_rejects_server_errors(
2368
- monkeypatch: pytest.MonkeyPatch,
2369
- ) -> None:
2370
- class _FakeResponse:
2371
- status = 502
2372
-
2373
- async def __aenter__(self):
2374
- return self
2375
-
2376
- async def __aexit__(self, exc_type, exc, tb) -> None:
2377
- del exc_type, exc, tb
2378
-
2379
- class _FakeSession:
2380
- async def __aenter__(self):
2381
- return self
2382
-
2383
- async def __aexit__(self, exc_type, exc, tb) -> None:
2384
- del exc_type, exc, tb
2385
-
2386
- def get(self, *args, **kwargs):
2387
- del args, kwargs
2388
- return _FakeResponse()
2389
-
2390
- monkeypatch.setattr(
2391
- image, "new_client_session", lambda *args, **kwargs: _FakeSession()
2392
- )
2393
-
2394
- assert await image._probe_liveness_url(url="https://sheets.meshagent.dev/") is False
2395
-
2396
-
2397
- @pytest.mark.asyncio
2398
- async def test_wait_for_deployed_service_live_streams_logs_and_checks_liveness(
2340
+ async def test_wait_for_deployed_service_live_streams_logs_and_checks_service_liveness(
2399
2341
  monkeypatch: pytest.MonkeyPatch,
2400
2342
  _stub_deploy_wait: dict[str, object],
2401
2343
  ) -> None:
@@ -2403,7 +2345,6 @@ async def test_wait_for_deployed_service_live_streams_logs_and_checks_liveness(
2403
2345
  "prints": [],
2404
2346
  "started_logs": [],
2405
2347
  "stopped_logs": [],
2406
- "probe_urls": [],
2407
2348
  }
2408
2349
  states = [
2409
2350
  ServiceRuntimeState(service_id="service-1", state="starting"),
@@ -2416,11 +2357,29 @@ async def test_wait_for_deployed_service_live_streams_logs_and_checks_liveness(
2416
2357
  service_id="service-1",
2417
2358
  state="running",
2418
2359
  container_id="container-1",
2360
+ status=ServiceRuntimeStatus(
2361
+ ports=[
2362
+ ServicePortRuntimeState(
2363
+ num=8000,
2364
+ liveness="/ready",
2365
+ liveness_status="not_ready",
2366
+ )
2367
+ ]
2368
+ ),
2419
2369
  ),
2420
2370
  ServiceRuntimeState(
2421
2371
  service_id="service-1",
2422
2372
  state="running",
2423
2373
  container_id="container-1",
2374
+ status=ServiceRuntimeStatus(
2375
+ ports=[
2376
+ ServicePortRuntimeState(
2377
+ num=8000,
2378
+ liveness="/ready",
2379
+ liveness_status="ready",
2380
+ )
2381
+ ]
2382
+ ),
2424
2383
  ),
2425
2384
  ]
2426
2385
  fake_active_logs = SimpleNamespace(container_id="container-1")
@@ -2430,7 +2389,7 @@ async def test_wait_for_deployed_service_live_streams_logs_and_checks_liveness(
2430
2389
  self._runtime_states = runtime_states
2431
2390
  self._index = 0
2432
2391
 
2433
- async def list_with_state(self):
2392
+ async def list(self):
2434
2393
  state = self._runtime_states[
2435
2394
  min(self._index, len(self._runtime_states) - 1)
2436
2395
  ]
@@ -2450,19 +2409,12 @@ async def test_wait_for_deployed_service_live_streams_logs_and_checks_liveness(
2450
2409
  async def _fake_stop_deploy_log_stream(*, active_logs) -> None:
2451
2410
  captured["stopped_logs"].append(active_logs)
2452
2411
 
2453
- probe_results = iter([False, True])
2454
-
2455
- async def _fake_probe_liveness_url(*, url: str) -> bool:
2456
- captured["probe_urls"].append(url)
2457
- return next(probe_results)
2458
-
2459
2412
  monkeypatch.setattr(image.asyncio, "to_thread", _fake_to_thread)
2460
2413
  monkeypatch.setattr(image, "_DEPLOY_WAIT_POLL_INTERVAL_SECONDS", 0)
2461
2414
  monkeypatch.setattr(
2462
2415
  image, "_start_deploy_log_stream", _fake_start_deploy_log_stream
2463
2416
  )
2464
2417
  monkeypatch.setattr(image, "_stop_deploy_log_stream", _fake_stop_deploy_log_stream)
2465
- monkeypatch.setattr(image, "_probe_liveness_url", _fake_probe_liveness_url)
2466
2418
  monkeypatch.setattr(
2467
2419
  image,
2468
2420
  "print",
@@ -2483,11 +2435,7 @@ async def test_wait_for_deployed_service_live_streams_logs_and_checks_liveness(
2483
2435
 
2484
2436
  assert captured["started_logs"] == ["container-1"]
2485
2437
  assert captured["stopped_logs"] == [fake_active_logs]
2486
- assert captured["probe_urls"] == [
2487
- "https://app.meshagent.app/ready",
2488
- "https://app.meshagent.app/ready",
2489
- ]
2490
- assert any("Liveness URL responded" in message for message in captured["prints"])
2438
+ assert any("Service liveness is ready" in message for message in captured["prints"])
2491
2439
 
2492
2440
 
2493
2441
  @pytest.mark.asyncio
@@ -2521,7 +2469,7 @@ async def test_wait_for_deployed_service_live_exits_when_container_restarts(
2521
2469
  self._runtime_states = runtime_states
2522
2470
  self._index = 0
2523
2471
 
2524
- async def list_with_state(self):
2472
+ async def list(self):
2525
2473
  state = self._runtime_states[
2526
2474
  min(self._index, len(self._runtime_states) - 1)
2527
2475
  ]
@@ -2828,7 +2776,7 @@ async def test_deploy_image_creates_room_service_with_mounts_env_secret_and_toke
2828
2776
  async def restart(self, *, service_id: str) -> None:
2829
2777
  captured["restarted_service_id"] = service_id
2830
2778
 
2831
- async def list_with_state(self):
2779
+ async def list(self):
2832
2780
  return SimpleNamespace(
2833
2781
  service_states={
2834
2782
  "service-1": ServiceRuntimeState(
@@ -4940,7 +4888,7 @@ async def test_deploy_image_updates_existing_service_route_and_replaces_environm
4940
4888
  async def restart(self, *, service_id: str) -> None:
4941
4889
  captured["restarted_service_id"] = service_id
4942
4890
 
4943
- async def list_with_state(self):
4891
+ async def list(self):
4944
4892
  return SimpleNamespace(
4945
4893
  service_states={
4946
4894
  "service-1": ServiceRuntimeState(
@@ -5044,7 +4992,7 @@ async def test_deploy_image_updates_existing_service_route_and_replaces_environm
5044
4992
  assert env_by_name["MESHAGENT_TOKEN"].token.role == "agent"
5045
4993
  assert env_by_name["MESHAGENT_TOKEN"].token.api is not None
5046
4994
  assert env_by_name["MESHAGENT_TOKEN"].token.api.admin is not None
5047
- assert env_by_name["MESHAGENT_TOKEN"].token.api.secrets is not None
4995
+ assert env_by_name["MESHAGENT_TOKEN"].token.api.secrets is None
5048
4996
  assert env_by_name["MESHAGENT_TOKEN"].token.api.tunnels is not None
5049
4997
  for env_name in ("OPENAI_API_KEY", "ANTHROPIC_API_KEY"):
5050
4998
  assert env_by_name[env_name].token is not None
@@ -5094,7 +5042,7 @@ async def test_deploy_image_sets_cookie_validation_on_private_published_ports(
5094
5042
  async def restart(self, *, service_id: str) -> None:
5095
5043
  captured["restarted_service_id"] = service_id
5096
5044
 
5097
- async def list_with_state(self):
5045
+ async def list(self):
5098
5046
  return SimpleNamespace(
5099
5047
  service_states={
5100
5048
  "service-1": ServiceRuntimeState(
@@ -5219,7 +5167,7 @@ async def test_deploy_image_preserves_existing_liveness_when_default_is_used(
5219
5167
  async def restart(self, *, service_id: str) -> None:
5220
5168
  captured["restarted_service_id"] = service_id
5221
5169
 
5222
- async def list_with_state(self):
5170
+ async def list(self):
5223
5171
  return SimpleNamespace(
5224
5172
  service_states={
5225
5173
  "service-1": ServiceRuntimeState(
@@ -5321,7 +5269,7 @@ async def test_deploy_image_liveness_flag_overrides_http_ports_only(
5321
5269
  async def restart(self, *, service_id: str) -> None:
5322
5270
  captured["restarted_service_id"] = service_id
5323
5271
 
5324
- async def list_with_state(self):
5272
+ async def list(self):
5325
5273
  return SimpleNamespace(
5326
5274
  service_states={
5327
5275
  "service-1": ServiceRuntimeState(
@@ -5413,7 +5361,7 @@ async def test_deploy_image_domain_requires_exactly_one_published_port(
5413
5361
  )
5414
5362
 
5415
5363
  class _FakeServices:
5416
- async def list_with_state(self):
5364
+ async def list(self):
5417
5365
  return SimpleNamespace(
5418
5366
  service_states={
5419
5367
  "service-1": ServiceRuntimeState(