agent ui: add a clickable new-session menu entry
Same gap #4611 fixed for logout: the Preact rewrite's StatusChips menu never picked up new-session as a click path, only /new-session typed twice into the terminal. postNewSession already existed in termActions.ts. Wire it into the status menu with the same arm-then- confirm click pattern logout/cancel-turn already use. Closes #4612
This commit is contained in:
parent
3b8df27dcf
commit
9a444c27fa
2 changed files with 43 additions and 2 deletions
|
|
@ -27,7 +27,11 @@ import { fmtAge, fmtTokens } from "./lib/format.js";
|
||||||
import { resolveDashboardBase } from "./lib/dashboardBase.js";
|
import { resolveDashboardBase } from "./lib/dashboardBase.js";
|
||||||
import { submitPauseResume } from "./lib/pauseAction.js";
|
import { submitPauseResume } from "./lib/pauseAction.js";
|
||||||
import { postModel, postEffort } from "./lib/modelEffort.js";
|
import { postModel, postEffort } from "./lib/modelEffort.js";
|
||||||
import { postCancelTurn, postLogout } from "./lib/termActions.js";
|
import {
|
||||||
|
postCancelTurn,
|
||||||
|
postLogout,
|
||||||
|
postNewSession,
|
||||||
|
} from "./lib/termActions.js";
|
||||||
import type { TokenUsage } from "./types.js";
|
import type { TokenUsage } from "./types.js";
|
||||||
|
|
||||||
type OpenPanel = "inbox" | "todos" | null;
|
type OpenPanel = "inbox" | "todos" | null;
|
||||||
|
|
@ -225,6 +229,7 @@ export function Root() {
|
||||||
onTogglePause={() => {}}
|
onTogglePause={() => {}}
|
||||||
thinking={false}
|
thinking={false}
|
||||||
onCancelTurn={() => Promise.resolve()}
|
onCancelTurn={() => Promise.resolve()}
|
||||||
|
onNewSession={() => Promise.resolve()}
|
||||||
onLogout={() => Promise.resolve()}
|
onLogout={() => Promise.resolve()}
|
||||||
/>
|
/>
|
||||||
</Header>
|
</Header>
|
||||||
|
|
@ -332,6 +337,15 @@ export function Root() {
|
||||||
refresh();
|
refresh();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
onNewSession={() =>
|
||||||
|
postNewSession().then((r) => {
|
||||||
|
if (!r.ok)
|
||||||
|
liveStreamRef.current?.pushNote(
|
||||||
|
`✗ /new-session failed${r.detail ? ": " + r.detail : ""}`,
|
||||||
|
);
|
||||||
|
refresh();
|
||||||
|
})
|
||||||
|
}
|
||||||
onLogout={() =>
|
onLogout={() =>
|
||||||
postLogout().then((r) => {
|
postLogout().then((r) => {
|
||||||
if (!r.ok)
|
if (!r.ok)
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,12 @@ export interface StatusChipsProps {
|
||||||
lastTurnLabel?: string;
|
lastTurnLabel?: string;
|
||||||
thinking: boolean;
|
thinking: boolean;
|
||||||
onCancelTurn: () => Promise<void>;
|
onCancelTurn: () => Promise<void>;
|
||||||
|
/** Drops all prior `--continue` context and starts fresh. Always
|
||||||
|
* offered, same as logout — the old app.js overflow menu had it as
|
||||||
|
* an unconditional click target too, this is just the click path
|
||||||
|
* catching up to what `/new-session` already does. See
|
||||||
|
* `termActions.ts`'s `postNewSession`. */
|
||||||
|
onNewSession: () => Promise<void>;
|
||||||
/** Rotates OAuth creds + parks the agent in needs-login. Always
|
/** Rotates OAuth creds + parks the agent in needs-login. Always
|
||||||
* offered (unlike cancel-turn, not gated on `thinking`) — the old
|
* offered (unlike cancel-turn, not gated on `thinking`) — the old
|
||||||
* page's overflow menu had it unconditionally too. See
|
* page's overflow menu had it unconditionally too. See
|
||||||
|
|
@ -119,6 +125,7 @@ function StatusMenu({
|
||||||
onTogglePause,
|
onTogglePause,
|
||||||
thinking,
|
thinking,
|
||||||
onCancelTurn,
|
onCancelTurn,
|
||||||
|
onNewSession,
|
||||||
onLogout,
|
onLogout,
|
||||||
}: Pick<
|
}: Pick<
|
||||||
StatusChipsProps,
|
StatusChipsProps,
|
||||||
|
|
@ -129,16 +136,19 @@ function StatusMenu({
|
||||||
| "onTogglePause"
|
| "onTogglePause"
|
||||||
| "thinking"
|
| "thinking"
|
||||||
| "onCancelTurn"
|
| "onCancelTurn"
|
||||||
|
| "onNewSession"
|
||||||
| "onLogout"
|
| "onLogout"
|
||||||
>) {
|
>) {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [confirmCancel, setConfirmCancel] = useState(false);
|
const [confirmCancel, setConfirmCancel] = useState(false);
|
||||||
|
const [confirmNewSession, setConfirmNewSession] = useState(false);
|
||||||
const [confirmLogout, setConfirmLogout] = useState(false);
|
const [confirmLogout, setConfirmLogout] = useState(false);
|
||||||
const anchorRef = useRef<HTMLDivElement>(null);
|
const anchorRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
function close() {
|
function close() {
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
setConfirmCancel(false);
|
setConfirmCancel(false);
|
||||||
|
setConfirmNewSession(false);
|
||||||
setConfirmLogout(false);
|
setConfirmLogout(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -153,7 +163,12 @@ function StatusMenu({
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Always offered, regardless of turn state — same as the old overflow
|
// Always offered, regardless of turn state — same as the old overflow
|
||||||
// menu's unconditional 🔓 logout entry.
|
// menu's unconditional ↻ new-session and 🔓 logout entries.
|
||||||
|
options.push({
|
||||||
|
value: "new-session",
|
||||||
|
label: confirmNewSession ? "↻ click again to confirm" : "↻ new session",
|
||||||
|
danger: true,
|
||||||
|
});
|
||||||
options.push({
|
options.push({
|
||||||
value: "logout",
|
value: "logout",
|
||||||
label: confirmLogout ? "🔓 click again to confirm" : "🔓 logout",
|
label: confirmLogout ? "🔓 click again to confirm" : "🔓 logout",
|
||||||
|
|
@ -189,6 +204,16 @@ function StatusMenu({
|
||||||
close();
|
close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (value === "new-session") {
|
||||||
|
// Same arm-then-fire shape as cancel-turn/logout.
|
||||||
|
if (!confirmNewSession) {
|
||||||
|
setConfirmNewSession(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
onNewSession();
|
||||||
|
close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
// value === 'logout': same arm-then-fire shape as cancel-turn.
|
// value === 'logout': same arm-then-fire shape as cancel-turn.
|
||||||
if (!confirmLogout) {
|
if (!confirmLogout) {
|
||||||
setConfirmLogout(true);
|
setConfirmLogout(true);
|
||||||
|
|
@ -222,6 +247,7 @@ export function StatusChips({
|
||||||
lastTurnLabel,
|
lastTurnLabel,
|
||||||
thinking,
|
thinking,
|
||||||
onCancelTurn,
|
onCancelTurn,
|
||||||
|
onNewSession,
|
||||||
onLogout,
|
onLogout,
|
||||||
}: StatusChipsProps) {
|
}: StatusChipsProps) {
|
||||||
return (
|
return (
|
||||||
|
|
@ -234,6 +260,7 @@ export function StatusChips({
|
||||||
onTogglePause={onTogglePause}
|
onTogglePause={onTogglePause}
|
||||||
thinking={thinking}
|
thinking={thinking}
|
||||||
onCancelTurn={onCancelTurn}
|
onCancelTurn={onCancelTurn}
|
||||||
|
onNewSession={onNewSession}
|
||||||
onLogout={onLogout}
|
onLogout={onLogout}
|
||||||
/>
|
/>
|
||||||
<Picker
|
<Picker
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue