fluxloop-cli 0.2.12__tar.gz → 0.2.13__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 (35) hide show
  1. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/PKG-INFO +1 -1
  2. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/fluxloop_cli/__init__.py +1 -1
  3. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/fluxloop_cli/runner.py +88 -14
  4. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/fluxloop_cli.egg-info/PKG-INFO +1 -1
  5. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/pyproject.toml +1 -1
  6. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/README.md +0 -0
  7. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/fluxloop_cli/arg_binder.py +0 -0
  8. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/fluxloop_cli/commands/__init__.py +0 -0
  9. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/fluxloop_cli/commands/config.py +0 -0
  10. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/fluxloop_cli/commands/generate.py +0 -0
  11. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/fluxloop_cli/commands/init.py +0 -0
  12. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/fluxloop_cli/commands/parse.py +0 -0
  13. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/fluxloop_cli/commands/record.py +0 -0
  14. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/fluxloop_cli/commands/run.py +0 -0
  15. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/fluxloop_cli/commands/status.py +0 -0
  16. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/fluxloop_cli/config_loader.py +0 -0
  17. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/fluxloop_cli/config_schema.py +0 -0
  18. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/fluxloop_cli/constants.py +0 -0
  19. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/fluxloop_cli/input_generator.py +0 -0
  20. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/fluxloop_cli/llm_generator.py +0 -0
  21. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/fluxloop_cli/main.py +0 -0
  22. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/fluxloop_cli/project_paths.py +0 -0
  23. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/fluxloop_cli/target_loader.py +0 -0
  24. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/fluxloop_cli/templates.py +0 -0
  25. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/fluxloop_cli/validators.py +0 -0
  26. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/fluxloop_cli.egg-info/SOURCES.txt +0 -0
  27. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/fluxloop_cli.egg-info/dependency_links.txt +0 -0
  28. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/fluxloop_cli.egg-info/entry_points.txt +0 -0
  29. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/fluxloop_cli.egg-info/requires.txt +0 -0
  30. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/fluxloop_cli.egg-info/top_level.txt +0 -0
  31. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/setup.cfg +0 -0
  32. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/tests/test_arg_binder.py +0 -0
  33. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/tests/test_config_command.py +0 -0
  34. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/tests/test_input_generator.py +0 -0
  35. {fluxloop_cli-0.2.12 → fluxloop_cli-0.2.13}/tests/test_target_loader.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fluxloop-cli
3
- Version: 0.2.12
3
+ Version: 0.2.13
4
4
  Summary: FluxLoop CLI for running agent simulations
5
5
  Author-email: FluxLoop Team <team@fluxloop.dev>
6
6
  License: Apache-2.0
@@ -2,7 +2,7 @@
2
2
  FluxLoop CLI - Command-line interface for running agent simulations.
