mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-08 03:01:47 +00:00
Follow latest child session on dashboard resume
This commit is contained in:
parent
e9685a5cf7
commit
b12a5a72b0
3 changed files with 134 additions and 3 deletions
|
|
@ -49,6 +49,10 @@ export const api = {
|
|||
fetchJSON<PaginatedSessions>(`/api/sessions?limit=${limit}&offset=${offset}`),
|
||||
getSessionMessages: (id: string) =>
|
||||
fetchJSON<SessionMessagesResponse>(`/api/sessions/${encodeURIComponent(id)}/messages`),
|
||||
getSessionLatestDescendant: (id: string) =>
|
||||
fetchJSON<SessionLatestDescendantResponse>(
|
||||
`/api/sessions/${encodeURIComponent(id)}/latest-descendant`,
|
||||
),
|
||||
deleteSession: (id: string) =>
|
||||
fetchJSON<{ ok: boolean }>(`/api/sessions/${encodeURIComponent(id)}`, {
|
||||
method: "DELETE",
|
||||
|
|
@ -373,6 +377,14 @@ export interface SessionInfo {
|
|||
input_tokens: number;
|
||||
output_tokens: number;
|
||||
preview: string | null;
|
||||
parent_session_id?: string | null;
|
||||
}
|
||||
|
||||
export interface SessionLatestDescendantResponse {
|
||||
requested_session_id: string;
|
||||
session_id: string;
|
||||
path: string[];
|
||||
changed: boolean;
|
||||
}
|
||||
|
||||
export interface PaginatedSessions {
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import { useSearchParams } from "react-router-dom";
|
|||
import { ChatSidebar } from "@/components/ChatSidebar";
|
||||
import { usePageHeader } from "@/contexts/usePageHeader";
|
||||
import { useI18n } from "@/i18n";
|
||||
import { api } from "@/lib/api";
|
||||
import { PluginSlot } from "@/plugins";
|
||||
|
||||
function buildWsUrl(
|
||||
|
|
@ -111,7 +112,7 @@ export default function ChatPage({ isActive = true }: { isActive?: boolean }) {
|
|||
// the moment `isActive` flips back to true (display:none → display:flex
|
||||
// collapses the host's box, so ResizeObserver never fires on return).
|
||||
const syncMetricsRef = useRef<(() => void) | null>(null);
|
||||
const [searchParams] = useSearchParams();
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
// Lazy-init: the missing-token check happens at construction so the effect
|
||||
// body doesn't have to setState (React 19's set-state-in-effect rule).
|
||||
const [banner, setBanner] = useState<string | null>(() =>
|
||||
|
|
@ -153,8 +154,33 @@ export default function ChatPage({ isActive = true }: { isActive?: boolean }) {
|
|||
// Sessions page relies on `/chat?resume=<id>` changing at runtime, so we must
|
||||
// treat the current resume target as part of the PTY identity and rebuild the
|
||||
// terminal session when it changes.
|
||||
const resumeId = searchParams.get("resume");
|
||||
const channel = useMemo(() => generateChannelId(), [resumeId]);
|
||||
const resumeParam = searchParams.get("resume");
|
||||
const channel = useMemo(() => generateChannelId(), [resumeParam]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!resumeParam) return;
|
||||
|
||||
let cancelled = false;
|
||||
|
||||
api
|
||||
.getSessionLatestDescendant(resumeParam)
|
||||
.then((res) => {
|
||||
if (cancelled || !res.session_id || res.session_id === resumeParam) {
|
||||
return;
|
||||
}
|
||||
|
||||
const next = new URLSearchParams(searchParams);
|
||||
next.set("resume", res.session_id);
|
||||
setSearchParams(next, { replace: true });
|
||||
})
|
||||
.catch(() => {
|
||||
// Best-effort: old servers or missing sessions should not block chat.
|
||||
});
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [resumeParam, searchParams, setSearchParams]);
|
||||
|
||||
useEffect(() => {
|
||||
const mql = window.matchMedia("(max-width: 1023px)");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue