fluxloop-cli 0.2.1__py3-none-any.whl → 0.2.2__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.1"
5
+ __version__ = "0.2.2"
6
6
 
7
7
  from .main import app
8
8
 
@@ -22,7 +22,7 @@ from .constants import CONFIG_DIRECTORY_NAME
22
22
  # Add shared schemas to path
23
23
  sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent / "shared"))
24
24
 
25
- from fluxloop.schemas import ExperimentConfig
25
+ from fluxloop.schemas import ExperimentConfig, VariationStrategy
26
26
 
27
27
 
28
28
  def load_experiment_config(
@@ -75,6 +75,8 @@ def load_experiment_config(
75
75
  data = merged
76
76
  source_dir = project_root
77
77
 
78
+ _normalize_variation_strategies(data)
79
+
78
80
  # Validate and create config object
79
81
  try:
80
82
  config = ExperimentConfig(**data)
@@ -222,6 +224,42 @@ def _deep_merge(target: Dict[str, Any], incoming: Dict[str, Any]) -> Dict[str, A
222
224
  return target
223
225
 
224
226
 
227
+ def _normalize_variation_strategies(payload: Dict[str, Any]) -> None:
228
+ """Ensure variation strategies are represented as enum-compatible strings."""
229
+
230
+ strategies = payload.get("variation_strategies")
231
+ if not isinstance(strategies, list):
232
+ return
233
+
234
+ normalized = []
235
+ for entry in strategies:
236
+ if isinstance(entry, VariationStrategy):
237
+ normalized.append(entry.value)
238
+ continue
239
+
240
+ candidate: Optional[str]
241
+ if isinstance(entry, str):
242
+ candidate = entry
243
+ elif isinstance(entry, dict):
244
+ candidate = (
245
+ entry.get("type")
246
+ or entry.get("name")
247
+ or entry.get("strategy")
248
+ or entry.get("value")
249
+ )
250
+ else:
251
+ candidate = str(entry)
252
+
253
+ if not candidate:
254
+ continue
255
+
256
+ normalized.append(
257
+ candidate.strip().lower().replace(" ", "_").replace("-", "_")
258
+ )
259
+
260
+ payload["variation_strategies"] = normalized
261
+
262
+
225
263
  def _detect_config_context(resolved_path: Path) -> tuple[str, Path, Path]:
226
264
  """Determine whether the path points to legacy or multi-section config."""
227
265
 
@@ -88,40 +88,27 @@ class GenerationError(Exception):
88
88
  def generate_inputs(
89
89
  config: ExperimentConfig,
90
90
  settings: GenerationSettings,
91
- recording_template: Optional[Dict[str, Any]] = None,
92
91
  ) -> GenerationResult:
93
92
  """Generate deterministic input entries based on configuration."""
94
93
  base_inputs = config.base_inputs
95
- config_for_generation = config
96
- if recording_template:
97
- base_inputs = [
98
- {
99
- "input": recording_template["base_content"],
100
- "metadata": {
101
- "source": "recording",
102
- "target": recording_template.get("target"),
103
- },
104
- }
105
- ]
106
- config_for_generation = config.model_copy(update={"base_inputs": base_inputs})
107
94
 
108
95
  if not base_inputs:
109
96
  raise GenerationError("base_inputs must be defined to generate inputs")
110
97
 
111
- mode = settings.mode or config_for_generation.input_generation.mode
98
+ mode = settings.mode or config.input_generation.mode
112
99
 
113
100
  if mode == InputGenerationMode.LLM:
114
101
  strategies: Sequence[VariationStrategy]
115
102
  if settings.strategies and len(settings.strategies) > 0:
116
103
  strategies = list(settings.strategies)
117
- elif config_for_generation.variation_strategies:
118
- strategies = config_for_generation.variation_strategies
104
+ elif config.variation_strategies:
105
+ strategies = config.variation_strategies
119
106
  else:
120
107
  strategies = DEFAULT_STRATEGIES
121
108
 
122
109
  try:
123
110
  raw_entries = generate_llm_inputs(
124
- config=config_for_generation,
111
+ config=config,
125
112
  strategies=strategies,
126
113
  settings=settings,
127
114
  )
@@ -134,23 +121,16 @@ def generate_inputs(
134
121
  ]
135
122
 
136
123
  metadata = {
137
- "config_name": config_for_generation.name,
124
+ "config_name": config.name,
138
125
  "total_base_inputs": len(base_inputs),
139
- "total_personas": len(config_for_generation.personas),
126
+ "total_personas": len(config.personas),
140
127
  "strategies": [strategy.value for strategy in strategies],
141
128
  "limit": settings.limit,
142
129
  "generation_mode": InputGenerationMode.LLM.value,
143
- "llm_provider": config_for_generation.input_generation.llm.provider,
144
- "llm_model": config_for_generation.input_generation.llm.model,
130
+ "llm_provider": config.input_generation.llm.provider,
131
+ "llm_model": config.input_generation.llm.model,
145
132
  }
146
133
 
147
- if recording_template:
148
- for entry in entries:
149
- entry.metadata["args_template"] = "use_recorded"
150
- entry.metadata["template_kwargs"] = recording_template.get("full_kwargs")
151
- metadata["recording_target"] = recording_template.get("target")
152
- metadata["recording_base_input"] = recording_template.get("base_content")
153
-
154
134
  return GenerationResult(entries=entries, metadata=metadata)
155
135
 
156
136
  raise GenerationError(
fluxloop_cli/templates.py CHANGED
@@ -69,9 +69,9 @@ def create_input_config() -> str:
69
69
  expected_intent: demo
70
70
 
71
71
  variation_strategies:
72
- - type: rephrase
73
- - type: verbose
74
- - type: error_prone
72
+ - rephrase
73
+ - verbose
74
+ - error_prone
75
75
 
76
76
  variation_count: 2
77
77
  variation_temperature: 0.7
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fluxloop-cli
3
- Version: 0.2.1
3
+ Version: 0.2.2
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,15 +1,15 @@
1
- fluxloop_cli/__init__.py,sha256=ruOUy_2OfGptrnwDm5kRp5VPJX6Prl0Lk5dZqKBMmb8,142
1
+ fluxloop_cli/__init__.py,sha256=Dt2rOSQnnfVKTAgaaXWrhMb5qq6x-Bk8S58KCmkdfBc,142
2
2
  fluxloop_cli/arg_binder.py,sha256=oluHrwe1nNVq7alxBhBEoZrLrYop-cRgXgSu59LJcw4,7827
3
- fluxloop_cli/config_loader.py,sha256=8kG5QHCrBqREpJ59yG7lJlveOX7jGAk5XFYmKKOTt50,7801
3
+ fluxloop_cli/config_loader.py,sha256=KC2zgqlctNRzXA8PgkTrXGkrgQjAraVss734fg4nP0c,8876
4
4
  fluxloop_cli/config_schema.py,sha256=JZJRcMFun5hp3vKLAyek7W3NvISyzRzZt0BZAeSU38I,2415
5
5
  fluxloop_cli/constants.py,sha256=oMYCkUUqy2LORNY99gDRCOkgLOPrT1FY_Vrylo-QSSw,719
6
- fluxloop_cli/input_generator.py,sha256=H7gy1zw8kFDei_tLjuWHESafkEU_wGjHHb34bhJjCmk,5031
6
+ fluxloop_cli/input_generator.py,sha256=ldlVdPSDfGsP9zO2RALk7QmZjkIvUzTaxDgwOjuPB-0,4043
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
10
  fluxloop_cli/runner.py,sha256=Aqd5Gkqn3XqzteAOU4C7-5k3wjoiBVMNBln1fGGNI1o,22545
11
11
  fluxloop_cli/target_loader.py,sha256=F8fTxf-Jfu8rxK7-3Y_uPPxa6GBkCbQpXPaorQNqF6g,3220
12
- fluxloop_cli/templates.py,sha256=YKFOtt14cD_tFa7ILc0BVFeJfbHq4MWVaK0OVwhGGPs,11225
12
+ fluxloop_cli/templates.py,sha256=_QJxAq3JnylGryRjFwLVzaPmYMLsIl5eyVBNfkgGOeA,11207
13
13
  fluxloop_cli/validators.py,sha256=8cOCLSqvkQDSHRuty9-s5WJ70uvHGT_BEcXtxdlnX78,884
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.1.dist-info/METADATA,sha256=f3FzEx8Rh19l1PlLfmtpBsiKcrA03c_YWi6UYuWGJzs,3062
23
- fluxloop_cli-0.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
24
- fluxloop_cli-0.2.1.dist-info/entry_points.txt,sha256=NxOEMku4yLMY5kp_Qcd3JcevfXP6A98FsSf9xHcwkyE,51
25
- fluxloop_cli-0.2.1.dist-info/top_level.txt,sha256=ahLkaxzwhmVU4z-YhkmQVzAbW3-wez9cKnwPiDK7uKM,13
26
- fluxloop_cli-0.2.1.dist-info/RECORD,,
22
+ fluxloop_cli-0.2.2.dist-info/METADATA,sha256=ewOQY0n03-FdwJOpSwS73D5tgYmZWwRFmMfklofjb6s,3062
23
+ fluxloop_cli-0.2.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
24
+ fluxloop_cli-0.2.2.dist-info/entry_points.txt,sha256=NxOEMku4yLMY5kp_Qcd3JcevfXP6A98FsSf9xHcwkyE,51
25
+ fluxloop_cli-0.2.2.dist-info/top_level.txt,sha256=ahLkaxzwhmVU4z-YhkmQVzAbW3-wez9cKnwPiDK7uKM,13
26
+ fluxloop_cli-0.2.2.dist-info/RECORD,,