3
3
  """
4
4
 
5
- __version__ = "0.2.12"
5
+ __version__ = "0.2.13"
6
6
 
7
7
  from .main import app
8
8
 
@@ -57,8 +57,17 @@ class ExperimentRunner:
57
57
 
58
58
  offline_dir = output_base / "artifacts"
59
59
  offline_dir.mkdir(parents=True, exist_ok=True)
60
+ # Ensure downstream load_env() calls don't re-enable collector unintentionally
61
+ should_use_collector = (not no_collector) and bool(config.collector_url)
62
+ if not should_use_collector:
63
+ os.environ["FLUXLOOP_USE_COLLECTOR"] = "false"
64
+ else:
65
+ os.environ["FLUXLOOP_USE_COLLECTOR"] = "true"
66
+ # Pin offline store dir in env so refresh_config respects our path
67
+ os.environ.setdefault("FLUXLOOP_OFFLINE_DIR", str(offline_dir))
68
+ os.environ.setdefault("FLUXLOOP_OFFLINE_ENABLED", "true")
60
69
  fluxloop.configure(
61
- use_collector=not no_collector and bool(config.collector_url),
70
+ use_collector=should_use_collector,
62
71
  collector_url=config.collector_url or None,
63
72
  api_key=config.collector_api_key,
64
73
  offline_store_enabled=True,
@@ -347,6 +356,11 @@ class ExperimentRunner:
347
356
  final_output = self._extract_final_output(callback_messages, observations)
348
357
  if final_output is not None:
349
358
  result = final_output
359
+ else:
360
+ # As a fallback, coerce async streams or objects into text
361
+ coerced = await self._coerce_result_to_text(result)
362
+ if coerced is not None:
363
+ result = coerced
350
364
 
351
365
  # Mark successful
352
366
  self.results["successful"] += 1
@@ -610,6 +624,33 @@ class ExperimentRunner:
610
624
  "args": list(args),
611
625
  "kwargs": kwargs,
612
626
  }
627
+
628
+ async def _coerce_result_to_text(self, value: Any) -> Optional[str]:
629
+ """Best-effort conversion of agent result into text for summaries.
630
+
631
+ Handles async generators/iterables, known streaming item shapes, and strings.
632
+ """
633
+ import inspect as _inspect
634
+
635
+ if value is None:
636
+ return None
637
+
638
+ if isinstance(value, str):
639
+ return value
640
+
641
+ # Async iterable/generator → consume to text
642
+ if _inspect.isasyncgen(value) or hasattr(value, "__aiter__"):
643
+ try:
644
+ return await self._consume_async_iterable(value)
645
+ except Exception:
646
+ return None
647
+
648
+ # Try extracting text from known event-like objects
649
+ fallback = self._extract_stream_text(value)
650
+ if fallback:
651
+ return fallback
652
+
653
+ return None
613
654
 
614
655
  def _save_results(self) -> None:
615
656
  """Save results to output directory."""
@@ -676,26 +717,59 @@ class ExperimentRunner:
676
717
  if not trace_ids:
677
718
  return
678
719
 
679
- source_path = self.offline_dir / "observations.jsonl"
680
- if not source_path.exists():
720
+ # Gather candidate offline stores
721
+ candidates = []
722
+ try:
723
+ from fluxloop import get_config as _get_sdk_config # type: ignore
724
+ sdk_dir = Path(_get_sdk_config().offline_store_dir)
725
+ candidates.append(sdk_dir / "observations.jsonl")
726
+ except Exception:
727
+ pass
728
+
729
+ candidates.append(self.offline_dir / "observations.jsonl")
730
+ # Legacy fallback removed now that SDK defaults to experiments/artifacts
731
+
732
+ # Unique existing paths in priority order
733
+ seen = set()
734
+ existing: list[Path] = []
735
+ for p in candidates:
736
+ try:
737
+ rp = p.resolve()
738
+ except Exception:
739
+ continue
740
+ if rp in seen:
741
+ continue
742
+ seen.add(rp)
743
+ if rp.exists():
744
+ existing.append(rp)
745
+
746
+ if not existing:
681
747
  return
682
748
 
683
749
  destination = self.output_dir / "observations.jsonl"
684
750
  copied = 0
751
+ seen_lines = set()
685
752
 
686
- with source_path.open("r", encoding="utf-8") as src, destination.open(
687
- "w", encoding="utf-8"
688
- ) as dst:
689
- for line in src:
690
- if not line.strip():
691
- continue
753
+ with destination.open("w", encoding="utf-8") as dst:
754
+ for source_path in existing:
692
755
  try:
693
- record = json.loads(line)
694
- except json.JSONDecodeError:
756
+ with source_path.open("r", encoding="utf-8") as src:
757
+ for line in src:
758
+ if not line.strip():
759
+ continue
760
+ try:
761
+ record = json.loads(line)
762
+ except json.JSONDecodeError:
763
+ continue
764
+ if record.get("trace_id") in trace_ids:
765
+ key = (record.get("id"), record.get("start_time"))
766
+ if key in seen_lines:
767
+ continue
768
+ dst.write(json.dumps(record) + "\n")
769
+ seen_lines.add(key)
770
+ copied += 1
771
+ except OSError:
695
772
  continue
696
- if record.get("trace_id") in trace_ids:
697
- dst.write(json.dumps(record) + "\n")
698
- copied += 1
699
773
 
700
774
  console.print(
701
775
  f"[green]✅ Saved {copied} observations to {destination.name}[/green]"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fluxloop-cli
3
- Version: 0.2.12
3
+ Version: 0.2.13
4
4
  Summary: FluxLoop CLI for running agent simulations
5
5
  Author-email: FluxLoop Team <team@fluxloop.dev>
6
6
  License: Apache-2.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "fluxloop-cli"
7
- version = "0.2.12"
7
+ version = "0.2.13"
8
8
  description = "FluxLoop CLI for running agent simulations"
9
9
  authors = [
10
10
  {name = "FluxLoop Team", email = "team@fluxloop.dev"}
File without changes
File without changes