xinyu-pro 0.22.4 → 0.22.6
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/app/api/chat/route.ts +6 -8
- package/app/api/generate-svg/route.ts +5 -7
- package/app/api/generate-theme/route.ts +5 -7
- package/app/api/plugins/scan/route.ts +6 -21
- package/app/api/suggest-fields/route.ts +5 -7
- package/app/editor/page.tsx +6 -3
- package/app/extensions/edit/[id]/page.tsx +2412 -2342
- package/app/extensions/page.tsx +1576 -1572
- package/app/page.tsx +2 -2
- package/app/settings/page.tsx +1 -1
- package/bin/cli.js +226 -211
- package/components/ui/ThemeSwitcher.tsx +39 -37
- package/lib/db.ts +6 -9
- package/lib/get-ai-config.ts +33 -0
- package/lib/plugin-files.ts +186 -186
- package/package.json +2 -3
- package/version.json +7 -6
- package/.env.example +0 -17
- package/plugins/xinyu.auto-start-and-choices.xye +0 -0
- package/plugins/xinyu.bag-system.xye +0 -0
- package/plugins/xinyu.cache-optimizer.xye +0 -0
- package/plugins/xinyu.character-studio.xye +0 -0
- package/plugins/xinyu.dice-arbiter.xye +0 -0
- package/plugins/xinyu.game-auto-start-choices.xye +0 -0
- package/plugins/xinyu.markdown-render.xye +0 -0
- package/plugins/xinyu.slot-ui-beautify.xye +0 -0
- package/plugins/xinyu.world-info.xye +0 -0
package/app/api/chat/route.ts
CHANGED
|
@@ -2,10 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { NextRequest, NextResponse } from 'next/server';
|
|
4
4
|
import { buildSystemPrompt } from '@/lib/prompt-builder';
|
|
5
|
-
|
|
6
|
-
const SERVER_API_KEY = process.env.AI_API_KEY || '';
|
|
7
|
-
const SERVER_API_BASE = process.env.AI_API_BASE || 'https://api.openai.com/v1';
|
|
8
|
-
const SERVER_MODEL = process.env.AI_MODEL || 'gpt-4o';
|
|
5
|
+
import { getAiConfig } from '@/lib/get-ai-config';
|
|
9
6
|
|
|
10
7
|
export async function POST(request: NextRequest) {
|
|
11
8
|
try {
|
|
@@ -19,15 +16,16 @@ export async function POST(request: NextRequest) {
|
|
|
19
16
|
);
|
|
20
17
|
}
|
|
21
18
|
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
const
|
|
19
|
+
const aiConfig = await getAiConfig();
|
|
20
|
+
const apiKey = apiConfig?.apiKey || aiConfig.apiKey;
|
|
21
|
+
const apiBase = apiConfig?.apiBase || aiConfig.apiBase;
|
|
22
|
+
const model = apiConfig?.model || aiConfig.model;
|
|
25
23
|
const temperature = apiConfig?.temperature ?? 0.8;
|
|
26
24
|
const maxTokens = apiConfig?.maxTokens ?? 1024;
|
|
27
25
|
|
|
28
26
|
if (!apiKey) {
|
|
29
27
|
return NextResponse.json(
|
|
30
|
-
{ error: 'AI API Key
|
|
28
|
+
{ error: 'AI API Key 未配置,请在设置页面中填写 API Key' },
|
|
31
29
|
{ status: 500 }
|
|
32
30
|
);
|
|
33
31
|
}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
// app/api/generate-svg/route.ts - AI 生成 SVG 世界卡片
|
|
2
2
|
|
|
3
3
|
import { NextRequest, NextResponse } from 'next/server';
|
|
4
|
-
|
|
5
|
-
const SERVER_API_KEY = process.env.AI_API_KEY || '';
|
|
6
|
-
const SERVER_API_BASE = process.env.AI_API_BASE || 'https://api.openai.com/v1';
|
|
7
|
-
const SERVER_MODEL = process.env.AI_MODEL || 'gpt-4o';
|
|
4
|
+
import { getAiConfig } from '@/lib/get-ai-config';
|
|
8
5
|
|
|
9
6
|
interface GenerateSvgRequest {
|
|
10
7
|
worldData: Record<string, unknown>;
|
|
@@ -60,9 +57,10 @@ export async function POST(request: NextRequest) {
|
|
|
60
57
|
return NextResponse.json({ error: '缺少世界设定信息' }, { status: 400 });
|
|
61
58
|
}
|
|
62
59
|
|
|
63
|
-
const
|
|
64
|
-
const
|
|
65
|
-
const
|
|
60
|
+
const aiConfig = await getAiConfig();
|
|
61
|
+
const apiKey = apiConfig?.apiKey || aiConfig.apiKey;
|
|
62
|
+
const apiBase = apiConfig?.apiBase || aiConfig.apiBase;
|
|
63
|
+
const model = apiConfig?.model || aiConfig.model;
|
|
66
64
|
|
|
67
65
|
if (!apiKey) {
|
|
68
66
|
return NextResponse.json(
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
// app/api/generate-theme/route.ts - AI 生成配色方案
|
|
2
2
|
|
|
3
3
|
import { NextRequest, NextResponse } from 'next/server';
|
|
4
|
-
|
|
5
|
-
const SERVER_API_KEY = process.env.AI_API_KEY || '';
|
|
6
|
-
const SERVER_API_BASE = process.env.AI_API_BASE || 'https://api.openai.com/v1';
|
|
7
|
-
const SERVER_MODEL = process.env.AI_MODEL || 'gpt-4o';
|
|
4
|
+
import { getAiConfig } from '@/lib/get-ai-config';
|
|
8
5
|
|
|
9
6
|
interface GenerateThemeRequest {
|
|
10
7
|
prompt: string;
|
|
@@ -69,9 +66,10 @@ export async function POST(request: NextRequest) {
|
|
|
69
66
|
return NextResponse.json({ error: '请描述你想要的配色风格' }, { status: 400 });
|
|
70
67
|
}
|
|
71
68
|
|
|
72
|
-
const
|
|
73
|
-
const
|
|
74
|
-
const
|
|
69
|
+
const aiConfig = await getAiConfig();
|
|
70
|
+
const apiKey = apiConfig?.apiKey || aiConfig.apiKey;
|
|
71
|
+
const apiBase = apiConfig?.apiBase || aiConfig.apiBase;
|
|
72
|
+
const model = apiConfig?.model || aiConfig.model;
|
|
75
73
|
|
|
76
74
|
if (!apiKey) {
|
|
77
75
|
return NextResponse.json({ error: 'AI API Key 未配置' }, { status: 500 });
|
|
@@ -213,24 +213,9 @@ export async function POST(request: NextRequest) {
|
|
|
213
213
|
/** 尝试使用 AI API 进行深度分析 */
|
|
214
214
|
async function aiAnalysis(code: string, manifest?: ScanRequest['manifest']): Promise<ScanResult | null> {
|
|
215
215
|
try {
|
|
216
|
-
|
|
217
|
-
const
|
|
218
|
-
|
|
219
|
-
await ensureDb();
|
|
220
|
-
const [rows] = await execute('SELECT value FROM app_settings WHERE key = ?', ['app_settings']);
|
|
221
|
-
|
|
222
|
-
let apiKey = process.env.AI_API_KEY || '';
|
|
223
|
-
let apiBase = process.env.AI_API_BASE || 'https://api.openai.com/v1';
|
|
224
|
-
let model = process.env.AI_MODEL || 'gpt-4o';
|
|
225
|
-
|
|
226
|
-
if (rows.length > 0 && rows[0].value) {
|
|
227
|
-
const settings = typeof rows[0].value === 'string' ? JSON.parse(rows[0].value) : rows[0].value;
|
|
228
|
-
if (settings.aiApiKey) apiKey = settings.aiApiKey;
|
|
229
|
-
if (settings.aiApiBase) apiBase = settings.aiApiBase;
|
|
230
|
-
if (settings.aiModel) model = settings.aiModel;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
if (!apiKey) return null;
|
|
216
|
+
const { getAiConfig } = await import('@/lib/get-ai-config');
|
|
217
|
+
const config = await getAiConfig();
|
|
218
|
+
if (!config.apiKey) return null;
|
|
234
219
|
|
|
235
220
|
const systemPrompt = `你是一个代码安全分析专家。分析以下插件代码的安全性,返回 JSON 格式的安全报告。
|
|
236
221
|
JSON 格式:
|
|
@@ -244,14 +229,14 @@ JSON 格式:
|
|
|
244
229
|
|
|
245
230
|
检测维度:网络请求、DOM 操作、数据访问、代码执行(eval/Function)、恶意模式、权限需求。`;
|
|
246
231
|
|
|
247
|
-
const response = await fetch(`${apiBase}/chat/completions`, {
|
|
232
|
+
const response = await fetch(`${config.apiBase}/chat/completions`, {
|
|
248
233
|
method: 'POST',
|
|
249
234
|
headers: {
|
|
250
235
|
'Content-Type': 'application/json',
|
|
251
|
-
'Authorization': `Bearer ${apiKey}`,
|
|
236
|
+
'Authorization': `Bearer ${config.apiKey}`,
|
|
252
237
|
},
|
|
253
238
|
body: JSON.stringify({
|
|
254
|
-
model,
|
|
239
|
+
model: config.model,
|
|
255
240
|
messages: [
|
|
256
241
|
{ role: 'system', content: systemPrompt },
|
|
257
242
|
{ role: 'user', content: `插件信息:${JSON.stringify(manifest || {})}\n\n插件代码:\n${code}` },
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
// app/api/suggest-fields/route.ts - AI 智能补全字段 API
|
|
2
2
|
|
|
3
3
|
import { NextRequest, NextResponse } from 'next/server';
|
|
4
|
-
|
|
5
|
-
const SERVER_API_KEY = process.env.AI_API_KEY || '';
|
|
6
|
-
const SERVER_API_BASE = process.env.AI_API_BASE || 'https://api.openai.com/v1';
|
|
7
|
-
const SERVER_MODEL = process.env.AI_MODEL || 'gpt-4o';
|
|
4
|
+
import { getAiConfig } from '@/lib/get-ai-config';
|
|
8
5
|
|
|
9
6
|
const SYSTEM_PROMPT = `你是一个 RPG 世界卡片设计专家。根据模板名称和已有字段的键名、类型,为每个字段智能补全默认值、占位文本、选项等内容。
|
|
10
7
|
|
|
@@ -40,9 +37,10 @@ export async function POST(request: NextRequest) {
|
|
|
40
37
|
const body = await request.json();
|
|
41
38
|
const { templateName, existingFields, apiConfig } = body;
|
|
42
39
|
|
|
43
|
-
const
|
|
44
|
-
const
|
|
45
|
-
const
|
|
40
|
+
const aiConfig = await getAiConfig();
|
|
41
|
+
const apiKey = apiConfig?.apiKey || aiConfig.apiKey;
|
|
42
|
+
const apiBase = apiConfig?.apiBase || aiConfig.apiBase;
|
|
43
|
+
const model = apiConfig?.model || aiConfig.model;
|
|
46
44
|
|
|
47
45
|
if (!apiKey) {
|
|
48
46
|
return NextResponse.json(
|
package/app/editor/page.tsx
CHANGED
|
@@ -1042,9 +1042,12 @@ function EditorPageContent() {
|
|
|
1042
1042
|
|
|
1043
1043
|
{/* 字段管理(可折叠面板) */}
|
|
1044
1044
|
<div className="shrink-0 border-b" style={{ borderColor: 'var(--color-border)' }}>
|
|
1045
|
-
<
|
|
1045
|
+
<div
|
|
1046
1046
|
onClick={() => setFieldsExpanded(!fieldsExpanded)}
|
|
1047
|
-
|
|
1047
|
+
onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); setFieldsExpanded(!fieldsExpanded); } }}
|
|
1048
|
+
role="button"
|
|
1049
|
+
tabIndex={0}
|
|
1050
|
+
className="w-full flex items-center justify-between px-3 py-2 transition-colors cursor-pointer"
|
|
1048
1051
|
style={{ color: 'var(--color-text-muted)' }}
|
|
1049
1052
|
>
|
|
1050
1053
|
<span className="flex items-center gap-1.5 text-xs font-bold">
|
|
@@ -1106,7 +1109,7 @@ function EditorPageContent() {
|
|
|
1106
1109
|
<i className={`fa-solid fa-chevron-${fieldsExpanded ? 'up' : 'down'}`}
|
|
1107
1110
|
style={{ fontSize: '10px' }} />
|
|
1108
1111
|
</div>
|
|
1109
|
-
</
|
|
1112
|
+
</div>
|
|
1110
1113
|
|
|
1111
1114
|
{fieldsExpanded && (
|
|
1112
1115
|
<div className="overflow-y-auto px-2 pb-2"
|