refactorai-cli 0.3.10__tar.gz → 0.3.12__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. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/PKG-INFO +2 -2
  2. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/pyproject.toml +2 -2
  3. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli/__init__.py +1 -1
  4. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli/cloud_rr.py +126 -13
  5. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli/commands/run_cmds.py +7 -6
  6. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli.egg-info/PKG-INFO +2 -2
  7. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli.egg-info/requires.txt +1 -1
  8. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/README.md +0 -0
  9. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli/auth.py +0 -0
  10. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli/client.py +0 -0
  11. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli/commands/__init__.py +0 -0
  12. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli/commands/account_cmds.py +0 -0
  13. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli/commands/auth_cmds.py +0 -0
  14. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli/commands/cloud_cmds.py +0 -0
  15. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli/commands/engine_cmds.py +0 -0
  16. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli/commands/model_cmds.py +0 -0
  17. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli/commands/rules_cmds.py +0 -0
  18. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli/commands/runtime_cmds.py +0 -0
  19. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli/commands/runtime_proxy_cmds.py +0 -0
  20. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli/commands/setup_cmds.py +0 -0
  21. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli/commands/toolchains_cmds.py +0 -0
  22. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli/control_plane.py +0 -0
  23. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli/credentials.py +0 -0
  24. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli/local_constitution.py +0 -0
  25. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli/local_engine_runtime.py +0 -0
  26. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli/local_paths.py +0 -0
  27. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli/main.py +0 -0
  28. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli/model_policy.py +0 -0
  29. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli/runtime_manager.py +0 -0
  30. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli/settings.py +0 -0
  31. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli/setup_flow.py +0 -0
  32. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli.egg-info/SOURCES.txt +0 -0
  33. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli.egg-info/dependency_links.txt +0 -0
  34. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli.egg-info/entry_points.txt +0 -0
  35. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/refactorai_cli.egg-info/top_level.txt +0 -0
  36. {refactorai_cli-0.3.10 → refactorai_cli-0.3.12}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: refactorai-cli
3
- Version: 0.3.10
3
+ Version: 0.3.12
4
4
  Summary: Local-first CLI for the refactor platform
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -8,7 +8,7 @@ Requires-Dist: typer>=0.12.0
8
8
  Requires-Dist: httpx>=0.27.0
9
9
  Requires-Dist: rich>=13.7.0
10
10
  Requires-Dist: PyYAML>=6.0.1
11
- Requires-Dist: refactorai-core>=3.1.0
11
+ Requires-Dist: refactorai-core>=3.1.1
12
12
 
13
13
  # refactorai-cli
14
14
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "refactorai-cli"
3
- version = "0.3.10"
3
+ version = "0.3.12"
4
4
  description = "Local-first CLI for the refactor platform"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -12,7 +12,7 @@ dependencies = [
12
12
  "httpx>=0.27.0",
13
13
  "rich>=13.7.0",
14
14
  "PyYAML>=6.0.1",
15
- "refactorai-core>=3.1.0",
15
+ "refactorai-core>=3.1.1",
16
16
  ]
17
17
 
18
18
  [project.scripts]
@@ -5,4 +5,4 @@ the shared `refactor_core` pipeline from a project folder while staying
5
5
  authenticated to the hosted platform via a developer key.
