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
|
@@ -1,48 +1,88 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Storage
|
|
3
|
-
*
|
|
2
|
+
* Storage Plugin - JSONL-based key-value storage
|
|
3
|
+
* Supports delayed compaction to reduce file size
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
const { Plugin } = require('../src/core/plugin-base')
|
|
7
|
-
const { logger } = require('../src/utils/logger')
|
|
8
|
-
const log = logger.child('Storage')
|
|
9
|
-
const { z } = require('zod')
|
|
10
|
-
const
|
|
11
|
-
const
|
|
6
|
+
const { Plugin } = require('../src/core/plugin-base');
|
|
7
|
+
const { logger } = require('../src/utils/logger');
|
|
8
|
+
const log = logger.child('Storage');
|
|
9
|
+
const { z } = require('zod');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const { StorageManager } = require('../src/core/storage-manager');
|
|
12
12
|
|
|
13
13
|
class StoragePlugin extends Plugin {
|
|
14
14
|
constructor(config = {}) {
|
|
15
|
-
super()
|
|
16
|
-
this.name = 'storage'
|
|
17
|
-
this.version = '1.0
|
|
18
|
-
this.description = '
|
|
19
|
-
this.priority = 3
|
|
15
|
+
super();
|
|
16
|
+
this.name = 'storage';
|
|
17
|
+
this.version = '2.1.0';
|
|
18
|
+
this.description = '数据持久化存储插件,支持键值对存储(JSONL格式)+ 自动 compaction';
|
|
19
|
+
this.priority = 3;
|
|
20
20
|
|
|
21
|
-
this.system = true
|
|
21
|
+
this.system = true;
|
|
22
22
|
|
|
23
23
|
this.config = {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
path: config.path || '.foliko/data',
|
|
25
|
+
namespace: config.namespace || 'default',
|
|
26
|
+
// Compaction 配置
|
|
27
|
+
compactionThreshold: config.compactionThreshold || 1000,
|
|
28
|
+
compactionIntervalMs: config.compactionIntervalMs || 5000,
|
|
29
|
+
autoCompact: config.autoCompact !== false,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
this._framework = null;
|
|
33
|
+
this._storageManager = null;
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
install(framework) {
|
|
35
|
-
this._framework = framework
|
|
36
|
-
return this
|
|
37
|
+
this._framework = framework;
|
|
38
|
+
return this;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Initialize storage manager with compaction settings
|
|
43
|
+
*/
|
|
44
|
+
_initStorage() {
|
|
45
|
+
if (this._storageManager) return;
|
|
46
|
+
|
|
47
|
+
const baseDir = path.resolve(process.cwd(), this.config.path);
|
|
48
|
+
const filePath = path.join(baseDir, `${this.config.namespace}.jsonl`);
|
|
49
|
+
|
|
50
|
+
// 传递 compaction 配置
|
|
51
|
+
this._storageManager = new StorageManager(filePath, true, {
|
|
52
|
+
compactionThreshold: this.config.compactionThreshold,
|
|
53
|
+
compactionIntervalMs: this.config.compactionIntervalMs,
|
|
54
|
+
autoCompact: this.config.autoCompact,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Get storage store (for internal use)
|
|
60
|
+
*/
|
|
61
|
+
getStore() {
|
|
62
|
+
this._initStorage();
|
|
63
|
+
return this._storageManager;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Set value directly (for internal use by other plugins)
|
|
68
|
+
*/
|
|
69
|
+
setDirect(key, value) {
|
|
70
|
+
this._initStorage();
|
|
71
|
+
return this._storageManager.set(key, value);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Delete key directly (for internal use by other plugins)
|
|
76
|
+
*/
|
|
77
|
+
deleteDirect(key) {
|
|
78
|
+
this._initStorage();
|
|
79
|
+
return this._storageManager.delete(key);
|
|
37
80
|
}
|
|
38
81
|
|
|
39
82
|
start(framework) {
|
|
40
|
-
|
|
41
|
-
if (this.config.type === 'json') {
|
|
42
|
-
this._initJsonStore()
|
|
43
|
-
}
|
|
83
|
+
this._initStorage();
|
|
44
84
|
|
|
45
|
-
//
|
|
85
|
+
// Register storage tools
|
|
46
86
|
framework.registerTool({
|
|
47
87
|
name: 'storage_set',
|
|
48
88
|
description: '存储数据到键值存储',
|
|
@@ -53,23 +93,21 @@ class StoragePlugin extends Plugin {
|
|
|
53
93
|
}),
|
|
54
94
|
execute: async (args) => {
|
|
55
95
|
try {
|
|
56
|
-
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return { success: true, data: { key: args.key, namespace: ns } }
|
|
96
|
+
this._initStorage();
|
|
97
|
+
const ns = args.namespace ? `${args.namespace}:` : '';
|
|
98
|
+
const fullKey = `${ns}${args.key}`;
|
|
99
|
+
const entry = this._storageManager.set(fullKey, args.value);
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
success: true,
|
|
103
|
+
data: { key: args.key, namespace: args.namespace || this.config.namespace }
|
|
104
|
+
};
|
|
68
105
|
} catch (err) {
|
|
69
|
-
|
|
106
|
+
log.error('storage_set error:', err.message);
|
|
107
|
+
return { success: false, error: err.message };
|
|
70
108
|
}
|
|
71
109
|
}
|
|
72
|
-
})
|
|
110
|
+
});
|
|
73
111
|
|
|
74
112
|
framework.registerTool({
|
|
75
113
|
name: 'storage_get',
|
|
@@ -79,46 +117,52 @@ class StoragePlugin extends Plugin {
|
|
|
79
117
|
namespace: z.string().optional().describe('命名空间')
|
|
80
118
|
}),
|
|
81
119
|
execute: async (args) => {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
return { success: false, error: 'Key not found', key: args.key }
|
|
88
|
-
}
|
|
120
|
+
try {
|
|
121
|
+
this._initStorage();
|
|
122
|
+
const ns = args.namespace ? `${args.namespace}:` : '';
|
|
123
|
+
const fullKey = `${ns}${args.key}`;
|
|
124
|
+
const value = this._storageManager.get(fullKey);
|
|
89
125
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
data: {
|
|
93
|
-
key: args.key,
|
|
94
|
-
namespace: ns,
|
|
95
|
-
value: entry.value,
|
|
96
|
-
updatedAt: entry.updatedAt
|
|
126
|
+
if (value === null) {
|
|
127
|
+
return { success: false, error: 'Key not found', key: args.key };
|
|
97
128
|
}
|
|
129
|
+
|
|
130
|
+
return {
|
|
131
|
+
success: true,
|
|
132
|
+
data: {
|
|
133
|
+
key: args.key,
|
|
134
|
+
namespace: args.namespace || this.config.namespace,
|
|
135
|
+
value
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
} catch (err) {
|
|
139
|
+
log.error('storage_get error:', err.message);
|
|
140
|
+
return { success: false, error: err.message };
|
|
98
141
|
}
|
|
99
142
|
}
|
|
100
|
-
})
|
|
143
|
+
});
|
|
101
144
|
|
|
102
145
|
framework.registerTool({
|
|
103
146
|
name: 'storage_delete',
|
|
104
|
-
description: '
|
|
147
|
+
description: '删除存储的数据(软删除,物理删除由 compaction 自动处理)',
|
|
105
148
|
inputSchema: z.object({
|
|
106
149
|
key: z.string().describe('存储键名'),
|
|
107
150
|
namespace: z.string().optional().describe('命名空间')
|
|
108
151
|
}),
|
|
109
152
|
execute: async (args) => {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
153
|
+
try {
|
|
154
|
+
this._initStorage();
|
|
155
|
+
const ns = args.namespace ? `${args.namespace}:` : '';
|
|
156
|
+
const fullKey = `${ns}${args.key}`;
|
|
157
|
+
const deleted = this._storageManager.delete(fullKey);
|
|
114
158
|
|
|
115
|
-
|
|
116
|
-
|
|
159
|
+
return { success: true, data: { deleted, key: args.key } };
|
|
160
|
+
} catch (err) {
|
|
161
|
+
log.error('storage_delete error:', err.message);
|
|
162
|
+
return { success: false, error: err.message };
|
|
117
163
|
}
|
|
118
|
-
|
|
119
|
-
return { success: true, data: { deleted: existed, key: args.key } }
|
|
120
164
|
}
|
|
121
|
-
})
|
|
165
|
+
});
|
|
122
166
|
|
|
123
167
|
framework.registerTool({
|
|
124
168
|
name: 'storage_list',
|
|
@@ -127,139 +171,154 @@ class StoragePlugin extends Plugin {
|
|
|
127
171
|
namespace: z.string().optional().describe('命名空间,默认全局')
|
|
128
172
|
}),
|
|
129
173
|
execute: async (args) => {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
174
|
+
try {
|
|
175
|
+
this._initStorage();
|
|
176
|
+
const ns = args.namespace ? `${args.namespace}:` : '';
|
|
177
|
+
const keys = this._storageManager.list(ns);
|
|
178
|
+
|
|
179
|
+
return {
|
|
180
|
+
success: true,
|
|
181
|
+
data: keys.map(k => k.substring(ns.length)),
|
|
182
|
+
metadata: {
|
|
183
|
+
namespace: args.namespace || this.config.namespace,
|
|
184
|
+
count: keys.length
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
} catch (err) {
|
|
188
|
+
log.error('storage_list error:', err.message);
|
|
189
|
+
return { success: false, error: err.message };
|
|
144
190
|
}
|
|
145
191
|
}
|
|
146
|
-
})
|
|
192
|
+
});
|
|
147
193
|
|
|
148
194
|
framework.registerTool({
|
|
149
195
|
name: 'storage_clear',
|
|
150
|
-
description: '
|
|
196
|
+
description: '清空命名空间下的所有数据(立即物理删除)',
|
|
151
197
|
inputSchema: z.object({
|
|
152
198
|
namespace: z.string().optional().describe('命名空间,默认全局')
|
|
153
199
|
}),
|
|
154
200
|
execute: async (args) => {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
201
|
+
try {
|
|
202
|
+
this._initStorage();
|
|
203
|
+
const ns = args.namespace ? `${args.namespace}:` : '';
|
|
204
|
+
const keys = this._storageManager.list(ns);
|
|
205
|
+
let count = 0;
|
|
206
|
+
|
|
207
|
+
for (const key of keys) {
|
|
208
|
+
if (this._storageManager.delete(key)) {
|
|
209
|
+
count++;
|
|
210
|
+
}
|
|
163
211
|
}
|
|
164
|
-
}
|
|
165
212
|
|
|
166
|
-
|
|
167
|
-
|
|
213
|
+
return { success: true, data: { namespace: args.namespace || this.config.namespace, cleared: count } };
|
|
214
|
+
} catch (err) {
|
|
215
|
+
log.error('storage_clear error:', err.message);
|
|
216
|
+
return { success: false, error: err.message };
|
|
168
217
|
}
|
|
169
|
-
|
|
170
|
-
return { success: true, data: { namespace: ns, cleared: count } }
|
|
171
218
|
}
|
|
172
|
-
})
|
|
173
|
-
|
|
174
|
-
return this
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* 初始化 JSON 文件存储
|
|
179
|
-
*/
|
|
180
|
-
_initJsonStore() {
|
|
181
|
-
this._filePath = path.resolve(process.cwd(), this.config.path, `${this.config.namespace}.json`)
|
|
182
|
-
|
|
183
|
-
// 确保目录存在
|
|
184
|
-
const dir = path.dirname(this._filePath)
|
|
185
|
-
if (!fs.existsSync(dir)) {
|
|
186
|
-
fs.mkdirSync(dir, { recursive: true })
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// 加载已有数据
|
|
190
|
-
if (fs.existsSync(this._filePath)) {
|
|
191
|
-
try {
|
|
192
|
-
const content = fs.readFileSync(this._filePath, 'utf-8')
|
|
193
|
-
const data = JSON.parse(content)
|
|
219
|
+
});
|
|
194
220
|
|
|
195
|
-
|
|
196
|
-
|
|
221
|
+
framework.registerTool({
|
|
222
|
+
name: 'storage_watch',
|
|
223
|
+
description: '监听键值变化(返回当前值)',
|
|
224
|
+
inputSchema: z.object({
|
|
225
|
+
key: z.string().describe('存储键名'),
|
|
226
|
+
namespace: z.string().optional().describe('命名空间')
|
|
227
|
+
}),
|
|
228
|
+
execute: async (args) => {
|
|
229
|
+
try {
|
|
230
|
+
this._initStorage();
|
|
231
|
+
const ns = args.namespace ? `${args.namespace}:` : '';
|
|
232
|
+
const fullKey = `${ns}${args.key}`;
|
|
233
|
+
const value = this._storageManager.watch(fullKey);
|
|
234
|
+
|
|
235
|
+
return {
|
|
236
|
+
success: true,
|
|
237
|
+
data: { key: args.key, value },
|
|
238
|
+
metadata: { watched: true }
|
|
239
|
+
};
|
|
240
|
+
} catch (err) {
|
|
241
|
+
log.error('storage_watch error:', err.message);
|
|
242
|
+
return { success: false, error: err.message };
|
|
197
243
|
}
|
|
198
|
-
|
|
199
|
-
log.info(` Loaded ${this._store.size} entries from ${this._filePath}`)
|
|
200
|
-
} catch (err) {
|
|
201
|
-
log.warn(` Failed to load storage file: ${err.message}`)
|
|
202
244
|
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
245
|
+
});
|
|
205
246
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
247
|
+
/**
|
|
248
|
+
* 新增: 手动触发 compaction
|
|
249
|
+
* 当 tombstone 数量达到阈值时,compaction 会自动在后台执行
|
|
250
|
+
* 此工具可手动触发 compaction 立即清理
|
|
251
|
+
*/
|
|
252
|
+
framework.registerTool({
|
|
253
|
+
name: 'storage_compact',
|
|
254
|
+
description: '手动触发 compaction,清理已删除的墓碑记录并重写文件',
|
|
255
|
+
inputSchema: z.object({
|
|
256
|
+
namespace: z.string().optional().describe('命名空间,默认全局')
|
|
257
|
+
}),
|
|
258
|
+
execute: async (args) => {
|
|
259
|
+
try {
|
|
260
|
+
this._initStorage();
|
|
261
|
+
|
|
262
|
+
const result = await this._storageManager.compact();
|
|
263
|
+
|
|
264
|
+
return {
|
|
265
|
+
success: true,
|
|
266
|
+
data: {
|
|
267
|
+
namespace: args.namespace || this.config.namespace,
|
|
268
|
+
compacted: result.compacted,
|
|
269
|
+
status: result.status
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
} catch (err) {
|
|
273
|
+
log.error('storage_compact error:', err.message);
|
|
274
|
+
return { success: false, error: err.message };
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
});
|
|
226
278
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
279
|
+
/**
|
|
280
|
+
* 新增: 获取存储统计信息
|
|
281
|
+
*/
|
|
282
|
+
framework.registerTool({
|
|
283
|
+
name: 'storage_stats',
|
|
284
|
+
description: '获取存储统计信息,包括条目数、墓碑数量、compaction 配置等',
|
|
285
|
+
inputSchema: z.object({
|
|
286
|
+
namespace: z.string().optional().describe('命名空间,默认全局')
|
|
287
|
+
}),
|
|
288
|
+
execute: async (args) => {
|
|
289
|
+
try {
|
|
290
|
+
this._initStorage();
|
|
291
|
+
const stats = this._storageManager.getCompactionStats();
|
|
292
|
+
|
|
293
|
+
return {
|
|
294
|
+
success: true,
|
|
295
|
+
data: {
|
|
296
|
+
namespace: args.namespace || this.config.namespace,
|
|
297
|
+
...stats
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
} catch (err) {
|
|
301
|
+
log.error('storage_stats error:', err.message);
|
|
302
|
+
return { success: false, error: err.message };
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
});
|
|
238
306
|
|
|
239
|
-
|
|
240
|
-
* 删除键并自动持久化(供其他插件使用)
|
|
241
|
-
* @param {string} key - 键
|
|
242
|
-
*/
|
|
243
|
-
deleteDirect(key) {
|
|
244
|
-
this._store.delete(key)
|
|
245
|
-
if (this.config.type === 'json') {
|
|
246
|
-
this._persistToFile()
|
|
247
|
-
}
|
|
307
|
+
return this;
|
|
248
308
|
}
|
|
249
309
|
|
|
250
310
|
reload(framework) {
|
|
251
|
-
this._framework = framework
|
|
252
|
-
this.
|
|
253
|
-
|
|
254
|
-
if (this.config.type === 'json') {
|
|
255
|
-
this._initJsonStore()
|
|
256
|
-
}
|
|
311
|
+
this._framework = framework;
|
|
312
|
+
this._initStorage();
|
|
257
313
|
}
|
|
258
314
|
|
|
259
315
|
uninstall(framework) {
|
|
260
|
-
this.
|
|
261
|
-
|
|
316
|
+
if (this._storageManager) {
|
|
317
|
+
this._storageManager.clear();
|
|
318
|
+
this._storageManager = null;
|
|
319
|
+
}
|
|
320
|
+
this._framework = null;
|
|
262
321
|
}
|
|
263
322
|
}
|
|
264
323
|
|
|
265
|
-
module.exports = StoragePlugin
|
|
324
|
+
module.exports = { StoragePlugin };
|
|
@@ -499,7 +499,7 @@ class SubAgentManagerPlugin extends Plugin {
|
|
|
499
499
|
|
|
500
500
|
agent.registerTool({
|
|
501
501
|
name: 'subagent_reload',
|
|
502
|
-
description: '重新加载子Agent配置(当新增或删除.
|
|
502
|
+
description: '重新加载子Agent配置(当新增或删除.foliko/agents下的文件后使用)',
|
|
503
503
|
inputSchema: z.object({}),
|
|
504
504
|
execute: async () => {
|
|
505
505
|
try {
|
|
@@ -567,7 +567,7 @@ class SubAgentManagerPlugin extends Plugin {
|
|
|
567
567
|
|
|
568
568
|
framework.registerTool({
|
|
569
569
|
name: 'subagent_reload',
|
|
570
|
-
description: '重新加载子Agent配置(当新增或删除.
|
|
570
|
+
description: '重新加载子Agent配置(当新增或删除.foliko/agents下的文件后使用)',
|
|
571
571
|
inputSchema: z.object({}),
|
|
572
572
|
execute: async () => {
|
|
573
573
|
try {
|
|
@@ -586,8 +586,8 @@ class SubAgentManagerPlugin extends Plugin {
|
|
|
586
586
|
* 从 agentsDir 目录加载子Agent配置
|
|
587
587
|
*/
|
|
588
588
|
_loadAgentsFromDir() {
|
|
589
|
-
// 默认使用 .
|
|
590
|
-
const agentsDir = this.config.agentsDir || path.join(process.cwd(), '.
|
|
589
|
+
// 默认使用 .foliko/agents 目录
|
|
590
|
+
const agentsDir = this.config.agentsDir || path.join(process.cwd(), '.foliko', 'agents')
|
|
591
591
|
//log.info(' _loadAgentsFromDir called, agentsDir:', agentsDir)
|
|
592
592
|
if (!fs.existsSync(agentsDir)) {
|
|
593
593
|
log.info(' agentsDir not found or does not exist')
|