xinyu-pro 0.22.6 → 0.23.0

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.
Files changed (105) hide show
  1. package/app/api/chat/route.ts +2 -2
  2. package/app/api/generate-svg/route.ts +1 -1
  3. package/app/api/generate-theme/route.ts +112 -135
  4. package/app/api/plugins/bindings/route.ts +4 -4
  5. package/app/api/plugins/export/route.ts +9 -3
  6. package/app/api/plugins/export-xye/route.ts +12 -7
  7. package/app/api/plugins/files/route.ts +9 -9
  8. package/app/api/plugins/files-list/route.ts +7 -3
  9. package/app/api/plugins/files-upload/route.ts +3 -3
  10. package/app/api/plugins/files-write/all/route.ts +250 -0
  11. package/app/api/plugins/files-write/route.ts +13 -15
  12. package/app/api/plugins/import/route.ts +5 -5
  13. package/app/api/plugins/import-package/route.ts +9 -9
  14. package/app/api/plugins/resources/route.ts +6 -2
  15. package/app/api/plugins/route.ts +215 -119
  16. package/app/api/plugins/scan/route.ts +1 -1
  17. package/app/api/plugins/storage/route.ts +3 -3
  18. package/app/api/plugins/toggle/route.ts +21 -0
  19. package/app/api/sessions/route.ts +8 -3
  20. package/app/api/settings/route.ts +2 -2
  21. package/app/api/suggest-fields/route.ts +1 -1
  22. package/app/api/templates/route.ts +2 -2
  23. package/app/api/themes/route.ts +116 -0
  24. package/app/editor/page.tsx +21 -4
  25. package/app/extensions/edit/[id]/page.tsx +2148 -984
  26. package/app/extensions/page.tsx +477 -86
  27. package/app/extensions/tutorial/code-examples.ts +833 -0
  28. package/app/extensions/tutorial/nav-link.tsx +27 -0
  29. package/app/extensions/tutorial/page.tsx +47 -3616
  30. package/app/extensions/tutorial/sections/AiInterceptionSection.tsx +87 -0
  31. package/app/extensions/tutorial/sections/ArchitectureSection.tsx +39 -0
  32. package/app/extensions/tutorial/sections/BestPracticesSection.tsx +78 -0
  33. package/app/extensions/tutorial/sections/ChatApiSection.tsx +212 -0
  34. package/app/extensions/tutorial/sections/CrossPluginSection.tsx +90 -0
  35. package/app/extensions/tutorial/sections/CssVariablesSection.tsx +189 -0
  36. package/app/extensions/tutorial/sections/DebugSection.tsx +48 -0
  37. package/app/extensions/tutorial/sections/DependencySection.tsx +134 -0
  38. package/app/extensions/tutorial/sections/DomSandboxSection.tsx +229 -0
  39. package/app/extensions/tutorial/sections/ExamplesSection.tsx +29 -0
  40. package/app/extensions/tutorial/sections/FileApiSection.tsx +44 -0
  41. package/app/extensions/tutorial/sections/GlobalApiSection.tsx +50 -0
  42. package/app/extensions/tutorial/sections/InputApiSection.tsx +213 -0
  43. package/app/extensions/tutorial/sections/LifecycleSection.tsx +105 -0
  44. package/app/extensions/tutorial/sections/OverviewSection.tsx +54 -0
  45. package/app/extensions/tutorial/sections/PermissionsSection.tsx +239 -0
  46. package/app/extensions/tutorial/sections/PersistentStorageSection.tsx +49 -0
  47. package/app/extensions/tutorial/sections/PluginConfigSection.tsx +81 -0
  48. package/app/extensions/tutorial/sections/PluginImportExportSection.tsx +68 -0
  49. package/app/extensions/tutorial/sections/PluginStorageSection.tsx +94 -0
  50. package/app/extensions/tutorial/sections/ResourceApiSection.tsx +88 -0
  51. package/app/extensions/tutorial/sections/SecuritySection.tsx +106 -0
  52. package/app/extensions/tutorial/sections/SlotsSection.tsx +130 -0
  53. package/app/extensions/tutorial/sections/UiApiSection.tsx +147 -0
  54. package/app/extensions/tutorial/sections/UtilsApiSection.tsx +96 -0
  55. package/app/extensions/tutorial/sections-data.tsx +325 -0
  56. package/app/extensions/tutorial/styles.ts +59 -0
  57. package/app/extensions/tutorial/types.ts +14 -0
  58. package/app/game/[id]/page.tsx +336 -148
  59. package/app/globals.css +41 -0
  60. package/app/page.tsx +17 -10
  61. package/app/settings/page.tsx +218 -236
  62. package/bin/cli.js +3 -10
  63. package/components/ChatInput.tsx +20 -6
  64. package/components/ChatWindow.tsx +1 -1
  65. package/components/MessageBubble.tsx +5 -6
  66. package/components/ui/ConfirmDialog.tsx +28 -6
  67. package/components/ui/DeprecatedBadge.tsx +163 -0
  68. package/components/ui/PageHeader.tsx +1 -1
  69. package/components/ui/PermissionConflictDialog.tsx +1 -1
  70. package/components/ui/PluginConfigForm.tsx +2 -3
  71. package/components/ui/PluginFloatingLayer.tsx +2 -2
  72. package/components/ui/PluginModalRenderer.tsx +84 -38
  73. package/components/ui/PluginProvider.tsx +32 -13
  74. package/components/ui/PluginSlotRenderer.tsx +2 -2
  75. package/components/ui/ThemeCustomizer.tsx +4 -7
  76. package/components/ui/ThemeProvider.tsx +214 -125
  77. package/components/ui/ThemeSwitcher.tsx +119 -157
  78. package/components/ui/ToastProvider.tsx +47 -17
  79. package/lib/{parseWorldCard.ts → client/parseWorldCard.ts} +1 -1
  80. package/lib/{plugin-dom-sandbox.ts → client/plugin-dom-sandbox.ts} +2 -2
  81. package/lib/{plugin-runtime.ts → client/plugin-runtime.ts} +166 -67
  82. package/lib/client/plugin-utils.ts +105 -0
  83. package/lib/{router-history.ts → client/router-history.ts} +1 -1
  84. package/lib/{storage.ts → client/storage.ts} +66 -3
  85. package/lib/{themes.ts → client/themes.ts} +21 -1
  86. package/lib/{builtin-plugins.ts → server/builtin-plugins.ts} +1 -1
  87. package/lib/{db-init.ts → server/db-init.ts} +2 -2
  88. package/lib/{db.ts → server/db.ts} +48 -8
  89. package/lib/{get-ai-config.ts → server/get-ai-config.ts} +2 -2
  90. package/lib/{plugin-files.ts → server/plugin-files.ts} +7 -2
  91. package/lib/server/plugin-utils.ts +88 -0
  92. package/lib/{manifest-parser.ts → shared/manifest-parser.ts} +4 -4
  93. package/lib/{plugin-types.ts → shared/plugin-types.ts} +11 -6
  94. package/lib/{version.ts → shared/version.ts} +1 -1
  95. package/next.config.mjs +3 -2
  96. package/package.json +4 -3
  97. package/styles/themes.css +7 -2
  98. package/version.json +2 -2
  99. package/app/extensions/create/page.tsx +0 -1422
  100. /package/lib/{plugin-events.ts → client/plugin-events.ts} +0 -0
  101. /package/lib/{plugin-resource-tracker.ts → client/plugin-resource-tracker.ts} +0 -0
  102. /package/lib/{plugin-html-sanitizer.ts → shared/plugin-html-sanitizer.ts} +0 -0
  103. /package/lib/{plugin-security.ts → shared/plugin-security.ts} +0 -0
  104. /package/lib/{prompt-builder.ts → shared/prompt-builder.ts} +0 -0
  105. /package/lib/{types.ts → shared/types.ts} +0 -0
