fluxloop-cli 0.2.13__tar.gz → 0.2.15__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.13 → fluxloop_cli-0.2.15}/PKG-INFO +1 -1
  2. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/fluxloop_cli/__init__.py +1 -1
  3. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/fluxloop_cli/runner.py +66 -3
  4. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/fluxloop_cli.egg-info/PKG-INFO +1 -1
  5. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/pyproject.toml +1 -1
  6. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/README.md +0 -0
  7. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/fluxloop_cli/arg_binder.py +0 -0
  8. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/fluxloop_cli/commands/__init__.py +0 -0
  9. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/fluxloop_cli/commands/config.py +0 -0
  10. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/fluxloop_cli/commands/generate.py +0 -0
  11. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/fluxloop_cli/commands/init.py +0 -0
  12. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/fluxloop_cli/commands/parse.py +0 -0
  13. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/fluxloop_cli/commands/record.py +0 -0
  14. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/fluxloop_cli/commands/run.py +0 -0
  15. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/fluxloop_cli/commands/status.py +0 -0
  16. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/fluxloop_cli/config_loader.py +0 -0
  17. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/fluxloop_cli/config_schema.py +0 -0
  18. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/fluxloop_cli/constants.py +0 -0
  19. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/fluxloop_cli/input_generator.py +0 -0
  20. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/fluxloop_cli/llm_generator.py +0 -0
  21. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/fluxloop_cli/main.py +0 -0
  22. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/fluxloop_cli/project_paths.py +0 -0
  23. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/fluxloop_cli/target_loader.py +0 -0
  24. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/fluxloop_cli/templates.py +0 -0
  25. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/fluxloop_cli/validators.py +0 -0
  26. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/fluxloop_cli.egg-info/SOURCES.txt +0 -0
  27. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/fluxloop_cli.egg-info/dependency_links.txt +0 -0
  28. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/fluxloop_cli.egg-info/entry_points.txt +0 -0
  29. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/fluxloop_cli.egg-info/requires.txt +0 -0
  30. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/fluxloop_cli.egg-info/top_level.txt +0 -0
  31. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/setup.cfg +0 -0
  32. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/tests/test_arg_binder.py +0 -0
  33. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/tests/test_config_command.py +0 -0
  34. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/tests/test_input_generator.py +0 -0
  35. {fluxloop_cli-0.2.13 → fluxloop_cli-0.2.15}/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.13
3
+ Version: 0.2.15
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.13"
5
+ __version__ = "0.2.15"
6
6
 
7
7
  from .main import app
8
8
 
@@ -512,11 +512,15 @@ class ExperimentRunner:
512
512
  """Derive the final output from callbacks or observations."""
513
513
  for observation in reversed(observations):
514
514
  if observation.get("name") == "agent_final_response" and observation.get("output") is not None:
515
- return observation.get("output")
515
+ val = observation.get("output")
516
+ if not ExperimentRunner._looks_like_generator_repr(val):
517
+ return val
516
518
 
517
519
  for observation in reversed(observations):
518
520
  if observation.get("type") == "agent" and observation.get("output") is not None:
519
- return observation.get("output")
521
+ val = observation.get("output")
522
+ if not ExperimentRunner._looks_like_generator_repr(val):
523
+ return val
520
524
 
521
525
  send_messages = callback_messages.get("send") if callback_messages else None
522
526
  if send_messages:
@@ -525,6 +529,13 @@ class ExperimentRunner:
525
529
 
526
530
  return None
527
531
 
532
+ @staticmethod
533
+ def _looks_like_generator_repr(value: Any) -> bool:
534
+ if not isinstance(value, str):
535
+ return False
536
+ s = value.strip().lower()
537
+ return s.startswith("<async_generator ") or s.startswith("<generator ") or " object at 0x" in s
538
+
528
539
  async def _consume_async_gen(self, func: Callable, kwargs: Dict[str, Any]) -> Any:
529
540
  """Consume an async generator function by joining text chunks resolved from events."""
530
541
  gen = func(**kwargs)
@@ -536,7 +547,8 @@ class ExperimentRunner:
536
547
  Uses a copied contextvars context to ensure FluxLoop context is preserved
537
548
  across async iteration boundaries created by upstream frameworks.
538
549
  """
539
- path = (getattr(self.config.runner, "stream_output_path", None) or "message.delta").split(".")
550
+ # Prefer ChatKit-like path by default; configurable via runner.stream_output_path
551
+ path = (getattr(self.config.runner, "stream_output_path", None) or "update.delta").split(".")
540
552
  chunks: List[str] = []
541
553
 
542
554
  ctx = contextvars.copy_context()
@@ -599,7 +611,58 @@ class ExperimentRunner:
599
611
  text_attr = getattr(event, "text", None)
600
612
  if isinstance(text_attr, str) and text_attr:
601
613
  return text_attr
614
+ # Final deep fallback: search common fields recursively
615
+ return ExperimentRunner._deep_extract_text(event)
602
616
 
617
+ @staticmethod
618
+ def _deep_extract_text(obj: Any, *, _depth: int = 0) -> Optional[str]:
619
+ if _depth > 3 or obj is None:
620
+ return None
621
+ if isinstance(obj, str):
622
+ return obj if obj else None
623
+ # dict-like
624
+ if isinstance(obj, dict):
625
+ for key in ("delta", "text"):
626
+ val = obj.get(key)
627
+ if isinstance(val, str) and val:
628
+ return val
629
+ # content as list of parts with text
630
+ content = obj.get("content")
631
+ if isinstance(content, list):
632
+ parts: List[str] = []
633
+ for piece in content:
634
+ txt = ExperimentRunner._deep_extract_text(piece, _depth=_depth + 1)
635
+ if txt:
636
+ parts.append(txt)
637
+ if parts:
638
+ return " ".join(parts)
639
+ # Recurse selected fields
640
+ for key in ("update", "message", "item", "data"):
641
+ val = obj.get(key)
642
+ txt = ExperimentRunner._deep_extract_text(val, _depth=_depth + 1)
643
+ if txt:
644
+ return txt
645
+ return None
646
+ # object with attributes
647
+ for attr in ("delta", "text"):
648
+ val = getattr(obj, attr, None)
649
+ if isinstance(val, str) and val:
650
+ return val
651
+ for attr in ("content",):
652
+ val = getattr(obj, attr, None)
653
+ if isinstance(val, list):
654
+ parts: List[str] = []
655
+ for piece in val:
656
+ txt = ExperimentRunner._deep_extract_text(piece, _depth=_depth + 1)
657
+ if txt:
658
+ parts.append(txt)
659
+ if parts:
660
+ return " ".join(parts)
661
+ for attr in ("update", "message", "item", "data"):
662
+ val = getattr(obj, attr, None)
663
+ txt = ExperimentRunner._deep_extract_text(val, _depth=_depth + 1)
664
+ if txt:
665
+ return txt
603
666
  return None
604
667
 
605
668
  @staticmethod
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fluxloop-cli
3
- Version: 0.2.13
3
+ Version: 0.2.15
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.13"
7
+ version = "0.2.15"
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