@lobehub/chat 0.104.0 → 0.105.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,56 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 0.105.1](https://github.com/lobehub/lobe-chat/compare/v0.105.0...v0.105.1)
6
+
7
+ <sup>Released on **2023-11-27**</sup>
8
+
9
+ #### 🐛 Bug Fixes
10
+
11
+ - **misc**: Fix agent market detail scroll error.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### What's fixed
19
+
20
+ - **misc**: Fix agent market detail scroll error, closes [#503](https://github.com/lobehub/lobe-chat/issues/503) ([8900ad0](https://github.com/lobehub/lobe-chat/commit/8900ad0))
21
+
22
+ </details>
23
+
24
+ <div align="right">
25
+
26
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
27
+
28
+ </div>
29
+
30
+ ## [Version 0.105.0](https://github.com/lobehub/lobe-chat/compare/v0.104.0...v0.105.0)
31
+
32
+ <sup>Released on **2023-11-22**</sup>
33
+
34
+ #### ✨ Features
35
+
36
+ - **misc**: Standalone pluginn can get more arguments on init.
37
+
38
+ <br/>
39
+
40
+ <details>
41
+ <summary><kbd>Improvements and Fixes</kbd></summary>
42
+
43
+ #### What's improved
44
+
45
+ - **misc**: Standalone pluginn can get more arguments on init, closes [#498](https://github.com/lobehub/lobe-chat/issues/498) ([a7624f5](https://github.com/lobehub/lobe-chat/commit/a7624f5))
46
+
47
+ </details>
48
+
49
+ <div align="right">
50
+
51
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
52
+
53
+ </div>
54
+
5
55
  ## [Version 0.104.0](https://github.com/lobehub/lobe-chat/compare/v0.103.1...v0.104.0)
6
56
 
7
57
  <sup>Released on **2023-11-21**</sup>
package/README.md CHANGED
@@ -1,12 +1,10 @@
1
- <a name="readme-top"></a>
2
-
3
- <div align="center">
1
+ <a name="readme-top"></a><div align="center">
4
2
 
5
3
  <img height="120" src="https://registry.npmmirror.com/@lobehub/assets-logo/1.0.0/files/assets/logo-3d.webp">
6
4
  <img height="120" src="https://gw.alipayobjects.com/zos/kitchen/qJ3l3EPsdW/split.svg">
7
5
  <img height="120" src="https://registry.npmmirror.com/@lobehub/assets-emoji-anim/1.0.0/files/assets/robot.webp">
8
6
 
9
- <h1>Lobe Chat</h1>
7
+ # Lobe Chat
10
8
 
11
9
  LobeChat is an open-source, high-performance chatbot framework<br/>that supports speech synthesis, multimodal, and extensible ([Function Call][fc-link]) plugin system. <br/>
12
10
  Supports one-click free deployment of your private ChatGPT/LLM web application.
@@ -81,7 +79,8 @@ Please be aware that LobeChat is currently under active development, and feedbac
81
79
 
82
80
  ![](https://gw.alipayobjects.com/zos/kitchen/0hcO8QiU9c/star.webp)
83
81
 
84
- <details><summary><kbd>Star History</kbd></summary>
82
+ <details>
83
+ <summary><kbd>Star History</kbd></summary>
85
84
  <picture>
86
85
  <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=lobehub%2Flobe-chat&theme=dark&type=Date">
87
86
  <img width="100%" src="https://api.star-history.com/svg?repos=lobehub%2Flobe-chat&type=Date">
@@ -153,8 +152,9 @@ Users can choose the voice that suits their personal preferences or specific sce
153
152
  > As a result, we invested a lot of effort, including data conversion, audio progress management, and speech visualization, among other tasks.
154
153
 
155
154
  > \[!IMPORTANT]
155
+ >
156
156
  > Therefore, we decided to refine our implementation and make it open source, hoping to assist developers who wish to implement TTS.
157
- > [@lobehub/tts][lobe-tts-link] is a high-quality TTS toolkit developed in TypeScript, which supports usage both on the server-side and in the browser.
157
+ > [@lobehub/tts][lobe-tts-github] is a high-quality TTS toolkit developed in TypeScript, which supports usage both on the server-side and in the browser.
158
158
  >
159
159
  > - **Server-side:** With just 15 lines of code, you can achieve high-quality voice generation capabilities comparable to OpenAI's TTS service. It currently supports EdgeSpeechTTS, MicrosoftTTS, OpenAITTS, and OpenAISTT.
160
160
  > - **Browser-side:** It provides high-quality React Hooks and visual audio components, supporting common functions such as loading, playing, pausing, and dragging the timeline. Additionally, it offers a very rich set of capabilities for adjusting the audio track styles.
@@ -186,7 +186,7 @@ e-commerce platform data access, and various third-party services.
186
186
  > We welcome developers to use these resources to unleash their creativity and write feature-rich, user-friendly plugins.
187
187
  > With collective efforts, we can continuously expand the boundaries of chat applications and explore a more intelligent and efficient creativity platform.
188
188
 
189
- <https://github.com/lobehub/lobe-chat/assets/28616219/f29475a3-f346-4196-a435-41a6373ab9e2>
189
+ <video controls src="https://github.com/lobehub/lobe-chat/assets/28616219/f29475a3-f346-4196-a435-41a6373ab9e2" muted="false"></video>
190
190
 
191
191
  <!-- PLUGIN LIST -->
192
192
 
@@ -229,14 +229,14 @@ Our marketplace is not just a showcase platform but also a collaborative space.
229
229
 
230
230
  <!-- AGENT LIST -->
231
231
 
232
- | Recent Submits | Description |
233
- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
234
- | [Short Video Script Assistant](https://chat-preview.lobehub.com/market?agent=tik-tok-director)<br/><sup>By **[aihoom](https://github.com/aihoom)** on **2023-11-17**</sup> | Designed to help users write engaging and trendy short video scripts<br/>`short-video` `tkitok` `screenwriter` |
235
- | [Expert Agent Mentor](https://chat-preview.lobehub.com/market?agent=co-agent)<br/><sup>By **[tcmonster](https://github.com/tcmonster)** on **2023-11-16**</sup> | Call on expert agents perfectly suited for the task to support your goals<br/>`task-guidance` `execution-plan` `communication` `support` |
236
- | [Full-stack Developer](https://chat-preview.lobehub.com/market?agent=fs-dev)<br/><sup>By **[cloverfield11](https://github.com/cloverfield11)** on **2023-11-15**</sup> | Full-stack web developer with experience in HTML, CSS, JavaScript, Python, Java, Ruby, and frameworks such as React, Angular, Vue.js, Express, Django, Next.js, Flask, or Ruby on Rails. Experience in databases, application architecture, security, and testing.<br/>`web-development` `front-end` `back-end` `programming` `databases` |
237
- | [Graphic Creative Master](https://chat-preview.lobehub.com/market?agent=graphic-creativity)<br/><sup>By **[yingxirz](https://github.com/yingxirz)** on **2023-11-15**</sup> | Specializes in graphic creative design and graphic creativity<br/>`graphic` `creative` `design` `graphic-design` |
232
+ | Recent Submits | Description |
233
+ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
234
+ | [JS Code Quality Optimization](https://chat-preview.lobehub.com/market?agent=js-code-quality)<br/><sup>By **[canisminor1990](https://github.com/canisminor1990)** on **2023-11-22**</sup> | Dedicated to clean and elegant code refactoring<br/>`refactoring` `code-optimization` `code-quality` |
235
+ | [LobeChat Test Engineer](https://chat-preview.lobehub.com/market?agent=lobe-chat-unit-test-dev)<br/><sup>By **[arvinxx](https://github.com/arvinxx)** on **2023-11-22**</sup> | Proficient in writing frontend automation tests, especially comprehensive test coverage for TypeScript applications. Skilled in using the Vitest testing framework with a deep understanding of testing principles and strategies.<br/>`automation-testing` `testing` `lobe-chat` `frontend` |
236
+ | [Q\&A Document Conversion Expert](https://chat-preview.lobehub.com/market?agent=q-a-helper)<br/><sup>By **[barryWang12138](https://github.com/barryWang12138)** on **2023-11-22**</sup> | Please provide your document content, and I will segment and clean it according to your requirements, and provide answers in a standardized format.<br/>`q-a` `document` |
237
+ | [True Friend](https://chat-preview.lobehub.com/market?agent=ai-0x0-old-friends)<br/><sup>By **[mushan0x0](https://github.com/mushan0x0)** on **2023-11-21**</sup> | You can talk to me about anything. I can give you some thoughts and advice as a friend. Relax.<br/>`friendship` `humor` `authentic` `simulation` |
238
238
 
239
- > 📊 Total agents: [<kbd>**48**</kbd> ](https://github.com/lobehub/lobe-chat-agents)
239
+ > 📊 Total agents: [<kbd>**52**</kbd> ](https://github.com/lobehub/lobe-chat-agents)
240
240
 
241
241
  <!-- AGENT LIST -->
242
242
 
package/README.zh-CN.md CHANGED
@@ -208,14 +208,14 @@ LobeChat 的插件生态系统是其核心功能的重要扩展,它极大地
208
208
 
209
209
  <!-- AGENT LIST -->
210
210
 
211
- | 最近新增 | 助手说明 |
212
- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
213
- | [短视频脚本助手](https://chat-preview.lobehub.com/market?agent=tik-tok-director)<br/><sup>By **[aihoom](https://github.com/aihoom)** on **2023-11-17**</sup> | 旨在帮助用户编写吸引人、潮流的短视频剧本<br/>`短视频` `tkitok` `编剧` |
214
- | [专家代理人导师](https://chat-preview.lobehub.com/market?agent=co-agent)<br/><sup>By **[tcmonster](https://github.com/tcmonster)** on **2023-11-16**</sup> | 调用完全适合任务的专家代理人来支持您的目标<br/>`任务指导` `执行计划` `沟通` `支持` |
215
- | [全栈开发人员](https://chat-preview.lobehub.com/market?agent=fs-dev)<br/><sup>By **[cloverfield11](https://github.com/cloverfield11)** on **2023-11-15**</sup> | 具有 HTML、CSS、JavaScript、Python、Java、Ruby 和 React、Angular、Vue.js、Express、Django、Next.js、Flask 或 Ruby on Rails 框架经验的全栈 Web 开发人员。具备数据库、应用架构、安全性和测试经验。<br/>`web开发` `前端` `后端` `编程` `数据库` |
216
- | [图形创意大师](https://chat-preview.lobehub.com/market?agent=graphic-creativity)<br/><sup>By **[yingxirz](https://github.com/yingxirz)** on **2023-11-15**</sup> | 擅长平面创意设计与图形创意<br/>`图形` `创意` `设计` `平面` |
217
-
218
- > 📊 Total agents: [<kbd>**48**</kbd> ](https://github.com/lobehub/lobe-chat-agents)
211
+ | 最近新增 | 助手说明 |
212
+ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
213
+ | [JS 代码质量优化](https://chat-preview.lobehub.com/market?agent=js-code-quality)<br/><sup>By **[canisminor1990](https://github.com/canisminor1990)** on **2023-11-22**</sup> | 致力于干净和优雅的代码重构<br/>`重构` `代码优化` `代码质量` |
214
+ | [LobeChat 测试工程师](https://chat-preview.lobehub.com/market?agent=lobe-chat-unit-test-dev)<br/><sup>By **[arvinxx](https://github.com/arvinxx)** on **2023-11-22**</sup> | 擅长编写前端自动化测试,特别是 TypeScript 应用的全面测试覆盖。熟练使用 Vitest 测试框架,具备深入的测试原理和策略理解。<br/>`自动化测试` `测试` `lobe-chat` `前端` |
215
+ | [问答文档转换专家](https://chat-preview.lobehub.com/market?agent=q-a-helper)<br/><sup>By **[barryWang12138](https://github.com/barryWang12138)** on **2023-11-22**</sup> | 请提供您的文档内容,我将根据您的要求进行分段和清洗,并按照规范的格式回答。<br/>`q-a` `文档` |
216
+ | [真实的老友](https://chat-preview.lobehub.com/market?agent=ai-0x0-old-friends)<br/><sup>By **[mushan0x0](https://github.com/mushan0x0)** on **2023-11-21**</sup> | 可以跟我谈论一切,我可以给你作为老友的一些想法和建议,放轻松<br/>`友情` `幽默` `真实` `模拟` |
217
+
218
+ > 📊 Total agents: [<kbd>**52**</kbd> ](https://github.com/lobehub/lobe-chat-agents)
219
219
 
220
220
  <!-- AGENT LIST -->
221
221
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "0.104.0",
3
+ "version": "0.105.1",
4
4
  "description": "An open-source, extensible (Function Calling), high-performance chatbot framework. It supports one-click free deployment of your private ChatGPT/LLM web application",
5
5
  "keywords": [
6
6
  "chatbot",
@@ -16,12 +16,16 @@ describe('getPreferredRegion', () => {
16
16
 
17
17
  it('returns default value when get config error', () => {
18
18
  const originalProcess = global.process;
19
+ const originalError = console.error;
19
20
  // @ts-ignore
20
21
  global.process = undefined;
22
+ console.error = () => {};
23
+
21
24
  const preferredRegion = getPreferredRegion();
22
25
  expect(preferredRegion).toBe('auto');
23
26
 
24
27
  global.process = originalProcess;
28
+ console.error = originalError;
25
29
  });
26
30
 
27
31
  it('return default value when preferredRegion is empty', () => {
@@ -23,6 +23,11 @@ import {
23
23
  sendPluginStateToPlugin,
24
24
  } from '../utils/postMessage';
25
25
 
26
+ // just to simplify code a little, don't use this pattern everywhere
27
+ const getSettings = (identifier: string) =>
28
+ pluginSelectors.getPluginSettingsById(identifier)(usePluginStore.getState());
29
+ const getMessage = (id: string) => chatSelectors.getMessageById(id)(useSessionStore.getState());
30
+
26
31
  interface IFrameRenderProps {
27
32
  height?: number;
28
33
  id: string;
@@ -39,8 +44,13 @@ const IFrameRender = memo<IFrameRenderProps>(({ url, id, payload, width = 600, h
39
44
  // when payload change,send content to plugin
40
45
  useOnPluginReadyForInteraction(() => {
41
46
  const iframeWin = iframeRef.current?.contentWindow;
47
+
42
48
  if (iframeWin && payload) {
43
- sendPayloadToPlugin(iframeWin, payload);
49
+ const settings = getSettings(payload.identifier);
50
+ const message = getMessage(id);
51
+ const state = message?.pluginState;
52
+
53
+ sendPayloadToPlugin(iframeWin, { payload, settings, state });
44
54
  }
45
55
  }, [payload]);
46
56
 
@@ -74,7 +84,7 @@ const IFrameRender = memo<IFrameRenderProps>(({ url, id, payload, width = 600, h
74
84
  const iframeWin = iframeRef.current?.contentWindow;
75
85
 
76
86
  if (iframeWin) {
77
- const message = chatSelectors.getMessageById(id)(useSessionStore.getState());
87
+ const message = getMessage(id);
78
88
  if (!message) return;
79
89
 
80
90
  sendPluginStateToPlugin(iframeWin, key, message.pluginState?.[key]);
@@ -94,9 +104,7 @@ const IFrameRender = memo<IFrameRenderProps>(({ url, id, payload, width = 600, h
94
104
  if (iframeWin) {
95
105
  if (!payload?.identifier) return;
96
106
 
97
- const settings = pluginSelectors.getPluginSettingsById(payload?.identifier)(
98
- usePluginStore.getState(),
99
- );
107
+ const settings = getSettings(payload.identifier);
100
108
 
101
109
  sendPluginSettingsToPlugin(iframeWin, settings);
102
110
  }
@@ -0,0 +1,75 @@
1
+ import { PluginChannel } from '@lobehub/chat-plugin-sdk/client';
2
+ import { act, renderHook } from '@testing-library/react';
3
+ import { afterEach, describe, expect, it, vi } from 'vitest';
4
+
5
+ import { useOnPluginReadyForInteraction } from './iframeOnReady';
6
+
7
+ describe('useOnPluginReadyForInteraction', () => {
8
+ const mockOnReady = vi.fn();
9
+
10
+ afterEach(() => {
11
+ mockOnReady.mockReset();
12
+ window.removeEventListener('message', expect.any(Function));
13
+ });
14
+
15
+ it('sets readyForRender to true when a PluginChannel.pluginReadyForRender message is received', async () => {
16
+ const { result } = renderHook(() => useOnPluginReadyForInteraction(mockOnReady));
17
+
18
+ expect(result.current).toBe(false); // Initially, readyForRender should be false
19
+
20
+ const event = new MessageEvent('message', {
21
+ data: { type: PluginChannel.pluginReadyForRender },
22
+ });
23
+
24
+ act(() => {
25
+ window.dispatchEvent(event);
26
+ });
27
+
28
+ expect(result.current).toBe(true); // After the event, readyForRender should be true
29
+ });
30
+
31
+ it('sets readyForRender to true when a PluginChannel.pluginReadyForRender message is received', async () => {
32
+ const { result } = renderHook(() => useOnPluginReadyForInteraction(mockOnReady));
33
+
34
+ expect(result.current).toBe(false); // Initially, readyForRender should be false
35
+
36
+ const event = new MessageEvent('message', {
37
+ data: { type: PluginChannel.pluginReadyForRender },
38
+ });
39
+
40
+ act(() => {
41
+ window.dispatchEvent(event);
42
+ });
43
+
44
+ expect(result.current).toBe(true); // After the event, readyForRender should be true
45
+ expect(mockOnReady).toHaveBeenCalledTimes(1); // onReady should have been called once
46
+ });
47
+
48
+ it('does not call onReady for non-pluginReadyForRender messages', async () => {
49
+ renderHook(() => useOnPluginReadyForInteraction(mockOnReady));
50
+
51
+ const event = new MessageEvent('message', {
52
+ data: { type: 'nonPluginReadyMessage' },
53
+ });
54
+
55
+ act(() => {
56
+ window.dispatchEvent(event);
57
+ });
58
+
59
+ expect(mockOnReady).not.toHaveBeenCalled();
60
+ });
61
+
62
+ it('cleans up message event listener on unmount', () => {
63
+ const { unmount } = renderHook(() => useOnPluginReadyForInteraction(mockOnReady));
64
+
65
+ unmount();
66
+
67
+ const event = new MessageEvent('message', {
68
+ data: { type: PluginChannel.pluginReadyForRender },
69
+ });
70
+
71
+ window.dispatchEvent(event);
72
+
73
+ expect(mockOnReady).not.toHaveBeenCalled();
74
+ });
75
+ });
@@ -20,4 +20,6 @@ export const useOnPluginReadyForInteraction = (onReady: () => void, deps: any[]
20
20
  onReady();
21
21
  }
22
22
  }, [readyForRender, ...deps]);
23
+
24
+ return readyForRender;
23
25
  };
@@ -0,0 +1,104 @@
1
+ import { PluginChannel } from '@lobehub/chat-plugin-sdk/client';
2
+ import { renderHook } from '@testing-library/react';
3
+ import { afterEach, describe, expect, it, vi } from 'vitest';
4
+
5
+ import {
6
+ useOnPluginFetchMessage,
7
+ useOnPluginFetchPluginSettings,
8
+ useOnPluginFetchPluginState,
9
+ useOnPluginFillContent,
10
+ } from './listenToPlugin';
11
+
12
+ afterEach(() => {
13
+ vi.restoreAllMocks();
14
+ });
15
+
16
+ describe('useOnPluginFetchMessage', () => {
17
+ it('calls onRequest when a fetchPluginMessage is received', () => {
18
+ const mockOnRequest = vi.fn();
19
+ renderHook(() => useOnPluginFetchMessage(mockOnRequest));
20
+
21
+ const testData = { key: 'testData', type: PluginChannel.fetchPluginMessage };
22
+ const event = new MessageEvent('message', {
23
+ data: testData,
24
+ });
25
+
26
+ window.dispatchEvent(event);
27
+
28
+ expect(mockOnRequest).toHaveBeenCalledWith(testData);
29
+ });
30
+
31
+ it('does not call onRequest for other message types', () => {
32
+ const mockOnRequest = vi.fn();
33
+ renderHook(() => useOnPluginFetchMessage(mockOnRequest));
34
+
35
+ const event = new MessageEvent('message', {
36
+ data: { type: 'otherMessageType' },
37
+ });
38
+
39
+ window.dispatchEvent(event);
40
+
41
+ expect(mockOnRequest).not.toHaveBeenCalled();
42
+ });
43
+ });
44
+
45
+ describe('useOnPluginFetchPluginState', () => {
46
+ it('calls onRequest with the key when a fetchPluginState message is received', () => {
47
+ const mockOnRequest = vi.fn();
48
+ renderHook(() => useOnPluginFetchPluginState(mockOnRequest));
49
+
50
+ const testKey = 'testKey';
51
+ const event = new MessageEvent('message', {
52
+ data: { type: PluginChannel.fetchPluginState, key: testKey },
53
+ });
54
+
55
+ window.dispatchEvent(event);
56
+
57
+ expect(mockOnRequest).toHaveBeenCalledWith(testKey);
58
+ });
59
+ });
60
+
61
+ describe('useOnPluginFillContent', () => {
62
+ it('calls callback with content when a fillStandalonePluginContent message is received', () => {
63
+ const mockCallback = vi.fn();
64
+ renderHook(() => useOnPluginFillContent(mockCallback));
65
+
66
+ const testContent = 'testContent';
67
+ const event = new MessageEvent('message', {
68
+ data: { type: PluginChannel.fillStandalonePluginContent, content: testContent },
69
+ });
70
+
71
+ window.dispatchEvent(event);
72
+
73
+ expect(mockCallback).toHaveBeenCalledWith(testContent);
74
+ });
75
+
76
+ it('calls callback with JSON stringified content if content is not a string', () => {
77
+ const mockCallback = vi.fn();
78
+ renderHook(() => useOnPluginFillContent(mockCallback));
79
+
80
+ const testContent = { some: 'data' };
81
+ const event = new MessageEvent('message', {
82
+ data: { type: PluginChannel.fillStandalonePluginContent, content: testContent },
83
+ });
84
+
85
+ window.dispatchEvent(event);
86
+
87
+ expect(mockCallback).toHaveBeenCalledWith(JSON.stringify(testContent));
88
+ });
89
+ });
90
+
91
+ describe('useOnPluginFetchPluginSettings', () => {
92
+ it('calls onRequest when a fetchPluginSettings message is received', () => {
93
+ const mockOnRequest = vi.fn();
94
+ renderHook(() => useOnPluginFetchPluginSettings(mockOnRequest));
95
+
96
+ const event = new MessageEvent('message', {
97
+ data: { type: PluginChannel.fetchPluginSettings },
98
+ });
99
+
100
+ window.dispatchEvent(event);
101
+
102
+ expect(mockOnRequest).toHaveBeenCalled();
103
+ });
104
+ });
@@ -0,0 +1,53 @@
1
+ import { PluginChannel } from '@lobehub/chat-plugin-sdk/client';
2
+ import { renderHook } from '@testing-library/react';
3
+ import { afterEach, describe, expect, it, vi } from 'vitest';
4
+
5
+ import { useOnPluginSettingsUpdate } from './pluginSettings';
6
+
7
+ describe('useOnPluginSettingsUpdate', () => {
8
+ const mockCallback = vi.fn();
9
+
10
+ afterEach(() => {
11
+ mockCallback.mockReset();
12
+ window.removeEventListener('message', expect.any(Function));
13
+ });
14
+
15
+ it('calls the callback when a PluginChannel updatePluginSettings message is received', () => {
16
+ renderHook(() => useOnPluginSettingsUpdate(mockCallback));
17
+
18
+ const testSettings = { theme: 'dark', notifications: true };
19
+ const event = new MessageEvent('message', {
20
+ data: { type: PluginChannel.updatePluginSettings, value: testSettings },
21
+ });
22
+
23
+ window.dispatchEvent(event);
24
+
25
+ expect(mockCallback).toHaveBeenCalledWith(testSettings);
26
+ });
27
+
28
+ it('does not call the callback for non-updatePluginSettings messages', () => {
29
+ renderHook(() => useOnPluginSettingsUpdate(mockCallback));
30
+
31
+ const event = new MessageEvent('message', {
32
+ data: { type: 'nonPluginSettingsUpdate', value: { irrelevant: true } },
33
+ });
34
+
35
+ window.dispatchEvent(event);
36
+
37
+ expect(mockCallback).not.toHaveBeenCalled();
38
+ });
39
+
40
+ it('cleans up message event listener on unmount', () => {
41
+ const { unmount } = renderHook(() => useOnPluginSettingsUpdate(mockCallback));
42
+
43
+ unmount();
44
+
45
+ const event = new MessageEvent('message', {
46
+ data: { type: PluginChannel.updatePluginSettings, value: {} },
47
+ });
48
+
49
+ window.dispatchEvent(event);
50
+
51
+ expect(mockCallback).not.toHaveBeenCalled();
52
+ });
53
+ });
@@ -0,0 +1,43 @@
1
+ import { PluginChannel } from '@lobehub/chat-plugin-sdk/client';
2
+ import { renderHook } from '@testing-library/react';
3
+ import { afterEach, describe, expect, it, vi } from 'vitest';
4
+
5
+ import { useOnPluginStateUpdate } from './pluginState';
6
+
7
+ describe('useOnPluginStateUpdate', () => {
8
+ // Mock for the callback function to be used in tests
9
+ const mockCallback = vi.fn();
10
+
11
+ afterEach(() => {
12
+ // Reset the mock callback after each test
13
+ mockCallback.mockReset();
14
+ // Ensure no event listeners are left hanging after each test
15
+ window.removeEventListener('message', expect.any(Function));
16
+ });
17
+
18
+ it('calls the callback when a PluginChannel update message is received', () => {
19
+ renderHook(() => useOnPluginStateUpdate(mockCallback));
20
+
21
+ const testKey = 'testKey';
22
+ const testValue = 'testValue';
23
+ const event = new MessageEvent('message', {
24
+ data: { type: PluginChannel.updatePluginState, key: testKey, value: testValue },
25
+ });
26
+
27
+ window.dispatchEvent(event);
28
+
29
+ expect(mockCallback).toHaveBeenCalledWith(testKey, testValue);
30
+ });
31
+
32
+ it('does not call the callback for non-PluginChannel messages', () => {
33
+ renderHook(() => useOnPluginStateUpdate(mockCallback));
34
+
35
+ const event = new MessageEvent('message', {
36
+ data: { type: 'nonPluginMessage', key: 'key', value: 'value' },
37
+ });
38
+
39
+ window.dispatchEvent(event);
40
+
41
+ expect(mockCallback).not.toHaveBeenCalled();
42
+ });
43
+ });
@@ -0,0 +1,64 @@
1
+ import { PluginChannel } from '@lobehub/chat-plugin-sdk/client';
2
+ import { describe, expect, it, vi } from 'vitest';
3
+
4
+ import {
5
+ sendMessageContentToPlugin,
6
+ sendPayloadToPlugin,
7
+ sendPluginSettingsToPlugin,
8
+ sendPluginStateToPlugin,
9
+ } from './postMessage';
10
+
11
+ // Mock window object with a postMessage spy
12
+ const mockWindow = {
13
+ postMessage: vi.fn(),
14
+ };
15
+
16
+ describe('plugin communication functions', () => {
17
+ it('sendMessageContentToPlugin should call window.postMessage with correct arguments', () => {
18
+ const props = { some: 'data' };
19
+ sendMessageContentToPlugin(mockWindow as unknown as Window, props);
20
+ expect(mockWindow.postMessage).toHaveBeenCalledWith(
21
+ { props, type: PluginChannel.renderPlugin },
22
+ '*',
23
+ );
24
+ });
25
+
26
+ it('sendPayloadToPlugin should call window.postMessage with correct arguments', () => {
27
+ const props = { payload: 'payload', settings: 'settings', state: 'state' };
28
+ sendPayloadToPlugin(mockWindow as unknown as Window, props);
29
+ expect(mockWindow.postMessage).toHaveBeenCalledWith(
30
+ {
31
+ type: PluginChannel.initStandalonePlugin,
32
+ payload: props.payload,
33
+ settings: props.settings,
34
+ state: props.state,
35
+ props: props.payload, // Note: This is due to the TODO in your code
36
+ },
37
+ '*',
38
+ );
39
+ });
40
+
41
+ it('sendPluginStateToPlugin should call window.postMessage with correct arguments', () => {
42
+ const key = 'key';
43
+ const value = 'value';
44
+ sendPluginStateToPlugin(mockWindow as unknown as Window, key, value);
45
+ expect(mockWindow.postMessage).toHaveBeenCalledWith(
46
+ { key, type: PluginChannel.renderPluginState, value },
47
+ '*',
48
+ );
49
+ });
50
+
51
+ it('sendPluginSettingsToPlugin should call window.postMessage with correct arguments', () => {
52
+ const settings = { setting1: 'value1' };
53
+ sendPluginSettingsToPlugin(mockWindow as unknown as Window, settings);
54
+ expect(mockWindow.postMessage).toHaveBeenCalledWith(
55
+ { type: PluginChannel.renderPluginSettings, value: settings },
56
+ '*',
57
+ );
58
+ });
59
+ });
60
+
61
+ // Reset the mock after each test
62
+ afterEach(() => {
63
+ vi.resetAllMocks();
64
+ });
@@ -4,8 +4,19 @@ export const sendMessageContentToPlugin = (window: Window, props: any) => {
4
4
  window.postMessage({ props, type: PluginChannel.renderPlugin }, '*');
5
5
  };
6
6
 
7
- export const sendPayloadToPlugin = (window: Window, props: any) => {
8
- window.postMessage({ props, type: PluginChannel.initStandalonePlugin }, '*');
7
+ export const sendPayloadToPlugin = (
8
+ window: Window,
9
+ props: { payload: any; settings: any; state?: any },
10
+ ) => {
11
+ window.postMessage(
12
+ {
13
+ type: PluginChannel.initStandalonePlugin,
14
+ ...props,
15
+ // TODO: props need to deprecated
16
+ props: props.payload,
17
+ },
18
+ '*',
19
+ );
9
20
  };
10
21
 
11
22
  export const sendPluginStateToPlugin = (window: Window, key: string, value: any) => {
@@ -12,6 +12,7 @@ const useStyles = createStyles(({ css, token, stylish }) => ({
12
12
  content: css`
13
13
  display: flex;
14
14
  flex-direction: column;
15
+ height: 100% !important;
15
16
  `,
16
17
  drawer: css`
17
18
  background: ${token.colorBgLayout};
@@ -11,7 +11,7 @@ import StoreHydration from './StoreHydration';
11
11
 
12
12
  const useStyles = createStyles(({ css, token }) => ({
13
13
  bg: css`
14
- overflow-y: scroll;
14
+ overflow-y: hidden;
15
15
  display: flex;
16
16
  flex-direction: column;
17
17
  align-items: center;