You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
add shared session preference APIs and server-side in-memory state so desktop, Feishu, and WeChat read and update the same agent, model, variant, and approval settings
update desktop preference and permission handling to react to session preference change events and keep approval state in sync across clients
move Feishu and WeChat session overrides onto shared session preferences for consistent cross-client behavior
This PR replaces per-client in-memory preference state (model, agent, variant, approval) with a shared server-side SessionPreference store, enabling cross-client sync for desktop, Feishu, and WeChat. Overall direction is good, but there are several issues worth addressing:
Medium — WeChat _cmd_set_model uses fire-and-forget asyncio.create_task (aether_wechat_agent.py ~line 842): Unlike _cmd_agent, _cmd_variant, and _cmd_approval which all await _set_preference(...), the model setter dispatches the HTTP call via asyncio.get_event_loop().create_task(...) and immediately returns success. If the PUT fails, the user sees "✅ 已切换模型" but the preference was never persisted. This should await like the other commands.
Medium — addPreferenceMethods does not check HTTP status (packages/app/src/utils/server.ts): Both get and set call resp.json() without checking resp.ok. A 4xx/5xx response will parse error JSON as if it were valid preference data, and the caller gets a misleading { data: ... } wrapper. At minimum, check resp.ok and throw or return null on failure.
Low — _approval_mode is now dead code (aether_wechat_agent.py): It unconditionally returns "ask" and is no longer called anywhere meaningful — the actual approval check in _auto_approve was rewritten to use the preference API directly. Consider removing it to avoid confusion.
Low — addPreferenceMethods bypasses SDK middleware (packages/app/src/utils/server.ts): These methods use raw fetch with manually constructed Authorization headers, duplicating auth logic from createSdkForServer. This is fragile — any future change to the auth flow (e.g., token refresh, header format) must be updated in two places. Consider routing through the SDK client or at least extracting a shared header builder.
Low — Race potential in desktop preference sync (packages/app/src/context/local.tsx): syncPreferenceToServer fires on every setSaved call and the SSE listener writes back into saved on every session.preference.changed event. With a rapid sequence of local changes and server echoes, there's a feedback loop risk: a local write -> server sync -> SSE echo -> re-set into saved. The .catch(() => {}) on both sides silently swallows errors, making this hard to debug if it manifests. Consider adding a guard (e.g., comparing current state before writing back from SSE) to break potential echo loops.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #265