droidrun 0.3.10.dev5__py3-none-any.whl → 0.3.10.dev7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. droidrun/agent/codeact/codeact_agent.py +21 -29
  2. droidrun/agent/context/task_manager.py +0 -1
  3. droidrun/agent/droid/droid_agent.py +1 -3
  4. droidrun/agent/droid/events.py +6 -3
  5. droidrun/agent/executor/executor_agent.py +24 -38
  6. droidrun/agent/executor/prompts.py +0 -108
  7. droidrun/agent/manager/__init__.py +1 -1
  8. droidrun/agent/manager/manager_agent.py +104 -87
  9. droidrun/agent/utils/executer.py +11 -10
  10. droidrun/agent/utils/llm_picker.py +63 -1
  11. droidrun/agent/utils/tools.py +30 -1
  12. droidrun/app_cards/app_card_provider.py +26 -0
  13. droidrun/app_cards/providers/__init__.py +7 -0
  14. droidrun/app_cards/providers/composite_provider.py +97 -0
  15. droidrun/app_cards/providers/local_provider.py +115 -0
  16. droidrun/app_cards/providers/server_provider.py +126 -0
  17. droidrun/cli/logs.py +4 -4
  18. droidrun/cli/main.py +244 -34
  19. droidrun/config_manager/__init__.py +0 -2
  20. droidrun/config_manager/config_manager.py +45 -102
  21. droidrun/config_manager/path_resolver.py +1 -1
  22. droidrun/config_manager/prompt_loader.py +48 -51
  23. droidrun/macro/cli.py +0 -1
  24. droidrun/portal.py +17 -0
  25. droidrun/tools/adb.py +13 -34
  26. {droidrun-0.3.10.dev5.dist-info → droidrun-0.3.10.dev7.dist-info}/METADATA +2 -9
  27. {droidrun-0.3.10.dev5.dist-info → droidrun-0.3.10.dev7.dist-info}/RECORD +30 -26
  28. droidrun/config_manager/app_card_loader.py +0 -148
  29. {droidrun-0.3.10.dev5.dist-info → droidrun-0.3.10.dev7.dist-info}/WHEEL +0 -0
  30. {droidrun-0.3.10.dev5.dist-info → droidrun-0.3.10.dev7.dist-info}/entry_points.txt +0 -0
  31. {droidrun-0.3.10.dev5.dist-info → droidrun-0.3.10.dev7.dist-info}/licenses/LICENSE +0 -0
droidrun/cli/main.py CHANGED
@@ -8,22 +8,22 @@ import os
8
8
  import warnings
9
9
  from contextlib import nullcontext
10
10
  from functools import wraps
11
- from pathlib import Path
12
11
 
13
12
  import click
14
13
  from adbutils import adb
15
14
  from rich.console import Console
16
15
 
17
16
  from droidrun.agent.droid import DroidAgent
18
- from droidrun.agent.utils.llm_picker import load_llm
17
+ from droidrun.agent.utils.llm_picker import load_llm, load_llms_from_profiles
19
18
  from droidrun.cli.logs import LogHandler
19
+ from droidrun.config_manager import ConfigManager
20
20
  from droidrun.config_manager.config_manager import (
21
21
  AgentConfig,
22
22
  CodeActConfig,
23
- ManagerConfig,
24
- ExecutorConfig,
25
23
  DeviceConfig,
24
+ ExecutorConfig,
26
25
  LoggingConfig,
26
+ ManagerConfig,
27
27
  ToolsConfig,
28
28
  TracingConfig,
29
29
  )
@@ -38,8 +38,6 @@ from droidrun.portal import (
38
38
  )
39
39
  from droidrun.telemetry import print_telemetry_message
40
40
  from droidrun.tools import AdbTools, IOSTools
41
- from droidrun.config_manager import ConfigManager
42
-
43
41
 
44
42
  # Suppress all warnings
45
43
  warnings.filterwarnings("ignore")
