feat(profiles): first-class profile switching — phase 0 baseline port (#820)

* feat(profiles): make profile switching actually scope the app (issue #781 follow-up)

* fix(profiles): inherit connection token when switching to same-dashboard profile (issue #781 follow-up)

* fix(chat): reset open session on profile switch + prefill login profile (desktop parity)

* fix(ws): inject profile into profile-scoped RPC params so chat follows the selected profile

* test(chat): de-poison SlashCommandDispatchRpcTest (drop static Dispatchers mock)

mockkStatic(Dispatchers::class) + a stubbed Dispatchers.IO bleeds JVM-wide and
breaks later classes in suite order (CI 2026-08-06: COMMAND_DISPATCH captures
cross-wired → ComparisonFailure on lower stack PRs). ChatViewModel gains an
injected ioDispatcher (38 sites); the slash test constructs the VM with the
test dispatcher so the IO stub is unnecessary.

---------

Co-authored-by: M57 <hy4ri@users.noreply.github.com>
This commit is contained in:
M57andM57 authored and GitHub committed 2026-08-06 15:06:28 +03:00
1 parent e56d4c9bfa
commit 75ac0c4790
14 files changed
+579 -56

No files matched your search

@@ -19,19 +19,20 @@ import okhttp3.Response
* - If the URL already carries an explicit `profile=` query, leave it
* untouched — explicit beats global.
* - Only the endpoint families below honor `?profile=` on the backend;
* everything else (ops, pairing, cron, profiles themselves) is
* machine-global or self-scoped and must NOT be rewritten.
* everything else (ops, pairing, profiles themselves) is machine-global
* or self-scoped and must NOT be rewritten. Cron, sessions and plugins
* are profile-scoped on the backend (`/api/cron/jobs?profile=`,
* `/api/sessions?profile=`, plugin REST) and ARE rewritten here so
* switching profiles actually switches what the app shows.
*/
object ProfileScopeInterceptor : Interceptor {
private val PROFILE_SCOPED_PREFIXES =
listOf(
"/api/status",
"/api/gateway",
"/api/analytics",
"/api/skills",
"/api/tools/toolsets",
"/api/config",
"/api/cron",
"/api/env",
"/api/gateway",
"/api/mcp",
"/api/messaging/platforms",
"/api/messaging/telegram/onboarding",
@@ -41,6 +42,11 @@ object ProfileScopeInterceptor : Interceptor {
"/api/model/auxiliary",
"/api/model/moa",
"/api/model/options",
"/api/plugins",
"/api/sessions",
"/api/skills",
"/api/status",
"/api/tools/toolsets",
)
/**