fluxloop-cli 0.2.16__tar.gz → 0.2.17__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 (36) hide show
  1. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/PKG-INFO +19 -1
  2. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/README.md +18 -0
  3. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/fluxloop_cli/__init__.py +1 -1
  4. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/fluxloop_cli/commands/__init__.py +2 -2
  5. fluxloop_cli-0.2.17/fluxloop_cli/commands/doctor.py +252 -0
  6. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/fluxloop_cli/main.py +2 -1
  7. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/fluxloop_cli/templates.py +3 -0
  8. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/fluxloop_cli.egg-info/PKG-INFO +19 -1
  9. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/fluxloop_cli.egg-info/SOURCES.txt +1 -0
  10. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/pyproject.toml +1 -1
  11. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/fluxloop_cli/arg_binder.py +0 -0
  12. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/fluxloop_cli/commands/config.py +0 -0
  13. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/fluxloop_cli/commands/generate.py +0 -0
  14. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/fluxloop_cli/commands/init.py +0 -0
  15. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/fluxloop_cli/commands/parse.py +0 -0
  16. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/fluxloop_cli/commands/record.py +0 -0
  17. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/fluxloop_cli/commands/run.py +0 -0
  18. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/fluxloop_cli/commands/status.py +0 -0
  19. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/fluxloop_cli/config_loader.py +0 -0
  20. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/fluxloop_cli/config_schema.py +0 -0
  21. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/fluxloop_cli/constants.py +0 -0
  22. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/fluxloop_cli/input_generator.py +0 -0
  23. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/fluxloop_cli/llm_generator.py +0 -0
  24. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/fluxloop_cli/project_paths.py +0 -0
  25. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/fluxloop_cli/runner.py +0 -0
  26. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/fluxloop_cli/target_loader.py +0 -0
  27. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/fluxloop_cli/validators.py +0 -0
  28. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/fluxloop_cli.egg-info/dependency_links.txt +0 -0
  29. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/fluxloop_cli.egg-info/entry_points.txt +0 -0
  30. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/fluxloop_cli.egg-info/requires.txt +0 -0
  31. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/fluxloop_cli.egg-info/top_level.txt +0 -0
  32. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/setup.cfg +0 -0
  33. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/tests/test_arg_binder.py +0 -0
  34. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/tests/test_config_command.py +0 -0
  35. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/tests/test_input_generator.py +0 -0
  36. {fluxloop_cli-0.2.16 → fluxloop_cli-0.2.17}/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.16
3
+ Version: 0.2.17
4
4
  Summary: FluxLoop CLI for running agent simulations
5
5
  Author-email: FluxLoop Team <team@fluxloop.dev>
6
6
  License: Apache-2.0
@@ -68,9 +68,27 @@ The legacy `setting.yaml` is still supported, but new projects created with
68
68
  - `fluxloop parse experiment` – convert experiment outputs into readable artifacts
69
69
  - `fluxloop config set-llm` – update LLM provider/model in `configs/input.yaml`
70
70
  - `fluxloop record enable|disable|status` – toggle recording mode across `.env` and simulation config
71
+ - `fluxloop doctor` – summarize Python, FluxLoop CLI/MCP, and MCP index state for the active environment
71
72
 
72
73
  Run `fluxloop --help` or `fluxloop <command> --help` for more detail.
73
74
 
75
+ ## Quick Setup Script
76
+
77
+ To prepare a fresh checkout (create `.venv`, install dependencies, and run diagnostics):
78
+
79
+ ```
80
+ bash scripts/setup_fluxloop_env.sh --target-source-root path/to/your/source
81
+ ```
82
+
83
+ Options:
84
+
85
+ - `--python PATH` – choose a specific interpreter (default `python3`)
86
+ - `--target-source-root PATH` – pre-populate VSCode `fluxloop.targetSourceRoot`
87
+ - `--skip-doctor` – skip the final `fluxloop doctor` check
88
+
89
+ After running the script, open the folder in VSCode and use `FluxLoop: Show Environment Info`
90
+ or `FluxLoop: Run Doctor` to confirm the environment.
91
+
74
92
  ## Runner Integration Patterns
