fluxloop-cli 0.2.5__py3-none-any.whl → 0.2.7__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.

Potentially problematic release.


This version of fluxloop-cli might be problematic. Click here for more details.

fluxloop_cli/__init__.py CHANGED
@@ -2,7 +2,7 @@
2
2
  FluxLoop CLI - Command-line interface for running agent simulations.
3
3
  """
4
4
 
5
- __version__ = "0.2.5"
5
+ __version__ = "0.2.7"
6
6
 
7
7
  from .main import app
8
8
 
@@ -76,6 +76,7 @@ def load_experiment_config(
76
76
  source_dir = project_root
77
77
 
78
78
  _normalize_variation_strategies(data)
79
+ _normalize_runner_target(data)
79
80
 
80
81
  # Validate and create config object
81
82
  try:
@@ -284,6 +285,27 @@ def _normalize_variation_strategies(payload: Dict[str, Any]) -> None:
284
285
  payload["variation_strategies"] = deduped
285
286
 
286
287
 
288
+ def _normalize_runner_target(payload: Dict[str, Any]) -> None:
289
+ """Populate runner.module_path/function_name when only target is provided."""
290
+
291
+ runner = payload.get("runner")
292
+ if not isinstance(runner, dict):
293
+ return
294
+
295
+ target = runner.get("target")
296
+ module_path = runner.get("module_path")
297
+ function_name = runner.get("function_name")
298
+
299
+ if target and (not module_path or not function_name):
300
+ if ":" in target:
301
+ module_part, attr_part = target.split(":", 1)
302
+ runner.setdefault("module_path", module_part)
303
+ if "." in attr_part:
304
+ # module:Class.method -> record class.method as function placeholder
305
+ runner.setdefault("function_name", attr_part)
306
+ else:
307
+ runner.setdefault("function_name", attr_part)
308
+
287
309
  def _detect_config_context(resolved_path: Path) -> tuple[str, Path, Path]:
288
310
  """Determine whether the path points to legacy or multi-section config."""
289
311
 
@@ -5,7 +5,7 @@ from __future__ import annotations
5
5
  import importlib
6
6
  import sys
7
7
  from pathlib import Path
8
- from typing import Any, Callable, Optional
8
+ from typing import Any, Callable, Optional, List
9
9
 
10
10
  from fluxloop.schemas import RunnerConfig
11
11
 
@@ -21,11 +21,16 @@ class TargetLoader:
21
21
  """Return a callable based on the configured target."""
22
22
 
23
23
  work_dir = self._resolve_working_directory()
24
- remove_path = False
24
+ added_paths: list[str] = []
25
25
 
26
26
  if work_dir and work_dir not in sys.path:
27
27
  sys.path.insert(0, work_dir)
28
- remove_path = True
28
+ added_paths.append(work_dir)
29
+
30
+ for extra in self._resolve_python_paths():
31
+ if extra not in sys.path:
32
+ sys.path.insert(0, extra)
33
+ added_paths.append(extra)
29
34
 
30
35
  try:
31
36
  if self.config.target:
@@ -34,8 +39,9 @@ class TargetLoader:
34
39
  module = importlib.import_module(self.config.module_path)
35
40
  return getattr(module, self.config.function_name)
36
41
  finally:
37
- if remove_path:
38
- sys.path.remove(work_dir)
42
+ for path_entry in added_paths:
43
+ if path_entry in sys.path:
44
+ sys.path.remove(path_entry)
39
45
 
40
46
  def _resolve_working_directory(self) -> str | None:
41
47
  if not self.config.working_directory:
@@ -50,6 +56,22 @@ class TargetLoader:
50
56
  path = raw_path
51
57
  return str(path)
52
58
 
59
+ def _resolve_python_paths(self) -> List[str]:
60
+ resolved: List[str] = []
61
+ entries = getattr(self.config, "python_path", []) or []
62
+
63
+ for entry in entries:
64
+ raw_path = Path(entry)
65
+ if not raw_path.is_absolute():
66
+ base = self.source_dir if self.source_dir else Path.cwd()
67
+ raw_path = (base / raw_path).resolve()
68
+ else:
69
+ raw_path = raw_path.expanduser().resolve()
70
+
71
+ resolved.append(str(raw_path))
72
+
73
+ return resolved
74
+
53
75
  def _load_from_target(self, target: str) -> Callable:
54
76
  """Resolve a callable from target string.
55
77
 
fluxloop_cli/templates.py CHANGED
@@ -108,6 +108,7 @@ def create_simulation_config(project_name: str) -> str:
108
108
  function_name: "run"
109
109
  target: "examples.simple_agent:run"
110
110
  working_directory: .
111
+ python_path: []
111
112
  timeout_seconds: 120
112
113
  max_retries: 3
113
114
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fluxloop-cli
3
- Version: 0.2.5
3
+ Version: 0.2.7
4
4
  Summary: FluxLoop CLI for running agent simulations
5
5
  Author-email: FluxLoop Team <team@fluxloop.dev>
6
6
  License: Apache-2.0
@@ -1,6 +1,6 @@
1
- fluxloop_cli/__init__.py,sha256=vTo0FNr89gD6dt3AL9MCou3IF7daTWQ2Jxi2xN5yXng,142
1
+ fluxloop_cli/__init__.py,sha256=5RtBfYOqQhX75chqufRn6HZkc5JT80RBQyujESfLvPA,142
2
2
  fluxloop_cli/arg_binder.py,sha256=oluHrwe1nNVq7alxBhBEoZrLrYop-cRgXgSu59LJcw4,7827
3
- fluxloop_cli/config_loader.py,sha256=IoOY39KxDWNjSWyN5a8n89ym7jiUDTmy7Id-o4E0Usk,9450
3
+ fluxloop_cli/config_loader.py,sha256=PYy0CfGVbU8jpPbx4sJzOu7i3BbrkQMNaRiSOp_uX9g,10307
4
4
  fluxloop_cli/config_schema.py,sha256=JZJRcMFun5hp3vKLAyek7W3NvISyzRzZt0BZAeSU38I,2415
5
5
  fluxloop_cli/constants.py,sha256=oMYCkUUqy2LORNY99gDRCOkgLOPrT1FY_Vrylo-QSSw,719
6
6
  fluxloop_cli/input_generator.py,sha256=ldlVdPSDfGsP9zO2RALk7QmZjkIvUzTaxDgwOjuPB-0,4043
@@ -8,8 +8,8 @@ fluxloop_cli/llm_generator.py,sha256=SosP5DeZuhBLEM6bj7BDp-7mckvVhtNJMEk2ZgV143M
8
8
  fluxloop_cli/main.py,sha256=xJgrKMv6cN6Q1SNz0rbL4owHsN5CSiLkAaAd747WYds,2584
9
9
  fluxloop_cli/project_paths.py,sha256=FoHp-g3aY1nytxGys85Oy3wJ6gmiKU6FVOwkgTtlHNA,4128
10
10
  fluxloop_cli/runner.py,sha256=dzKv0OZiqBoFfO9LMP5rro9lBL3vkvNmlXqh0U-z9vU,24046
11
- fluxloop_cli/target_loader.py,sha256=TdMBnuD7qkv71C48y5gCaK5sMFyPCoNyOt-JprL0jOI,4734
12
- fluxloop_cli/templates.py,sha256=_QJxAq3JnylGryRjFwLVzaPmYMLsIl5eyVBNfkgGOeA,11207
11
+ fluxloop_cli/target_loader.py,sha256=ACCu2izqGKoOrEiNnAajH0FgLZcw3j1pWn5rAhEuWFU,5528
12
+ fluxloop_cli/templates.py,sha256=5IDUgqFC7Q1wivyDWCCYinNFvpdPnFpH5INLwTPCRZE,11233
13
13
  fluxloop_cli/validators.py,sha256=_bLXmxUSzVrDtLjqyTba0bDqamRIaOUHhV4xZ7K36Xw,1155
14
14
  fluxloop_cli/commands/__init__.py,sha256=sxJX1mJoOSJnH_iIuCqYT8tjh7_yxlJB702j_B_GPUw,164
15
15
  fluxloop_cli/commands/config.py,sha256=xVpBv9D1zCTz3rABl1F1Pm1YMOx6r7B9AICy0-_9kao,11418
@@ -19,8 +19,8 @@ fluxloop_cli/commands/parse.py,sha256=AVPYi59ejFWx4TYyM7JuI69koxDVkIBxy4LBRDMMbF
19
19
  fluxloop_cli/commands/record.py,sha256=56ASu3Np6TX8_F8caMBJArv10ag5M96kJ-sII8df-5Q,4803
20
20
  fluxloop_cli/commands/run.py,sha256=NLkBN2puqDLdHhKhilLriXsZnm7pMDMcoWeBSEXPM-o,9660
21
21
  fluxloop_cli/commands/status.py,sha256=ERZrWoSP3V7dz5A_TEE5b8E0nGwsPggP4nXw4tLOzxE,7841
22
- fluxloop_cli-0.2.5.dist-info/METADATA,sha256=2xwM-V70x7FNcaK4gB2ikjqoul3mVIUj2OKUzl4g7mU,3664
23
- fluxloop_cli-0.2.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
24
- fluxloop_cli-0.2.5.dist-info/entry_points.txt,sha256=NxOEMku4yLMY5kp_Qcd3JcevfXP6A98FsSf9xHcwkyE,51
25
- fluxloop_cli-0.2.5.dist-info/top_level.txt,sha256=ahLkaxzwhmVU4z-YhkmQVzAbW3-wez9cKnwPiDK7uKM,13
26
- fluxloop_cli-0.2.5.dist-info/RECORD,,
22
+ fluxloop_cli-0.2.7.dist-info/METADATA,sha256=Ifx0jS6-3AZxsb3YtDpyk96YOxCacRWcdentqNcW85k,3664
23
+ fluxloop_cli-0.2.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
24
+ fluxloop_cli-0.2.7.dist-info/entry_points.txt,sha256=NxOEMku4yLMY5kp_Qcd3JcevfXP6A98FsSf9xHcwkyE,51
25
+ fluxloop_cli-0.2.7.dist-info/top_level.txt,sha256=ahLkaxzwhmVU4z-YhkmQVzAbW3-wez9cKnwPiDK7uKM,13
26
+ fluxloop_cli-0.2.7.dist-info/RECORD,,