mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-30 11:52:04 +00:00
fix(tui): restart dashboard chat on idle exit hotkeys
This commit is contained in:
parent
a64fc490fe
commit
12dfcfdf73
13 changed files with 207 additions and 18 deletions
|
|
@ -74,9 +74,15 @@ interface ChatSidebarProps {
|
|||
/** Management profile from the dashboard switcher — scopes session.create. */
|
||||
profile?: string;
|
||||
className?: string;
|
||||
onDashboardNewSessionRequest?: () => void;
|
||||
}
|
||||
|
||||
export function ChatSidebar({ channel, profile, className }: ChatSidebarProps) {
|
||||
export function ChatSidebar({
|
||||
channel,
|
||||
profile,
|
||||
className,
|
||||
onDashboardNewSessionRequest,
|
||||
}: ChatSidebarProps) {
|
||||
// `version` bumps on reconnect; gw is derived so we never call setState
|
||||
// for it inside an effect (React 19's set-state-in-effect rule). The
|
||||
// counter is the dependency on purpose — it's not read in the memo body,
|
||||
|
|
@ -112,9 +118,12 @@ export function ChatSidebar({ channel, profile, className }: ChatSidebarProps) {
|
|||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
setSessionId(null);
|
||||
setInfo({});
|
||||
setError(null);
|
||||
queueMicrotask(() => {
|
||||
if (cancelled) return;
|
||||
setSessionId(null);
|
||||
setInfo({});
|
||||
setError(null);
|
||||
});
|
||||
const offState = gw.onState(setState);
|
||||
|
||||
const offSessionInfo = gw.on<SessionInfo>("session.info", (ev) => {
|
||||
|
|
@ -233,7 +242,9 @@ export function ChatSidebar({ channel, profile, className }: ChatSidebarProps) {
|
|||
|
||||
const { type, payload } = frame.params;
|
||||
|
||||
if (type === "tool.start") {
|
||||
if (type === "dashboard.new_session_requested") {
|
||||
onDashboardNewSessionRequest?.();
|
||||
} else if (type === "tool.start") {
|
||||
const p = payload as
|
||||
| { tool_id?: string; name?: string; context?: string }
|
||||
| undefined;
|
||||
|
|
@ -309,7 +320,7 @@ export function ChatSidebar({ channel, profile, className }: ChatSidebarProps) {
|
|||
unmounting = true;
|
||||
ws?.close();
|
||||
};
|
||||
}, [channel, version]);
|
||||
}, [channel, onDashboardNewSessionRequest, version]);
|
||||
|
||||
const reconnect = useCallback(() => {
|
||||
setError(null);
|
||||
|
|
|
|||
|
|
@ -153,6 +153,15 @@ export default function ChatPage({ isActive = true }: { isActive?: boolean }) {
|
|||
setBanner(null);
|
||||
setReconnectNonce((n) => n + 1);
|
||||
}, []);
|
||||
const startFreshDashboardChat = useCallback(() => {
|
||||
const next = new URLSearchParams(searchParams);
|
||||
|
||||
next.delete("resume");
|
||||
setSearchParams(next, { replace: true });
|
||||
setSessionEnded(false);
|
||||
setBanner(null);
|
||||
setReconnectNonce((n) => n + 1);
|
||||
}, [searchParams, setSearchParams]);
|
||||
// Raw state for the mobile side-sheet + a derived value that force-
|
||||
// closes whenever the chat tab isn't active. The *derived* value is
|
||||
// what side-effects (body-scroll lock, keydown listener, portal render)
|
||||
|
|
@ -881,7 +890,11 @@ export default function ChatPage({ isActive = true }: { isActive?: boolean }) {
|
|||
"border-t border-current/10",
|
||||
)}
|
||||
>
|
||||
<ChatSidebar channel={channel} profile={scopedProfile} />
|
||||
<ChatSidebar
|
||||
channel={channel}
|
||||
profile={scopedProfile}
|
||||
onDashboardNewSessionRequest={startFreshDashboardChat}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</>,
|
||||
|
|
@ -967,7 +980,11 @@ export default function ChatPage({ isActive = true }: { isActive?: boolean }) {
|
|||
className="flex min-h-0 shrink-0 flex-col overflow-hidden lg:h-full lg:w-80"
|
||||
>
|
||||
<div className="min-h-0 flex-1 overflow-hidden">
|
||||
<ChatSidebar channel={channel} profile={scopedProfile} />
|
||||
<ChatSidebar
|
||||
channel={channel}
|
||||
profile={scopedProfile}
|
||||
onDashboardNewSessionRequest={startFreshDashboardChat}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue