fix(editor): stabilize image generation, layer editing and controls (#6992)

* fix(editor): stabilize image workflows and editing controls

* docs(editor): add desktop and mobile visual validation evidence

* fix(editor): synchronize quick edit model events and register imagePreferences in test coordinator

* fix(settings): enforce authoritative global image-gen policy and non-admin preference persistence

- Enforce authoritative administrator global image_gen_enabled disable in get_user_setting, do_generate_image, and image_editing_provider_available, preventing non-admin user preference overrides while preserving user-disabled opt-outs and can_generate_images privilege checks across direct, gallery, and editor paths.
- Filter non-admin preference persistence in saveImagePreferences to user preference keys only (image_model, image_edit_model, image_quality), preventing global policy toggles from leaking into user preferences.
- Return accurate 200 OK Response from saveImagePreferences after fallback persistence succeeds so settings UI displays 'Saved' instead of false 403 error, while retaining visibility of real errors.
- Load per-user preferences via readImagePreferences in initImageSettings so non-admin selections persist and display correctly after page reload.
- Clear per-user model preferences on successful admin save (POST /api/auth/settings) via PUT /api/prefs/{key} with value: null to prevent stale per-user preferences from shadowing updated global settings.
- Support clearing keys in PUT /api/prefs/{key} when value is null.
- Add comprehensive Python regression tests for global-disabled/user-enabled, global-enabled/user-disabled, and authorized generation, plus Node and browser regression tests for non-admin persistence, toggle isolation, reload, and admin clearing.

* fix(settings): invalidate shared appConfig cache near auth settings write

* fix(test): isolate test_tool_policy unit suite from external model endpoint state

* fix(test): isolate web_fetch failure regression from contextual follow-up heuristics

* fix(test): isolate test_tool_policy from cross-test approval gate state

Ensure _patch_loop_basics disables TOOL_APPROVAL_GATE_ENABLED so routing tests in test_tool_policy run in the intended opt-out posture even when prior tests populate DATA_DIR with skills or untrusted context. Remove unnecessary forced_tools and contextual web mock workarounds.

* fix(settings): isolate non-admin image toggle and surface preference cleanup errors

- Restrict image generation availability toggle to admin users in imageModels.js, disabling the switch for non-admins and reverting unauthorized changes with an explicit message.
- Separate non-admin image model preference saves from global toggle updates.
- Track preference cleanup results on admin save in imagePreferences.js, propagating cleanup failures instead of ignoring them.
- Require valid preference keys on 403 fallback so toggle-only attempts reject cleanly.
- Add /api/prefs route mock to test_image_model_settings_sync_both_directions_and_survive_reopening.
- Add regression coverage for admin cleanup failures and non-admin toggle rejection.

* fix(settings): reconcile admin toggle on partial cleanup failure and report errors

- In imagePreferences.js, distinguish pre-persistence failures from post-save cleanup failures using err.globalSaved and err.phase.

- In imagePreferences.js, notify listeners of global policy updates on partial success before propagating cleanup failure.

- In imageModels.js, retain the persisted target state on admin toggle when global persistence succeeds but cleanup fails.

- In imageModels.js, reconcile admin toggle with authoritative server state via readImagePreferences() after ambiguous or partial failures.

- In imageModels.js, report partial success accurately without suppressing preference cleanup error messages.

- Add regression coverage in test_settings_save_response_ok_js.py for cleanup HTTP 500, cleanup network rejection, successful cleanup, and failed global POST.

---------

Co-authored-by: pewdiepie-archdaemon <pewdiepie-archdaemon@users.noreply.github.com>
Co-authored-by: Alexandre Teixeira <general@alexandreteixeira.dev>
This commit is contained in:
PewDiePie
2026-11-01 02:56:46 +00:00
committed by GitHub
co-authored by pewdiepie-archdaemon Alexandre Teixeira
parent 5353241743
commit 39303f19cd
56 changed files with 3384 additions and 278 deletions
+16 -1
View File
@@ -46,6 +46,7 @@ DEFAULT_SETTINGS = {
"agent_email_confirm": True,
"image_gen_enabled": False,
"image_model": "",
"image_edit_model": "",
"image_quality": "medium",
# Optional editor planner/caption endpoints. Empty uses configured chat
# fallback without probing a developer-specific host.
@@ -294,7 +295,7 @@ def is_setting_overridden(key: str) -> bool:
# resolved by FastAPI deps; an empty/None owner falls through to the global.
_PER_USER_KEYS = {
"vision_model", "vision_enabled", "vision_model_fallbacks",
"image_model", "image_gen_enabled", "image_quality",
"image_model", "image_edit_model", "image_gen_enabled", "image_quality",
# Default chat endpoint / model — without per-user resolution every new
# account inherited whatever the most-recent admin picked, which then
# got injected into the chat composer on first open.
@@ -313,6 +314,20 @@ def get_user_setting(key: str, owner: str = "", default: Any = None) -> Any:
Falls back gracefully if the prefs module can't be imported (cycle/early
boot) — admin-global settings keep working.
"""
if key == "image_gen_enabled":
global_val = get_setting("image_gen_enabled", default if default is not None else False)
if not global_val:
return False
if owner:
try:
from routes.prefs_routes import _load_for_user
prefs = _load_for_user(owner) or {}
if "image_gen_enabled" in prefs and prefs["image_gen_enabled"] is not None:
return bool(prefs["image_gen_enabled"])
except Exception:
pass
return bool(global_val)
if owner and key in _PER_USER_KEYS:
try:
from routes.prefs_routes import _load_for_user