minitap-mobile-use 2.4.0__tar.gz → 2.5.1__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.

Potentially problematic release.


This version of minitap-mobile-use might be problematic. Click here for more details.

Files changed (100) hide show
  1. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/PKG-INFO +1 -1
  2. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/config.py +28 -1
  3. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/sdk/builders/agent_config_builder.py +3 -2
  4. minitap_mobile_use-2.5.1/minitap/mobile_use/sdk/examples/platform_manual_task_example.py +65 -0
  5. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/sdk/examples/platform_minimal_example.py +1 -1
  6. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/sdk/services/platform.py +86 -23
  7. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/sdk/types/__init__.py +2 -0
  8. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/sdk/types/platform.py +5 -3
  9. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/sdk/types/task.py +21 -3
  10. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/services/llm.py +3 -3
  11. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/pyproject.toml +1 -1
  12. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/LICENSE +0 -0
  13. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/README.md +0 -0
  14. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/__init__.py +0 -0
  15. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/agents/contextor/contextor.py +0 -0
  16. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/agents/cortex/cortex.md +0 -0
  17. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/agents/cortex/cortex.py +0 -0
  18. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/agents/cortex/types.py +0 -0
  19. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/agents/executor/executor.md +0 -0
  20. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/agents/executor/executor.py +0 -0
  21. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/agents/executor/tool_node.py +0 -0
  22. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/agents/executor/utils.py +0 -0
  23. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/agents/hopper/hopper.md +0 -0
  24. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/agents/hopper/hopper.py +0 -0
  25. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/agents/orchestrator/human.md +0 -0
  26. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/agents/orchestrator/orchestrator.md +0 -0
  27. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/agents/orchestrator/orchestrator.py +0 -0
  28. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/agents/orchestrator/types.py +0 -0
  29. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/agents/outputter/human.md +0 -0
  30. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/agents/outputter/outputter.py +0 -0
  31. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/agents/outputter/test_outputter.py +0 -0
  32. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/agents/planner/human.md +0 -0
  33. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/agents/planner/planner.md +0 -0
  34. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/agents/planner/planner.py +0 -0
  35. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/agents/planner/types.py +0 -0
  36. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/agents/planner/utils.py +0 -0
  37. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/agents/summarizer/summarizer.py +0 -0
  38. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/clients/device_hardware_client.py +0 -0
  39. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/clients/ios_client.py +0 -0
  40. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/clients/screen_api_client.py +0 -0
  41. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/constants.py +0 -0
  42. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/context.py +0 -0
  43. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/controllers/__init__.py +0 -0
  44. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/controllers/mobile_command_controller.py +0 -0
  45. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/controllers/platform_specific_commands_controller.py +0 -0
  46. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/graph/graph.py +0 -0
  47. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/graph/state.py +0 -0
  48. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/main.py +0 -0
  49. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/sdk/__init__.py +0 -0
  50. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/sdk/agent.py +0 -0
  51. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/sdk/builders/__init__.py +0 -0
  52. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/sdk/builders/index.py +0 -0
  53. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/sdk/builders/task_request_builder.py +0 -0
  54. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/sdk/constants.py +0 -0
  55. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/sdk/examples/README.md +0 -0
  56. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/sdk/examples/__init__.py +0 -0
  57. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/sdk/examples/simple_photo_organizer.py +0 -0
  58. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/sdk/examples/smart_notification_assistant.py +0 -0
  59. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/sdk/types/agent.py +0 -0
  60. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/sdk/types/exceptions.py +0 -0
  61. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/sdk/utils.py +0 -0
  62. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/servers/config.py +0 -0
  63. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/servers/device_hardware_bridge.py +0 -0
  64. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/servers/device_screen_api.py +0 -0
  65. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/servers/start_servers.py +0 -0
  66. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/servers/stop_servers.py +0 -0
  67. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/servers/utils.py +0 -0
  68. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/services/accessibility.py +0 -0
  69. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/tools/index.py +0 -0
  70. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/tools/mobile/back.py +0 -0
  71. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/tools/mobile/clear_text.py +0 -0
  72. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/tools/mobile/erase_one_char.py +0 -0
  73. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/tools/mobile/glimpse_screen.py +0 -0
  74. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/tools/mobile/input_text.py +0 -0
  75. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/tools/mobile/launch_app.py +0 -0
  76. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/tools/mobile/long_press_on.py +0 -0
  77. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/tools/mobile/open_link.py +0 -0
  78. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/tools/mobile/press_key.py +0 -0
  79. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/tools/mobile/stop_app.py +0 -0
  80. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/tools/mobile/swipe.py +0 -0
  81. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/tools/mobile/tap.py +0 -0
  82. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/tools/mobile/wait_for_animation_to_end.py +0 -0
  83. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/tools/test_utils.py +0 -0
  84. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/tools/tool_wrapper.py +0 -0
  85. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/tools/types.py +0 -0
  86. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/tools/utils.py +0 -0
  87. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/utils/cli_helpers.py +0 -0
  88. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/utils/cli_selection.py +0 -0
  89. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/utils/conversations.py +0 -0
  90. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/utils/decorators.py +0 -0
  91. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/utils/errors.py +0 -0
  92. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/utils/file.py +0 -0
  93. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/utils/logger.py +0 -0
  94. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/utils/media.py +0 -0
  95. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/utils/recorder.py +0 -0
  96. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/utils/requests_utils.py +0 -0
  97. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/utils/shell_utils.py +0 -0
  98. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/utils/test_ui_hierarchy.py +0 -0
  99. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/utils/time.py +0 -0
  100. {minitap_mobile_use-2.4.0 → minitap_mobile_use-2.5.1}/minitap/mobile_use/utils/ui_hierarchy.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: minitap-mobile-use
