refactorai-cli 0.3.0__tar.gz → 0.3.2__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 (33) hide show
  1. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/PKG-INFO +3 -3
  2. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/README.md +1 -1
  3. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/pyproject.toml +2 -2
  4. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/refactorai_cli/__init__.py +1 -1
  5. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/refactorai_cli/commands/run_cmds.py +216 -90
  6. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/refactorai_cli.egg-info/PKG-INFO +3 -3
  7. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/refactorai_cli.egg-info/requires.txt +1 -1
  8. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/refactorai_cli/auth.py +0 -0
  9. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/refactorai_cli/client.py +0 -0
  10. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/refactorai_cli/commands/__init__.py +0 -0
  11. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/refactorai_cli/commands/auth_cmds.py +0 -0
  12. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/refactorai_cli/commands/cloud_cmds.py +0 -0
  13. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/refactorai_cli/commands/engine_cmds.py +0 -0
  14. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/refactorai_cli/commands/model_cmds.py +0 -0
  15. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/refactorai_cli/commands/rules_cmds.py +0 -0
  16. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/refactorai_cli/commands/runtime_cmds.py +0 -0
  17. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/refactorai_cli/commands/runtime_proxy_cmds.py +0 -0
  18. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/refactorai_cli/commands/setup_cmds.py +0 -0
  19. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/refactorai_cli/control_plane.py +0 -0
  20. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/refactorai_cli/credentials.py +0 -0
  21. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/refactorai_cli/local_constitution.py +0 -0
  22. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/refactorai_cli/local_engine_runtime.py +0 -0
  23. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/refactorai_cli/local_paths.py +0 -0
  24. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/refactorai_cli/main.py +0 -0
  25. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/refactorai_cli/model_policy.py +0 -0
  26. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/refactorai_cli/runtime_manager.py +0 -0
  27. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/refactorai_cli/settings.py +0 -0
  28. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/refactorai_cli/setup_flow.py +0 -0
  29. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/refactorai_cli.egg-info/SOURCES.txt +0 -0
  30. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/refactorai_cli.egg-info/dependency_links.txt +0 -0
  31. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/refactorai_cli.egg-info/entry_points.txt +0 -0
  32. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/refactorai_cli.egg-info/top_level.txt +0 -0
  33. {refactorai_cli-0.3.0 → refactorai_cli-0.3.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: refactorai-cli
3
- Version: 0.3.0
3
+ Version: 0.3.2
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.0.0
11
+ Requires-Dist: refactorai-core>=3.0.2
12
12
 
13
13
  # refactorai-cli
14
14
 
@@ -54,7 +54,7 @@ python -m twine upload ./refactorai-cli/dist/*
54
54
  ## Install test (local)
55
55
 
56
56
  ```bash
57
- python -m pip install ./refactorai-cli/dist/refactorai_cli-0.3.0-py3-none-any.whl
57
+ python -m pip install ./refactorai-cli/dist/refactorai_cli-0.3.2-py3-none-any.whl
58
58
  refactor --version
59
59
  ```
60
60
 
@@ -42,7 +42,7 @@ 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.3.0-py3-none-any.whl
45
+ python -m pip install ./refactorai-cli/dist/refactorai_cli-0.3.2-py3-none-any.whl
46
46
  refactor --version
47
47
  ```
48
48
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "refactorai-cli"
3
- version = "0.3.0"
3
+ version = "0.3.2"
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.0.0",
15
+ "refactorai-core>=3.0.2",
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.0"
8
+ __version__ = "0.3.2"
@@ -157,19 +157,25 @@ def _default_config_for_init() -> tuple[str, str]:
157
157
  if backend == BACKEND_LOCAL_SERVER:
158
158
  model_id = _setup_recommended_model_id()
159
159
  base_url = _setup_engine_base_url()
160
- config_text = DEFAULT_CONFIG.replace("provider: heuristic", "provider: ollama", 1)
161
- config_text = config_text.replace(
160
+ # local_server stays in `mode: local` but swaps the default heuristic
161
+ # provider block for an Ollama block pointing at the local engine.
162
+ config_text = DEFAULT_CONFIG.replace(
163
+ "# Heuristic (local, no LLM) - default for mode: local\n"
164
+ "provider: heuristic\n"
162
165
  "model_id: heuristic-local-v1",
163
- f"model_id: {model_id}\nbase_url: {base_url}",
166
+ "# Ollama (local engine) - configured by `refactor init`\n"
167
+ "provider: ollama\n"
168
+ f"model_id: {model_id}\n"
169
+ f"base_url: {base_url}",
164
170
  1,
165
171
  )
166
172
  return config_text, "local_server"
167
173
  if backend == BACKEND_BYOK:
168
- config_text = DEFAULT_CONFIG.replace("mode: local", "mode: cloud_byok", 1)
169
- config_text = config_text.replace("provider: heuristic", "provider: openai", 1)
170
- config_text = config_text.replace(
171
- "model_id: heuristic-local-v1",
172
- "model_id: gpt-4.1-mini\nprovider_key: ${OPENAI_API_KEY}\n# credential_ref: cred_01J...",
174
+ # BYOK only flips the execution mode. The developer chooses and
175
+ # uncomments a provider block in the Provider selection section.
176
+ config_text = DEFAULT_CONFIG.replace(
177
+ "mode: local\n# mode: cloud_byok",
178
+ "# mode: local\nmode: cloud_byok",
173
179
  1,
174
180
  )
175
181
  return config_text, "byok"
@@ -659,29 +665,7 @@ def _cloud_inference(
659
665
  }
660
666
 
661
667
  if execution_mode == "cloud_byok":
662
- provider_name = str(constitution.get_setting("provider", "") or "").strip()
663
- provider_key = str(constitution.get_setting("provider_key", "") or "").strip()
664
- credential_ref = str(constitution.get_setting("credential_ref", "") or "").strip()
665
-
666
- # Env-key-first BYOK path: when provider_key is configured (typically via
667
- # ${ENV_VAR} interpolation), prefer it over credential_ref.
668
- if provider_key:
669
- if not provider_name or provider_name.lower() == "cloud":
670
- raise RuntimeError(
671
- "cloud_byok with provider_key requires an explicit provider "
672
- "(e.g. provider: openai)."
673
- )
674
- payload["provider_key"] = provider_key
675
- payload["provider"] = provider_name
676
- elif credential_ref:
677
- payload["credential_ref"] = credential_ref
678
- if provider_name and provider_name.lower() != "cloud":
679
- payload["provider"] = provider_name
680
- else:
681
- raise RuntimeError(
682
- "cloud_byok requires either `provider_key` (preferred env-key path) "
683
- "or `credential_ref` (platform-stored credential path) in refactor.config."
684
- )
668
+ _apply_byok_payload(payload, constitution)
685
669
 
686
670
  idempotency_key = _stable_idempotency_key(
687
671
  account_id=auth_ctx.account_id,
@@ -758,6 +742,185 @@ def _cloud_inference(
758
742
  )
759
743
 
760
744
 
745
+ def _apply_byok_payload(payload: dict, constitution) -> None:
746
+ """Populate BYOK provider fields on a cloud inference ``payload`` in place.
747
+
748
+ Env-key-first: prefer ``provider_key`` (typically ``${ENV_VAR}``) over a
749
+ platform-stored ``credential_ref``. Shared by the review/refactor path and
750
+ the per-RR proposal path so BYOK resolution stays consistent.
751
+ """
752
+ provider_name = str(constitution.get_setting("provider", "") or "").strip()
753
+ provider_key = str(constitution.get_setting("provider_key", "") or "").strip()
754
+ credential_ref = str(constitution.get_setting("credential_ref", "") or "").strip()
755
+
756
+ if provider_key:
757
+ if not provider_name or provider_name.lower() == "cloud":
758
+ raise RuntimeError(
759
+ "cloud_byok with provider_key requires an explicit provider "
760
+ "(e.g. provider: openai)."
761
+ )
762
+ payload["provider_key"] = provider_key
763
+ payload["provider"] = provider_name
764
+ elif credential_ref:
765
+ payload["credential_ref"] = credential_ref
766
+ if provider_name and provider_name.lower() != "cloud":
767
+ payload["provider"] = provider_name
768
+ else:
769
+ raise RuntimeError(
770
+ "cloud_byok requires either `provider_key` (preferred env-key path) "
771
+ "or `credential_ref` (platform-stored credential path) in refactor.config."
772
+ )
773
+
774
+
775
+ def _post_cloud_inference(*, payload: dict, idempotency_key: str, auth_ctx, execution_mode: str) -> dict:
776
+ """POST a cloud inference request and return the parsed JSON body.
777
+
778
+ Centralizes transport + status-code error mapping so the per-RR proposal
779
+ path surfaces the same remediation messages as review/refactor.
780
+ """
781
+ try:
782
+ response = httpx.post(
783
+ f"{platform_url()}/v1/inference/refactor",
784
+ headers={
785
+ "Authorization": f"Bearer {auth_ctx.key.key}",
786
+ "Content-Type": "application/json",
787
+ "Idempotency-Key": idempotency_key,
788
+ },
789
+ json=payload,
790
+ timeout=45.0,
791
+ )
792
+ except httpx.HTTPError as exc:
793
+ raise RuntimeError(f"Could not reach cloud inference service: {exc}") from exc
794
+
795
+ if response.status_code == 401:
796
+ raise RuntimeError("Cloud inference unauthorized (developer key invalid or revoked).")
797
+ if response.status_code == 402:
798
+ if execution_mode == "cloud_byok":
799
+ raise RuntimeError(
800
+ "Cloud BYOK is not enabled for this account (missing `run:byok`). "
801
+ "Contact your admin to enable BYOK cloud execution."
802
+ )
803
+ raise RuntimeError("Cloud inference requires paid tier (`mode: cloud_managed`).")
804
+ if response.status_code == 404 and execution_mode == "cloud_byok":
805
+ raise RuntimeError(
806
+ "BYOK credential not found or not owned by this account. "
807
+ "Check `refactor cloud credentials list` and your `credential_ref`."
808
+ )
809
+ if response.status_code == 429:
810
+ raise RuntimeError("Cloud inference quota exhausted or rate-limited.")
811
+ if response.status_code >= 400:
812
+ raise RuntimeError(f"Cloud inference failed ({response.status_code}): {response.text[:500]}")
813
+
814
+ return response.json() if response.content else {}
815
+
816
+
817
+ class _CloudRRProvider:
818
+ """Lightweight provider stub for cloud RR execution (R22).
819
+
820
+ The executor reads ``provider.model_id`` for the artifact and would call
821
+ ``provider.complete(...)`` for proposals/tests. In cloud mode the proposal
822
+ and test-gen hooks are supplied, so ``complete`` is never invoked; it raises
823
+ to make any accidental local-prompt path explicit rather than silent.
824
+ """
825
+
826
+ def __init__(self, *, model_id: str) -> None:
827
+ self.model_id = model_id
828
+ self.provider_name = "cloud"
829
+ self.supports_refactor = True
830
+
831
+ def complete(self, system: str, user: str) -> str: # pragma: no cover - guard
832
+ raise RuntimeError(
833
+ "cloud RR execution must use server-side proposal hooks; "
834
+ "provider.complete should not be called."
835
+ )
836
+
837
+
838
+ def _cloud_rr_hooks(
839
+ *,
840
+ project_root: Path,
841
+ constitution,
842
+ model_hint: str | None,
843
+ ) -> tuple[Callable, Callable, str]:
844
+ """Build (propose_fn, gen_test_fn, model_id) for cloud per-RR execution (R22).
845
+
846
+ The returned callables match the executor's hook contract. They send the
847
+ single RR's context + current source to the platform, which builds the
848
+ proprietary prompts server-side and returns a proposal / characterization
849
+ test. Idempotency keys include the RR id and attempt so retries of distinct
850
+ RRs/attempts never collapse into a replayed result.
851
+ """
852
+ execution_mode = _cloud_execution_mode(constitution) or "cloud_managed"
853
+ auth_ctx = ensure_authenticated(project_root)
854
+ constitution_body = getattr(constitution, "body", "") or ""
855
+ resolved_model = model_hint or str(
856
+ constitution.get_setting("model_id", "managed-default") or "managed-default"
857
+ )
858
+
859
+ def _rr_context(rr) -> dict:
860
+ return {
861
+ "location": getattr(rr, "location", ""),
862
+ "file_path": getattr(rr, "file_path", ""),
863
+ "category": getattr(rr, "category", ""),
864
+ "severity": getattr(rr, "severity", ""),
865
+ "recommendation": getattr(rr, "recommendation", ""),
866
+ }
867
+
868
+ def _base_payload(stage: str, rr, source: str) -> dict:
869
+ payload = {
870
+ "stage": stage,
871
+ "execution_mode": execution_mode,
872
+ "constitution_hash": constitution.content_hash,
873
+ "constitution_body": constitution_body,
874
+ "rr_context": _rr_context(rr),
875
+ "source": source,
876
+ "max_alerts": int(constitution.get_setting("max_alerts_per_run", 5) or 5),
877
+ "model_hint": resolved_model,
878
+ }
879
+ if execution_mode == "cloud_byok":
880
+ _apply_byok_payload(payload, constitution)
881
+ return payload
882
+
883
+ def _idempotency(stage: str, rr, attempt: int) -> str:
884
+ seed = "|".join(
885
+ [
886
+ auth_ctx.account_id,
887
+ execution_mode,
888
+ stage,
889
+ constitution.content_hash,
890
+ str(getattr(rr, "rr_id", "")),
891
+ str(int(attempt)),
892
+ ]
893
+ )
894
+ return hashlib.sha256(seed.encode("utf-8")).hexdigest()
895
+
896
+ def propose_fn(rr, source: str, prior_failures: list[str]) -> dict:
897
+ # Attempt number is derived from prior failures so each retry gets a
898
+ # distinct idempotency key (1-based).
899
+ attempt = len(prior_failures or []) + 1
900
+ payload = _base_payload("rr_propose", rr, source)
901
+ payload["prior_failures"] = list(prior_failures or [])
902
+ data = _post_cloud_inference(
903
+ payload=payload,
904
+ idempotency_key=_idempotency("rr_propose", rr, attempt),
905
+ auth_ctx=auth_ctx,
906
+ execution_mode=execution_mode,
907
+ )
908
+ proposal = data.get("proposal") or {}
909
+ if not isinstance(proposal, dict):
910
+ return {}
911
+ return proposal
912
+
913
+ def gen_test_fn(rr, source: str) -> dict:
914
+ # Server-side characterization-test generation is not part of Phase 1.
915
+ # Returning no test makes the executor fall back to the configured test
916
+ # command for behavioral verification (parity with a local run that has
917
+ # no generated test). This keeps cloud RR execution safe today and lets
918
+ # a future phase add a dedicated server test-gen stage.
919
+ return {}
920
+
921
+ return propose_fn, gen_test_fn, resolved_model
922
+
923
+
761
924
  def _load_project() -> tuple[Path, object, object]:
762
925
  files = find_project_files()
763
926
  if not files:
@@ -1796,7 +1959,8 @@ def review(
1796
1959
  if _sandbox_enabled(project_config):
1797
1960
  if cloud:
1798
1961
  console.print(
1799
- "[dim]review: sandbox.enabled is ignored in cloud_managed mode.[/dim]"
1962
+ f"[dim]review: sandbox.enabled is ignored in "
1963
+ f"{_cloud_execution_mode(constitution)} mode.[/dim]"
1800
1964
  )
1801
1965
  else:
1802
1966
  sandbox_ctx = _ensure_sandbox_ready(
@@ -2023,7 +2187,8 @@ def code(
2023
2187
  if _sandbox_enabled(project_config):
2024
2188
  if cloud:
2025
2189
  console.print(
2026
- "[dim]code: sandbox.enabled is ignored in cloud_managed mode.[/dim]"
2190
+ f"[dim]code: sandbox.enabled is ignored in "
2191
+ f"{_cloud_execution_mode(constitution)} mode.[/dim]"
2027
2192
  )
2028
2193
  else:
2029
2194
  sandbox_ctx = _ensure_sandbox_ready(
@@ -2127,64 +2292,23 @@ def code(
2127
2292
  console.print("[green]No issues to refactor.[/green]")
2128
2293
  return
2129
2294
 
2130
- if cloud:
2131
- # Cloud modes generate patches via the platform inference API rather
2132
- # than the local RR interactive loop. Reuse prior review findings as
2133
- # prompt context; fall back to the latest stored review findings when
2134
- # requests were carried over from an earlier run.
2135
- if not cloud_review_findings:
2136
- existing_dir = head_run_dir(project_root)
2137
- if existing_dir is not None:
2138
- try:
2139
- cloud_review_findings = [
2140
- Finding.model_validate(item) for item in (read_findings(existing_dir) or [])
2141
- ]
2142
- except Exception:
2143
- cloud_review_findings = []
2144
- with console.status("[cyan]code[/cyan] generating patches (cloud)...", spinner="dots"):
2145
- artifact = _cloud_inference(
2146
- stage="refactor",
2147
- project_root=project_root,
2148
- constitution=constitution,
2149
- target=target,
2150
- model_hint=provider,
2151
- findings=cloud_review_findings,
2152
- )
2153
- cloud_store = create_run(project_root, run_id=artifact.run_id)
2154
- cloud_store.write_artifact(artifact, target=target, status="completed")
2295
+ from refactor_core.execution.rr_executor import run_refactor_requests
2155
2296
 
2156
- _print_rr_summary(artifact)
2157
- _print_patches(artifact.patches)
2158
- gate_color = "green" if artifact.gate.status == "passed" else "red"
2159
- console.print(
2160
- f"\n[bold]result[/bold]: [{gate_color}]{artifact.gate.status}[/{gate_color}] "
2161
- f"[dim]model={artifact.model_id} mode={_cloud_execution_mode(constitution)} "
2162
- f"run={artifact.run_id}[/dim]"
2297
+ # Cloud and local both drive the SAME per-RR interactive loop (R22 cloud
2298
+ # RR parity). The only difference is where proposals come from: cloud
2299
+ # passes server-side proposal hooks; local uses the local provider and
2300
+ # client-side prompt builders. This guarantees identical UX (proposal
2301
+ # diff + approval prompt), status transitions, and outcomes table.
2302
+ cloud_propose_fn = None
2303
+ cloud_gen_test_fn = None
2304
+ rr_provider = selected_provider
2305
+ if cloud:
2306
+ cloud_propose_fn, cloud_gen_test_fn, cloud_model_id = _cloud_rr_hooks(
2307
+ project_root=project_root,
2308
+ constitution=constitution,
2309
+ model_hint=provider,
2163
2310
  )
2164
-
2165
- if apply:
2166
- gate_mode = str(constitution.get_setting("gate_mode", "strict") or "strict")
2167
- diffs = [p.diff_text for p in (artifact.patches or [])]
2168
- if not diffs:
2169
- console.print("[dim]No patches to apply.[/dim]")
2170
- else:
2171
- _apply_diffs(
2172
- project_root,
2173
- cloud_store.run_dir,
2174
- diffs,
2175
- artifact.gate.status,
2176
- gate_mode,
2177
- force,
2178
- project_config,
2179
- )
2180
- elif artifact.patches:
2181
- console.print(
2182
- "[dim]Review patches with `refactor diff`, then apply with "
2183
- "`refactor code --apply` or `refactor apply`.[/dim]"
2184
- )
2185
- return
2186
-
2187
- from refactor_core.execution.rr_executor import run_refactor_requests
2311
+ rr_provider = _CloudRRProvider(model_id=cloud_model_id)
2188
2312
 
2189
2313
  with console.status("[cyan]code[/cyan] running...", spinner="dots") as status:
2190
2314
  rr_config = (
@@ -2195,13 +2319,15 @@ def code(
2195
2319
  artifact = run_refactor_requests(
2196
2320
  project_root=project_root,
2197
2321
  constitution=constitution,
2198
- provider=selected_provider,
2322
+ provider=rr_provider,
2199
2323
  requests=requests,
2200
2324
  config=rr_config,
2201
2325
  progress_cb=_rr_progress_logger(status=status),
2202
2326
  approval_cb=_rr_approval_prompt(auto_approve=auto_approve),
2203
2327
  on_rr_failure=on_rr_failure,
2204
2328
  equivalence_mode=equivalence,
2329
+ propose_fn=cloud_propose_fn,
2330
+ gen_test_fn=cloud_gen_test_fn,
2205
2331
  )
2206
2332
  except typer.Exit:
2207
2333
  # Intentional exits (e.g. gate-blocked apply) keep their own code/message.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: refactorai-cli
3
- Version: 0.3.0
3
+ Version: 0.3.2
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.0.0
11
+ Requires-Dist: refactorai-core>=3.0.2
12
12
 
13
13
  # refactorai-cli
14
14
 
@@ -54,7 +54,7 @@ python -m twine upload ./refactorai-cli/dist/*
54
54
  ## Install test (local)
55
55
 
56
56
  ```bash
57
- python -m pip install ./refactorai-cli/dist/refactorai_cli-0.3.0-py3-none-any.whl
57
+ python -m pip install ./refactorai-cli/dist/refactorai_cli-0.3.2-py3-none-any.whl
58
58
  refactor --version
59
59
  ```
60
60
 
@@ -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.0.0
5
+ refactorai-core>=3.0.2
File without changes