6
6
  """
7
7
 
8
- __version__ = "0.3.10"
8
+ __version__ = "0.3.12"
@@ -22,6 +22,8 @@ this design fixes. ``tests/test_cloud_rr_client_boundary.py`` enforces this.
22
22
 
23
23
  from __future__ import annotations
24
24
 
25
+ from collections import deque
26
+ import contextlib
25
27
  import hashlib
26
28
  import re
27
29
  import shlex
@@ -135,6 +137,55 @@ def _run_test(
135
137
  return False, (proc.stdout or proc.stderr or "")[-500:]
136
138
 
137
139
 
140
+ def _run_command_with_progress(
141
+ project_root: Path,
142
+ command: str,
143
+ *,
144
+ env: dict | None = None,
145
+ progress_cb: Callable[[dict], None] | None = None,
146
+ label: str = "",
147
+ timeout: int = 1800,
148
+ ) -> tuple[bool, str]:
149
+ """Run a host command and stream output lines as progress events.
150
+
151
+ Used for long-running dependency setup steps (e.g. ``npm install``) so the
152
+ CLI does not appear stuck while the process is active.
153
+ """
154
+ try:
155
+ proc = subprocess.Popen(
156
+ command,
157
+ shell=True,
158
+ cwd=str(project_root),
159
+ stdout=subprocess.PIPE,
160
+ stderr=subprocess.STDOUT,
161
+ text=True,
162
+ bufsize=1,
163
+ env=env,
164
+ )
165
+ except (subprocess.SubprocessError, OSError) as exc:
166
+ return False, f"command error: {exc}"
167
+
168
+ tail: deque[str] = deque(maxlen=30)
169
+ try:
170
+ if proc.stdout is not None:
171
+ for raw in iter(proc.stdout.readline, ""):
172
+ line = raw.rstrip()
173
+ if not line:
174
+ continue
175
+ tail.append(line)
176
+ detail = f"{label}: {line}" if label else line
177
+ _emit(progress_cb, phase="rr", event="toolchain_provisioning", detail=detail[:240])
178
+ code = proc.wait(timeout=timeout)
179
+ except subprocess.TimeoutExpired:
180
+ proc.kill()
181
+ with contextlib.suppress(Exception):
182
+ proc.wait(timeout=2)
183
+ return False, f"command timed out after {timeout}s: {command}"
184
+ if code == 0:
185
+ return True, "ok"
186
+ return False, ("\n".join(tail))[-700:]
187
+
188
+
138
189
  def _leading_binary(command: str | None) -> str | None:
139
190
  """Return the leading executable of a simple command, or None.
140
191
 
@@ -266,16 +317,72 @@ def _restore_dependencies(
266
317
  present. Failures are non-fatal: the test run surfaces the real error.
267
318
  """
268
319
  if runtime == "node" and (project_root / "package.json").is_file():
269
- _emit(progress_cb, phase="rr", event="toolchain_provisioning", detail="npm install")
270
- _run_test(project_root, "npm install", env=env)
320
+ _emit(
321
+ progress_cb,
322
+ phase="rr",
323
+ event="toolchain_provisioning",
324
+ detail="step 1/1: npm install (streaming output below)",
325
+ )
326
+ ok, detail = _run_command_with_progress(
327
+ project_root,
328
+ "npm install",
329
+ env=env,
330
+ progress_cb=progress_cb,
331
+ label="npm",
332
+ timeout=1800,
333
+ )
334
+ if not ok:
335
+ _emit(
336
+ progress_cb,
337
+ phase="rr",
338
+ event="toolchain_provisioning",
339
+ detail=f"npm install finished with errors: {detail}",
340
+ )
271
341
  elif runtime == "python":
272
342
  if (project_root / "requirements.txt").is_file():
273
- _emit(progress_cb, phase="rr", event="toolchain_provisioning",
274
- detail="pip install -r requirements.txt")
275
- _run_test(project_root, "python -m pip install -r requirements.txt", env=env)
343
+ _emit(
344
+ progress_cb,
345
+ phase="rr",
346
+ event="toolchain_provisioning",
347
+ detail="step 1/1: pip install -r requirements.txt (streaming output below)",
348
+ )
349
+ ok, detail = _run_command_with_progress(
350
+ project_root,
351
+ "python -m pip install -r requirements.txt",
352
+ env=env,
353
+ progress_cb=progress_cb,
354
+ label="pip",
355
+ timeout=1800,
356
+ )
357
+ if not ok:
358
+ _emit(
359
+ progress_cb,
360
+ phase="rr",
361
+ event="toolchain_provisioning",
362
+ detail=f"pip install finished with errors: {detail}",
363
+ )
276
364
  elif (project_root / "pyproject.toml").is_file() or (project_root / "setup.py").is_file():
277
- _emit(progress_cb, phase="rr", event="toolchain_provisioning", detail="pip install -e .")
278
- _run_test(project_root, "python -m pip install -e .", env=env)
365
+ _emit(
366
+ progress_cb,
367
+ phase="rr",
368
+ event="toolchain_provisioning",
369
+ detail="step 1/1: pip install -e . (streaming output below)",
370
+ )
371
+ ok, detail = _run_command_with_progress(
372
+ project_root,
373
+ "python -m pip install -e .",
374
+ env=env,
375
+ progress_cb=progress_cb,
376
+ label="pip",
377
+ timeout=1800,
378
+ )
379
+ if not ok:
380
+ _emit(
381
+ progress_cb,
382
+ phase="rr",
383
+ event="toolchain_provisioning",
384
+ detail=f"pip install finished with errors: {detail}",
385
+ )
279
386
 
280
387
 
281
388
  def _collect_test_manifests(
@@ -569,6 +676,18 @@ def run_cloud_refactor_requests(
569
676
  apply_byok_payload=apply_byok_payload,
570
677
  )
571
678
 
679
+ if requests is None:
680
+ requests = pending_requests(project_root)
681
+
682
+ _emit(
683
+ progress_cb,
684
+ phase="rr",
685
+ event="run_start",
686
+ total_requests=len(requests),
687
+ test_command=test_command or "",
688
+ execution_env="cloud",
689
+ )
690
+
572
691
  # Managed host toolchain: when the resolved command's runtime is missing from
573
692
  # the host PATH, download a pinned runtime into the central store and run
574
693
  # tests with it (no container, no system changes). ``toolchain_env`` is None
@@ -581,18 +700,12 @@ def run_cloud_refactor_requests(
581
700
  progress_cb=progress_cb,
582
701
  )
583
702
 
584
- if requests is None:
585
- requests = pending_requests(project_root)
586
-
587
703
  run_store = create_run(project_root)
588
704
  run_id = run_store.run_id
589
705
  resolved_model = model_hint or str(
590
706
  constitution.get_setting("model_id", "managed-default") or "managed-default"
591
707
  )
592
708
 
593
- _emit(progress_cb, phase="rr", event="run_start", total_requests=len(requests),
594
- test_command=test_command or "", execution_env="cloud")
595
-
596
709
  outcomes: list[dict] = []
597
710
  counts = {"applied": 0, "denied": 0, "failed": 0, "deferred": 0}
598
711
  notes: list[str] = []
@@ -464,8 +464,10 @@ def _toolchain_consent_prompt(*, auto_approve: bool) -> Callable[[dict], bool]:
464
464
  """First-run consent for downloading a managed language runtime.
465
465
 
466
466
  Managed toolchains are downloaded into the central store (``~/.refactor``),
467
- never system paths, so this is low-risk; we still confirm once per run before
468
- fetching. ``--auto-approve`` and non-interactive terminals proceed silently.
467
+ never system paths. To avoid an apparent "stuck" run when Rich status
468
+ spinners are active, interactive runs default to approve after showing an
469
+ informational message (no blocking prompt). ``--auto-approve`` and
470
+ non-interactive terminals proceed silently.
469
471
  """
470
472
 
471
473
  def _ask(info: dict) -> bool:
@@ -474,11 +476,10 @@ def _toolchain_consent_prompt(*, auto_approve: bool) -> Callable[[dict], bool]:
474
476
  if auto_approve or not sys.stdin.isatty():
475
477
  return True
476
478
  console.print(
477
- f"[dim]'{binary}' was not found on your PATH. refactor can download a "
478
- f"pinned {runtime} runtime into ~/.refactor (no system changes, no container).[/dim]"
479
+ f"[dim]{binary} not found on your PATH. "
480
+ f"Refactor is downloading a pinned {runtime} runtime for testing.[/dim]"
479
481
  )
480
- raw = typer.prompt("Download managed toolchain? (Y/n)", default="Y")
481
- return raw.strip().lower() in {"", "y", "yes"}
482
+ return True
482
483
 
483
484
  return _ask
484
485
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: refactorai-cli
3
- Version: 0.3.10
3
+ Version: 0.3.12
4
4
  Summary: Local-first CLI for the refactor platform
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -8,7 +8,7 @@ Requires-Dist: typer>=0.12.0
8
8
  Requires-Dist: httpx>=0.27.0
9
9
  Requires-Dist: rich>=13.7.0
10
10
  Requires-Dist: PyYAML>=6.0.1
11
- Requires-Dist: refactorai-core>=3.1.0
11
+ Requires-Dist: refactorai-core>=3.1.1
12
12
 
13
13
  # refactorai-cli
14
14
 
@@ -2,4 +2,4 @@ typer>=0.12.0
2
2
  httpx>=0.27.0
3
3
  rich>=13.7.0
4
4
  PyYAML>=6.0.1
5
- refactorai-core>=3.1.0
5
+ refactorai-core>=3.1.1