Skip to content

Commit 6a130a9

Browse files
committed
Bare ucode: dedicated message when the feature is disabled
On bare `ucode`, a disabled feature previously showed the generic "no managed config found; using your local settings" line, because the launch read collapses FEATURE_DISABLED to an empty result. Re-read on the no-config path to tell the two apart and, when the feature is off, point the developer at a specific agent (`ucode codex` / `ucode claude`). Also promote is_feature_disabled to a public helper (now shared by cli, managed_wizard, and managed_config). Co-authored-by: Isaac
1 parent 525c086 commit 6a130a9

5 files changed

Lines changed: 15 additions & 15 deletions

File tree

‎src/ucode/cli.py‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
ensure_ai_gateway_v2,
4545
ensure_databricks_auth,
4646
ensure_pat_bearer,
47+
fetch_managed_coding_agent_configs,
4748
find_profile_name_for_host,
4849
get_databricks_profiles,
4950
get_databricks_token,
@@ -63,6 +64,7 @@
6364
)
6465
from ucode.managed_config import (
6566
get_model_recommendation,
67+
is_feature_disabled,
6668
load_managed_state,
6769
managed_agent_config_enabled,
6870
refresh_managed_config,
@@ -1853,6 +1855,14 @@ def _launch_managed_default(
18531855
"dry-run. Run `ucode` without --dry-run to pull your workspace's config first."
18541856
)
18551857
return
1858+
token = get_databricks_token(current, state.get("profile"))
1859+
_, reason = fetch_managed_coding_agent_configs(current, token)
1860+
if reason is not None and is_feature_disabled(reason):
1861+
print_warning(
1862+
"Managed coding agent config is not enabled for your workspace. Please launch "
1863+
"ucode with a specific agent, ex. `ucode codex` or `ucode claude`."
1864+
)
1865+
return
18561866
_print_no_managed_config_guidance(current, state.get("profile"))
18571867
return
18581868
# The budget tier can move the org to a cheaper agent, so it outranks the config's

‎src/ucode/managed_config.py‎

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -276,9 +276,7 @@ def get_model_recommendation(workspace: str, token: str) -> tuple[dict | None, s
276276
"""
277277
payload, reason = fetch_model_recommendation(workspace, token)
278278
if reason is not None:
279-
# A disabled feature means the workspace behaves as though no config existed: fall back to
280-
# the default model silently instead of warning about a budget we couldn't read.
281-
if _is_feature_disabled(reason):
279+
if is_feature_disabled(reason):
282280
return None, None
283281
return None, reason
284282
agent = AGENT_ENUM_TO_TOOL.get(_str(payload.get("recommended_agent")) or "")
@@ -314,11 +312,7 @@ def get_managed_config(workspace: str, token: str) -> tuple[dict | None, str | N
314312
"""
315313
configs, reason = fetch_managed_coding_agent_configs(workspace, token)
316314
if reason is not None:
317-
# A NOT_FOUND means the admin hasn't defined a config for this workspace — not a failure.
318-
# A FEATURE_DISABLED means the feature is switched off server-side; either way the workspace
319-
# has no config in effect, so both collapse to the authoritative (None, None) that clears a
320-
# previously cached config rather than a warning that would reapply it.
321-
if _is_not_found(reason) or _is_feature_disabled(reason):
315+
if _is_not_found(reason) or is_feature_disabled(reason):
322316
return None, None
323317
return None, reason
324318
if not configs:
@@ -335,7 +329,7 @@ def _is_not_found(reason: str) -> bool:
335329
return "http 404" in lowered or "not_found" in lowered
336330

337331

338-
def _is_feature_disabled(reason: str) -> bool:
332+
def is_feature_disabled(reason: str) -> bool:
339333
"""True when a read failure means the coding-agent config feature is switched off server-side.
340334
341335
The gateway gates the feature behind a SAFE flag; when it is off, reads fail with a

‎src/ucode/managed_wizard.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@
4040
update_coding_agent_config,
4141
)
4242
from ucode.managed_config import (
43-
_is_feature_disabled,
4443
get_managed_config,
44+
is_feature_disabled,
4545
load_managed_state,
4646
managed_state_workspace,
4747
save_managed_state,
@@ -874,7 +874,7 @@ def _require_feature_enabled(workspace: str, token: str) -> None:
874874
"""
875875
with spinner("Checking whether managed coding-agent config is enabled..."):
876876
_, reason = fetch_managed_coding_agent_configs(workspace, token)
877-
if reason is not None and _is_feature_disabled(reason):
877+
if reason is not None and is_feature_disabled(reason):
878878
raise RuntimeError(
879879
f"Managed coding-agent config is not enabled for {workspace}. Reach out to your "
880880
"account admin to enable the Enhanced Unity AI Gateway Preview."

‎tests/test_managed_config.py‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,6 @@ def test_not_found_is_treated_as_no_config(self, monkeypatch, not_found_reason):
186186
],
187187
)
188188
def test_feature_disabled_is_treated_as_no_config(self, monkeypatch, disabled_reason):
189-
# A FEATURE_DISABLED means the feature is switched off server-side — the workspace behaves as
190-
# though no config existed, so it collapses to (None, None) and clears any cached config.
191189
monkeypatch.setattr(
192190
mc_mod,
193191
"fetch_managed_coding_agent_configs",
@@ -512,7 +510,6 @@ def test_failed_read_surfaces_the_reason(self, monkeypatch):
512510
assert mc_mod.get_model_recommendation("https://w", "tok") == (None, "HTTP 500")
513511

514512
def test_feature_disabled_is_no_recommendation(self, monkeypatch):
515-
# A disabled feature reads as no recommendation, not a failure to warn the developer about.
516513
self._stub(
517514
monkeypatch, {}, reason='HTTP 400 Bad Request: {"error_code":"FEATURE_DISABLED"}'
518515
)

‎tests/test_managed_wizard.py‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,6 @@ def test_feature_enabled_passes(self):
227227
wizard._require_feature_enabled(WORKSPACE, "token") # must not raise
228228

229229
def test_transient_read_failure_is_allowed_through(self):
230-
# A non-FEATURE_DISABLED read failure must not block setup — the API still gates writes.
231230
with patch.object(
232231
wizard,
233232
"fetch_managed_coding_agent_configs",

0 commit comments

Comments
 (0)