mirror of
https://github.com/ikechan8370/chatgpt-plugin.git
synced 2025-12-14 12:27:10 +00:00
fix: 对接
This commit is contained in:
parent
89ab58b3d7
commit
eee1285e2f
11 changed files with 221 additions and 26 deletions
|
|
@ -21,8 +21,8 @@ export class Chat extends plugin {
|
|||
|
||||
async chat (e) {
|
||||
const state = await Chaite.getInstance().getUserStateStorage().getItem(e.sender.user_id + '')
|
||||
const sendMessageOptions = SendMessageOption.create(state.settings)
|
||||
const preset = await getPreset(e, state.settings.preset, Config.basic.toggleMode, Config.basic.togglePrefix)
|
||||
const sendMessageOptions = SendMessageOption.create(state?.settings)
|
||||
const preset = await getPreset(e, state?.settings.preset || Config.llm.defaultChatPresetId, Config.basic.toggleMode, Config.basic.togglePrefix)
|
||||
if (!preset) {
|
||||
logger.debug('未找到预设,不进入对话')
|
||||
return false
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import ChatGPTConfig from '../config/config.js'
|
||||
import { createCRUDCommandRules, createSwitchCommandRules } from '../utils/command.js'
|
||||
import { Chaite } from '../../../../../../WebstormProjects/node-chaite/src/index.js'
|
||||
import { Chaite } from 'chaite'
|
||||
import { resolve } from 'eslint-plugin-promise/rules/lib/promise-statics.js'
|
||||
|
||||
export class ChatGPTManagement extends plugin {
|
||||
constructor () {
|
||||
|
|
@ -22,7 +23,19 @@ export class ChatGPTManagement extends plugin {
|
|||
}
|
||||
]
|
||||
})
|
||||
this.rules.push(...[
|
||||
this.initCommand(cmdPrefix)
|
||||
}
|
||||
|
||||
async initCommand (cmdPrefix) {
|
||||
const waitForChaite = async () => {
|
||||
while (!Chaite.getInstance()) {
|
||||
await new Promise(resolve => setTimeout(resolve, 1000))
|
||||
}
|
||||
return Chaite.getInstance()
|
||||
}
|
||||
|
||||
await waitForChaite()
|
||||
this.rule.push(...[
|
||||
...createCRUDCommandRules.bind(this)(cmdPrefix, '渠道', 'channels'),
|
||||
...createCRUDCommandRules.bind(this)(cmdPrefix, '预设', 'presets'),
|
||||
...createCRUDCommandRules.bind(this)(cmdPrefix, '工具', 'tools'),
|
||||
|
|
|
|||
152
config/config.js
152
config/config.js
|
|
@ -1,3 +1,7 @@
|
|||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import yaml from 'js-yaml'
|
||||
|
||||
class ChatGPTConfig {
|
||||
/**
|
||||
* 版本号
|
||||
|
|
@ -105,13 +109,159 @@ class ChatGPTConfig {
|
|||
cloudBaseUrl: '',
|
||||
// 云端API Key
|
||||
cloudApiKey: '',
|
||||
// jwt key,非必要勿修改
|
||||
// jwt key,非必要勿修改,修改需重启
|
||||
authKey: '',
|
||||
// 管理面板监听地址
|
||||
host: '',
|
||||
// 管理面板监听端口
|
||||
port: 48370
|
||||
}
|
||||
|
||||
constructor () {
|
||||
this.version = '3.0.0'
|
||||
this.basic = {
|
||||
toggleMode: 'at',
|
||||
togglePrefix: '#chat',
|
||||
debug: false,
|
||||
commandPrefix: '^#chatgpt'
|
||||
}
|
||||
this.llm = {
|
||||
defaultModel: '',
|
||||
embeddingModel: 'gemini-embedding-exp-03-07',
|
||||
dimensions: 0,
|
||||
defaultChatPresetId: '',
|
||||
enableCustomPreset: false,
|
||||
customPresetUserWhiteList: [],
|
||||
customPresetUserBlackList: [],
|
||||
promptBlockWords: [],
|
||||
responseBlockWords: [],
|
||||
blockStrategy: 'full',
|
||||
blockWordMask: '***'
|
||||
}
|
||||
this.management = {
|
||||
blackGroups: [],
|
||||
whiteGroups: [],
|
||||
blackUsers: [],
|
||||
whiteUsers: [],
|
||||
defaultRateLimit: 0
|
||||
}
|
||||
this.chaite = {
|
||||
dataDir: 'data',
|
||||
processorsDirPath: 'utils/processors',
|
||||
toolsDirPath: 'utils/tools',
|
||||
cloudBaseUrl: '',
|
||||
cloudApiKey: '',
|
||||
authKey: '',
|
||||
host: '',
|
||||
port: 48370
|
||||
}
|
||||
|
||||
this.watcher = null
|
||||
this.configPath = ''
|
||||
}
|
||||
|
||||
/**
|
||||
* Start config file sync
|
||||
* call once!
|
||||
* @param {string} configDir Directory containing config files
|
||||
*/
|
||||
startSync (configDir) {
|
||||
const jsonPath = path.join(configDir, 'config.json')
|
||||
const yamlPath = path.join(configDir, 'config.yaml')
|
||||
|
||||
// Determine which config file to use
|
||||
if (fs.existsSync(jsonPath)) {
|
||||
this.configPath = jsonPath
|
||||
} else if (fs.existsSync(yamlPath)) {
|
||||
this.configPath = yamlPath
|
||||
} else {
|
||||
this.configPath = jsonPath
|
||||
this.saveToFile()
|
||||
}
|
||||
|
||||
// Load initial config
|
||||
this.loadFromFile()
|
||||
|
||||
// Watch for file changes
|
||||
this.watcher = fs.watchFile(this.configPath, (curr, prev) => {
|
||||
if (curr.mtime !== prev.mtime) {
|
||||
this.loadFromFile()
|
||||
}
|
||||
})
|
||||
|
||||
const createDeepProxy = (obj, handler) => {
|
||||
if (obj === null || typeof obj !== 'object') return obj
|
||||
|
||||
for (let key of Object.keys(obj)) {
|
||||
if (typeof obj[key] === 'object' && obj[key] !== null) {
|
||||
obj[key] = createDeepProxy(obj[key], handler)
|
||||
}
|
||||
}
|
||||
|
||||
return new Proxy(obj, handler)
|
||||
}
|
||||
|
||||
// 创建处理器
|
||||
const handler = {
|
||||
set: (target, prop, value) => {
|
||||
if (prop !== 'watcher' && prop !== 'configPath') {
|
||||
target[prop] = typeof value === 'object' && value !== null
|
||||
? createDeepProxy(value, handler)
|
||||
: value
|
||||
this.saveToFile()
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// 为所有嵌套对象创建Proxy
|
||||
this.basic = createDeepProxy(this.basic, handler)
|
||||
this.llm = createDeepProxy(this.llm, handler)
|
||||
this.management = createDeepProxy(this.management, handler)
|
||||
this.chaite = createDeepProxy(this.chaite, handler)
|
||||
|
||||
// 返回最外层的Proxy
|
||||
return new Proxy(this, handler)
|
||||
}
|
||||
|
||||
/**
|
||||
* Load config from file
|
||||
*/
|
||||
loadFromFile () {
|
||||
try {
|
||||
const content = fs.readFileSync(this.configPath, 'utf8')
|
||||
const config = this.configPath.endsWith('.json')
|
||||
? JSON.parse(content)
|
||||
: yaml.load(content)
|
||||
|
||||
Object.assign(this, config)
|
||||
} catch (error) {
|
||||
console.error('Failed to load config:', error)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save config to file
|
||||
*/
|
||||
saveToFile () {
|
||||
try {
|
||||
const config = {
|
||||
version: this.version,
|
||||
basic: this.basic,
|
||||
llm: this.llm,
|
||||
management: this.management,
|
||||
chaite: this.chaite
|
||||
}
|
||||
|
||||
const content = this.configPath.endsWith('.json')
|
||||
? JSON.stringify(config, null, 2)
|
||||
: yaml.dump(config)
|
||||
|
||||
fs.writeFileSync(this.configPath, content, 'utf8')
|
||||
} catch (error) {
|
||||
console.error('Failed to save config:', error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new ChatGPTConfig()
|
||||
|
|
|
|||
2
index.js
2
index.js
|
|
@ -35,6 +35,8 @@ for (let i in files) {
|
|||
global.chatgpt = {
|
||||
|
||||
}
|
||||
|
||||
ChatGPTConfig.startSync('./plugins/chatgpt-plugin/data')
|
||||
initChaite()
|
||||
logger.info('chatgpt-plugin加载成功')
|
||||
logger.info(`当前版本${ChatGPTConfig.version}`)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { ChaiteStorage } from 'chaite'
|
||||
import { ChaiteStorage, Channel } from 'chaite'
|
||||
|
||||
export class LowDBChannelStorage extends ChaiteStorage {
|
||||
/**
|
||||
|
|
@ -21,7 +21,8 @@ export class LowDBChannelStorage extends ChaiteStorage {
|
|||
* @returns {Promise<import('chaite').Channel>}
|
||||
*/
|
||||
async getItem (key) {
|
||||
return this.collection.findOne({ id: key })
|
||||
const obj = await this.collection.findOne({ id: key })
|
||||
return new Channel({}).fromString(JSON.stringify(obj))
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -53,7 +54,8 @@ export class LowDBChannelStorage extends ChaiteStorage {
|
|||
* @returns {Promise<import('chaite').Channel[]>}
|
||||
*/
|
||||
async listItems () {
|
||||
return this.collection.findAll()
|
||||
const list = await this.collection.findAll()
|
||||
return list.map(item => new Channel({}).fromString(JSON.stringify(item)))
|
||||
}
|
||||
|
||||
async clear () {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { ChaiteStorage } from 'chaite'
|
||||
import { ChaiteStorage, ChatPreset } from 'chaite'
|
||||
|
||||
/**
|
||||
* @extends {ChaiteStorage<import('chaite').ChatPreset>}
|
||||
|
|
@ -24,7 +24,11 @@ export class LowDBChatPresetsStorage extends ChaiteStorage {
|
|||
* @returns {Promise<import('chaite').ChatPreset>}
|
||||
*/
|
||||
async getItem (key) {
|
||||
return this.collection.findOne({ id: key })
|
||||
const obj = await this.collection.findOne({ id: key })
|
||||
if (!obj) {
|
||||
return null
|
||||
}
|
||||
return new ChatPreset({}).fromString(JSON.stringify(obj))
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -56,7 +60,8 @@ export class LowDBChatPresetsStorage extends ChaiteStorage {
|
|||
* @returns {Promise<import('chaite').ChatPreset[]>}
|
||||
*/
|
||||
async listItems () {
|
||||
return this.collection.findAll()
|
||||
const list = await this.collection.findAll()
|
||||
return list.map(item => new ChatPreset({}).fromString(JSON.stringify(item)))
|
||||
}
|
||||
|
||||
async clear () {
|
||||
|
|
|
|||
|
|
@ -126,7 +126,11 @@ export async function initChaite () {
|
|||
chaite.setCloudService(ChatGPTConfig.chaite.cloudBaseUrl)
|
||||
logger.info('Chaite.Cloud 初始化完成')
|
||||
ChatGPTConfig.chaite.cloudApiKey && await chaite.auth(ChatGPTConfig.chaite.cloudApiKey)
|
||||
await initRagManager(ChatGPTConfig.llm.embeddingModel, ChatGPTConfig.dimensions)
|
||||
await initRagManager(ChatGPTConfig.llm.embeddingModel, ChatGPTConfig.llm.dimensions)
|
||||
if (!ChatGPTConfig.chaite.authKey) {
|
||||
ChatGPTConfig.chaite.authKey = Chaite.getInstance().getFrontendAuthHandler().generateToken(0, true)
|
||||
}
|
||||
chaite.getGlobalConfig().setAuthKey(ChatGPTConfig.chaite.authKey)
|
||||
// 监听Chaite配置变化,同步需要同步的配置
|
||||
chaite.on('config-change', obj => {
|
||||
const { key, newVal, oldVal } = obj
|
||||
|
|
@ -139,19 +143,33 @@ export async function initChaite () {
|
|||
chaite.setUpdateConfigCallback(config => {
|
||||
logger.debug('chatgpt-plugin config updated')
|
||||
Object.keys(config).forEach(key => {
|
||||
ChatGPTConfig[key] = config[key]
|
||||
// 回传部分需要同步的配置,以防不一致
|
||||
if (key === 'serverAuthKey') {
|
||||
chaite.getGlobalConfig().setAuthKey(config[key])
|
||||
if (typeof config[key] === 'object' && config[key] !== null && ChatGPTConfig[key]) {
|
||||
deepMerge(ChatGPTConfig[key], config[key])
|
||||
} else {
|
||||
ChatGPTConfig[key] = config[key]
|
||||
}
|
||||
})
|
||||
// 回传部分需要同步的配置,以防不一致
|
||||
chaite.getGlobalConfig().setAuthKey(ChatGPTConfig.chaite.authKey)
|
||||
})
|
||||
// 授予Chaite获取插件配置的能力以便通过api放出
|
||||
chaite.setGetConfig(async () => {
|
||||
return ChatGPTConfig
|
||||
})
|
||||
logger.info('Chaite.RAGManager 初始化完成')
|
||||
const token = chaite.getFrontendAuthHandler().generateToken()
|
||||
logger.info(token)
|
||||
chaite.runApiServer()
|
||||
}
|
||||
|
||||
function deepMerge (target, source) {
|
||||
for (const key in source) {
|
||||
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
||||
if (typeof source[key] === 'object' && source[key] !== null && target[key]) {
|
||||
// 如果是对象且目标属性存在,递归合并
|
||||
deepMerge(target[key], source[key])
|
||||
} else {
|
||||
// 否则直接赋值
|
||||
target[key] = source[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { ChaiteStorage } from 'chaite'
|
||||
import { ChaiteStorage, ProcessorDTO } from 'chaite'
|
||||
|
||||
/**
|
||||
* @extends {ChaiteStorage<import('chaite').Processor>}
|
||||
|
|
@ -24,7 +24,8 @@ export class LowDBProcessorsStorage extends ChaiteStorage {
|
|||
* @returns {Promise<import('chaite').Processor>}
|
||||
*/
|
||||
async getItem (key) {
|
||||
return this.collection.findOne({ id: key })
|
||||
const obj = await this.collection.findOne({ id: key })
|
||||
return new ProcessorDTO({}).fromString(JSON.stringify(obj))
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -56,7 +57,8 @@ export class LowDBProcessorsStorage extends ChaiteStorage {
|
|||
* @returns {Promise<import('chaite').Processor[]>}
|
||||
*/
|
||||
async listItems () {
|
||||
return this.collection.findAll()
|
||||
const list = await this.collection.findAll()
|
||||
return list.map(item => new ProcessorDTO({}).fromString(JSON.stringify(item)))
|
||||
}
|
||||
|
||||
async clear () {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { ChaiteStorage } from 'chaite'
|
||||
import { ChaiteStorage, ToolDTO } from 'chaite'
|
||||
|
||||
/**
|
||||
* @extends {ChaiteStorage<import('chaite').ToolDTO>}
|
||||
|
|
@ -24,7 +24,8 @@ export class LowDBToolsStorage extends ChaiteStorage {
|
|||
* @returns {Promise<import('chaite').ToolDTO>}
|
||||
*/
|
||||
async getItem (key) {
|
||||
return this.collection.findOne({ id: key })
|
||||
const obj = await this.collection.findOne({ id: key })
|
||||
return new ToolDTO({}).fromString(JSON.stringify(obj))
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -56,7 +57,8 @@ export class LowDBToolsStorage extends ChaiteStorage {
|
|||
* @returns {Promise<import('chaite').ToolDTO[]>}
|
||||
*/
|
||||
async listItems () {
|
||||
return this.collection.findAll()
|
||||
const list = await this.collection.findAll()
|
||||
return list.map(item => new ToolDTO({}).fromString(JSON.stringify(item)))
|
||||
}
|
||||
|
||||
async clear () {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
"author": "ikechan8370",
|
||||
"dependencies": {
|
||||
"chaite": "/Users/geyinchi/WebstormProjects/node-chaite",
|
||||
"js-yaml": "^4.1.0",
|
||||
"keyv": "^5.3.1",
|
||||
"keyv-file": "^5.1.2",
|
||||
"lowdb": "^7.0.1",
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ export async function intoUserMessage (e, options = {}) {
|
|||
if (text) {
|
||||
contents.push({
|
||||
type: 'text',
|
||||
content: text
|
||||
text
|
||||
})
|
||||
}
|
||||
return {
|
||||
|
|
@ -134,7 +134,7 @@ export async function getPreset (e, presetId, toggleMode, togglePrefix) {
|
|||
* @returns {boolean}
|
||||
*/
|
||||
export function checkChatMsg (e, toggleMode, togglePrefix) {
|
||||
if (toggleMode === 'at' && e.atBot) {
|
||||
if (toggleMode === 'at' && (e.atBot || e.isPrivate)) {
|
||||
return true
|
||||
}
|
||||
const prefixReg = new RegExp(`^#?(图片)?${togglePrefix}[^gpt][sS]*`)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue