mirror of
https://github.com/enricoros/big-AGI.git
synced 2026-05-10 21:50:14 -07:00
AI Inspector: memstored collapse state, and disable auto-snap
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
|
||||
import type { SxProps } from '@mui/joy/styles/types';
|
||||
import { Box, Card, Chip, Divider, Sheet, Typography } from '@mui/joy';
|
||||
@@ -10,6 +11,7 @@ import TimelapseIcon from '@mui/icons-material/Timelapse';
|
||||
|
||||
import type { AixClientDebugger } from './memstore-aix-client-debugger';
|
||||
import { AixDebuggerMeasurementsTable } from './AixDebuggerMeasurementsTable';
|
||||
import { useAixClientDebuggerStore } from './memstore-aix-client-debugger';
|
||||
|
||||
|
||||
const _styles = {
|
||||
@@ -79,14 +81,17 @@ export function AixDebuggerFrame(props: {
|
||||
frame: AixClientDebugger.Frame;
|
||||
}) {
|
||||
|
||||
// state
|
||||
const [showHeaders, setShowHeaders] = React.useState(true);
|
||||
const [showBody, setShowBody] = React.useState(true);
|
||||
const [showParticles, setShowParticles] = React.useState(false); // hide by default (heavy)
|
||||
// state: section open/close is kept in the debugger store so it persists across frame switches
|
||||
const { showHeaders, showBody, showParticles, toggleOpenState } = useAixClientDebuggerStore(useShallow(state => ({
|
||||
showHeaders: !!state.openStates.headers,
|
||||
showBody: !!state.openStates.body,
|
||||
showParticles: !!state.openStates.particles,
|
||||
toggleOpenState: state.toggleOpenState,
|
||||
})));
|
||||
|
||||
const handleToggleShowHeaders = React.useCallback(() => setShowHeaders(on => !on), []);
|
||||
const handleToggleShowBody = React.useCallback(() => setShowBody(on => !on), []);
|
||||
const handleToggleShowParticles = React.useCallback(() => setShowParticles(on => !on), []);
|
||||
const handleToggleShowHeaders = React.useCallback(() => toggleOpenState('headers'), [toggleOpenState]);
|
||||
const handleToggleShowBody = React.useCallback(() => toggleOpenState('body'), [toggleOpenState]);
|
||||
const handleToggleShowParticles = React.useCallback(() => toggleOpenState('particles'), [toggleOpenState]);
|
||||
|
||||
const { frame } = props;
|
||||
|
||||
|
||||
@@ -89,10 +89,14 @@ function _createAixClientDebuggerFrame(transport: AixClientDebugger.Transport, f
|
||||
|
||||
/// Store ///
|
||||
|
||||
export type AixDebuggerOpenKey = 'headers' | 'body' | 'particles';
|
||||
|
||||
interface AixClientDebuggerState {
|
||||
frames: AixClientDebugger.Frame[];
|
||||
activeFrameId: AixFrameId | null;
|
||||
maxFrames: number;
|
||||
// per-section open state for the current frame view
|
||||
openStates: Partial<Record<AixDebuggerOpenKey, true>>;
|
||||
// AIX force disable streaming for all requests (separate from per-model llmForceNoStream)
|
||||
aixNoStreaming: boolean;
|
||||
// AIX next payload override - JSON string injected into requests after validation
|
||||
@@ -111,6 +115,7 @@ interface AixClientDebuggerActions {
|
||||
setActiveFrame: (activeFrameId: AixFrameId | null) => void;
|
||||
setMaxFrames: (count: number) => void;
|
||||
clearHistory: () => void;
|
||||
toggleOpenState: (key: AixDebuggerOpenKey) => void;
|
||||
}
|
||||
|
||||
type AixClientDebuggerStore = AixClientDebuggerState & AixClientDebuggerActions;
|
||||
@@ -122,6 +127,7 @@ export const useAixClientDebuggerStore = create<AixClientDebuggerStore>((_set) =
|
||||
frames: [],
|
||||
activeFrameId: null,
|
||||
maxFrames: DEFAULT_FRAMES_COUNT,
|
||||
openStates: { headers: true, body: true }, // headers + body open by default; particles closed (heavy)
|
||||
aixNoStreaming: false,
|
||||
requestBodyOverrideJson: '',
|
||||
|
||||
@@ -135,11 +141,16 @@ export const useAixClientDebuggerStore = create<AixClientDebuggerStore>((_set) =
|
||||
// stealing focus from the main conversation request
|
||||
const isBackgroundOperation = (BACKGROUND_CONTEXT_NAMES as readonly string[]).includes(initialContext.contextName);
|
||||
|
||||
_set((state) => ({
|
||||
frames: [newFrame, ...state.frames].slice(0, state.maxFrames),
|
||||
// Auto-select if: no active frame yet, OR this is not a background operation
|
||||
activeFrameId: (!state.activeFrameId || !isBackgroundOperation) ? newFrame.id : state.activeFrameId,
|
||||
}));
|
||||
_set(({ activeFrameId, frames, maxFrames }) => {
|
||||
// Sticky selection: only snap to the new frame if the user was following latest (nothing selected, or the current selection is the previous top frame).
|
||||
const previousLatestId = frames[0]?.id ?? null;
|
||||
const isFollowingLatest = activeFrameId === null || activeFrameId === previousLatestId;
|
||||
const shouldAutoSelect = isFollowingLatest && !isBackgroundOperation;
|
||||
return {
|
||||
frames: [newFrame, ...(frames)].slice(0, maxFrames),
|
||||
activeFrameId: shouldAutoSelect ? newFrame.id : activeFrameId,
|
||||
};
|
||||
});
|
||||
|
||||
return newFrame.id;
|
||||
},
|
||||
@@ -193,6 +204,13 @@ export const useAixClientDebuggerStore = create<AixClientDebuggerStore>((_set) =
|
||||
activeFrameId: null,
|
||||
}),
|
||||
|
||||
toggleOpenState: (key) => _set(state => {
|
||||
const next = { ...state.openStates };
|
||||
if (next[key]) delete next[key];
|
||||
else next[key] = true;
|
||||
return { openStates: next };
|
||||
}),
|
||||
|
||||
}));
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user