75
93
 
76
94
  Configure how FluxLoop calls your code in `configs/simulation.yaml`:
@@ -28,9 +28,27 @@ The legacy `setting.yaml` is still supported, but new projects created with
28
28
  - `fluxloop parse experiment` – convert experiment outputs into readable artifacts
29
29
  - `fluxloop config set-llm` – update LLM provider/model in `configs/input.yaml`
30
30
  - `fluxloop record enable|disable|status` – toggle recording mode across `.env` and simulation config
31
+ - `fluxloop doctor` – summarize Python, FluxLoop CLI/MCP, and MCP index state for the active environment
31
32
 
32
33
  Run `fluxloop --help` or `fluxloop <command> --help` for more detail.
33
34
 
35
+ ## Quick Setup Script
36
+
37
+ To prepare a fresh checkout (create `.venv`, install dependencies, and run diagnostics):
38
+
39
+ ```
40
+ bash scripts/setup_fluxloop_env.sh --target-source-root path/to/your/source
41
+ ```
42
+
43
+ Options:
44
+
45
+ - `--python PATH` – choose a specific interpreter (default `python3`)
46
+ - `--target-source-root PATH` – pre-populate VSCode `fluxloop.targetSourceRoot`
47
+ - `--skip-doctor` – skip the final `fluxloop doctor` check
48
+
49
+ After running the script, open the folder in VSCode and use `FluxLoop: Show Environment Info`
50
+ or `FluxLoop: Run Doctor` to confirm the environment.
51
+
34
52
  ## Runner Integration Patterns
35
53
 
36
54
  Configure how FluxLoop calls your code in `configs/simulation.yaml`:
@@ -2,7 +2,7 @@
2
2
  FluxLoop CLI - Command-line interface for running agent simulations.
