fluxloop-cli 0.3.4__tar.gz → 0.3.5__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.
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/PKG-INFO +1 -1
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/__init__.py +1 -1
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/api_utils.py +32 -9
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/commands/auth.py +6 -13
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/commands/config.py +3 -8
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/commands/projects.py +8 -2
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/commands/sync.py +5 -13
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/context_manager.py +3 -3
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/templates.py +1 -2
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli.egg-info/PKG-INFO +1 -1
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/pyproject.toml +1 -1
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/README.md +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/arg_binder.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/auth_manager.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/commands/__init__.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/commands/apikeys.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/commands/bundles.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/commands/context.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/commands/criteria.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/commands/data.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/commands/evaluate.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/commands/generate.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/commands/init.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/commands/inputs.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/commands/local_context.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/commands/personas.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/commands/run.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/commands/scenarios.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/commands/status.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/commands/test.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/common_options.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/config_loader.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/config_schema.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/constants.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/conversation_supervisor.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/environment.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/http_client.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/input_generator.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/llm_generator.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/main.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/project_paths.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/runner.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/target_loader.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/testing/__init__.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/testing/pytest_plugin.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/testing/types.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/token_usage.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/turns.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli/validators.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli.egg-info/SOURCES.txt +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli.egg-info/dependency_links.txt +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli.egg-info/entry_points.txt +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli.egg-info/requires.txt +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/fluxloop_cli.egg-info/top_level.txt +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/setup.cfg +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/tests/test_analysis_recommendations.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/tests/test_arg_binder.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/tests/test_config_command.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/tests/test_conversation_supervisor.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/tests/test_evaluate_command.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/tests/test_evaluation_llm.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/tests/test_init_pytest_template.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/tests/test_input_generator.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/tests/test_prompt_library.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/tests/test_pytest_plugin.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/tests/test_run_command.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/tests/test_runner_multi_turn.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/tests/test_success_criteria.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/tests/test_target_loader.py +0 -0
- {fluxloop_cli-0.3.4 → fluxloop_cli-0.3.5}/tests/test_testing_types.py +0 -0
|
@@ -20,18 +20,41 @@ from rich.console import Console
|
|
|
20
20
|
console = Console()
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
PRODUCTION_API_URL = "https://api.fluxloop.ai"
|
|
24
|
+
STAGING_API_URL = "https://staging.api.fluxloop.ai"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _read_project_json_api_url() -> Optional[str]:
|
|
28
|
+
"""Read api_url from .fluxloop/project.json if it exists."""
|
|
29
|
+
try:
|
|
30
|
+
from .context_manager import load_project_connection
|
|
31
|
+
|
|
32
|
+
conn = load_project_connection()
|
|
33
|
+
if conn and conn.api_url:
|
|
34
|
+
return conn.api_url
|
|
35
|
+
except Exception:
|
|
36
|
+
pass
|
|
37
|
+
return None
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def resolve_api_url(
|
|
41
|
+
override: Optional[str] = None,
|
|
42
|
+
*,
|
|
43
|
+
staging: bool = False,
|
|
44
|
+
) -> str:
|
|
24
45
|
"""
|
|
25
|
-
Resolve API URL
|
|
46
|
+
Resolve API URL with a single, unified priority chain.
|
|
26
47
|
|
|
27
48
|
Priority:
|
|
28
|
-
1.
|
|
29
|
-
2. FLUXLOOP_API_URL
|
|
30
|
-
3.
|
|
31
|
-
4.
|
|
49
|
+
1. ``override`` parameter (--api-url)
|
|
50
|
+
2. FLUXLOOP_API_URL environment variable
|
|
51
|
+
3. .fluxloop/project.json ``api_url``
|
|
52
|
+
4. ``--staging`` flag → staging URL
|
|
53
|
+
5. Hardcoded production URL (final fallback)
|
|
32
54
|
|
|
33
55
|
Args:
|
|
34
|
-
override: Optional URL override.
|
|
56
|
+
override: Optional URL override (--api-url).
|
|
57
|
+
staging: When True, use staging URL as fallback instead of production.
|
|
35
58
|
|
|
36
59
|
Returns:
|
|
37
60
|
Resolved API URL (trailing slash removed).
|
|
@@ -39,8 +62,8 @@ def resolve_api_url(override: Optional[str]) -> str:
|
|
|
39
62
|
url = (
|
|
40
63
|
override
|
|
41
64
|
or os.getenv("FLUXLOOP_API_URL")
|
|
42
|
-
or
|
|
43
|
-
or
|
|
65
|
+
or _read_project_json_api_url()
|
|
66
|
+
or (STAGING_API_URL if staging else PRODUCTION_API_URL)
|
|
44
67
|
)
|
|
45
68
|
return url.rstrip("/")
|
|
46
69
|
|
|
@@ -16,6 +16,7 @@ from rich.panel import Panel
|
|
|
16
16
|
from rich.spinner import Spinner
|
|
17
17
|
from rich.live import Live
|
|
18
18
|
|
|
19
|
+
from ..api_utils import resolve_api_url
|
|
19
20
|
from ..auth_manager import (
|
|
20
21
|
start_device_code_flow,
|
|
21
22
|
poll_device_code,
|
|
@@ -35,17 +36,6 @@ app = typer.Typer(help="Manage FluxLoop authentication")
|
|
|
35
36
|
console = Console()
|
|
36
37
|
|
|
37
38
|
|
|
38
|
-
def _resolve_api_url(override: Optional[str]) -> str:
|
|
39
|
-
"""Resolve API URL from override or environment variables."""
|
|
40
|
-
url = (
|
|
41
|
-
override
|
|
42
|
-
or os.getenv("FLUXLOOP_API_URL")
|
|
43
|
-
or os.getenv("FLUXLOOP_SYNC_URL")
|
|
44
|
-
or "https://api.fluxloop.ai"
|
|
45
|
-
)
|
|
46
|
-
return url.rstrip("/")
|
|
47
|
-
|
|
48
|
-
|
|
49
39
|
def _is_agent_environment() -> bool:
|
|
50
40
|
"""Detect if running in an agent/headless environment."""
|
|
51
41
|
# Check common agent environment indicators
|
|
@@ -63,6 +53,9 @@ def login(
|
|
|
63
53
|
api_url: Optional[str] = typer.Option(
|
|
64
54
|
None, "--api-url", help="FluxLoop API base URL"
|
|
65
55
|
),
|
|
56
|
+
staging: bool = typer.Option(
|
|
57
|
+
False, "--staging", help="Use staging API (staging.api.fluxloop.ai)"
|
|
58
|
+
),
|
|
66
59
|
force: bool = typer.Option(
|
|
67
60
|
False, "--force", "-f", help="Force re-login even if already logged in"
|
|
68
61
|
),
|
|
@@ -87,7 +80,7 @@ def login(
|
|
|
87
80
|
unless --force is specified. This makes the command idempotent and
|
|
88
81
|
safe to call from automated scripts or AI agents.
|
|
89
82
|
"""
|
|
90
|
-
api_url =
|
|
83
|
+
api_url = resolve_api_url(api_url, staging=staging)
|
|
91
84
|
|
|
92
85
|
# Check if already logged in (idempotent behavior)
|
|
93
86
|
if not force:
|
|
@@ -290,7 +283,7 @@ def status():
|
|
|
290
283
|
If token is expired or about to expire, automatically attempts to refresh.
|
|
291
284
|
Only suggests re-login if refresh fails.
|
|
292
285
|
"""
|
|
293
|
-
api_url =
|
|
286
|
+
api_url = resolve_api_url()
|
|
294
287
|
token = load_auth_token()
|
|
295
288
|
|
|
296
289
|
if not token:
|
|
@@ -191,8 +191,7 @@ def env(
|
|
|
191
191
|
loaded_paths = []
|
|
192
192
|
|
|
193
193
|
env_vars = [
|
|
194
|
-
("
|
|
195
|
-
("FLUXLOOP_API_KEY", "API key for authentication", None),
|
|
194
|
+
("FLUXLOOP_API_URL", "API base URL override (optional, project.json is primary)", None),
|
|
196
195
|
("FLUXLOOP_SYNC_API_KEY", "Sync API key for uploads", None),
|
|
197
196
|
("FLUXLOOP_ENABLED", "Enable/disable tracing", "true"),
|
|
198
197
|
("FLUXLOOP_DEBUG", "Enable debug mode", "false"),
|
|
@@ -327,13 +326,12 @@ def set_llm(
|
|
|
327
326
|
@app.command()
|
|
328
327
|
def set_sync_key(
|
|
329
328
|
api_key: str = typer.Argument(..., help="Sync API key"),
|
|
330
|
-
api_url: Optional[str] = typer.Option(None, "--url", help="Sync API base URL"),
|
|
331
329
|
overwrite_env: bool = typer.Option(False, "--overwrite-env", help="Overwrite existing key in .env"),
|
|
332
330
|
env_file: Path = typer.Option(Path(".env"), "--env-file", help="Path to environment file"),
|
|
333
331
|
project: Optional[str] = typer.Option(None, "--project", help="Project name under the FluxLoop root"),
|
|
334
332
|
root: Path = typer.Option(Path(DEFAULT_ROOT_DIR_NAME), "--root", help="FluxLoop root directory"),
|
|
335
333
|
):
|
|
336
|
-
"""Save Sync API
|
|
334
|
+
"""Save Sync API key to .env."""
|
|
337
335
|
|
|
338
336
|
env_path = resolve_env_path(env_file, project, root)
|
|
339
337
|
env_contents: Dict[str, str] = {}
|
|
@@ -351,12 +349,9 @@ def set_sync_key(
|
|
|
351
349
|
else:
|
|
352
350
|
env_contents["FLUXLOOP_SYNC_API_KEY"] = api_key
|
|
353
351
|
|
|
354
|
-
if api_url:
|
|
355
|
-
env_contents["FLUXLOOP_SYNC_URL"] = api_url
|
|
356
|
-
|
|
357
352
|
env_lines = [f"{key}={value}" for key, value in env_contents.items()]
|
|
358
353
|
env_path.write_text("\n".join(env_lines) + "\n")
|
|
359
|
-
console.print(f"[green]✓[/green] Saved sync
|
|
354
|
+
console.print(f"[green]✓[/green] Saved sync API key to {env_path}")
|
|
360
355
|
|
|
361
356
|
|
|
362
357
|
@app.command()
|
|
@@ -120,6 +120,9 @@ def create_project(
|
|
|
120
120
|
api_url: Optional[str] = typer.Option(
|
|
121
121
|
None, "--api-url", help="FluxLoop API base URL"
|
|
122
122
|
),
|
|
123
|
+
staging: bool = typer.Option(
|
|
124
|
+
False, "--staging", help="Use staging API (staging.api.fluxloop.ai)"
|
|
125
|
+
),
|
|
123
126
|
select: bool = typer.Option(
|
|
124
127
|
True, "--select/--no-select", help="Automatically select the created project"
|
|
125
128
|
),
|
|
@@ -127,7 +130,7 @@ def create_project(
|
|
|
127
130
|
"""
|
|
128
131
|
Create a new Web Project.
|
|
129
132
|
"""
|
|
130
|
-
api_url = resolve_api_url(api_url)
|
|
133
|
+
api_url = resolve_api_url(api_url, staging=staging)
|
|
131
134
|
|
|
132
135
|
try:
|
|
133
136
|
client = create_authenticated_client(api_url, use_jwt=True)
|
|
@@ -165,6 +168,9 @@ def select_project(
|
|
|
165
168
|
api_url: Optional[str] = typer.Option(
|
|
166
169
|
None, "--api-url", help="FluxLoop API base URL"
|
|
167
170
|
),
|
|
171
|
+
staging: bool = typer.Option(
|
|
172
|
+
False, "--staging", help="Use staging API (staging.api.fluxloop.ai)"
|
|
173
|
+
),
|
|
168
174
|
):
|
|
169
175
|
"""
|
|
170
176
|
Select a Web Project for this workspace.
|
|
@@ -176,7 +182,7 @@ def select_project(
|
|
|
176
182
|
Use this to connect your local workspace to a Web Project before
|
|
177
183
|
creating scenarios with 'fluxloop init scenario'.
|
|
178
184
|
"""
|
|
179
|
-
api_url = resolve_api_url(api_url)
|
|
185
|
+
api_url = resolve_api_url(api_url, staging=staging)
|
|
180
186
|
|
|
181
187
|
try:
|
|
182
188
|
# Verify project exists by fetching it
|
|
@@ -16,6 +16,7 @@ import typer
|
|
|
16
16
|
import yaml
|
|
17
17
|
from rich.console import Console
|
|
18
18
|
|
|
19
|
+
from ..api_utils import resolve_api_url
|
|
19
20
|
from ..config_loader import load_experiment_config
|
|
20
21
|
from ..constants import DEFAULT_CONFIG_PATH, FLUXLOOP_DIR_NAME, SCENARIOS_DIR_NAME
|
|
21
22
|
from ..context_manager import get_current_web_project_id, get_current_scenario
|
|
@@ -98,15 +99,6 @@ def _load_env(scenario: Optional[str], base_dir: Optional[Path] = None) -> None:
|
|
|
98
99
|
load_env_chain(source_dir, refresh_config=False)
|
|
99
100
|
|
|
100
101
|
|
|
101
|
-
def _resolve_api_url(override: Optional[str]) -> str:
|
|
102
|
-
url = (
|
|
103
|
-
override
|
|
104
|
-
or os.getenv("FLUXLOOP_SYNC_URL")
|
|
105
|
-
or "https://api.fluxloop.ai"
|
|
106
|
-
)
|
|
107
|
-
return url.rstrip("/")
|
|
108
|
-
|
|
109
|
-
|
|
110
102
|
def _resolve_api_key(override: Optional[str]) -> str:
|
|
111
103
|
key = (
|
|
112
104
|
override
|
|
@@ -165,7 +157,7 @@ def precreate_runs(
|
|
|
165
157
|
Precreate runs via /api/sync/upload so streaming can reference existing runs.
|
|
166
158
|
"""
|
|
167
159
|
_load_env(scenario, base_dir)
|
|
168
|
-
api_url =
|
|
160
|
+
api_url = resolve_api_url(api_url)
|
|
169
161
|
api_key = _resolve_api_key(api_key)
|
|
170
162
|
scenario_root = _resolve_scenario_dir(scenario, base_dir)
|
|
171
163
|
sync_state = _read_sync_state(scenario_root)
|
|
@@ -229,7 +221,7 @@ def stream_turn(
|
|
|
229
221
|
Stream a single turn to the sync API (best-effort).
|
|
230
222
|
"""
|
|
231
223
|
try:
|
|
232
|
-
api_url =
|
|
224
|
+
api_url = resolve_api_url(api_url)
|
|
233
225
|
api_key = _resolve_api_key(api_key)
|
|
234
226
|
run_id = turn.get("run_id")
|
|
235
227
|
turn_id = turn.get("turn_id")
|
|
@@ -543,7 +535,7 @@ def pull(
|
|
|
543
535
|
console.print(f"[dim]Using scenario: {scenario}[/dim]")
|
|
544
536
|
|
|
545
537
|
_load_env(scenario)
|
|
546
|
-
api_url =
|
|
538
|
+
api_url = resolve_api_url(api_url)
|
|
547
539
|
api_key = _resolve_api_key(api_key)
|
|
548
540
|
|
|
549
541
|
if not project_id:
|
|
@@ -661,7 +653,7 @@ def upload(
|
|
|
661
653
|
console.print(f"[dim]Using scenario: {scenario}[/dim]")
|
|
662
654
|
|
|
663
655
|
_load_env(scenario)
|
|
664
|
-
api_url =
|
|
656
|
+
api_url = resolve_api_url(api_url)
|
|
665
657
|
api_key = _resolve_api_key(api_key)
|
|
666
658
|
|
|
667
659
|
scenario_root = _resolve_scenario_dir(scenario)
|
|
@@ -40,7 +40,7 @@ class WebProjectConnection:
|
|
|
40
40
|
"""
|
|
41
41
|
project_id: str
|
|
42
42
|
project_name: str
|
|
43
|
-
api_url: str = "
|
|
43
|
+
api_url: str = ""
|
|
44
44
|
connected_at: Optional[str] = None
|
|
45
45
|
|
|
46
46
|
def to_dict(self) -> dict:
|
|
@@ -56,7 +56,7 @@ class WebProjectConnection:
|
|
|
56
56
|
return cls(
|
|
57
57
|
project_id=data["project_id"],
|
|
58
58
|
project_name=data["project_name"],
|
|
59
|
-
api_url=data.get("api_url", "
|
|
59
|
+
api_url=data.get("api_url", ""),
|
|
60
60
|
connected_at=data.get("connected_at"),
|
|
61
61
|
)
|
|
62
62
|
|
|
@@ -336,7 +336,7 @@ def save_project_connection(connection: WebProjectConnection, base_dir: Optional
|
|
|
336
336
|
def select_web_project(
|
|
337
337
|
project_id: str,
|
|
338
338
|
project_name: str,
|
|
339
|
-
api_url: str = "
|
|
339
|
+
api_url: str = "",
|
|
340
340
|
base_dir: Optional[Path] = None
|
|
341
341
|
) -> WebProjectConnection:
|
|
342
342
|
"""Select a Web Project for this workspace."""
|
|
@@ -336,9 +336,8 @@ def create_env_file() -> str:
|
|
|
336
336
|
return dedent(
|
|
337
337
|
"""
|
|
338
338
|
# FluxLoop Configuration
|
|
339
|
-
|
|
339
|
+
# API URL is managed via .fluxloop/project.json (set by 'fluxloop projects select')
|
|
340
340
|
FLUXLOOP_SYNC_API_KEY=your-api-key-here
|
|
341
|
-
# Legacy alias (still supported): FLUXLOOP_API_KEY
|
|
342
341
|
FLUXLOOP_ENABLED=true
|
|
343
342
|
FLUXLOOP_DEBUG=false
|
|
344
343
|
FLUXLOOP_SAMPLE_RATE=1.0
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|