@@ -0,0 +1,116 @@
1
+ // app/api/themes/route.ts - 自定义主题 CRUD API
2
+
3
+ import { NextRequest, NextResponse } from 'next/server';
4
+ import { execute } from '@/lib/server/db';
5
+ import { ensureDb } from '@/lib/server/db-init';
6
+
7
+ export const dynamic = 'force-dynamic';
8
+
9
+ export async function GET(request: NextRequest) {
10
+ try {
11
+ await ensureDb();
12
+ const { searchParams } = new URL(request.url);
13
+ const id = searchParams.get('id');
14
+
15
+ if (id) {
16
+ const [rows] = await execute('SELECT * FROM themes WHERE id = ?', [id]);
17
+ const list = Array.isArray(rows) ? rows : [];
18
+ const row = list[0] as Record<string, unknown> | undefined;
19
+ if (row) {
20
+ return NextResponse.json(formatThemeRow(row));
21
+ }
22
+ return NextResponse.json(null);
23
+ }
24
+
25
+ const [rows] = await execute('SELECT * FROM themes ORDER BY updated_at DESC');
26
+ const list = Array.isArray(rows) ? rows : [];
27
+ return NextResponse.json(list.map(formatThemeRow));
28
+ } catch (error) {
29
+ console.error('Themes GET error:', error);
30
+ return NextResponse.json({ error: '读取主题失败' }, { status: 500 });
31
+ }
32
+ }
33
+
34
+ export async function POST(request: NextRequest) {
35
+ try {
36
+ const body = await request.json();
37
+ await ensureDb();
38
+
39
+ const {
40
+ id = `theme-${Date.now()}`,
41
+ name,
42
+ description = '',
43
+ isDark = true,
44
+ variables = {},
45
+ previewType = '',
46
+ previewContent = '',
47
+ } = body;
48
+
49
+ if (!name) {
50
+ return NextResponse.json({ error: '主题名称不能为空' }, { status: 400 });
51
+ }
52
+
53
+ await execute(
54
+ `INSERT INTO themes (id, name, description, is_dark, variables, preview_type, preview_content)
55
+ VALUES (?, ?, ?, ?, ?, ?, ?)
56
+ ON CONFLICT(id) DO UPDATE SET
57
+ name = excluded.name,
58
+ description = excluded.description,
59
+ is_dark = excluded.is_dark,
60
+ variables = excluded.variables,
61
+ preview_type = excluded.preview_type,
62
+ preview_content = excluded.preview_content,
63
+ updated_at = datetime('now')`,
64
+ [
65
+ id,
66
+ name,
67
+ description,
68
+ isDark ? 1 : 0,
69
+ JSON.stringify(variables),
70
+ previewType || '',
71
+ previewContent || '',
72
+ ]
73
+ );
74
+
75
+ const [rows] = await execute('SELECT * FROM themes WHERE id = ?', [id]);
76
+ const list = Array.isArray(rows) ? rows : [];
77
+ const row = list[0] as Record<string, unknown> | undefined;
78
+
79
+ return NextResponse.json(row ? formatThemeRow(row) : { id, name });
80
+ } catch (error) {
81
+ console.error('Themes POST error:', error);
82
+ return NextResponse.json({ error: '保存主题失败' }, { status: 500 });
83
+ }
84
+ }
85
+
86
+ export async function DELETE(request: NextRequest) {
87
+ try {
88
+ await ensureDb();
89
+ const { searchParams } = new URL(request.url);
90
+ const id = searchParams.get('id');
91
+
92
+ if (!id) {
93
+ return NextResponse.json({ error: '缺少主题 ID' }, { status: 400 });
94
+ }
95
+
96
+ await execute('DELETE FROM themes WHERE id = ?', [id]);
97
+ return NextResponse.json({ success: true });
98
+ } catch (error) {
99
+ console.error('Themes DELETE error:', error);
100
+ return NextResponse.json({ error: '删除主题失败' }, { status: 500 });
101
+ }
102
+ }
103
+
104
+ function formatThemeRow(row: Record<string, unknown>) {
105
+ return {
106
+ id: row.id,
107
+ name: row.name,
108
+ description: row.description,
109
+ isDark: row.is_dark === 1 || row.is_dark === true,
110
+ variables: typeof row.variables === 'string' ? JSON.parse(row.variables as string) : row.variables,
111
+ previewType: row.preview_type || '',
112
+ previewContent: row.preview_content || '',
113
+ createdAt: row.created_at,
114
+ updatedAt: row.updated_at,
115
+ };
116
+ }
@@ -3,10 +3,13 @@
3
3
 
