foliko 1.1.68 → 1.1.69

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 (142) hide show
  1. package/.claude/settings.local.json +19 -10
  2. package/.dockerignore +45 -45
  3. package/.env.example +56 -56
  4. package/CLAUDE.md +2 -2
  5. package/README.md +13 -13
  6. package/SPEC.md +3 -3
  7. package/cli/src/commands/chat.js +2 -20
  8. package/cli/src/commands/list.js +7 -6
  9. package/cli/src/commands/plugin.js +3 -2
  10. package/cli/src/daemon.js +2 -2
  11. package/cli/src/ui/chat-ui-old.js +15 -4
  12. package/cli/src/ui/chat-ui.js +152 -38
  13. package/cli/src/ui/footer-bar.js +13 -14
  14. package/cli/src/utils/config.js +29 -0
  15. package/cli/src/utils/plugin-config.js +1 -1
  16. package/docker-compose.yml +33 -33
  17. package/docs/features.md +120 -120
  18. package/docs/quick-reference.md +160 -160
  19. package/docs/user-manual.md +1391 -1391
  20. package/examples/ambient-example.js +2 -2
  21. package/examples/bootstrap.js +3 -3
  22. package/examples/test-chat.js +1 -1
  23. package/examples/test-reload.js +1 -1
  24. package/examples/test-telegram.js +1 -1
  25. package/examples/test-tg-bot.js +1 -1
  26. package/examples/test-tg-simple.js +2 -2
  27. package/examples/test-tg.js +1 -1
  28. package/examples/test-think.js +1 -1
  29. package/examples/test-weixin-feishu.js +3 -3
  30. package/package.json +3 -1
  31. package/plugins/ambient-agent/index.js +1 -1
  32. package/plugins/audit-plugin.js +75 -24
  33. package/plugins/default-plugins.js +21 -11
  34. package/plugins/email/index.js +1 -1
  35. package/plugins/extension-executor-plugin.js +85 -7
  36. package/plugins/feishu-plugin.js +118 -16
  37. package/plugins/install-plugin.js +4 -4
  38. package/plugins/memory-plugin.js +1 -1
  39. package/plugins/plugin-manager-plugin.js +3 -3
  40. package/plugins/python-executor-plugin.js +1 -1
  41. package/plugins/python-plugin-loader.js +1 -1
  42. package/plugins/qq-plugin.js +143 -16
  43. package/plugins/rules-plugin.js +1 -1
  44. package/plugins/scheduler-plugin.js +2 -2
  45. package/plugins/session-plugin.js +309 -393
  46. package/plugins/storage-plugin.js +235 -176
  47. package/plugins/subagent-plugin.js +4 -4
  48. package/plugins/telegram-plugin.js +116 -17
  49. package/plugins/think-plugin.js +1 -1
  50. package/plugins/web-plugin.js +2 -2
  51. package/plugins/weixin-plugin.js +102 -19
  52. package/skills/find-skills/AGENTS.md +2 -2
  53. package/skills/find-skills/SKILL.md +133 -133
  54. package/skills/foliko-dev/AGENTS.md +236 -236
  55. package/skills/foliko-dev/SKILL.md +19 -19
  56. package/skills/mcp-usage/SKILL.md +200 -200
  57. package/skills/plugin-guide/SKILL.md +4 -4
  58. package/skills/python-plugin-dev/SKILL.md +5 -5
  59. package/skills/skill-guide/SKILL.md +104 -6
  60. package/skills/subagent-guide/SKILL.md +237 -237
  61. package/skills/workflow-guide/SKILL.md +646 -646
  62. package/src/capabilities/skill-manager.js +101 -2
  63. package/src/capabilities/workflow-engine.js +1 -1
  64. package/src/core/agent-chat.js +17 -14
  65. package/src/core/branch-summary-auto.js +206 -0
  66. package/src/core/chat-session.js +38 -8
  67. package/src/core/command-registry.js +200 -0
  68. package/src/core/constants.js +11 -11
  69. package/src/core/context-compressor.js +700 -149
  70. package/src/core/context-manager.js +0 -1
  71. package/src/core/enhanced-context-compressor.js +210 -0
  72. package/src/core/framework.js +140 -83
  73. package/src/core/jsonl-storage.js +253 -0
  74. package/src/core/plugin-manager.js +15 -10
  75. package/src/core/provider-registry.js +159 -0
  76. package/src/core/provider.js +2 -0
  77. package/src/core/session-entry.js +225 -0
  78. package/src/core/session-manager.js +701 -0
  79. package/src/core/storage-manager.js +494 -0
  80. package/src/core/sub-agent-config.js +1 -1
  81. package/src/core/token-counter.js +177 -58
  82. package/src/core/ui-extension-context.js +174 -0
  83. package/src/executors/mcp-executor.js +15 -6
  84. package/src/utils/logger.js +152 -180
  85. package/src/utils/plugin-helpers.js +2 -2
  86. package/website_v2/docs/api.html +1 -1
  87. package/website_v2/docs/configuration.html +2 -2
  88. package/website_v2/docs/plugin-development.html +4 -4
  89. package/website_v2/docs/project-structure.html +2 -2
  90. package/website_v2/docs/skill-development.html +2 -2
  91. package/website_v2/index.html +1 -1
  92. package/website_v2/styles/animations.css +7 -7
  93. package/.agent/agents/backend-dev.md +0 -102
  94. package/.agent/agents/data-analyst.md +0 -117
  95. package/.agent/agents/devops.md +0 -115
  96. package/.agent/agents/frontend-dev.md +0 -94
  97. package/.agent/agents/network-requester.md +0 -44
  98. package/.agent/agents/poster-designer.md +0 -52
  99. package/.agent/agents/product-manager.md +0 -85
  100. package/.agent/agents/qa-engineer.md +0 -100
  101. package/.agent/agents/security-engineer.md +0 -99
  102. package/.agent/agents/team-lead.md +0 -137
  103. package/.agent/agents/ui-designer.md +0 -116
  104. package/.agent/data/default.json +0 -58
  105. package/.agent/data/email/processed-emails.json +0 -1
  106. package/.agent/data/plugins-state.json +0 -207
  107. package/.agent/data/scheduler/tasks.json +0 -1
  108. package/.agent/data/web/web-config.json +0 -5
  109. package/.agent/data/weixin/images/file_1776188148383jpg +0 -0
  110. package/.agent/data/weixin/images/file_1776188458326.jpg +0 -0
  111. package/.agent/data/weixin/images/file_1776188689423.jpg +0 -0
  112. package/.agent/data/weixin/images/file_1776188813604.jpg +0 -0
  113. package/.agent/data/weixin/images/file_1776189097450.jpg +0 -0
  114. package/.agent/data/weixin/videos/file_1776188318431.mp4 +0 -0
  115. package/.agent/data/weixin.json +0 -6
  116. package/.agent/mcp_config.json +0 -14
  117. package/.agent/memory/user/mof6gk94-kneeuh.md +0 -9
  118. package/.agent/package.json +0 -8
  119. package/.agent/plugins/marknative/README.md +0 -134
  120. package/.agent/plugins/marknative/fonts/SegoeUI Emoji.ttf +0 -0
  121. package/.agent/plugins/marknative/fonts.zip +0 -0
  122. package/.agent/plugins/marknative/index.js +0 -256
  123. package/.agent/plugins/marknative/package.json +0 -12
  124. package/.agent/plugins/test-plugin.py +0 -99
  125. package/.agent/plugins.json +0 -14
  126. package/.agent/python-scripts/test_sample.py +0 -24
  127. package/.agent/sessions/cli_default.json +0 -4121
  128. package/.agent/skills/agent-browser/SKILL.md +0 -311
  129. package/.agent/skills/agent-browser/TEST_PLAN.md +0 -200
  130. package/.agent/skills/sysinfo/SKILL.md +0 -38
  131. package/.agent/skills/sysinfo/system-info.sh +0 -130
  132. package/.agent/skills/workflow/SKILL.md +0 -324
  133. package/.agent/test-agent.js +0 -35
  134. package/.agent/weixin.json +0 -6
  135. package/.agent/workflows/email-digest.json +0 -50
  136. package/.agent/workflows/file-backup.json +0 -21
  137. package/.agent/workflows/get-ip-notify.json +0 -32
  138. package/.agent/workflows/news-aggregator.json +0 -93
  139. package/.agent/workflows/news-dashboard-v2.json +0 -94
  140. package/.agent/workflows/notification-batch.json +0 -32
  141. package/src/core/session-context.js +0 -346
  142. package/src/core/session-storage.js +0 -295
