Skip to content

Commit

Permalink
♻️ refactor: 优化 plugin 文件夹命名以支持 standalone 类型的插件
Browse files Browse the repository at this point in the history
  • Loading branch information
arvinxx committed Oct 22, 2023
1 parent e195fdb commit 98860a8
Show file tree
Hide file tree
Showing 16 changed files with 153 additions and 67 deletions.
26 changes: 11 additions & 15 deletions src/app/chat/features/Conversation/ChatList/Messages/Assistant.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,18 @@ import { useSessionStore } from '@/store/session';
import { chatSelectors } from '@/store/session/selectors';
import { isFunctionMessageAtStart } from '@/utils/message';

import FunctionCall from '../Plugins/FunctionCall';
import Inspector from '../Plugins/Inspector';
import { DefaultMessage } from './Default';

export const AssistantMessage: RenderMessage = memo(
({ id, plugin, function_call, content, ...props }) => {
const genFunctionCallProps = useSessionStore(chatSelectors.getFunctionMessageParams);
export const AssistantMessage: RenderMessage = memo(({ id, plugin, content, ...props }) => {
const fcProps = useSessionStore(chatSelectors.getFunctionMessageProps({ content, id, plugin }));

if (!isFunctionMessageAtStart(content))
return <DefaultMessage content={content} id={id} {...props} />;
if (!isFunctionMessageAtStart(content))
return <DefaultMessage content={content} id={id} {...props} />;

const fcProps = genFunctionCallProps({ content, function_call, id, plugin });

return (
<div id={id}>
<FunctionCall {...fcProps} />
</div>
);
},
);
return (
<div id={id}>
<Inspector {...fcProps} />
</div>
);
});
29 changes: 15 additions & 14 deletions src/app/chat/features/Conversation/ChatList/Messages/Function.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
import { RenderMessage } from '@lobehub/ui';
import isEqual from 'fast-deep-equal';
import { memo } from 'react';
import { Flexbox } from 'react-layout-kit';

import { useSessionStore } from '@/store/session';
import { chatSelectors } from '@/store/session/selectors';

import FunctionCall from '../Plugins/FunctionCall';
import PluginMessage from '../Plugins/PluginMessage';
import Inspector from '../Plugins/Inspector';
import PluginRender from '../Plugins/Render';

