refactorai-cli 0.7.15__tar.gz → 0.7.17__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 (54) hide show
  1. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/PKG-INFO +2 -2
  2. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/pyproject.toml +2 -2
  3. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/__init__.py +1 -1
  4. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/commands/run_cmds.py +7 -3
  5. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/mode_sync.py +90 -19
  6. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli.egg-info/PKG-INFO +2 -2
  7. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli.egg-info/requires.txt +1 -1
  8. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/README.md +0 -0
  9. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/auth.py +0 -0
  10. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/client.py +0 -0
  11. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/cloud_rr.py +0 -0
  12. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/commands/__init__.py +0 -0
  13. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/commands/account_cmds.py +0 -0
  14. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/commands/auth_cmds.py +0 -0
  15. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/commands/branch_cmds.py +0 -0
  16. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/commands/cloud_cmds.py +0 -0
  17. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/commands/engine_cmds.py +0 -0
  18. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/commands/hook_cmds.py +0 -0
  19. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/commands/model_cmds.py +0 -0
  20. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/commands/policy_cmds.py +0 -0
  21. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/commands/pre_push_cmds.py +0 -0
  22. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/commands/request_cmds.py +0 -0
  23. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/commands/rules_cmds.py +0 -0
  24. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/commands/runtime_cmds.py +0 -0
  25. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/commands/runtime_proxy_cmds.py +0 -0
  26. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/commands/setup_cmds.py +0 -0
  27. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/commands/toolchains_cmds.py +0 -0
  28. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/commands/watch_cmds.py +0 -0
  29. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/commands/workspace_cmds.py +0 -0
  30. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/commit_queue.py +0 -0
  31. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/commit_telemetry.py +0 -0
  32. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/control_plane.py +0 -0
  33. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/credentials.py +0 -0
  34. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/dotenv_loader.py +0 -0
  35. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/git_scope.py +0 -0
  36. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/local_constitution.py +0 -0
  37. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/local_engine_runtime.py +0 -0
  38. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/local_paths.py +0 -0
  39. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/main.py +0 -0
  40. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/model_policy.py +0 -0
  41. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/pre_push_gate.py +0 -0
  42. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/refactor_branch_store.py +0 -0
  43. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/review_runner.py +0 -0
  44. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/runtime_manager.py +0 -0
  45. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/settings.py +0 -0
  46. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/setup_flow.py +0 -0
  47. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/watch_ledger.py +0 -0
  48. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/watch_state.py +0 -0
  49. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli/watch_supervisor.py +0 -0
  50. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli.egg-info/SOURCES.txt +0 -0
  51. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli.egg-info/dependency_links.txt +0 -0
  52. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli.egg-info/entry_points.txt +0 -0
  53. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/refactorai_cli.egg-info/top_level.txt +0 -0
  54. {refactorai_cli-0.7.15 → refactorai_cli-0.7.17}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: refactorai-cli
3
- Version: 0.7.15
3
+ Version: 0.7.17
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.2.23
11
+ Requires-Dist: refactorai-core>=3.2.24
12
12
 
13
13
  # refactorai-cli
