foliko 1.0.83 → 1.0.85

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 (168) hide show
  1. package/.agent/.shared/ui-ux-pro-max/data/charts.csv +26 -0
  2. package/.agent/.shared/ui-ux-pro-max/data/colors.csv +97 -0
  3. package/.agent/.shared/ui-ux-pro-max/data/icons.csv +101 -0
  4. package/.agent/.shared/ui-ux-pro-max/data/landing.csv +31 -0
  5. package/.agent/.shared/ui-ux-pro-max/data/products.csv +97 -0
  6. package/.agent/.shared/ui-ux-pro-max/data/prompts.csv +24 -0
  7. package/.agent/.shared/ui-ux-pro-max/data/react-performance.csv +45 -0
  8. package/.agent/.shared/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
  9. package/.agent/.shared/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
  10. package/.agent/.shared/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
  11. package/.agent/.shared/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
  12. package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
  13. package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
  14. package/.agent/.shared/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
  15. package/.agent/.shared/ui-ux-pro-max/data/stacks/react.csv +54 -0
  16. package/.agent/.shared/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
  17. package/.agent/.shared/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
  18. package/.agent/.shared/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
  19. package/.agent/.shared/ui-ux-pro-max/data/stacks/vue.csv +50 -0
  20. package/.agent/.shared/ui-ux-pro-max/data/styles.csv +59 -0
  21. package/.agent/.shared/ui-ux-pro-max/data/typography.csv +58 -0
  22. package/.agent/.shared/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
  23. package/.agent/.shared/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
  24. package/.agent/.shared/ui-ux-pro-max/data/web-interface.csv +31 -0
  25. package/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/core.cpython-313.pyc +0 -0
  26. package/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-313.pyc +0 -0
  27. package/.agent/.shared/ui-ux-pro-max/scripts/core.py +258 -0
  28. package/.agent/.shared/ui-ux-pro-max/scripts/design_system.py +1067 -0
  29. package/.agent/.shared/ui-ux-pro-max/scripts/search.py +106 -0
  30. package/.agent/ARCHITECTURE.md +288 -0
  31. package/.agent/agents/ambient-agent.md +57 -0
  32. package/.agent/agents/debugger.md +55 -0
  33. package/.agent/agents/email-assistant.md +49 -0
  34. package/.agent/agents/file-manager.md +42 -0
  35. package/.agent/agents/python-developer.md +60 -0
  36. package/.agent/agents/scheduler.md +59 -0
  37. package/.agent/agents/web-developer.md +45 -0
  38. package/.agent/data/default.json +355 -6
  39. package/.agent/data/plugins-state.json +185 -146
  40. package/.agent/data/puppeteer-sessions/undefined.json +6 -0
  41. package/.agent/mcp_config.json +0 -1
  42. package/.agent/mcp_config_updated.json +12 -0
  43. package/.agent/plugins/puppeteer-plugin/README.md +147 -0
  44. package/.agent/plugins/puppeteer-plugin/index.js +1418 -0
  45. package/.agent/plugins/puppeteer-plugin/package.json +9 -0
  46. package/.agent/plugins.json +5 -14
  47. package/.agent/rules/GEMINI.md +273 -0
  48. package/.agent/rules/allow-rule.md +77 -0
  49. package/.agent/rules/log-rule.md +83 -0
  50. package/.agent/rules/security-rule.md +93 -0
  51. package/.agent/scripts/auto_preview.py +148 -0
  52. package/.agent/scripts/checklist.py +217 -0
  53. package/.agent/scripts/session_manager.py +120 -0
  54. package/.agent/scripts/verify_all.py +327 -0
  55. package/.agent/skills/api-patterns/SKILL.md +81 -0
  56. package/.agent/skills/api-patterns/api-style.md +42 -0
  57. package/.agent/skills/api-patterns/auth.md +24 -0
  58. package/.agent/skills/api-patterns/documentation.md +26 -0
  59. package/.agent/skills/api-patterns/graphql.md +41 -0
  60. package/.agent/skills/api-patterns/rate-limiting.md +31 -0
  61. package/.agent/skills/api-patterns/response.md +37 -0
  62. package/.agent/skills/api-patterns/rest.md +40 -0
  63. package/.agent/skills/api-patterns/scripts/api_validator.py +211 -0
  64. package/.agent/skills/api-patterns/security-testing.md +122 -0
  65. package/.agent/skills/api-patterns/trpc.md +41 -0
  66. package/.agent/skills/api-patterns/versioning.md +22 -0
  67. package/.agent/skills/app-builder/SKILL.md +75 -0
  68. package/.agent/skills/app-builder/agent-coordination.md +71 -0
  69. package/.agent/skills/app-builder/feature-building.md +53 -0
  70. package/.agent/skills/app-builder/project-detection.md +34 -0
  71. package/.agent/skills/app-builder/scaffolding.md +118 -0
  72. package/.agent/skills/app-builder/tech-stack.md +40 -0
  73. package/.agent/skills/app-builder/templates/SKILL.md +39 -0
  74. package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +76 -0
  75. package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +92 -0
  76. package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +88 -0
  77. package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +88 -0
  78. package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +83 -0
  79. package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +90 -0
  80. package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -0
  81. package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +122 -0
  82. package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +122 -0
  83. package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +169 -0
  84. package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +134 -0
  85. package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +83 -0
  86. package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +119 -0
  87. package/.agent/skills/architecture/SKILL.md +55 -0
  88. package/.agent/skills/architecture/context-discovery.md +43 -0
  89. package/.agent/skills/architecture/examples.md +94 -0
  90. package/.agent/skills/architecture/pattern-selection.md +68 -0
  91. package/.agent/skills/architecture/patterns-reference.md +50 -0
  92. package/.agent/skills/architecture/trade-off-analysis.md +77 -0
  93. package/.agent/skills/clean-code/SKILL.md +201 -0
  94. package/.agent/skills/doc.md +177 -0
  95. package/.agent/skills/frontend-design/SKILL.md +418 -0
  96. package/.agent/skills/frontend-design/animation-guide.md +331 -0
  97. package/.agent/skills/frontend-design/color-system.md +311 -0
  98. package/.agent/skills/frontend-design/decision-trees.md +418 -0
  99. package/.agent/skills/frontend-design/motion-graphics.md +306 -0
  100. package/.agent/skills/frontend-design/scripts/accessibility_checker.py +183 -0
  101. package/.agent/skills/frontend-design/scripts/ux_audit.py +722 -0
  102. package/.agent/skills/frontend-design/typography-system.md +345 -0
  103. package/.agent/skills/frontend-design/ux-psychology.md +1116 -0
  104. package/.agent/skills/frontend-design/visual-effects.md +383 -0
  105. package/.agent/skills/i18n-localization/SKILL.md +154 -0
  106. package/.agent/skills/i18n-localization/scripts/i18n_checker.py +241 -0
  107. package/.agent/skills/mcp-builder/SKILL.md +176 -0
  108. package/.agent/skills/web-design-guidelines/SKILL.md +57 -0
  109. package/.agent/workflows/brainstorm.md +113 -0
  110. package/.agent/workflows/create.md +59 -0
  111. package/.agent/workflows/debug.md +103 -0
  112. package/.agent/workflows/deploy.md +176 -0
  113. package/.agent/workflows/enhance.md +63 -0
  114. package/.agent/workflows/orchestrate.md +237 -0
  115. package/.agent/workflows/plan.md +89 -0
  116. package/.agent/workflows/preview.md +81 -0
  117. package/.agent/workflows/simple-test.md +42 -0
  118. package/.agent/workflows/status.md +86 -0
  119. package/.agent/workflows/structured-orchestrate.md +180 -0
  120. package/.agent/workflows/test.md +144 -0
  121. package/.agent/workflows/ui-ux-pro-max.md +296 -0
  122. package/.claude/settings.local.json +178 -171
  123. package/.env.example +56 -56
  124. package/cli/src/commands/plugin.js +482 -0
  125. package/cli/src/index.js +7 -0
  126. package/cli/src/utils/plugin-config.js +50 -0
  127. package/package.json +1 -1
  128. package/plugins/audit-plugin.js +2 -0
  129. package/plugins/extension-executor-plugin.js +38 -0
  130. package/plugins/plugin-manager-plugin.js +402 -0
  131. package/plugins/session-plugin.js +3 -3
  132. package/skills/find-skills/AGENTS.md +162 -162
  133. package/skills/find-skills/SKILL.md +133 -133
  134. package/skills/foliko-dev/SKILL.md +563 -563
  135. package/skills/plugin-guide/SKILL.md +139 -0
  136. package/skills/python-plugin-dev/SKILL.md +238 -238
  137. package/src/core/agent-chat.js +103 -45
  138. package/src/core/framework.js +42 -1
  139. package/src/executors/mcp-executor.js +33 -0
  140. package/src/utils/index.js +153 -0
  141. package/xhs_auth.json +268 -0
  142. package/.agent/agents/code-assistant.json +0 -14
  143. package/.agent/agents/email-assistant.json +0 -14
  144. package/.agent/agents/file-assistant.json +0 -15
  145. package/.agent/agents/system-assistant.json +0 -15
  146. package/.agent/agents/web-assistant.json +0 -12
  147. package/.agent/data/ambient/goals.json +0 -50
  148. package/.agent/data/ambient/memories.json +0 -7
  149. package/.agent/data/scheduler/tasks.json +0 -1
  150. package/.agent/package.json +0 -8
  151. package/.agent/plugins/__pycache__/test_plugin.cpython-312.pyc +0 -0
  152. package/.agent/plugins/system-info/index.js +0 -387
  153. package/.agent/plugins/system-info/package.json +0 -4
  154. package/.agent/plugins/system-info/test.js +0 -40
  155. package/.agent/plugins/test_plugin.py +0 -304
  156. package/.agent/python-scripts/test_sample.py +0 -24
  157. package/.agent/skills/sysinfo/SKILL.md +0 -38
  158. package/.agent/skills/sysinfo/system-info.sh +0 -130
  159. package/.agent/skills/workflow/SKILL.md +0 -324
  160. package/.agent/workflows/email-digest.json +0 -50
  161. package/.agent/workflows/file-backup.json +0 -21
  162. package/.agent/workflows/get-ip-notify.json +0 -32
  163. package/.agent/workflows/news-aggregator.json +0 -93
  164. package/.agent/workflows/news-dashboard-v2.json +0 -94
  165. package/.agent/workflows/notification-batch.json +0 -32
  166. package/reports/system-health-report-20260401.md +0 -79
  167. package/test/tool-registry-validation.test.js +0 -218
  168. package/test_report.md +0 -70
