koishi-plugin-chatluna 1.0.0-beta.20

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.
Files changed (232) hide show
  1. package/README.MD +130 -0
  2. package/lib/authorization/service.d.ts +24 -0
  3. package/lib/authorization/service.js +342 -0
  4. package/lib/authorization/types.d.ts +36 -0
  5. package/lib/authorization/types.js +2 -0
  6. package/lib/cache.d.ts +18 -0
  7. package/lib/cache.js +27 -0
  8. package/lib/chains/chain.d.ts +66 -0
  9. package/lib/chains/chain.js +465 -0
  10. package/lib/chains/rooms.d.ts +24 -0
  11. package/lib/chains/rooms.js +486 -0
  12. package/lib/command.d.ts +3 -0
  13. package/lib/command.js +21 -0
  14. package/lib/commands/auth.d.ts +4 -0
  15. package/lib/commands/auth.js +92 -0
  16. package/lib/commands/chat.d.ts +4 -0
  17. package/lib/commands/chat.js +51 -0
  18. package/lib/commands/model.d.ts +4 -0
  19. package/lib/commands/model.js +18 -0
  20. package/lib/commands/preset.d.ts +4 -0
  21. package/lib/commands/preset.js +47 -0
  22. package/lib/commands/providers.d.ts +4 -0
  23. package/lib/commands/providers.js +44 -0
  24. package/lib/commands/room.d.ts +4 -0
  25. package/lib/commands/room.js +169 -0
  26. package/lib/config.d.ts +36 -0
  27. package/lib/config.js +151 -0
  28. package/lib/index.d.ts +11 -0
  29. package/lib/index.js +101 -0
  30. package/lib/llm-core/chain/base.d.ts +79 -0
  31. package/lib/llm-core/chain/base.js +111 -0
  32. package/lib/llm-core/chain/browsing_chat_chain.d.ts +33 -0
  33. package/lib/llm-core/chain/browsing_chat_chain.js +183 -0
  34. package/lib/llm-core/chain/chat_chain.d.ts +24 -0
  35. package/lib/llm-core/chain/chat_chain.js +109 -0
  36. package/lib/llm-core/chain/function_calling_browsing_chain.d.ts +31 -0
  37. package/lib/llm-core/chain/function_calling_browsing_chain.js +149 -0
  38. package/lib/llm-core/chain/out_parsers.d.ts +11 -0
  39. package/lib/llm-core/chain/out_parsers.js +34 -0
  40. package/lib/llm-core/chain/plugin_chat_chain.d.ts +29 -0
  41. package/lib/llm-core/chain/plugin_chat_chain.js +133 -0
  42. package/lib/llm-core/chain/prompt.d.ts +85 -0
  43. package/lib/llm-core/chain/prompt.js +437 -0
  44. package/lib/llm-core/chain/wrapper_chain.d.ts +21 -0
  45. package/lib/llm-core/chain/wrapper_chain.js +61 -0
  46. package/lib/llm-core/chat/app.d.ts +40 -0
  47. package/lib/llm-core/chat/app.js +281 -0
  48. package/lib/llm-core/chat/default.d.ts +3 -0
  49. package/lib/llm-core/chat/default.js +119 -0
  50. package/lib/llm-core/memory/message/database_memory.d.ts +50 -0
  51. package/lib/llm-core/memory/message/database_memory.js +184 -0
  52. package/lib/llm-core/model/base.d.ts +18 -0
  53. package/lib/llm-core/model/base.js +35 -0
  54. package/lib/llm-core/model/in_memory.d.ts +15 -0
  55. package/lib/llm-core/model/in_memory.js +32 -0
  56. package/lib/llm-core/platform/api.d.ts +59 -0
  57. package/lib/llm-core/platform/api.js +15 -0
  58. package/lib/llm-core/platform/client.d.ts +25 -0
  59. package/lib/llm-core/platform/client.js +46 -0
  60. package/lib/llm-core/platform/config.d.ts +40 -0
  61. package/lib/llm-core/platform/config.js +93 -0
  62. package/lib/llm-core/platform/model.d.ts +105 -0
  63. package/lib/llm-core/platform/model.js +334 -0
  64. package/lib/llm-core/platform/service.d.ts +54 -0
  65. package/lib/llm-core/platform/service.js +216 -0
  66. package/lib/llm-core/platform/types.d.ts +51 -0
  67. package/lib/llm-core/platform/types.js +9 -0
  68. package/lib/llm-core/prompt/index.d.ts +1 -0
  69. package/lib/llm-core/prompt/index.js +17 -0
  70. package/lib/llm-core/prompt/preset_prompt_parse.d.ts +19 -0
  71. package/lib/llm-core/prompt/preset_prompt_parse.js +103 -0
  72. package/lib/llm-core/utils/chunk.d.ts +1 -0
  73. package/lib/llm-core/utils/chunk.js +11 -0
  74. package/lib/llm-core/utils/count_tokens.d.ts +13 -0
  75. package/lib/llm-core/utils/count_tokens.js +138 -0
  76. package/lib/llm-core/utils/tiktoken.d.ts +10 -0
  77. package/lib/llm-core/utils/tiktoken.js +40 -0
  78. package/lib/middleware.d.ts +3 -0
  79. package/lib/middleware.js +21 -0
  80. package/lib/middlewares/add_preset.d.ts +12 -0
  81. package/lib/middlewares/add_preset.js +46 -0
  82. package/lib/middlewares/add_room_to_group.d.ts +9 -0
  83. package/lib/middlewares/add_room_to_group.js +36 -0
  84. package/lib/middlewares/add_user_to_auth_group.d.ts +9 -0
  85. package/lib/middlewares/add_user_to_auth_group.js +20 -0
  86. package/lib/middlewares/allow_reply.d.ts +9 -0
  87. package/lib/middlewares/allow_reply.js +41 -0
  88. package/lib/middlewares/black_list.d.ts +9 -0
  89. package/lib/middlewares/black_list.js +21 -0
  90. package/lib/middlewares/censor.d.ts +9 -0
  91. package/lib/middlewares/censor.js +17 -0
  92. package/lib/middlewares/chat_time_limit_check.d.ts +25 -0
  93. package/lib/middlewares/chat_time_limit_check.js +93 -0
  94. package/lib/middlewares/chat_time_limit_save.d.ts +9 -0
  95. package/lib/middlewares/chat_time_limit_save.js +32 -0
  96. package/lib/middlewares/check_room.d.ts +9 -0
  97. package/lib/middlewares/check_room.js +37 -0
  98. package/lib/middlewares/clear_balance.d.ts +9 -0
  99. package/lib/middlewares/clear_balance.js +20 -0
  100. package/lib/middlewares/clear_room.d.ts +9 -0
  101. package/lib/middlewares/clear_room.js +36 -0
  102. package/lib/middlewares/clone_preset.d.ts +15 -0
  103. package/lib/middlewares/clone_preset.js +44 -0
  104. package/lib/middlewares/cooldown_time.d.ts +9 -0
  105. package/lib/middlewares/cooldown_time.js +23 -0
  106. package/lib/middlewares/create_auth_group.d.ts +20 -0
  107. package/lib/middlewares/create_auth_group.js +253 -0
  108. package/lib/middlewares/create_room.d.ts +21 -0
  109. package/lib/middlewares/create_room.js +257 -0
  110. package/lib/middlewares/delete_preset.d.ts +12 -0
  111. package/lib/middlewares/delete_preset.js +60 -0
  112. package/lib/middlewares/delete_room.d.ts +9 -0
  113. package/lib/middlewares/delete_room.js +45 -0
  114. package/lib/middlewares/invite_room.d.ts +14 -0
  115. package/lib/middlewares/invite_room.js +33 -0
  116. package/lib/middlewares/join_room.d.ts +9 -0
  117. package/lib/middlewares/join_room.js +65 -0
  118. package/lib/middlewares/kick_member.d.ts +9 -0
  119. package/lib/middlewares/kick_member.js +33 -0
  120. package/lib/middlewares/kick_user_form_auth_group.d.ts +9 -0
  121. package/lib/middlewares/kick_user_form_auth_group.js +20 -0
  122. package/lib/middlewares/leave_room.d.ts +9 -0
  123. package/lib/middlewares/leave_room.js +45 -0
  124. package/lib/middlewares/lifecycle.d.ts +29 -0
  125. package/lib/middlewares/lifecycle.js +31 -0
  126. package/lib/middlewares/list_all_embeddings.d.ts +9 -0
  127. package/lib/middlewares/list_all_embeddings.js +28 -0
  128. package/lib/middlewares/list_all_model.d.ts +13 -0
  129. package/lib/middlewares/list_all_model.js +28 -0
  130. package/lib/middlewares/list_all_preset.d.ts +9 -0
  131. package/lib/middlewares/list_all_preset.js +39 -0
  132. package/lib/middlewares/list_all_vectorstore.d.ts +9 -0
  133. package/lib/middlewares/list_all_vectorstore.js +27 -0
  134. package/lib/middlewares/list_auth_group.d.ts +14 -0
  135. package/lib/middlewares/list_auth_group.js +39 -0
  136. package/lib/middlewares/list_room.d.ts +11 -0
  137. package/lib/middlewares/list_room.js +43 -0
  138. package/lib/middlewares/mute_user.d.ts +9 -0
  139. package/lib/middlewares/mute_user.js +38 -0
  140. package/lib/middlewares/query_balance.d.ts +9 -0
  141. package/lib/middlewares/query_balance.js +19 -0
  142. package/lib/middlewares/read_chat_message.d.ts +9 -0
  143. package/lib/middlewares/read_chat_message.js +51 -0
  144. package/lib/middlewares/render_message.d.ts +14 -0
  145. package/lib/middlewares/render_message.js +30 -0
  146. package/lib/middlewares/request_model.d.ts +15 -0
  147. package/lib/middlewares/request_model.js +207 -0
  148. package/lib/middlewares/resolve_model.d.ts +9 -0
  149. package/lib/middlewares/resolve_model.js +21 -0
  150. package/lib/middlewares/resolve_room.d.ts +14 -0
  151. package/lib/middlewares/resolve_room.js +84 -0
  152. package/lib/middlewares/room_info.d.ts +9 -0
  153. package/lib/middlewares/room_info.js +37 -0
  154. package/lib/middlewares/room_permission.d.ts +9 -0
  155. package/lib/middlewares/room_permission.js +49 -0
  156. package/lib/middlewares/set_auto_update_room.d.ts +12 -0
  157. package/lib/middlewares/set_auto_update_room.js +42 -0
  158. package/lib/middlewares/set_balance.d.ts +13 -0
  159. package/lib/middlewares/set_balance.js +20 -0
  160. package/lib/middlewares/set_default_embeddings.d.ts +16 -0
  161. package/lib/middlewares/set_default_embeddings.js +46 -0
  162. package/lib/middlewares/set_default_vectorstore.d.ts +12 -0
  163. package/lib/middlewares/set_default_vectorstore.js +45 -0
  164. package/lib/middlewares/set_preset.d.ts +12 -0
  165. package/lib/middlewares/set_preset.js +38 -0
  166. package/lib/middlewares/set_room.d.ts +9 -0
  167. package/lib/middlewares/set_room.js +194 -0
  168. package/lib/middlewares/switch_room.d.ts +9 -0
  169. package/lib/middlewares/switch_room.js +18 -0
  170. package/lib/middlewares/thinking_message_recall.d.ts +9 -0
  171. package/lib/middlewares/thinking_message_recall.js +16 -0
  172. package/lib/middlewares/thinking_message_send.d.ts +18 -0
  173. package/lib/middlewares/thinking_message_send.js +53 -0
  174. package/lib/middlewares/transfer_room.d.ts +9 -0
  175. package/lib/middlewares/transfer_room.js +46 -0
  176. package/lib/middlewares/wipe.d.ts +13 -0
  177. package/lib/middlewares/wipe.js +91 -0
  178. package/lib/preset.d.ts +19 -0
  179. package/lib/preset.js +116 -0
  180. package/lib/render.d.ts +18 -0
  181. package/lib/render.js +58 -0
  182. package/lib/renders/image.d.ts +14 -0
  183. package/lib/renders/image.js +104 -0
  184. package/lib/renders/mixed-image.d.ts +16 -0
  185. package/lib/renders/mixed-image.js +191 -0
  186. package/lib/renders/mixed-voice.d.ts +14 -0
  187. package/lib/renders/mixed-voice.js +89 -0
  188. package/lib/renders/raw.d.ts +5 -0
  189. package/lib/renders/raw.js +12 -0
  190. package/lib/renders/text.d.ts +7 -0
  191. package/lib/renders/text.js +38 -0
  192. package/lib/renders/voice.d.ts +7 -0
  193. package/lib/renders/voice.js +58 -0
  194. package/lib/services/chat.d.ts +104 -0
  195. package/lib/services/chat.js +586 -0
  196. package/lib/services/message_transform.d.ts +9 -0
  197. package/lib/services/message_transform.js +35 -0
  198. package/lib/services/types.d.ts +23 -0
  199. package/lib/services/types.js +2 -0
  200. package/lib/types.d.ts +53 -0
  201. package/lib/types.js +2 -0
  202. package/lib/utils/error.d.ts +47 -0
  203. package/lib/utils/error.js +71 -0
  204. package/lib/utils/flow.d.ts +11 -0
  205. package/lib/utils/flow.js +52 -0
  206. package/lib/utils/lock.d.ts +9 -0
  207. package/lib/utils/lock.js +46 -0
  208. package/lib/utils/logger.d.ts +4 -0
  209. package/lib/utils/logger.js +25 -0
  210. package/lib/utils/pagination.d.ts +18 -0
  211. package/lib/utils/pagination.js +42 -0
  212. package/lib/utils/promise.d.ts +7 -0
  213. package/lib/utils/promise.js +20 -0
  214. package/lib/utils/queue.d.ts +9 -0
  215. package/lib/utils/queue.js +56 -0
  216. package/lib/utils/request.d.ts +18 -0
  217. package/lib/utils/request.js +121 -0
  218. package/lib/utils/sse.d.ts +2 -0
  219. package/lib/utils/sse.js +63 -0
  220. package/lib/utils/stream.d.ts +1 -0
  221. package/lib/utils/stream.js +45 -0
  222. package/lib/utils/string.d.ts +1 -0
  223. package/lib/utils/string.js +17 -0
  224. package/lib/utils/types.d.ts +1 -0
  225. package/lib/utils/types.js +2 -0
  226. package/package.json +102 -0
  227. package/resources/css/code.css +118 -0
  228. package/resources/css/main.css +412 -0
  229. package/resources/out.html +64 -0
  230. package/resources/presets/catgirl.yml +23 -0
  231. package/resources/presets/chatgpt.yml +10 -0
  232. package/resources/template.html +63 -0
