foliko 1.1.67 → 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 +236 -203
- package/cli/src/ui/footer-bar.js +20 -46
- package/cli/src/ui/message-bubble.js +24 -2
- package/cli/src/ui/status-bar.js +177 -0
- 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 +84 -29
- package/plugins/coordinator-plugin.js +14 -12
- package/plugins/data-splitter-plugin.js +323 -0
- package/plugins/default-plugins.js +23 -12
- package/plugins/email/index.js +1 -1
- package/plugins/extension-executor-plugin.js +87 -9
- package/plugins/feishu-plugin.js +118 -16
- package/plugins/file-system-plugin.js +68 -50
- package/plugins/gate-trading.js +10 -10
- package/plugins/install-plugin.js +7 -7
- package/plugins/memory-plugin.js +9 -12
- package/plugins/plugin-manager-plugin.js +12 -14
- package/plugins/python-executor-plugin.js +1 -1
- package/plugins/python-plugin-loader.js +1 -1
- package/plugins/qq-plugin.js +151 -24
- package/plugins/rules-plugin.js +8 -8
- package/plugins/scheduler-plugin.js +24 -20
- package/plugins/session-plugin.js +313 -397
- package/plugins/storage-plugin.js +235 -175
- package/plugins/subagent-plugin.js +17 -13
- package/plugins/telegram-plugin.js +116 -17
- package/plugins/think-plugin.js +64 -60
- package/plugins/tools-plugin.js +8 -8
- package/plugins/web-plugin.js +2 -2
- package/plugins/weixin-plugin.js +107 -24
- 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 +124 -17
- package/src/capabilities/workflow-engine.js +3 -3
- package/src/core/agent-chat.js +72 -26
- package/src/core/agent.js +17 -27
- package/src/core/branch-summary-auto.js +206 -0
- package/src/core/chat-session.js +45 -169
- package/src/core/command-registry.js +200 -0
- package/src/core/constants.js +198 -0
- package/src/core/context-compressor.js +702 -326
- package/src/core/context-manager.js +0 -1
- package/src/core/enhanced-context-compressor.js +210 -0
- package/src/core/framework.js +260 -84
- package/src/core/jsonl-storage.js +253 -0
- package/src/core/plugin-base.js +7 -5
- 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/subagent.js +16 -135
- package/src/core/token-counter.js +177 -58
- package/src/core/tool-executor.js +2 -70
- package/src/core/ui-extension-context.js +174 -0
- package/src/executors/mcp-executor.js +27 -16
- package/src/utils/chat-queue.js +11 -22
- package/src/utils/data-splitter.js +345 -0
- package/src/utils/logger.js +152 -180
- package/src/utils/message-validator.js +283 -0
- package/src/utils/plugin-helpers.js +2 -2
- package/src/utils/retry.js +168 -22
- 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 -199
- 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 -247
- 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/footer-bar.js
CHANGED
|
@@ -6,12 +6,13 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
const chalk = require('chalk').default;
|
|
9
|
+
const { visibleWidth, truncateToWidth } = require('@earendil-works/pi-tui');
|
|
9
10
|
const { TokenCounter } = require('../../../src/core/token-counter');
|
|
10
11
|
|
|
11
12
|
// Foliko 配色
|
|
12
13
|
const folikoDim = chalk.hex('#6B7280');
|
|
13
14
|
const folikoAccent = chalk.hex('#2A9D8F');
|
|
14
|
-
const folikoGold = chalk.hex('#
|
|
15
|
+
const folikoGold = chalk.hex('#999a9c');
|
|
15
16
|
|
|
16
17
|
class FooterBar {
|
|
17
18
|
/**
|
|
@@ -116,7 +117,7 @@ class FooterBar {
|
|
|
116
117
|
|
|
117
118
|
/**
|
|
118
119
|
* 从 agent 刷新数据
|
|
119
|
-
* 从
|
|
120
|
+
* 从 SessionManager 获取最新一次调用的用量,计算增量后累加
|
|
120
121
|
*/
|
|
121
122
|
refreshFromAgent() {
|
|
122
123
|
try {
|
|
@@ -125,14 +126,9 @@ class FooterBar {
|
|
|
125
126
|
|
|
126
127
|
const sessionId = 'cli_default';
|
|
127
128
|
|
|
128
|
-
// 主动加载历史记录(确保从 SessionContext/文件加载历史消息)
|
|
129
|
-
chatHandler._chatSession.loadHistory(sessionId);
|
|
130
|
-
|
|
131
|
-
const messageStore = chatHandler._chatSession.getSessionMessageStore(sessionId);
|
|
132
|
-
if (!messageStore) return;
|
|
133
|
-
|
|
134
129
|
// 1. Token 用量:计算与上次记录的增量
|
|
135
|
-
|
|
130
|
+
const messageStore = chatHandler._chatSession.getSessionMessageStore(sessionId);
|
|
131
|
+
if (messageStore && messageStore.usage) {
|
|
136
132
|
const u = messageStore.usage;
|
|
137
133
|
const inputTokens = u.promptTokens || u.prompt_tokens || 0;
|
|
138
134
|
const outputTokens = u.completionTokens || u.completion_tokens || 0;
|
|
@@ -152,12 +148,16 @@ class FooterBar {
|
|
|
152
148
|
this._lastUsage = { inputTokens, outputTokens };
|
|
153
149
|
}
|
|
154
150
|
|
|
155
|
-
// 2. 上下文 token 估算(使用
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
if (
|
|
160
|
-
|
|
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
|
+
}
|
|
161
161
|
}
|
|
162
162
|
}
|
|
163
163
|
|
|
@@ -182,10 +182,10 @@ class FooterBar {
|
|
|
182
182
|
const parts = [];
|
|
183
183
|
|
|
184
184
|
// ↑ input tokens
|
|
185
|
-
parts.push(
|
|
185
|
+
parts.push(chalk.dim(`↑${this._formatNum(s.inputTokens)}`));
|
|
186
186
|
|
|
187
187
|
// ↓ output tokens
|
|
188
|
-
parts.push(
|
|
188
|
+
parts.push(chalk.dim(`↓${this._formatNum(s.outputTokens)}`));
|
|
189
189
|
|
|
190
190
|
// $ cost
|
|
191
191
|
if (s.cost > 0) {
|
|
@@ -212,7 +212,7 @@ class FooterBar {
|
|
|
212
212
|
let line = parts.join(' ');
|
|
213
213
|
|
|
214
214
|
// 计算实际显示宽度(去除 ANSI 编码)
|
|
215
|
-
const visibleLen = visibleWidth
|
|
215
|
+
const visibleLen = visibleWidth(line);
|
|
216
216
|
|
|
217
217
|
// 如果太长,缩短模型名
|
|
218
218
|
if (visibleLen > width) {
|
|
@@ -226,38 +226,12 @@ class FooterBar {
|
|
|
226
226
|
}
|
|
227
227
|
|
|
228
228
|
// 截断到可用宽度
|
|
229
|
-
if (visibleWidth
|
|
230
|
-
line = truncateToWidth
|
|
229
|
+
if (visibleWidth(line) > width) {
|
|
230
|
+
line = truncateToWidth(line, width);
|
|
231
231
|
}
|
|
232
232
|
|
|
233
233
|
return [line];
|
|
234
234
|
}
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
-
function visibleWidth(text) {
|
|
238
|
-
// 简易 ANSI 不可见宽度计算
|
|
239
|
-
const stripped = text.replace(/\x1B\[[0-9;]*m/g, '');
|
|
240
|
-
return stripped.length;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
function truncateToWidth(text, maxWidth) {
|
|
244
|
-
const stripped = text.replace(/\x1B\[[0-9;]*m/g, '');
|
|
245
|
-
if (stripped.length <= maxWidth) return text;
|
|
246
|
-
|
|
247
|
-
// 需要截断,保留 ANSI 编码不变
|
|
248
|
-
let result = '';
|
|
249
|
-
let visLen = 0;
|
|
250
|
-
const regex = /(\x1B\[[0-9;]*m)|(.)/g;
|
|
251
|
-
let match;
|
|
252
|
-
while ((match = regex.exec(text)) !== null && visLen < maxWidth) {
|
|
253
|
-
if (match[1]) {
|
|
254
|
-
result += match[1];
|
|
255
|
-
} else {
|
|
256
|
-
result += match[2];
|
|
257
|
-
visLen++;
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
return result;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
237
|
module.exports = { FooterBar };
|
|
@@ -28,11 +28,22 @@ class MessageBubble {
|
|
|
28
28
|
this._cachedLines = null;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
/**
|
|
32
|
+
* 实现 pi-tui Component 的 invalidate 接口
|
|
33
|
+
* 主题变化时由 TUI 调用,清除所有缓存
|
|
34
|
+
*/
|
|
35
|
+
invalidate() {
|
|
36
|
+
this._cacheKey = null;
|
|
37
|
+
this._cachedLines = null;
|
|
38
|
+
if (this._markdown) {
|
|
39
|
+
this._markdown.invalidate?.();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
31
43
|
setContent(content) {
|
|
32
44
|
if (this.content !== content) {
|
|
33
45
|
this.content = content;
|
|
34
|
-
this.
|
|
35
|
-
this._cachedLines = null;
|
|
46
|
+
this.invalidate();
|
|
36
47
|
}
|
|
37
48
|
}
|
|
38
49
|
|
|
@@ -41,6 +52,17 @@ class MessageBubble {
|
|
|
41
52
|
this.setContent(content);
|
|
42
53
|
}
|
|
43
54
|
|
|
55
|
+
/**
|
|
56
|
+
* 追加已渲染的内容(流式输出增量追加)
|
|
57
|
+
* 比 setText 更高效:跳过全量置换,只追加新内容并清缓存
|
|
58
|
+
* @param {string} renderedDelta - 新渲染的 ANSI 文本片段
|
|
59
|
+
*/
|
|
60
|
+
appendContent(renderedDelta) {
|
|
61
|
+
this.content += renderedDelta;
|
|
62
|
+
this._cacheKey = null;
|
|
63
|
+
this._cachedLines = null;
|
|
64
|
+
}
|
|
65
|
+
|
|
44
66
|
render(width) {
|
|
45
67
|
// 检查缓存
|
|
46
68
|
const cacheKey = `${width}:${this.content}`;
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StatusBar — 状态栏组件
|
|
3
|
+
*
|
|
4
|
+
* 封装三个状态槽位:通知(notifier) / 工具调用(tooler) / 思考中(loader)
|
|
5
|
+
* 每个槽位通过子 Container 管理显示/隐藏
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { Container, Spacer,Loader } = require('@earendil-works/pi-tui');
|
|
9
|
+
const chalk = require('chalk').default;
|
|
10
|
+
|
|
11
|
+
// Foliko 配色
|
|
12
|
+
const folikoPrimary = chalk.hex('#2A9D8F');
|
|
13
|
+
const folikoGold = chalk.hex('#E9C46A');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* NoMarginLoader — 去掉 Loader 默认的上方空行
|
|
17
|
+
*/
|
|
18
|
+
class NoMarginLoader extends Loader {
|
|
19
|
+
render(width) {
|
|
20
|
+
return super.render(width).slice(1); // 去掉 Loader 自动追加的空行
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
class StatusBar {
|
|
25
|
+
constructor(tui, editor) {
|
|
26
|
+
this.tui = tui;
|
|
27
|
+
this.editor = editor;
|
|
28
|
+
|
|
29
|
+
// 顶层容器
|
|
30
|
+
this.container = new Container();
|
|
31
|
+
|
|
32
|
+
// 三个子 Container 槽位
|
|
33
|
+
this._notifierSlot = new Container();
|
|
34
|
+
this._toolerSlot = new Container();
|
|
35
|
+
this._loaderSlot = new Container();
|
|
36
|
+
|
|
37
|
+
// 工具调用 Loader
|
|
38
|
+
const tooler = new NoMarginLoader(
|
|
39
|
+
tui,
|
|
40
|
+
(s) => chalk.green(s),
|
|
41
|
+
(s) => chalk.yellow(s),
|
|
42
|
+
'工具调用...',
|
|
43
|
+
{ frames: ['|', '/', '-', '\\'].map((str) => folikoGold(str)) },
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
// 思考中 Loader
|
|
47
|
+
const loader = new NoMarginLoader(
|
|
48
|
+
tui,
|
|
49
|
+
(s) => chalk.cyan(s),
|
|
50
|
+
(s) => chalk.dim(s),
|
|
51
|
+
'正在思考中...',
|
|
52
|
+
{ frames: ['⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷'].map((str) => folikoPrimary(str)) },
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
// Spacer 占位(隐藏时填充)
|
|
56
|
+
const toolerSpacer = new Spacer(0);
|
|
57
|
+
const loaderSpacer = new Spacer(0);
|
|
58
|
+
const notifierSpacer = new Spacer(0);
|
|
59
|
+
|
|
60
|
+
// 初始化所有槽位为 Spacer
|
|
61
|
+
this._notifierSlot.addChild(notifierSpacer);
|
|
62
|
+
this._toolerSlot.addChild(toolerSpacer);
|
|
63
|
+
this._loaderSlot.addChild(loaderSpacer);
|
|
64
|
+
|
|
65
|
+
// 挂载到顶层容器
|
|
66
|
+
this.container.addChild(this._notifierSlot);
|
|
67
|
+
this.container.addChild(this._toolerSlot);
|
|
68
|
+
this.container.addChild(this._loaderSlot);
|
|
69
|
+
|
|
70
|
+
// ——— 公开 API ———
|
|
71
|
+
const self = this;
|
|
72
|
+
|
|
73
|
+
/** 工具调用状态 */
|
|
74
|
+
this.tooler = {
|
|
75
|
+
dom: tooler,
|
|
76
|
+
_spacer: toolerSpacer,
|
|
77
|
+
_showed: false,
|
|
78
|
+
show(text) {
|
|
79
|
+
this._showed = true;
|
|
80
|
+
self._toolerSlot.clear();
|
|
81
|
+
self._toolerSlot.addChild(this.dom);
|
|
82
|
+
this.dom.setMessage(text);
|
|
83
|
+
return this.dom;
|
|
84
|
+
},
|
|
85
|
+
hide() {
|
|
86
|
+
this._showed = false;
|
|
87
|
+
self._toolerSlot.clear();
|
|
88
|
+
self._toolerSlot.addChild(this._spacer);
|
|
89
|
+
self.tui.requestRender();
|
|
90
|
+
},
|
|
91
|
+
setText(text) {
|
|
92
|
+
if (!this._showed) {
|
|
93
|
+
this.show(text);
|
|
94
|
+
} else {
|
|
95
|
+
this.dom.setMessage(text);
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
/** 通知提示 */
|
|
101
|
+
this.notifier = {
|
|
102
|
+
dom: null,
|
|
103
|
+
_spacer: notifierSpacer,
|
|
104
|
+
_showed: false,
|
|
105
|
+
_timeout: null,
|
|
106
|
+
show(text, duration = 5000) {
|
|
107
|
+
if (this._timeout) clearTimeout(this._timeout);
|
|
108
|
+
|
|
109
|
+
if (!this.dom) {
|
|
110
|
+
this.dom = new NoMarginLoader(tui, (s) => chalk.cyan(s), (s) => chalk.yellow(s), text);
|
|
111
|
+
}
|
|
112
|
+
this.dom.setMessage(text);
|
|
113
|
+
self._notifierSlot.clear();
|
|
114
|
+
self._notifierSlot.addChild(this.dom);
|
|
115
|
+
this._showed = true;
|
|
116
|
+
|
|
117
|
+
this._timeout = setTimeout(() => this.hide(), duration);
|
|
118
|
+
},
|
|
119
|
+
hide() {
|
|
120
|
+
if (this._timeout) {
|
|
121
|
+
clearTimeout(this._timeout);
|
|
122
|
+
this._timeout = null;
|
|
123
|
+
}
|
|
124
|
+
this._showed = false;
|
|
125
|
+
self._notifierSlot.clear();
|
|
126
|
+
self._notifierSlot.addChild(this._spacer);
|
|
127
|
+
self.tui.requestRender();
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
/** 思考中 Loader(带计时) */
|
|
132
|
+
this.loader = {
|
|
133
|
+
dom: loader,
|
|
134
|
+
_spacer: loaderSpacer,
|
|
135
|
+
_startTime: null,
|
|
136
|
+
_timer: null,
|
|
137
|
+
show() {
|
|
138
|
+
self._loaderSlot.clear();
|
|
139
|
+
self._loaderSlot.addChild(this.dom);
|
|
140
|
+
if (self.editor) self.editor.disableSubmit = true;
|
|
141
|
+
|
|
142
|
+
this._startTime = Date.now();
|
|
143
|
+
this.dom.setMessage('正在思考中... (0秒)');
|
|
144
|
+
this.dom.start();
|
|
145
|
+
|
|
146
|
+
this._timer = setInterval(() => {
|
|
147
|
+
const elapsed = Math.floor((Date.now() - this._startTime) / 1000);
|
|
148
|
+
const seconds = elapsed % 60;
|
|
149
|
+
const minutes = Math.floor(elapsed / 60);
|
|
150
|
+
const timeStr = minutes > 0 ? `${minutes}分${seconds}秒` : `${seconds}秒`;
|
|
151
|
+
this.dom.setMessage(`正在思考中... (${timeStr})`);
|
|
152
|
+
}, 1000);
|
|
153
|
+
|
|
154
|
+
return this.dom;
|
|
155
|
+
},
|
|
156
|
+
hide() {
|
|
157
|
+
if (self.editor) self.editor.disableSubmit = false;
|
|
158
|
+
if (this._timer) {
|
|
159
|
+
clearInterval(this._timer);
|
|
160
|
+
this._timer = null;
|
|
161
|
+
}
|
|
162
|
+
this.dom.stop();
|
|
163
|
+
self._loaderSlot.clear();
|
|
164
|
+
self._loaderSlot.addChild(this._spacer);
|
|
165
|
+
self.tui.requestRender();
|
|
166
|
+
},
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
invalidate() {
|
|
171
|
+
for (const child of this.container.children) {
|
|
172
|
+
child.invalidate?.();
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
module.exports = { StatusBar };
|
|
@@ -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:
|