diff --git a/.dumirc.ts b/.dumirc.ts new file mode 100644 index 0000000..a14c68a --- /dev/null +++ b/.dumirc.ts @@ -0,0 +1,45 @@ +import { defineConfig } from 'dumi'; + +import { homepage } from './package.json'; + +const themeConfig = { + actions: [ + { + link: homepage, + openExternal: true, + text: 'Github', + }, + { + link: '/components/action-icon', + text: 'Get Started', + type: 'primary', + }, + ], + footer: 'Made with 🤯 by LobeHub', + name: 'Lobe Chat Plugin SDK', + socialLinks: { + discord: 'https://discord.gg/AYFPHvv2jT', + github: homepage, + }, +}; + +export default defineConfig({ + extraBabelPlugins: ['babel-plugin-antd-style'], + favicons: [ + 'https://registry.npmmirror.com/@lobehub/assets-emoji/1.3.0/files/assets/puzzle-piece.webp', + ], + // locales: [{ id: 'en-US', name: 'English' }], + mfsu: {}, + npmClient: 'pnpm', + outputPath: 'docs-dist', + // ssr: isProduction ? {} : false, + styles: [ + `html, body { background: transparent; } + + @media (prefers-color-scheme: dark) { + html, body { background: #000; } + }`, + ], + themeConfig, + title: 'Lobe Chat Plugin SDK', +}); diff --git a/docs/api/channel.md b/docs/api/channel.md new file mode 100644 index 0000000..8cd21ed --- /dev/null +++ b/docs/api/channel.md @@ -0,0 +1,54 @@ +--- +title: 消息通信类型 +order: 10 +group: 前端渲染 +atomId: PluginChannel +description: 提供了关于插件通信的消息类型的详细说明 +nav: + title: API + order: 1 +--- + +# PluginChannel 通信消息 + +一般来说你可能用不到 `PluginChannel` ,但如果你希望使用 LobeChat 底层的消息通信机制,你可能需要了解这些消息类型。 本文档包含了通信消息类型的详细说明。 + +## fetchPluginMessage + +- 字面量:`'lobe-chat:fetch-plugin-message` + +用于插件主动向 LobeChat 发起消息请求的通道 + +```ts +import { PluginChannel } from '@lobehub/chat-plugin-sdk'; + +const channel = PluginChannel.fetchPluginMessage; +``` + +## pluginReadyForRender + +- 字面量:`lobe-chat:plugin-ready-for-render` + +用于通知 LobeChat 主体,插件已准备好进行渲染的通道 + +```ts +import { PluginChannel } from '@lobehub/chat-plugin-sdk'; + +const channel = PluginChannel.pluginReadyForRender; +``` + +:::info +主程序将会在收到此消息后,通过 `renderPlugin` 通道发送插件的信息 +::: + +## renderPlugin + +- 字面量:`'lobe-chat:render-plugin` + +用于主程序向插件发送渲染指令的通道。 + +```ts +import { PluginChannel } from '@lobehub/chat-plugin-sdk'; + +const channel = PluginChannel.pluginReadyForRender; +``` diff --git a/docs/api/error.md b/docs/api/error.md new file mode 100644 index 0000000..348ec2f --- /dev/null +++ b/docs/api/error.md @@ -0,0 +1,61 @@ +--- +title: 服务端错误类型 +atomId: PluginErrorType +description: 插件错误类型 +group: 服务端 +nav: API +order: 100 +--- + +LobeChat 在插件服务请求中所有的错误类型,包括业务语义错误、客户端错误和服务端错误。 + +## 使用方式 + +搭配 `createErrorResponse` 使用: + +```ts +import { PluginErrorType } from '@lobehub/chat-plugin-sdk'; + +export default async (req: Request) => { + if (req.method !== 'POST') return createErrorResponse(PluginErrorType.MethodNotAllowed); + + // ... +}; +``` + +## 错误类型明细 + +### 业务错误 + +| 错误类型 | 描述 | +| --------------------------- | ----------------------- | +| `PluginMarketIndexNotFound` | 插件市场索引解析失败 | +| `PluginMarketIndexInvalid` | 插件市场索引无效 | +| `PluginMetaNotFound` | 没有找到插件元数据 | +| `PluginMetaInvalid` | 插件元数据无效 | +| `PluginManifestNotFound` | 插件描述文件不存在 | +| `PluginManifestInvalid` | 插件描述文件格式不正确 | +| `PluginSettingsInvalid` | 插件设置不正确 | +| `PluginApiNotFound` | 插件 API 不存在 | +| `PluginApiParamsError` | 插件 API 请求入参有问题 | +| `PluginServerError` | 插件服务端出错 | + +### 客户端错误 + +| 错误类型 | 描述 | +| ------------------ | ---------------------- | +| `BadRequest` | 400 Bad Request | +| `Unauthorized` | 401 Unauthorized | +| `Forbidden` | 403 Forbidden | +| `ContentNotFound` | 404 Not Found | +| `MethodNotAllowed` | 405 Method Not Allowed | +| `TooManyRequests` | 429 Too Many Requests | + +### 服务端错误 + +| 错误类型 | 描述 | +| --------------------- | ------------------------- | +| `InternalServerError` | 500 Internal Server Error | +| `BadGateway` | 502 Bad Gateway | +| `ServiceUnavailable` | 503 Service Unavailable | +| `GatewayTimeout` | 504 Gateway Timeout | diff --git a/docs/api/message.md b/docs/api/message.md new file mode 100644 index 0000000..d93fd19 --- /dev/null +++ b/docs/api/message.md @@ -0,0 +1,39 @@ +--- +title: fetchPluginMessage +description: 该方法用于从插件通道获取插件消息 +group: + title: 前端渲染 + order: 10 +nav: API +--- + +该方法用于从插件通道获取插件消息。 + +## 类型 + +```ts +export const fetchPluginMessage = () => Promise; +``` + +## 返回值 + +一个 Promise,返回插件消息的内容。 + +### 示例 + +```ts +import { fetchPluginMessage } from '@lobehub/chat-plugin-sdk'; + +fetchPluginMessage() + .then((message) => { + console.log(message); + }) + .catch((error) => { + console.error(error); + }); +``` + +## 注意事项 + +- 该函数使用了浏览器的 `postMessage` 和 `addEventListener` 方法,因此需要在浏览器环境中使用; +- 该函数通过插件通道向父窗口发送消息,因此调用该方法的应用必须嵌入在 LobeChat 中才能返回正确的消息; diff --git a/docs/api/plugin-manifest.md b/docs/api/plugin-manifest.md new file mode 100644 index 0000000..accc6c5 --- /dev/null +++ b/docs/api/plugin-manifest.md @@ -0,0 +1,118 @@ +--- +title: 插件描述清单 Schema +group: Schema +atomId: pluginManifestSchema +description: 插件描述文件的 Schema +nav: API +--- + +## pluginManifestSchema + +**描述**:插件的清单文件(Manifest)数据模式定义。 + +### 使用示例 + +```typescript +import { pluginManifestSchema } from '@lobehub/chat-plugin-sdk'; + +const manifestData = { + api: [ + { + description: 'API 描述', + name: 'API 名称', + parameters: { + properties: {}, + type: 'object', + }, + url: 'http://example.com/api', + }, + ], + gateway: 'http://example.com/gateway', + identifier: 'plugin-identifier', + openapi: 'http://example.com/openapi', + settings: { + properties: {}, + type: 'object', + }, + ui: { + height: 500, + mode: 'iframe', + url: 'http://example.com/plugin', + width: 800, + }, +}; + +const result = pluginManifestSchema.parse(manifestData); + +console.log(result); + +// 输出:{ api: [ { description: 'API 描述', name: 'API 名称', parameters: { properties: {}, type: 'object' }, url: 'http://example.com/api' } ], gateway: 'http://example.com/gateway', identifier: 'plugin-identifier', openapi: 'http://example.com/openapi', settings: { properties: {}, type: 'object' }, ui: { height: 500, mode: 'iframe', url: 'http://example.com/plugin', width: 800 } } +``` + +## `pluginApiSchema` + +**描述**:插件 API 的数据模式定义。 + +```typescript +import { z } from 'zod'; + +const JSONSchema = z.object({ + properties: z.object({}), + type: z.enum(['object']), +}); + +const pluginApiSchema = z.object({ + description: z.string(), + name: z.string(), + parameters: JSONSchema, + url: z.string().url(), +}); + +export default pluginApiSchema; +``` + +### 使用示例 + +```typescript +import { pluginApiSchema } from '@lobehub/chat-plugin-sdk'; + +const apiData = { + description: 'API 描述', + name: 'API 名称', + parameters: { + properties: {}, + type: 'object', + }, + url: 'http://example.com/api', +}; + +const result = pluginApiSchema.parse(apiData); +console.log(result); +// 输出:{ description: 'API 描述', name: 'API 名称', parameters: { properties: {}, type: 'object' }, url: 'http://example.com/api' } +``` + +## Schema 定义 + +### pluginManifestSchema + +| 属性 | 类型 | 描述 | +| ------------ | ------------------- | ----------------------- | +| `api` | `pluginApiSchema[]` | 插件的 API 列表 | +| `gateway` | `string` (可选) | 插件的网关 URL | +| `identifier` | `string` | 插件的标识符 | +| `openapi` | `string` (可选) | 插件的 OpenAPI 文档 URL | +| `settings` | `JSONSchema` (可选) | 插件的设置数据定义 | +| `ui` | `object` (可选) | 插件的 UI 配置 | +| `ui.height` | `number` (可选) | 插件 UI 的高度 | +| `ui.mode` | `'iframe'` (可选) | 插件 UI 的模式 | +| `ui.url` | `string` | 插件 UI 的 URL | +| `ui.width` | `number` (可选) | 插件 UI 的宽度 | + +### pluginApiSchema + +| 属性 | 类型 | 描述 | +| ------------- | ------------ | ------------------- | +| `description` | `string` | 插件 API 的描述 | +| `name` | `string` | 插件 API 的名称 | +| `parameters` | `JSONSchema` | 插件 API 的参数定义 | +| `url` | `string` | 插件 API 的 URL | diff --git a/docs/api/plugin-meta-index.md b/docs/api/plugin-meta-index.md new file mode 100644 index 0000000..1f61ad5 --- /dev/null +++ b/docs/api/plugin-meta-index.md @@ -0,0 +1,48 @@ +--- +title: 插件市场元数据 Schema +group: Schema +atomId: pluginMetaSchema +description: 上架到插件市场中的插件元数据的数据模式定义。 +nav: API +--- + +插件元数据的 Schema。 + +### 使用示例 + +```typescript +import { pluginMetaSchema } from '@lobehub/chat-plugin-sdk'; + +const meta = { + author: 'John Doe', + createAt: '2022-01-01', + homepage: 'http://example.com', + identifier: 'plugin-identifier', + manifest: 'http://example.com/manifest', + meta: { + avatar: 'http://example.com/avatar.png', + tags: ['tag1', 'tag2'], + }, + schemaVersion: 1, +}; + +const result = pluginMetaSchema.parse(meta); + +console.log(result); + +// 输出:{ author: 'John Doe', createAt: '2022-01-01', homepage: 'http://example.com', identifier: 'plugin-identifier', manifest: 'http://example.com/manifest', meta: { avatar: 'http://example.com/avatar.png', tags: ['tag1', 'tag2'] }, schemaVersion: 1 } +``` + +### Schema 定义 + +| 属性 | 类型 | 描述 | +| --------------- | ----------------- | -------------------------------- | +| `author` | `string` | 插件的作者 | +| `createAt` | `string` | 插件的创建日期 | +| `homepage` | `string` | 插件的主页 URL | +| `identifier` | `string` | 插件的标识符 | +| `manifest` | `string` | 插件描述文件的 URL | +| `meta` | `object` (可选) | 插件的元数据 | +| `meta.avatar` | `string` (可选) | 插件作者的头像 URL | +| `meta.tags` | `string[]` (可选) | 插件的标签列表 | +| `schemaVersion` | `number` | 插件元数据的数据模式定义的版本号 | diff --git a/docs/api/request.md b/docs/api/request.md new file mode 100644 index 0000000..1435077 --- /dev/null +++ b/docs/api/request.md @@ -0,0 +1,49 @@ +--- +title: getPluginSettingsStringFromRequest +description: 从请求中获取插件设置字符串 +group: + title: 服务端 + order: 1 +nav: API +--- + +用于从请求中获取插件设置字符串。 + +## 语法 + +```ts +const settings = getPluginSettingsStringFromRequest(req: Request): T | undefined; +``` + +## 参数 + +| 参数名 | 类型 | 描述 | +| ------ | --------- | ------------ | +| `req` | `Request` | 标准请求对象 | + +## 返回值 + +返回值类型为 `T | undefined`,表示插件设置字符串。 + +## 示例 + +```ts +import { + createHeadersWithPluginSettings, + getPluginSettingsStringFromRequest, +} from '@lobehub/chat-plugin-sdk'; + +const req = new Request('https://api.example.com', { + headers: createHeadersWithPluginSettings({ theme: 'dark' }), +}); + +const settings = getPluginSettingsStringFromRequest(req); + +console.log(settings); // 输出: { theme: "dark" } +``` + +## 注意事项 + +- 请确保传入的请求对象包含 `Lobe-Plugin-Settings` 头部字段。 + +- 如果解析插件设置字符串失败,则返回 `undefined`。 diff --git a/docs/api/use-watch-plugin-message.md b/docs/api/use-watch-plugin-message.md new file mode 100644 index 0000000..4821fbb --- /dev/null +++ b/docs/api/use-watch-plugin-message.md @@ -0,0 +1,48 @@ +--- +title: useWatchPluginMessage +description: 监听获取 LobeChat 发过来的插件消息 +nav: API +group: 前端渲染 +--- + +`useWatchPluginMessage` 是 Chat Plugin SDK 封装一个的 React Hook,用于监听从 LobeChat 发过来的插件消息。 + +## 语法 + +```ts +const { data, loading } = useWatchPluginMessage(); +``` + +## 示例 + +```tsx | pure +import { useWatchPluginMessage } from '@lobehub/chat-plugin-sdk'; + +const Demo = () => { + const { data, loading } = useWatchPluginMessage(); + + if (loading) { + return
Loading...
; + } + + return ( +
+

插件发送的消息数据:

+
{JSON.stringify(data, null, 2)}
+
+ ); +}; + +export default Demo; +``` + +## 注意事项 + +- 请确保 `useWatchPluginMessage` 在 React 函数组件内部使用。 + +## 返回值类型定义 + +| 属性 | 类型 | 描述 | +| --------- | --------- | -------------------- | +| `data` | `T` | 插件发送的消息数据 | +| `loading` | `boolean` | 表示是否正在加载数据 | diff --git a/docs/changelog.md b/docs/changelog.md new file mode 100644 index 0000000..6660760 --- /dev/null +++ b/docs/changelog.md @@ -0,0 +1,9 @@ +--- +title: Changelog +description: New updates and improvements to @lobehub/chat-plugin-sdk +nav: + title: Changelog + order: 999 +--- + + diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..89f545d --- /dev/null +++ b/docs/index.md @@ -0,0 +1,5 @@ +--- +hero: + title: Chat Plugin SDK + description: Build your Chat Plugin easily +--- diff --git a/package.json b/package.json index 9cd908f..4212b12 100644 --- a/package.json +++ b/package.json @@ -30,10 +30,10 @@ ], "scripts": { "build": "father build", - "build:docs": "npm run build && npm run build --prefix=example", "ci": "npm run lint && npm run type-check && npm run test", "dev": "father dev", - "dev:docs": "npm run start --prefix=example", + "docs:build": "dumi build", + "docs:dev": "dumi dev", "doctor": "father doctor", "lint": "eslint \"{src,example}/**/*.{js,jsx,ts,tsx}\" --fix", "lint:md": "remark . --quiet --frail --output", @@ -84,7 +84,7 @@ "clean-pkg-json": "^1", "commitlint": "^17", "dumi": "^2", - "dumi-assets-types": "^1", + "dumi-theme-lobehub": "latest", "eslint": "^8", "father": "^4", "husky": "^8",