3
3
  """
4
4
 
5
- __version__ = "0.2.16"
5
+ __version__ = "0.2.17"
6
6
 
7
7
  from .main import app
8
8
 
@@ -1,5 +1,5 @@
1
1
  """CLI commands."""
2
2
 
3
- from . import config, generate, init, parse, run, status, record
3
+ from . import config, generate, init, parse, run, status, record, doctor
4
4
 
5
- __all__ = ["config", "generate", "init", "parse", "run", "status", "record"]
5
+ __all__ = ["config", "generate", "init", "parse", "run", "status", "record", "doctor"]
@@ -0,0 +1,252 @@
1
+ """
2
+ Doctor command for diagnosing FluxLoop environment issues.
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ import json
8
+ import os
9
+ import platform
10
+ import subprocess
11
+ import sys
12
+ from dataclasses import dataclass, asdict
13
+ from pathlib import Path
14
+ from typing import Any, Dict, Optional
15
+
16
+ import typer
17
+ from rich.console import Console
18
+ from rich.padding import Padding
19
+ from rich.panel import Panel
20
+ from rich.table import Table
21
+
22
+ from ..project_paths import resolve_config_directory, resolve_config_path
23
+ from ..constants import DEFAULT_CONFIG_PATH, DEFAULT_ROOT_DIR_NAME
24
+
25
+ app = typer.Typer(
26
+ help="Diagnose FluxLoop CLI, MCP and environment setup.",
27
+ invoke_without_command=True,
28
+ no_args_is_help=False,
29
+ )
30
+ console = Console()
31
+
32
+
33
+ @dataclass
34
+ class CommandResult:
35
+ success: bool
36
+ path: Optional[str]
37
+ output: Optional[str]
38
+ error: Optional[str]
39
+
40
+
41
+ def _which(executable: str) -> Optional[str]:
42
+ from shutil import which
43
+
44
+ return which(executable)
45
+
46
+
47
+ def _run_command(command: str, *args: str) -> CommandResult:
48
+ candidate = _which(command)
49
+ if not candidate:
50
+ return CommandResult(False, None, None, f"{command} not found on PATH")
51
+
52
+ try:
53
+ completed = subprocess.run(
54
+ [candidate, *args],
55
+ capture_output=True,
56
+ text=True,
57
+ check=True,
58
+ )
59
+ return CommandResult(True, candidate, completed.stdout.strip(), completed.stderr.strip() or None)
60
+ except subprocess.CalledProcessError as exc:
61
+ return CommandResult(
62
+ False,
63
+ candidate,
64
+ exc.stdout.strip() or None,
65
+ exc.stderr.strip() or exc.stdout.strip() or str(exc),
66
+ )
67
+
68
+
69
+ def _detect_virtual_environment() -> Dict[str, Any]:
70
+ env_vars = {
71
+ "VIRTUAL_ENV": os.environ.get("VIRTUAL_ENV"),
72
+ "CONDA_PREFIX": os.environ.get("CONDA_PREFIX"),
73
+ "UV_PROJECT_ENV": os.environ.get("UV_PROJECT_ENV"),
74
+ }
75
+ virtualized = sys.prefix != getattr(sys, "base_prefix", sys.prefix)
76
+ return {
77
+ "python_executable": sys.executable,
78
+ "python_version": platform.python_version(),
79
+ "platform": platform.platform(),
80
+ "virtual_env": virtualized,
81
+ "virtual_env_path": (
82
+ env_vars["VIRTUAL_ENV"]
83
+ or env_vars["CONDA_PREFIX"]
84
+ or (Path(sys.prefix).as_posix() if virtualized else None)
85
+ ),
86
+ "environment_variables": {k: v for k, v in env_vars.items() if v},
87
+ }
88
+
89
+
90
+ def _check_index_directory(index_dir: Path) -> Dict[str, Any]:
91
+ exists = index_dir.exists()
92
+ chunks_file = index_dir / "chunks.jsonl"
93
+ chunks_exists = chunks_file.exists()
94
+ chunks_size = chunks_file.stat().st_size if chunks_exists else 0
95
+ return {
96
+ "exists": exists,
97
+ "path": index_dir.as_posix(),
98
+ "chunks_exists": chunks_exists,
99
+ "chunks_size": chunks_size,
100
+ }
101
+
102
+
103
+ def _resolve_project_info(root: Path, project: Optional[str]) -> Dict[str, Any]:
104
+ config_path = resolve_config_path(DEFAULT_CONFIG_PATH, project, root)
105
+ config_dir = resolve_config_directory(project, root)
106
+ return {
107
+ "root": str(root.resolve()),
108
+ "config_directory": str(config_dir.resolve()),
109
+ "project_yaml": str(config_path.resolve()),
110
+ "project_yaml_exists": config_path.exists(),
111
+ "config_directory_exists": config_dir.exists(),
112
+ }
113
+
114
+
115
+ def _run_diagnostics(
116
+ project: Optional[str],
117
+ root: Path,
118
+ index_dir: Optional[Path],
119
+ output_json: bool,
120
+ ) -> None:
121
+ console.print(Panel.fit("FluxLoop Environment Doctor", border_style="blue"))
122
+
123
+ virtual_info = _detect_virtual_environment()
124
+ fluxloop_result = _run_command("fluxloop", "--version")
125
+ mcp_result = _run_command("fluxloop-mcp", "--help")
126
+ python_result = _run_command(sys.executable, "--version")
127
+
128
+ resolved_root = root
129
+ project_info = _resolve_project_info(resolved_root, project)
130
+ resolved_index_dir = (
131
+ index_dir
132
+ if index_dir is not None
133
+ else Path.home() / ".fluxloop" / "mcp" / "index" / "dev"
134
+ )
135
+ index_info = _check_index_directory(resolved_index_dir)
136
+
137
+ diagnostics = {
138
+ "python": {
139
+ "executable": sys.executable,
140
+ "version": virtual_info["python_version"],
141
+ "platform": virtual_info["platform"],
142
+ "command_output": python_result.output,
143
+ },
144
+ "virtual_environment": virtual_info,
145
+ "fluxloop_cli": asdict(fluxloop_result),
146
+ "fluxloop_mcp": asdict(mcp_result),
147
+ "project": project_info,
148
+ "mcp_index": index_info,
149
+ }
150
+
151
+ if output_json:
152
+ typer.echo(json.dumps(diagnostics, indent=2, default=str))
153
+ raise typer.Exit()
154
+
155
+ items_panel = Table(show_header=False, box=None)
156
+ items_panel.add_column("Component", style="cyan", no_wrap=True)
157
+ items_panel.add_column("Status")
158
+ items_panel.add_column("Details", style="dim")
159
+
160
+ items_panel.add_row(
161
+ "Python",
162
+ "[green]✓[/green]" if python_result.success else "[red]✗[/red]",
163
+ f"{virtual_info['python_version']} ({sys.executable})",
164
+ )
165
+
166
+ items_panel.add_row(
167
+ "Virtual Env",
168
+ "[green]✓[/green]" if virtual_info["virtual_env"] else "[yellow]–[/yellow]",
169
+ virtual_info["virtual_env_path"] or "Global interpreter",
170
+ )
171
+
172
+ items_panel.add_row(
173
+ "FluxLoop CLI",
174
+ "[green]✓[/green]" if fluxloop_result.success else "[red]✗[/red]",
175
+ fluxloop_result.path or fluxloop_result.error or "Not found",
176
+ )
177
+
178
+ items_panel.add_row(
179
+ "FluxLoop MCP",
180
+ "[green]✓[/green]" if mcp_result.success else "[red]✗[/red]",
181
+ mcp_result.path or mcp_result.error or "Not found",
182
+ )
183
+
184
+ index_status = "[green]✓[/green]" if index_info["exists"] else "[yellow]–[/yellow]"
185
+ index_details = index_info["path"]
186
+ if index_info["exists"]:
187
+ chunk_detail = (
188
+ f"chunks.jsonl ({index_info['chunks_size']} bytes)"
189
+ if index_info["chunks_exists"]
190
+ else "missing chunks.jsonl"
191
+ )
192
+ index_details = f"{index_details} • {chunk_detail}"
193
+
194
+ items_panel.add_row("MCP Index", index_status, index_details)
195
+
196
+ config_status = (
197
+ "[green]✓[/green]" if project_info["project_yaml_exists"] else "[yellow]–[/yellow]"
198
+ )
199
+ config_details = (
200
+ f"{project_info['project_yaml']} (project.yaml)"
201
+ if project_info["project_yaml_exists"]
202
+ else "Run: fluxloop init project"
203
+ )
204
+ items_panel.add_row("Project Config", config_status, config_details)
205
+
206
+ console.print(Padding(items_panel, (1, 0, 1, 0)))
207
+
208
+ if fluxloop_result.error or mcp_result.error:
209
+ console.print("[bold red]Errors[/bold red]")
210
+ if fluxloop_result.error:
211
+ console.print(f"• FluxLoop CLI: {fluxloop_result.error}")
212
+ if mcp_result.error:
213
+ console.print(f"• fluxloop-mcp: {mcp_result.error}")
214
+ console.print()
215
+
216
+ if diagnostics["fluxloop_cli"]["output"]:
217
+ console.print(Panel(diagnostics["fluxloop_cli"]["output"], title="fluxloop --version", border_style="green"))
218
+ if diagnostics["fluxloop_mcp"]["output"]:
219
+ console.print(Panel(diagnostics["fluxloop_mcp"]["output"], title="fluxloop-mcp --help", border_style="green"))
220
+
221
+ console.print(Padding(Panel.fit("Doctor completed", border_style="green"), (1, 0, 0, 0)))
222
+
223
+
224
+ @app.callback()
225
+ def doctor_callback(
226
+ ctx: typer.Context,
227
+ project: Optional[str] = typer.Option(
228
+ None, "--project", "-p", help="Project name under the FluxLoop root directory."
229
+ ),
230
+ root: Path = typer.Option(
231
+ Path(DEFAULT_ROOT_DIR_NAME),
232
+ "--root",
233
+ help="FluxLoop root directory (defaults to ./fluxloop).",
234
+ ),
235
+ index_dir: Optional[Path] = typer.Option(
236
+ None,
237
+ "--index-dir",
238
+ help="Override FluxLoop MCP index directory.",
239
+ ),
240
+ output_json: bool = typer.Option(
241
+ False,
242
+ "--json",
243
+ help="Output diagnostic information as JSON.",
244
+ ),
245
+ ) -> None:
246
+ """
247
+ Diagnose the FluxLoop CLI, MCP installation, virtual environment, and project configuration.
248
+ """
249
+ if ctx.invoked_subcommand:
250
+ return
251
+ _run_diagnostics(project, root, index_dir, output_json)
252
+
@@ -11,7 +11,7 @@ from rich.console import Console
11
11
  from rich.panel import Panel