14
14
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "refactorai-cli"
3
- version = "0.7.15"
3
+ version = "0.7.17"
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.2.23",
15
+ "refactorai-core>=3.2.24",
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.7.15"
8
+ __version__ = "0.7.16"
@@ -5115,8 +5115,11 @@ def _cloud_doctor(
5115
5115
  resolving/pinging a local provider.
5116
5116
  """
5117
5117
  console.print(f"[bold]project[/bold]: {project_root}")
5118
- console.print(f"[bold]mode[/bold]: {execution_mode}")
5118
+ # Clarify the two axes to avoid confusion for local_byok/local_managed:
5119
+ # - execution variant: user-facing mode contract
5120
+ # - platform inference mode: wire mode used for server inference endpoint
5119
5121
  console.print(f"[bold]execution variant[/bold]: {execution_variant}")
5122
+ console.print(f"[bold]platform inference mode[/bold]: {execution_mode}")
5120
5123
  _report_verification_environment(project_root, execution_variant, project_config)
5121
5124
  _report_store_binding(project_root)
5122
5125
 
@@ -5135,13 +5138,14 @@ def _cloud_doctor(
5135
5138
  credential_ref = ""
5136
5139
  provider_key = ""
5137
5140
  provider_name = ""
5141
+ mode_label = "local_byok" if execution_variant == "local_byok" else execution_mode
5138
5142
  if execution_mode == "cloud_byok":
5139
5143
  provider_name = str(constitution.get_setting("provider", "") or "").strip()
5140
5144
  provider_key = str(constitution.get_setting("provider_key", "") or "").strip()
5141
5145
  credential_ref = str(constitution.get_setting("credential_ref", "") or "").strip()
5142
5146
  if not provider_name or provider_name.lower() == "cloud":
5143
5147
  console.print(
5144
- "[red]cloud_byok[/red]: set an explicit `provider` "
5148
+ f"[red]{mode_label}[/red]: set an explicit `provider` "
5145
5149
  "(for example `provider: openai`)."
5146
5150
  )
5147
5151
  raise typer.Exit(code=1)
@@ -5155,7 +5159,7 @@ def _cloud_doctor(
5155
5159
  console.print(f"[green]credential_ref[/green]: {credential_ref}")
5156
5160
  else:
5157
5161
  console.print(
5158
- "[red]cloud_byok[/red]: set either `provider_key` (preferred) "
5162
+ f"[red]{mode_label}[/red]: set either `provider_key` (preferred) "
5159
5163
  "or `credential_ref` in refactor.config."
5160
5164
  )
5161
5165
  if dotenv is not None and not dotenv.found:
@@ -17,9 +17,10 @@ from typing import Callable
17
17
 
18
18
  from refactor_core.constitution import (
19
19
  CONFIG_FILENAME,
20
+ MANAGED_BLOCK_BEGIN,
21
+ MANAGED_BLOCK_END,
20
22
  MANAGED_KEYS,
21
23
  find_project_files,
22
- load_config,
23
24
  upsert_managed_block,
24
25
  )
25
26
  from refactor_core.execution_variant import normalize_execution_variant
@@ -38,33 +39,90 @@ def _local_config_path(project_root: Path) -> Path | None:
38
39
 
39
40
 
40
41
  def _current_managed_values(project_root: Path) -> dict:
41
- """Current values of the managed keys as parsed from refactor.config."""
42
+ """Current values from the raw managed block (no env interpolation)."""
42
43
  config_path = _local_config_path(project_root)
43
44
  if config_path is None:
44
45
  return {}
45
46
  try:
46
- settings = getattr(load_config(config_path), "settings", {}) or {}
47
- except Exception:
47
+ text = config_path.read_text(encoding="utf-8")
48
+ except OSError:
49
+ return {}
50
+ begin = text.find(MANAGED_BLOCK_BEGIN)
51
+ if begin == -1:
52
+ return {}
53
+ end = text.find(MANAGED_BLOCK_END, begin)
54
+ if end == -1:
48
55
  return {}
56
+ body = text[begin + len(MANAGED_BLOCK_BEGIN) : end]
49
57
  values: dict = {}
50
- for key in MANAGED_KEYS:
51
- raw = settings.get(key)
52
- if raw is None:
58
+ for line in body.splitlines():
59
+ stripped = line.strip()
60
+ if not stripped or stripped.startswith("#") or ":" not in stripped:
53
61
  continue
54
- text = str(raw).strip()
55
- if text:
56
- values[key] = text
62
+ key, raw = stripped.split(":", 1)
63
+ key = key.strip()
64
+ if key not in MANAGED_KEYS:
65
+ continue
66
+ value = raw.strip()
67
+ if value:
68
+ values[key] = value
57
69
  return values
58
70
 
59
71
 
72
+ _LOCAL_BYOK_ENV_DEFAULTS: dict[str, dict[str, str]] = {
73
+ "openai": {
74
+ "provider_key": "${OPENAI_API_KEY}",
75
+ "model_id": "${OPENAI_MODEL_ID}",
76
+ "base_url": "${OPENAI_BASE_URL}",
77
+ },
78
+ "anthropic": {
79
+ "provider_key": "${ANTHROPIC_API_KEY}",
80
+ "model_id": "${ANTHROPIC_MODEL_ID}",
81
+ },
82
+ "openrouter": {
83
+ "provider_key": "${OPENROUTER_API_KEY}",
84
+ "model_id": "${OPENROUTER_MODEL_ID}",
85
+ "base_url": "${OPENROUTER_BASE_URL}",
86
+ },
87
+ "nvidia": {
88
+ "provider_key": "${NVIDIA_API_KEY}",
89
+ "model_id": "${NVIDIA_MODEL_ID}",
90
+ "base_url": "${NVIDIA_BASE_URL}",
91
+ },
92
+ "azure_openai": {
93
+ "provider_key": "${AZURE_OPENAI_API_KEY}",
94
+ "model_id": "${AZURE_OPENAI_DEPLOYMENT}",
95
+ "base_url": "${AZURE_OPENAI_ENDPOINT}",
96
+ "api_version": "${AZURE_OPENAI_API_VERSION}",
97
+ },
98
+ "vertex_ai": {
99
+ "provider_key": "${GOOGLE_OAUTH_ACCESS_TOKEN}",
100
+ "model_id": "${VERTEX_MODEL_ID}",
101
+ "project": "${GOOGLE_CLOUD_PROJECT}",
102
+ "region": "${GOOGLE_CLOUD_LOCATION}",
103
+ },
104
+ "bedrock": {
105
+ "provider_key": "${AWS_BEARER_TOKEN_BEDROCK}",
106
+ "model_id": "${BEDROCK_MODEL_ID}",
107
+ "region": "${AWS_REGION}",
108
+ },
109
+ "ollama": {
110
+ "model_id": "${OLLAMA_MODEL_ID}",
111
+ "base_url": "${OLLAMA_BASE_URL}",
112
+ },
113
+ }
114
+
115
+
60
116
  def _desired_managed_fields(record: dict, current: dict, server_variant: str) -> dict:
61
117
  """Compute the managed-block fields from the server record (server-wins).
62
118
 
63
119
  When the server carries a remote provider (BYOK/managed set from the UI), the
64
- provider/model/credential come from the server and any local ``base_url`` is
65
- dropped. Otherwise (heuristic / terminal-set local_model, where the server has
66
- no provider) the local provider/model/base_url are preserved and only the
67
- variant is reconciled.
120
+ provider/model/credential come from the server. Provider-local extras
121
+ (``provider_key`` env token, region/project/base_url/api_version) are preserved
122
+ from the local managed block so sync does not strip local BYOK readiness.
123
+ Otherwise (heuristic / terminal-set local_model, where the server has no
124
+ provider) local provider-scoped values are preserved and only the variant is
125
+ reconciled.
68
126
  """
69
127
  provider = str(record.get("inference_provider") or "").strip()
70
128
  model_id = str(record.get("model_id") or "").strip()
@@ -77,8 +135,20 @@ def _desired_managed_fields(record: dict, current: dict, server_variant: str) ->
77
135
  fields["model_id"] = model_id
78
136
  if credential_ref:
79
137
  fields["credential_ref"] = credential_ref
138
+ # Preserve local provider-scoped values when server record doesn't carry
139
+ # them. This keeps local BYOK config/env wiring stable across syncs.
140
+ for key in ("model_id", "provider_key", "base_url", "region", "project", "api_version"):
141
+ if key not in fields and current.get(key):
142
+ fields[key] = current[key]
143
+ # Local BYOK should be immediately runnable from env after sync. Seed
144
+ # provider-specific env-token placeholders when missing.
145
+ if server_variant == "local_byok":
146
+ defaults = _LOCAL_BYOK_ENV_DEFAULTS.get(provider, {})
147
+ for key, value in defaults.items():
148
+ if not str(fields.get(key) or "").strip():
149
+ fields[key] = value
80
150
  else:
81
- for key in ("provider", "model_id", "base_url", "credential_ref"):
151
+ for key in ("provider", "model_id", "provider_key", "base_url", "region", "project", "api_version", "credential_ref"):
82
152
  if current.get(key):
83
153
  fields[key] = current[key]
84
154
  return fields
@@ -92,10 +162,11 @@ def sync_execution_variant_from_server(
92
162
  ) -> str | None:
93
163
  """Pull the server project's execution settings into the managed config block.
94
164
 
95
- Server-wins for the managed keys (execution_variant / provider / model_id /
96
- credential_ref). Secrets (``provider_key``) are never written -- they stay in
97
- the environment. Returns the applied variant when the local config changed,
98
- else ``None`` (already in sync, offline, unauthenticated, or unbound project).
165
+ Server-wins for mode/provider identity, while preserving provider-local env
166
+ wiring in the managed block. ``provider_key`` is written only as an env token
167
+ placeholder (for example ``${OPENAI_API_KEY}``) and never as a raw secret.
168
+ Returns the applied variant when the local config changed, else ``None``
169
+ (already in sync, offline, unauthenticated, or unbound project).
99
170
  """
100
171
  try:
101
172
  project_id = resolve_project_id(project_root)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: refactorai-cli
3
- Version: 0.7.15
3
+ Version: 0.7.17
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.2.23
11
+ Requires-Dist: refactorai-core>=3.2.24
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.2.23
5
+ refactorai-core>=3.2.24