mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-19 10:02:16 +00:00
The dashboard becomes a machine-level management surface with one write-target selector, replacing per-profile dashboard fragmentation. Backend: - profile param (query or body) on /api/config (get/put/raw), /api/env (get/put/delete/reveal), /api/mcp/servers (list/add/remove/test/enabled), /api/mcp/catalog (list/install), /api/model/info, /api/model/set — all scoped through the existing _profile_scope() context manager - model/set restructured: expensive-model warning (await) runs before the scope; the config write runs sync inside the scope in a worker thread - MCP catalog installs + git-bootstrap entries spawn 'hermes -p <profile>' - chat PTY: ?profile= on /api/pty points the child's HERMES_HOME at the profile dir (its own gateway subprocess, config/skills/memory/state.db all profile-bound); in-process gateway attach skipped when scoped CLI launch unification: - '<profile> dashboard' routes to the machine dashboard: attach (open browser at ?profile=) when one is listening, else re-exec pinned to the default profile with --open-profile preselecting the launcher - --isolated preserves the old dedicated per-profile server behavior - start_server(initial_profile=...) appends ?profile= to the auto-open URL Frontend: - ProfileProvider + sidebar ProfileSwitcher: ONE global selector, URL- persisted (?profile=), mirrored into fetchJSON which auto-appends the param to the scoped endpoint families (explicit params win) - app-wide amber banner names the managed profile - SkillsPage's page-local selector (from the skills-scoping PR) folded into the global context — single source of truth - ChatPage threads the scope into the PTY WS URL; switching profiles remounts the terminal into a fresh scoped session Omitted profile keeps legacy behavior everywhere.
27 lines
985 B
TypeScript
27 lines
985 B
TypeScript
import { Users } from "lucide-react";
|
|
import { useProfileScope } from "@/contexts/useProfileScope";
|
|
import { useI18n } from "@/i18n";
|
|
|
|
/**
|
|
* App-wide amber banner shown while the global switcher targets a profile
|
|
* OTHER than the dashboard's own — every management write (config, keys,
|
|
* skills, MCPs, model) and new Chat sessions land in that profile.
|
|
*/
|
|
export function ProfileScopeBanner() {
|
|
const { profile, currentProfile } = useProfileScope();
|
|
const { t } = useI18n();
|
|
|
|
if (!profile || profile === currentProfile) return null;
|
|
|
|
return (
|
|
<div className="flex items-center gap-2 border-b border-amber-500/40 bg-amber-500/10 px-4 py-1.5 text-xs text-amber-300">
|
|
<Users className="h-3.5 w-3.5 shrink-0" />
|
|
<span>
|
|
{(
|
|
t.app.managingProfileBanner ??
|
|
"Managing profile “{name}” — config, keys, skills, MCPs, model, and new chats apply to that profile."
|
|
).replace("{name}", profile)}
|
|
</span>
|
|
</div>
|
|
);
|
|
}
|