@@ -6,7 +6,7 @@ const chalk = require('chalk').default;
6
6
  const figlet = require('figlet');
7
7
  const { CLEAR_LINE, CYAN, DIM, GREEN, RED, YELLOW, colored } = require('../utils/ansi');
8
8
  const { TUI, ProcessTerminal, Editor, Text, CombinedAutocompleteProvider, matchesKey, Container } = require('@earendil-works/pi-tui');
9
- const { cleanResponse } = require('../../../src/utils');
9
+ const { cleanResponse, logger } = require('../../../src/utils');
10
10
  const { logEmitter } = require('../../../src/utils/logger');
11
11
  const { renderLine } = require('../utils/markdown');
12
12
  const { MessageBubble } = require('./message-bubble');
@@ -89,12 +89,24 @@ class ChatUI {
89
89
  // 会话管理
90
90
  this.sessionId = options.sessionId || 'cli_default';
91
91
  this.sessionPlugin = null;
92
+
93
+ // 获取 skill 命令列表
94
+ const skillCommands = [];
95
+ if (agent.framework) {
96
+ const extExecutor = agent.framework.pluginManager?.get('extension-executor');
97
+ if (extExecutor && typeof extExecutor.getSkillCommands === 'function') {
98
+ skillCommands.push(...extExecutor.getSkillCommands());
99
+ }
100
+ }
101
+
102
+ const baseCommands = [
103
+ { name: "compress", description: "压缩记录" },
104
+ { name: "clear", description: "清除记录" },
105
+ { name: "exit", description: "退出" },
106
+ ];
107
+
92
108
  const autocompleteProvider = new CombinedAutocompleteProvider(
93
- [
94
- { name: "compress", description: "压缩记录" },
95
- { name: "clear", description: "清除记录" },
96
- { name: "exit", description: "退出" },
97
- ],
109
+ [...baseCommands, ...skillCommands],
98
110
  process.cwd(),
99
111
  );
100
112
 
@@ -176,18 +188,19 @@ class ChatUI {
176
188
  this._setupSessionListeners();
177
189
  const level_dict={
178
190
  DEBUG: 'cyan',
179
- // INFO: 'dim',
191
+ INFO: 'dim',
192
+ LOG: 'dim',
180
193
  WARN: 'yellow',
181
194
  ERROR: 'red',
182
195
  }
183
196
  // 监听错误日志,显示到 tooler
184
- // this._logHandler = (data) => {
185
- // if(!Object.keys(level_dict).includes(data.level))return;
186
- // const level=folikoTerracotta(`[${data.level}]`)
187
- // const level_key=level_dict[data.level]||'dim'
188
- // this.notifier.show(`${level} ${chalk[level_key](data.message)}`);
189
- // };
190
- // logEmitter.on('log', this._logHandler);
197
+ this._logHandler = (data) => {
198
+ if(!Object.keys(level_dict).includes(data.level))return;
199
+ const level=folikoTerracotta(`[${data.level}]`)
200
+ const level_key=level_dict[data.level]||'dim'
201
+ this.statusBar.notifier.show(`${level} ${chalk[level_key](data.message)}`)
202
+ };
203
+ logger.on('log', this._logHandler);
191
204
 
192
205
  // 监听通知事件,显示到通知区域
193
206
  this._notificationHandler = (data) => {
@@ -230,7 +243,7 @@ class ChatUI {
230
243
  this._streamBufferTimer = null;
231
244
  }
232
245
  if (this._logHandler && this.agent.framework) {
233
- logEmitter.off('log', this._logHandler);
246
+ logger.off('log', this._logHandler);
234
247
  this._logHandler = null;
235
248
  }
236
249
  if (this._notificationHandler && this.agent.framework) {
@@ -270,6 +283,106 @@ class ChatUI {
270
283
  return
271
284
  }
272
285
 
286
+ /**
287
+ * 统一命令执行入口
288
+ */
289
+ async _executeCommand(trimmed) {
290
+ // 基础命令
291
+ const cmd = trimmed.toLowerCase();
292
+ if (cmd === '/clear') {
293
+ this._clearContext()
294
+ this.create_message(`${colored('[提示]', CYAN)} 对话上下文已清除\n`,chalk.dim('● '))
295
+ return true;
296
+ }
297
+ if (cmd === '/compress') {
298
+ this._compressContext()
299
+ return true;
300
+ }
301
+ if (cmd === '/exit') {
302
+ this.create_message(`${colored('[再见]', CYAN)} 感谢使用 Foliko!\n`,chalk.dim('● '))
303
+ this.tui.stop();
304
+ setTimeout(() => process.exit(0), 500);
305
+ return true;
306
+ }
307
+
308
+ // /help 命令显示所有注册的命令
309
+ if (cmd === '/help') {
310
+ const { getCommandRegistry } = require('../../../src/core/command-registry');
311
+ const registry = getCommandRegistry();
312
+ const commands = registry.getAllCommands();
313
+
314
+ let helpText = `${colored('[帮助]', CYAN)} 可用命令:\n`;
315
+ helpText += ` ${colored('/clear', CYAN)} - 清除对话上下文\n`;
316
+ helpText += ` ${colored('/compress', CYAN)} - 压缩上下文\n`;
317
+ helpText += ` ${colored('/exit', CYAN)} - 退出\n`;
318
+
319
+ // 添加 skill 命令
320
+ const extExecutor = this.agent.framework?.pluginManager?.get('extension-executor');
321
+ if (extExecutor && typeof extExecutor.getSkillCommandsHelp === 'function') {
322
+ const skillHelp = extExecutor.getSkillCommandsHelp();
323
+ if (skillHelp) {
324
+ helpText += `\n${colored('[技能命令]', CYAN)}\n`;
325
+ helpText += skillHelp.split('\n').map(line => ` ${line}`).join('\n') + '\n';
326
+ }
327
+ }
328
+
329
+ if (commands.length > 0) {
330
+ helpText += `\n${colored('[扩展命令]', CYAN)}\n`;
331
+ for (const cmd of commands) {
332
+ const pluginTag = cmd.registeredBy ? ` [${cmd.registeredBy}]` : '';
333
+ helpText += ` ${colored('/' + cmd.name, CYAN)}${pluginTag} - ${cmd.description || '无描述'}\n`;
334
+ }
335
+ }
336
+ this.create_message(helpText, chalk.dim('● '));
337
+ return true;
338
+ }
339
+
340
+ // 尝试通过 CommandRegistry 执行命令
341
+ const cmdName = trimmed.slice(1).split(' ')[0];
342
+ const cmdArgs = trimmed.slice(cmdName.length + 2);
343
+ if (trimmed.startsWith('/') && cmdName) {
344
+ // 检查 skill 命令 (格式: skillname:cmdname)
345
+ if (cmdName.includes(':')) {
346
+ try {
347
+ const result = await this.agent.framework.executeTool('ext_call', {
348
+ plugin: 'skill',
349
+ tool: cmdName,
350
+ args: { args: cmdArgs }
351
+ });
352
+ if (result.success !== false) {
353
+ this.create_message(`${colored('[结果]', CYAN)} ${result.data || result}\n`, chalk.dim('● '));
354
+ return true;
355
+ }
356
+ } catch (err) {
357
+ log.warn('Skill command failed:', err.message);
358
+ }
359
+ }
360
+
361
+ // 检查 CommandRegistry 中的命令
362
+ const { getCommandRegistry } = require('../../../src/core/command-registry');
363
+ const registry = getCommandRegistry();
364
+ const cmd = registry.getCommand(cmdName);
365
+ if (cmd) {
366
+ try {
367
+ const context = {
368
+ sessionId: this.sessionId,
369
+ agent: this.agent,
370
+ ui: this,
371
+ framework: this.agent.framework,
372
+ };
373
+ registry.execute(cmdName, cmdArgs, context).catch(err => {
374
+ this.create_message(`${colored('[命令错误]', 'red')} ${err.message}\n`, chalk.dim('● '));
375
+ });
376
+ } catch (err) {
377
+ this.create_message(`${colored('[命令错误]', 'red')} ${err.message}\n`, chalk.dim('● '));
378
+ }
379
+ return true;
380
+ }
381
+ }
382
+
383
+ return false;
384
+ }
385
+
273
386
  async handleOnSubmit(value){
274
387
  try{
275
388
  if (this.isResponding) {
@@ -280,21 +393,8 @@ class ChatUI {
280
393
  return;
281
394
  }
282
395
 
283
- // 处理快捷命令
284
- const cmd = trimmed.toLowerCase();
285
- if (cmd === '/clear') {
286
- this._clearContext()
287
- this.create_message(`${colored('[提示]', CYAN)} 对话上下文已清除\n`,chalk.dim('● '))
288
- return;
289
- }
290
- if (cmd === '/compress') {
291
- this._compressContext()
292
- return;
293
- }
294
- if (cmd === '/exit') {
295
- this.create_message(`${colored('[再见]', CYAN)} 感谢使用 Foliko!\n`,chalk.dim('● '))
296
- this.tui.stop();
297
- setTimeout(() => process.exit(0), 500);
396
+ // 尝试执行命令
397
+ if (await this._executeCommand(trimmed)) {
298
398
  return;
299
399
  }
300
400
 
@@ -333,6 +433,11 @@ class ChatUI {
333
433
 
334
434
  const { sessionId } = this;
335
435
 
436
+ // Clear ChatSession message store (memory + file)
437
+ if (this.agent._chatSession) {
438
+ this.agent._chatSession.clearSessionMessages(sessionId, true);
439
+ }
440
+
336
441
  // 1. 清除 AgentChatHandler 的消息存储(需要传 sessionId)
337
442
  if (this.agent._chatHandler) {
338
443
  this.agent._chatHandler.clearHistory(sessionId);
@@ -343,21 +448,29 @@ class ChatUI {
343
448
  const sessionCtx = this.agent.framework.getSessionContext(sessionId);
344
449
  if (sessionCtx) {
345
450
  sessionCtx.clearMessages();
346
- sessionCtx.compressionState.count = 0;
347
- sessionCtx.metadata.compressionCount = 0;
451
+ if (sessionCtx.compressionState) {
452
+ sessionCtx.compressionState.count = 0;
453
+ }
454
+ if (sessionCtx.metadata) {
455
+ sessionCtx.metadata.compressionCount = 0;
456
+ }
348
457
  }
349
458
  // 同步清除 framework 缓存的 sessionContexts
350
459
  const cachedCtx = this.agent.framework._sessionContexts?.get(sessionId);
351
460
  if (cachedCtx) {
352
461
  cachedCtx.clearMessages();
353
- cachedCtx.compressionState.count = 0;
354
- cachedCtx.metadata.compressionCount = 0;
462
+ if (cachedCtx.compressionState) {
463
+ cachedCtx.compressionState.count = 0;
464
+ }
465
+ if (cachedCtx.metadata) {
466
+ cachedCtx.metadata.compressionCount = 0;
467
+ }
355
468
  }
356
469
  // 清除 SessionPlugin 中的消息
357
470
  if (this.sessionPlugin) {
358
- const session = this.sessionPlugin.getSession(sessionId);
359
- if (session) {
360
- session.messages = [];
471
+ const manager = this.sessionPlugin._getSessionManager(sessionId);
472
+ if (manager) {
473
+ manager.clearMessages();
361
474
  }
362
475
  }
363
476
  }
@@ -511,7 +624,8 @@ class ChatUI {
511
624
  if (resultObj && resultObj.diff) {
512
625
  const diffContent = renderDiffWithHeader(resultObj.diff, resultObj.filePath);
513
626
  const bgColor = chalk.bgHex('#1a1a2e');
514
- this.create_message(diffContent, chalk.yellow(''), true, (line) => bgColor(line));
627
+ this._currentBotMessage.appendContent(['\n',diffContent,'\n\n'].join(''));
628
+ // this.create_message(diffContent, chalk.yellow('▸ '), true, (line) => bgColor(line));
515
629
  this.statusBar.tooler.show(`${chalk.green('[Diff]')} ${folikoGold(resultObj.filePath)}`);
516
630
  }
517
631
  }
@@ -117,7 +117,7 @@ class FooterBar {
117
117
 
118
118
  /**
119
119
  * 从 agent 刷新数据
120
- * 从 messageStore 获取最新一次调用的用量,计算增量后累加
120
+ * 从 SessionManager 获取最新一次调用的用量,计算增量后累加
121
121
  */
122
122
  refreshFromAgent() {
123
123
  try {
@@ -126,14 +126,9 @@ class FooterBar {
126
126
 
127
127
  const sessionId = 'cli_default';
128
128
 
129
- // 主动加载历史记录(确保从 SessionContext/文件加载历史消息)
130
- chatHandler._chatSession.loadHistory(sessionId);
131
-
132
- const messageStore = chatHandler._chatSession.getSessionMessageStore(sessionId);
133
- if (!messageStore) return;
134
-
135
129
  // 1. Token 用量:计算与上次记录的增量
136
- if (messageStore.usage) {
130
+ const messageStore = chatHandler._chatSession.getSessionMessageStore(sessionId);
131
+ if (messageStore && messageStore.usage) {
137
132
  const u = messageStore.usage;
138
133
  const inputTokens = u.promptTokens || u.prompt_tokens || 0;
139
134
  const outputTokens = u.completionTokens || u.completion_tokens || 0;
@@ -153,12 +148,16 @@ class FooterBar {
153
148
  this._lastUsage = { inputTokens, outputTokens };
154
149
  }
155
150
 
156
- // 2. 上下文 token 估算(使用 TokenCounter
157
- if (messageStore.messages && messageStore.messages.length > 0) {
158
- const msgTokens = this._tokenCounter.countMessages(messageStore.messages);
159
- this._stats.contextTokens = msgTokens;
160
- if (this._stats.maxContextTokens > 0) {
161
- this._stats.contextPercent = Math.min(100, (msgTokens / this._stats.maxContextTokens) * 100);
151
+ // 2. 上下文 token 估算(使用 SessionManager
152
+ const sessionCtx = this.agent.framework?.getSessionContext(sessionId);
153
+ if (sessionCtx && typeof sessionCtx.getMessages === 'function') {
154
+ const messages = sessionCtx.getMessages();
155
+ if (messages && messages.length > 0) {
156
+ const msgTokens = this._tokenCounter.countMessages(messages);
157
+ this._stats.contextTokens = msgTokens;
158
+ if (this._stats.maxContextTokens > 0) {
159
+ this._stats.contextPercent = Math.min(100, (msgTokens / this._stats.maxContextTokens) * 100);
160
+ }
162
161
  }
163
162
  }
164
163
 
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Foliko 公共配置
3
+ */
4
+
5
+ // 配置目录名(统一管理,方便改名)
6
+ const AGENT_DIR_NAME = '.foliko';
7
+
8
+ // 其他配置目录
9
+ const AGENT_SUBDIRS = {
10
+ AGENTS: 'agents',
11
+ PLUGINS: 'plugins',
12
+ SKILLS: 'skills',
13
+ DATA: 'data',
14
+ SESSIONS: 'sessions',
15
+ LOGS: 'logs',
16
+ MCP_CONFIG: 'mcp_config.json',
17
+ RULES: 'rules',
18
+ };
19
+
20
+ module.exports = {
21
+ AGENT_DIR_NAME,
22
+ AGENT_SUBDIRS,
23
+ getAgentDir: () => AGENT_DIR_NAME,
24
+ getAgentsDir: () => `${AGENT_DIR_NAME}/${AGENT_SUBDIRS.AGENTS}`,
25
+ getPluginsDir: () => `${AGENT_DIR_NAME}/${AGENT_SUBDIRS.PLUGINS}`,
26
+ getDataDir: () => `${AGENT_DIR_NAME}/${AGENT_SUBDIRS.DATA}`,
27
+ getSessionsDir: () => `${AGENT_DIR_NAME}/${AGENT_SUBDIRS.SESSIONS}`,
28
+ getLogsDir: () => `${AGENT_DIR_NAME}/${AGENT_SUBDIRS.LOGS}`,
29
+ };
@@ -16,7 +16,7 @@ const IGNORE_PATTERNS = [
16
16
  '*.lock',
17
17
  '*.bak',
18
18
  '.claude',
19
- '.agent',
19
+ '.foliko',
20
20
  'examples',
21
21
  'dist',
22
22
  'build',
@@ -1,33 +1,33 @@
1
- # ========== Foliko Docker Compose ==========
2
- # 使用方式: docker-compose up -d
3
-
4
- services:
5
- foliko:
6
- build: .
7
- container_name: foliko-agent
8
- restart: unless-stopped
9
- ports:
10
- - '3000:3000'
11
- environment:
12
- # AI 配置
13
- - FOLIKO_PROVIDER=${FOLIKO_PROVIDER:-minimax}
14
- - FOLIKO_MODEL=${FOLIKO_MODEL:-}
15
- - FOLIKO_BASE_URL=${FOLIKO_BASE_URL:-}
16
- - FOLIKO_API_KEY=${FOLIKO_API_KEY:-}
17
- # Web 服务配置
18
- - WEB_PORT=3000
19
- - WEB_HOST=0.0.0.0
20
- - WEB_BASE_URL=${WEB_BASE_URL:-}
21
- # Telegram 配置(可选)
22
- - TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN:-}
23
- # 飞书配置(可选)
24
- - FEISHU_APP_ID=${FEISHU_APP_ID:-}
25
- - FEISHU_APP_SECRET=${FEISHU_APP_SECRET:-}
26
- volumes:
27
- # 持久化数据
28
- - foliko-data:/app/.agent/data
29
- tty: true
30
- stdin_open: true
31
-
32
- volumes:
33
- foliko-data:
1
+ # ========== Foliko Docker Compose ==========
2
+ # 使用方式: docker-compose up -d
3
+
4
+ services:
5
+ foliko:
6
+ build: .
7
+ container_name: foliko-agent
8
+ restart: unless-stopped
9
+ ports:
10
+ - '3000:3000'
11
+ environment:
12
+ # AI 配置
13
+ - FOLIKO_PROVIDER=${FOLIKO_PROVIDER:-minimax}
14
+ - FOLIKO_MODEL=${FOLIKO_MODEL:-}
15
+ - FOLIKO_BASE_URL=${FOLIKO_BASE_URL:-}
16
+ - FOLIKO_API_KEY=${FOLIKO_API_KEY:-}
17
+ # Web 服务配置
18
+ - WEB_PORT=3000
19
+ - WEB_HOST=0.0.0.0
20
+ - WEB_BASE_URL=${WEB_BASE_URL:-}
21
+ # Telegram 配置(可选)
22
+ - TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN:-}
23
+ # 飞书配置(可选)
24
+ - FEISHU_APP_ID=${FEISHU_APP_ID:-}
25
+ - FEISHU_APP_SECRET=${FEISHU_APP_SECRET:-}
26
+ volumes:
27
+ # 持久化数据
28
+ - foliko-data:/app/.foliko/data
29
+ tty: true
30
+ stdin_open: true
31
+
32
+ volumes:
33
+ foliko-data:
package/docs/features.md CHANGED
@@ -1,120 +1,120 @@
1
- # Foliko 功能点清单
2
-
3
- ## 1. AI 对话
4
-
5
- | 功能 | 说明 |
6
- | ----------- | --------------------------------------- |
7
- | 流式输出 | 实时流式响应 |
8
- | 多 Provider | minimax / deepseek / openai / anthropic |
9
- | 模型配置 | 支持自定义 model、baseURL、apiKey |
10
- | 系统提示词 | 支持 sharedPrompt 模板变量 |
11
- | 思考过程 | 可选的 think 插件显示推理 |
12
-
13
- ## 2. 工具系统
14
-
15
- | 功能 | 说明 |
16
- | ------------------------ | --------------------------- |
17
- | `Bash` | 执行 Shell/Bash 命令 |
18
- | `Read` | 读取文件内容 |
19
- | `Write` | 写入文件 |
20
- | `Edit` | 编辑文件(diff 替换) |
21
- | `Glob` | 按模式搜索文件 |
22
- | `Grep` | 文件内容搜索 |
23
- | `python` | 执行 Python 代码 |
24
- | `execute_workflow` | 执行工作流 |
25
- | `loadSkill/reloadSkills` | 技能加载与重载 |
26
- | `reloadWorkflows` | 工作流重载 |
27
- | MCP 工具 | Model Context Protocol 集成 |
28
-
29
- ## 3. 插件系统
30
-
31
- | 功能 | 说明 |
32
- | ------------ | ------------------------------------ |
33
- | 插件目录 | `.agent/plugins/` 自动加载 |
34
- | 插件生命周期 | install / start / reload / uninstall |
35
- | 工具注册 | 插件可注册工具到 Agent |
36
- | 事件系统 | 插件间通过事件通信 |
37
- | 状态持久化 | 插件配置保存到 JSON |
38
- | 优先级控制 | priority 决定加载顺序 |
39
-
40
- ## 4. 工作流引擎
41
-
42
- | 功能 | 说明 |
43
- | ----------- | ------------------------------- |
44
- | `script` | JavaScript 脚本执行 |
45
- | `loop` | 循环(maxIterations) |
46
- | `condition` | 条件分支 |
47
- | `delay` | 延时等待 |
48
- | `parallel` | 并行执行 |
49
- | 上下文共享 | variables / input / stepResults |
50
- | 目录加载 | `.agent/workflows/` 自动注册 |
51
-
52
- ## 5. 技能系统
53
-
54
- | 功能 | 说明 |
55
- | -------- | ---------------------------- |
56
- | 技能目录 | `skills/` + `.agent/skills/` |
57
- | SKILL.md | frontmatter 元数据格式 |
58
- | 自动发现 | 递归扫描子目录 |
59
- | 工具过滤 | allowed-tools 限制可用工具 |
60
- | 重载支持 | reloadSkills 动态加载 |
61
-
62
- ## 6. 会话管理
63
-
64
- | 功能 | 说明 |
65
- | ------------- | ------------------------- |
66
- | SessionPlugin | 统一会话历史管理 |
67
- | 多会话 | 按 sessionId 隔离 |
68
- | 消息持久化 | JSON 文件存储 |
69
- | 元数据 | 支持 platform / userId 等 |
70
- | 会话事件 | session:created / deleted |
71
-
72
- ## 7. 子 Agent
73
-
74
- | 功能 | 说明 |
75
- | ----------- | --------------------------- |
76
- | 子Agent配置 | `.agent/agents/*.json/*.md` |
77
- | 角色定义 | role / description |
78
- | 工具继承 | parentTools 指定可用工具 |
79
- | 工具路由 | 自动匹配最合适 Agent |
80
- | 协作执行 | 支持多 Agent 分工 |
81
-
82
- ## 8. 通讯插件
83
-
84
- | 功能 | 说明 |
85
- | -------- | -------------------------------- |
86
- | Telegram | Bot Token / 群组模式 / 命令前缀 |
87
- | 微信 | WebSocket 登录 / 二维码 |
88
- | 飞书 | WS 长连接 / 事件订阅 |
89
- | 邮件 | IMAP 读取 / SMTP 发送 / 163 兼容 |
90
-
91
- ## 9. 执行器
92
-
93
- | 功能 | 说明 |
94
- | -------------- | ---------------------- |
95
- | ShellExecutor | system 命令执行 |
96
- | PythonExecutor | Python 3 代码执行 |
97
- | 超时控制 | 可配置 maxDuration |
98
- | 结果返回 | stdout/stderr/exitCode |
99
-
100
- ## 10. Web 服务
101
-
102
- | 功能 | 说明 |
103
- | ---------------------- | --------------------------------- |
104
- | `web_start` | 启动 HTTP 服务器 |
105
- | `web_stop` | 停止 HTTP 服务器 |
106
- | `web_register_route` | 注册 HTTP 路由 |
107
- | `web_register_webhook` | 注册 Webhook(数据交给 LLM 处理) |
108
- | `web_list_routes` | 列出所有路由和 Webhook |
109
- | 路由参数 | 支持 `/user/:id` 路径参数 |
110
- | Webhook LLM | 接收数据后转发给 LLM 处理 |
111
-
112
- ## 11. 其他内置插件
113
-
114
- | 功能 | 说明 |
115
- | ----------- | ------------------- |
116
- | `scheduler` | 定时任务 / 循环调度 |
117
- | `rules` | 规则引擎 / 条件触发 |
118
- | `storage` | 键值存储 |
119
- | `audit` | 操作审计日志 |
120
- | `install` | 插件安装工具 |
1
+ # Foliko 功能点清单
2
+
3
+ ## 1. AI 对话
4
+
5
+ | 功能 | 说明 |
6
+ | ----------- | --------------------------------------- |
7
+ | 流式输出 | 实时流式响应 |
8
+ | 多 Provider | minimax / deepseek / openai / anthropic |
9
+ | 模型配置 | 支持自定义 model、baseURL、apiKey |
10
+ | 系统提示词 | 支持 sharedPrompt 模板变量 |
11
+ | 思考过程 | 可选的 think 插件显示推理 |
12
+
13
+ ## 2. 工具系统
14
+
15
+ | 功能 | 说明 |
16
+ | ------------------------ | --------------------------- |
17
+ | `Bash` | 执行 Shell/Bash 命令 |
18
+ | `Read` | 读取文件内容 |
19
+ | `Write` | 写入文件 |
20
+ | `Edit` | 编辑文件(diff 替换) |
21
+ | `Glob` | 按模式搜索文件 |
22
+ | `Grep` | 文件内容搜索 |
23
+ | `python` | 执行 Python 代码 |
24
+ | `execute_workflow` | 执行工作流 |
25
+ | `loadSkill/reloadSkills` | 技能加载与重载 |
26
+ | `reloadWorkflows` | 工作流重载 |
27
+ | MCP 工具 | Model Context Protocol 集成 |
28
+
29
+ ## 3. 插件系统
30
+
31
+ | 功能 | 说明 |
32
+ | ------------ | ------------------------------------ |
33
+ | 插件目录 | `.foliko/plugins/` 自动加载 |
34
+ | 插件生命周期 | install / start / reload / uninstall |
35
+ | 工具注册 | 插件可注册工具到 Agent |
36
+ | 事件系统 | 插件间通过事件通信 |
37
+ | 状态持久化 | 插件配置保存到 JSON |
38
+ | 优先级控制 | priority 决定加载顺序 |
39
+
40
+ ## 4. 工作流引擎
41
+
42
+ | 功能 | 说明 |
43
+ | ----------- | ------------------------------- |
44
+ | `script` | JavaScript 脚本执行 |
45
+ | `loop` | 循环(maxIterations) |
46
+ | `condition` | 条件分支 |
47
+ | `delay` | 延时等待 |
48
+ | `parallel` | 并行执行 |
49
+ | 上下文共享 | variables / input / stepResults |
50
+ | 目录加载 | `.foliko/workflows/` 自动注册 |
51
+
52
+ ## 5. 技能系统
53
+
54
+ | 功能 | 说明 |
55
+ | -------- | ---------------------------- |
56
+ | 技能目录 | `skills/` + `.foliko/skills/` |
57
+ | SKILL.md | frontmatter 元数据格式 |
58
+ | 自动发现 | 递归扫描子目录 |
59
+ | 工具过滤 | allowed-tools 限制可用工具 |
60
+ | 重载支持 | reloadSkills 动态加载 |
61
+
62
+ ## 6. 会话管理
63
+
64
+ | 功能 | 说明 |
65
+ | ------------- | ------------------------- |
66
+ | SessionPlugin | 统一会话历史管理 |
67
+ | 多会话 | 按 sessionId 隔离 |
68
+ | 消息持久化 | JSON 文件存储 |
69
+ | 元数据 | 支持 platform / userId 等 |
70
+ | 会话事件 | session:created / deleted |
71
+
72
+ ## 7. 子 Agent
73
+
74
+ | 功能 | 说明 |
75
+ | ----------- | --------------------------- |
76
+ | 子Agent配置 | `.foliko/agents/*.json/*.md` |
77
+ | 角色定义 | role / description |
78
+ | 工具继承 | parentTools 指定可用工具 |
79
+ | 工具路由 | 自动匹配最合适 Agent |
80
+ | 协作执行 | 支持多 Agent 分工 |
81
+
82
+ ## 8. 通讯插件
83
+
84
+ | 功能 | 说明 |
85
+ | -------- | -------------------------------- |
86
+ | Telegram | Bot Token / 群组模式 / 命令前缀 |
87
+ | 微信 | WebSocket 登录 / 二维码 |
88
+ | 飞书 | WS 长连接 / 事件订阅 |
89
+ | 邮件 | IMAP 读取 / SMTP 发送 / 163 兼容 |
90
+
91
+ ## 9. 执行器
92
+
93
+ | 功能 | 说明 |
94
+ | -------------- | ---------------------- |
95
+ | ShellExecutor | system 命令执行 |
96
+ | PythonExecutor | Python 3 代码执行 |
97
+ | 超时控制 | 可配置 maxDuration |
98
+ | 结果返回 | stdout/stderr/exitCode |
99
+
100
+ ## 10. Web 服务
101
+
102
+ | 功能 | 说明 |
103
+ | ---------------------- | --------------------------------- |
104
+ | `web_start` | 启动 HTTP 服务器 |
105
+ | `web_stop` | 停止 HTTP 服务器 |
106
+ | `web_register_route` | 注册 HTTP 路由 |
107
+ | `web_register_webhook` | 注册 Webhook(数据交给 LLM 处理) |
108
+ | `web_list_routes` | 列出所有路由和 Webhook |
109
+ | 路由参数 | 支持 `/user/:id` 路径参数 |
110
+ | Webhook LLM | 接收数据后转发给 LLM 处理 |
111
+
112
+ ## 11. 其他内置插件
113
+
114
+ | 功能 | 说明 |
115
+ | ----------- | ------------------- |
116
+ | `scheduler` | 定时任务 / 循环调度 |
117
+ | `rules` | 规则引擎 / 条件触发 |
118
+ | `storage` | 键值存储 |
119
+ | `audit` | 操作审计日志 |
120
+ | `install` | 插件安装工具 |