fluxloop-cli 0.2.10__py3-none-any.whl → 0.2.11__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.10"
5
+ __version__ = "0.2.11"
6
6
 
7
7
  from .main import app
8
8
 
fluxloop_cli/runner.py CHANGED
@@ -7,6 +7,7 @@ from __future__ import annotations
7
7
  import asyncio
8
8
  import json
9
9
  import inspect
10
+ import os
10
11
  import time
11
12
  from datetime import datetime
12
13
  from pathlib import Path
@@ -39,6 +40,9 @@ class ExperimentRunner:
39
40
  self.config = config
40
41
  self.no_collector = no_collector
41
42
 
43
+ # Apply project environment (.env + inline environment variables)
44
+ self._apply_environment()
45
+
42
46
  # Configure output directories (respect config location for relative paths)
43
47
  output_base = Path(config.output_directory)
44
48
  if not output_base.is_absolute():
@@ -51,6 +55,7 @@ class ExperimentRunner:
51
55
  output_base.mkdir(parents=True, exist_ok=True)
52
56
 
53
57
  offline_dir = output_base / "artifacts"
58
+ offline_dir.mkdir(parents=True, exist_ok=True)
54
59
  fluxloop.configure(
55
60
  use_collector=not no_collector and bool(config.collector_url),
56
61
  collector_url=config.collector_url or None,
@@ -78,6 +83,31 @@ class ExperimentRunner:
78
83
  # Helpers for target loading and argument binding
79
84
  self._arg_binder = ArgBinder(config)
80
85
 
86
+ def _apply_environment(self) -> None:
87
+ """Load environment variables from .env and runner settings."""
88
+
89
+ source_dir = self.config.get_source_dir()
90
+ env_candidates: List[Path] = []
91
+
92
+ if source_dir:
93
+ env_candidates.append(source_dir / ".env")
94
+ parent = source_dir.parent
95
+ if parent != source_dir:
96
+ env_candidates.append(parent / ".env")
97
+
98
+ for candidate in env_candidates:
99
+ if candidate.exists():
100
+ try:
101
+ fluxloop.load_env(candidate, override=True, refresh_config=True)
102
+ except Exception:
103
+ console.log(f"[yellow]Warning:[/yellow] Failed to load environment from {candidate}")
104
+ else:
105
+ break
106
+
107
+ env_vars = getattr(self.config.runner, "environment_vars", {}) or {}
108
+ for key, value in env_vars.items():
109
+ os.environ[key] = str(value)
110
+
81
111
  def _load_agent(self) -> Callable:
82
112
  """Load the agent function from module path."""
83
113
  loader = TargetLoader(self.config.runner, source_dir=self.config.get_source_dir())
@@ -487,6 +517,11 @@ class ExperimentRunner:
487
517
  val = self._get_by_path(item, path)
488
518
  if isinstance(val, str) and val:
489
519
  chunks.append(val)
520
+ continue
521
+
522
+ fallback = self._extract_stream_text(item)
523
+ if fallback:
524
+ chunks.append(fallback)
490
525
  return "".join(chunks) if chunks else None
491
526
 
492
527
  @staticmethod
@@ -501,6 +536,39 @@ class ExperimentRunner:
501
536
  cur = getattr(cur, key, None)
502
537
  return cur
503
538
 
539
+ @staticmethod
540
+ def _extract_stream_text(event: Any) -> Optional[str]:
541
+ """Best-effort extraction of text payloads from streaming events."""
542
+
543
+ update = getattr(event, "update", None)
544
+ if update is not None:
545
+ delta = getattr(update, "delta", None)
546
+ if isinstance(delta, str) and delta:
547
+ return delta
548
+
549
+ content = getattr(update, "content", None)
550
+ text = getattr(content, "text", None) if content is not None else None
551
+ if isinstance(text, str) and text:
552
+ return text
553
+
554
+ item = getattr(event, "item", None)
555
+ if item is not None:
556
+ content = getattr(item, "content", None)
557
+ if isinstance(content, list):
558
+ parts: List[str] = []
559
+ for piece in content:
560
+ text = getattr(piece, "text", None)
561
+ if isinstance(text, str) and text:
562
+ parts.append(text)
563
+ if parts:
564
+ return " ".join(parts)
565
+
566
+ text_attr = getattr(event, "text", None)
567
+ if isinstance(text_attr, str) and text_attr:
568
+ return text_attr
569
+
570
+ return None
571
+
504
572
  @staticmethod
505
573
  def _extract_payload(args: Sequence[Any], kwargs: Dict[str, Any]) -> Any:
506
574
  if kwargs:
@@ -591,9 +659,6 @@ class ExperimentRunner:
591
659
 
592
660
  source_path = self.offline_dir / "observations.jsonl"
593
661
  if not source_path.exists():
594
- console.print(
595
- f"[yellow]⚠️ Observations file not found: {source_path}[/yellow]"
596
- )
597
662
  return
598
663
 
599
664
  destination = self.output_dir / "observations.jsonl"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fluxloop-cli
3
- Version: 0.2.10
3
+ Version: 0.2.11
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,4 +1,4 @@
1
- fluxloop_cli/__init__.py,sha256=8aHKnuCYiKZ2JYjaQTCSmi-M_GUENpy7VUSqG399-9I,143
1
+ fluxloop_cli/__init__.py,sha256=NgsS7Nxhi0nRomvzdHVsIubTKzIZKUykYNcexsVQb1o,143
2
2
  fluxloop_cli/arg_binder.py,sha256=yaK79zRNBEyTO1CB76WLLKQwYBW404HEKeDC2Y1QlLk,9725
3
3
  fluxloop_cli/config_loader.py,sha256=PYy0CfGVbU8jpPbx4sJzOu7i3BbrkQMNaRiSOp_uX9g,10307
4
4
  fluxloop_cli/config_schema.py,sha256=JZJRcMFun5hp3vKLAyek7W3NvISyzRzZt0BZAeSU38I,2415
@@ -7,7 +7,7 @@ fluxloop_cli/input_generator.py,sha256=ldlVdPSDfGsP9zO2RALk7QmZjkIvUzTaxDgwOjuPB
7
7
  fluxloop_cli/llm_generator.py,sha256=SosP5DeZuhBLEM6bj7BDp-7mckvVhtNJMEk2ZgV143M,12894
8
8
  fluxloop_cli/main.py,sha256=xJgrKMv6cN6Q1SNz0rbL4owHsN5CSiLkAaAd747WYds,2584
9
9
  fluxloop_cli/project_paths.py,sha256=FoHp-g3aY1nytxGys85Oy3wJ6gmiKU6FVOwkgTtlHNA,4128
10
- fluxloop_cli/runner.py,sha256=dzKv0OZiqBoFfO9LMP5rro9lBL3vkvNmlXqh0U-z9vU,24046
10
+ fluxloop_cli/runner.py,sha256=cb9e8lhK0NVIhAfhyMejgNVSDHVWwBiYCOIMQGhXqkw,26387
11
11
  fluxloop_cli/target_loader.py,sha256=ACCu2izqGKoOrEiNnAajH0FgLZcw3j1pWn5rAhEuWFU,5528
12
12
  fluxloop_cli/templates.py,sha256=Y7sE_hSm8q2IGXwXDLq-jCEBS_eCUzDPdQSrQELTzWk,11230
13
13
  fluxloop_cli/validators.py,sha256=_bLXmxUSzVrDtLjqyTba0bDqamRIaOUHhV4xZ7K36Xw,1155
@@ -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.10.dist-info/METADATA,sha256=7RmpBYanuT8ROZBYNCaWdrEdXH9lQ5UE85HJoa8beGo,3665
23
- fluxloop_cli-0.2.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
24
- fluxloop_cli-0.2.10.dist-info/entry_points.txt,sha256=NxOEMku4yLMY5kp_Qcd3JcevfXP6A98FsSf9xHcwkyE,51
25
- fluxloop_cli-0.2.10.dist-info/top_level.txt,sha256=ahLkaxzwhmVU4z-YhkmQVzAbW3-wez9cKnwPiDK7uKM,13
26
- fluxloop_cli-0.2.10.dist-info/RECORD,,
22
+ fluxloop_cli-0.2.11.dist-info/METADATA,sha256=RhgDfMz7r9-YfhZRQDmNvqut1k1KHcZqycbBM1tzGkI,3665
23
+ fluxloop_cli-0.2.11.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
24
+ fluxloop_cli-0.2.11.dist-info/entry_points.txt,sha256=NxOEMku4yLMY5kp_Qcd3JcevfXP6A98FsSf9xHcwkyE,51
25
+ fluxloop_cli-0.2.11.dist-info/top_level.txt,sha256=ahLkaxzwhmVU4z-YhkmQVzAbW3-wez9cKnwPiDK7uKM,13
26
+ fluxloop_cli-0.2.11.dist-info/RECORD,,