mirror of
https://github.com/ikechan8370/chatgpt-plugin.git
synced 2025-12-16 21:37:11 +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) {
|
async chat (e) {
|
||||||
const state = await Chaite.getInstance().getUserStateStorage().getItem(e.sender.user_id + '')
|
const state = await Chaite.getInstance().getUserStateStorage().getItem(e.sender.user_id + '')
|
||||||
const sendMessageOptions = SendMessageOption.create(state.settings)
|
const sendMessageOptions = SendMessageOption.create(state?.settings)
|
||||||
const preset = await getPreset(e, state.settings.preset, Config.basic.toggleMode, Config.basic.togglePrefix)
|
const preset = await getPreset(e, state?.settings.preset || Config.llm.defaultChatPresetId, Config.basic.toggleMode, Config.basic.togglePrefix)
|
||||||
if (!preset) {
|
if (!preset) {
|
||||||
logger.debug('未找到预设,不进入对话')
|
logger.debug('未找到预设,不进入对话')
|
||||||
return false
|
return false
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import ChatGPTConfig from '../config/config.js'
|
import ChatGPTConfig from '../config/config.js'
|
||||||
import { createCRUDCommandRules, createSwitchCommandRules } from '../utils/command.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 {
|
export class ChatGPTManagement extends plugin {
|
||||||
constructor () {
|
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, '渠道', 'channels'),
|
||||||
...createCRUDCommandRules.bind(this)(cmdPrefix, '预设', 'presets'),
|
...createCRUDCommandRules.bind(this)(cmdPrefix, '预设', 'presets'),
|
||||||
...createCRUDCommandRules.bind(this)(cmdPrefix, '工具', 'tools'),
|
...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 {
|
class ChatGPTConfig {
|
||||||
/**
|
/**
|
||||||
* 版本号
|
* 版本号
|
||||||
|
|
@ -105,13 +109,159 @@ class ChatGPTConfig {
|
||||||
cloudBaseUrl: '',
|
cloudBaseUrl: '',
|
||||||
// 云端API Key
|
// 云端API Key
|
||||||
cloudApiKey: '',
|
cloudApiKey: '',
|
||||||
// jwt key,非必要勿修改
|
// jwt key,非必要勿修改,修改需重启
|
||||||
authKey: '',
|
authKey: '',
|
||||||
// 管理面板监听地址
|
// 管理面板监听地址
|
||||||
host: '',
|
host: '',
|
||||||
// 管理面板监听端口
|
// 管理面板监听端口
|
||||||
port: 48370
|
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()
|
export default new ChatGPTConfig()
|
||||||
|
|
|
||||||
2
index.js
2
index.js
|
|
@ -35,6 +35,8 @@ for (let i in files) {
|
||||||
global.chatgpt = {
|
global.chatgpt = {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ChatGPTConfig.startSync('./plugins/chatgpt-plugin/data')
|
||||||
initChaite()
|
initChaite()
|
||||||
logger.info('chatgpt-plugin加载成功')
|
logger.info('chatgpt-plugin加载成功')
|
||||||
logger.info(`当前版本${ChatGPTConfig.version}`)
|
logger.info(`当前版本${ChatGPTConfig.version}`)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { ChaiteStorage } from 'chaite'
|
import { ChaiteStorage, Channel } from 'chaite'
|
||||||
|
|
||||||
export class LowDBChannelStorage extends ChaiteStorage {
|
export class LowDBChannelStorage extends ChaiteStorage {
|
||||||
/**
|
/**
|
||||||
|
|
@ -21,7 +21,8 @@ export class LowDBChannelStorage extends ChaiteStorage {
|
||||||
* @returns {Promise<import('chaite').Channel>}
|
* @returns {Promise<import('chaite').Channel>}
|
||||||
*/
|
*/
|
||||||
async getItem (key) {
|
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[]>}
|
* @returns {Promise<import('chaite').Channel[]>}
|
||||||
*/
|
*/
|
||||||
async listItems () {
|
async listItems () {
|
||||||
return this.collection.findAll()
|
const list = await this.collection.findAll()
|
||||||
|
return list.map(item => new Channel({}).fromString(JSON.stringify(item)))
|
||||||
}
|
}
|
||||||
|
|
||||||
async clear () {
|
async clear () {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { ChaiteStorage } from 'chaite'
|
import { ChaiteStorage, ChatPreset } from 'chaite'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @extends {ChaiteStorage<import('chaite').ChatPreset>}
|
* @extends {ChaiteStorage<import('chaite').ChatPreset>}
|
||||||
|
|
@ -24,7 +24,11 @@ export class LowDBChatPresetsStorage extends ChaiteStorage {
|
||||||
* @returns {Promise<import('chaite').ChatPreset>}
|
* @returns {Promise<import('chaite').ChatPreset>}
|
||||||
*/
|
*/
|
||||||
async getItem (key) {
|
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[]>}
|
* @returns {Promise<import('chaite').ChatPreset[]>}
|
||||||
*/
|
*/
|
||||||
async listItems () {
|
async listItems () {
|
||||||
return this.collection.findAll()
|
const list = await this.collection.findAll()
|
||||||
|
return list.map(item => new ChatPreset({}).fromString(JSON.stringify(item)))
|
||||||
}
|
}
|
||||||
|
|
||||||
async clear () {
|
async clear () {
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,11 @@ export async function initChaite () {
|
||||||
chaite.setCloudService(ChatGPTConfig.chaite.cloudBaseUrl)
|
chaite.setCloudService(ChatGPTConfig.chaite.cloudBaseUrl)
|
||||||
logger.info('Chaite.Cloud 初始化完成')
|
logger.info('Chaite.Cloud 初始化完成')
|
||||||
ChatGPTConfig.chaite.cloudApiKey && await chaite.auth(ChatGPTConfig.chaite.cloudApiKey)
|
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配置变化,同步需要同步的配置
|
||||||
chaite.on('config-change', obj => {
|
chaite.on('config-change', obj => {
|
||||||
const { key, newVal, oldVal } = obj
|
const { key, newVal, oldVal } = obj
|
||||||
|
|
@ -139,19 +143,33 @@ export async function initChaite () {
|
||||||
chaite.setUpdateConfigCallback(config => {
|
chaite.setUpdateConfigCallback(config => {
|
||||||
logger.debug('chatgpt-plugin config updated')
|
logger.debug('chatgpt-plugin config updated')
|
||||||
Object.keys(config).forEach(key => {
|
Object.keys(config).forEach(key => {
|
||||||
ChatGPTConfig[key] = config[key]
|
if (typeof config[key] === 'object' && config[key] !== null && ChatGPTConfig[key]) {
|
||||||
// 回传部分需要同步的配置,以防不一致
|
deepMerge(ChatGPTConfig[key], config[key])
|
||||||
if (key === 'serverAuthKey') {
|
} else {
|
||||||
chaite.getGlobalConfig().setAuthKey(config[key])
|
ChatGPTConfig[key] = config[key]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
// 回传部分需要同步的配置,以防不一致
|
||||||
|
chaite.getGlobalConfig().setAuthKey(ChatGPTConfig.chaite.authKey)
|
||||||
})
|
})
|
||||||
// 授予Chaite获取插件配置的能力以便通过api放出
|
// 授予Chaite获取插件配置的能力以便通过api放出
|
||||||
chaite.setGetConfig(async () => {
|
chaite.setGetConfig(async () => {
|
||||||
return ChatGPTConfig
|
return ChatGPTConfig
|
||||||
})
|
})
|
||||||
logger.info('Chaite.RAGManager 初始化完成')
|
logger.info('Chaite.RAGManager 初始化完成')
|
||||||
const token = chaite.getFrontendAuthHandler().generateToken()
|
|
||||||
logger.info(token)
|
|
||||||
chaite.runApiServer()
|
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>}
|
* @extends {ChaiteStorage<import('chaite').Processor>}
|
||||||
|
|
@ -24,7 +24,8 @@ export class LowDBProcessorsStorage extends ChaiteStorage {
|
||||||
* @returns {Promise<import('chaite').Processor>}
|
* @returns {Promise<import('chaite').Processor>}
|
||||||
*/
|
*/
|
||||||
async getItem (key) {
|
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[]>}
|
* @returns {Promise<import('chaite').Processor[]>}
|
||||||
*/
|
*/
|
||||||
async listItems () {
|
async listItems () {
|
||||||
return this.collection.findAll()
|
const list = await this.collection.findAll()
|
||||||
|
return list.map(item => new ProcessorDTO({}).fromString(JSON.stringify(item)))
|
||||||
}
|
}
|
||||||
|
|
||||||
async clear () {
|
async clear () {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { ChaiteStorage } from 'chaite'
|
import { ChaiteStorage, ToolDTO } from 'chaite'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @extends {ChaiteStorage<import('chaite').ToolDTO>}
|
* @extends {ChaiteStorage<import('chaite').ToolDTO>}
|
||||||
|
|
@ -24,7 +24,8 @@ export class LowDBToolsStorage extends ChaiteStorage {
|
||||||
* @returns {Promise<import('chaite').ToolDTO>}
|
* @returns {Promise<import('chaite').ToolDTO>}
|
||||||
*/
|
*/
|
||||||
async getItem (key) {
|
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[]>}
|
* @returns {Promise<import('chaite').ToolDTO[]>}
|
||||||
*/
|
*/
|
||||||
async listItems () {
|
async listItems () {
|
||||||
return this.collection.findAll()
|
const list = await this.collection.findAll()
|
||||||
|
return list.map(item => new ToolDTO({}).fromString(JSON.stringify(item)))
|
||||||
}
|
}
|
||||||
|
|
||||||
async clear () {
|
async clear () {
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
"author": "ikechan8370",
|
"author": "ikechan8370",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chaite": "/Users/geyinchi/WebstormProjects/node-chaite",
|
"chaite": "/Users/geyinchi/WebstormProjects/node-chaite",
|
||||||
|
"js-yaml": "^4.1.0",
|
||||||
"keyv": "^5.3.1",
|
"keyv": "^5.3.1",
|
||||||
"keyv-file": "^5.1.2",
|
"keyv-file": "^5.1.2",
|
||||||
"lowdb": "^7.0.1",
|
"lowdb": "^7.0.1",
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ export async function intoUserMessage (e, options = {}) {
|
||||||
if (text) {
|
if (text) {
|
||||||
contents.push({
|
contents.push({
|
||||||
type: 'text',
|
type: 'text',
|
||||||
content: text
|
text
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
|
@ -134,7 +134,7 @@ export async function getPreset (e, presetId, toggleMode, togglePrefix) {
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
export function checkChatMsg (e, toggleMode, togglePrefix) {
|
export function checkChatMsg (e, toggleMode, togglePrefix) {
|
||||||
if (toggleMode === 'at' && e.atBot) {
|
if (toggleMode === 'at' && (e.atBot || e.isPrivate)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
const prefixReg = new RegExp(`^#?(图片)?${togglePrefix}[^gpt][sS]*`)
|
const prefixReg = new RegExp(`^#?(图片)?${togglePrefix}[^gpt][sS]*`)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue