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.
- package/.claude/settings.local.json +19 -10
- package/.dockerignore +45 -45
- package/.env.example +56 -56
- package/CLAUDE.md +2 -2
- package/README.md +13 -13
- package/SPEC.md +3 -3
- package/cli/src/commands/chat.js +2 -20
- package/cli/src/commands/list.js +7 -6
- package/cli/src/commands/plugin.js +3 -2
- package/cli/src/daemon.js +2 -2
- package/cli/src/ui/chat-ui-old.js +15 -4
- package/cli/src/ui/chat-ui.js +152 -38
- package/cli/src/ui/footer-bar.js +13 -14
- package/cli/src/utils/config.js +29 -0
- package/cli/src/utils/plugin-config.js +1 -1
- package/docker-compose.yml +33 -33
- package/docs/features.md +120 -120
- package/docs/quick-reference.md +160 -160
- package/docs/user-manual.md +1391 -1391
- package/examples/ambient-example.js +2 -2
- package/examples/bootstrap.js +3 -3
- package/examples/test-chat.js +1 -1
- package/examples/test-reload.js +1 -1
- package/examples/test-telegram.js +1 -1
- package/examples/test-tg-bot.js +1 -1
- package/examples/test-tg-simple.js +2 -2
- package/examples/test-tg.js +1 -1
- package/examples/test-think.js +1 -1
- package/examples/test-weixin-feishu.js +3 -3
- package/package.json +3 -1
- package/plugins/ambient-agent/index.js +1 -1
- package/plugins/audit-plugin.js +75 -24
- package/plugins/default-plugins.js +21 -11
- package/plugins/email/index.js +1 -1
- package/plugins/extension-executor-plugin.js +85 -7
- package/plugins/feishu-plugin.js +118 -16
- package/plugins/install-plugin.js +4 -4
- package/plugins/memory-plugin.js +1 -1
- package/plugins/plugin-manager-plugin.js +3 -3
- package/plugins/python-executor-plugin.js +1 -1
- package/plugins/python-plugin-loader.js +1 -1
- package/plugins/qq-plugin.js +143 -16
- package/plugins/rules-plugin.js +1 -1
- package/plugins/scheduler-plugin.js +2 -2
- package/plugins/session-plugin.js +309 -393
- package/plugins/storage-plugin.js +235 -176
- package/plugins/subagent-plugin.js +4 -4
- package/plugins/telegram-plugin.js +116 -17
- package/plugins/think-plugin.js +1 -1
- package/plugins/web-plugin.js +2 -2
- package/plugins/weixin-plugin.js +102 -19
- package/skills/find-skills/AGENTS.md +2 -2
- package/skills/find-skills/SKILL.md +133 -133
- package/skills/foliko-dev/AGENTS.md +236 -236
- package/skills/foliko-dev/SKILL.md +19 -19
- package/skills/mcp-usage/SKILL.md +200 -200
- package/skills/plugin-guide/SKILL.md +4 -4
- package/skills/python-plugin-dev/SKILL.md +5 -5
- package/skills/skill-guide/SKILL.md +104 -6
- package/skills/subagent-guide/SKILL.md +237 -237
- package/skills/workflow-guide/SKILL.md +646 -646
- package/src/capabilities/skill-manager.js +101 -2
- package/src/capabilities/workflow-engine.js +1 -1
- package/src/core/agent-chat.js +17 -14
- package/src/core/branch-summary-auto.js +206 -0
- package/src/core/chat-session.js +38 -8
- package/src/core/command-registry.js +200 -0
- package/src/core/constants.js +11 -11
- package/src/core/context-compressor.js +700 -149
- package/src/core/context-manager.js +0 -1
- package/src/core/enhanced-context-compressor.js +210 -0
- package/src/core/framework.js +140 -83
- package/src/core/jsonl-storage.js +253 -0
- package/src/core/plugin-manager.js +15 -10
- package/src/core/provider-registry.js +159 -0
- package/src/core/provider.js +2 -0
- package/src/core/session-entry.js +225 -0
- package/src/core/session-manager.js +701 -0
- package/src/core/storage-manager.js +494 -0
- package/src/core/sub-agent-config.js +1 -1
- package/src/core/token-counter.js +177 -58
- package/src/core/ui-extension-context.js +174 -0
- package/src/executors/mcp-executor.js +15 -6
- package/src/utils/logger.js +152 -180
- package/src/utils/plugin-helpers.js +2 -2
- package/website_v2/docs/api.html +1 -1
- package/website_v2/docs/configuration.html +2 -2
- package/website_v2/docs/plugin-development.html +4 -4
- package/website_v2/docs/project-structure.html +2 -2
- package/website_v2/docs/skill-development.html +2 -2
- package/website_v2/index.html +1 -1
- package/website_v2/styles/animations.css +7 -7
- package/.agent/agents/backend-dev.md +0 -102
- package/.agent/agents/data-analyst.md +0 -117
- package/.agent/agents/devops.md +0 -115
- package/.agent/agents/frontend-dev.md +0 -94
- package/.agent/agents/network-requester.md +0 -44
- package/.agent/agents/poster-designer.md +0 -52
- package/.agent/agents/product-manager.md +0 -85
- package/.agent/agents/qa-engineer.md +0 -100
- package/.agent/agents/security-engineer.md +0 -99
- package/.agent/agents/team-lead.md +0 -137
- package/.agent/agents/ui-designer.md +0 -116
- package/.agent/data/default.json +0 -58
- package/.agent/data/email/processed-emails.json +0 -1
- package/.agent/data/plugins-state.json +0 -207
- package/.agent/data/scheduler/tasks.json +0 -1
- package/.agent/data/web/web-config.json +0 -5
- package/.agent/data/weixin/images/file_1776188148383jpg +0 -0
- package/.agent/data/weixin/images/file_1776188458326.jpg +0 -0
- package/.agent/data/weixin/images/file_1776188689423.jpg +0 -0
- package/.agent/data/weixin/images/file_1776188813604.jpg +0 -0
- package/.agent/data/weixin/images/file_1776189097450.jpg +0 -0
- package/.agent/data/weixin/videos/file_1776188318431.mp4 +0 -0
- package/.agent/data/weixin.json +0 -6
- package/.agent/mcp_config.json +0 -14
- package/.agent/memory/user/mof6gk94-kneeuh.md +0 -9
- package/.agent/package.json +0 -8
- package/.agent/plugins/marknative/README.md +0 -134
- package/.agent/plugins/marknative/fonts/SegoeUI Emoji.ttf +0 -0
- package/.agent/plugins/marknative/fonts.zip +0 -0
- package/.agent/plugins/marknative/index.js +0 -256
- package/.agent/plugins/marknative/package.json +0 -12
- package/.agent/plugins/test-plugin.py +0 -99
- package/.agent/plugins.json +0 -14
- package/.agent/python-scripts/test_sample.py +0 -24
- package/.agent/sessions/cli_default.json +0 -4121
- package/.agent/skills/agent-browser/SKILL.md +0 -311
- package/.agent/skills/agent-browser/TEST_PLAN.md +0 -200
- package/.agent/skills/sysinfo/SKILL.md +0 -38
- package/.agent/skills/sysinfo/system-info.sh +0 -130
- package/.agent/skills/workflow/SKILL.md +0 -324
- package/.agent/test-agent.js +0 -35
- package/.agent/weixin.json +0 -6
- package/.agent/workflows/email-digest.json +0 -50
- package/.agent/workflows/file-backup.json +0 -21
- package/.agent/workflows/get-ip-notify.json +0 -32
- package/.agent/workflows/news-aggregator.json +0 -93
- package/.agent/workflows/news-dashboard-v2.json +0 -94
- package/.agent/workflows/notification-batch.json +0 -32
- package/src/core/session-context.js +0 -346
- package/src/core/session-storage.js +0 -295
package/cli/src/ui/chat-ui.js
CHANGED
|
@@ -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
|
-
|
|
191
|
+
INFO: 'dim',
|
|
192
|
+
LOG: 'dim',
|
|
180
193
|
WARN: 'yellow',
|
|
181
194
|
ERROR: 'red',
|
|
182
195
|
}
|
|
183
196
|
// 监听错误日志,显示到 tooler
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
347
|
-
|
|
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
|
|
354
|
-
|
|
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
|
|
359
|
-
if (
|
|
360
|
-
|
|
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.
|
|
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
|
}
|
package/cli/src/ui/footer-bar.js
CHANGED
|
@@ -117,7 +117,7 @@ class FooterBar {
|
|
|
117
117
|
|
|
118
118
|
/**
|
|
119
119
|
* 从 agent 刷新数据
|
|
120
|
-
* 从
|
|
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
|
-
|
|
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 估算(使用
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
if (
|
|
161
|
-
|
|
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
|
+
};
|
package/docker-compose.yml
CHANGED
|
@@ -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/.
|
|
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
|
-
| 插件目录 | `.
|
|
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
|
-
| 目录加载 | `.
|
|
51
|
-
|
|
52
|
-
## 5. 技能系统
|
|
53
|
-
|
|
54
|
-
| 功能 | 说明 |
|
|
55
|
-
| -------- | ---------------------------- |
|
|
56
|
-
| 技能目录 | `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配置 | `.
|
|
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` | 插件安装工具 |
|