package/README.MD ADDED
@@ -0,0 +1,130 @@
1
+
2
+ <div align="center">
3
+
4
+ # koishi-plugin-chathub
5
+
6
+ _多平台模型接入,可扩展,多种输出格式,基于 LangChain,提供语言模型聊天服务的 Koishi 插件。_
7
+
8
+ ## [![npm](https://img.shields.io/npm/v/koishi-plugin-chatluna/next)](https://www.npmjs.com/package/koishi-plugin-chatluna) [![npm](https://img.shields.io/npm/dm/koishi-plugin-chatluna)](https://www.npmjs.com/package/koishi-plugin-chatluna) ![node version](https://img.shields.io/badge/node-%3E=18-green) ![github top language](https://img.shields.io/github/languages/top/dingyi222666/koishi-plugin-chathub?logo=github) [![Telegram](https://img.shields.io/badge/Join-Telegram_Group-blue)](https://t.me/koishi_chathub) [![QQ](https://img.shields.io/badge/Join-QQ_Group-ff69b4)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=eEBVq6GK7HYX2y61x55WD6hnXTIRop-0&authKey=i4pG5%2BJ%2FY8auWprBubhremTkn3vroPigQq5m9RENGBLrLmlj%2BSu3G%2BqllK7Wts2M&noverify=0&group_code=282381753) [![doc](https://img.shields.io/badge/See-Document(WIP)-green)](https://chathub.dingyi222666.top/)
9
+
10
+ **当前项目状态:缓慢迭代到 1.0 正式版**
11
+
12
+ </div>
13
+
14
+ ### 截图
15
+
16
+ 施工中.....
17
+
18
+ ### 特性
19
+
20
+ - 高扩展性,基于 LangChain 和 Koishi,我们提供了一套扩展 API,让第三方插件开发者可以轻松的扩展或调用此项目的服务。如 调用模型,对接新模型等
21
+ - 预设系统,可设置对话的预设,调教模型。
22
+ - 黑名单系统,全局冷却时间和模型并发请求限制,以及按小时的模型的调用额度限制,轻松管理模型的调用限额等。
23
+ - 支持 语音/文字/图片/图文混合 回复,也支持解析返回的 markdown ,实现比较自然的分割成多条消息来发送
24
+ - 上下文对话,长期记忆的支持 (需要适配器支持)
25
+ - 三种聊天模式: `chat`,`browsing`,`plugin`
26
+
27
+ 后两种模式可让模型调用外部工具,使得模型能获取到外部信息,执行相关操作等。
28
+
29
+ - 内容安全过滤,基于 Koishi 的 [censor 服务](`https://censor.koishi.chat/`), 防止模型返回不良内容
30
+
31
+ ### TODO (画饼是吧)
32
+
33
+ - [x] 基于房间的对话系统
34
+ - [x] 回复内容审核 (基于其他插件提供的 censor 服务)
35
+ - [x] 语音输出支持(即文字转语音)(基于 initialencounter 佬的 [vits服务](https://github.com/initialencounter/mykoishi/blame/master/vits/readme.md),可在 Koishi 插件市场搜索 `open-vits`来使用可开箱即用的 vits 服务)
36
+ - [x] 图片渲染回复
37
+ - [x] 接入更多模型/平台
38
+ - [x] 预设系统
39
+ - [x] 导入或导出会话记录(实际未完成,已暂时放弃支持)
40
+ - [x] 重构到 v1 版本
41
+ - [x] 流式响应支持
42
+ - [ ] i18n 本地化支持
43
+
44
+ ### 部署
45
+
46
+ #### 环境要求
47
+
48
+ ```text
49
+ koishi >= 4.15
50
+ nodejs >= 18
51
+ ```
52
+
53
+ 由于 Koishi 平台的插件市场的友好和便捷,我们可在 Koishi 下直接安装本插件使用基础功能而无需额外配置。
54
+
55
+ 前往 Koishi 控制台的插件市场,搜索 `chathub`,然后按下面顺序操作:
56
+
57
+ 1. 安装核心服务支持插件:`@dingyi222666/chathub`
58
+ 2. 安装模型适配器插件:`@dingyi222666/chathub-xxx-adapter` (xxx 为目前我们支持的模型适配器的名称,见下表)
59
+ 3. 按上面的顺序依次安装插件(注意安装后了要先启用插件了然后在下一步),然后在安装好插件所需要的其他插件(也就是插件的必须服务)(例如`@dingyi222666/chathub`插件依赖`cache`服务,你需要安装一个提供了`cache`服务的插件)。
60
+ 4. 配置好插件和适配器。(具体配置基本上描述都有写到,如果没有的话可能需要自己摸索了(我暂时还没空写这块的文档))
61
+ 5. 先启动主插件,然后在主插件上配置好模板房间使用的模型,预设等,然后保存。
62
+
63
+ 接下来就可以使用本插件了。
64
+
65
+ ### 适配支持
66
+
67
+ 我们目前支持以下模型/平台:
68
+
69
+ | 模型/平台 | 接入方式 | 特性 | 注意事项 |
70
+ |:----------|:----------|-------|:----------|
71
+ | [OpenAI (GPT-3/GPT3.5)](/packages/openai-adapter/README.md) | 本地 Client,官方 API 接入 | 可自定义人格,支持插件/浏览模式等聊天模式 | API 接入需要付费 |
72
+ | [New Bing](/packages/newbing-adapter/README.md) | 本地 Client,逆向 API 接入 | 自带网络搜索,强时效性,可无需登录使用 | 需要代理(无需 Cookie 也可用) |
73
+ | [Google Bard](/packages/bard-adapter/README.md) | 本地 Client,逆向 API 接入 | 和 New Bing 一样可以网络搜索,强时效性 | 需要有 Bard 访问权限账号,只能英文交流 |
74
+ | [Claude 2](/packages/claude2-adapter/) | 本地 Client,逆向 API 接入 | 超大上下文,大部分情况下能超过 GPT 3.5,类似 New Bing 有账号就行,免费 | 需要有 Claude 2 访问权限账号。后续可能会有限流 |
75
+ | [poe.com](/packages/poe-adapter/README.md) | 本地 Client,逆向 API 接入 | 网站可选多种模型,和 New Bing 一样免费 | 需要有 [poe.com](poe.com) 的账号 |
76
+ | [智谱](/packages/zhipu-adapter/README.md) | 本地 Client,官方 API 接入 | ChatGLM,新人注册可获取免费 Token 额度 | 实测效果比讯飞星火略好,但和 GPT 3.5 仍有差距 |
77
+ | [讯飞星火](/packages/spark-adapter/README.md) | 本地 Client,官方 API 接入 | 国产模型,新人注册可获取免费 Token 额度 | 实测效果约等于 GPT 3.5,有部分场景不如 GPT 3.5 |
78
+ | [GPT Free](/packages/gptfree-adapter/README.md) | 本地 Client,官方 API 接入 | 本地转发使用其他网站的 GPT 模型,项目自动配置网站等配置,无需手动注册 | 可能随时失效,不稳定 |
79
+ | [ChatGLM](/packages/chatglm-adapter/README.md) | 本地 Client,自搭建后端 API 接入 | 可本地搭建,四舍五入不要钱 | 需要自己搭建后端 API,要求一定的配置,6B参数聊天效果不够好 |
80
+ | [RWKV](/packages/rwkv-adapter/README.md) | 本地 Client,自搭建 API 接入 | 知名开源模型,可本地搭建 | 需要自己搭建后端 API,要求一定的配置 |
81
+
82
+ [为模型提供网络搜索能力](/packages/search-service/README.md) 我们支持:
83
+
84
+ - Baidu (Web)
85
+ - Bing (Web)
86
+ - DuckDuckGO (Lite & Web)
87
+ - Google (Api)
88
+ - Bing (Api)
89
+
90
+ ### 人格预设
91
+
92
+ 从`1.0.0-alpha.10`版本开始,我们支持更加可定制化的人格预设。新的人格预设使用 yaml。
93
+
94
+ 你可以点这里来查看我们默认附带的人格文件:[catgirl.yml](/packages/core/resources/presets/catgirl.yml)
95
+
96
+ 我们默认的预设文件夹路径为 `你当前运行插件的 koishi 目录的路径+/data/chathub/presets`。
97
+
98
+ 所有的预设文件都是从上面的文件夹上加载的。因此你可以自由添加和编辑预设文件在这个文件夹下,然后使用命令来切换人格预设。
99
+
100
+ **不是所有的适配器都支持预设,目前 Bard,Copliot Hub 不支持!**
101
+
102
+ ### 手动接入其他模型
103
+
104
+ 等待施工....
105
+
106
+ ### 贡献者名单
107
+
108
+ <a href="https://github.com/ChatLunaLab/chatluna/graphs/contributors">
109
+ <img src="https://contrib.rocks/image?repo=ChatHubLab/chathub" />
110
+ </a>
111
+
112
+ ![Alt](https://repobeats.axiom.co/api/embed/6996e228e38a44a28ed2629b667ef87a729f12ae.svg "Repobeats analytics image")
113
+
114
+ ### 感谢
115
+
116
+ 本项目在编写时参考了其他开源项目,特别感谢以下项目:
117
+
118
+ [koishi-plugin-openai](https://github.com/TomLBZ/koishi-plugin-openai)
119
+
120
+ [node-chatgpt-api](https://github.com/waylaidwanderer/node-chatgpt-api)
121
+
122
+ [poe-api](https://github.com/ading2210/poe-api)
123
+
124
+ [Bard](https://github.com/muhiris/wgpt)
125
+
126
+ [chathub](https://github.com/chathub-dev/chathub)
127
+
128
+ ## Star History
129
+
130
+ [![Star History Chart](https://api.star-history.com/svg?repos=ChatHubLab/chathub&type=Date)](https://star-history.com/#ChatHubLab/chathub)
@@ -0,0 +1,24 @@
1
+ import { Context, Service, Session } from 'koishi';
2
+ import { Config } from '../config';
3
+ import { ChatHubAuthGroup, ChatHubAuthUser } from './types';
4
+ export declare class ChatLunaAuthService extends Service {
5
+ readonly ctx: Context;
6
+ config: Config;
7
+ constructor(ctx: Context, config: Config);
8
+ getUser(session: Session, userId?: string): Promise<ChatHubAuthUser>;
9
+ private _createUser;
10
+ createAuthGroup(session: Session, group: ChatHubAuthGroup): Promise<void>;
11
+ resolveAuthGroup(session: Session, platform: string, userId?: string): Promise<ChatHubAuthGroup>;
12
+ getAuthGroups(platform?: string): Promise<Pick<ChatHubAuthGroup, import("koishi").Keys<ChatHubAuthGroup, any>>[]>;
13
+ getAuthGroup(name: string): Promise<Pick<ChatHubAuthGroup, import("koishi").Keys<ChatHubAuthGroup, any>>>;
14
+ calculateBalance(session: Session, platform: string, usedTokenNumber: number, userId?: string): Promise<number>;
15
+ getBalance(session: Session, userId?: string): Promise<number>;
16
+ modifyBalance(session: Session, amount: number, userId?: string): Promise<number>;
17
+ private _getAuthGroup;
18
+ resetAuthGroup(authGroupId: number): Promise<Pick<ChatHubAuthGroup, import("koishi").Keys<ChatHubAuthGroup, any>>>;
19
+ increaseAuthGroupCount(authGroupId: number): Promise<void>;
20
+ addUserToGroup(user: ChatHubAuthUser, groupName: string): Promise<void>;
21
+ removeUserFormGroup(user: ChatHubAuthUser, groupName: string): Promise<void>;
22
+ private _initAuthGroup;
23
+ private _defineDatabase;
24
+ }
@@ -0,0 +1,342 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ChatLunaAuthService = void 0;
4
+ const koishi_1 = require("koishi");
5
+ const error_1 = require("../utils/error");
6
+ const decimal_js_1 = require("decimal.js");
7
+ class ChatLunaAuthService extends koishi_1.Service {
8
+ ctx;
9
+ config;
10
+ constructor(ctx, config) {
11
+ super(ctx, 'chatluna_auth');
12
+ this.ctx = ctx;
13
+ this.config = config;
14
+ ctx.on('ready', async () => {
15
+ await this._defineDatabase();
16
+ });
17
+ }
18
+ async getUser(session, userId = session.userId) {
19
+ const list = await this.ctx.database.get('chathub_auth_user', {
20
+ userId
21
+ });
22
+ if (list.length === 0) {
23
+ return this._createUser(session, userId);
24
+ }
25
+ else if (list.length > 1) {
26
+ throw new error_1.ChatLunaError(error_1.ChatLunaErrorCode.USER_NOT_FOUND);
27
+ }
28
+ return list[0];
29
+ }
30
+ async _createUser(session, userId = session.userId) {
31
+ const user = await this.ctx.database.getUser(session.platform, userId);
32
+ if (user == null) {
33
+ throw new error_1.ChatLunaError(error_1.ChatLunaErrorCode.USER_NOT_FOUND, new Error(`
34
+ user not found in platform ${session.platform} and id ${userId}`));
35
+ }
36
+ const resolveAuthType = (authType) => authType > 2 ? 'admin' : authType > 1 ? 'user' : 'guest';
37
+ const copyOfSession = session.bot.session(session.event);
38
+ copyOfSession.userId = userId;
39
+ let [rawAuthType, balance, authGroup] = (await copyOfSession.resolve(this.config.authUserDefaultGroup)) ?? [0, 0, 'guest'];
40
+ const authType = resolveAuthType(user.authority > rawAuthType ? user.authority : rawAuthType);
41
+ if (authType === 'admin') {
42
+ authGroup = authType;
43
+ }
44
+ const authUser = {
45
+ userId,
46
+ balance: balance === 0
47
+ ? authType === 'admin'
48
+ ? 10000
49
+ : authType === 'user'
50
+ ? 10
51
+ : 1
52
+ : balance,
53
+ authType
54
+ };
55
+ await this.ctx.database.upsert('chathub_auth_user', [authUser]);
56
+ await this.addUserToGroup(authUser, authGroup);
57
+ return authUser;
58
+ }
59
+ async createAuthGroup(session, group) {
60
+ const user = await this.getUser(session);
61
+ await this.ctx.database.upsert('chathub_auth_group', [group]);
62
+ await this.addUserToGroup(user, group.name);
63
+ }
64
+ async resolveAuthGroup(session, platform, userId = session.userId) {
65
+ // search platform
66
+ const groups = (await this.ctx.database.get('chathub_auth_group', {
67
+ platform: {
68
+ $or: [undefined, platform]
69
+ }
70
+ })).sort((a, b) => {
71
+ // prefer the same platform
72
+ if (a.platform === platform) {
73
+ return -1;
74
+ }
75
+ if (b.platform === platform) {
76
+ return 1;
77
+ }
78
+ return b.priority - a.priority;
79
+ });
80
+ // Here there will be no such thing as a user joining too many groups, so a query will work.
81
+ const groupIds = groups.map((g) => g.id);
82
+ const joinedGroups = (await this.ctx.database.get('chathub_auth_joined_user', {
83
+ groupId: {
84
+ // max 50??
85
+ $in: groupIds
86
+ },
87
+ userId
88
+ })).sort((a, b) => groupIds.indexOf(a.groupId) - groupIds.indexOf(b.groupId));
89
+ if (joinedGroups.length === 0) {
90
+ throw new error_1.ChatLunaError(error_1.ChatLunaErrorCode.AUTH_GROUP_NOT_JOINED);
91
+ }
92
+ const result = groups.find((g) => g.id === joinedGroups[0].groupId);
93
+ if (result == null) {
94
+ throw new error_1.ChatLunaError(error_1.ChatLunaErrorCode.AUTH_GROUP_NOT_FOUND, new Error(`Group not found for user ${session.username} and platform
95
+ ${platform}`));
96
+ }
97
+ return result;
98
+ }
99
+ async getAuthGroups(platform) {
100
+ const groups = await this.ctx.database.get('chathub_auth_group', {
101
+ platform
102
+ });
103
+ return groups;
104
+ }
105
+ async getAuthGroup(name) {
106
+ const result = (await this.ctx.database.get('chathub_auth_group', { name }))?.[0];
107
+ if (result == null) {
108
+ throw new error_1.ChatLunaError(error_1.ChatLunaErrorCode.AUTH_GROUP_NOT_FOUND);
109
+ }
110
+ return result;
111
+ }
112
+ async calculateBalance(session, platform, usedTokenNumber, userId = session.userId) {
113
+ // TODO: use default balance checker
114
+ // await this.getUser(session)
115
+ const currentAuthGroup = await this.resolveAuthGroup(session, platform, userId);
116
+ // 1k token per
117
+ const usedBalance = new decimal_js_1.Decimal(0.001)
118
+ .mul(currentAuthGroup.costPerToken)
119
+ .mul(usedTokenNumber);
120
+ return await this.modifyBalance(session, -usedBalance.toNumber());
121
+ }
122
+ async getBalance(session, userId = session.userId) {
123
+ return (await this.getUser(session, userId)).balance;
124
+ }
125
+ async modifyBalance(session, amount, userId = session.userId) {
126
+ const user = await this.getUser(session, userId);
127
+ user.balance = new decimal_js_1.Decimal(user.balance).add(amount).toNumber();
128
+ await this.ctx.database.upsert('chathub_auth_user', [user]);
129
+ return user.balance;
130
+ }
131
+ async _getAuthGroup(authGroupId) {
132
+ const authGroup = (await this.ctx.database.get('chathub_auth_group', {
133
+ id: authGroupId
134
+ }))?.[0];
135
+ if (authGroup == null) {
136
+ throw new error_1.ChatLunaError(error_1.ChatLunaErrorCode.AUTH_GROUP_NOT_FOUND, new Error(`Auth group not found for id ${authGroupId}`));
137
+ }
138
+ return authGroup;
139
+ }
140
+ async resetAuthGroup(authGroupId) {
141
+ const authGroup = await this._getAuthGroup(authGroupId);
142
+ const currentTime = new Date();
143
+ authGroup.lastCallTime = authGroup.lastCallTime ?? currentTime.getTime();
144
+ const authGroupDate = new Date(authGroup.lastCallTime);
145
+ const currentDayOfStart = new Date().setHours(0, 0, 0, 0);
146
+ // If the last call time is not today, then all zeroed out
147
+ if (authGroupDate.getTime() < currentDayOfStart) {
148
+ authGroup.currentLimitPerDay = 0;
149
+ authGroup.currentLimitPerMin = 0;
150
+ authGroup.lastCallTime = currentTime.getTime();
151
+ await this.ctx.database.upsert('chathub_auth_group', [authGroup]);
152
+ return authGroup;
153
+ }
154
+ // Check to see if it's been more than a minute since the last call
155
+ if (currentTime.getTime() - authGroup.lastCallTime >= 60000) {
156
+ // clear
157
+ authGroup.currentLimitPerMin = 0;
158
+ authGroup.lastCallTime = currentTime.getTime();
159
+ await this.ctx.database.upsert('chathub_auth_group', [authGroup]);
160
+ return authGroup;
161
+ }
162
+ return authGroup;
163
+ }
164
+ async increaseAuthGroupCount(authGroupId) {
165
+ const authGroup = await this._getAuthGroup(authGroupId);
166
+ const currentTime = new Date();
167
+ authGroup.lastCallTime = authGroup.lastCallTime ?? currentTime.getTime();
168
+ const authGroupDate = new Date(authGroup.lastCallTime);
169
+ const currentDayOfStart = new Date().setHours(0, 0, 0, 0);
170
+ // If the last call time is not today, then all zeroed out
171
+ if (authGroupDate.getTime() < currentDayOfStart) {
172
+ authGroup.currentLimitPerDay = 1;
173
+ authGroup.currentLimitPerMin = 1;
174
+ authGroup.lastCallTime = currentTime.getTime();
175
+ await this.ctx.database.upsert('chathub_auth_group', [authGroup]);
176
+ return;
177
+ }
178
+ // Check to see if it's been more than a minute since the last call
179
+ if (currentTime.getTime() - authGroup.lastCallTime >= 60000) {
180
+ // clear
181
+ authGroup.currentLimitPerDay += 1;
182
+ authGroup.currentLimitPerMin = 1;
183
+ authGroup.lastCallTime = currentTime.getTime();
184
+ await this.ctx.database.upsert('chathub_auth_group', [authGroup]);
185
+ }
186
+ authGroup.currentLimitPerDay += 1;
187
+ authGroup.currentLimitPerMin += 1;
188
+ await this.ctx.database.upsert('chathub_auth_group', [authGroup]);
189
+ }
190
+ async addUserToGroup(user, groupName) {
191
+ const group = await this.getAuthGroup(groupName);
192
+ const isJoined = (await this.ctx.database.get('chathub_auth_joined_user', {
193
+ groupName,
194
+ userId: user.userId
195
+ })).length === 1;
196
+ if (isJoined) {
197
+ throw new error_1.ChatLunaError(error_1.ChatLunaErrorCode.AUTH_GROUP_ALREADY_JOINED);
198
+ }
199
+ await this.ctx.database.upsert('chathub_auth_joined_user', [
200
+ {
201
+ userId: user.userId,
202
+ groupId: group.id,
203
+ groupName: group.name
204
+ }
205
+ ]);
206
+ }
207
+ async removeUserFormGroup(user, groupName) {
208
+ const group = await this.getAuthGroup(groupName);
209
+ await this.ctx.database.remove('chathub_auth_joined_user', {
210
+ userId: user.userId,
211
+ groupName: group.name
212
+ });
213
+ }
214
+ async _initAuthGroup() {
215
+ // init guest group
216
+ const groups = await this.ctx.database.get('chathub_auth_group', {
217
+ name: {
218
+ $in: ['guest', 'user', 'admin']
219
+ }
220
+ });
221
+ let currentGroup;
222
+ if (!groups.some((g) => g.name === 'guest')) {
223
+ currentGroup = {
224
+ name: 'guest',
225
+ priority: 0,
226
+ limitPerMin: 10,
227
+ limitPerDay: 2000,
228
+ // 1000 token / 0.3
229
+ costPerToken: 0.3
230
+ };
231
+ await this.ctx.database.upsert('chathub_auth_group', [currentGroup]);
232
+ }
233
+ if (!groups.some((g) => g.name === 'user')) {
234
+ currentGroup = {
235
+ name: 'user',
236
+ priority: 1,
237
+ limitPerMin: 1000,
238
+ limitPerDay: 200000,
239
+ // 1000 token / 0.01
240
+ costPerToken: 0.01
241
+ };
242
+ await this.ctx.database.upsert('chathub_auth_group', [currentGroup]);
243
+ }
244
+ if (!groups.some((g) => g.name === 'admin')) {
245
+ currentGroup = {
246
+ name: 'admin',
247
+ priority: 2,
248
+ limitPerMin: 10000,
249
+ limitPerDay: 20000000,
250
+ // 1000 token / 0.001
251
+ costPerToken: 0.001
252
+ };
253
+ await this.ctx.database.upsert('chathub_auth_group', [currentGroup]);
254
+ }
255
+ }
256
+ async _defineDatabase() {
257
+ const ctx = this.ctx;
258
+ ctx.database.extend('chathub_auth_user', {
259
+ userId: {
260
+ type: 'string'
261
+ },
262
+ balance: {
263
+ type: 'decimal',
264
+ precision: 20,
265
+ scale: 10
266
+ },
267
+ authType: {
268
+ type: 'char',
269
+ length: 50
270
+ }
271
+ }, {
272
+ autoInc: false,
273
+ primary: 'userId',
274
+ unique: ['userId']
275
+ });
276
+ ctx.database.extend('chathub_auth_joined_user', {
277
+ userId: 'string',
278
+ groupId: 'integer',
279
+ groupName: 'string',
280
+ id: 'integer'
281
+ }, {
282
+ autoInc: true,
283
+ primary: 'id',
284
+ unique: ['id']
285
+ });
286
+ ctx.database.extend('chathub_auth_group', {
287
+ limitPerDay: {
288
+ type: 'integer',
289
+ nullable: false
290
+ },
291
+ limitPerMin: {
292
+ type: 'integer',
293
+ nullable: false
294
+ },
295
+ lastCallTime: {
296
+ type: 'integer',
297
+ length: 16,
298
+ nullable: true
299
+ },
300
+ currentLimitPerDay: {
301
+ type: 'integer',
302
+ nullable: true
303
+ },
304
+ currentLimitPerMin: {
305
+ type: 'integer',
306
+ nullable: true
307
+ },
308
+ supportModels: {
309
+ type: 'json',
310
+ nullable: true
311
+ },
312
+ priority: {
313
+ type: 'integer',
314
+ nullable: false,
315
+ initial: 0
316
+ },
317
+ platform: {
318
+ type: 'char',
319
+ length: 255,
320
+ nullable: true
321
+ },
322
+ costPerToken: {
323
+ type: 'decimal',
324
+ precision: 8,
325
+ scale: 4
326
+ },
327
+ name: {
328
+ type: 'char',
329
+ length: 255
330
+ },
331
+ id: {
332
+ type: 'integer'
333
+ }
334
+ }, {
335
+ autoInc: true,
336
+ primary: 'id',
337
+ unique: ['id', 'name']
338
+ });
339
+ await this._initAuthGroup();
340
+ }
341
+ }
342
+ exports.ChatLunaAuthService = ChatLunaAuthService;
@@ -0,0 +1,36 @@
1
+ import { ChatLunaAuthService } from './service';
2
+ export interface ChatHubAuthUser {
3
+ userId: string;
4
+ balance: number;
5
+ authType: AuthType;
6
+ }
7
+ export interface ChatHubAuthJoinedUser {
8
+ userId: string;
9
+ groupId: number;
10
+ groupName: string;
11
+ id: number;
12
+ }
13
+ export type AuthType = 'guest' | 'user' | 'admin';
14
+ export interface ChatHubAuthGroup {
15
+ name: string;
16
+ platform?: string;
17
+ priority: number;
18
+ id: number;
19
+ limitPerMin: number;
20
+ limitPerDay: number;
21
+ costPerToken: number;
22
+ currentLimitPerMin?: number;
23
+ currentLimitPerDay?: number;
24
+ lastCallTime?: number;
25
+ supportModels: string[];
26
+ }
27
+ declare module 'koishi' {
28
+ interface Context {
29
+ chatluna_auth: ChatLunaAuthService;
30
+ }
31
+ interface Tables {
32
+ chathub_auth_group: ChatHubAuthGroup;
33
+ chathub_auth_user: ChatHubAuthUser;
34
+ chathub_auth_joined_user: ChatHubAuthJoinedUser;
35
+ }
36
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/lib/cache.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ import { Tables } from '@koishijs/cache';
2
+ import { Context } from 'koishi';
3
+ import { Config } from './config';
4
+ export declare class Cache<K extends keyof Tables, T extends Tables[K]> {
5
+ private ctx;
6
+ readonly config: Config;
7
+ readonly tableName: K;
8
+ constructor(ctx: Context, config: Config, tableName: K);
9
+ get(id: string): Promise<T>;
10
+ set(id: string, value: T): Promise<void>;
11
+ delete(id: string): Promise<void>;
12
+ clear(): Promise<void>;
13
+ }
14
+ declare module '@koishijs/cache' {
15
+ interface Tables {
16
+ 'chathub/keys': string;
17
+ }
18
+ }
package/lib/cache.js ADDED
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Cache = void 0;
4
+ class Cache {
5
+ ctx;
6
+ config;
7
+ tableName;
8
+ constructor(ctx, config, tableName) {
9
+ this.ctx = ctx;
10
+ this.config = config;
11
+ this.tableName = tableName;
12
+ }
13
+ get(id) {
14
+ return this.ctx.cache.get(this.tableName, id);
15
+ }
16
+ set(id, value) {
17
+ // 单位分钟
18
+ return this.ctx.cache.set(this.tableName, id, value);
19
+ }
20
+ async delete(id) {
21
+ await this.ctx.cache.delete(this.tableName, id);
22
+ }
23
+ async clear() {
24
+ await this.ctx.cache.clear(this.tableName);
25
+ }
26
+ }
27
+ exports.Cache = Cache;
@@ -0,0 +1,66 @@
1
+ import { Context, h, Session } from 'koishi';
2
+ import { Config } from '../config';
3
+ import '../middlewares/lifecycle';
4
+ /**
5
+ * ChatChain为消息的发送和接收提供了一个统一的中间提供交互
6
+ */
7
+ export declare class ChatChain {
8
+ private readonly ctx;
9
+ private readonly config;
10
+ readonly _graph: ChatChainDependencyGraph;
11
+ private readonly _senders;
12
+ constructor(ctx: Context, config: Config);
13
+ receiveMessage(session: Session, ctx?: Context): Promise<boolean>;
14
+ receiveCommand(session: Session, command: string, options?: ChainMiddlewareContextOptions): Promise<boolean>;
15
+ middleware<T extends keyof ChainMiddlewareName>(name: T, middleware: ChainMiddlewareFunction, ctx?: Context): ChainMiddleware;
16
+ sender(sender: ChatChainSender): void;
17
+ private _runMiddleware;
18
+ private sendMessage;
19
+ }
20
+ declare class ChatChainDependencyGraph {
21
+ private _tasks;
22
+ private _dependencies;
23
+ private _eventEmitter;
24
+ private _listeners;
25
+ constructor();
26
+ addNode(middleware: ChainMiddleware): void;
27
+ removeNode(name: string): void;
28
+ once(name: string, listener: (...args: any[]) => void): void;
29
+ before(taskA: ChainMiddleware | string, taskB: ChainMiddleware | string): void;
30
+ after(taskA: ChainMiddleware | string, taskB: ChainMiddleware | string): void;
31
+ getDependencies(task: string): Set<string>;
32
+ getDependents(task: string): string[];
33
+ build(): ChainMiddleware[];
34
+ }
35
+ export declare class ChainMiddleware {
36
+ readonly name: string;
37
+ private readonly execute;
38
+ private readonly graph;
39
+ constructor(name: string, execute: ChainMiddlewareFunction, graph: ChatChainDependencyGraph);
40
+ before<T extends keyof ChainMiddlewareName>(name: T): this;
41
+ after<T extends keyof ChainMiddlewareName>(name: T): this;
42
+ run(session: Session, options: ChainMiddlewareContext): Promise<string | h[] | h[][] | ChainMiddlewareRunStatus>;
43
+ }
44
+ export interface ChainMiddlewareContext {
45
+ config: Config;
46
+ ctx: Context;
47
+ session: Session;
48
+ message: string | h[] | h[][];
49
+ options?: ChainMiddlewareContextOptions;
50
+ command?: string;
51
+ recallThinkingMessage?: () => Promise<void>;
52
+ send: (message: h[][] | h[] | h | string) => Promise<void>;
53
+ }
54
+ export interface ChainMiddlewareContextOptions {
55
+ [key: string]: any;
56
+ }
57
+ export interface ChainMiddlewareName {
58
+ }
59
+ export type ChainMiddlewareFunction = (session: Session, context: ChainMiddlewareContext) => Promise<string | h[] | h[][] | ChainMiddlewareRunStatus | null>;
60
+ export type ChatChainSender = (session: Session, message: (h[] | h | string)[]) => Promise<void>;
61
+ export declare enum ChainMiddlewareRunStatus {
62
+ SKIPPED = 0,
63
+ STOP = 1,
64
+ CONTINUE = 2
65
+ }
66
+ export {};