refactorai-cli 0.2.24__tar.gz → 0.2.26__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.
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/PKG-INFO +2 -2
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/README.md +1 -1
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/pyproject.toml +1 -1
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/refactorai_cli/__init__.py +1 -1
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/refactorai_cli/commands/setup_cmds.py +6 -0
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/refactorai_cli/setup_flow.py +185 -1
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/refactorai_cli.egg-info/PKG-INFO +2 -2
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/refactorai_cli/auth.py +0 -0
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/refactorai_cli/client.py +0 -0
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/refactorai_cli/commands/__init__.py +0 -0
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/refactorai_cli/commands/auth_cmds.py +0 -0
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/refactorai_cli/commands/engine_cmds.py +0 -0
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/refactorai_cli/commands/model_cmds.py +0 -0
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/refactorai_cli/commands/rules_cmds.py +0 -0
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/refactorai_cli/commands/run_cmds.py +0 -0
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/refactorai_cli/commands/runtime_cmds.py +0 -0
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/refactorai_cli/commands/runtime_proxy_cmds.py +0 -0
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/refactorai_cli/control_plane.py +0 -0
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/refactorai_cli/credentials.py +0 -0
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/refactorai_cli/local_constitution.py +0 -0
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/refactorai_cli/local_engine_runtime.py +0 -0
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/refactorai_cli/local_paths.py +0 -0
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/refactorai_cli/main.py +0 -0
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/refactorai_cli/model_policy.py +0 -0
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/refactorai_cli/runtime_manager.py +0 -0
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/refactorai_cli/settings.py +0 -0
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/refactorai_cli.egg-info/SOURCES.txt +0 -0
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/refactorai_cli.egg-info/dependency_links.txt +0 -0
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/refactorai_cli.egg-info/entry_points.txt +0 -0
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/refactorai_cli.egg-info/requires.txt +0 -0
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/refactorai_cli.egg-info/top_level.txt +0 -0
- {refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: refactorai-cli
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.26
|
|
4
4
|
Summary: Local-first CLI for the refactor platform
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -53,6 +53,6 @@ python -m twine upload ./refactorai-cli/dist/*
|
|
|
53
53
|
## Install test (local)
|
|
54
54
|
|
|
55
55
|
```bash
|
|
56
|
-
python -m pip install ./refactorai-cli/dist/refactorai_cli-0.2.
|
|
56
|
+
python -m pip install ./refactorai-cli/dist/refactorai_cli-0.2.26-py3-none-any.whl
|
|
57
57
|
refactor --version
|
|
58
58
|
```
|
|
@@ -42,6 +42,6 @@ python -m twine upload ./refactorai-cli/dist/*
|
|
|
42
42
|
## Install test (local)
|
|
43
43
|
|
|
44
44
|
```bash
|
|
45
|
-
python -m pip install ./refactorai-cli/dist/refactorai_cli-0.2.
|
|
45
|
+
python -m pip install ./refactorai-cli/dist/refactorai_cli-0.2.26-py3-none-any.whl
|
|
46
46
|
refactor --version
|
|
47
47
|
```
|
|
@@ -66,5 +66,11 @@ def setup(
|
|
|
66
66
|
console.print("[green]Setup completed successfully.[/green]")
|
|
67
67
|
if result.execution_backend:
|
|
68
68
|
console.print(f"[bold]backend[/bold]: {result.execution_backend}")
|
|
69
|
+
if result.sandbox_ready is True:
|
|
70
|
+
runtime = result.sandbox_runtime or "podman"
|
|
71
|
+
console.print(f"[bold]sandbox[/bold]: ready ({runtime})")
|
|
72
|
+
elif result.sandbox_ready is False:
|
|
73
|
+
detail = result.sandbox_reason or "Podman missing or not ready."
|
|
74
|
+
console.print(f"[yellow]sandbox[/yellow]: not ready ({detail})")
|
|
69
75
|
console.print(f"[bold]completed stages[/bold]: {', '.join(result.completed_stages)}")
|
|
70
76
|
console.print("[bold]next[/bold]: run `refactor init` and then `refactor review .`")
|
|
@@ -4,6 +4,8 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import json
|
|
6
6
|
import shutil
|
|
7
|
+
import subprocess
|
|
8
|
+
import sys
|
|
7
9
|
from dataclasses import dataclass
|
|
8
10
|
from datetime import datetime, timezone
|
|
9
11
|
from pathlib import Path
|
|
@@ -55,6 +57,9 @@ class SetupResult:
|
|
|
55
57
|
completed_stages: list[str]
|
|
56
58
|
last_error: str = ""
|
|
57
59
|
execution_backend: str = ""
|
|
60
|
+
sandbox_ready: bool | None = None
|
|
61
|
+
sandbox_runtime: str = ""
|
|
62
|
+
sandbox_reason: str = ""
|
|
58
63
|
|
|
59
64
|
|
|
60
65
|
def _now_iso() -> str:
|
|
@@ -147,19 +152,186 @@ def get_setup_diagnostics() -> dict:
|
|
|
147
152
|
return {"state": state, "stages": stages}
|
|
148
153
|
|
|
149
154
|
|
|
155
|
+
def _host_runtime_install_plan(runtime: str) -> list[str]:
|
|
156
|
+
"""Return host-level install commands for a missing runtime binary."""
|
|
157
|
+
rt = (runtime or "").strip().lower()
|
|
158
|
+
if rt != "podman":
|
|
159
|
+
return []
|
|
160
|
+
if shutil.which("apt-get"):
|
|
161
|
+
return ["sudo apt-get update", "sudo apt-get install -y podman"]
|
|
162
|
+
if shutil.which("dnf"):
|
|
163
|
+
return ["sudo dnf install -y podman"]
|
|
164
|
+
if shutil.which("yum"):
|
|
165
|
+
return ["sudo yum install -y podman"]
|
|
166
|
+
if shutil.which("apk"):
|
|
167
|
+
return ["sudo apk add --no-cache podman"]
|
|
168
|
+
if shutil.which("pacman"):
|
|
169
|
+
return ["sudo pacman -Sy --noconfirm podman"]
|
|
170
|
+
if shutil.which("brew"):
|
|
171
|
+
plan = ["brew install podman"]
|
|
172
|
+
if sys.platform == "darwin":
|
|
173
|
+
plan.extend(
|
|
174
|
+
[
|
|
175
|
+
"podman machine inspect >/dev/null 2>&1 || podman machine init",
|
|
176
|
+
"podman machine start",
|
|
177
|
+
]
|
|
178
|
+
)
|
|
179
|
+
return plan
|
|
180
|
+
return []
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def _host_runtime_repair_plan(runtime: str) -> list[str]:
|
|
184
|
+
"""Return host-level repair commands for an installed runtime."""
|
|
185
|
+
rt = (runtime or "").strip().lower()
|
|
186
|
+
if rt != "podman":
|
|
187
|
+
return []
|
|
188
|
+
if sys.platform == "darwin":
|
|
189
|
+
return [
|
|
190
|
+
"podman machine inspect >/dev/null 2>&1 || podman machine init",
|
|
191
|
+
"podman machine start",
|
|
192
|
+
]
|
|
193
|
+
return []
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def _run_host_plan(commands: list[str], emit: Callable[[str], None] | None = None) -> tuple[bool, str]:
|
|
197
|
+
"""Run host-level setup commands sequentially."""
|
|
198
|
+
for command in commands:
|
|
199
|
+
if emit:
|
|
200
|
+
emit(f"Executing host command: {command}")
|
|
201
|
+
proc = subprocess.run(command, shell=True, capture_output=True, text=True)
|
|
202
|
+
if proc.returncode != 0:
|
|
203
|
+
detail = (proc.stderr or proc.stdout or "").strip()[:500]
|
|
204
|
+
return False, f"`{command}` -> {detail or 'unknown error'}"
|
|
205
|
+
return True, ""
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def _podman_runtime_ready(runtime: str) -> tuple[bool, str]:
|
|
209
|
+
"""Return whether Podman is installed and ready for container operations."""
|
|
210
|
+
try:
|
|
211
|
+
proc = subprocess.run([runtime, "info"], capture_output=True, text=True)
|
|
212
|
+
except OSError as exc:
|
|
213
|
+
return False, str(exc)
|
|
214
|
+
if proc.returncode == 0:
|
|
215
|
+
return True, ""
|
|
216
|
+
detail = (proc.stderr or proc.stdout or "").strip()[:500]
|
|
217
|
+
return False, detail or "Podman runtime is installed but not ready."
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def _sandbox_summary_from_precheck() -> tuple[bool | None, str, str]:
|
|
221
|
+
"""Read S1 output and derive sandbox readiness summary for CLI output."""
|
|
222
|
+
path = stage_output_path("S1")
|
|
223
|
+
if not path.is_file():
|
|
224
|
+
return None, "", ""
|
|
225
|
+
try:
|
|
226
|
+
payload = json.loads(path.read_text(encoding="utf-8"))
|
|
227
|
+
except (json.JSONDecodeError, OSError):
|
|
228
|
+
return None, "", ""
|
|
229
|
+
output = payload.get("output")
|
|
230
|
+
if not isinstance(output, dict):
|
|
231
|
+
return None, "", ""
|
|
232
|
+
ready_raw = output.get("podman_ready")
|
|
233
|
+
available_raw = output.get("podman_available")
|
|
234
|
+
sandbox_ready: bool | None = None
|
|
235
|
+
if isinstance(ready_raw, bool):
|
|
236
|
+
sandbox_ready = ready_raw
|
|
237
|
+
elif isinstance(available_raw, bool):
|
|
238
|
+
sandbox_ready = available_raw
|
|
239
|
+
reason = str(output.get("podman_ready_reason") or output.get("podman_reason") or "").strip()
|
|
240
|
+
runtime = "podman" if sandbox_ready is not None else ""
|
|
241
|
+
return sandbox_ready, runtime, reason
|
|
242
|
+
|
|
243
|
+
|
|
150
244
|
def _stage_s1_precheck(_ask_approval: Callable[[str], bool], _emit: Callable[[str], None] | None = None) -> dict:
|
|
151
245
|
profile = detect_machine_profile()
|
|
152
246
|
runtime, reason = resolve_engine_runtime("podman")
|
|
247
|
+
podman_install_plan: list[str] = []
|
|
248
|
+
podman_install_approved = False
|
|
249
|
+
podman_install_attempted = False
|
|
250
|
+
podman_repair_plan: list[str] = []
|
|
251
|
+
podman_repair_approved = False
|
|
252
|
+
podman_repair_attempted = False
|
|
153
253
|
disk = shutil.disk_usage(str(refactor_home()))
|
|
154
254
|
blockers: list[str] = []
|
|
155
255
|
if disk.free < 2 * 1024 * 1024 * 1024:
|
|
156
256
|
blockers.append("Less than 2GB free disk available in REFACTOR_HOME filesystem.")
|
|
157
257
|
if blockers:
|
|
158
258
|
raise SetupError("Precheck failed: " + "; ".join(blockers))
|
|
259
|
+
if not runtime:
|
|
260
|
+
podman_install_plan = _host_runtime_install_plan("podman")
|
|
261
|
+
if podman_install_plan:
|
|
262
|
+
podman_install_approved = _ask_approval(
|
|
263
|
+
"Install Podman host runtime now so sandboxed review can run?"
|
|
264
|
+
)
|
|
265
|
+
if podman_install_approved:
|
|
266
|
+
podman_install_attempted = True
|
|
267
|
+
if _emit:
|
|
268
|
+
_emit("Podman was not found. Running guided host install plan...")
|
|
269
|
+
ok, detail = _run_host_plan(podman_install_plan, emit=_emit)
|
|
270
|
+
if not ok:
|
|
271
|
+
raise SetupError(
|
|
272
|
+
"Podman host install failed: "
|
|
273
|
+
f"{detail}. Install manually and retry (`refactor doctor --sandbox`)."
|
|
274
|
+
)
|
|
275
|
+
runtime, reason = resolve_engine_runtime("podman")
|
|
276
|
+
if not runtime:
|
|
277
|
+
raise SetupError(
|
|
278
|
+
"Podman install completed but runtime is still unavailable. "
|
|
279
|
+
"Verify PATH and retry (`refactor doctor --sandbox`)."
|
|
280
|
+
)
|
|
281
|
+
elif _emit:
|
|
282
|
+
_emit("Podman is missing and no automated install plan is available on this host.")
|
|
283
|
+
|
|
284
|
+
podman_ready = False
|
|
285
|
+
podman_ready_reason = reason
|
|
286
|
+
if runtime:
|
|
287
|
+
podman_ready, podman_ready_reason = _podman_runtime_ready(str(runtime))
|
|
288
|
+
if not podman_ready:
|
|
289
|
+
podman_repair_plan = _host_runtime_repair_plan(str(runtime))
|
|
290
|
+
if podman_repair_plan:
|
|
291
|
+
podman_repair_approved = _ask_approval(
|
|
292
|
+
"Podman is installed but not ready. Initialize/start Podman machine now?"
|
|
293
|
+
)
|
|
294
|
+
if podman_repair_approved:
|
|
295
|
+
podman_repair_attempted = True
|
|
296
|
+
if _emit:
|
|
297
|
+
_emit("Podman is installed but not ready. Running repair plan...")
|
|
298
|
+
ok, detail = _run_host_plan(podman_repair_plan, emit=_emit)
|
|
299
|
+
if not ok:
|
|
300
|
+
raise SetupError(
|
|
301
|
+
"Podman runtime repair failed: "
|
|
302
|
+
f"{detail}. Run `podman machine start` and retry."
|
|
303
|
+
)
|
|
304
|
+
podman_ready, podman_ready_reason = _podman_runtime_ready(str(runtime))
|
|
305
|
+
if not podman_ready:
|
|
306
|
+
raise SetupError(
|
|
307
|
+
"Podman is installed but still not ready after repair: "
|
|
308
|
+
f"{podman_ready_reason}"
|
|
309
|
+
)
|
|
310
|
+
if _emit:
|
|
311
|
+
if runtime and podman_ready:
|
|
312
|
+
_emit("Sandbox runtime precheck: Podman is ready.")
|
|
313
|
+
elif runtime:
|
|
314
|
+
_emit(
|
|
315
|
+
"Sandbox runtime precheck: Podman is installed but not ready. "
|
|
316
|
+
"Setup can continue, but `refactor review` may fail until Podman is started."
|
|
317
|
+
)
|
|
318
|
+
else:
|
|
319
|
+
_emit(
|
|
320
|
+
"Sandbox runtime precheck: Podman is not installed. "
|
|
321
|
+
"Setup can continue, but sandboxed review requires Podman."
|
|
322
|
+
)
|
|
159
323
|
return {
|
|
160
324
|
"profile": profile,
|
|
161
325
|
"podman_available": bool(runtime),
|
|
162
326
|
"podman_reason": reason,
|
|
327
|
+
"podman_ready": bool(runtime and podman_ready),
|
|
328
|
+
"podman_ready_reason": podman_ready_reason,
|
|
329
|
+
"podman_install_plan": podman_install_plan,
|
|
330
|
+
"podman_install_approved": podman_install_approved,
|
|
331
|
+
"podman_install_attempted": podman_install_attempted,
|
|
332
|
+
"podman_repair_plan": podman_repair_plan,
|
|
333
|
+
"podman_repair_approved": podman_repair_approved,
|
|
334
|
+
"podman_repair_attempted": podman_repair_attempted,
|
|
163
335
|
"disk_free_mb": int(disk.free / (1024 * 1024)),
|
|
164
336
|
}
|
|
165
337
|
|
|
@@ -399,7 +571,15 @@ def run_setup(
|
|
|
399
571
|
elif resume:
|
|
400
572
|
pending = [stage for stage in STAGE_IDS if stage not in completed]
|
|
401
573
|
if not pending:
|
|
402
|
-
|
|
574
|
+
sandbox_ready, sandbox_runtime, sandbox_reason = _sandbox_summary_from_precheck()
|
|
575
|
+
return SetupResult(
|
|
576
|
+
status="already_completed",
|
|
577
|
+
completed_stages=completed,
|
|
578
|
+
last_error="",
|
|
579
|
+
sandbox_ready=sandbox_ready,
|
|
580
|
+
sandbox_runtime=sandbox_runtime,
|
|
581
|
+
sandbox_reason=sandbox_reason,
|
|
582
|
+
)
|
|
403
583
|
start_index = STAGE_IDS.index(pending[0])
|
|
404
584
|
else:
|
|
405
585
|
start_index = 0
|
|
@@ -478,9 +658,13 @@ def run_setup(
|
|
|
478
658
|
"last_error": "",
|
|
479
659
|
}
|
|
480
660
|
)
|
|
661
|
+
sandbox_ready, sandbox_runtime, sandbox_reason = _sandbox_summary_from_precheck()
|
|
481
662
|
return SetupResult(
|
|
482
663
|
status="completed",
|
|
483
664
|
completed_stages=completed,
|
|
484
665
|
last_error="",
|
|
485
666
|
execution_backend=final_backend,
|
|
667
|
+
sandbox_ready=sandbox_ready,
|
|
668
|
+
sandbox_runtime=sandbox_runtime,
|
|
669
|
+
sandbox_reason=sandbox_reason,
|
|
486
670
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: refactorai-cli
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.26
|
|
4
4
|
Summary: Local-first CLI for the refactor platform
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -53,6 +53,6 @@ python -m twine upload ./refactorai-cli/dist/*
|
|
|
53
53
|
## Install test (local)
|
|
54
54
|
|
|
55
55
|
```bash
|
|
56
|
-
python -m pip install ./refactorai-cli/dist/refactorai_cli-0.2.
|
|
56
|
+
python -m pip install ./refactorai-cli/dist/refactorai_cli-0.2.26-py3-none-any.whl
|
|
57
57
|
refactor --version
|
|
58
58
|
```
|
|
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
|
{refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/refactorai_cli/commands/runtime_proxy_cmds.py
RENAMED
|
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
|
{refactorai_cli-0.2.24 → refactorai_cli-0.2.26}/refactorai_cli.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|