refactorai-cli 0.2.8__tar.gz → 0.2.10__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.8 → refactorai_cli-0.2.10}/PKG-INFO +1 -1
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/pyproject.toml +1 -1
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/refactorai_cli/__init__.py +1 -1
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/refactorai_cli/commands/run_cmds.py +122 -13
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/refactorai_cli/commands/runtime_proxy_cmds.py +14 -0
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/refactorai_cli.egg-info/PKG-INFO +1 -1
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/README.md +0 -0
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/refactorai_cli/auth.py +0 -0
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/refactorai_cli/client.py +0 -0
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/refactorai_cli/commands/__init__.py +0 -0
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/refactorai_cli/commands/auth_cmds.py +0 -0
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/refactorai_cli/commands/engine_cmds.py +0 -0
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/refactorai_cli/commands/model_cmds.py +0 -0
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/refactorai_cli/commands/rules_cmds.py +0 -0
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/refactorai_cli/commands/runtime_cmds.py +0 -0
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/refactorai_cli/commands/setup_cmds.py +0 -0
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/refactorai_cli/control_plane.py +0 -0
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/refactorai_cli/credentials.py +0 -0
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/refactorai_cli/local_constitution.py +0 -0
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/refactorai_cli/local_engine_runtime.py +0 -0
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/refactorai_cli/local_paths.py +0 -0
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/refactorai_cli/main.py +0 -0
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/refactorai_cli/model_policy.py +0 -0
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/refactorai_cli/runtime_manager.py +0 -0
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/refactorai_cli/settings.py +0 -0
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/refactorai_cli/setup_flow.py +0 -0
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/refactorai_cli.egg-info/SOURCES.txt +0 -0
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/refactorai_cli.egg-info/dependency_links.txt +0 -0
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/refactorai_cli.egg-info/entry_points.txt +0 -0
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/refactorai_cli.egg-info/requires.txt +0 -0
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/refactorai_cli.egg-info/top_level.txt +0 -0
- {refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/setup.cfg +0 -0
|
@@ -8,6 +8,7 @@ generation and application.
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
10
|
import os
|
|
11
|
+
import json
|
|
11
12
|
import re
|
|
12
13
|
import shlex
|
|
13
14
|
import shutil
|
|
@@ -61,9 +62,12 @@ from refactor_core.sandbox_runtime import (
|
|
|
61
62
|
DEFAULT_IMAGE as SANDBOX_DEFAULT_IMAGE,
|
|
62
63
|
DEFAULT_SHELL as SANDBOX_DEFAULT_SHELL,
|
|
63
64
|
attach_shell as attach_sandbox_shell,
|
|
65
|
+
command_exists_in_container,
|
|
64
66
|
command_exists_in_sandbox,
|
|
67
|
+
detect_installer_in_container,
|
|
65
68
|
detect_installer_in_sandbox,
|
|
66
69
|
ensure_sandbox,
|
|
70
|
+
exec_in_container,
|
|
67
71
|
exec_in_sandbox,
|
|
68
72
|
remove_sandbox_container,
|
|
69
73
|
sandbox_name,
|
|
@@ -89,10 +93,62 @@ from refactor_core.store import (
|
|
|
89
93
|
from refactor_core.testcmd import resolve_test_command
|
|
90
94
|
|
|
91
95
|
from refactorai_cli.auth import AuthError, ensure_authenticated
|
|
96
|
+
from refactorai_cli.local_engine_runtime import DEFAULT_ENGINE_PORT, read_engine_state
|
|
92
97
|
from refactorai_cli.settings import platform_url
|
|
98
|
+
from refactorai_cli.setup_flow import (
|
|
99
|
+
BACKEND_BYOK,
|
|
100
|
+
BACKEND_LOCAL_SERVER,
|
|
101
|
+
read_setup_state,
|
|
102
|
+
stage_output_path,
|
|
103
|
+
)
|
|
93
104
|
|
|
94
105
|
console = Console()
|
|
95
106
|
|
|
107
|
+
|
|
108
|
+
def _read_stage_output(stage_id: str) -> dict:
|
|
109
|
+
path = stage_output_path(stage_id)
|
|
110
|
+
if not path.is_file():
|
|
111
|
+
return {}
|
|
112
|
+
try:
|
|
113
|
+
payload = json.loads(path.read_text(encoding="utf-8"))
|
|
114
|
+
except (json.JSONDecodeError, OSError):
|
|
115
|
+
return {}
|
|
116
|
+
output = payload.get("output")
|
|
117
|
+
return output if isinstance(output, dict) else {}
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def _setup_recommended_model_id() -> str:
|
|
121
|
+
s5_output = _read_stage_output("S5")
|
|
122
|
+
model_id = str(s5_output.get("recommended_model_id") or "").strip()
|
|
123
|
+
return model_id or "qwen2.5-coder:1.5b-instruct"
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def _setup_engine_base_url() -> str:
|
|
127
|
+
state = read_engine_state()
|
|
128
|
+
try:
|
|
129
|
+
port = int(state.get("port", DEFAULT_ENGINE_PORT))
|
|
130
|
+
except (TypeError, ValueError):
|
|
131
|
+
port = DEFAULT_ENGINE_PORT
|
|
132
|
+
return f"http://127.0.0.1:{port}/v1"
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def _default_config_for_init() -> tuple[str, str]:
|
|
136
|
+
setup_state = read_setup_state()
|
|
137
|
+
backend = str(setup_state.get("execution_backend") or "").strip().lower()
|
|
138
|
+
if backend == BACKEND_LOCAL_SERVER:
|
|
139
|
+
model_id = _setup_recommended_model_id()
|
|
140
|
+
base_url = _setup_engine_base_url()
|
|
141
|
+
config_text = DEFAULT_CONFIG.replace("provider: heuristic", "provider: ollama", 1)
|
|
142
|
+
config_text = config_text.replace(
|
|
143
|
+
"model_id: heuristic-local-v1",
|
|
144
|
+
f"model_id: {model_id}\nbase_url: {base_url}",
|
|
145
|
+
1,
|
|
146
|
+
)
|
|
147
|
+
return config_text, "local_server"
|
|
148
|
+
if backend == BACKEND_BYOK:
|
|
149
|
+
return DEFAULT_CONFIG, "byok"
|
|
150
|
+
return DEFAULT_CONFIG, "default"
|
|
151
|
+
|
|
96
152
|
_SEVERITY_STYLE = {
|
|
97
153
|
"critical": "bold red",
|
|
98
154
|
"high": "red",
|
|
@@ -600,12 +656,23 @@ def init(
|
|
|
600
656
|
)
|
|
601
657
|
raise typer.Exit(code=1)
|
|
602
658
|
consti_target.write_text(DEFAULT_CONSTITUTION, encoding="utf-8")
|
|
603
|
-
|
|
659
|
+
config_text, config_profile = _default_config_for_init()
|
|
660
|
+
config_target.write_text(config_text, encoding="utf-8")
|
|
604
661
|
|
|
605
662
|
constitution = load_constitution(consti_target)
|
|
606
663
|
record = register_project(project_root, constitution_hash=constitution.content_hash)
|
|
607
664
|
console.print(f"[green]Created[/green] {consti_target}")
|
|
608
665
|
console.print(f"[green]Created[/green] {config_target}")
|
|
666
|
+
if config_profile == "local_server":
|
|
667
|
+
console.print(
|
|
668
|
+
"[green]Configured[/green] refactor.config for local server setup "
|
|
669
|
+
"(provider=ollama with setup-recommended model)."
|
|
670
|
+
)
|
|
671
|
+
elif config_profile == "byok":
|
|
672
|
+
console.print(
|
|
673
|
+
"[green]Configured[/green] refactor.config for BYOK setup "
|
|
674
|
+
"(provider=heuristic; uncomment a provider block to use your key)."
|
|
675
|
+
)
|
|
609
676
|
console.print(
|
|
610
677
|
f"[green]Registered[/green] project in central store: {project_store_dir(project_root)}"
|
|
611
678
|
)
|
|
@@ -854,13 +921,47 @@ def _sandbox_preflight(
|
|
|
854
921
|
config_settings: dict,
|
|
855
922
|
auto_approve: bool,
|
|
856
923
|
no_install: bool,
|
|
924
|
+
runtime: str | None = None,
|
|
925
|
+
container_name: str | None = None,
|
|
926
|
+
workdir: str | None = None,
|
|
857
927
|
) -> tuple[bool, str]:
|
|
858
928
|
"""Run sandbox preflight and optionally perform approved install plan."""
|
|
929
|
+
|
|
930
|
+
has_container_ctx = bool(runtime and container_name)
|
|
931
|
+
resolved_workdir = str(workdir or "/workspace")
|
|
932
|
+
|
|
933
|
+
def _binary_exists(binary: str) -> bool:
|
|
934
|
+
if has_container_ctx:
|
|
935
|
+
return command_exists_in_container(
|
|
936
|
+
runtime=str(runtime),
|
|
937
|
+
container_name=str(container_name),
|
|
938
|
+
binary=binary,
|
|
939
|
+
workdir=resolved_workdir,
|
|
940
|
+
)
|
|
941
|
+
return command_exists_in_sandbox(project_root=project_root, binary=binary)
|
|
942
|
+
|
|
943
|
+
def _exec(command: str) -> tuple[bool, str]:
|
|
944
|
+
if has_container_ctx:
|
|
945
|
+
return exec_in_container(
|
|
946
|
+
runtime=str(runtime),
|
|
947
|
+
container_name=str(container_name),
|
|
948
|
+
command=command,
|
|
949
|
+
workdir=resolved_workdir,
|
|
950
|
+
)
|
|
951
|
+
return exec_in_sandbox(project_root=project_root, command=command)
|
|
952
|
+
|
|
953
|
+
def _detect_installer() -> str | None:
|
|
954
|
+
if has_container_ctx:
|
|
955
|
+
return detect_installer_in_container(
|
|
956
|
+
runtime=str(runtime),
|
|
957
|
+
container_name=str(container_name),
|
|
958
|
+
workdir=resolved_workdir,
|
|
959
|
+
)
|
|
960
|
+
return detect_installer_in_sandbox(project_root=project_root)
|
|
961
|
+
|
|
859
962
|
test_command = resolve_test_command(project_root, config_settings)
|
|
860
963
|
required_lsp = _required_lsp_commands(project_root)
|
|
861
|
-
missing_lsp = [
|
|
862
|
-
cmd for cmd in sorted(required_lsp) if not command_exists_in_sandbox(project_root=project_root, binary=cmd)
|
|
863
|
-
]
|
|
964
|
+
missing_lsp = [cmd for cmd in sorted(required_lsp) if not _binary_exists(cmd)]
|
|
864
965
|
missing_binary = ""
|
|
865
966
|
test_command_present = ""
|
|
866
967
|
if test_command:
|
|
@@ -877,7 +978,7 @@ def _sandbox_preflight(
|
|
|
877
978
|
)
|
|
878
979
|
return False, f"Could not parse test command: {test_command!r}"
|
|
879
980
|
test_command_present = binary
|
|
880
|
-
if not
|
|
981
|
+
if not _binary_exists(binary):
|
|
881
982
|
missing_binary = binary
|
|
882
983
|
|
|
883
984
|
if not missing_binary and not missing_lsp:
|
|
@@ -896,7 +997,7 @@ def _sandbox_preflight(
|
|
|
896
997
|
return True, "No test command configured."
|
|
897
998
|
return True, f"Preflight ok: found '{test_command_present}' and required LSP server(s) in sandbox."
|
|
898
999
|
|
|
899
|
-
installer =
|
|
1000
|
+
installer = _detect_installer()
|
|
900
1001
|
plan: list[str] = []
|
|
901
1002
|
if missing_binary:
|
|
902
1003
|
plan.extend(
|
|
@@ -1007,7 +1108,7 @@ def _sandbox_preflight(
|
|
|
1007
1108
|
"results": [],
|
|
1008
1109
|
}
|
|
1009
1110
|
for cmd in plan:
|
|
1010
|
-
ok, output =
|
|
1111
|
+
ok, output = _exec(cmd)
|
|
1011
1112
|
entry["results"].append({"command": cmd, "ok": ok, "output": (output or "")[:500]})
|
|
1012
1113
|
if not ok:
|
|
1013
1114
|
detail = output[:400] if output else "unknown error"
|
|
@@ -1027,7 +1128,7 @@ def _sandbox_preflight(
|
|
|
1027
1128
|
return False, f"Install command failed: `{cmd}` -> {detail}"
|
|
1028
1129
|
append_sandbox_install_history(project_root, entry)
|
|
1029
1130
|
|
|
1030
|
-
if missing_binary and not
|
|
1131
|
+
if missing_binary and not _binary_exists(missing_binary):
|
|
1031
1132
|
write_sandbox_preflight(
|
|
1032
1133
|
project_root,
|
|
1033
1134
|
{
|
|
@@ -1041,9 +1142,7 @@ def _sandbox_preflight(
|
|
|
1041
1142
|
},
|
|
1042
1143
|
)
|
|
1043
1144
|
return False, f"Preflight still failed after install: '{missing_binary}' not found."
|
|
1044
|
-
still_missing_lsp = [
|
|
1045
|
-
cmd for cmd in missing_lsp if not command_exists_in_sandbox(project_root=project_root, binary=cmd)
|
|
1046
|
-
]
|
|
1145
|
+
still_missing_lsp = [cmd for cmd in missing_lsp if not _binary_exists(cmd)]
|
|
1047
1146
|
if still_missing_lsp:
|
|
1048
1147
|
write_sandbox_preflight(
|
|
1049
1148
|
project_root,
|
|
@@ -1140,6 +1239,9 @@ def _ensure_sandbox_ready(
|
|
|
1140
1239
|
config_settings=settings,
|
|
1141
1240
|
auto_approve=auto_approve_install,
|
|
1142
1241
|
no_install=no_install,
|
|
1242
|
+
runtime=resolved_runtime,
|
|
1243
|
+
container_name=str(state.get("container_name", "") or ""),
|
|
1244
|
+
workdir=str(state.get("workdir") or workdir),
|
|
1143
1245
|
)
|
|
1144
1246
|
if not preflight_ok:
|
|
1145
1247
|
console.print(f"[red]{stage}: {preflight_msg}[/red]")
|
|
@@ -1149,6 +1251,7 @@ def _ensure_sandbox_ready(
|
|
|
1149
1251
|
"ephemeral": ephemeral,
|
|
1150
1252
|
"runtime": resolved_runtime,
|
|
1151
1253
|
"container_name": state.get("container_name", ""),
|
|
1254
|
+
"workdir": str(state.get("workdir") or workdir),
|
|
1152
1255
|
"stage": stage,
|
|
1153
1256
|
}
|
|
1154
1257
|
|
|
@@ -1233,6 +1336,9 @@ def start(
|
|
|
1233
1336
|
config_settings=settings,
|
|
1234
1337
|
auto_approve=yes,
|
|
1235
1338
|
no_install=no_install,
|
|
1339
|
+
runtime=resolved_runtime,
|
|
1340
|
+
container_name=str(state.get("container_name", "") or ""),
|
|
1341
|
+
workdir=str(state.get("workdir") or workdir),
|
|
1236
1342
|
)
|
|
1237
1343
|
if not preflight_ok:
|
|
1238
1344
|
console.print(f"[red]{preflight_msg}[/red]")
|
|
@@ -1497,8 +1603,11 @@ def code(
|
|
|
1497
1603
|
constitution=constitution,
|
|
1498
1604
|
provider=selected_provider,
|
|
1499
1605
|
requests=requests,
|
|
1500
|
-
config=
|
|
1501
|
-
|
|
1606
|
+
config=(
|
|
1607
|
+
dict(getattr(project_config, "settings", {}) or {})
|
|
1608
|
+
| ({"sandbox": {"enabled": True}} if sandbox_on else {})
|
|
1609
|
+
| ({"_sandbox_context": sandbox_ctx} if sandbox_ctx else {})
|
|
1610
|
+
)
|
|
1502
1611
|
or dict(getattr(constitution, "settings", {}) or {}),
|
|
1503
1612
|
progress_cb=_rr_progress_logger(status=status),
|
|
1504
1613
|
approval_cb=_rr_approval_prompt(auto_approve=auto_approve),
|
{refactorai_cli-0.2.8 → refactorai_cli-0.2.10}/refactorai_cli/commands/runtime_proxy_cmds.py
RENAMED
|
@@ -44,6 +44,20 @@ def _exec_runtime(command_name: str, passthrough_args: list[str]) -> None:
|
|
|
44
44
|
artifact.chmod(mode | 0o111)
|
|
45
45
|
except OSError:
|
|
46
46
|
pass
|
|
47
|
+
probe = subprocess.run(
|
|
48
|
+
[str(artifact), command_name, "--help"],
|
|
49
|
+
check=False,
|
|
50
|
+
capture_output=True,
|
|
51
|
+
text=True,
|
|
52
|
+
)
|
|
53
|
+
probe_text = f"{probe.stdout}\n{probe.stderr}".lower()
|
|
54
|
+
if "unrecognized arguments" in probe_text and command_name in probe_text:
|
|
55
|
+
console.print(
|
|
56
|
+
"[red]Active runtime artifact does not support command dispatch yet.[/red]\n"
|
|
57
|
+
"Run `refactor runtime update` (or rerun setup from S3) to install the "
|
|
58
|
+
"latest runtime binary from your server."
|
|
59
|
+
)
|
|
60
|
+
raise typer.Exit(code=2)
|
|
47
61
|
proc = subprocess.run([str(artifact), command_name, *passthrough_args], check=False)
|
|
48
62
|
if proc.returncode != 0:
|
|
49
63
|
raise typer.Exit(code=proc.returncode)
|
|
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
|