mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-09-22 08:12:00 +02:00
✨ refactor: Imports to Prevent Circular Type Refs (#8423)
This commit is contained in:
parent
f1b29ffb45
commit
170cc340d8
12 changed files with 201 additions and 196 deletions
|
@ -1,4 +1,4 @@
|
||||||
import React, { memo, useMemo, useRef, useEffect } from 'react';
|
import React, { memo, useMemo } from 'react';
|
||||||
import remarkGfm from 'remark-gfm';
|
import remarkGfm from 'remark-gfm';
|
||||||
import remarkMath from 'remark-math';
|
import remarkMath from 'remark-math';
|
||||||
import supersub from 'remark-supersub';
|
import supersub from 'remark-supersub';
|
||||||
|
@ -7,168 +7,16 @@ import { useRecoilValue } from 'recoil';
|
||||||
import ReactMarkdown from 'react-markdown';
|
import ReactMarkdown from 'react-markdown';
|
||||||
import rehypeHighlight from 'rehype-highlight';
|
import rehypeHighlight from 'rehype-highlight';
|
||||||
import remarkDirective from 'remark-directive';
|
import remarkDirective from 'remark-directive';
|
||||||
import { PermissionTypes, Permissions } from 'librechat-data-provider';
|
|
||||||
import type { Pluggable } from 'unified';
|
import type { Pluggable } from 'unified';
|
||||||
import {
|
|
||||||
useToastContext,
|
|
||||||
ArtifactProvider,
|
|
||||||
CodeBlockProvider,
|
|
||||||
useCodeBlockContext,
|
|
||||||
} from '~/Providers';
|
|
||||||
import { Citation, CompositeCitation, HighlightedText } from '~/components/Web/Citation';
|
import { Citation, CompositeCitation, HighlightedText } from '~/components/Web/Citation';
|
||||||
import { Artifact, artifactPlugin } from '~/components/Artifacts/Artifact';
|
import { Artifact, artifactPlugin } from '~/components/Artifacts/Artifact';
|
||||||
import { langSubset, preprocessLaTeX, handleDoubleClick } from '~/utils';
|
import { ArtifactProvider, CodeBlockProvider } from '~/Providers';
|
||||||
import CodeBlock from '~/components/Messages/Content/CodeBlock';
|
|
||||||
import MarkdownErrorBoundary from './MarkdownErrorBoundary';
|
import MarkdownErrorBoundary from './MarkdownErrorBoundary';
|
||||||
import useHasAccess from '~/hooks/Roles/useHasAccess';
|
import { langSubset, preprocessLaTeX } from '~/utils';
|
||||||
import { unicodeCitation } from '~/components/Web';
|
import { unicodeCitation } from '~/components/Web';
|
||||||
import { useFileDownload } from '~/data-provider';
|
import { code, a, p } from './MarkdownComponents';
|
||||||
import useLocalize from '~/hooks/useLocalize';
|
|
||||||
import store from '~/store';
|
import store from '~/store';
|
||||||
|
|
||||||
type TCodeProps = {
|
|
||||||
inline?: boolean;
|
|
||||||
className?: string;
|
|
||||||
children: React.ReactNode;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const code: React.ElementType = memo(({ className, children }: TCodeProps) => {
|
|
||||||
const canRunCode = useHasAccess({
|
|
||||||
permissionType: PermissionTypes.RUN_CODE,
|
|
||||||
permission: Permissions.USE,
|
|
||||||
});
|
|
||||||
const match = /language-(\w+)/.exec(className ?? '');
|
|
||||||
const lang = match && match[1];
|
|
||||||
const isMath = lang === 'math';
|
|
||||||
const isSingleLine = typeof children === 'string' && children.split('\n').length === 1;
|
|
||||||
|
|
||||||
const { getNextIndex, resetCounter } = useCodeBlockContext();
|
|
||||||
const blockIndex = useRef(getNextIndex(isMath || isSingleLine)).current;
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
resetCounter();
|
|
||||||
}, [children, resetCounter]);
|
|
||||||
|
|
||||||
if (isMath) {
|
|
||||||
return <>{children}</>;
|
|
||||||
} else if (isSingleLine) {
|
|
||||||
return (
|
|
||||||
<code onDoubleClick={handleDoubleClick} className={className}>
|
|
||||||
{children}
|
|
||||||
</code>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<CodeBlock
|
|
||||||
lang={lang ?? 'text'}
|
|
||||||
codeChildren={children}
|
|
||||||
blockIndex={blockIndex}
|
|
||||||
allowExecution={canRunCode}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
export const codeNoExecution: React.ElementType = memo(({ className, children }: TCodeProps) => {
|
|
||||||
const match = /language-(\w+)/.exec(className ?? '');
|
|
||||||
const lang = match && match[1];
|
|
||||||
|
|
||||||
if (lang === 'math') {
|
|
||||||
return children;
|
|
||||||
} else if (typeof children === 'string' && children.split('\n').length === 1) {
|
|
||||||
return (
|
|
||||||
<code onDoubleClick={handleDoubleClick} className={className}>
|
|
||||||
{children}
|
|
||||||
</code>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return <CodeBlock lang={lang ?? 'text'} codeChildren={children} allowExecution={false} />;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
type TAnchorProps = {
|
|
||||||
href: string;
|
|
||||||
children: React.ReactNode;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const a: React.ElementType = memo(({ href, children }: TAnchorProps) => {
|
|
||||||
const user = useRecoilValue(store.user);
|
|
||||||
const { showToast } = useToastContext();
|
|
||||||
const localize = useLocalize();
|
|
||||||
|
|
||||||
const {
|
|
||||||
file_id = '',
|
|
||||||
filename = '',
|
|
||||||
filepath,
|
|
||||||
} = useMemo(() => {
|
|
||||||
const pattern = new RegExp(`(?:files|outputs)/${user?.id}/([^\\s]+)`);
|
|
||||||
const match = href.match(pattern);
|
|
||||||
if (match && match[0]) {
|
|
||||||
const path = match[0];
|
|
||||||
const parts = path.split('/');
|
|
||||||
const name = parts.pop();
|
|
||||||
const file_id = parts.pop();
|
|
||||||
return { file_id, filename: name, filepath: path };
|
|
||||||
}
|
|
||||||
return { file_id: '', filename: '', filepath: '' };
|
|
||||||
}, [user?.id, href]);
|
|
||||||
|
|
||||||
const { refetch: downloadFile } = useFileDownload(user?.id ?? '', file_id);
|
|
||||||
const props: { target?: string; onClick?: React.MouseEventHandler } = { target: '_new' };
|
|
||||||
|
|
||||||
if (!file_id || !filename) {
|
|
||||||
return (
|
|
||||||
<a href={href} {...props}>
|
|
||||||
{children}
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleDownload = async (event: React.MouseEvent<HTMLAnchorElement>) => {
|
|
||||||
event.preventDefault();
|
|
||||||
try {
|
|
||||||
const stream = await downloadFile();
|
|
||||||
if (stream.data == null || stream.data === '') {
|
|
||||||
console.error('Error downloading file: No data found');
|
|
||||||
showToast({
|
|
||||||
status: 'error',
|
|
||||||
message: localize('com_ui_download_error'),
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const link = document.createElement('a');
|
|
||||||
link.href = stream.data;
|
|
||||||
link.setAttribute('download', filename);
|
|
||||||
document.body.appendChild(link);
|
|
||||||
link.click();
|
|
||||||
document.body.removeChild(link);
|
|
||||||
window.URL.revokeObjectURL(stream.data);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error downloading file:', error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
props.onClick = handleDownload;
|
|
||||||
props.target = '_blank';
|
|
||||||
|
|
||||||
return (
|
|
||||||
<a
|
|
||||||
href={filepath?.startsWith('files/') ? `/api/${filepath}` : `/api/files/${filepath}`}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
type TParagraphProps = {
|
|
||||||
children: React.ReactNode;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const p: React.ElementType = memo(({ children }: TParagraphProps) => {
|
|
||||||
return <p className="mb-2 whitespace-pre-wrap">{children}</p>;
|
|
||||||
});
|
|
||||||
|
|
||||||
type TContentProps = {
|
type TContentProps = {
|
||||||
content: string;
|
content: string;
|
||||||
isLatestMessage: boolean;
|
isLatestMessage: boolean;
|
||||||
|
|
|
@ -0,0 +1,153 @@
|
||||||
|
import React, { memo, useMemo, useRef, useEffect } from 'react';
|
||||||
|
import { useRecoilValue } from 'recoil';
|
||||||
|
import { PermissionTypes, Permissions } from 'librechat-data-provider';
|
||||||
|
import { useToastContext, useCodeBlockContext } from '~/Providers';
|
||||||
|
import CodeBlock from '~/components/Messages/Content/CodeBlock';
|
||||||
|
import useHasAccess from '~/hooks/Roles/useHasAccess';
|
||||||
|
import { useFileDownload } from '~/data-provider';
|
||||||
|
import useLocalize from '~/hooks/useLocalize';
|
||||||
|
import { handleDoubleClick } from '~/utils';
|
||||||
|
import store from '~/store';
|
||||||
|
|
||||||
|
type TCodeProps = {
|
||||||
|
inline?: boolean;
|
||||||
|
className?: string;
|
||||||
|
children: React.ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const code: React.ElementType = memo(({ className, children }: TCodeProps) => {
|
||||||
|
const canRunCode = useHasAccess({
|
||||||
|
permissionType: PermissionTypes.RUN_CODE,
|
||||||
|
permission: Permissions.USE,
|
||||||
|
});
|
||||||
|
const match = /language-(\w+)/.exec(className ?? '');
|
||||||
|
const lang = match && match[1];
|
||||||
|
const isMath = lang === 'math';
|
||||||
|
const isSingleLine = typeof children === 'string' && children.split('\n').length === 1;
|
||||||
|
|
||||||
|
const { getNextIndex, resetCounter } = useCodeBlockContext();
|
||||||
|
const blockIndex = useRef(getNextIndex(isMath || isSingleLine)).current;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
resetCounter();
|
||||||
|
}, [children, resetCounter]);
|
||||||
|
|
||||||
|
if (isMath) {
|
||||||
|
return <>{children}</>;
|
||||||
|
} else if (isSingleLine) {
|
||||||
|
return (
|
||||||
|
<code onDoubleClick={handleDoubleClick} className={className}>
|
||||||
|
{children}
|
||||||
|
</code>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<CodeBlock
|
||||||
|
lang={lang ?? 'text'}
|
||||||
|
codeChildren={children}
|
||||||
|
blockIndex={blockIndex}
|
||||||
|
allowExecution={canRunCode}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export const codeNoExecution: React.ElementType = memo(({ className, children }: TCodeProps) => {
|
||||||
|
const match = /language-(\w+)/.exec(className ?? '');
|
||||||
|
const lang = match && match[1];
|
||||||
|
|
||||||
|
if (lang === 'math') {
|
||||||
|
return children;
|
||||||
|
} else if (typeof children === 'string' && children.split('\n').length === 1) {
|
||||||
|
return (
|
||||||
|
<code onDoubleClick={handleDoubleClick} className={className}>
|
||||||
|
{children}
|
||||||
|
</code>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return <CodeBlock lang={lang ?? 'text'} codeChildren={children} allowExecution={false} />;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
type TAnchorProps = {
|
||||||
|
href: string;
|
||||||
|
children: React.ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const a: React.ElementType = memo(({ href, children }: TAnchorProps) => {
|
||||||
|
const user = useRecoilValue(store.user);
|
||||||
|
const { showToast } = useToastContext();
|
||||||
|
const localize = useLocalize();
|
||||||
|
|
||||||
|
const {
|
||||||
|
file_id = '',
|
||||||
|
filename = '',
|
||||||
|
filepath,
|
||||||
|
} = useMemo(() => {
|
||||||
|
const pattern = new RegExp(`(?:files|outputs)/${user?.id}/([^\\s]+)`);
|
||||||
|
const match = href.match(pattern);
|
||||||
|
if (match && match[0]) {
|
||||||
|
const path = match[0];
|
||||||
|
const parts = path.split('/');
|
||||||
|
const name = parts.pop();
|
||||||
|
const file_id = parts.pop();
|
||||||
|
return { file_id, filename: name, filepath: path };
|
||||||
|
}
|
||||||
|
return { file_id: '', filename: '', filepath: '' };
|
||||||
|
}, [user?.id, href]);
|
||||||
|
|
||||||
|
const { refetch: downloadFile } = useFileDownload(user?.id ?? '', file_id);
|
||||||
|
const props: { target?: string; onClick?: React.MouseEventHandler } = { target: '_new' };
|
||||||
|
|
||||||
|
if (!file_id || !filename) {
|
||||||
|
return (
|
||||||
|
<a href={href} {...props}>
|
||||||
|
{children}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDownload = async (event: React.MouseEvent<HTMLAnchorElement>) => {
|
||||||
|
event.preventDefault();
|
||||||
|
try {
|
||||||
|
const stream = await downloadFile();
|
||||||
|
if (stream.data == null || stream.data === '') {
|
||||||
|
console.error('Error downloading file: No data found');
|
||||||
|
showToast({
|
||||||
|
status: 'error',
|
||||||
|
message: localize('com_ui_download_error'),
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.href = stream.data;
|
||||||
|
link.setAttribute('download', filename);
|
||||||
|
document.body.appendChild(link);
|
||||||
|
link.click();
|
||||||
|
document.body.removeChild(link);
|
||||||
|
window.URL.revokeObjectURL(stream.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error downloading file:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
props.onClick = handleDownload;
|
||||||
|
props.target = '_blank';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
href={filepath?.startsWith('files/') ? `/api/${filepath}` : `/api/files/${filepath}`}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
type TParagraphProps = {
|
||||||
|
children: React.ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const p: React.ElementType = memo(({ children }: TParagraphProps) => {
|
||||||
|
return <p className="mb-2 whitespace-pre-wrap">{children}</p>;
|
||||||
|
});
|
|
@ -4,7 +4,7 @@ import supersub from 'remark-supersub';
|
||||||
import ReactMarkdown from 'react-markdown';
|
import ReactMarkdown from 'react-markdown';
|
||||||
import rehypeHighlight from 'rehype-highlight';
|
import rehypeHighlight from 'rehype-highlight';
|
||||||
import type { PluggableList } from 'unified';
|
import type { PluggableList } from 'unified';
|
||||||
import { code, codeNoExecution, a, p } from './Markdown';
|
import { code, codeNoExecution, a, p } from './MarkdownComponents';
|
||||||
import { CodeBlockProvider } from '~/Providers';
|
import { CodeBlockProvider } from '~/Providers';
|
||||||
import { langSubset } from '~/utils';
|
import { langSubset } from '~/utils';
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import supersub from 'remark-supersub';
|
||||||
import ReactMarkdown from 'react-markdown';
|
import ReactMarkdown from 'react-markdown';
|
||||||
import rehypeHighlight from 'rehype-highlight';
|
import rehypeHighlight from 'rehype-highlight';
|
||||||
import type { PluggableList } from 'unified';
|
import type { PluggableList } from 'unified';
|
||||||
import { code, codeNoExecution, a, p } from './Markdown';
|
import { code, codeNoExecution, a, p } from './MarkdownComponents';
|
||||||
import { CodeBlockProvider, ArtifactProvider } from '~/Providers';
|
import { CodeBlockProvider, ArtifactProvider } from '~/Providers';
|
||||||
import MarkdownErrorBoundary from './MarkdownErrorBoundary';
|
import MarkdownErrorBoundary from './MarkdownErrorBoundary';
|
||||||
import { langSubset } from '~/utils';
|
import { langSubset } from '~/utils';
|
||||||
|
|
|
@ -8,8 +8,8 @@ import rehypeHighlight from 'rehype-highlight';
|
||||||
import { replaceSpecialVars } from 'librechat-data-provider';
|
import { replaceSpecialVars } from 'librechat-data-provider';
|
||||||
import { useForm, useFieldArray, Controller, useWatch } from 'react-hook-form';
|
import { useForm, useFieldArray, Controller, useWatch } from 'react-hook-form';
|
||||||
import type { TPromptGroup } from 'librechat-data-provider';
|
import type { TPromptGroup } from 'librechat-data-provider';
|
||||||
|
import { codeNoExecution } from '~/components/Chat/Messages/Content/MarkdownComponents';
|
||||||
import { cn, wrapVariable, defaultTextProps, extractVariableInfo } from '~/utils';
|
import { cn, wrapVariable, defaultTextProps, extractVariableInfo } from '~/utils';
|
||||||
import { codeNoExecution } from '~/components/Chat/Messages/Content/Markdown';
|
|
||||||
import { TextareaAutosize, InputCombobox, Button } from '~/components/ui';
|
import { TextareaAutosize, InputCombobox, Button } from '~/components/ui';
|
||||||
import { useAuthContext, useLocalize, useSubmitMessage } from '~/hooks';
|
import { useAuthContext, useLocalize, useSubmitMessage } from '~/hooks';
|
||||||
import { PromptVariableGfm } from '../Markdown';
|
import { PromptVariableGfm } from '../Markdown';
|
||||||
|
|
|
@ -7,7 +7,7 @@ import supersub from 'remark-supersub';
|
||||||
import rehypeHighlight from 'rehype-highlight';
|
import rehypeHighlight from 'rehype-highlight';
|
||||||
import { replaceSpecialVars } from 'librechat-data-provider';
|
import { replaceSpecialVars } from 'librechat-data-provider';
|
||||||
import type { TPromptGroup } from 'librechat-data-provider';
|
import type { TPromptGroup } from 'librechat-data-provider';
|
||||||
import { codeNoExecution } from '~/components/Chat/Messages/Content/Markdown';
|
import { codeNoExecution } from '~/components/Chat/Messages/Content/MarkdownComponents';
|
||||||
import { useLocalize, useAuthContext } from '~/hooks';
|
import { useLocalize, useAuthContext } from '~/hooks';
|
||||||
import CategoryIcon from './Groups/CategoryIcon';
|
import CategoryIcon from './Groups/CategoryIcon';
|
||||||
import PromptVariables from './PromptVariables';
|
import PromptVariables from './PromptVariables';
|
||||||
|
|
|
@ -9,7 +9,7 @@ import rehypeKatex from 'rehype-katex';
|
||||||
import remarkMath from 'remark-math';
|
import remarkMath from 'remark-math';
|
||||||
import supersub from 'remark-supersub';
|
import supersub from 'remark-supersub';
|
||||||
import ReactMarkdown from 'react-markdown';
|
import ReactMarkdown from 'react-markdown';
|
||||||
import { codeNoExecution } from '~/components/Chat/Messages/Content/Markdown';
|
import { codeNoExecution } from '~/components/Chat/Messages/Content/MarkdownComponents';
|
||||||
import AlwaysMakeProd from '~/components/Prompts/Groups/AlwaysMakeProd';
|
import AlwaysMakeProd from '~/components/Prompts/Groups/AlwaysMakeProd';
|
||||||
import { SaveIcon, CrossIcon } from '~/components/svg';
|
import { SaveIcon, CrossIcon } from '~/components/svg';
|
||||||
import VariablesDropdown from './VariablesDropdown';
|
import VariablesDropdown from './VariablesDropdown';
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Spinner } from '~/components/svg';
|
import { Spinner } from '~/components/svg';
|
||||||
import { useLocalize } from '~/hooks';
|
import { useLocalize } from '~/hooks';
|
||||||
import VersionItem from './VersionItem';
|
import VersionItem from './VersionItem';
|
||||||
import { VersionContext } from './VersionPanel';
|
import type { VersionContext } from './types';
|
||||||
|
|
||||||
type VersionContentProps = {
|
type VersionContentProps = {
|
||||||
selectedAgentId: string;
|
selectedAgentId: string;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { useLocalize } from '~/hooks';
|
import { useLocalize } from '~/hooks';
|
||||||
import { VersionRecord } from './VersionPanel';
|
import type { VersionRecord } from './types';
|
||||||
|
|
||||||
type VersionItemProps = {
|
type VersionItemProps = {
|
||||||
version: VersionRecord;
|
version: VersionRecord;
|
||||||
|
|
|
@ -1,44 +1,13 @@
|
||||||
import { ChevronLeft } from 'lucide-react';
|
import { ChevronLeft } from 'lucide-react';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
import { useGetAgentByIdQuery, useRevertAgentVersionMutation } from '~/data-provider';
|
import { useGetAgentByIdQuery, useRevertAgentVersionMutation } from '~/data-provider';
|
||||||
import type { Agent } from 'librechat-data-provider';
|
import type { AgentWithVersions, VersionContext } from './types';
|
||||||
import { isActiveVersion } from './isActiveVersion';
|
import { isActiveVersion } from './isActiveVersion';
|
||||||
import { useAgentPanelContext } from '~/Providers';
|
import { useAgentPanelContext } from '~/Providers';
|
||||||
import { useLocalize, useToast } from '~/hooks';
|
import { useLocalize, useToast } from '~/hooks';
|
||||||
import VersionContent from './VersionContent';
|
import VersionContent from './VersionContent';
|
||||||
import { Panel } from '~/common';
|
import { Panel } from '~/common';
|
||||||
|
|
||||||
export type VersionRecord = Record<string, any>;
|
|
||||||
|
|
||||||
export type AgentState = {
|
|
||||||
name: string | null;
|
|
||||||
description: string | null;
|
|
||||||
instructions: string | null;
|
|
||||||
artifacts?: string | null;
|
|
||||||
capabilities?: string[];
|
|
||||||
tools?: string[];
|
|
||||||
} | null;
|
|
||||||
|
|
||||||
export type VersionWithId = {
|
|
||||||
id: number;
|
|
||||||
originalIndex: number;
|
|
||||||
version: VersionRecord;
|
|
||||||
isActive: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type VersionContext = {
|
|
||||||
versions: VersionRecord[];
|
|
||||||
versionIds: VersionWithId[];
|
|
||||||
currentAgent: AgentState;
|
|
||||||
selectedAgentId: string;
|
|
||||||
activeVersion: VersionRecord | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface AgentWithVersions extends Agent {
|
|
||||||
capabilities?: string[];
|
|
||||||
versions?: Array<VersionRecord>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function VersionPanel() {
|
export default function VersionPanel() {
|
||||||
const localize = useLocalize();
|
const localize = useLocalize();
|
||||||
const { showToast } = useToast();
|
const { showToast } = useToast();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { AgentState, VersionRecord } from './VersionPanel';
|
import type { AgentState, VersionRecord } from './types';
|
||||||
|
|
||||||
export const isActiveVersion = (
|
export const isActiveVersion = (
|
||||||
version: VersionRecord,
|
version: VersionRecord,
|
||||||
|
|
35
client/src/components/SidePanel/Agents/Version/types.ts
Normal file
35
client/src/components/SidePanel/Agents/Version/types.ts
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
export type VersionRecord = Record<string, any>;
|
||||||
|
|
||||||
|
export type AgentState = {
|
||||||
|
name: string | null;
|
||||||
|
description: string | null;
|
||||||
|
instructions: string | null;
|
||||||
|
artifacts?: string | null;
|
||||||
|
capabilities?: string[];
|
||||||
|
tools?: string[];
|
||||||
|
} | null;
|
||||||
|
|
||||||
|
export type VersionWithId = {
|
||||||
|
id: number;
|
||||||
|
originalIndex: number;
|
||||||
|
version: VersionRecord;
|
||||||
|
isActive: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type VersionContext = {
|
||||||
|
versions: VersionRecord[];
|
||||||
|
versionIds: VersionWithId[];
|
||||||
|
currentAgent: AgentState;
|
||||||
|
selectedAgentId: string;
|
||||||
|
activeVersion: VersionRecord | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface AgentWithVersions {
|
||||||
|
name: string;
|
||||||
|
description: string | null;
|
||||||
|
instructions: string | null;
|
||||||
|
artifacts?: string | null;
|
||||||
|
capabilities?: string[];
|
||||||
|
tools?: string[];
|
||||||
|
versions?: Array<VersionRecord>;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue