diff --git a/src/apps/settings-modal/SettingsModal.tsx b/src/apps/settings-modal/SettingsModal.tsx
index 1086724f4..28749de7d 100644
--- a/src/apps/settings-modal/SettingsModal.tsx
+++ b/src/apps/settings-modal/SettingsModal.tsx
@@ -199,7 +199,7 @@ export function SettingsModal(props: {
const { setTab } = props;
const isToolsTab = props.tab === 'tools';
- const enableAixDebugger = Is.Deployment.Localhost;
+ const enableAixDebuggerDialog = true;
const handleSetTab = React.useCallback((_event: any, value: string | number | null) => {
setTab((value ?? undefined) as PreferencesTabId);
@@ -221,12 +221,12 @@ export function SettingsModal(props: {
{!isMobile && !isToolsTab && } sx={darkModeToggleButtonSx}>
Shortcuts
}
+ {isToolsTab && } sx={darkModeToggleButtonSx}>
+ AI Inspector
+ }
{isToolsTab && } sx={darkModeToggleButtonSx}>
Logs Viewer
}
- {isToolsTab && } sx={darkModeToggleButtonSx}>
- AIX Debugger
- }
}
sx={_styles.modal}
diff --git a/src/common/stores/store-ui.ts b/src/common/stores/store-ui.ts
index de6c33c2f..ff6d67bcd 100644
--- a/src/common/stores/store-ui.ts
+++ b/src/common/stores/store-ui.ts
@@ -4,6 +4,7 @@ import { persist } from 'zustand/middleware';
import type { ContentScaling, UIComplexityMode } from '~/common/app.theme';
import { BrowserLang } from '~/common/util/pwaUtils';
+import { Release } from '~/common/app.release';
// UI Preferences
@@ -47,6 +48,11 @@ interface UIPreferencesStore {
composerQuickButton: 'off' | 'call' | 'beam';
setComposerQuickButton: (composerQuickButton: 'off' | 'call' | 'beam') => void;
+ // Advanced features
+
+ aixInspector: boolean;
+ toggleAixInspector: () => void;
+
// UI Dismissals
dismissals: Record;
@@ -103,6 +109,11 @@ export const useUIPreferencesStore = create()(
composerQuickButton: 'beam',
setComposerQuickButton: (composerQuickButton: 'off' | 'call' | 'beam') => set({ composerQuickButton }),
+ // Advanced features
+
+ aixInspector: false,
+ toggleAixInspector: () => set((state) => ({ aixInspector: !state.aixInspector })),
+
// UI Dismissals
dismissals: {},
@@ -133,6 +144,13 @@ export const useUIPreferencesStore = create()(
*/
version: 3,
+ partialize: (state) => {
+ if (Release.IsNodeDevBuild) return state; // in dev, persist everything
+ // In production, exclude aixInspector from persistence
+ const { aixInspector, ...rest } = state;
+ return rest;
+ },
+
migrate: (state: any, fromVersion: number): UIPreferencesStore => {
// 1: rename 'enterToSend' to 'enterIsNewline' (flip the meaning)
@@ -169,6 +187,10 @@ export function useUIContentScaling(): ContentScaling {
return useUIPreferencesStore((state) => state.contentScaling);
}
+export function getAixInspector(): boolean {
+ return useUIPreferencesStore.getState().aixInspector;
+}
+
export function useUIIsDismissed(key: string | null): boolean | undefined {
return useUIPreferencesStore((state) => !key ? undefined : Boolean(state.dismissals[key]));
diff --git a/src/modules/aix/client/aix.client.ts b/src/modules/aix/client/aix.client.ts
index a9a67082d..7cc07a5e8 100644
--- a/src/modules/aix/client/aix.client.ts
+++ b/src/modules/aix/client/aix.client.ts
@@ -10,7 +10,8 @@ import { DMetricsChatGenerate_Lg, metricsChatGenerateLgToMd, metricsComputeChatG
import { DModelParameterValues, getAllModelParameterValues } from '~/common/stores/llms/llms.parameters';
import { createErrorContentFragment, DMessageContentFragment, DMessageErrorPart, DMessageVoidFragment, isContentFragment, isErrorPart } from '~/common/stores/chat/chat.fragments';
import { findLLMOrThrow } from '~/common/stores/llms/store-llms';
-import { getLabsDevMode, getLabsDevNoStreaming } from '~/common/stores/store-ux-labs';
+import { getAixInspector } from '~/common/stores/store-ui';
+import { getLabsDevNoStreaming } from '~/common/stores/store-ux-labs';
import { metricsStoreAddChatGenerate } from '~/common/stores/metrics/store-metrics';
import { presentErrorToHumans } from '~/common/util/errorUtils';
import { webGeolocationCached } from '~/common/util/webGeolocationUtils';
@@ -631,7 +632,7 @@ async function _aixChatGenerateContent_LL(
* - AIX inspector is now independent from sudo mode
* - every request thereafter both sends back the Aix server-side dispatch packet, and appends all the particles received by the client side
*/
- const requestServerDebugging = getLabsDevMode();
+ const requestServerDebugging = getAixInspector();
const debugContext = !requestServerDebugging ? undefined : { contextName: aixContext.name, contextRef: aixContext.ref };
/**
diff --git a/src/modules/aix/client/debugger/AixDebuggerDialog.tsx b/src/modules/aix/client/debugger/AixDebuggerDialog.tsx
index 32398aca3..861b9780b 100644
--- a/src/modules/aix/client/debugger/AixDebuggerDialog.tsx
+++ b/src/modules/aix/client/debugger/AixDebuggerDialog.tsx
@@ -1,11 +1,12 @@
import * as React from 'react';
import { useShallow } from 'zustand/react/shallow';
-import { Box, Button, Divider, FormControl, FormLabel, Option, Select, Typography } from '@mui/joy';
+import { Box, Button, Divider, FormControl, FormLabel, Link, Option, Select, Switch, Typography } from '@mui/joy';
import ClearAllIcon from '@mui/icons-material/ClearAll';
import { GoodModal } from '~/common/components/modals/GoodModal';
import { useIsMobile } from '~/common/components/useMatchMedia';
+import { useUIPreferencesStore } from '~/common/stores/store-ui';
import { AixDebuggerFrame } from './AixDebuggerFrame';
import { aixClientDebuggerActions, useAixClientDebuggerStore } from './memstore-aix-client-debugger';
@@ -15,8 +16,10 @@ export function AixDebuggerDialog(props: {
onClose: () => void;
}) {
- // external state - we subscribe to Any update - it's a temp debugger anyway
+ // external state
const isMobile = useIsMobile();
+ const aixInspector = useUIPreferencesStore(state => state.aixInspector);
+ // NOTE: we subscribe to Any update - which can be ultra noisy
const { frames, activeFrameId, maxFrames } = useAixClientDebuggerStore(useShallow((state) => ({
frames: state.frames,
activeFrameId: state.activeFrameId,
@@ -42,7 +45,14 @@ export function AixDebuggerDialog(props: {
+ }
autoOverflow
fullscreen={isMobile}
sx={{ maxWidth: undefined }}
@@ -74,7 +84,7 @@ export function AixDebuggerDialog(props: {
- {/* History Size Preferenes */}
+ {/* History Size Preferences */}
History Size
@@ -111,11 +121,20 @@ export function AixDebuggerDialog(props: {
{!frames.length && <>
- No AIX API requests recorded yet
+ {aixInspector ? 'Ready to capture' : 'AI Request Inspector'}
-
- Ensure AIX debugging is active (Settings -> Labs -> Developer Mode)
- and you are running your own localhost:3000 installation.
+
+ {aixInspector
+ ? 'Your next AI request will be captured here.'
+ : <>
+
+ Turn on inspector
+ to see the exact requests to AI models.
+ >}
>}
{!activeFrame && !!frames.length && (
diff --git a/src/modules/aix/client/debugger/AixDebuggerFrame.tsx b/src/modules/aix/client/debugger/AixDebuggerFrame.tsx
index 9cd45b768..2c6247248 100644
--- a/src/modules/aix/client/debugger/AixDebuggerFrame.tsx
+++ b/src/modules/aix/client/debugger/AixDebuggerFrame.tsx
@@ -94,8 +94,9 @@ export function AixDebuggerFrame(props: {
{/* Body */}
-
- -> Body {frame.bodySize > 0 && `(${frame.bodySize.toLocaleString()} chars)`}
+
+ -> Body
+ {frame.bodySize > 0 && {frame.bodySize.toLocaleString()} bytes}