@@ -240,7 +238,7 @@ async def run_command(
240
238
  if temperature is not None:
241
239
  overrides = {name: {'temperature': temperature} for name in profile_names}
242
240
 
243
- llms = config.load_all_llms(profile_names=profile_names, **overrides)
241
+ llms = load_llms_from_profiles(config.llm_profiles, profile_names=profile_names, **overrides)
244
242
  logger.info(f"🧠 Loaded {len(llms)} agent-specific LLMs from profiles")
245
243
 
246
244
  # ================================================================
@@ -532,29 +530,43 @@ def run(
532
530
  ):
533
531
  """Run a command on your Android device using natural language."""
534
532
 
535
- # Call our standalone function
536
- return run_command(
537
- command,
538
- config,
539
- device,
540
- provider,
541
- model,
542
- steps,
543
- base_url,
544
- api_base,
545
- vision,
546
- manager_vision,
547
- executor_vision,
548
- codeact_vision,
549
- reasoning,
550
- tracing,
551
- debug,
552
- use_tcp,
553
- temperature=temperature,
554
- save_trajectory=save_trajectory,
555
- allow_drag=allow_drag,
556
- ios=ios if ios is not None else False,
557
- )
533
+ try:
534
+ run_command(
535
+ command,
536
+ config,
537
+ device,
538
+ provider,
539
+ model,
540
+ steps,
541
+ base_url,
542
+ api_base,
543
+ vision,
544
+ manager_vision,
545
+ executor_vision,
546
+ codeact_vision,
547
+ reasoning,
548
+ tracing,
549
+ debug,
550
+ use_tcp,
551
+ temperature=temperature,
552
+ save_trajectory=save_trajectory,
553
+ allow_drag=allow_drag,
554
+ ios=ios if ios is not None else False,
555
+ )
556
+ finally:
557
+ # Disable DroidRun keyboard after execution
558
+ try:
559
+ if not (ios if ios is not None else False):
560
+ device_serial = adb.device().serial
561
+ if device_serial:
562
+ tools = AdbTools(serial=device, use_tcp=use_tcp if use_tcp is not None else False)
563
+ if hasattr(tools, 'device') and tools.device:
564
+ tools.device.shell("ime disable com.droidrun.portal/.DroidrunKeyboardIME")
565
+ click.echo("DroidRun keyboard disabled successfully")
566
+ # Cleanup tools
567
+ del tools
568
+ except Exception as disable_e:
569
+ click.echo(f"Warning: Failed to disable DroidRun keyboard: {disable_e}")
558
570
 
559
571
 
560
572
  @cli.command()
@@ -756,8 +768,206 @@ def ping(device: str | None, use_tcp: bool, debug: bool):
756
768
  cli.add_command(macro_cli, name="macro")
757
769
 
758
770
 
771
+ async def test(command: str):
772
+ config = ConfigManager(path="config.yaml")
773
+ # Initialize logging first (use config default if debug not specified)
774
+ debug_mode = debug if debug is not None else config.logging.debug
775
+ log_handler = configure_logging(command, debug_mode, config.logging.rich_text)
776
+ logger = logging.getLogger("droidrun")
777
+
778
+ log_handler.update_step("Initializing...")
779
+
780
+ with log_handler.render():
781
+ try:
782
+ logger.info(f"🚀 Starting: {command}")
783
+ print_telemetry_message()
784
+
785
+ # ================================================================
786
+ # STEP 1: Build config objects with CLI overrides
787
+ # ================================================================
788
+
789
+ # Build agent-specific configs with vision overrides
790
+ if vision is not None:
791
+ # --vision flag overrides all agents
792
+ manager_vision_val = vision
793
+ executor_vision_val = vision
794
+ codeact_vision_val = vision
795
+ logger.debug(f"CLI override: vision={vision} (all agents)")
796
+ else:
797
+ # Use individual overrides or config defaults
798
+ manager_vision_val = config.agent.manager.vision
799
+ executor_vision_val = config.agent.executor.vision
800
+ codeact_vision_val = config.agent.codeact.vision
801
+
802
+ manager_cfg = ManagerConfig(
803
+ vision=manager_vision_val,
804
+ system_prompt="rev1.jinja2"
805
+ )
806
+
807
+ executor_cfg = ExecutorConfig(
808
+ vision=executor_vision_val,
809
+ system_prompt="rev1.jinja2"
810
+ )
811
+
812
+ codeact_cfg = CodeActConfig(
813
+ vision=codeact_vision_val,
814
+ system_prompt=config.agent.codeact.system_prompt,
815
+ user_prompt=config.agent.codeact.user_prompt
816
+ )
817
+
818
+ agent_cfg = AgentConfig(
819
+ max_steps=steps if steps is not None else config.agent.max_steps,
820
+ reasoning=reasoning if reasoning is not None else config.agent.reasoning,
821
+ after_sleep_action=config.agent.after_sleep_action,
822
+ wait_for_stable_ui=config.agent.wait_for_stable_ui,
823
+ prompts_dir=config.agent.prompts_dir,
824
+ manager=manager_cfg,
825
+ executor=executor_cfg,
826
+ codeact=codeact_cfg,
827
+ app_cards=config.agent.app_cards,
828
+ )
829
+
830
+ device_cfg = DeviceConfig(
831
+ serial=device if device is not None else config.device.serial,
832
+ use_tcp=use_tcp if use_tcp is not None else config.device.use_tcp,
833
+ )
834
+
835
+ tools_cfg = ToolsConfig(
836
+ allow_drag=allow_drag if allow_drag is not None else config.tools.allow_drag,
837
+ )
838
+
839
+ logging_cfg = LoggingConfig(
840
+ debug=debug if debug is not None else config.logging.debug,
841
+ save_trajectory=save_trajectory if save_trajectory is not None else config.logging.save_trajectory,
842
+ rich_text=config.logging.rich_text,
843
+ )
844
+
845
+ tracing_cfg = TracingConfig(
846
+ enabled=tracing if tracing is not None else config.tracing.enabled,
847
+ )
848
+
849
+ # ================================================================
850
+ # STEP 3: Load LLMs
851
+ # ================================================================
852
+
853
+ log_handler.update_step("Loading LLMs...")
854
+
855
+ # No custom provider/model - use profiles from config
856
+ logger.info("📋 Loading LLMs from config profiles...")
857
+
858
+ profile_names = ['manager', 'executor', 'codeact', 'text_manipulator', 'app_opener']
859
+
860
+ # Apply temperature override to all profiles if specified
861
+ overrides = {}
862
+ if temperature is not None:
863
+ overrides = {name: {'temperature': temperature} for name in profile_names}
864
+
865
+ llms = load_llms_from_profiles(config.llm_profiles, profile_names=profile_names, **overrides)
866
+ logger.info(f"🧠 Loaded {len(llms)} agent-specific LLMs from profiles")
867
+
868
+ # ================================================================
869
+ # STEP 4: Setup device and tools
870
+ # ================================================================
871
+
872
+ log_handler.update_step("Setting up tools...")
873
+
874
+ device_serial = device_cfg.serial
875
+ if device_serial is None and not ios:
876
+ logger.info("🔍 Finding connected device...")
877
+ devices = adb.list()
878
+ if not devices:
879
+ raise ValueError("No connected devices found.")
880
+ device_serial = devices[0].serial
881
+ device_cfg = DeviceConfig(serial=device_serial, use_tcp=device_cfg.use_tcp)
882
+ logger.info(f"📱 Using device: {device_serial}")
883
+ elif device_serial is None and ios:
884
+ raise ValueError("iOS device not specified. Please specify device base url via --device")
885
+ else:
886
+ logger.info(f"📱 Using device: {device_serial}")
887
+
888
+ tools = (
889
+ AdbTools(
890
+ serial=device_serial,
891
+ use_tcp=device_cfg.use_tcp,
892
+ app_opener_llm=llms.get('app_opener'),
893
+ text_manipulator_llm=llms.get('text_manipulator')
894
+ )
895
+ if not ios
896
+ else IOSTools(url=device_serial)
897
+ )
898
+
899
+ excluded_tools = [] if tools_cfg.allow_drag else ["drag"]
900
+
901
+ # ================================================================
902
+ # STEP 5: Initialize DroidAgent with all settings
903
+ # ================================================================
904
+
905
+ log_handler.update_step("Initializing DroidAgent...")
906
+
907
+ mode = "planning with reasoning" if agent_cfg.reasoning else "direct execution"
908
+ logger.info(f"🤖 Agent mode: {mode}")
909
+ logger.info(f"👁️ Vision settings: Manager={agent_cfg.manager.vision}, "
910
+ f"Executor={agent_cfg.executor.vision}, CodeAct={agent_cfg.codeact.vision}")
911
+
912
+ if tracing_cfg.enabled:
913
+ logger.info("🔍 Tracing enabled")
914
+
915
+ droid_agent = DroidAgent(
916
+ goal=command,
917
+ llms=llms,
918
+ tools=tools,
919
+ config=config,
920
+ agent_config=agent_cfg,
921
+ device_config=device_cfg,
922
+ tools_config=tools_cfg,
923
+ logging_config=logging_cfg,
924
+ tracing_config=tracing_cfg,
925
+ excluded_tools=excluded_tools,
926
+ timeout=1000,
927
+ )
928
+
929
+ # ================================================================
930
+ # STEP 6: Run agent
931
+ # ================================================================
932
+
933
+ logger.info("▶️ Starting agent execution...")
934
+ logger.info("Press Ctrl+C to stop")
935
+ log_handler.update_step("Running agent...")
936
+
937
+ try:
938
+ handler = droid_agent.run()
939
+
940
+ async for event in handler.stream_events():
941
+ log_handler.handle_event(event)
942
+ result = await handler # noqa: F841
943
+
944
+ except KeyboardInterrupt:
945
+ log_handler.is_completed = True
946
+ log_handler.is_success = False
947
+ log_handler.current_step = "Stopped by user"
948
+ logger.info("⏹️ Stopped by user")
949
+
950
+ except Exception as e:
951
+ log_handler.is_completed = True
952
+ log_handler.is_success = False
953
+ log_handler.current_step = f"Error: {e}"
954
+ logger.error(f"💥 Error: {e}")
955
+ if logging_cfg.debug:
956
+ import traceback
957
+ logger.debug(traceback.format_exc())
958
+
959
+ except Exception as e:
960
+ log_handler.current_step = f"Error: {e}"
961
+ logger.error(f"💥 Setup error: {e}")
962
+ debug_mode = debug if debug is not None else config.logging.debug
963
+ if debug_mode:
964
+ import traceback
965
+ logger.debug(traceback.format_exc())
966
+
967
+
968
+
759
969
  if __name__ == "__main__":
760
- command = "Download clash royale app"
970
+ command = "set gboard to the default keyboard"
761
971
  device = None
762
972
  provider = "GoogleGenAI"
763
973
  model = "models/gemini-2.5-flash"
@@ -765,7 +975,7 @@ if __name__ == "__main__":
765
975
  api_key = os.getenv("GOOGLE_API_KEY")
766
976
  steps = 15
767
977
  vision = True
768
- reasoning = True
978
+ reasoning = False
769
979
  tracing = True
770
980
  debug = True
771
981
  use_tcp = False
@@ -774,6 +984,6 @@ if __name__ == "__main__":
774
984
  ios = False
775
985
  save_trajectory = "none"
776
986
  allow_drag = False
777
- run_command(
778
- command
987
+ asyncio.run(
988
+ test(command)
779
989
  )
@@ -1,4 +1,3 @@
1
- from droidrun.config_manager.app_card_loader import AppCardLoader
2
1
  from droidrun.config_manager.config_manager import (
3
2
  AgentConfig,
4
3
  AppCardConfig,
@@ -23,5 +22,4 @@ __all__ = [
23
22
  "TracingConfig",
24
23
  "LoggingConfig",
25
24
  "ToolsConfig",
26
- "AppCardLoader",
27
25
  ]
@@ -3,7 +3,6 @@ from __future__ import annotations
3
3
  import os
4
4
  import threading
5
5
  from dataclasses import asdict, dataclass, field
6
- from pathlib import Path
7
6
  from typing import Any, Callable, Dict, List, Optional
8
7
 
9
8
  import yaml
@@ -35,30 +34,38 @@ agent:
35
34
  # Enable vision capabilities (screenshots)
36
35
  vision: false
37
36
  # System prompt filename (located in prompts_dir/codeact/)
38
- system_prompt: system.md
37
+ system_prompt: system.jinja2
39
38
  # User prompt filename (located in prompts_dir/codeact/)
40
- user_prompt: user.md
39
+ user_prompt: user.jinja2
41
40
 
42
41
  # Manager Agent Configuration
43
42
  manager:
44
43
  # Enable vision capabilities (screenshots)
45
44
  vision: false
46
45
  # System prompt filename (located in prompts_dir/manager/)
47
- system_prompt: system.md
46
+ system_prompt: system.jinja2
48
47
 
49
48
  # Executor Agent Configuration
50
49
  executor:
51
50
  # Enable vision capabilities (screenshots)
52
51
  vision: false
53
52
  # System prompt filename (located in prompts_dir/executor/)
54
- system_prompt: system.md
53
+ system_prompt: system.jinja2
55
54
 
56
55
  # App Cards Configuration
57
56
  app_cards:
58
57
  # Enable app-specific instruction cards
59
58
  enabled: true
60
- # Directory containing app card files
59
+ # Mode: local (file-based), server (HTTP API), or composite (server with local fallback)
60
+ mode: local
61
+ # Directory containing app card files (for local/composite modes)
61
62
  app_cards_dir: config/app_cards
63
+ # Server URL for remote app cards (for server/composite modes)
64
+ server_url: null
65
+ # Server request timeout in seconds
66
+ server_timeout: 2.0
67
+ # Number of server retry attempts
68
+ server_max_retries: 2
62
69
 
63
70
  # === LLM Profiles ===
64
71
  # Define LLM configurations for each agent type
@@ -170,29 +177,33 @@ class LLMProfile:
170
177
  class CodeActConfig:
171
178
  """CodeAct agent configuration."""
172
179
  vision: bool = False
173
- system_prompt: str = "system.md"
174
- user_prompt: str = "user.md"
180
+ system_prompt: str = "system.jinja2"
181
+ user_prompt: str = "user.jinja2"
175
182
 
176
183
 
177
184
  @dataclass
178
185
  class ManagerConfig:
179
186
  """Manager agent configuration."""
180
187
  vision: bool = False
181
- system_prompt: str = "system.md"
188
+ system_prompt: str = "system.jinja2"
182
189
 
183
190
 
184
191
  @dataclass
185
192
  class ExecutorConfig:
186
193
  """Executor agent configuration."""
187
194
  vision: bool = False
188
- system_prompt: str = "system.md"
195
+ system_prompt: str = "system.jinja2"
189
196
 
190
197
 
191
198
  @dataclass
192
199
  class AppCardConfig:
193
200
  """App card configuration."""
194
201
  enabled: bool = True
202
+ mode: str = "local" # local | server | composite
195
203
  app_cards_dir: str = "config/app_cards"
204
+ server_url: Optional[str] = None
205
+ server_timeout: float = 2.0
206
+ server_max_retries: int = 2
196
207
 
197
208
 
198
209
  @dataclass
@@ -210,20 +221,24 @@ class AgentConfig:
210
221
  app_cards: AppCardConfig = field(default_factory=AppCardConfig)
211
222
 
212
223
  def get_codeact_system_prompt_path(self) -> str:
213
- """Get full path to CodeAct system prompt."""
214
- return f"{self.prompts_dir}/codeact/{self.codeact.system_prompt}"
224
+ """Get resolved absolute path to CodeAct system prompt."""
225
+ path = f"{self.prompts_dir}/codeact/{self.codeact.system_prompt}"
226
+ return str(PathResolver.resolve(path, must_exist=True))
215
227
 
216
228
  def get_codeact_user_prompt_path(self) -> str:
217
- """Get full path to CodeAct user prompt."""
218
- return f"{self.prompts_dir}/codeact/{self.codeact.user_prompt}"
229
+ """Get resolved absolute path to CodeAct user prompt."""
230
+ path = f"{self.prompts_dir}/codeact/{self.codeact.user_prompt}"
231
+ return str(PathResolver.resolve(path, must_exist=True))
219
232
 
220
233
  def get_manager_system_prompt_path(self) -> str:
221
- """Get full path to Manager system prompt."""
222
- return f"{self.prompts_dir}/manager/{self.manager.system_prompt}"
234
+ """Get resolved absolute path to Manager system prompt."""
235
+ path = f"{self.prompts_dir}/manager/{self.manager.system_prompt}"
236
+ return str(PathResolver.resolve(path, must_exist=True))
223
237
 
224
238
  def get_executor_system_prompt_path(self) -> str:
225
- """Get full path to Executor system prompt."""
226
- return f"{self.prompts_dir}/executor/{self.executor.system_prompt}"
239
+ """Get resolved absolute path to Executor system prompt."""
240
+ path = f"{self.prompts_dir}/executor/{self.executor.system_prompt}"
241
+ return str(PathResolver.resolve(path, must_exist=True))
227
242
 
228
243
 
229
244
  @dataclass
@@ -372,6 +387,7 @@ class ConfigManager:
372
387
 
373
388
  Usage:
374
389
  from droidrun.config_manager.config_manager import ConfigManager
390
+ from droidrun.agent.utils.llm_picker import load_llms_from_profiles
375
391
 
376
392
  # Create config instance (singleton pattern)
377
393
  config = ConfigManager()
@@ -379,12 +395,19 @@ class ConfigManager:
379
395
  # Access typed config objects
380
396
  print(config.agent.max_steps)
381
397
 
382
- # Load all LLMs
383
- llms = config.load_all_llms()
398
+ # Load all LLMs from profiles
399
+ llms = load_llms_from_profiles(config.llm_profiles)
384
400
  manager_llm = llms['manager']
385
401
  executor_llm = llms['executor']
386
402
  codeact_llm = llms['codeact']
387
403
 
404
+ # Load specific profiles with overrides
405
+ llms = load_llms_from_profiles(
406
+ config.llm_profiles,
407
+ profile_names=['manager', 'executor'],
408
+ manager={'temperature': 0.1}
409
+ )
410
+
388
411
  # Modify and save
389
412
  config.save()
390
413
  """
@@ -494,86 +517,6 @@ class ConfigManager:
494
517
 
495
518
  return self._config.llm_profiles[profile_name]
496
519
 
497
- def load_llm_from_profile(self, profile_name: str, **override_kwargs):
498
- """
499
- Load an LLM using a profile configuration.
500
-
501
- Args:
502
- profile_name: Name of the profile to use (fast, mid, smart, custom)
503
- **override_kwargs: Additional kwargs to override profile settings
504
-
505
- Returns:
506
- Initialized LLM instance
507
-
508
- Example:
509
- # Use specific profile
510
- llm = config.load_llm_from_profile("smart")
511
-
512
- # Override specific settings
513
- llm = config.load_llm_from_profile("fast", temperature=0.5)
514
- """
515
- from droidrun.agent.utils.llm_picker import load_llm
516
-
517
- profile = self.get_llm_profile(profile_name)
518
-
519
- # Get kwargs from profile
520
- kwargs = profile.to_load_llm_kwargs()
521
-
522
- # Override with any provided kwargs
523
- kwargs.update(override_kwargs)
524
-
525
- # Load the LLM
526
- return load_llm(provider_name=profile.provider, **kwargs)
527
-
528
- def load_all_llms(self, profile_names: Optional[list[str]] = None, **override_kwargs_per_profile):
529
- """
530
- Load multiple LLMs from profiles for different use cases.
531
-
532
- Args:
533
- profile_names: List of profile names to load. If None, loads agent-specific profiles
534
- **override_kwargs_per_profile: Dict of profile-specific overrides
535
- Example: manager={'temperature': 0.1}, executor={'max_tokens': 8000}
536
-
537
- Returns:
538
- Dict mapping profile names to initialized LLM instances
539
-
540
- Example:
541
- # Load all agent-specific profiles
542
- llms = config.load_all_llms()
543
- manager_llm = llms['manager']
544
- executor_llm = llms['executor']
545
- codeact_llm = llms['codeact']
546
-
547
- # Load specific profiles
548
- llms = config.load_all_llms(['manager', 'executor'])
549
-
550
- # Load with overrides
551
- llms = config.load_all_llms(
552
- manager={'temperature': 0.1},
553
- executor={'max_tokens': 8000}
554
- )
555
- """
556
- from droidrun.agent.utils.llm_picker import load_llm
557
-
558
- if profile_names is None:
559
- profile_names = ["manager", "executor", "codeact", "text_manipulator", "app_opener"]
560
-
561
- llms = {}
562
- for profile_name in profile_names:
563
- profile = self.get_llm_profile(profile_name)
564
-
565
- # Get kwargs from profile
566
- kwargs = profile.to_load_llm_kwargs()
567
-
568
- # Apply profile-specific overrides if provided
569
- if profile_name in override_kwargs_per_profile:
570
- kwargs.update(override_kwargs_per_profile[profile_name])
571
-
572
- # Load the LLM
573
- llms[profile_name] = load_llm(provider_name=profile.provider, **kwargs)
574
-
575
- return llms
576
-
577
520
  # ---------------- I/O ----------------
578
521
  def _ensure_file_exists(self) -> None:
579
522
  parent = self.path.parent
@@ -653,7 +596,7 @@ class ConfigManager:
653
596
 
654
597
  Example:
655
598
  >>> config.list_available_prompts("manager")
656
- ['system.md', 'experimental.md', 'minimal.md']
599
+ ['system.jinja2', 'experimental.jinja2', 'minimal.jinja2']
657
600
  """
658
601
  agent_type = agent_type.lower()
659
602
  if agent_type not in ["codeact", "manager", "executor"]:
@@ -667,7 +610,7 @@ class ConfigManager:
667
610
  return []
668
611
 
669
612
  # List all .md files in the directory
670
- return sorted([f.name for f in prompts_dir.glob("*.md")])
613
+ return sorted([f.name for f in prompts_dir.glob("*.jinja2")])
671
614
 
672
615
  # useful for tests to reset singleton state
673
616
  @classmethod
@@ -64,7 +64,7 @@ class PathResolver:
64
64
  output_dir = PathResolver.resolve("trajectories", create_if_missing=True)
65
65
 
66
66
  # Loading prompts (must exist, checks both locations)
67
- prompt = PathResolver.resolve("config/prompts/system.md", must_exist=True)
67
+ prompt = PathResolver.resolve("config/prompts/system.jinja2", must_exist=True)
68
68
 
69
69
  # Absolute path (used as-is)
70
70
  abs_path = PathResolver.resolve("/tmp/output")