4
4
  import React, { useState, useCallback, useEffect, useMemo, useRef, Suspense } from 'react';
5
5
  import { useRouter, useSearchParams } from 'next/navigation';
6
- import { useRouterHistory } from '@/lib/router-history';
7
- import { WorldCardField, WorldCardTemplate, FieldType } from '@/lib/types';
8
- import { getAppSettings, saveWorldTemplate, getWorldTemplate, saveGameSession, StoredSession, getPlugins } from '@/lib/storage';
9
- import { fieldsToWorldSetting, fieldsToWorldData, injectWorldData } from '@/lib/parseWorldCard';
6
+ import { useRouterHistory } from '@/lib/client/router-history';
7
+ import { WorldCardField, WorldCardTemplate, FieldType } from '@/lib/shared/types';
8
+ import {
9
+ getAppSettings, saveWorldTemplate, getWorldTemplate, saveGameSession, StoredSession, getPlugins,
10
+ getPluginBindings, upsertPluginBinding
11
+ } from '@/lib/client/storage';
12
+ import { fieldsToWorldSetting, fieldsToWorldData, injectWorldData } from '@/lib/client/parseWorldCard';
10
13
  import { useToast } from '@/components/ui/ToastProvider';
11
14
  import ConfirmDialog from '@/components/ui/ConfirmDialog';
12
15
  import PageHeader from '@/components/ui/PageHeader';
@@ -891,6 +894,20 @@ function EditorPageContent() {
891
894
  createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(),
892
895
  };
893
896
  await saveGameSession(session);
897
+
898
+ // 为插件创建世界级绑定(使用全局绑定的配置作为默认值)
899
+ if (validPlugins.length > 0) {
900
+ const globalBindings = await getPluginBindings('global');
901
+ const globalBindingMap = new Map(globalBindings.map(b => [b.extensionId, b]));
902
+ for (const pid of validPlugins) {
903
+ const globalBinding = globalBindingMap.get(pid);
904
+ await upsertPluginBinding({
905
+ extensionId: pid, scope: 'world', worldId: gameId,
906
+ enabled: true, config: globalBinding?.config || {}, sortOrder: 0,
907
+ });
908
+ }
909
+ }
910
+
894
911
  navigate(`/game/${gameId}`, {record: recordRouter});
895
912
  } catch (err) {
896
913
  toast(err instanceof Error ? err.message : '创建游戏失败', 'error');