mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
Merge branch 'main' into enhance/invokeai-logs
This commit is contained in:
commit
0bc2edc044
@ -65,6 +65,7 @@
|
|||||||
"@emotion/styled": "^11.10.6",
|
"@emotion/styled": "^11.10.6",
|
||||||
"@fontsource/inter": "^4.5.15",
|
"@fontsource/inter": "^4.5.15",
|
||||||
"@reduxjs/toolkit": "^1.9.5",
|
"@reduxjs/toolkit": "^1.9.5",
|
||||||
|
"@roarr/browser-log-writer": "^1.1.5",
|
||||||
"chakra-ui-contextmenu": "^1.0.5",
|
"chakra-ui-contextmenu": "^1.0.5",
|
||||||
"dateformat": "^5.0.3",
|
"dateformat": "^5.0.3",
|
||||||
"formik": "^2.2.9",
|
"formik": "^2.2.9",
|
||||||
@ -93,17 +94,19 @@
|
|||||||
"redux-deep-persist": "^1.0.7",
|
"redux-deep-persist": "^1.0.7",
|
||||||
"redux-dynamic-middlewares": "^2.2.0",
|
"redux-dynamic-middlewares": "^2.2.0",
|
||||||
"redux-persist": "^6.0.0",
|
"redux-persist": "^6.0.0",
|
||||||
|
"roarr": "^7.15.0",
|
||||||
"socket.io-client": "^4.6.0",
|
"socket.io-client": "^4.6.0",
|
||||||
"use-image": "^1.1.0",
|
"use-image": "^1.1.0",
|
||||||
"uuid": "^9.0.0"
|
"uuid": "^9.0.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
"@chakra-ui/cli": "^2.4.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"ts-toolbelt": "^9.6.0",
|
"ts-toolbelt": "^9.6.0"
|
||||||
"@chakra-ui/cli": "^2.4.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@chakra-ui/cli": "^2.4.0",
|
||||||
"@types/dateformat": "^5.0.0",
|
"@types/dateformat": "^5.0.0",
|
||||||
"@types/lodash-es": "^4.14.194",
|
"@types/lodash-es": "^4.14.194",
|
||||||
"@types/node": "^18.16.2",
|
"@types/node": "^18.16.2",
|
||||||
|
@ -530,7 +530,11 @@
|
|||||||
"resetWebUI": "Reset Web UI",
|
"resetWebUI": "Reset Web UI",
|
||||||
"resetWebUIDesc1": "Resetting the web UI only resets the browser's local cache of your images and remembered settings. It does not delete any images from disk.",
|
"resetWebUIDesc1": "Resetting the web UI only resets the browser's local cache of your images and remembered settings. It does not delete any images from disk.",
|
||||||
"resetWebUIDesc2": "If images aren't showing up in the gallery or something else isn't working, please try resetting before submitting an issue on GitHub.",
|
"resetWebUIDesc2": "If images aren't showing up in the gallery or something else isn't working, please try resetting before submitting an issue on GitHub.",
|
||||||
"resetComplete": "Web UI has been reset. Refresh the page to reload."
|
"resetComplete": "Web UI has been reset. Refresh the page to reload.",
|
||||||
|
"consoleLogLevel": "Log Level",
|
||||||
|
"shouldLogToConsole": "Console Logging",
|
||||||
|
"developer": "Developer",
|
||||||
|
"general": "General"
|
||||||
},
|
},
|
||||||
"toast": {
|
"toast": {
|
||||||
"serverError": "Server Error",
|
"serverError": "Server Error",
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import ImageUploader from 'common/components/ImageUploader';
|
import ImageUploader from 'common/components/ImageUploader';
|
||||||
import Console from 'features/system/components/Console';
|
|
||||||
import ProgressBar from 'features/system/components/ProgressBar';
|
import ProgressBar from 'features/system/components/ProgressBar';
|
||||||
import SiteHeader from 'features/system/components/SiteHeader';
|
import SiteHeader from 'features/system/components/SiteHeader';
|
||||||
import InvokeTabs from 'features/ui/components/InvokeTabs';
|
import InvokeTabs from 'features/ui/components/InvokeTabs';
|
||||||
@ -27,6 +26,7 @@ import { PartialAppConfig } from 'app/types/invokeai';
|
|||||||
import { useGlobalHotkeys } from 'common/hooks/useGlobalHotkeys';
|
import { useGlobalHotkeys } from 'common/hooks/useGlobalHotkeys';
|
||||||
import { configChanged } from 'features/system/store/configSlice';
|
import { configChanged } from 'features/system/store/configSlice';
|
||||||
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus';
|
||||||
|
import { useLogger } from 'app/logging/useLogger';
|
||||||
|
|
||||||
const DEFAULT_CONFIG = {};
|
const DEFAULT_CONFIG = {};
|
||||||
|
|
||||||
@ -37,6 +37,7 @@ interface Props extends PropsWithChildren {
|
|||||||
const App = ({ config = DEFAULT_CONFIG, children }: Props) => {
|
const App = ({ config = DEFAULT_CONFIG, children }: Props) => {
|
||||||
useToastWatcher();
|
useToastWatcher();
|
||||||
useGlobalHotkeys();
|
useGlobalHotkeys();
|
||||||
|
const log = useLogger();
|
||||||
|
|
||||||
const currentTheme = useAppSelector((state) => state.ui.currentTheme);
|
const currentTheme = useAppSelector((state) => state.ui.currentTheme);
|
||||||
|
|
||||||
@ -50,9 +51,9 @@ const App = ({ config = DEFAULT_CONFIG, children }: Props) => {
|
|||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('Received config: ', config);
|
log.info({ namespace: 'App', data: config }, 'Received config');
|
||||||
dispatch(configChanged(config));
|
dispatch(configChanged(config));
|
||||||
}, [dispatch, config]);
|
}, [dispatch, config, log]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setColorMode(['light'].includes(currentTheme) ? 'light' : 'dark');
|
setColorMode(['light'].includes(currentTheme) ? 'light' : 'dark');
|
||||||
@ -119,9 +120,6 @@ const App = ({ config = DEFAULT_CONFIG, children }: Props) => {
|
|||||||
<Portal>
|
<Portal>
|
||||||
<FloatingGalleryButton />
|
<FloatingGalleryButton />
|
||||||
</Portal>
|
</Portal>
|
||||||
<Portal>
|
|
||||||
<Console />
|
|
||||||
</Portal>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
94
invokeai/frontend/web/src/app/logging/useLogger.ts
Normal file
94
invokeai/frontend/web/src/app/logging/useLogger.ts
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { systemSelector } from 'features/system/store/systemSelectors';
|
||||||
|
import { isEqual } from 'lodash-es';
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
import { LogLevelName, ROARR, Roarr } from 'roarr';
|
||||||
|
import { createLogWriter } from '@roarr/browser-log-writer';
|
||||||
|
|
||||||
|
// Base logging context includes only the package name
|
||||||
|
const baseContext = { package: '@invoke-ai/invoke-ai-ui' };
|
||||||
|
|
||||||
|
// Create browser log writer
|
||||||
|
ROARR.write = createLogWriter();
|
||||||
|
|
||||||
|
// Module-scoped logger - can be imported and used anywhere
|
||||||
|
export let log = Roarr.child(baseContext);
|
||||||
|
|
||||||
|
// Translate human-readable log levels to numbers, used for log filtering
|
||||||
|
export const LOG_LEVEL_MAP: Record<LogLevelName, number> = {
|
||||||
|
trace: 10,
|
||||||
|
debug: 20,
|
||||||
|
info: 30,
|
||||||
|
warn: 40,
|
||||||
|
error: 50,
|
||||||
|
fatal: 60,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const VALID_LOG_LEVELS = [
|
||||||
|
'trace',
|
||||||
|
'debug',
|
||||||
|
'info',
|
||||||
|
'warn',
|
||||||
|
'error',
|
||||||
|
'fatal',
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
export type InvokeLogLevel = (typeof VALID_LOG_LEVELS)[number];
|
||||||
|
|
||||||
|
const selector = createSelector(
|
||||||
|
systemSelector,
|
||||||
|
(system) => {
|
||||||
|
const { app_version, consoleLogLevel, shouldLogToConsole } = system;
|
||||||
|
|
||||||
|
return {
|
||||||
|
version: app_version,
|
||||||
|
consoleLogLevel,
|
||||||
|
shouldLogToConsole,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
{
|
||||||
|
memoizeOptions: {
|
||||||
|
resultEqualityCheck: isEqual,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export const useLogger = () => {
|
||||||
|
const { version, consoleLogLevel, shouldLogToConsole } =
|
||||||
|
useAppSelector(selector);
|
||||||
|
|
||||||
|
// The provided Roarr browser log writer uses localStorage to config logging to console
|
||||||
|
useEffect(() => {
|
||||||
|
if (shouldLogToConsole) {
|
||||||
|
// Enable console log output
|
||||||
|
localStorage.setItem('ROARR_LOG', 'true');
|
||||||
|
|
||||||
|
// Use a filter to show only logs of the given level
|
||||||
|
localStorage.setItem(
|
||||||
|
'ROARR_FILTER',
|
||||||
|
`context.logLevel:>=${LOG_LEVEL_MAP[consoleLogLevel]}`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Disable console log output
|
||||||
|
localStorage.setItem('ROARR_LOG', 'false');
|
||||||
|
}
|
||||||
|
ROARR.write = createLogWriter();
|
||||||
|
}, [consoleLogLevel, shouldLogToConsole]);
|
||||||
|
|
||||||
|
// Update the module-scoped logger context as needed
|
||||||
|
useEffect(() => {
|
||||||
|
const newContext: Record<string, any> = {
|
||||||
|
...baseContext,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (version) {
|
||||||
|
newContext.version = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
log = Roarr.child(newContext);
|
||||||
|
}, [version]);
|
||||||
|
|
||||||
|
// Use the logger within components - no different than just importing it directly
|
||||||
|
return log;
|
||||||
|
};
|
@ -12,7 +12,6 @@ import {
|
|||||||
removeImage,
|
removeImage,
|
||||||
} from 'features/gallery/store/gallerySlice';
|
} from 'features/gallery/store/gallerySlice';
|
||||||
import {
|
import {
|
||||||
addLogEntry,
|
|
||||||
generationRequested,
|
generationRequested,
|
||||||
modelChangeRequested,
|
modelChangeRequested,
|
||||||
modelConvertRequested,
|
modelConvertRequested,
|
||||||
|
@ -6,7 +6,6 @@ import { v4 as uuidv4 } from 'uuid';
|
|||||||
import * as InvokeAI from 'app/types/invokeai';
|
import * as InvokeAI from 'app/types/invokeai';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
addLogEntry,
|
|
||||||
addToast,
|
addToast,
|
||||||
errorOccurred,
|
errorOccurred,
|
||||||
processingCanceled,
|
processingCanceled,
|
||||||
|
@ -28,7 +28,7 @@ import { lightboxDenylist } from 'features/lightbox/store/lightboxPersistDenylis
|
|||||||
import { modelsDenylist } from 'features/system/store/modelsPersistDenylist';
|
import { modelsDenylist } from 'features/system/store/modelsPersistDenylist';
|
||||||
import { nodesDenylist } from 'features/nodes/store/nodesPersistDenylist';
|
import { nodesDenylist } from 'features/nodes/store/nodesPersistDenylist';
|
||||||
import { postprocessingDenylist } from 'features/parameters/store/postprocessingPersistDenylist';
|
import { postprocessingDenylist } from 'features/parameters/store/postprocessingPersistDenylist';
|
||||||
import { systemDenylist } from 'features/system/store/systemPersistsDenylist';
|
import { systemDenylist } from 'features/system/store/systemPersistDenylist';
|
||||||
import { uiDenylist } from 'features/ui/store/uiPersistDenylist';
|
import { uiDenylist } from 'features/ui/store/uiPersistDenylist';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -82,7 +82,6 @@ const rootPersistConfig = getPersistConfig({
|
|||||||
'hotkeys',
|
'hotkeys',
|
||||||
'config',
|
'config',
|
||||||
],
|
],
|
||||||
debounce: 300,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const persistedReducer = persistReducer(rootPersistConfig, rootReducer);
|
const persistedReducer = persistReducer(rootPersistConfig, rootReducer);
|
||||||
|
@ -16,13 +16,23 @@ type IAISelectProps = SelectProps & {
|
|||||||
validValues:
|
validValues:
|
||||||
| Array<number | string>
|
| Array<number | string>
|
||||||
| Array<{ key: string; value: string | number }>;
|
| Array<{ key: string; value: string | number }>;
|
||||||
|
horizontal?: boolean;
|
||||||
|
spaceEvenly?: boolean;
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* Customized Chakra FormControl + Select multi-part component.
|
* Customized Chakra FormControl + Select multi-part component.
|
||||||
*/
|
*/
|
||||||
const IAISelect = (props: IAISelectProps) => {
|
const IAISelect = (props: IAISelectProps) => {
|
||||||
const { label, isDisabled, validValues, tooltip, tooltipProps, ...rest } =
|
const {
|
||||||
props;
|
label,
|
||||||
|
isDisabled,
|
||||||
|
validValues,
|
||||||
|
tooltip,
|
||||||
|
tooltipProps,
|
||||||
|
horizontal,
|
||||||
|
spaceEvenly,
|
||||||
|
...rest
|
||||||
|
} = props;
|
||||||
return (
|
return (
|
||||||
<FormControl
|
<FormControl
|
||||||
isDisabled={isDisabled}
|
isDisabled={isDisabled}
|
||||||
@ -32,10 +42,28 @@ const IAISelect = (props: IAISelectProps) => {
|
|||||||
e.nativeEvent.stopPropagation();
|
e.nativeEvent.stopPropagation();
|
||||||
e.nativeEvent.cancelBubble = true;
|
e.nativeEvent.cancelBubble = true;
|
||||||
}}
|
}}
|
||||||
|
sx={
|
||||||
|
horizontal
|
||||||
|
? {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
gap: 4,
|
||||||
|
}
|
||||||
|
: {}
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{label && <FormLabel>{label}</FormLabel>}
|
{label && (
|
||||||
|
<FormLabel sx={spaceEvenly ? { flexBasis: 0, flexGrow: 1 } : {}}>
|
||||||
|
{label}
|
||||||
|
</FormLabel>
|
||||||
|
)}
|
||||||
<Tooltip label={tooltip} {...tooltipProps}>
|
<Tooltip label={tooltip} {...tooltipProps}>
|
||||||
<Select {...rest}>
|
<Select
|
||||||
|
{...rest}
|
||||||
|
rootProps={{ sx: spaceEvenly ? { flexBasis: 0, flexGrow: 1 } : {} }}
|
||||||
|
>
|
||||||
{validValues.map((opt) => {
|
{validValues.map((opt) => {
|
||||||
return typeof opt === 'string' || typeof opt === 'number' ? (
|
return typeof opt === 'string' || typeof opt === 'number' ? (
|
||||||
<IAIOption key={opt} value={opt}>
|
<IAIOption key={opt} value={opt}>
|
||||||
|
@ -16,6 +16,8 @@ import { receivedOpenAPISchema } from 'services/thunks/schema';
|
|||||||
import { isFulfilledAnyGraphBuilt } from 'services/thunks/session';
|
import { isFulfilledAnyGraphBuilt } from 'services/thunks/session';
|
||||||
import { InvocationTemplate, InvocationValue } from '../types/types';
|
import { InvocationTemplate, InvocationValue } from '../types/types';
|
||||||
import { parseSchema } from '../util/parseSchema';
|
import { parseSchema } from '../util/parseSchema';
|
||||||
|
import { log } from 'app/logging/useLogger';
|
||||||
|
import { size } from 'lodash-es';
|
||||||
|
|
||||||
export type NodesState = {
|
export type NodesState = {
|
||||||
nodes: Node<InvocationValue>[];
|
nodes: Node<InvocationValue>[];
|
||||||
@ -85,7 +87,12 @@ const nodesSlice = createSlice({
|
|||||||
parsedOpenAPISchema: (state, action: PayloadAction<OpenAPIV3.Document>) => {
|
parsedOpenAPISchema: (state, action: PayloadAction<OpenAPIV3.Document>) => {
|
||||||
try {
|
try {
|
||||||
const parsedSchema = parseSchema(action.payload);
|
const parsedSchema = parseSchema(action.payload);
|
||||||
console.debug('Parsed schema: ', parsedSchema);
|
|
||||||
|
// TODO: Achtung! Side effect in a reducer!
|
||||||
|
log.info(
|
||||||
|
{ namespace: 'schema', nodes: parsedSchema },
|
||||||
|
`Parsed ${size(parsedSchema)} nodes`
|
||||||
|
);
|
||||||
state.invocationTemplates = parsedSchema;
|
state.invocationTemplates = parsedSchema;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
@ -1,197 +0,0 @@
|
|||||||
import { Flex, Text, Tooltip } from '@chakra-ui/react';
|
|
||||||
import { createSelector } from '@reduxjs/toolkit';
|
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
|
||||||
import IAIIconButton from 'common/components/IAIIconButton';
|
|
||||||
import {
|
|
||||||
errorSeen,
|
|
||||||
setShouldShowLogViewer,
|
|
||||||
SystemState,
|
|
||||||
} from 'features/system/store/systemSlice';
|
|
||||||
import { isEqual } from 'lodash-es';
|
|
||||||
import { Resizable } from 're-resizable';
|
|
||||||
import { memo, useLayoutEffect, useRef, useState } from 'react';
|
|
||||||
import { useHotkeys } from 'react-hotkeys-hook';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { FaAngleDoubleDown, FaCode, FaMinus } from 'react-icons/fa';
|
|
||||||
import { systemSelector } from '../store/systemSelectors';
|
|
||||||
|
|
||||||
const logSelector = createSelector(
|
|
||||||
systemSelector,
|
|
||||||
(system: SystemState) => system.log,
|
|
||||||
{
|
|
||||||
memoizeOptions: {
|
|
||||||
// We don't need a deep equality check for this selector.
|
|
||||||
resultEqualityCheck: (a, b) => a.length === b.length,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const consoleSelector = createSelector(
|
|
||||||
systemSelector,
|
|
||||||
(system: SystemState) => {
|
|
||||||
return {
|
|
||||||
shouldShowLogViewer: system.shouldShowLogViewer,
|
|
||||||
hasError: system.hasError,
|
|
||||||
wasErrorSeen: system.wasErrorSeen,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
{
|
|
||||||
memoizeOptions: {
|
|
||||||
resultEqualityCheck: isEqual,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Basic log viewer, floats on bottom of page.
|
|
||||||
*/
|
|
||||||
const Console = () => {
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const log = useAppSelector(logSelector);
|
|
||||||
const { shouldShowLogViewer, hasError, wasErrorSeen } =
|
|
||||||
useAppSelector(consoleSelector);
|
|
||||||
|
|
||||||
// Rudimentary autoscroll
|
|
||||||
const [shouldAutoscroll, setShouldAutoscroll] = useState<boolean>(true);
|
|
||||||
const viewerRef = useRef<HTMLDivElement>(null);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If autoscroll is on, scroll to the bottom when:
|
|
||||||
* - log updates
|
|
||||||
* - viewer is toggled
|
|
||||||
*
|
|
||||||
* Also scroll to the bottom whenever autoscroll is turned on.
|
|
||||||
*/
|
|
||||||
useLayoutEffect(() => {
|
|
||||||
if (viewerRef.current !== null && shouldAutoscroll) {
|
|
||||||
viewerRef.current.scrollTop = viewerRef.current.scrollHeight;
|
|
||||||
}
|
|
||||||
}, [shouldAutoscroll, log, shouldShowLogViewer]);
|
|
||||||
|
|
||||||
const handleClickLogViewerToggle = () => {
|
|
||||||
dispatch(errorSeen());
|
|
||||||
dispatch(setShouldShowLogViewer(!shouldShowLogViewer));
|
|
||||||
};
|
|
||||||
|
|
||||||
useHotkeys(
|
|
||||||
'`',
|
|
||||||
() => {
|
|
||||||
dispatch(setShouldShowLogViewer(!shouldShowLogViewer));
|
|
||||||
},
|
|
||||||
[shouldShowLogViewer]
|
|
||||||
);
|
|
||||||
|
|
||||||
useHotkeys('esc', () => {
|
|
||||||
dispatch(setShouldShowLogViewer(false));
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleOnScroll = () => {
|
|
||||||
if (!viewerRef.current) return;
|
|
||||||
if (
|
|
||||||
shouldAutoscroll &&
|
|
||||||
viewerRef.current.scrollTop <
|
|
||||||
viewerRef.current.scrollHeight - viewerRef.current.clientHeight
|
|
||||||
) {
|
|
||||||
setShouldAutoscroll(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{shouldShowLogViewer && (
|
|
||||||
<Resizable
|
|
||||||
defaultSize={{
|
|
||||||
width: '100%',
|
|
||||||
height: 200,
|
|
||||||
}}
|
|
||||||
style={{
|
|
||||||
display: 'flex',
|
|
||||||
position: 'fixed',
|
|
||||||
insetInlineStart: 0,
|
|
||||||
bottom: 0,
|
|
||||||
zIndex: 1,
|
|
||||||
}}
|
|
||||||
maxHeight="90vh"
|
|
||||||
>
|
|
||||||
<Flex
|
|
||||||
sx={{
|
|
||||||
flexDirection: 'column',
|
|
||||||
width: '100vw',
|
|
||||||
overflow: 'auto',
|
|
||||||
direction: 'column',
|
|
||||||
fontFamily: 'monospace',
|
|
||||||
pt: 0,
|
|
||||||
pr: 4,
|
|
||||||
pb: 4,
|
|
||||||
pl: 12,
|
|
||||||
borderTopWidth: 5,
|
|
||||||
bg: 'base.850',
|
|
||||||
borderColor: 'base.700',
|
|
||||||
zIndex: 2,
|
|
||||||
}}
|
|
||||||
ref={viewerRef}
|
|
||||||
onScroll={handleOnScroll}
|
|
||||||
>
|
|
||||||
{log.map((entry, i) => {
|
|
||||||
const { timestamp, message, level } = entry;
|
|
||||||
const colorScheme = level === 'info' ? 'base' : level;
|
|
||||||
return (
|
|
||||||
<Flex
|
|
||||||
key={i}
|
|
||||||
sx={{
|
|
||||||
gap: 2,
|
|
||||||
color: `${colorScheme}.300`,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Text fontWeight="600">{timestamp}:</Text>
|
|
||||||
<Text wordBreak="break-all">{message}</Text>
|
|
||||||
</Flex>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Flex>
|
|
||||||
</Resizable>
|
|
||||||
)}
|
|
||||||
{shouldShowLogViewer && (
|
|
||||||
<Tooltip
|
|
||||||
hasArrow
|
|
||||||
label={shouldAutoscroll ? 'Autoscroll On' : 'Autoscroll Off'}
|
|
||||||
>
|
|
||||||
<IAIIconButton
|
|
||||||
size="sm"
|
|
||||||
aria-label={t('accessibility.toggleAutoscroll')}
|
|
||||||
icon={<FaAngleDoubleDown />}
|
|
||||||
onClick={() => setShouldAutoscroll(!shouldAutoscroll)}
|
|
||||||
isChecked={shouldAutoscroll}
|
|
||||||
sx={{
|
|
||||||
position: 'fixed',
|
|
||||||
insetInlineStart: 2,
|
|
||||||
bottom: 12,
|
|
||||||
zIndex: 1,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
<Tooltip
|
|
||||||
hasArrow
|
|
||||||
label={shouldShowLogViewer ? 'Hide Console' : 'Show Console'}
|
|
||||||
>
|
|
||||||
<IAIIconButton
|
|
||||||
size="sm"
|
|
||||||
aria-label={t('accessibility.toggleLogViewer')}
|
|
||||||
icon={shouldShowLogViewer ? <FaMinus /> : <FaCode />}
|
|
||||||
onClick={handleClickLogViewerToggle}
|
|
||||||
sx={{
|
|
||||||
position: 'fixed',
|
|
||||||
insetInlineStart: 2,
|
|
||||||
bottom: 2,
|
|
||||||
zIndex: 1,
|
|
||||||
}}
|
|
||||||
colorScheme={hasError || !wasErrorSeen ? 'error' : 'base'}
|
|
||||||
/>
|
|
||||||
</Tooltip>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default memo(Console);
|
|
@ -23,12 +23,14 @@ import IAISelect from 'common/components/IAISelect';
|
|||||||
import IAISwitch from 'common/components/IAISwitch';
|
import IAISwitch from 'common/components/IAISwitch';
|
||||||
import { systemSelector } from 'features/system/store/systemSelectors';
|
import { systemSelector } from 'features/system/store/systemSelectors';
|
||||||
import {
|
import {
|
||||||
|
consoleLogLevelChanged,
|
||||||
InProgressImageType,
|
InProgressImageType,
|
||||||
setEnableImageDebugging,
|
setEnableImageDebugging,
|
||||||
setSaveIntermediatesInterval,
|
setSaveIntermediatesInterval,
|
||||||
setShouldConfirmOnDelete,
|
setShouldConfirmOnDelete,
|
||||||
setShouldDisplayGuides,
|
setShouldDisplayGuides,
|
||||||
setShouldDisplayInProgressType,
|
setShouldDisplayInProgressType,
|
||||||
|
shouldLogToConsoleChanged,
|
||||||
SystemState,
|
SystemState,
|
||||||
} from 'features/system/store/systemSlice';
|
} from 'features/system/store/systemSlice';
|
||||||
import { uiSelector } from 'features/ui/store/uiSelectors';
|
import { uiSelector } from 'features/ui/store/uiSelectors';
|
||||||
@ -39,8 +41,11 @@ import {
|
|||||||
import { UIState } from 'features/ui/store/uiTypes';
|
import { UIState } from 'features/ui/store/uiTypes';
|
||||||
import { isEqual, map } from 'lodash-es';
|
import { isEqual, map } from 'lodash-es';
|
||||||
import { persistor } from 'app/store/persistor';
|
import { persistor } from 'app/store/persistor';
|
||||||
import { ChangeEvent, cloneElement, ReactElement } from 'react';
|
import { ChangeEvent, cloneElement, ReactElement, useCallback } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { InvokeLogLevel, VALID_LOG_LEVELS } from 'app/logging/useLogger';
|
||||||
|
import { LogLevelName } from 'roarr';
|
||||||
|
import { F } from 'ts-toolbelt';
|
||||||
|
|
||||||
const selector = createSelector(
|
const selector = createSelector(
|
||||||
[systemSelector, uiSelector],
|
[systemSelector, uiSelector],
|
||||||
@ -52,6 +57,8 @@ const selector = createSelector(
|
|||||||
model_list,
|
model_list,
|
||||||
saveIntermediatesInterval,
|
saveIntermediatesInterval,
|
||||||
enableImageDebugging,
|
enableImageDebugging,
|
||||||
|
consoleLogLevel,
|
||||||
|
shouldLogToConsole,
|
||||||
} = system;
|
} = system;
|
||||||
|
|
||||||
const { shouldUseCanvasBetaLayout, shouldUseSliders } = ui;
|
const { shouldUseCanvasBetaLayout, shouldUseSliders } = ui;
|
||||||
@ -65,6 +72,8 @@ const selector = createSelector(
|
|||||||
enableImageDebugging,
|
enableImageDebugging,
|
||||||
shouldUseCanvasBetaLayout,
|
shouldUseCanvasBetaLayout,
|
||||||
shouldUseSliders,
|
shouldUseSliders,
|
||||||
|
consoleLogLevel,
|
||||||
|
shouldLogToConsole,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -77,6 +86,7 @@ const modalSectionStyles: ChakraProps['sx'] = {
|
|||||||
gap: 2,
|
gap: 2,
|
||||||
p: 4,
|
p: 4,
|
||||||
bg: 'base.900',
|
bg: 'base.900',
|
||||||
|
borderRadius: 'base',
|
||||||
};
|
};
|
||||||
|
|
||||||
type SettingsModalProps = {
|
type SettingsModalProps = {
|
||||||
@ -116,6 +126,8 @@ const SettingsModal = ({ children }: SettingsModalProps) => {
|
|||||||
enableImageDebugging,
|
enableImageDebugging,
|
||||||
shouldUseCanvasBetaLayout,
|
shouldUseCanvasBetaLayout,
|
||||||
shouldUseSliders,
|
shouldUseSliders,
|
||||||
|
consoleLogLevel,
|
||||||
|
shouldLogToConsole,
|
||||||
} = useAppSelector(selector);
|
} = useAppSelector(selector);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -135,6 +147,20 @@ const SettingsModal = ({ children }: SettingsModalProps) => {
|
|||||||
dispatch(setSaveIntermediatesInterval(value));
|
dispatch(setSaveIntermediatesInterval(value));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleLogLevelChanged = useCallback(
|
||||||
|
(e: ChangeEvent<HTMLSelectElement>) => {
|
||||||
|
dispatch(consoleLogLevelChanged(e.target.value as LogLevelName));
|
||||||
|
},
|
||||||
|
[dispatch]
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleLogToConsoleChanged = useCallback(
|
||||||
|
(e: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
dispatch(shouldLogToConsoleChanged(e.target.checked));
|
||||||
|
},
|
||||||
|
[dispatch]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{cloneElement(children, {
|
{cloneElement(children, {
|
||||||
@ -145,15 +171,20 @@ const SettingsModal = ({ children }: SettingsModalProps) => {
|
|||||||
isOpen={isSettingsModalOpen}
|
isOpen={isSettingsModalOpen}
|
||||||
onClose={onSettingsModalClose}
|
onClose={onSettingsModalClose}
|
||||||
size="xl"
|
size="xl"
|
||||||
|
isCentered
|
||||||
>
|
>
|
||||||
<ModalOverlay />
|
<ModalOverlay />
|
||||||
<ModalContent paddingInlineEnd={4}>
|
<ModalContent paddingInlineEnd={4}>
|
||||||
<ModalHeader>{t('common.settingsLabel')}</ModalHeader>
|
<ModalHeader>{t('common.settingsLabel')}</ModalHeader>
|
||||||
<ModalCloseButton />
|
<ModalCloseButton />
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
<Grid gap={4}>
|
<Flex sx={{ gap: 4, flexDirection: 'column' }}>
|
||||||
<Flex sx={modalSectionStyles}>
|
<Flex sx={modalSectionStyles}>
|
||||||
|
<Heading size="sm">{t('settings.general')}</Heading>
|
||||||
|
|
||||||
<IAISelect
|
<IAISelect
|
||||||
|
horizontal
|
||||||
|
spaceEvenly
|
||||||
label={t('settings.displayInProgress')}
|
label={t('settings.displayInProgress')}
|
||||||
validValues={IN_PROGRESS_IMAGE_TYPES}
|
validValues={IN_PROGRESS_IMAGE_TYPES}
|
||||||
value={shouldDisplayInProgressType}
|
value={shouldDisplayInProgressType}
|
||||||
@ -208,9 +239,21 @@ const SettingsModal = ({ children }: SettingsModalProps) => {
|
|||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
<Flex sx={modalSectionStyles}>
|
<Flex sx={modalSectionStyles}>
|
||||||
<Heading size="sm" style={{ fontWeight: 'bold' }}>
|
<Heading size="sm">{t('settings.developer')}</Heading>
|
||||||
Developer
|
<IAISwitch
|
||||||
</Heading>
|
label={t('settings.shouldLogToConsole')}
|
||||||
|
isChecked={shouldLogToConsole}
|
||||||
|
onChange={handleLogToConsoleChanged}
|
||||||
|
/>
|
||||||
|
<IAISelect
|
||||||
|
horizontal
|
||||||
|
spaceEvenly
|
||||||
|
isDisabled={!shouldLogToConsole}
|
||||||
|
label={t('settings.consoleLogLevel')}
|
||||||
|
onChange={handleLogLevelChanged}
|
||||||
|
value={consoleLogLevel}
|
||||||
|
validValues={VALID_LOG_LEVELS.concat()}
|
||||||
|
/>
|
||||||
<IAISwitch
|
<IAISwitch
|
||||||
label={t('settings.enableImageDebugging')}
|
label={t('settings.enableImageDebugging')}
|
||||||
isChecked={enableImageDebugging}
|
isChecked={enableImageDebugging}
|
||||||
@ -228,7 +271,7 @@ const SettingsModal = ({ children }: SettingsModalProps) => {
|
|||||||
<Text>{t('settings.resetWebUIDesc1')}</Text>
|
<Text>{t('settings.resetWebUIDesc1')}</Text>
|
||||||
<Text>{t('settings.resetWebUIDesc2')}</Text>
|
<Text>{t('settings.resetWebUIDesc2')}</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Grid>
|
</Flex>
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
|
|
||||||
<ModalFooter>
|
<ModalFooter>
|
||||||
|
@ -17,7 +17,6 @@ const itemsToDenylist: (keyof SystemState)[] = [
|
|||||||
'totalSteps',
|
'totalSteps',
|
||||||
'openModel',
|
'openModel',
|
||||||
'isCancelScheduled',
|
'isCancelScheduled',
|
||||||
// 'sessionId',
|
|
||||||
'progressImage',
|
'progressImage',
|
||||||
'wereModelsReceived',
|
'wereModelsReceived',
|
||||||
'wasSchemaParsed',
|
'wasSchemaParsed',
|
@ -14,13 +14,14 @@ import {
|
|||||||
} from 'services/events/actions';
|
} from 'services/events/actions';
|
||||||
|
|
||||||
import i18n from 'i18n';
|
import i18n from 'i18n';
|
||||||
import { isImageOutput } from 'services/types/guards';
|
|
||||||
import { ProgressImage } from 'services/events/types';
|
import { ProgressImage } from 'services/events/types';
|
||||||
import { initialImageSelected } from 'features/parameters/store/generationSlice';
|
import { initialImageSelected } from 'features/parameters/store/generationSlice';
|
||||||
import { makeToast } from '../hooks/useToastWatcher';
|
import { makeToast } from '../hooks/useToastWatcher';
|
||||||
import { sessionCanceled, sessionInvoked } from 'services/thunks/session';
|
import { sessionCanceled, sessionInvoked } from 'services/thunks/session';
|
||||||
import { receivedModels } from 'services/thunks/model';
|
import { receivedModels } from 'services/thunks/model';
|
||||||
import { parsedOpenAPISchema } from 'features/nodes/store/nodesSlice';
|
import { parsedOpenAPISchema } from 'features/nodes/store/nodesSlice';
|
||||||
|
import { LogLevelName } from 'roarr';
|
||||||
|
import { InvokeLogLevel } from 'app/logging/useLogger';
|
||||||
|
|
||||||
export type LogLevel = 'info' | 'warning' | 'error';
|
export type LogLevel = 'info' | 'warning' | 'error';
|
||||||
|
|
||||||
@ -42,7 +43,6 @@ export interface SystemState
|
|||||||
extends InvokeAI.SystemStatus,
|
extends InvokeAI.SystemStatus,
|
||||||
InvokeAI.SystemConfig {
|
InvokeAI.SystemConfig {
|
||||||
shouldDisplayInProgressType: InProgressImageType;
|
shouldDisplayInProgressType: InProgressImageType;
|
||||||
log: Array<LogEntry>;
|
|
||||||
shouldShowLogViewer: boolean;
|
shouldShowLogViewer: boolean;
|
||||||
isGFPGANAvailable: boolean;
|
isGFPGANAvailable: boolean;
|
||||||
isESRGANAvailable: boolean;
|
isESRGANAvailable: boolean;
|
||||||
@ -97,12 +97,16 @@ export interface SystemState
|
|||||||
* Whether or not the OpenAPI schema was received and parsed
|
* Whether or not the OpenAPI schema was received and parsed
|
||||||
*/
|
*/
|
||||||
wasSchemaParsed: boolean;
|
wasSchemaParsed: boolean;
|
||||||
|
/**
|
||||||
|
* The console output logging level
|
||||||
|
*/
|
||||||
|
consoleLogLevel: InvokeLogLevel;
|
||||||
|
shouldLogToConsole: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialSystemState: SystemState = {
|
const initialSystemState: SystemState = {
|
||||||
isConnected: false,
|
isConnected: false,
|
||||||
isProcessing: false,
|
isProcessing: false,
|
||||||
log: [],
|
|
||||||
shouldShowLogViewer: false,
|
shouldShowLogViewer: false,
|
||||||
shouldDisplayInProgressType: 'latents',
|
shouldDisplayInProgressType: 'latents',
|
||||||
shouldDisplayGuides: true,
|
shouldDisplayGuides: true,
|
||||||
@ -144,11 +148,10 @@ const initialSystemState: SystemState = {
|
|||||||
cancelType: 'immediate',
|
cancelType: 'immediate',
|
||||||
isCancelScheduled: false,
|
isCancelScheduled: false,
|
||||||
subscribedNodeIds: [],
|
subscribedNodeIds: [],
|
||||||
// shouldTransformUrls: false,
|
|
||||||
// disabledTabs: [],
|
|
||||||
// disabledFeatures: [],
|
|
||||||
wereModelsReceived: false,
|
wereModelsReceived: false,
|
||||||
wasSchemaParsed: false,
|
wasSchemaParsed: false,
|
||||||
|
consoleLogLevel: 'error',
|
||||||
|
shouldLogToConsole: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const systemSlice = createSlice({
|
export const systemSlice = createSlice({
|
||||||
@ -189,25 +192,6 @@ export const systemSlice = createSlice({
|
|||||||
? i18n.t('common.statusConnected')
|
? i18n.t('common.statusConnected')
|
||||||
: i18n.t('common.statusDisconnected');
|
: i18n.t('common.statusDisconnected');
|
||||||
},
|
},
|
||||||
addLogEntry: (
|
|
||||||
state,
|
|
||||||
action: PayloadAction<{
|
|
||||||
timestamp: string;
|
|
||||||
message: string;
|
|
||||||
level?: LogLevel;
|
|
||||||
}>
|
|
||||||
) => {
|
|
||||||
const { timestamp, message, level } = action.payload;
|
|
||||||
const logLevel = level || 'info';
|
|
||||||
|
|
||||||
const entry: LogEntry = {
|
|
||||||
timestamp,
|
|
||||||
message,
|
|
||||||
level: logLevel,
|
|
||||||
};
|
|
||||||
|
|
||||||
state.log.push(entry);
|
|
||||||
},
|
|
||||||
setShouldShowLogViewer: (state, action: PayloadAction<boolean>) => {
|
setShouldShowLogViewer: (state, action: PayloadAction<boolean>) => {
|
||||||
state.shouldShowLogViewer = action.payload;
|
state.shouldShowLogViewer = action.payload;
|
||||||
},
|
},
|
||||||
@ -346,6 +330,12 @@ export const systemSlice = createSlice({
|
|||||||
subscribedNodeIdsSet: (state, action: PayloadAction<string[]>) => {
|
subscribedNodeIdsSet: (state, action: PayloadAction<string[]>) => {
|
||||||
state.subscribedNodeIds = action.payload;
|
state.subscribedNodeIds = action.payload;
|
||||||
},
|
},
|
||||||
|
consoleLogLevelChanged: (state, action: PayloadAction<LogLevelName>) => {
|
||||||
|
state.consoleLogLevel = action.payload;
|
||||||
|
},
|
||||||
|
shouldLogToConsoleChanged: (state, action: PayloadAction<boolean>) => {
|
||||||
|
state.shouldLogToConsole = action.payload;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
extraReducers(builder) {
|
extraReducers(builder) {
|
||||||
/**
|
/**
|
||||||
@ -353,7 +343,6 @@ export const systemSlice = createSlice({
|
|||||||
*/
|
*/
|
||||||
builder.addCase(socketSubscribed, (state, action) => {
|
builder.addCase(socketSubscribed, (state, action) => {
|
||||||
state.sessionId = action.payload.sessionId;
|
state.sessionId = action.payload.sessionId;
|
||||||
console.log(`Subscribed to session ${action.payload.sessionId}`);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -371,11 +360,6 @@ export const systemSlice = createSlice({
|
|||||||
|
|
||||||
state.isConnected = true;
|
state.isConnected = true;
|
||||||
state.currentStatus = i18n.t('common.statusConnected');
|
state.currentStatus = i18n.t('common.statusConnected');
|
||||||
state.log.push({
|
|
||||||
timestamp,
|
|
||||||
message: `Connected to server`,
|
|
||||||
level: 'info',
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -386,11 +370,6 @@ export const systemSlice = createSlice({
|
|||||||
|
|
||||||
state.isConnected = false;
|
state.isConnected = false;
|
||||||
state.currentStatus = i18n.t('common.statusDisconnected');
|
state.currentStatus = i18n.t('common.statusDisconnected');
|
||||||
state.log.push({
|
|
||||||
timestamp,
|
|
||||||
message: `Disconnected from server`,
|
|
||||||
level: 'error',
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -433,15 +412,6 @@ export const systemSlice = createSlice({
|
|||||||
state.totalSteps = 0;
|
state.totalSteps = 0;
|
||||||
state.progressImage = null;
|
state.progressImage = null;
|
||||||
state.currentStatus = i18n.t('common.statusProcessingComplete');
|
state.currentStatus = i18n.t('common.statusProcessingComplete');
|
||||||
|
|
||||||
// TODO: handle logging for other invocation types
|
|
||||||
if (isImageOutput(data.result)) {
|
|
||||||
state.log.push({
|
|
||||||
timestamp,
|
|
||||||
message: `Generated: ${data.result.image.image_name}`,
|
|
||||||
level: 'info',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -450,12 +420,6 @@ export const systemSlice = createSlice({
|
|||||||
builder.addCase(invocationError, (state, action) => {
|
builder.addCase(invocationError, (state, action) => {
|
||||||
const { data, timestamp } = action.payload;
|
const { data, timestamp } = action.payload;
|
||||||
|
|
||||||
state.log.push({
|
|
||||||
timestamp,
|
|
||||||
message: `Server error: ${data.error}`,
|
|
||||||
level: 'error',
|
|
||||||
});
|
|
||||||
|
|
||||||
state.wasErrorSeen = true;
|
state.wasErrorSeen = true;
|
||||||
state.progressImage = null;
|
state.progressImage = null;
|
||||||
state.isProcessing = false;
|
state.isProcessing = false;
|
||||||
@ -463,12 +427,6 @@ export const systemSlice = createSlice({
|
|||||||
state.toastQueue.push(
|
state.toastQueue.push(
|
||||||
makeToast({ title: i18n.t('toast.serverError'), status: 'error' })
|
makeToast({ title: i18n.t('toast.serverError'), status: 'error' })
|
||||||
);
|
);
|
||||||
|
|
||||||
state.log.push({
|
|
||||||
timestamp,
|
|
||||||
message: `Server error: ${data.error}`,
|
|
||||||
level: 'error',
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -495,12 +453,6 @@ export const systemSlice = createSlice({
|
|||||||
state.toastQueue.push(
|
state.toastQueue.push(
|
||||||
makeToast({ title: i18n.t('toast.canceled'), status: 'warning' })
|
makeToast({ title: i18n.t('toast.canceled'), status: 'warning' })
|
||||||
);
|
);
|
||||||
|
|
||||||
state.log.push({
|
|
||||||
timestamp,
|
|
||||||
message: `Processing canceled`,
|
|
||||||
level: 'warning',
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -529,7 +481,6 @@ export const systemSlice = createSlice({
|
|||||||
export const {
|
export const {
|
||||||
setShouldDisplayInProgressType,
|
setShouldDisplayInProgressType,
|
||||||
setIsProcessing,
|
setIsProcessing,
|
||||||
addLogEntry,
|
|
||||||
setShouldShowLogViewer,
|
setShouldShowLogViewer,
|
||||||
setIsConnected,
|
setIsConnected,
|
||||||
setSocketId,
|
setSocketId,
|
||||||
@ -562,6 +513,8 @@ export const {
|
|||||||
scheduledCancelAborted,
|
scheduledCancelAborted,
|
||||||
cancelTypeChanged,
|
cancelTypeChanged,
|
||||||
subscribedNodeIdsSet,
|
subscribedNodeIdsSet,
|
||||||
|
consoleLogLevelChanged,
|
||||||
|
shouldLogToConsoleChanged,
|
||||||
} = systemSlice.actions;
|
} = systemSlice.actions;
|
||||||
|
|
||||||
export default systemSlice.reducer;
|
export default systemSlice.reducer;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { createAction } from '@reduxjs/toolkit';
|
import { createAction } from '@reduxjs/toolkit';
|
||||||
import {
|
import {
|
||||||
GeneratorProgressEvent,
|
GeneratorProgressEvent,
|
||||||
|
GraphExecutionStateCompleteEvent,
|
||||||
InvocationCompleteEvent,
|
InvocationCompleteEvent,
|
||||||
InvocationErrorEvent,
|
InvocationErrorEvent,
|
||||||
InvocationStartedEvent,
|
InvocationStartedEvent,
|
||||||
@ -45,6 +46,10 @@ export const invocationError = createAction<
|
|||||||
BaseSocketPayload & { data: InvocationErrorEvent }
|
BaseSocketPayload & { data: InvocationErrorEvent }
|
||||||
>('socket/invocationError');
|
>('socket/invocationError');
|
||||||
|
|
||||||
|
export const graphExecutionStateComplete = createAction<
|
||||||
|
BaseSocketPayload & { data: GraphExecutionStateCompleteEvent }
|
||||||
|
>('socket/graphExecutionStateComplete');
|
||||||
|
|
||||||
export const generatorProgress = createAction<
|
export const generatorProgress = createAction<
|
||||||
BaseSocketPayload & { data: GeneratorProgressEvent }
|
BaseSocketPayload & { data: GeneratorProgressEvent }
|
||||||
>('socket/generatorProgress');
|
>('socket/generatorProgress');
|
||||||
|
@ -6,13 +6,9 @@ import {
|
|||||||
ServerToClientEvents,
|
ServerToClientEvents,
|
||||||
} from 'services/events/types';
|
} from 'services/events/types';
|
||||||
import {
|
import {
|
||||||
generatorProgress,
|
|
||||||
invocationComplete,
|
invocationComplete,
|
||||||
invocationError,
|
|
||||||
invocationStarted,
|
|
||||||
socketConnected,
|
socketConnected,
|
||||||
socketDisconnected,
|
socketDisconnected,
|
||||||
socketReset,
|
|
||||||
socketSubscribed,
|
socketSubscribed,
|
||||||
socketUnsubscribed,
|
socketUnsubscribed,
|
||||||
} from './actions';
|
} from './actions';
|
||||||
@ -25,7 +21,6 @@ import { getTimestamp } from 'common/util/getTimestamp';
|
|||||||
import {
|
import {
|
||||||
sessionInvoked,
|
sessionInvoked,
|
||||||
isFulfilledSessionCreatedAction,
|
isFulfilledSessionCreatedAction,
|
||||||
sessionCanceled,
|
|
||||||
} from 'services/thunks/session';
|
} from 'services/thunks/session';
|
||||||
import { OpenAPI } from 'services/api';
|
import { OpenAPI } from 'services/api';
|
||||||
import { receivedModels } from 'services/thunks/model';
|
import { receivedModels } from 'services/thunks/model';
|
||||||
@ -33,6 +28,9 @@ import { receivedOpenAPISchema } from 'services/thunks/schema';
|
|||||||
import { isImageOutput } from 'services/types/guards';
|
import { isImageOutput } from 'services/types/guards';
|
||||||
import { imageReceived, thumbnailReceived } from 'services/thunks/image';
|
import { imageReceived, thumbnailReceived } from 'services/thunks/image';
|
||||||
import { setEventListeners } from 'services/events/util/setEventListeners';
|
import { setEventListeners } from 'services/events/util/setEventListeners';
|
||||||
|
import { log } from 'app/logging/useLogger';
|
||||||
|
|
||||||
|
const moduleLog = log.child({ namespace: 'socketio' });
|
||||||
|
|
||||||
export const socketMiddleware = () => {
|
export const socketMiddleware = () => {
|
||||||
let areListenersSet = false;
|
let areListenersSet = false;
|
||||||
@ -91,6 +89,8 @@ export const socketMiddleware = () => {
|
|||||||
// Must happen in middleware to get access to `dispatch`
|
// Must happen in middleware to get access to `dispatch`
|
||||||
if (!areListenersSet) {
|
if (!areListenersSet) {
|
||||||
socket.on('connect', () => {
|
socket.on('connect', () => {
|
||||||
|
moduleLog.debug('Connected');
|
||||||
|
|
||||||
dispatch(socketConnected({ timestamp: getTimestamp() }));
|
dispatch(socketConnected({ timestamp: getTimestamp() }));
|
||||||
|
|
||||||
const { results, uploads, models, nodes, config, system } =
|
const { results, uploads, models, nodes, config, system } =
|
||||||
@ -116,7 +116,12 @@ export const socketMiddleware = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (system.sessionId) {
|
if (system.sessionId) {
|
||||||
console.log(`Re-subscribing to session ${system.sessionId}`);
|
const sessionLog = moduleLog.child({ sessionId: system.sessionId });
|
||||||
|
|
||||||
|
sessionLog.debug(
|
||||||
|
`Subscribed to existing session (${system.sessionId})`
|
||||||
|
);
|
||||||
|
|
||||||
socket.emit('subscribe', { session: system.sessionId });
|
socket.emit('subscribe', { session: system.sessionId });
|
||||||
dispatch(
|
dispatch(
|
||||||
socketSubscribed({
|
socketSubscribed({
|
||||||
@ -124,11 +129,12 @@ export const socketMiddleware = () => {
|
|||||||
timestamp: getTimestamp(),
|
timestamp: getTimestamp(),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
setEventListeners({ socket, store });
|
setEventListeners({ socket, store, sessionLog });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('disconnect', () => {
|
socket.on('disconnect', () => {
|
||||||
|
moduleLog.debug('Disconnected');
|
||||||
dispatch(socketDisconnected({ timestamp: getTimestamp() }));
|
dispatch(socketDisconnected({ timestamp: getTimestamp() }));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -140,6 +146,8 @@ export const socketMiddleware = () => {
|
|||||||
|
|
||||||
// Everything else only happens once we have created a session
|
// Everything else only happens once we have created a session
|
||||||
if (isFulfilledSessionCreatedAction(action)) {
|
if (isFulfilledSessionCreatedAction(action)) {
|
||||||
|
const sessionId = action.payload.id;
|
||||||
|
const sessionLog = moduleLog.child({ sessionId });
|
||||||
const oldSessionId = getState().system.sessionId;
|
const oldSessionId = getState().system.sessionId;
|
||||||
|
|
||||||
// const subscribedNodeIds = getState().system.subscribedNodeIds;
|
// const subscribedNodeIds = getState().system.subscribedNodeIds;
|
||||||
@ -152,6 +160,10 @@ export const socketMiddleware = () => {
|
|||||||
// };
|
// };
|
||||||
|
|
||||||
if (oldSessionId) {
|
if (oldSessionId) {
|
||||||
|
sessionLog.debug(
|
||||||
|
{ oldSessionId },
|
||||||
|
`Unsubscribed from old session (${oldSessionId})`
|
||||||
|
);
|
||||||
// Unsubscribe when invocations complete
|
// Unsubscribe when invocations complete
|
||||||
socket.emit('unsubscribe', {
|
socket.emit('unsubscribe', {
|
||||||
session: oldSessionId,
|
session: oldSessionId,
|
||||||
@ -176,8 +188,7 @@ export const socketMiddleware = () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const sessionId = action.payload.id;
|
sessionLog.debug(`Subscribe to new session (${sessionId})`);
|
||||||
|
|
||||||
socket.emit('subscribe', { session: sessionId });
|
socket.emit('subscribe', { session: sessionId });
|
||||||
dispatch(
|
dispatch(
|
||||||
socketSubscribed({
|
socketSubscribed({
|
||||||
@ -185,7 +196,7 @@ export const socketMiddleware = () => {
|
|||||||
timestamp: getTimestamp(),
|
timestamp: getTimestamp(),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
setEventListeners({ socket, store });
|
setEventListeners({ socket, store, sessionLog });
|
||||||
|
|
||||||
// Finally we actually invoke the session, starting processing
|
// Finally we actually invoke the session, starting processing
|
||||||
dispatch(sessionInvoked({ sessionId }));
|
dispatch(sessionInvoked({ sessionId }));
|
||||||
|
@ -5,34 +5,42 @@ import { sessionCanceled } from 'services/thunks/session';
|
|||||||
import { Socket } from 'socket.io-client';
|
import { Socket } from 'socket.io-client';
|
||||||
import {
|
import {
|
||||||
generatorProgress,
|
generatorProgress,
|
||||||
|
graphExecutionStateComplete,
|
||||||
invocationComplete,
|
invocationComplete,
|
||||||
invocationError,
|
invocationError,
|
||||||
invocationStarted,
|
invocationStarted,
|
||||||
} from '../actions';
|
} from '../actions';
|
||||||
import { ClientToServerEvents, ServerToClientEvents } from '../types';
|
import { ClientToServerEvents, ServerToClientEvents } from '../types';
|
||||||
|
import { Logger } from 'roarr';
|
||||||
|
import { JsonObject } from 'roarr/dist/types';
|
||||||
|
|
||||||
type SetEventListenersArg = {
|
type SetEventListenersArg = {
|
||||||
socket: Socket<ServerToClientEvents, ClientToServerEvents>;
|
socket: Socket<ServerToClientEvents, ClientToServerEvents>;
|
||||||
store: MiddlewareAPI<AppDispatch, RootState>;
|
store: MiddlewareAPI<AppDispatch, RootState>;
|
||||||
|
sessionLog: Logger<JsonObject>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const setEventListeners = (arg: SetEventListenersArg) => {
|
export const setEventListeners = (arg: SetEventListenersArg) => {
|
||||||
const { socket, store } = arg;
|
const { socket, store, sessionLog } = arg;
|
||||||
const { dispatch, getState } = store;
|
const { dispatch, getState } = store;
|
||||||
// Set up listeners for the present subscription
|
// Set up listeners for the present subscription
|
||||||
socket.on('invocation_started', (data) => {
|
socket.on('invocation_started', (data) => {
|
||||||
|
sessionLog.child({ data }).info(`Invocation started (${data.node.type})`);
|
||||||
dispatch(invocationStarted({ data, timestamp: getTimestamp() }));
|
dispatch(invocationStarted({ data, timestamp: getTimestamp() }));
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('generator_progress', (data) => {
|
socket.on('generator_progress', (data) => {
|
||||||
|
sessionLog.child({ data }).trace(`Generator progress (${data.node.type})`);
|
||||||
dispatch(generatorProgress({ data, timestamp: getTimestamp() }));
|
dispatch(generatorProgress({ data, timestamp: getTimestamp() }));
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('invocation_error', (data) => {
|
socket.on('invocation_error', (data) => {
|
||||||
|
sessionLog.child({ data }).error(`Invocation error (${data.node.type})`);
|
||||||
dispatch(invocationError({ data, timestamp: getTimestamp() }));
|
dispatch(invocationError({ data, timestamp: getTimestamp() }));
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('invocation_complete', (data) => {
|
socket.on('invocation_complete', (data) => {
|
||||||
|
sessionLog.child({ data }).info(`Invocation complete (${data.node.type})`);
|
||||||
const sessionId = data.graph_execution_state_id;
|
const sessionId = data.graph_execution_state_id;
|
||||||
|
|
||||||
const { cancelType, isCancelScheduled } = getState().system;
|
const { cancelType, isCancelScheduled } = getState().system;
|
||||||
@ -51,4 +59,13 @@ export const setEventListeners = (arg: SetEventListenersArg) => {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
socket.on('graph_execution_state_complete', (data) => {
|
||||||
|
sessionLog
|
||||||
|
.child({ data })
|
||||||
|
.info(
|
||||||
|
`Graph execution state complete (${data.graph_execution_state_id})`
|
||||||
|
);
|
||||||
|
dispatch(graphExecutionStateComplete({ data, timestamp: getTimestamp() }));
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
|
import { log } from 'app/logging/useLogger';
|
||||||
import { createAppAsyncThunk } from 'app/store/storeUtils';
|
import { createAppAsyncThunk } from 'app/store/storeUtils';
|
||||||
import { ImagesService } from 'services/api';
|
import { ImagesService } from 'services/api';
|
||||||
|
|
||||||
export const IMAGES_PER_PAGE = 20;
|
export const IMAGES_PER_PAGE = 20;
|
||||||
|
|
||||||
|
const galleryLog = log.child({ namespace: 'gallery' });
|
||||||
|
|
||||||
export const receivedResultImagesPage = createAppAsyncThunk(
|
export const receivedResultImagesPage = createAppAsyncThunk(
|
||||||
'results/receivedResultImagesPage',
|
'results/receivedResultImagesPage',
|
||||||
async (_arg, { getState }) => {
|
async (_arg, { getState }) => {
|
||||||
@ -12,6 +15,8 @@ export const receivedResultImagesPage = createAppAsyncThunk(
|
|||||||
perPage: IMAGES_PER_PAGE,
|
perPage: IMAGES_PER_PAGE,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
galleryLog.info({ response }, `Received ${response.items.length} results`);
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -25,6 +30,8 @@ export const receivedUploadImagesPage = createAppAsyncThunk(
|
|||||||
perPage: IMAGES_PER_PAGE,
|
perPage: IMAGES_PER_PAGE,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
galleryLog.info({ response }, `Received ${response.items.length} uploads`);
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
import { isFulfilled, isRejected } from '@reduxjs/toolkit';
|
import { isFulfilled, isRejected } from '@reduxjs/toolkit';
|
||||||
|
import { log } from 'app/logging/useLogger';
|
||||||
import { createAppAsyncThunk } from 'app/store/storeUtils';
|
import { createAppAsyncThunk } from 'app/store/storeUtils';
|
||||||
import { imageSelected } from 'features/gallery/store/gallerySlice';
|
import { imageSelected } from 'features/gallery/store/gallerySlice';
|
||||||
import { clamp } from 'lodash-es';
|
import { clamp } from 'lodash-es';
|
||||||
import { ImagesService } from 'services/api';
|
import { ImagesService } from 'services/api';
|
||||||
import { getHeaders } from 'services/util/getHeaders';
|
import { getHeaders } from 'services/util/getHeaders';
|
||||||
|
|
||||||
|
const imagesLog = log.child({ namespace: 'image' });
|
||||||
|
|
||||||
type ImageReceivedArg = Parameters<(typeof ImagesService)['getImage']>[0];
|
type ImageReceivedArg = Parameters<(typeof ImagesService)['getImage']>[0];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -14,6 +17,9 @@ export const imageReceived = createAppAsyncThunk(
|
|||||||
'api/imageReceived',
|
'api/imageReceived',
|
||||||
async (arg: ImageReceivedArg, _thunkApi) => {
|
async (arg: ImageReceivedArg, _thunkApi) => {
|
||||||
const response = await ImagesService.getImage(arg);
|
const response = await ImagesService.getImage(arg);
|
||||||
|
|
||||||
|
imagesLog.info({ arg, response }, 'Received image');
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -29,6 +35,9 @@ export const thumbnailReceived = createAppAsyncThunk(
|
|||||||
'api/thumbnailReceived',
|
'api/thumbnailReceived',
|
||||||
async (arg: ThumbnailReceivedArg, _thunkApi) => {
|
async (arg: ThumbnailReceivedArg, _thunkApi) => {
|
||||||
const response = await ImagesService.getThumbnail(arg);
|
const response = await ImagesService.getThumbnail(arg);
|
||||||
|
|
||||||
|
imagesLog.info({ arg, response }, 'Received thumbnail');
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -43,6 +52,12 @@ export const imageUploaded = createAppAsyncThunk(
|
|||||||
async (arg: ImageUploadedArg, _thunkApi) => {
|
async (arg: ImageUploadedArg, _thunkApi) => {
|
||||||
const response = await ImagesService.uploadImage(arg);
|
const response = await ImagesService.uploadImage(arg);
|
||||||
const { location } = getHeaders(response);
|
const { location } = getHeaders(response);
|
||||||
|
|
||||||
|
imagesLog.info(
|
||||||
|
{ arg: '<Blob>', response, location },
|
||||||
|
`Image uploaded (${response.image_name})`
|
||||||
|
);
|
||||||
|
|
||||||
return { response, location };
|
return { response, location };
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -96,6 +111,11 @@ export const imageDeleted = createAppAsyncThunk(
|
|||||||
|
|
||||||
const response = await ImagesService.deleteImage(arg);
|
const response = await ImagesService.deleteImage(arg);
|
||||||
|
|
||||||
|
imagesLog.info(
|
||||||
|
{ arg, response },
|
||||||
|
`Image deleted (${arg.imageType} - ${arg.imageName})`
|
||||||
|
);
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
|
import { log } from 'app/logging/useLogger';
|
||||||
import { createAppAsyncThunk } from 'app/store/storeUtils';
|
import { createAppAsyncThunk } from 'app/store/storeUtils';
|
||||||
import { Model } from 'features/system/store/modelSlice';
|
import { Model } from 'features/system/store/modelSlice';
|
||||||
import { reduce } from 'lodash-es';
|
import { reduce, size } from 'lodash-es';
|
||||||
import { ModelsService } from 'services/api';
|
import { ModelsService } from 'services/api';
|
||||||
|
|
||||||
|
const models = log.child({ namespace: 'model' });
|
||||||
|
|
||||||
export const IMAGES_PER_PAGE = 20;
|
export const IMAGES_PER_PAGE = 20;
|
||||||
|
|
||||||
export const receivedModels = createAppAsyncThunk(
|
export const receivedModels = createAppAsyncThunk(
|
||||||
'models/receivedModels',
|
'models/receivedModels',
|
||||||
async (_arg) => {
|
async (_) => {
|
||||||
const response = await ModelsService.listModels();
|
const response = await ModelsService.listModels();
|
||||||
|
|
||||||
const deserializedModels = reduce(
|
const deserializedModels = reduce(
|
||||||
response.models,
|
response.models,
|
||||||
(modelsAccumulator, model, modelName) => {
|
(modelsAccumulator, model, modelName) => {
|
||||||
@ -19,6 +23,8 @@ export const receivedModels = createAppAsyncThunk(
|
|||||||
{} as Record<string, Model>
|
{} as Record<string, Model>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
models.info({ response }, `Received ${size(response.models)} models`);
|
||||||
|
|
||||||
return deserializedModels;
|
return deserializedModels;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
import { createAsyncThunk } from '@reduxjs/toolkit';
|
import { createAsyncThunk } from '@reduxjs/toolkit';
|
||||||
|
import { log } from 'app/logging/useLogger';
|
||||||
import { parsedOpenAPISchema } from 'features/nodes/store/nodesSlice';
|
import { parsedOpenAPISchema } from 'features/nodes/store/nodesSlice';
|
||||||
import { OpenAPIV3 } from 'openapi-types';
|
import { OpenAPIV3 } from 'openapi-types';
|
||||||
|
|
||||||
|
const schemaLog = log.child({ namespace: 'schema' });
|
||||||
|
|
||||||
export const receivedOpenAPISchema = createAsyncThunk(
|
export const receivedOpenAPISchema = createAsyncThunk(
|
||||||
'nodes/receivedOpenAPISchema',
|
'nodes/receivedOpenAPISchema',
|
||||||
async (_, { dispatch }): Promise<OpenAPIV3.Document> => {
|
async (_, { dispatch }): Promise<OpenAPIV3.Document> => {
|
||||||
const response = await fetch(`openapi.json`);
|
const response = await fetch(`openapi.json`);
|
||||||
const openAPISchema = (await response.json()) as OpenAPIV3.Document;
|
const openAPISchema = await response.json();
|
||||||
|
|
||||||
console.debug('OpenAPI schema: ', openAPISchema);
|
schemaLog.info({ openAPISchema }, 'Received OpenAPI schema');
|
||||||
|
|
||||||
dispatch(parsedOpenAPISchema(openAPISchema));
|
dispatch(parsedOpenAPISchema(openAPISchema as OpenAPIV3.Document));
|
||||||
|
|
||||||
return openAPISchema;
|
return openAPISchema;
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,9 @@ import { SessionsService } from 'services/api';
|
|||||||
import { buildLinearGraph as buildGenerateGraph } from 'features/nodes/util/linearGraphBuilder/buildLinearGraph';
|
import { buildLinearGraph as buildGenerateGraph } from 'features/nodes/util/linearGraphBuilder/buildLinearGraph';
|
||||||
import { isAnyOf, isFulfilled } from '@reduxjs/toolkit';
|
import { isAnyOf, isFulfilled } from '@reduxjs/toolkit';
|
||||||
import { buildNodesGraph } from 'features/nodes/util/nodesGraphBuilder/buildNodesGraph';
|
import { buildNodesGraph } from 'features/nodes/util/nodesGraphBuilder/buildNodesGraph';
|
||||||
|
import { log } from 'app/logging/useLogger';
|
||||||
|
|
||||||
|
const sessionLog = log.child({ namespace: 'session' });
|
||||||
|
|
||||||
export const generateGraphBuilt = createAppAsyncThunk(
|
export const generateGraphBuilt = createAppAsyncThunk(
|
||||||
'api/generateGraphBuilt',
|
'api/generateGraphBuilt',
|
||||||
@ -43,12 +46,12 @@ type SessionCreatedArg = {
|
|||||||
export const sessionCreated = createAppAsyncThunk(
|
export const sessionCreated = createAppAsyncThunk(
|
||||||
'api/sessionCreated',
|
'api/sessionCreated',
|
||||||
async (arg: SessionCreatedArg, { dispatch, getState }) => {
|
async (arg: SessionCreatedArg, { dispatch, getState }) => {
|
||||||
console.log('Session created, graph: ', arg.graph);
|
|
||||||
|
|
||||||
const response = await SessionsService.createSession({
|
const response = await SessionsService.createSession({
|
||||||
requestBody: arg.graph,
|
requestBody: arg.graph,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
sessionLog.info({ arg, response }, `Session created (${response.id})`);
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -74,6 +77,8 @@ export const nodeAdded = createAppAsyncThunk(
|
|||||||
sessionId: arg.sessionId,
|
sessionId: arg.sessionId,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
sessionLog.info({ arg, response }, `Node added (${response})`);
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -91,6 +96,8 @@ export const sessionInvoked = createAppAsyncThunk(
|
|||||||
all: true,
|
all: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
sessionLog.info({ arg, response }, `Session invoked (${sessionId})`);
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -111,6 +118,8 @@ export const sessionCanceled = createAppAsyncThunk(
|
|||||||
sessionId,
|
sessionId,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
sessionLog.info({ arg, response }, `Session canceled (${sessionId})`);
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -127,6 +136,11 @@ export const listedSessions = createAppAsyncThunk(
|
|||||||
async (arg: SessionsListedArg, _thunkApi) => {
|
async (arg: SessionsListedArg, _thunkApi) => {
|
||||||
const response = await SessionsService.listSessions(arg);
|
const response = await SessionsService.listSessions(arg);
|
||||||
|
|
||||||
|
sessionLog.info(
|
||||||
|
{ arg, response },
|
||||||
|
`Sessions listed (${response.items.length})`
|
||||||
|
);
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -1421,6 +1421,15 @@
|
|||||||
redux-thunk "^2.4.2"
|
redux-thunk "^2.4.2"
|
||||||
reselect "^4.1.8"
|
reselect "^4.1.8"
|
||||||
|
|
||||||
|
"@roarr/browser-log-writer@^1.1.5":
|
||||||
|
version "1.1.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@roarr/browser-log-writer/-/browser-log-writer-1.1.5.tgz#755ff62ddaa297bb3488067408a7085db382352b"
|
||||||
|
integrity sha512-yLn//DRjh1/rUgZpZkwmT/5RqHYfkdOwGXWXnKBR3l/HE04DIhSVeYin3sc8aWHBa7s7WglQpYX/uw/WI6POpw==
|
||||||
|
dependencies:
|
||||||
|
boolean "^3.1.4"
|
||||||
|
globalthis "^1.0.2"
|
||||||
|
liqe "^3.6.0"
|
||||||
|
|
||||||
"@rollup/pluginutils@^4.2.1":
|
"@rollup/pluginutils@^4.2.1":
|
||||||
version "4.2.1"
|
version "4.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.2.1.tgz#e6c6c3aba0744edce3fb2074922d3776c0af2a6d"
|
resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.2.1.tgz#e6c6c3aba0744edce3fb2074922d3776c0af2a6d"
|
||||||
@ -2077,7 +2086,7 @@ aggregate-error@^3.0.0:
|
|||||||
clean-stack "^2.0.0"
|
clean-stack "^2.0.0"
|
||||||
indent-string "^4.0.0"
|
indent-string "^4.0.0"
|
||||||
|
|
||||||
ajv@^6.10.0, ajv@^6.12.4, ajv@~6.12.6:
|
ajv@^6.10.0, ajv@^6.11.0, ajv@^6.12.4, ajv@~6.12.6:
|
||||||
version "6.12.6"
|
version "6.12.6"
|
||||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
|
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
|
||||||
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
|
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
|
||||||
@ -2307,6 +2316,11 @@ bl@^4.1.0:
|
|||||||
inherits "^2.0.4"
|
inherits "^2.0.4"
|
||||||
readable-stream "^3.4.0"
|
readable-stream "^3.4.0"
|
||||||
|
|
||||||
|
boolean@^3.1.4:
|
||||||
|
version "3.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.2.0.tgz#9e5294af4e98314494cbb17979fa54ca159f116b"
|
||||||
|
integrity sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==
|
||||||
|
|
||||||
boxen@^5.0.0:
|
boxen@^5.0.0:
|
||||||
version "5.1.2"
|
version "5.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50"
|
resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50"
|
||||||
@ -2609,7 +2623,7 @@ commander@^10.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06"
|
resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06"
|
||||||
integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==
|
integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==
|
||||||
|
|
||||||
commander@^2.16.0, commander@^2.20.0, commander@^2.20.3, commander@^2.8.1:
|
commander@^2.16.0, commander@^2.19.0, commander@^2.20.0, commander@^2.20.3, commander@^2.8.1:
|
||||||
version "2.20.3"
|
version "2.20.3"
|
||||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
||||||
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
|
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
|
||||||
@ -2828,6 +2842,11 @@ deepmerge@^2.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170"
|
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170"
|
||||||
integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==
|
integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==
|
||||||
|
|
||||||
|
deepmerge@^4.2.2:
|
||||||
|
version "4.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a"
|
||||||
|
integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==
|
||||||
|
|
||||||
defaults@^1.0.3:
|
defaults@^1.0.3:
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a"
|
resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a"
|
||||||
@ -3031,6 +3050,11 @@ dir-glob@^3.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
path-type "^4.0.0"
|
path-type "^4.0.0"
|
||||||
|
|
||||||
|
discontinuous-range@1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a"
|
||||||
|
integrity sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==
|
||||||
|
|
||||||
doctrine@^2.1.0:
|
doctrine@^2.1.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
|
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
|
||||||
@ -3442,11 +3466,28 @@ fast-json-stable-stringify@^2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
|
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
|
||||||
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
|
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
|
||||||
|
|
||||||
|
fast-json-stringify@^2.7.10:
|
||||||
|
version "2.7.13"
|
||||||
|
resolved "https://registry.yarnpkg.com/fast-json-stringify/-/fast-json-stringify-2.7.13.tgz#277aa86c2acba4d9851bd6108ed657aa327ed8c0"
|
||||||
|
integrity sha512-ar+hQ4+OIurUGjSJD1anvYSDcUflywhKjfxnsW4TBTD7+u0tJufv6DKRWoQk3vI6YBOWMoz0TQtfbe7dxbQmvA==
|
||||||
|
dependencies:
|
||||||
|
ajv "^6.11.0"
|
||||||
|
deepmerge "^4.2.2"
|
||||||
|
rfdc "^1.2.0"
|
||||||
|
string-similarity "^4.0.1"
|
||||||
|
|
||||||
fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6:
|
fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6:
|
||||||
version "2.0.6"
|
version "2.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
|
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
|
||||||
integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
|
integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
|
||||||
|
|
||||||
|
fast-printf@^1.6.9:
|
||||||
|
version "1.6.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/fast-printf/-/fast-printf-1.6.9.tgz#212f56570d2dc8ccdd057ee93d50dd414d07d676"
|
||||||
|
integrity sha512-FChq8hbz65WMj4rstcQsFB0O7Cy++nmbNfLYnD9cYv2cRn8EG6k/MGn9kO/tjO66t09DLDugj3yL+V2o6Qftrg==
|
||||||
|
dependencies:
|
||||||
|
boolean "^3.1.4"
|
||||||
|
|
||||||
fastq@^1.6.0:
|
fastq@^1.6.0:
|
||||||
version "1.15.0"
|
version "1.15.0"
|
||||||
resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a"
|
resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a"
|
||||||
@ -3768,7 +3809,7 @@ globals@^13.19.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
type-fest "^0.20.2"
|
type-fest "^0.20.2"
|
||||||
|
|
||||||
globalthis@^1.0.3:
|
globalthis@^1.0.2, globalthis@^1.0.3:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf"
|
resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf"
|
||||||
integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==
|
integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==
|
||||||
@ -4465,6 +4506,14 @@ lint-staged@^13.2.2:
|
|||||||
string-argv "^0.3.1"
|
string-argv "^0.3.1"
|
||||||
yaml "^2.2.2"
|
yaml "^2.2.2"
|
||||||
|
|
||||||
|
liqe@^3.6.0:
|
||||||
|
version "3.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/liqe/-/liqe-3.6.0.tgz#2d05376e93ff9f4bfdb3e76481f6456d165b499f"
|
||||||
|
integrity sha512-CYVQr0bk5CCTkX3wW2MdyEWdr9FHLpiE/1cQXQ36Sdjn5gv7JIpm9jnkovFwiVzumw7f6JDFXpljwUY+fAcFYQ==
|
||||||
|
dependencies:
|
||||||
|
nearley "^2.20.1"
|
||||||
|
ts-error "^1.0.6"
|
||||||
|
|
||||||
listr2@^5.0.7:
|
listr2@^5.0.7:
|
||||||
version "5.0.8"
|
version "5.0.8"
|
||||||
resolved "https://registry.yarnpkg.com/listr2/-/listr2-5.0.8.tgz#a9379ffeb4bd83a68931a65fb223a11510d6ba23"
|
resolved "https://registry.yarnpkg.com/listr2/-/listr2-5.0.8.tgz#a9379ffeb4bd83a68931a65fb223a11510d6ba23"
|
||||||
@ -4714,6 +4763,11 @@ module-lookup-amd@^7.0.1:
|
|||||||
requirejs "^2.3.5"
|
requirejs "^2.3.5"
|
||||||
requirejs-config-file "^4.0.0"
|
requirejs-config-file "^4.0.0"
|
||||||
|
|
||||||
|
moo@^0.5.0:
|
||||||
|
version "0.5.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/moo/-/moo-0.5.2.tgz#f9fe82473bc7c184b0d32e2215d3f6e67278733c"
|
||||||
|
integrity sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==
|
||||||
|
|
||||||
ms@2.1.2:
|
ms@2.1.2:
|
||||||
version "2.1.2"
|
version "2.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||||
@ -4734,6 +4788,16 @@ natural-compare@^1.4.0:
|
|||||||
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
||||||
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
|
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
|
||||||
|
|
||||||
|
nearley@^2.20.1:
|
||||||
|
version "2.20.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/nearley/-/nearley-2.20.1.tgz#246cd33eff0d012faf197ff6774d7ac78acdd474"
|
||||||
|
integrity sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==
|
||||||
|
dependencies:
|
||||||
|
commander "^2.19.0"
|
||||||
|
moo "^0.5.0"
|
||||||
|
railroad-diagrams "^1.0.0"
|
||||||
|
randexp "0.4.6"
|
||||||
|
|
||||||
neo-async@^2.6.0:
|
neo-async@^2.6.0:
|
||||||
version "2.6.2"
|
version "2.6.2"
|
||||||
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
|
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
|
||||||
@ -5215,6 +5279,19 @@ quote-unquote@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/quote-unquote/-/quote-unquote-1.0.0.tgz#67a9a77148effeaf81a4d428404a710baaac8a0b"
|
resolved "https://registry.yarnpkg.com/quote-unquote/-/quote-unquote-1.0.0.tgz#67a9a77148effeaf81a4d428404a710baaac8a0b"
|
||||||
integrity sha512-twwRO/ilhlG/FIgYeKGFqyHhoEhqgnKVkcmqMKi2r524gz3ZbDTcyFt38E9xjJI2vT+KbRNHVbnJ/e0I25Azwg==
|
integrity sha512-twwRO/ilhlG/FIgYeKGFqyHhoEhqgnKVkcmqMKi2r524gz3ZbDTcyFt38E9xjJI2vT+KbRNHVbnJ/e0I25Azwg==
|
||||||
|
|
||||||
|
railroad-diagrams@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz#eb7e6267548ddedfb899c1b90e57374559cddb7e"
|
||||||
|
integrity sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==
|
||||||
|
|
||||||
|
randexp@0.4.6:
|
||||||
|
version "0.4.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/randexp/-/randexp-0.4.6.tgz#e986ad5e5e31dae13ddd6f7b3019aa7c87f60ca3"
|
||||||
|
integrity sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==
|
||||||
|
dependencies:
|
||||||
|
discontinuous-range "1.0.0"
|
||||||
|
ret "~0.1.10"
|
||||||
|
|
||||||
rc@1.2.8, rc@^1.2.7, rc@^1.2.8:
|
rc@1.2.8, rc@^1.2.7, rc@^1.2.8:
|
||||||
version "1.2.8"
|
version "1.2.8"
|
||||||
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
|
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
|
||||||
@ -5554,12 +5631,17 @@ restore-cursor@^3.1.0:
|
|||||||
onetime "^5.1.0"
|
onetime "^5.1.0"
|
||||||
signal-exit "^3.0.2"
|
signal-exit "^3.0.2"
|
||||||
|
|
||||||
|
ret@~0.1.10:
|
||||||
|
version "0.1.15"
|
||||||
|
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
|
||||||
|
integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==
|
||||||
|
|
||||||
reusify@^1.0.4:
|
reusify@^1.0.4:
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
|
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
|
||||||
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
|
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
|
||||||
|
|
||||||
rfdc@^1.3.0:
|
rfdc@^1.2.0, rfdc@^1.3.0:
|
||||||
version "1.3.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b"
|
resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b"
|
||||||
integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==
|
integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==
|
||||||
@ -5578,6 +5660,18 @@ rimraf@^3.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
glob "^7.1.3"
|
glob "^7.1.3"
|
||||||
|
|
||||||
|
roarr@^7.15.0:
|
||||||
|
version "7.15.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/roarr/-/roarr-7.15.0.tgz#09b792f0cd31b4a7f91030bb1c47550ceec98ee4"
|
||||||
|
integrity sha512-CV9WefQfUXTX6wr8CrEMhfNef3sjIt9wNhE/5PNu4tNWsaoDNDXqq+OGn/RW9A1UPb0qc7FQlswXRaJJJsqn8A==
|
||||||
|
dependencies:
|
||||||
|
boolean "^3.1.4"
|
||||||
|
fast-json-stringify "^2.7.10"
|
||||||
|
fast-printf "^1.6.9"
|
||||||
|
globalthis "^1.0.2"
|
||||||
|
safe-stable-stringify "^2.4.1"
|
||||||
|
semver-compare "^1.0.0"
|
||||||
|
|
||||||
rollup-plugin-visualizer@^5.9.0:
|
rollup-plugin-visualizer@^5.9.0:
|
||||||
version "5.9.0"
|
version "5.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/rollup-plugin-visualizer/-/rollup-plugin-visualizer-5.9.0.tgz#013ac54fb6a9d7c9019e7eb77eced673399e5a0b"
|
resolved "https://registry.yarnpkg.com/rollup-plugin-visualizer/-/rollup-plugin-visualizer-5.9.0.tgz#013ac54fb6a9d7c9019e7eb77eced673399e5a0b"
|
||||||
@ -5630,6 +5724,11 @@ safe-regex-test@^1.0.0:
|
|||||||
get-intrinsic "^1.1.3"
|
get-intrinsic "^1.1.3"
|
||||||
is-regex "^1.1.4"
|
is-regex "^1.1.4"
|
||||||
|
|
||||||
|
safe-stable-stringify@^2.4.1:
|
||||||
|
version "2.4.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886"
|
||||||
|
integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==
|
||||||
|
|
||||||
sass-lookup@^3.0.0:
|
sass-lookup@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/sass-lookup/-/sass-lookup-3.0.0.tgz#3b395fa40569738ce857bc258e04df2617c48cac"
|
resolved "https://registry.yarnpkg.com/sass-lookup/-/sass-lookup-3.0.0.tgz#3b395fa40569738ce857bc258e04df2617c48cac"
|
||||||
@ -5644,6 +5743,11 @@ scheduler@^0.23.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
loose-envify "^1.1.0"
|
loose-envify "^1.1.0"
|
||||||
|
|
||||||
|
semver-compare@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"
|
||||||
|
integrity sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==
|
||||||
|
|
||||||
semver-diff@^3.1.1:
|
semver-diff@^3.1.1:
|
||||||
version "3.1.1"
|
version "3.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-3.1.1.tgz#05f77ce59f325e00e2706afd67bb506ddb1ca32b"
|
resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-3.1.1.tgz#05f77ce59f325e00e2706afd67bb506ddb1ca32b"
|
||||||
@ -5810,6 +5914,11 @@ string-argv@^0.3.1, string-argv@~0.3.1:
|
|||||||
resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da"
|
resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da"
|
||||||
integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==
|
integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==
|
||||||
|
|
||||||
|
string-similarity@^4.0.1:
|
||||||
|
version "4.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/string-similarity/-/string-similarity-4.0.4.tgz#42d01ab0b34660ea8a018da8f56a3309bb8b2a5b"
|
||||||
|
integrity sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ==
|
||||||
|
|
||||||
string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3:
|
string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3:
|
||||||
version "4.2.3"
|
version "4.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||||
@ -6032,6 +6141,11 @@ tree-kill@^1.2.2:
|
|||||||
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
|
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
|
||||||
integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==
|
integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==
|
||||||
|
|
||||||
|
ts-error@^1.0.6:
|
||||||
|
version "1.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/ts-error/-/ts-error-1.0.6.tgz#277496f2a28de6c184cfce8dfd5cdd03a4e6b0fc"
|
||||||
|
integrity sha512-tLJxacIQUM82IR7JO1UUkKlYuUTmoY9HBJAmNWFzheSlDS5SPMcNIepejHJa4BpPQLAcbRhRf3GDJzyj6rbKvA==
|
||||||
|
|
||||||
ts-graphviz@^1.5.0:
|
ts-graphviz@^1.5.0:
|
||||||
version "1.6.1"
|
version "1.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/ts-graphviz/-/ts-graphviz-1.6.1.tgz#f44525c048cb8c8c188b7324d2a91015fd31ceaf"
|
resolved "https://registry.yarnpkg.com/ts-graphviz/-/ts-graphviz-1.6.1.tgz#f44525c048cb8c8c188b7324d2a91015fd31ceaf"
|
||||||
|
Loading…
Reference in New Issue
Block a user