koishi-plugin-chatluna-anuneko-api-adapter 1.0.1 → 1.0.4
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/lib/index.d.ts +2 -1
- package/lib/index.js +31 -12
- package/package.json +1 -1
- package/readme.md +2 -0
- package/src/anuneko-requester.ts +12 -4
- package/src/index.ts +22 -8
package/lib/index.d.ts
CHANGED
|
@@ -3,13 +3,14 @@ import { ChatLunaPlugin } from 'koishi-plugin-chatluna/services/chat';
|
|
|
3
3
|
export declare let logger: Logger;
|
|
4
4
|
export declare let anunekoClient: any;
|
|
5
5
|
export declare const reusable = true;
|
|
6
|
-
export declare const usage = "\n<p><strong>\u96F6\u6210\u672C\u3001\u5FEB\u901F\u4F53\u9A8CChatluna</strong>\u3002</p>\n<ul>\n<li><strong>API\u6765\u6E90\uFF1A</strong> anuneko.com</li>\n<li>\n<strong>\u63A5\u53E3\u5730\u5740\uFF1A</strong>\n<a href=\"https://anuneko.com\" target=\"_blank\" rel=\"noopener noreferrer\">https://anuneko.com</a>\n</li>\n</ul>\n<p><strong>\u8BF7\u6CE8\u610F\uFF1A</strong></p>\n<p>\u8BE5\u670D\u52A1\u9700\u8981\u914D\u7F6E\u6709\u6548\u7684 x-token \u624D\u80FD\u4F7F\u7528\u3002\u652F\u6301\u6A58\u732B(Orange Cat)\u548C\u9ED1\u732B(Exotic Shorthair)\u4E24\u79CD\u6A21\u578B\u3002</p>\n";
|
|
6
|
+
export declare const usage = "\n<p><strong>\u96F6\u6210\u672C\u3001\u5FEB\u901F\u4F53\u9A8CChatluna</strong>\u3002</p>\n<ul>\n<li><strong>API\u6765\u6E90\uFF1A</strong> anuneko.com</li>\n<li>\n<strong>\u63A5\u53E3\u5730\u5740\uFF1A</strong>\n<a href=\"https://anuneko.com\" target=\"_blank\" rel=\"noopener noreferrer\">https://anuneko.com</a>\n</li>\n</ul>\n<p><strong>\u8BF7\u6CE8\u610F\uFF1A</strong></p>\n<p>\u8BE5\u670D\u52A1\u9700\u8981\u914D\u7F6E\u6709\u6548\u7684 x-token \u624D\u80FD\u4F7F\u7528\u3002</p>\n<p>\u8BE5\u670D\u52A1\u53EF\u80FD\u9700\u8981\u79D1\u5B66\u4E0A\u7F51\u3002</p>\n<p>\u652F\u6301\u6A58\u732B(Orange Cat)\u548C\u9ED1\u732B(Exotic Shorthair)\u4E24\u79CD\u6A21\u578B\u3002</p>\n\n---\n\nx-token \u83B7\u53D6\u65B9\u6CD5\u89C1\u4ED3\u5E93\u6587\u4EF6 https://github.com/koishi-shangxue-plugins/koishi-shangxue-apps/blob/main/plugins/chatluna-anuneko-api-adapter/data/2025-12-23_19-01-43.png\n";
|
|
7
7
|
export declare function apply(ctx: Context, config: Config): void;
|
|
8
8
|
export interface Config extends ChatLunaPlugin.Config {
|
|
9
9
|
platform: string;
|
|
10
10
|
xToken: string;
|
|
11
11
|
cookie?: string;
|
|
12
12
|
loggerinfo: boolean;
|
|
13
|
+
requestTimeout: number;
|
|
13
14
|
}
|
|
14
15
|
export declare const Config: Schema<Config>;
|
|
15
16
|
export declare const inject: string[];
|
package/lib/index.js
CHANGED
|
@@ -130,10 +130,12 @@ var AnunekoRequester = class extends import_api.ModelRequester {
|
|
|
130
130
|
const data = { model: modelName };
|
|
131
131
|
try {
|
|
132
132
|
logInfo("Creating new session with model:", modelName);
|
|
133
|
+
const signal = AbortSignal.timeout(this._pluginConfig.requestTimeout * 1e3);
|
|
133
134
|
const response = await fetch("https://anuneko.com/api/v1/chat", {
|
|
134
135
|
method: "POST",
|
|
135
136
|
headers,
|
|
136
|
-
body: JSON.stringify(data)
|
|
137
|
+
body: JSON.stringify(data),
|
|
138
|
+
signal
|
|
137
139
|
});
|
|
138
140
|
const responseData = await response.json();
|
|
139
141
|
const chatId = responseData.chat_id || responseData.id;
|
|
@@ -155,10 +157,12 @@ var AnunekoRequester = class extends import_api.ModelRequester {
|
|
|
155
157
|
const data = { chat_id: chatId, model: modelName };
|
|
156
158
|
try {
|
|
157
159
|
logInfo("Switching model to:", modelName);
|
|
160
|
+
const signal = AbortSignal.timeout(this._pluginConfig.requestTimeout * 1e3);
|
|
158
161
|
const response = await fetch("https://anuneko.com/api/v1/user/select_model", {
|
|
159
162
|
method: "POST",
|
|
160
163
|
headers,
|
|
161
|
-
body: JSON.stringify(data)
|
|
164
|
+
body: JSON.stringify(data),
|
|
165
|
+
signal
|
|
162
166
|
});
|
|
163
167
|
if (response.ok) {
|
|
164
168
|
this.modelMap.set(userId, modelName);
|
|
@@ -175,10 +179,12 @@ var AnunekoRequester = class extends import_api.ModelRequester {
|
|
|
175
179
|
const headers = this.buildHeaders();
|
|
176
180
|
const data = { msg_id: msgId, choice_idx: 0 };
|
|
177
181
|
try {
|
|
182
|
+
const signal = AbortSignal.timeout(this._pluginConfig.requestTimeout * 1e3);
|
|
178
183
|
await fetch("https://anuneko.com/api/v1/msg/select-choice", {
|
|
179
184
|
method: "POST",
|
|
180
185
|
headers,
|
|
181
|
-
body: JSON.stringify(data)
|
|
186
|
+
body: JSON.stringify(data),
|
|
187
|
+
signal
|
|
182
188
|
});
|
|
183
189
|
logInfo("Choice sent for msg_id:", msgId);
|
|
184
190
|
} catch (error) {
|
|
@@ -226,10 +232,12 @@ var AnunekoRequester = class extends import_api.ModelRequester {
|
|
|
226
232
|
logInfo("Sending request to API:", url, JSON.stringify(data, null, 2));
|
|
227
233
|
let result = "";
|
|
228
234
|
let currentMsgId = null;
|
|
235
|
+
const signal = AbortSignal.timeout(this._pluginConfig.requestTimeout * 1e3);
|
|
229
236
|
const response = await fetch(url, {
|
|
230
237
|
method: "POST",
|
|
231
238
|
headers,
|
|
232
|
-
body: JSON.stringify(data)
|
|
239
|
+
body: JSON.stringify(data),
|
|
240
|
+
signal
|
|
233
241
|
});
|
|
234
242
|
if (!response.ok) {
|
|
235
243
|
throw new Error(`Request failed with status ${response.status}`);
|
|
@@ -404,7 +412,13 @@ var usage = `
|
|
|
404
412
|
</li>
|
|
405
413
|
</ul>
|
|
406
414
|
<p><strong>请注意:</strong></p>
|
|
407
|
-
<p>该服务需要配置有效的 x-token
|
|
415
|
+
<p>该服务需要配置有效的 x-token 才能使用。</p>
|
|
416
|
+
<p>该服务可能需要科学上网。</p>
|
|
417
|
+
<p>支持橘猫(Orange Cat)和黑猫(Exotic Shorthair)两种模型。</p>
|
|
418
|
+
|
|
419
|
+
---
|
|
420
|
+
|
|
421
|
+
x-token 获取方法见仓库文件 https://github.com/koishi-shangxue-plugins/koishi-shangxue-apps/blob/main/plugins/chatluna-anuneko-api-adapter/data/2025-12-23_19-01-43.png
|
|
408
422
|
`;
|
|
409
423
|
function apply(ctx, config2) {
|
|
410
424
|
logger2 = (0, import_logger3.createLogger)(ctx, "chatluna-anuneko-api-adapter");
|
|
@@ -425,6 +439,7 @@ function apply(ctx, config2) {
|
|
|
425
439
|
"x-device_id": "7b75a432-6b24-48ad-b9d3-3dc57648e3e3",
|
|
426
440
|
"x-token": config2.xToken
|
|
427
441
|
};
|
|
442
|
+
const signal = AbortSignal.timeout(config2.requestTimeout * 1e3);
|
|
428
443
|
if (config2.cookie) {
|
|
429
444
|
headers["Cookie"] = config2.cookie;
|
|
430
445
|
}
|
|
@@ -432,7 +447,8 @@ function apply(ctx, config2) {
|
|
|
432
447
|
const createResponse = await fetch("https://anuneko.com/api/v1/chat", {
|
|
433
448
|
method: "POST",
|
|
434
449
|
headers,
|
|
435
|
-
body: JSON.stringify({ model: "Orange Cat" })
|
|
450
|
+
body: JSON.stringify({ model: "Orange Cat" }),
|
|
451
|
+
signal
|
|
436
452
|
});
|
|
437
453
|
const createData = await createResponse.json();
|
|
438
454
|
const chatId = createData.chat_id || createData.id;
|
|
@@ -446,7 +462,8 @@ function apply(ctx, config2) {
|
|
|
446
462
|
const response = await fetch(url, {
|
|
447
463
|
method: "POST",
|
|
448
464
|
headers,
|
|
449
|
-
body: JSON.stringify(data)
|
|
465
|
+
body: JSON.stringify(data),
|
|
466
|
+
signal
|
|
450
467
|
});
|
|
451
468
|
if (!response.ok) {
|
|
452
469
|
return `❌ 请求失败: ${response.status} ${response.statusText}`;
|
|
@@ -467,7 +484,7 @@ function apply(ctx, config2) {
|
|
|
467
484
|
}
|
|
468
485
|
logInfo("处理行:", line.substring(0, 100));
|
|
469
486
|
if (!line.startsWith("data: ")) {
|
|
470
|
-
|
|
487
|
+
logInfo("非 data: 格式的行:", line);
|
|
471
488
|
continue;
|
|
472
489
|
}
|
|
473
490
|
const rawJson = line.substring(6).trim();
|
|
@@ -503,7 +520,8 @@ function apply(ctx, config2) {
|
|
|
503
520
|
await fetch("https://anuneko.com/api/v1/msg/select-choice", {
|
|
504
521
|
method: "POST",
|
|
505
522
|
headers,
|
|
506
|
-
body: JSON.stringify({ msg_id: currentMsgId, choice_idx: 0 })
|
|
523
|
+
body: JSON.stringify({ msg_id: currentMsgId, choice_idx: 0 }),
|
|
524
|
+
signal
|
|
507
525
|
});
|
|
508
526
|
}
|
|
509
527
|
logInfo("收到完整响应");
|
|
@@ -568,13 +586,14 @@ function apply(ctx, config2) {
|
|
|
568
586
|
}
|
|
569
587
|
__name(apply, "apply");
|
|
570
588
|
var Config2 = import_koishi.Schema.intersect([
|
|
571
|
-
import_chat.ChatLunaPlugin.Config,
|
|
572
589
|
import_koishi.Schema.object({
|
|
573
590
|
platform: import_koishi.Schema.string().default("anuneko"),
|
|
574
591
|
xToken: import_koishi.Schema.string().required().role("textarea", { rows: [2, 4] }).description("anuneko API 的 x-token"),
|
|
575
592
|
cookie: import_koishi.Schema.string().role("textarea", { rows: [2, 4] }).description("anuneko API 的 Cookie(可选)"),
|
|
576
|
-
loggerinfo: import_koishi.Schema.boolean().default(false).description("日志调试模式").experimental()
|
|
577
|
-
|
|
593
|
+
loggerinfo: import_koishi.Schema.boolean().default(false).description("日志调试模式").experimental(),
|
|
594
|
+
requestTimeout: import_koishi.Schema.number().default(120).description("请求 API 的超时时间,单位为秒。")
|
|
595
|
+
}).description("基础设置"),
|
|
596
|
+
import_chat.ChatLunaPlugin.Config
|
|
578
597
|
]).i18n({
|
|
579
598
|
"zh-CN": require_zh_CN_schema(),
|
|
580
599
|
"en-US": require_en_US_schema()
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -3,3 +3,5 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/koishi-plugin-chatluna-anuneko-api-adapter)
|
|
4
4
|
|
|
5
5
|
anuneko api adapter for chatluna
|
|
6
|
+
|
|
7
|
+
`x-token` 获取方法见仓库文件 https://github.com/koishi-shangxue-plugins/koishi-shangxue-apps/blob/main/plugins/chatluna-anuneko-api-adapter/data/2025-12-23_19-01-43.png
|
package/src/anuneko-requester.ts
CHANGED
|
@@ -86,10 +86,12 @@ export class AnunekoRequester extends ModelRequester {
|
|
|
86
86
|
|
|
87
87
|
try {
|
|
88
88
|
logInfo('Creating new session with model:', modelName)
|
|
89
|
+
const signal = AbortSignal.timeout(this._pluginConfig.requestTimeout * 1000)
|
|
89
90
|
const response = await fetch('https://anuneko.com/api/v1/chat', {
|
|
90
91
|
method: 'POST',
|
|
91
92
|
headers,
|
|
92
|
-
body: JSON.stringify(data)
|
|
93
|
+
body: JSON.stringify(data),
|
|
94
|
+
signal
|
|
93
95
|
})
|
|
94
96
|
|
|
95
97
|
const responseData = await response.json()
|
|
@@ -117,10 +119,12 @@ export class AnunekoRequester extends ModelRequester {
|
|
|
117
119
|
|
|
118
120
|
try {
|
|
119
121
|
logInfo('Switching model to:', modelName)
|
|
122
|
+
const signal = AbortSignal.timeout(this._pluginConfig.requestTimeout * 1000)
|
|
120
123
|
const response = await fetch('https://anuneko.com/api/v1/user/select_model', {
|
|
121
124
|
method: 'POST',
|
|
122
125
|
headers,
|
|
123
|
-
body: JSON.stringify(data)
|
|
126
|
+
body: JSON.stringify(data),
|
|
127
|
+
signal
|
|
124
128
|
})
|
|
125
129
|
|
|
126
130
|
if (response.ok) {
|
|
@@ -141,10 +145,12 @@ export class AnunekoRequester extends ModelRequester {
|
|
|
141
145
|
const data = { msg_id: msgId, choice_idx: 0 }
|
|
142
146
|
|
|
143
147
|
try {
|
|
148
|
+
const signal = AbortSignal.timeout(this._pluginConfig.requestTimeout * 1000)
|
|
144
149
|
await fetch('https://anuneko.com/api/v1/msg/select-choice', {
|
|
145
150
|
method: 'POST',
|
|
146
151
|
headers,
|
|
147
|
-
body: JSON.stringify(data)
|
|
152
|
+
body: JSON.stringify(data),
|
|
153
|
+
signal
|
|
148
154
|
})
|
|
149
155
|
logInfo('Choice sent for msg_id:', msgId)
|
|
150
156
|
} catch (error) {
|
|
@@ -212,10 +218,12 @@ export class AnunekoRequester extends ModelRequester {
|
|
|
212
218
|
let currentMsgId: string | null = null
|
|
213
219
|
|
|
214
220
|
// 使用流式请求
|
|
221
|
+
const signal = AbortSignal.timeout(this._pluginConfig.requestTimeout * 1000)
|
|
215
222
|
const response = await fetch(url, {
|
|
216
223
|
method: 'POST',
|
|
217
224
|
headers,
|
|
218
|
-
body: JSON.stringify(data)
|
|
225
|
+
body: JSON.stringify(data),
|
|
226
|
+
signal
|
|
219
227
|
})
|
|
220
228
|
|
|
221
229
|
if (!response.ok) {
|
package/src/index.ts
CHANGED
|
@@ -21,7 +21,13 @@ export const usage = `
|
|
|
21
21
|
</li>
|
|
22
22
|
</ul>
|
|
23
23
|
<p><strong>请注意:</strong></p>
|
|
24
|
-
<p>该服务需要配置有效的 x-token
|
|
24
|
+
<p>该服务需要配置有效的 x-token 才能使用。</p>
|
|
25
|
+
<p>该服务可能需要科学上网。</p>
|
|
26
|
+
<p>支持橘猫(Orange Cat)和黑猫(Exotic Shorthair)两种模型。</p>
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
x-token 获取方法见仓库文件 https://github.com/koishi-shangxue-plugins/koishi-shangxue-apps/blob/main/plugins/chatluna-anuneko-api-adapter/data/2025-12-23_19-01-43.png
|
|
25
31
|
`
|
|
26
32
|
|
|
27
33
|
export function apply(ctx: Context, config: Config) {
|
|
@@ -47,6 +53,7 @@ export function apply(ctx: Context, config: Config) {
|
|
|
47
53
|
'x-device_id': '7b75a432-6b24-48ad-b9d3-3dc57648e3e3',
|
|
48
54
|
'x-token': config.xToken
|
|
49
55
|
}
|
|
56
|
+
const signal = AbortSignal.timeout(config.requestTimeout * 1000)
|
|
50
57
|
|
|
51
58
|
if (config.cookie) {
|
|
52
59
|
headers['Cookie'] = config.cookie
|
|
@@ -57,7 +64,8 @@ export function apply(ctx: Context, config: Config) {
|
|
|
57
64
|
const createResponse = await fetch('https://anuneko.com/api/v1/chat', {
|
|
58
65
|
method: 'POST',
|
|
59
66
|
headers,
|
|
60
|
-
body: JSON.stringify({ model: 'Orange Cat' })
|
|
67
|
+
body: JSON.stringify({ model: 'Orange Cat' }),
|
|
68
|
+
signal
|
|
61
69
|
})
|
|
62
70
|
|
|
63
71
|
const createData = await createResponse.json()
|
|
@@ -76,7 +84,8 @@ export function apply(ctx: Context, config: Config) {
|
|
|
76
84
|
const response = await fetch(url, {
|
|
77
85
|
method: 'POST',
|
|
78
86
|
headers,
|
|
79
|
-
body: JSON.stringify(data)
|
|
87
|
+
body: JSON.stringify(data),
|
|
88
|
+
signal
|
|
80
89
|
})
|
|
81
90
|
|
|
82
91
|
if (!response.ok) {
|
|
@@ -107,7 +116,7 @@ export function apply(ctx: Context, config: Config) {
|
|
|
107
116
|
logInfo('处理行:', line.substring(0, 100))
|
|
108
117
|
|
|
109
118
|
if (!line.startsWith('data: ')) {
|
|
110
|
-
|
|
119
|
+
logInfo('非 data: 格式的行:', line)
|
|
111
120
|
continue
|
|
112
121
|
}
|
|
113
122
|
|
|
@@ -153,7 +162,8 @@ export function apply(ctx: Context, config: Config) {
|
|
|
153
162
|
await fetch('https://anuneko.com/api/v1/msg/select-choice', {
|
|
154
163
|
method: 'POST',
|
|
155
164
|
headers,
|
|
156
|
-
body: JSON.stringify({ msg_id: currentMsgId, choice_idx: 0 })
|
|
165
|
+
body: JSON.stringify({ msg_id: currentMsgId, choice_idx: 0 }),
|
|
166
|
+
signal
|
|
157
167
|
})
|
|
158
168
|
}
|
|
159
169
|
|
|
@@ -237,10 +247,10 @@ export interface Config extends ChatLunaPlugin.Config {
|
|
|
237
247
|
xToken: string
|
|
238
248
|
cookie?: string
|
|
239
249
|
loggerinfo: boolean
|
|
250
|
+
requestTimeout: number
|
|
240
251
|
}
|
|
241
252
|
|
|
242
253
|
export const Config: Schema<Config> = Schema.intersect([
|
|
243
|
-
ChatLunaPlugin.Config,
|
|
244
254
|
Schema.object({
|
|
245
255
|
platform: Schema.string().default('anuneko'),
|
|
246
256
|
xToken: Schema.string()
|
|
@@ -253,8 +263,12 @@ export const Config: Schema<Config> = Schema.intersect([
|
|
|
253
263
|
loggerinfo: Schema.boolean()
|
|
254
264
|
.default(false)
|
|
255
265
|
.description('日志调试模式')
|
|
256
|
-
.experimental()
|
|
257
|
-
|
|
266
|
+
.experimental(),
|
|
267
|
+
requestTimeout: Schema.number()
|
|
268
|
+
.default(120)
|
|
269
|
+
.description('请求 API 的超时时间,单位为秒。')
|
|
270
|
+
}).description('基础设置'),
|
|
271
|
+
ChatLunaPlugin.Config,
|
|
258
272
|
]).i18n({
|
|
259
273
|
'zh-CN': require('./locales/zh-CN.schema.yml'),
|
|
260
274
|
'en-US': require('./locales/en-US.schema.yml')
|