3
- Version: 2.4.0
3
+ Version: 2.5.1
4
4
  Summary: AI-powered multi-agent system that automates real Android and iOS devices through low-level control using LangGraph.
5
5
  Author: Pierre-Louis Favreau, Jean-Pierre Lo, Nicolas Dehandschoewercker
6
6
  License: MIT License
@@ -26,7 +26,7 @@ class Settings(BaseSettings):
26
26
  MINITAP_API_KEY: SecretStr | None = None
27
27
 
28
28
  OPENAI_BASE_URL: str | None = None
29
- MINITAP_API_BASE_URL: str = "https://platform.minitap.ai"
29
+ MINITAP_BASE_URL: str = "https://platform.minitap.ai"
30
30
 
31
31
  DEVICE_SCREEN_API_BASE_URL: str | None = None
32
32
  DEVICE_HARDWARE_BRIDGE_BASE_URL: str | None = None
@@ -211,6 +211,33 @@ def get_default_llm_config() -> LLMConfig:
211
211
  )
212
212
 
213
213
 
214
+ def get_default_minitap_llm_config() -> LLMConfig | None:
215
+ """
216
+ Returns a default LLM config using the Minitap provider.
217
+ Only returns a config if MINITAP_API_KEY is available.
218
+
219
+ Returns:
220
+ LLMConfig with minitap provider if API key is available, None otherwise
221
+ """
222
+ if not settings.MINITAP_API_KEY:
223
+ return None
224
+
225
+ return LLMConfig(
226
+ planner=LLM(provider="minitap", model="meta-llama/llama-4-scout"),
227
+ orchestrator=LLM(provider="minitap", model="openai/gpt-oss-120b"),
228
+ cortex=LLMWithFallback(
229
+ provider="minitap",
230
+ model="google/gemini-2.5-pro",
231
+ fallback=LLM(provider="minitap", model="openai/gpt-5"),
232
+ ),
233
+ executor=LLM(provider="minitap", model="meta-llama/llama-3.3-70b-instruct"),
234
+ utils=LLMConfigUtils(
235
+ outputter=LLM(provider="minitap", model="openai/gpt-4.1"),
236
+ hopper=LLM(provider="minitap", model="openai/gpt-5-nano"),
237
+ ),
238
+ )
239
+
240
+
214
241
  def deep_merge_llm_config(default: LLMConfig, override: dict) -> LLMConfig:
215
242
  def _deep_merge_dict(base: dict, extra: dict):
216
243
  for key, value in extra.items():
@@ -6,7 +6,7 @@ import copy
6
6
 
7
7
  from langchain_core.callbacks.base import Callbacks
8
8
 
9
- from minitap.mobile_use.config import get_default_llm_config
9
+ from minitap.mobile_use.config import get_default_llm_config, get_default_minitap_llm_config
10
10
  from minitap.mobile_use.context import DevicePlatform
11
11
  from minitap.mobile_use.sdk.constants import (
12
12
  DEFAULT_HW_BRIDGE_BASE_URL,
@@ -187,9 +187,10 @@ class AgentConfigBuilder:
187
187
  if default_profile.name not in self._agent_profiles:
188
188
  self.add_profile(default_profile)
189
189
  elif nb_profiles <= 0:
190
+ llm_config = get_default_minitap_llm_config() or get_default_llm_config()
190
191
  default_profile = AgentProfile(
191
192
  name=DEFAULT_PROFILE_NAME,
192
- llm_config=get_default_llm_config(),
193
+ llm_config=llm_config,
193
194
  )
194
195
  self.add_profile(default_profile)
195
196
  elif nb_profiles == 1:
@@ -0,0 +1,65 @@
1
+ """
2
+ Platform Usage - Manual Task Creation Example
3
+
4
+ This example demonstrates how to use the mobile-use SDK with manual task creation:
5
+ - Agent with minitap_api_key
6
+ - PlatformTaskRequest with ManualTaskConfig instead of task_id
7
+ - Task configuration provided directly in code (goal, output_description)
8
+ - No need to pre-create task in platform UI
9
+
10
+ Platform Model:
11
+ - API key provides authentication and agent configuration
12
+ - ManualTaskConfig creates task on-the-fly with:
13
+ - max_steps: 400 (fixed)
14
+ - enable_remote_tracing: True (fixed)
15
+ - profile: "default" (fixed)
16
+ - goal: provided by you
17
+ - output_description: provided by you (optional)
18
+
19
+ Run:
20
+ - python src/mobile_use/sdk/examples/platform_manual_task_example.py
21
+ """
22
+
23
+ import asyncio
24
+
25
+ from minitap.mobile_use.sdk import Agent
26
+ from minitap.mobile_use.sdk.types import ManualTaskConfig, PlatformTaskRequest
27
+
28
+
29
+ async def main() -> None:
30
+ """
31
+ Main execution function demonstrating manual task creation pattern.
32
+
33
+ Visit https://platform.minitap.ai to get your API key.
34
+ Set MINITAP_API_KEY and MINITAP_BASE_URL environment variables.
35
+ """
36
+ agent = Agent()
37
+ agent.init()
38
+
39
+ # Example 1: Simple manual task
40
+ result = await agent.run_task(
41
+ request=PlatformTaskRequest(
42
+ task=ManualTaskConfig(
43
+ goal="Open the settings app and tell me the battery level",
44
+ ),
45
+ profile="default", # Optional, defaults to "default"
46
+ )
47
+ )
48
+ print("Result 1:", result)
49
+
50
+ # Example 2: Manual task with output description
51
+ result = await agent.run_task(
52
+ request=PlatformTaskRequest(
53
+ task=ManualTaskConfig(
54
+ goal="Find the first 3 unread emails in Gmail",
55
+ output_description="A JSON array with sender and subject for each email",
56
+ ),
57
+ )
58
+ )
59
+ print("Result 2:", result)
60
+
61
+ agent.clean()
62
+
63
+
64
+ if __name__ == "__main__":
65
+ asyncio.run(main())
@@ -28,7 +28,7 @@ async def main() -> None:
28
28
 
29
29
  Visit https://platform.minitap.ai to create a task, customize your profiles,
30
30
  and get your API key.
31
- Set MINITAP_API_KEY and MINITAP_API_BASE_URL environment variables.
31
+ Set MINITAP_API_KEY and MINITAP_BASE_URL environment variables.
32
32
  """
33
33
  agent = Agent()
34
34
  agent.init()
@@ -23,6 +23,7 @@ from minitap.mobile_use.sdk.types.platform import (
23
23
  )
24
24
  from minitap.mobile_use.sdk.types.task import (
25
25
  AgentProfile,
26
+ ManualTaskConfig,
26
27
  PlatformTaskInfo,
27
28
  PlatformTaskRequest,
28
29
  TaskRequest,
@@ -36,7 +37,7 @@ DEFAULT_PROFILE = "default"
36
37
 
37
38
  class PlatformService:
38
39
  def __init__(self, api_key: str | None = None):
39
- self._base_url = settings.MINITAP_API_BASE_URL
40
+ self._base_url = settings.MINITAP_BASE_URL
40
41
 
41
42
  if api_key:
42
43
  self._api_key = api_key
@@ -59,28 +60,61 @@ class PlatformService:
59
60
 
60
61
  async def create_task_run(self, request: PlatformTaskRequest) -> PlatformTaskInfo:
61
62
  try:
62
- logger.info(f"Getting task: {request.task}")
63
- response = await self._client.get(url=f"v1/tasks/{request.task}")
64
- response.raise_for_status()
65
- task_data = response.json()
66
- task = TaskResponse(**task_data)
67
- profile, agent_profile = await self._get_profile(
68
- profile_name=request.profile or DEFAULT_PROFILE,
69
- )
70
- task_request = TaskRequest(
71
- # Remote configuration
72
- max_steps=task.options.max_steps,
73
- goal=task.input_prompt,
74
- output_description=task.output_description,
75
- enable_remote_tracing=task.options.enable_tracing,
76
- profile=profile.name,
77
- # Local configuration
78
- record_trace=request.record_trace,
79
- trace_path=request.trace_path,
80
- llm_output_path=request.llm_output_path,
81
- thoughts_output_path=request.thoughts_output_path,
82
- )
83
- task_run = await self._create_task_run(task=task, profile=profile)
63
+ # Check if task is a string (fetch from platform) or ManualTaskConfig (create manually)
64
+ if isinstance(request.task, str):
65
+ # Fetch task from platform
66
+ logger.info(f"Getting task: {request.task}")
67
+ response = await self._client.get(url=f"v1/tasks/{request.task}")
68
+ response.raise_for_status()
69
+ task_data = response.json()
70
+ task = TaskResponse(**task_data)
71
+
72
+ profile, agent_profile = await self._get_profile(
73
+ profile_name=request.profile or DEFAULT_PROFILE,
74
+ )
75
+
76
+ task_request = TaskRequest(
77
+ # Remote configuration
78
+ max_steps=task.options.max_steps,
79
+ goal=task.input_prompt,
80
+ output_description=task.output_description,
81
+ enable_remote_tracing=task.options.enable_tracing,
82
+ profile=profile.name,
83
+ # Local configuration
84
+ record_trace=request.record_trace,
85
+ trace_path=request.trace_path,
86
+ llm_output_path=request.llm_output_path,
87
+ thoughts_output_path=request.thoughts_output_path,
88
+ )
89
+
90
+ task_run = await self._create_task_run(task=task, profile=profile)
91
+ else:
92
+ # Create task manually from ManualTaskConfig
93
+ logger.info(f"Creating manual task with goal: {request.task.goal}")
94
+
95
+ profile, agent_profile = await self._get_profile(
96
+ profile_name=request.profile or DEFAULT_PROFILE,
97
+ )
98
+
99
+ task_request = TaskRequest(
100
+ # Manual configuration
101
+ max_steps=400,
102
+ goal=request.task.goal,
103
+ output_description=request.task.output_description,
104
+ enable_remote_tracing=True,
105
+ profile=DEFAULT_PROFILE,
106
+ # Local configuration
107
+ record_trace=request.record_trace,
108
+ trace_path=request.trace_path,
109
+ llm_output_path=request.llm_output_path,
110
+ thoughts_output_path=request.thoughts_output_path,
111
+ )
112
+
113
+ task_run = await self._create_manual_task_run(
114
+ manual_config=request.task,
115
+ profile=profile,
116
+ )
117
+
84
118
  return PlatformTaskInfo(
85
119
  task_request=task_request,
86
120
  llm_profile=agent_profile,
@@ -226,6 +260,35 @@ class PlatformService:
226
260
  except httpx.HTTPStatusError as e:
227
261
  raise PlatformServiceError(message=f"Failed to create task run: {e}")
228
262
 
263
+ async def _create_manual_task_run(
264
+ self,
265
+ manual_config: ManualTaskConfig,
266
+ profile: LLMProfileResponse,
267
+ ) -> TaskRunResponse:
268
+ """
269
+ Create an orphan task run from a manual task configuration.
270
+ This creates a task run without a pre-existing task using the /orphan endpoint.
271
+ """
272
+ try:
273
+ logger.info(f"Creating orphan task run with goal: {manual_config.goal}")
274
+
275
+ # Create an orphan task run directly
276
+ orphan_payload = {
277
+ "inputPrompt": manual_config.goal,
278
+ "outputDescription": manual_config.output_description,
279
+ "llmProfileId": profile.id,
280
+ }
281
+
282
+ response = await self._client.post(url="v1/task-runs/orphan", json=orphan_payload)
283
+ response.raise_for_status()
284
+ task_run_data = response.json()
285
+ return TaskRunResponse(**task_run_data)
286
+
287
+ except ValidationError as e:
288
+ raise PlatformServiceError(message=f"API response validation error: {e}")
289
+ except httpx.HTTPStatusError as e:
290
+ raise PlatformServiceError(message=f"Failed to create orphan task run: {e}")
291
+
229
292
  async def _get_profile(self, profile_name: str) -> tuple[LLMProfileResponse, AgentProfile]:
230
293
  try:
231
294
  logger.info(f"Getting agent profile: {profile_name}")
@@ -19,6 +19,7 @@ from minitap.mobile_use.sdk.types.exceptions import (
19
19
  )
20
20
  from minitap.mobile_use.sdk.types.task import (
21
21
  AgentProfile,
22
+ ManualTaskConfig,
22
23
  PlatformTaskRequest,
23
24
  Task,
24
25
  TaskRequest,
@@ -33,6 +34,7 @@ __all__ = [
33
34
  "AgentProfile",
34
35
  "ServerConfig",
35
36
  "TaskRequest",
37
+ "ManualTaskConfig",
36
38
  "PlatformTaskRequest",
37
39
  "TaskResult",
38
40
  "TaskRequestCommon",
@@ -1,8 +1,8 @@
1
+ from datetime import datetime
1
2
  from typing import Annotated, Any, Literal
3
+
2
4
  from pydantic import BaseModel, ConfigDict, Field, PlainSerializer
3
5
  from pydantic.v1.utils import to_lower_camel
4
- from datetime import datetime
5
-
6
6
 
7
7
  TaskRunStatus = Literal["pending", "running", "completed", "failed", "cancelled"]
8
8
 
@@ -77,7 +77,9 @@ class TaskRunResponse(BaseApiModel):
77
77
  """Response model for a single task run."""
78
78
 
79
79
  id: str = Field(..., description="Unique identifier for the task run")
80
- task: TaskResponse = Field(..., description="ID of the task this run is for")
80
+ task: TaskResponse | None = Field(
81
+ ..., description="ID of the task this run is for or None if manually created"
82
+ )
81
83
  llm_profile: LLMProfileResponse = Field(..., description="LLM profile ID used for this run")
82
84
  status: TaskRunStatus = Field(..., description="Current status of the task run")
83
85
  input_prompt: str = Field(..., description="Input prompt for this task run")
@@ -105,18 +105,32 @@ class TaskRequest[TOutput](TaskRequestCommon):
105
105
  enable_remote_tracing: bool = False
106
106
 
107
107
 
108
+ class ManualTaskConfig(BaseModel):
109
+ """
110
+ Configuration for manually creating a task without fetching from the platform.
111
+
112
+ Attributes:
113
+ goal: Natural language description of the goal to achieve
114
+ output_description: Optional natural language description of expected output format
115
+ """
116
+
117
+ goal: str
118
+ output_description: str | None = None
119
+
120
+
108
121
  class PlatformTaskRequest[TOutput](TaskRequestBase):
109
122
  """
110
123
  Minitap-specific task request for SDK usage via the gateway platform.
111
124
 
112
125
  Attributes:
113
- task: Required task name specified by the user on the platform
126
+ task: Either a task name to fetch from the platform, or a
127
+ ManualTaskConfig to create manually
114
128
  profile: Optional profile name specified by the user on the platform
115
129
  api_key: Optional API key to authenticate with the platform
116
130
  (overrides MINITAP_API_KEY env variable)
117
131
  """
118
132
 
119
- task: str
133
+ task: str | ManualTaskConfig
120
134
  profile: str | None = None
121
135
  api_key: str | None = None
122
136
 
@@ -214,7 +228,11 @@ class Task(BaseModel):
214
228
 
215
229
  def get_name(self) -> str:
216
230
  if isinstance(self.request, PlatformTaskRequest):
217
- return self.request.task
231
+ if isinstance(self.request.task, str):
232
+ return self.request.task
233
+ else:
234
+ # ManualTaskConfig - use first 50 chars of goal
235
+ return f"Manual: {self.request.task.goal[:50]}"
218
236
  return self.request.task_name or self.id
219
237
 
220
238
  async def set_status(
@@ -71,10 +71,10 @@ def get_minitap_llm(
71
71
  else:
72
72
  raise ValueError("MINITAP_API_KEY must be provided or set in environment")
73
73
 
74
- if settings.MINITAP_API_BASE_URL is None:
75
- raise ValueError("MINITAP_API_BASE_URL must be set in environment")
74
+ if settings.MINITAP_BASE_URL is None:
75
+ raise ValueError("MINITAP_BASE_URL must be set in environment")
76
76
 
77
- llm_base_url = f"{settings.MINITAP_API_BASE_URL}/api/v1"
77
+ llm_base_url = f"{settings.MINITAP_BASE_URL}/api/v1"
78
78
 
79
79
  if max_retries is None and model.startswith("google/"):
80
80
  max_retries = 2
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "minitap-mobile-use"
3
- version = "2.4.0"
3
+ version = "2.5.1"
4
4
  description = "AI-powered multi-agent system that automates real Android and iOS devices through low-level control using LangGraph."
5
5
  readme = "README.md"
6
6
  license = { file = "LICENSE" }