koishi-plugin-openai-compatible 1.0.7 → 1.0.9

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/src/types.ts CHANGED
@@ -1,34 +1,222 @@
1
- export interface Message {
2
- role: 'system' | 'user' | 'assistant';
3
- content: string;
4
- }
5
-
6
- export interface ChatCompletionRequest {
7
- model: string;
8
- messages: Message[];
9
- temperature?: number;
10
- max_tokens?: number;
11
- top_p?: number;
12
- frequency_penalty?: number;
13
- presence_penalty?: number;
14
- }
15
-
16
- export interface ChatCompletionResponse {
17
- id: string;
18
- object: string;
19
- created: number;
20
- model: string;
21
- choices: Array<{
22
- index: number;
23
- message: {
24
- role: string;
25
- content: string;
26
- };
27
- finish_reason: string;
28
- }>;
29
- usage?: {
30
- prompt_tokens: number;
31
- completion_tokens: number;
32
- total_tokens: number;
33
- };
34
- }
1
+ import { Schema } from 'koishi'
2
+
3
+ // 情绪类型定义
4
+ export type EmotionType =
5
+ | 'happy' // 开心
6
+ | 'sad' // 悲伤
7
+ | 'angry' // 愤怒
8
+ | 'neutral' // 中性
9
+ | 'surprised' // 惊讶
10
+ | 'fearful' // 害怕
11
+ | 'disgusted' // 厌恶
12
+ | 'excited' // 兴奋
13
+ | 'calm' // 平静
14
+ | 'confused' // 困惑
15
+ | string // 自定义情绪类型
16
+
17
+ // 表情包配置接口
18
+ export interface EmojiConfig {
19
+ text: string // 文本表情
20
+ image?: string // 图片链接(可选)
21
+ }
22
+
23
+ export interface Config {
24
+ // 主模型配置
25
+ endpoint: string
26
+ apiKey: string
27
+ model: string
28
+ prompt: string
29
+
30
+ // 情绪分析模型配置
31
+ emotionAnalysis: {
32
+ enabled: boolean
33
+ endpoint: string
34
+ apiKey: string
35
+ model: string
36
+ prompt: string
37
+ }
38
+
39
+ // 情绪表情配置
40
+ emotionEmojis: Record<string, EmojiConfig>
41
+
42
+ // 系统提示
43
+ systemPrompt: string
44
+
45
+ // 交互控制
46
+ blacklist: string[]
47
+ cooldown: number
48
+ showError: boolean
49
+
50
+ // 模型参数
51
+ maxTokens: number
52
+ temperature: number
53
+ topP: number
54
+ presencePenalty: number
55
+ frequencyPenalty: number
56
+
57
+ // 情绪分析参数
58
+ emotionMaxTokens: number
59
+ emotionTemperature: number
60
+
61
+ // 网络设置
62
+ timeout: number
63
+ maxRetries: number
64
+ emotionTimeout: number
65
+
66
+ // 图片显示选项
67
+ showEmotionImage: boolean
68
+ imageAsMarkdown: boolean
69
+ }
70
+
71
+ export const Config: Schema<Config> = Schema.intersect([
72
+ Schema.object({
73
+ endpoint: Schema.string()
74
+ .description('OpenAI兼容API端点')
75
+ .default('https://api.openai.com/v1'),
76
+ apiKey: Schema.string()
77
+ .description('API密钥')
78
+ .role('secret'),
79
+ model: Schema.string()
80
+ .description('使用的模型')
81
+ .default('gpt-3.5-turbo'),
82
+ prompt: Schema.string()
83
+ .description('默认提示词(将被附加到用户消息前)')
84
+ .default(''),
85
+ }).description('基础配置'),
86
+
87
+ Schema.object({
88
+ emotionAnalysis: Schema.object({
89
+ enabled: Schema.boolean()
90
+ .description('是否启用情绪分析')
91
+ .default(true),
92
+ endpoint: Schema.string()
93
+ .description('情绪分析API端点(留空则使用主端点)')
94
+ .default(''),
95
+ apiKey: Schema.string()
96
+ .description('情绪分析API密钥(留空则使用主密钥)')
97
+ .role('secret')
98
+ .default(''),
99
+ model: Schema.string()
100
+ .description('情绪分析模型(建议使用较小较快的模型)')
101
+ .default('gpt-3.5-turbo'),
102
+ prompt: Schema.string()
103
+ .description('情绪分析提示词')
104
+ .default('请分析以下文本的情绪类型,只能返回以下情绪类型之一:happy(开心)、sad(悲伤)、angry(愤怒)、neutral(中性)、surprised(惊讶)、fearful(害怕)、disgusted(厌恶)、excited(兴奋)、calm(平静)、confused(困惑)。不要返回其他内容,只返回情绪类型单词。'),
105
+ }).description('情绪分析配置'),
106
+ }).description('情绪分析模块'),
107
+
108
+ Schema.object({
109
+ emotionEmojis: Schema.dict(
110
+ Schema.object({
111
+ text: Schema.string()
112
+ .description('文本表情符号')
113
+ .required(),
114
+ image: Schema.string()
115
+ .description('图片链接(可选,支持jpg/png/gif)')
116
+ .default(''),
117
+ })
118
+ )
119
+ .description('情绪类型对应的表情包配置')
120
+ .default({
121
+ 'happy': { text: '😊', image: '' },
122
+ 'sad': { text: '😢', image: '' },
123
+ 'angry': { text: '😠', image: '' },
124
+ 'neutral': { text: '😐', image: '' },
125
+ 'surprised': { text: '😲', image: '' },
126
+ 'fearful': { text: '😨', image: '' },
127
+ 'disgusted': { text: '🤢', image: '' },
128
+ 'excited': { text: '🤩', image: '' },
129
+ 'calm': { text: '😌', image: '' },
130
+ 'confused': { text: '😕', image: '' },
131
+ }),
132
+ showEmotionImage: Schema.boolean()
133
+ .description('是否显示情绪图片(如果配置了图片链接)')
134
+ .default(true),
135
+ imageAsMarkdown: Schema.boolean()
136
+ .description('是否使用Markdown格式显示图片(否则使用图片CQ码)')
137
+ .default(false),
138
+ }).description('情绪表情配置'),
139
+
140
+ Schema.object({
141
+ systemPrompt: Schema.string()
142
+ .description('系统提示词(用于system role)')
143
+ .default('你是一个有帮助的AI助手。'),
144
+ }).description('系统提示'),
145
+
146
+ Schema.object({
147
+ blacklist: Schema.array(String)
148
+ .description('黑名单用户ID')
149
+ .default([]),
150
+ cooldown: Schema.number()
151
+ .description('冷却时间(秒)')
152
+ .min(0)
153
+ .default(0),
154
+ showError: Schema.boolean()
155
+ .description('是否显示错误提示')
156
+ .default(true),
157
+ }).description('交互控制'),
158
+
159
+ Schema.object({
160
+ maxTokens: Schema.number()
161
+ .description('最大输出token数')
162
+ .min(1)
163
+ .max(4096)
164
+ .default(2048),
165
+ temperature: Schema.number()
166
+ .description('温度参数(0-2)')
167
+ .min(0)
168
+ .max(2)
169
+ .step(0.1)
170
+ .default(0.7),
171
+ topP: Schema.number()
172
+ .description('Top-p采样参数')
173
+ .min(0)
174
+ .max(1)
175
+ .step(0.1)
176
+ .default(1),
177
+ presencePenalty: Schema.number()
178
+ .description('存在惩罚(-2到2)')
179
+ .min(-2)
180
+ .max(2)
181
+ .step(0.1)
182
+ .default(0),
183
+ frequencyPenalty: Schema.number()
184
+ .description('频率惩罚(-2到2)')
185
+ .min(-2)
186
+ .max(2)
187
+ .step(0.1)
188
+ .default(0),
189
+ }).description('模型参数'),
190
+
191
+ Schema.object({
192
+ emotionMaxTokens: Schema.number()
193
+ .description('情绪分析最大token数')
194
+ .min(1)
195
+ .max(100)
196
+ .default(10),
197
+ emotionTemperature: Schema.number()
198
+ .description('情绪分析温度参数')
199
+ .min(0)
200
+ .max(1)
201
+ .step(0.1)
202
+ .default(0.1),
203
+ }).description('情绪分析参数'),
204
+
205
+ Schema.object({
206
+ timeout: Schema.number()
207
+ .description('主请求超时时间(毫秒)')
208
+ .min(1000)
209
+ .max(60000)
210
+ .default(30000),
211
+ emotionTimeout: Schema.number()
212
+ .description('情绪分析请求超时时间(毫秒)')
213
+ .min(1000)
214
+ .max(30000)
215
+ .default(5000),
216
+ maxRetries: Schema.number()
217
+ .description('最大重试次数')
218
+ .min(0)
219
+ .max(5)
220
+ .default(3),
221
+ }).description('网络设置'),
222
+ ])
package/lib/api.d.ts DELETED
@@ -1,7 +0,0 @@
1
- import type { ChatCompletionRequest } from './types';
2
- export declare class OpenAICompatibleAPI {
3
- private endpoint;
4
- private apiKey;
5
- constructor(endpoint: string, apiKey: string);
6
- chatCompletion(request: ChatCompletionRequest): Promise<string>;
7
- }
package/lib/api.js DELETED
@@ -1,32 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.OpenAICompatibleAPI = void 0;
4
- class OpenAICompatibleAPI {
5
- constructor(endpoint, apiKey) {
6
- this.endpoint = endpoint;
7
- this.apiKey = apiKey;
8
- }
9
- async chatCompletion(request) {
10
- const headers = {
11
- 'Content-Type': 'application/json',
12
- };
13
- if (this.apiKey) {
14
- headers['Authorization'] = `Bearer ${this.apiKey}`;
15
- }
16
- const response = await fetch(this.endpoint, {
17
- method: 'POST',
18
- headers,
19
- body: JSON.stringify(request),
20
- });
21
- if (!response.ok) {
22
- const errorText = await response.text();
23
- throw new Error(`API 请求失败: ${response.status} ${response.statusText}\n${errorText}`);
24
- }
25
- const data = await response.json();
26
- if (!data.choices || data.choices.length === 0) {
27
- throw new Error('API 返回了空的选择列表');
28
- }
29
- return data.choices[0].message.content;
30
- }
31
- }
32
- exports.OpenAICompatibleAPI = OpenAICompatibleAPI;
package/lib/config.d.ts DELETED
@@ -1,23 +0,0 @@
1
- import { Schema } from 'koishi';
2
- export interface Config {
3
- endpoint: string;
4
- apiKey: string;
5
- model: string;
6
- enableEmotion: boolean;
7
- emotionEndpoint: string;
8
- emotionApiKey: string;
9
- emotionModel: string;
10
- emotionImages: Record<string, string>;
11
- systemPrompt: string;
12
- emotionSystemPrompt: string;
13
- temperature: number;
14
- maxTokens: number;
15
- topP: number;
16
- frequencyPenalty: number;
17
- presencePenalty: number;
18
- blacklist: string[];
19
- cooldown: number;
20
- commandName: string;
21
- enableMessage: boolean;
22
- }
23
- export declare const Config: Schema<Config>;
package/lib/config.js DELETED
@@ -1,54 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Config = void 0;
4
- const koishi_1 = require("koishi");
5
- exports.Config = koishi_1.Schema.intersect([
6
- koishi_1.Schema.object({
7
- endpoint: koishi_1.Schema.string().default('https://api.openai.com/v1/chat/completions'),
8
- apiKey: koishi_1.Schema.string().default('').description('OpenAI API Key'),
9
- model: koishi_1.Schema.string().default('gpt-3.5-turbo'),
10
- }).description('API 配置'),
11
- koishi_1.Schema.object({
12
- enableEmotion: koishi_1.Schema.boolean().default(false).description('是否启用情绪分析'),
13
- emotionEndpoint: koishi_1.Schema.string().default('https://api.openai.com/v1/chat/completions'),
14
- emotionApiKey: koishi_1.Schema.string().default('').description('情绪分析 API Key'),
15
- emotionModel: koishi_1.Schema.string().default('gpt-3.5-turbo').description('推荐使用较快的模型'),
16
- emotionImages: koishi_1.Schema.dict(koishi_1.Schema.string().description('情绪表情包图片链接')).default({
17
- '快乐': 'https://example.com/happy.gif',
18
- '开心': 'https://example.com/happy.gif',
19
- '高兴': 'https://example.com/happy.gif',
20
- '伤心': 'https://example.com/sad.gif',
21
- '难过': 'https://example.com/sad.gif',
22
- '悲伤': 'https://example.com/sad.gif',
23
- '生气': 'https://example.com/angry.gif',
24
- '愤怒': 'https://example.com/angry.gif',
25
- '惊讶': 'https://example.com/surprised.gif',
26
- '疑惑': 'https://example.com/confused.gif',
27
- '害怕': 'https://example.com/afraid.gif',
28
- '恐惧': 'https://example.com/afraid.gif',
29
- '平静': 'https://example.com/calm.gif',
30
- '中立': 'https://example.com/neutral.gif',
31
- }).description('情绪名称对应的表情包图片链接'),
32
- }).description('情绪分析配置'),
33
- koishi_1.Schema.object({
34
- systemPrompt: koishi_1.Schema.string()
35
- .default('你是一个友好的 AI 助手,请用简洁、准确的语言回答用户的问题。')
36
- .description('系统提示词'),
37
- emotionSystemPrompt: koishi_1.Schema.string()
38
- .default('你是一个情绪分析助手。分析给定的文本内容,并判断其中表达的情绪。\n\n情绪类型包括:快乐、开心、高兴、伤心、难过、悲伤、生气、愤怒、惊讶、疑惑、害怕、恐惧、平静、中立。\n\n请直接输出一个情绪名称,不要输出任何其他内容,不要解释,不要添加标点符号。\n\n例如:\n- "今天天气真好,我很开心!" -> 快乐\n- "这次考试失败了,我好难过。" -> 伤心\n- "什么?这太不可思议了!" -> 惊讶\n- "我不知道该怎么办。" -> 疑惑\n- "这真是太可怕了!" -> 害怕\n- "一切都很平静。" -> 平静')
39
- .description('情绪分析系统提示词'),
40
- }).description('提示词配置'),
41
- koishi_1.Schema.object({
42
- temperature: koishi_1.Schema.number().min(0).max(2).default(0.7).description('温度参数'),
43
- maxTokens: koishi_1.Schema.number().min(1).default(2000).description('最大令牌数'),
44
- topP: koishi_1.Schema.number().min(0).max(1).default(1).description('Top P 参数'),
45
- frequencyPenalty: koishi_1.Schema.number().min(-2).max(2).default(0).description('频率惩罚'),
46
- presencePenalty: koishi_1.Schema.number().min(-2).max(2).default(0).description('存在惩罚'),
47
- }).description('参数配置'),
48
- koishi_1.Schema.object({
49
- blacklist: koishi_1.Schema.array(koishi_1.Schema.string()).default([]).description('黑名单用户 ID'),
50
- cooldown: koishi_1.Schema.number().min(0).default(10000).description('请求冷却时间(毫秒)'),
51
- commandName: koishi_1.Schema.string().default('ai').description('自定义指令名称'),
52
- enableMessage: koishi_1.Schema.boolean().default(true).description('是否开启提示(关闭后所有错误提示都不会输出)'),
53
- }).description('其他配置'),
54
- ]);
package/lib/emotion.d.ts DELETED
@@ -1,9 +0,0 @@
1
- import type { OpenAICompatibleAPI } from './api';
2
- import type { Config } from './config';
3
- export declare class EmotionAnalyzer {
4
- private api;
5
- private config;
6
- constructor(api: OpenAICompatibleAPI, config: Config);
7
- analyzeEmotion(text: string): Promise<string>;
8
- getEmotionImage(emotion: string): string | null;
9
- }
package/lib/emotion.js DELETED
@@ -1,32 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.EmotionAnalyzer = void 0;
4
- class EmotionAnalyzer {
5
- constructor(api, config) {
6
- this.api = api;
7
- this.config = config;
8
- }
9
- async analyzeEmotion(text) {
10
- const request = {
11
- model: this.config.emotionModel,
12
- messages: [
13
- { role: 'system', content: this.config.emotionSystemPrompt },
14
- { role: 'user', content: text },
15
- ],
16
- temperature: 0.3,
17
- max_tokens: 50,
18
- };
19
- try {
20
- const emotion = await this.api.chatCompletion(request);
21
- return emotion.trim();
22
- }
23
- catch (error) {
24
- console.error('情绪分析失败:', error);
25
- return '';
26
- }
27
- }
28
- getEmotionImage(emotion) {
29
- return this.config.emotionImages[emotion] || null;
30
- }
31
- }
32
- exports.EmotionAnalyzer = EmotionAnalyzer;
@@ -1,44 +0,0 @@
1
- declare const _default: {
2
- commands: {
3
- ai: {
4
- name: string;
5
- description: string;
6
- input: string;
7
- cooldown: string;
8
- blacklist: string;
9
- error: string;
10
- };
11
- admin: {
12
- add: {
13
- description: string;
14
- success: string;
15
- };
16
- remove: {
17
- description: string;
18
- success: string;
19
- notFound: string;
20
- };
21
- list: {
22
- description: string;
23
- empty: string;
24
- title: string;
25
- };
26
- clearcooldown: {
27
- description: string;
28
- success: string;
29
- };
30
- status: {
31
- description: string;
32
- title: string;
33
- model: string;
34
- endpoint: string;
35
- emotion: string;
36
- enabled: string;
37
- disabled: string;
38
- cooldown: string;
39
- blacklistCount: string;
40
- };
41
- };
42
- };
43
- };
44
- export default _default;
package/lib/locales/zh.js DELETED
@@ -1,45 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = {
4
- commands: {
5
- ai: {
6
- name: 'AI 对话',
7
- description: '与 AI 进行对话',
8
- input: '请输入要聊天的内容。',
9
- cooldown: '请求过于频繁,请等待 {0} 秒后再试。',
10
- blacklist: '您在黑名单中,无法使用此功能。',
11
- error: '请求失败: {0}',
12
- },
13
- admin: {
14
- add: {
15
- description: '添加黑名单',
16
- success: '已将用户 {0} 添加到黑名单。',
17
- },
18
- remove: {
19
- description: '移除黑名单',
20
- success: '已将用户 {0} 从黑名单中移除。',
21
- notFound: '用户 {0} 不在黑名单中。',
22
- },
23
- list: {
24
- description: '查看黑名单',
25
- empty: '黑名单为空。',
26
- title: '黑名单列表:',
27
- },
28
- clearcooldown: {
29
- description: '清除用户冷却',
30
- success: '已清除用户 {0} 的冷却时间。',
31
- },
32
- status: {
33
- description: '查看插件状态',
34
- title: '插件状态:',
35
- model: '模型: {0}',
36
- endpoint: '端点: {0}',
37
- emotion: '情绪分析: {0}',
38
- enabled: '已启用',
39
- disabled: '未启用',
40
- cooldown: '冷却时间: {0} 秒',
41
- blacklistCount: '黑名单数量: {0}',
42
- },
43
- },
44
- },
45
- };
package/lib/storage.d.ts DELETED
@@ -1,10 +0,0 @@
1
- export interface CooldownData {
2
- lastRequestTime: number;
3
- }
4
- export declare class Storage {
5
- private cooldowns;
6
- getCooldown(userId: string): CooldownData | undefined;
7
- setCooldown(userId: string, data: CooldownData): void;
8
- deleteCooldown(userId: string): void;
9
- isOnCooldown(userId: string, cooldownTime: number): boolean;
10
- }
package/lib/storage.js DELETED
@@ -1,25 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Storage = void 0;
4
- class Storage {
5
- constructor() {
6
- this.cooldowns = new Map();
7
- }
8
- getCooldown(userId) {
9
- return this.cooldowns.get(userId);
10
- }
11
- setCooldown(userId, data) {
12
- this.cooldowns.set(userId, data);
13
- }
14
- deleteCooldown(userId) {
15
- this.cooldowns.delete(userId);
16
- }
17
- isOnCooldown(userId, cooldownTime) {
18
- const data = this.getCooldown(userId);
19
- if (!data)
20
- return false;
21
- const elapsed = Date.now() - data.lastRequestTime;
22
- return elapsed < cooldownTime;
23
- }
24
- }
25
- exports.Storage = Storage;
package/src/api.ts DELETED
@@ -1,40 +0,0 @@
1
- import type { ChatCompletionRequest, ChatCompletionResponse } from './types';
2
-
3
- export class OpenAICompatibleAPI {
4
- private endpoint: string;
5
- private apiKey: string;
6
-
7
- constructor(endpoint: string, apiKey: string) {
8
- this.endpoint = endpoint;
9
- this.apiKey = apiKey;
10
- }
11
-
12
- async chatCompletion(request: ChatCompletionRequest): Promise<string> {
13
- const headers: Record<string, string> = {
14
- 'Content-Type': 'application/json',
15
- };
16
-
17
- if (this.apiKey) {
18
- headers['Authorization'] = `Bearer ${this.apiKey}`;
19
- }
20
-
21
- const response = await fetch(this.endpoint, {
22
- method: 'POST',
23
- headers,
24
- body: JSON.stringify(request),
25
- });
26
-
27
- if (!response.ok) {
28
- const errorText = await response.text();
29
- throw new Error(`API 请求失败: ${response.status} ${response.statusText}\n${errorText}`);
30
- }
31
-
32
- const data: ChatCompletionResponse = await response.json();
33
-
34
- if (!data.choices || data.choices.length === 0) {
35
- throw new Error('API 返回了空的选择列表');
36
- }
37
-
38
- return data.choices[0].message.content;
39
- }
40
- }