@@ -0,0 +1,402 @@
1
+ /**
2
+ * PluginManagerPlugin - 插件管理工具
3
+ * 提供远程插件的列表、发布和安装功能
4
+ */
5
+
6
+ const fs = require('fs');
7
+ const path = require('path');
8
+ const { execSync } = require('child_process');
9
+ const { Plugin } = require('../src/core/plugin-base');
10
+ const { logger } = require('../src/utils/logger');
11
+ const { z } = require('zod');
12
+
13
+ // 从共享配置加载
14
+ const { DEFAULT_REPO, shouldIgnore } = require('../cli/src/utils/plugin-config');
15
+
16
+ const log = logger.child('PluginManagerPlugin');
17
+
18
+ /**
19
+ * 递归复制目录(带过滤)
20
+ */
21
+ function copyDirRecursive(src, dest) {
22
+ if (!fs.existsSync(src)) return;
23
+
24
+ fs.mkdirSync(dest, { recursive: true });
25
+
26
+ const entries = fs.readdirSync(src, { withFileTypes: true });
27
+
28
+ for (const entry of entries) {
29
+ const srcPath = path.join(src, entry.name);
30
+ const destPath = path.join(dest, entry.name);
31
+
32
+ if (shouldIgnore(entry.name)) {
33
+ log.debug(`Ignoring: ${entry.name}`);
34
+ continue;
35
+ }
36
+
37
+ if (entry.isDirectory()) {
38
+ copyDirRecursive(srcPath, destPath);
39
+ } else {
40
+ fs.copyFileSync(srcPath, destPath);
41
+ }
42
+ }
43
+ }
44
+
45
+ /**
46
+ * 执行 Git 命令
47
+ */
48
+ function gitCommand(args, cwd) {
49
+ try {
50
+ return execSync(`git ${args}`, { cwd, encoding: 'utf-8', stdio: 'pipe' });
51
+ } catch (err) {
52
+ return err.stdout || err.stderr || '';
53
+ }
54
+ }
55
+
56
+ /**
57
+ * 解析 Git URL 获取信息
58
+ */
59
+ function parseGitUrl(url) {
60
+ const patterns = [
61
+ /^https:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?$/,
62
+ /^git@github\.com:([^/]+)\/([^/]+?)(?:\.git)?$/,
63
+ ];
64
+
65
+ for (const pattern of patterns) {
66
+ const match = url.match(pattern);
67
+ if (match) {
68
+ return { owner: match[1], repo: match[2] };
69
+ }
70
+ }
71
+ return null;
72
+ }
73
+
74
+ class PluginManagerPlugin extends Plugin {
75
+ constructor(config = {}) {
76
+ super();
77
+ this.name = 'plugin_manager';
78
+ this.version = '1.0.0';
79
+ this.description = '管理远程插件:列表、发布、安装';
80
+ this._repo = config.repo || process.env.FOLIKO_PLUGIN_REPO || DEFAULT_REPO;
81
+ this.system = true;
82
+ }
83
+
84
+ install(framework) {
85
+ this._framework = framework;
86
+ return this;
87
+ }
88
+
89
+ start(framework) {
90
+ // 1. plugin_list - 列出远程仓库插件
91
+ framework.registerTool({
92
+ name: 'plugin_list',
93
+ description: '列出远程插件仓库中所有可用的插件',
94
+ inputSchema: z.object({
95
+ repo: z.string().optional().describe('插件仓库 URL,默认为 https://github.com/chnak/foliko-plugins.git'),
96
+ }),
97
+ execute: async (args) => {
98
+ const repo = args.repo || this._repo;
99
+ return this._listPlugins(repo);
100
+ }
101
+ });
102
+
103
+ // 2. plugin_publish - 发布本地插件到远程仓库
104
+ framework.registerTool({
105
+ name: 'plugin_publish',
106
+ description: '将本地插件发布到远程 Git 仓库(需要仓库写权限)',
107
+ inputSchema: z.object({
108
+ name: z.string().describe('插件名称,如 puppeteer-plugin'),
109
+ repo: z.string().optional().describe('插件仓库 URL'),
110
+ }),
111
+ execute: async (args) => {
112
+ const { name, repo } = args;
113
+ const targetRepo = repo || this._repo;
114
+ return this._publishPlugin(name, targetRepo);
115
+ }
116
+ });
117
+
118
+ // 3. plugin_install - 从远程仓库安装插件到本地
119
+ framework.registerTool({
120
+ name: 'plugin_install',
121
+ description: '从远程 Git 仓库安装插件到本地 .agent/plugins 目录',
122
+ inputSchema: z.object({
123
+ name: z.string().describe('插件名称,如 puppeteer-plugin'),
124
+ repo: z.string().optional().describe('插件仓库 URL'),
125
+ }),
126
+ execute: async (args) => {
127
+ const { name, repo } = args;
128
+ const targetRepo = repo || this._repo;
129
+ return this._installPlugin(name, targetRepo);
130
+ }
131
+ });
132
+
133
+ return this;
134
+ }
135
+
136
+ /**
137
+ * 列出远程仓库的插件
138
+ */
139
+ async _listPlugins(repo) {
140
+ try {
141
+ log.info(`Listing plugins from ${repo}...`);
142
+
143
+ const repoInfo = parseGitUrl(repo);
144
+ if (!repoInfo) {
145
+ return { success: false, error: 'Invalid repository URL' };
146
+ }
147
+
148
+ // 使用 GitHub API 获取仓库内容
149
+ const apiUrl = `https://api.github.com/repos/${repoInfo.owner}/${repoInfo.repo}/contents`;
150
+ const response = await fetch(apiUrl);
151
+
152
+ if (!response.ok) {
153
+ if (response.status === 404) {
154
+ return { success: false, error: `Repository not found: ${repo}` };
155
+ }
156
+ return { success: false, error: `GitHub API error: ${response.status}` };
157
+ }
158
+
159
+ const contents = await response.json();
160
+
161
+ if (!Array.isArray(contents) || contents.length === 0) {
162
+ return { success: true, plugins: [], message: 'No plugins found in repository' };
163
+ }
164
+
165
+ const plugins = [];
166
+
167
+ for (const item of contents) {
168
+ if (item.type === 'dir') {
169
+ // 获取 README 描述
170
+ let description = '-';
171
+ try {
172
+ const readmeUrl = `https://raw.githubusercontent.com/${repoInfo.owner}/${repoInfo.repo}/main/${item.name}/README.md`;
173
+ const readmeResp = await fetch(readmeUrl);
174
+ if (readmeResp.ok) {
175
+ const readmeText = await readmeResp.text();
176
+ const lines = readmeText.split('\n').filter(l => l.trim());
177
+ if (lines.length > 1) {
178
+ description = lines.slice(1).join(' ').slice(0, 100);
179
+ }
180
+ }
181
+ } catch (e) {}
182
+
183
+ plugins.push({
184
+ name: item.name,
185
+ type: 'directory',
186
+ description,
187
+ });
188
+ } else if (item.type === 'file' && item.name.endsWith('.js')) {
189
+ const name = item.name.replace('.js', '');
190
+ plugins.push({
191
+ name,
192
+ type: 'file',
193
+ description: '(root file)',
194
+ });
195
+ }
196
+ }
197
+
198
+ return {
199
+ success: true,
200
+ plugins,
201
+ repo,
202
+ count: plugins.length,
203
+ };
204
+
205
+ } catch (err) {
206
+ log.error(`List plugins failed: ${err.message}`);
207
+ return { success: false, error: err.message };
208
+ }
209
+ }
210
+
211
+ /**
212
+ * 发布插件到远程仓库
213
+ */
214
+ async _publishPlugin(pluginName, repo) {
215
+ const pluginsDir = path.resolve(process.cwd(), '.agent', 'plugins');
216
+ const localPluginsDir = path.resolve(process.cwd(), 'plugins');
217
+
218
+ // 确定插件目录
219
+ let actualPluginsDir = pluginsDir;
220
+ if (!fs.existsSync(pluginsDir)) {
221
+ if (fs.existsSync(localPluginsDir)) {
222
+ actualPluginsDir = localPluginsDir;
223
+ } else {
224
+ return { success: false, error: `Plugins directory not found` };
225
+ }
226
+ }
227
+
228
+ const pluginPath = path.join(actualPluginsDir, `${pluginName}.js`);
229
+ const pluginSourceDir = path.join(actualPluginsDir, pluginName);
230
+
231
+ // 检查插件是否存在
232
+ if (!fs.existsSync(pluginPath) && !fs.existsSync(pluginSourceDir)) {
233
+ return {
234
+ success: false,
235
+ error: `Plugin "${pluginName}" not found`,
236
+ available: fs.readdirSync(actualPluginsDir).filter(f => {
237
+ if (f.endsWith('.js')) return true;
238
+ const fullPath = path.join(actualPluginsDir, f);
239
+ return fs.statSync(fullPath).isDirectory();
240
+ }),
241
+ };
242
+ }
243
+
244
+ const tmpDir = path.join(require('os').tmpdir(), `foliko-plugin-publish-${Date.now()}`);
245
+
246
+ try {
247
+ log.info(`Publishing plugin "${pluginName}" to ${repo}...`);
248
+
249
+ // 克隆仓库
250
+ fs.mkdirSync(tmpDir, { recursive: true });
251
+
252
+ let isNewRepo = false;
253
+ try {
254
+ gitCommand(`clone ${repo} "${tmpDir}" --depth 1`, process.cwd());
255
+ } catch (err) {
256
+ log.info('Initializing new repository...');
257
+ fs.mkdirSync(tmpDir, { recursive: true });
258
+ gitCommand('init', tmpDir);
259
+ gitCommand(`remote add origin ${repo}`, tmpDir);
260
+ isNewRepo = true;
261
+ }
262
+
263
+ // 创建插件目录
264
+ const pluginDir = path.join(tmpDir, pluginName);
265
+ fs.mkdirSync(pluginDir, { recursive: true });
266
+
267
+ // 复制插件
268
+ let pluginContent = null;
269
+ if (fs.existsSync(pluginSourceDir) && fs.statSync(pluginSourceDir).isDirectory()) {
270
+ log.info('Copying plugin directory...');
271
+ copyDirRecursive(pluginSourceDir, pluginDir);
272
+
273
+ const mainJsPath = path.join(pluginSourceDir, `${pluginName}.js`);
274
+ if (fs.existsSync(mainJsPath)) {
275
+ pluginContent = fs.readFileSync(mainJsPath, 'utf-8');
276
+ }
277
+ } else {
278
+ log.info('Copying plugin file...');
279
+ pluginContent = fs.readFileSync(pluginPath, 'utf-8');
280
+ const targetPath = path.join(pluginDir, `${pluginName}.js`);
281
+ fs.writeFileSync(targetPath, pluginContent);
282
+
283
+ const configPath = path.join(actualPluginsDir, `${pluginName}.json`);
284
+ if (fs.existsSync(configPath)) {
285
+ fs.copyFileSync(configPath, path.join(pluginDir, `${pluginName}.json`));
286
+ }
287
+ }
288
+
289
+ // 创建 README.md
290
+ const readmePath = path.join(pluginDir, 'README.md');
291
+ if (!fs.existsSync(readmePath)) {
292
+ const descMatch = pluginContent?.match(/\*\*Description\*\*:\s*(.+)/) ||
293
+ pluginContent?.match(/description[:\s]+(.+)/i);
294
+ const desc = descMatch ? descMatch[1] : `Foliko plugin: ${pluginName}`;
295
+ fs.writeFileSync(readmePath, `# ${pluginName}\n\n${desc}\n`);
296
+ }
297
+
298
+ // Git 提交和推送
299
+ gitCommand('add .', tmpDir);
300
+
301
+ const status = gitCommand('status --porcelain', tmpDir);
302
+ if (!status.trim()) {
303
+ return {
304
+ success: true,
305
+ message: `No changes to commit for plugin "${pluginName}"`,
306
+ repo,
307
+ };
308
+ }
309
+
310
+ gitCommand(`commit -m "Add/update plugin: ${pluginName}"`, tmpDir);
311
+ gitCommand(`push ${isNewRepo ? '-u' : ''} origin main`, tmpDir);
312
+
313
+ log.info(`Plugin "${pluginName}" published successfully!`);
314
+
315
+ return {
316
+ success: true,
317
+ message: `Plugin "${pluginName}" published successfully`,
318
+ repo,
319
+ path: `${pluginName}/${pluginName}.js`,
320
+ };
321
+
322
+ } catch (err) {
323
+ log.error(`Publish failed: ${err.message}`);
324
+ return { success: false, error: err.message };
325
+ } finally {
326
+ fs.rmSync(tmpDir, { recursive: true, force: true });
327
+ }
328
+ }
329
+
330
+ /**
331
+ * 从远程仓库安装插件
332
+ */
333
+ async _installPlugin(pluginName, repo) {
334
+ const localPluginsDir = path.resolve(process.cwd(), '.agent', 'plugins');
335
+ const tmpDir = path.join(require('os').tmpdir(), `foliko-plugin-install-${Date.now()}`);
336
+
337
+ try {
338
+ log.info(`Installing plugin "${pluginName}" from ${repo}...`);
339
+
340
+ // 克隆仓库
341
+ fs.mkdirSync(tmpDir, { recursive: true });
342
+ gitCommand(`clone ${repo} "${tmpDir}" --depth 1`, process.cwd());
343
+
344
+ // 查找插件
345
+ const pluginDir = path.join(tmpDir, pluginName);
346
+ let sourcePath;
347
+
348
+ if (fs.existsSync(pluginDir) && fs.statSync(pluginDir).isDirectory()) {
349
+ sourcePath = path.join(pluginDir, `${pluginName}.js`);
350
+ } else {
351
+ sourcePath = path.join(tmpDir, `${pluginName}.js`);
352
+ }
353
+
354
+ if (!fs.existsSync(sourcePath)) {
355
+ // 列出可用插件
356
+ const available = fs.readdirSync(tmpDir).filter(f => {
357
+ const fullPath = path.join(tmpDir, f);
358
+ return fs.statSync(fullPath).isDirectory();
359
+ });
360
+
361
+ return {
362
+ success: false,
363
+ error: `Plugin "${pluginName}" not found in repository`,
364
+ available,
365
+ };
366
+ }
367
+
368
+ // 确保本地目录存在
369
+ if (!fs.existsSync(localPluginsDir)) {
370
+ fs.mkdirSync(localPluginsDir, { recursive: true });
371
+ }
372
+
373
+ // 复制插件到本地
374
+ const targetDir = path.join(localPluginsDir, pluginName);
375
+ fs.mkdirSync(targetDir, { recursive: true });
376
+
377
+ // 复制目录内容
378
+ copyDirRecursive(path.dirname(sourcePath), targetDir);
379
+
380
+ // 如果是单文件插件,复制主文件
381
+ if (!fs.existsSync(path.join(targetDir, `${pluginName}.js`))) {
382
+ fs.copyFileSync(sourcePath, path.join(targetDir, `${pluginName}.js`));
383
+ }
384
+
385
+ log.info(`Plugin "${pluginName}" installed to ${targetDir}`);
386
+
387
+ return {
388
+ success: true,
389
+ message: `Plugin "${pluginName}" installed successfully`,
390
+ path: targetDir,
391
+ };
392
+
393
+ } catch (err) {
394
+ log.error(`Install failed: ${err.message}`);
395
+ return { success: false, error: err.message };
396
+ } finally {
397
+ fs.rmSync(tmpDir, { recursive: true, force: true });
398
+ }
399
+ }
400
+ }
401
+
402
+ module.exports = PluginManagerPlugin;
@@ -272,9 +272,9 @@ class SessionPlugin extends Plugin {
272
272
  }
273
273
 
274
274
  // 如果会话数超过限制,清理最老的
275
- if (this._sessions.size >= this.config.maxSessions) {
276
- this._cleanupLRU()
277
- }
275
+ // if (this._sessions.size >= this.config.maxSessions) {
276
+ // this._cleanupLRU()
277
+ // }
278
278
 
279
279
  const session = {
280
280
  id,