12
12
 
13
13
  from . import __version__
14
- from .commands import config, generate, init, parse, run, status, record
14
+ from .commands import config, doctor, generate, init, parse, run, status, record
15
15
 
16
16
  # Create the main Typer app
17
17
  app = typer.Typer(
@@ -32,6 +32,7 @@ app.add_typer(config.app, name="config", help="Manage configuration")
32
32
  app.add_typer(generate.app, name="generate", help="Generate input datasets")
33
33
  app.add_typer(parse.app, name="parse", help="Parse experiments into readable files")
34
34
  app.add_typer(record.app, name="record", help="Manage recording mode and settings")
35
+ app.add_typer(doctor.app, name="doctor", help="Diagnose CLI and MCP environment issues")
35
36
 
36
37
 
37
38
  def version_callback(value: bool):
@@ -15,6 +15,9 @@ def create_project_config(project_name: str) -> str:
15
15
  description: AI agent simulation project
16
16
  version: 1.0.0
17
17
 
18
+ # FluxLoop VSCode extension will prompt to set this path
19
+ source_root: ""
20
+
18
21
  collector_url: null
19
22
  collector_api_key: null
20
23
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fluxloop-cli
3
- Version: 0.2.16
3
+ Version: 0.2.17
4
4
  Summary: FluxLoop CLI for running agent simulations
5
5
  Author-email: FluxLoop Team <team@fluxloop.dev>
6
6
  License: Apache-2.0
@@ -68,9 +68,27 @@ The legacy `setting.yaml` is still supported, but new projects created with
68
68
  - `fluxloop parse experiment` – convert experiment outputs into readable artifacts
69
69
  - `fluxloop config set-llm` – update LLM provider/model in `configs/input.yaml`
70
70
  - `fluxloop record enable|disable|status` – toggle recording mode across `.env` and simulation config
71
+ - `fluxloop doctor` – summarize Python, FluxLoop CLI/MCP, and MCP index state for the active environment
71
72
 
72
73
  Run `fluxloop --help` or `fluxloop <command> --help` for more detail.
73
74
 
75
+ ## Quick Setup Script
76
+
77
+ To prepare a fresh checkout (create `.venv`, install dependencies, and run diagnostics):
78
+
79
+ ```
80
+ bash scripts/setup_fluxloop_env.sh --target-source-root path/to/your/source
81
+ ```
82
+
83
+ Options:
84
+
85
+ - `--python PATH` – choose a specific interpreter (default `python3`)
86
+ - `--target-source-root PATH` – pre-populate VSCode `fluxloop.targetSourceRoot`
87
+ - `--skip-doctor` – skip the final `fluxloop doctor` check
88
+
89
+ After running the script, open the folder in VSCode and use `FluxLoop: Show Environment Info`
90
+ or `FluxLoop: Run Doctor` to confirm the environment.
91
+
74
92
  ## Runner Integration Patterns
75
93
 
76
94
  Configure how FluxLoop calls your code in `configs/simulation.yaml`:
@@ -21,6 +21,7 @@ fluxloop_cli.egg-info/requires.txt
21
21
  fluxloop_cli.egg-info/top_level.txt
22
22
  fluxloop_cli/commands/__init__.py
23
23
  fluxloop_cli/commands/config.py
24
+ fluxloop_cli/commands/doctor.py
24
25
  fluxloop_cli/commands/generate.py
25
26
  fluxloop_cli/commands/init.py
26
27
  fluxloop_cli/commands/parse.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "fluxloop-cli"
7
- version = "0.2.16"
7
+ version = "0.2.17"
8
8
  description = "FluxLoop CLI for running agent simulations"
9
9
  authors = [
10
10
  {name = "FluxLoop Team", email = "team@fluxloop.dev"}
File without changes