export const FunctionMessage: RenderMessage = memo(
({ id, content, plugin, function_call, name }) => {
const genFunctionCallProps = useSessionStore(chatSelectors.getFunctionMessageParams);
const fcProps = genFunctionCallProps({ content, function_call, id, plugin });
export const FunctionMessage: RenderMessage = memo(({ id, content, plugin, name }) => {
const fcProps = useSessionStore(
chatSelectors.getFunctionMessageProps({ content, id, plugin }),
isEqual,
);

return (
<Flexbox gap={12} id={id}>
<FunctionCall {...fcProps} />
<PluginMessage content={content} loading={fcProps.loading} name={name} />
</Flexbox>
);
},
);
return (
<Flexbox gap={12} id={id}>
<Inspector {...fcProps} />
<PluginRender content={content} loading={fcProps.loading} name={name} type={fcProps.type} />
</Flexbox>
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ import { Flexbox } from 'react-layout-kit';

import { pluginHelpers, pluginSelectors, usePluginStore } from '@/store/plugin';

import PluginResult from './PluginResultRender';
import { useStyles } from './style';
import { useStyles } from '../style';
import PluginResult from './PluginResultJSON';

export interface FunctionCallProps {
export interface InspectorProps {
arguments?: string;
command?: any;
content: string;
id?: string;
loading?: boolean;
}

const FunctionCall = memo<FunctionCallProps>(
const Inspector = memo<InspectorProps>(
({ arguments: requestArgs = '{}', command, loading, content, id = 'unknown' }) => {
const { t } = useTranslation('plugin');
const { styles } = useStyles();
Expand Down Expand Up @@ -87,4 +87,4 @@ const FunctionCall = memo<FunctionCallProps>(
},
);

export default FunctionCall;
export default Inspector;
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ import IFrameRender from './IFrameRender';

const SystemJsRender = dynamic(() => import('./SystemJsRender'), { ssr: false });

export interface FunctionMessageProps {
export interface PluginDefaultTypeProps {
content: string;
loading?: boolean;
name?: string;
}

const PluginMessage = memo<FunctionMessageProps>(({ content, name }) => {
const PluginDefaultType = memo<PluginDefaultTypeProps>(({ content, name }) => {
const { t } = useTranslation('plugin');

const manifest = usePluginStore((s) => s.pluginManifestMap[name || '']);
Expand Down Expand Up @@ -65,4 +65,4 @@ const PluginMessage = memo<FunctionMessageProps>(({ content, name }) => {
);
});

export default PluginMessage;
export default PluginDefaultType;
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Skeleton } from 'antd';
import { memo, useRef, useState } from 'react';

interface IFrameRenderProps {
height?: number;
url: string;
width?: number;
}

const IFrameRender = memo<IFrameRenderProps>(({ url, width = 600, height = 300 }) => {
const [loading, setLoading] = useState(true);

const iframeRef = useRef<HTMLIFrameElement>(null);

return (
<>
{loading && <Skeleton active style={{ width }} />}
<iframe
// @ts-ignore
allowtransparency="true"
height={height}
hidden={loading}
onLoad={() => {
setLoading(false);
}}
ref={iframeRef}
src={url}
style={{
border: 0,
// iframe 在 color-scheme:dark 模式下无法透明
// refs: https://www.jianshu.com/p/bc5a37bb6a7b
colorScheme: 'light',
}}
width={width}
/>
</>
);
});
export default IFrameRender;
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { memo } from 'react';

import { usePluginStore } from '@/store/plugin';

import IFrameRender from './Iframe';

export interface PluginStandaloneTypeProps {
name?: string;
}

const PluginDefaultType = memo<PluginStandaloneTypeProps>(({ name = 'unknown' }) => {
const manifest = usePluginStore((s) => s.pluginManifestMap[name]);

if (!manifest?.ui) return;

const ui = manifest.ui;

if (!ui.url) return;

return <IFrameRender height={ui.height} url={ui.url} width={ui.width} />;
});

export default PluginDefaultType;
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { LobePluginType } from '@lobehub/chat-plugin-sdk';
import { memo } from 'react';

import DefaultType from './DefaultType';
import Standalone from './StandaloneType';

export interface PluginRenderProps {
content: string;
loading?: boolean;
name?: string;
type?: LobePluginType;
}

const PluginRender = memo<PluginRenderProps>(({ content, name, type }) => {
switch (type) {
case 'standalone': {
return <Standalone name={name} />;
}

default: {
return <DefaultType content={content} name={name} />;
}
}
});

export default PluginRender;
26 changes: 18 additions & 8 deletions src/store/session/slices/chat/actions/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ const t = setNamespace('chat/plugin');
* 插件方法
*/
export interface ChatPluginAction {
runPluginAutoMode: (id: string, payload: any) => Promise<void>;
runPluginDefaultType: (id: string, payload: any) => Promise<void>;
runPluginStandaloneType: (id: string, payload: any) => Promise<void>;
triggerFunctionCall: (id: string) => Promise<void>;
}

Expand All @@ -26,7 +27,7 @@ export const chatPlugin: StateCreator<
[],
ChatPluginAction
> = (set, get) => ({
runPluginAutoMode: async (id, payload) => {
runPluginDefaultType: async (id, payload) => {
const { dispatchMessage, coreProcessMessage, toggleChatLoading } = get();
let data: string;
try {
Expand All @@ -44,12 +45,13 @@ export const chatPlugin: StateCreator<
dispatchMessage({ id, key: 'content', type: 'updateMessage', value: data });

const chats = chatSelectors.currentChats(get());

await coreProcessMessage(chats, id);
},

runPluginStandaloneType: async (id, payload) => {
console.log('触发standalone', id, payload);
},
triggerFunctionCall: async (id) => {
const { dispatchMessage, runPluginAutoMode } = get();
const { dispatchMessage, runPluginDefaultType, runPluginStandaloneType } = get();
const session = sessionSelectors.currentSession(get());

if (!session) return;
Expand All @@ -58,15 +60,22 @@ export const chatPlugin: StateCreator<
if (!message) return;

let payload: PluginRequestPayload = { apiName: '', identifier: '' };

// 识别到内容是 function_call 的情况下
// 将 function_call 转换为 plugin request payload
if (message.content) {
const { function_call } = JSON.parse(message.content) as {
function_call: OpenAIFunctionCall;
};

const [identifier, apiName] = function_call.name.split(PLUGIN_SCHEMA_SEPARATOR);
payload = { apiName, arguments: function_call.arguments, identifier };
const [identifier, apiName, type] = function_call.name.split(PLUGIN_SCHEMA_SEPARATOR);

payload = {
apiName,
arguments: function_call.arguments,
identifier,
type: type ?? 'default',
};

dispatchMessage({ id, key: 'plugin', type: 'updateMessage', value: payload });
dispatchMessage({ id, key: 'content', type: 'updateMessage', value: '' });
Expand All @@ -82,6 +91,7 @@ export const chatPlugin: StateCreator<
dispatchMessage({ id, key: 'name', type: 'updateMessage', value: payload.identifier });
dispatchMessage({ id, key: 'plugin', type: 'updateMessage', value: payload });

runPluginAutoMode(id, payload);
if (payload.type === 'standalone') runPluginStandaloneType(id, payload);
else runPluginDefaultType(id, payload);
},
});
31 changes: 11 additions & 20 deletions src/store/session/slices/chat/selectors/chat.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { LobePluginType } from '@lobehub/chat-plugin-sdk';
import { t } from 'i18next';

import { FunctionCallProps } from '@/app/chat/features/Conversation/ChatList/Plugins/FunctionCall';
import { DEFAULT_INBOX_AVATAR, DEFAULT_USER_AVATAR } from '@/const/meta';
import { INBOX_SESSION_ID } from '@/const/session';
import { useGlobalStore } from '@/store/global';
Expand Down Expand Up @@ -92,22 +92,13 @@ export const chatsMessageString = (s: SessionStore): string => {
return chats.map((m) => m.content).join('');
};

export const getFunctionMessageParams =
(
s: SessionStore,
): ((
props: Pick<ChatMessage, 'plugin' | 'function_call' | 'content' | 'id'>,
) => FunctionCallProps) =>
({ plugin, function_call, content, id }) => {
const itemId = plugin?.identifier || function_call?.name;
const command = plugin ?? function_call;
const args = command?.arguments;

return {
arguments: args,
command,
content,
id: itemId,
loading: id === s.chatLoadingId,
};
};
export const getFunctionMessageProps =
({ plugin, content, id }: Pick<ChatMessage, 'plugin' | 'content' | 'id'>) =>
(s: SessionStore) => ({
arguments: plugin?.arguments,
command: plugin,
content,
id: plugin?.identifier,
loading: id === s.chatLoadingId,
type: plugin?.type as LobePluginType,
});
4 changes: 2 additions & 2 deletions src/store/session/slices/chat/selectors/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
currentChatsWithGuideMessage,
currentChatsWithHistoryConfig,
getChatsById,
getFunctionMessageParams,
getFunctionMessageProps,
} from './chat';
import { currentTopics, getTopicMessages } from './topic';

Expand All @@ -14,7 +14,7 @@ export const chatSelectors = {
currentChatsWithGuideMessage,
currentChatsWithHistoryConfig,
getChatsById,
getFunctionMessageParams,
getFunctionMessageProps,
};

export const topicSelectors = {
Expand Down

0 comments on commit 98860a8

Please sign in to comment.