flowmind 1.0.0
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/LICENSE +21 -0
- package/README.md +855 -0
- package/README_CN.md +854 -0
- package/bin/flowmind.js +464 -0
- package/core/adapters/api-doc-adapter.js +71 -0
- package/core/adapters/base-adapter.js +80 -0
- package/core/adapters/database-manager-adapter.js +60 -0
- package/core/adapters/database-query-adapter.js +51 -0
- package/core/adapters/knowledge-base-adapter.js +75 -0
- package/core/adapters/log-service-adapter.js +41 -0
- package/core/adapters/mcp-adapter.js +65 -0
- package/core/adapters/report-adapter.js +60 -0
- package/core/adapters/workflow-adapter.js +62 -0
- package/core/component-registry.js +281 -0
- package/core/component-types.js +63 -0
- package/core/config-manager.js +360 -0
- package/core/index.js +223 -0
- package/core/learning-engine.js +588 -0
- package/core/mcp-compatibility.js +150 -0
- package/core/providers/aliyun/dms-adapter.js +98 -0
- package/core/providers/aliyun/redis-adapter.js +88 -0
- package/core/providers/aliyun/sls-adapter.js +86 -0
- package/core/providers/friday/flow-adapter.js +85 -0
- package/core/providers/friday/report-adapter.js +83 -0
- package/core/providers/yapi/yapi-adapter.js +79 -0
- package/core/providers/yuque/yuque-adapter.js +90 -0
- package/core/scene-matcher.js +326 -0
- package/core/skill-loader.js +291 -0
- package/package.json +67 -0
- package/scripts/migrate-config.js +153 -0
- package/skills/api-sync/SKILL.md +203 -0
- package/skills/archive-change/SKILL.md +172 -0
- package/skills/auto-flow/SKILL.md +277 -0
- package/skills/code-review/SKILL.md +206 -0
- package/skills/code-review-audit/SKILL.md +150 -0
- package/skills/data-logic-validation/SKILL.md +162 -0
- package/skills/data-validation/SKILL.md +210 -0
- package/skills/git-review/SKILL.md +190 -0
- package/skills/learning-engine/SKILL.md +352 -0
- package/skills/learning-feedback/SKILL.md +174 -0
- package/skills/log-audit/SKILL.md +226 -0
- package/skills/project-review/SKILL.md +196 -0
- package/skills/requirement-analyst/SKILL.md +275 -0
- package/skills/resource-bind/SKILL.md +222 -0
- package/skills/sls-log-audit/SKILL.md +223 -0
- package/skills/yapi-sync-interface/SKILL.md +145 -0
- package/skills/yuque-sync-design/SKILL.md +157 -0
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FlowMind Configuration Manager
|
|
3
|
+
* Manages configuration loading and access
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const fs = require('fs-extra');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
|
|
9
|
+
class ConfigManager {
|
|
10
|
+
constructor(configPath = null) {
|
|
11
|
+
this.configPath = configPath;
|
|
12
|
+
this.config = {};
|
|
13
|
+
this.defaults = this.getDefaults();
|
|
14
|
+
this.initialized = false;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Load configuration
|
|
19
|
+
*/
|
|
20
|
+
async load() {
|
|
21
|
+
// Try to load from specified path
|
|
22
|
+
if (this.configPath) {
|
|
23
|
+
await this.loadFromFile(this.configPath);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Try to load from default locations
|
|
27
|
+
const defaultPaths = [
|
|
28
|
+
path.join(process.cwd(), 'flowmind.config.js'),
|
|
29
|
+
path.join(process.cwd(), 'flowmind.config.json'),
|
|
30
|
+
path.join(this.getHomeDir(), '.flowmind', 'config.json'),
|
|
31
|
+
path.join(this.getHomeDir(), '.flowmindrc')
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
for (const configPath of defaultPaths) {
|
|
35
|
+
if (await fs.pathExists(configPath)) {
|
|
36
|
+
await this.loadFromFile(configPath);
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Load resource config
|
|
42
|
+
await this.loadResourceConfig();
|
|
43
|
+
|
|
44
|
+
// Load learning config
|
|
45
|
+
await this.loadLearningConfig();
|
|
46
|
+
|
|
47
|
+
// Load component config
|
|
48
|
+
await this.loadComponentConfig();
|
|
49
|
+
|
|
50
|
+
this.initialized = true;
|
|
51
|
+
return this.config;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Load configuration from file
|
|
56
|
+
*/
|
|
57
|
+
async loadFromFile(filePath) {
|
|
58
|
+
try {
|
|
59
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
60
|
+
|
|
61
|
+
if (ext === '.js') {
|
|
62
|
+
const module = require(filePath);
|
|
63
|
+
this.mergeConfig(module);
|
|
64
|
+
} else if (ext === '.json') {
|
|
65
|
+
const data = await fs.readJson(filePath);
|
|
66
|
+
this.mergeConfig(data);
|
|
67
|
+
}
|
|
68
|
+
} catch (error) {
|
|
69
|
+
console.warn(`Failed to load config from ${filePath}:`, error.message);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Load resource configuration
|
|
75
|
+
*/
|
|
76
|
+
async loadResourceConfig() {
|
|
77
|
+
const resourceConfigPath = path.join(this.getHomeDir(), '.flowmind', 'resource-config.json');
|
|
78
|
+
|
|
79
|
+
if (await fs.pathExists(resourceConfigPath)) {
|
|
80
|
+
try {
|
|
81
|
+
const resourceConfig = await fs.readJson(resourceConfigPath);
|
|
82
|
+
this.mergeConfig({ resources: resourceConfig.resources || {} });
|
|
83
|
+
} catch (error) {
|
|
84
|
+
console.warn('Failed to load resource config:', error.message);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Load learning configuration
|
|
91
|
+
*/
|
|
92
|
+
async loadLearningConfig() {
|
|
93
|
+
const learningConfigPath = path.join(this.getHomeDir(), '.flowmind', 'learning-config.json');
|
|
94
|
+
|
|
95
|
+
if (await fs.pathExists(learningConfigPath)) {
|
|
96
|
+
try {
|
|
97
|
+
const learningConfig = await fs.readJson(learningConfigPath);
|
|
98
|
+
this.mergeConfig({ learning: learningConfig });
|
|
99
|
+
} catch (error) {
|
|
100
|
+
console.warn('Failed to load learning config:', error.message);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Load component configuration
|
|
107
|
+
* Supports loading from:
|
|
108
|
+
* - ~/.flowmind/component-config.json (dedicated component config)
|
|
109
|
+
* - flowmind.config.json (as part of main config under "components" key)
|
|
110
|
+
*/
|
|
111
|
+
async loadComponentConfig() {
|
|
112
|
+
const componentConfigPaths = [
|
|
113
|
+
path.join(this.getHomeDir(), '.flowmind', 'component-config.json'),
|
|
114
|
+
path.join(process.cwd(), 'component-config.json')
|
|
115
|
+
];
|
|
116
|
+
|
|
117
|
+
for (const configPath of componentConfigPaths) {
|
|
118
|
+
if (await fs.pathExists(configPath)) {
|
|
119
|
+
try {
|
|
120
|
+
const componentConfig = await fs.readJson(configPath);
|
|
121
|
+
if (componentConfig.components) {
|
|
122
|
+
this.mergeConfig({ components: componentConfig.components });
|
|
123
|
+
}
|
|
124
|
+
} catch (error) {
|
|
125
|
+
console.warn(`Failed to load component config from ${configPath}:`, error.message);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Get component configuration for a specific type.
|
|
133
|
+
* @param {string} componentType
|
|
134
|
+
* @returns {object|null}
|
|
135
|
+
*/
|
|
136
|
+
getComponentConfig(componentType) {
|
|
137
|
+
const components = this.get('components', {});
|
|
138
|
+
return components[componentType] || null;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Get the default provider for a component type.
|
|
143
|
+
* @param {string} componentType
|
|
144
|
+
* @returns {string|null}
|
|
145
|
+
*/
|
|
146
|
+
getDefaultProvider(componentType) {
|
|
147
|
+
const typeConfig = this.getComponentConfig(componentType);
|
|
148
|
+
return typeConfig ? typeConfig.default : null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Get provider configuration.
|
|
153
|
+
* @param {string} componentType
|
|
154
|
+
* @param {string} providerName
|
|
155
|
+
* @returns {object|null}
|
|
156
|
+
*/
|
|
157
|
+
getProviderConfig(componentType, providerName) {
|
|
158
|
+
const typeConfig = this.getComponentConfig(componentType);
|
|
159
|
+
if (!typeConfig || !typeConfig.providers) return null;
|
|
160
|
+
return typeConfig.providers[providerName] || null;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Get default configuration
|
|
165
|
+
*/
|
|
166
|
+
getDefaults() {
|
|
167
|
+
return {
|
|
168
|
+
// Core settings
|
|
169
|
+
version: '1.0.0',
|
|
170
|
+
name: 'FlowMind',
|
|
171
|
+
|
|
172
|
+
// Paths
|
|
173
|
+
skills: {
|
|
174
|
+
path: path.join(__dirname, '..', 'skills')
|
|
175
|
+
},
|
|
176
|
+
|
|
177
|
+
// Learning settings
|
|
178
|
+
learning: {
|
|
179
|
+
enabled: true,
|
|
180
|
+
autoApply: true,
|
|
181
|
+
confidenceThreshold: 0.7,
|
|
182
|
+
maxRecordsPerSkill: 100,
|
|
183
|
+
storagePath: path.join(this.getHomeDir(), '.flowmind', 'learning')
|
|
184
|
+
},
|
|
185
|
+
|
|
186
|
+
// Scene mapping settings
|
|
187
|
+
sceneMapping: {
|
|
188
|
+
enabled: true,
|
|
189
|
+
matchAlgorithm: 'weighted',
|
|
190
|
+
weights: {
|
|
191
|
+
keywordMatch: 0.4,
|
|
192
|
+
patternMatch: 0.3,
|
|
193
|
+
historyScore: 0.2,
|
|
194
|
+
confidence: 0.1
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
|
|
198
|
+
// Output settings
|
|
199
|
+
output: {
|
|
200
|
+
format: 'text',
|
|
201
|
+
language: 'auto',
|
|
202
|
+
verbose: false
|
|
203
|
+
},
|
|
204
|
+
|
|
205
|
+
// Resource settings
|
|
206
|
+
resources: {
|
|
207
|
+
database: { enabled: false },
|
|
208
|
+
redis: { enabled: false },
|
|
209
|
+
logs: { enabled: false },
|
|
210
|
+
apiDocs: { enabled: false }
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Merge configuration
|
|
217
|
+
*/
|
|
218
|
+
mergeConfig(newConfig) {
|
|
219
|
+
this.config = this.deepMerge(this.config, newConfig);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Deep merge objects
|
|
224
|
+
*/
|
|
225
|
+
deepMerge(target, source) {
|
|
226
|
+
const result = { ...target };
|
|
227
|
+
|
|
228
|
+
for (const key in source) {
|
|
229
|
+
if (source.hasOwnProperty(key)) {
|
|
230
|
+
if (this.isObject(source[key]) && this.isObject(target[key])) {
|
|
231
|
+
result[key] = this.deepMerge(target[key], source[key]);
|
|
232
|
+
} else {
|
|
233
|
+
result[key] = source[key];
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return result;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Check if value is object
|
|
243
|
+
*/
|
|
244
|
+
isObject(value) {
|
|
245
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Get configuration value
|
|
250
|
+
*/
|
|
251
|
+
get(keyPath, defaultValue = undefined) {
|
|
252
|
+
const keys = keyPath.split('.');
|
|
253
|
+
let value = this.config;
|
|
254
|
+
|
|
255
|
+
for (const key of keys) {
|
|
256
|
+
if (value === undefined || value === null) {
|
|
257
|
+
return defaultValue;
|
|
258
|
+
}
|
|
259
|
+
value = value[key];
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return value !== undefined ? value : defaultValue;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Set configuration value
|
|
267
|
+
*/
|
|
268
|
+
set(keyPath, value) {
|
|
269
|
+
const keys = keyPath.split('.');
|
|
270
|
+
let current = this.config;
|
|
271
|
+
|
|
272
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
273
|
+
const key = keys[i];
|
|
274
|
+
if (!current[key] || !this.isObject(current[key])) {
|
|
275
|
+
current[key] = {};
|
|
276
|
+
}
|
|
277
|
+
current = current[key];
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
current[keys[keys.length - 1]] = value;
|
|
281
|
+
return true;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Check if key exists
|
|
286
|
+
*/
|
|
287
|
+
has(keyPath) {
|
|
288
|
+
return this.get(keyPath) !== undefined;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Get all configuration
|
|
293
|
+
*/
|
|
294
|
+
getAll() {
|
|
295
|
+
return { ...this.config };
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Save configuration
|
|
300
|
+
*/
|
|
301
|
+
async save() {
|
|
302
|
+
const configPath = path.join(this.getHomeDir(), '.flowmind', 'config.json');
|
|
303
|
+
|
|
304
|
+
await fs.ensureDir(path.dirname(configPath));
|
|
305
|
+
await fs.writeJson(configPath, this.config, { spaces: 2 });
|
|
306
|
+
|
|
307
|
+
return configPath;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Get home directory
|
|
312
|
+
*/
|
|
313
|
+
getHomeDir() {
|
|
314
|
+
return process.env.HOME || process.env.USERPROFILE || os.homedir();
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Reload configuration
|
|
319
|
+
*/
|
|
320
|
+
async reload() {
|
|
321
|
+
this.config = {};
|
|
322
|
+
this.initialized = false;
|
|
323
|
+
return await this.load();
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Validate configuration
|
|
328
|
+
*/
|
|
329
|
+
validate() {
|
|
330
|
+
const errors = [];
|
|
331
|
+
|
|
332
|
+
// Check required fields
|
|
333
|
+
if (!this.config.version) {
|
|
334
|
+
errors.push('Missing required field: version');
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// Validate learning settings
|
|
338
|
+
if (this.config.learning) {
|
|
339
|
+
if (this.config.learning.confidenceThreshold < 0 || this.config.learning.confidenceThreshold > 1) {
|
|
340
|
+
errors.push('Invalid confidenceThreshold: must be between 0 and 1');
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Validate scene mapping weights
|
|
345
|
+
if (this.config.sceneMapping?.weights) {
|
|
346
|
+
const weights = this.config.sceneMapping.weights;
|
|
347
|
+
const sum = Object.values(weights).reduce((a, b) => a + b, 0);
|
|
348
|
+
if (Math.abs(sum - 1) > 0.01) {
|
|
349
|
+
errors.push('Scene mapping weights must sum to 1');
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
return {
|
|
354
|
+
valid: errors.length === 0,
|
|
355
|
+
errors: errors
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
module.exports = ConfigManager;
|
package/core/index.js
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FlowMind - The AI Agent That Learns How You Work
|
|
3
|
+
* Core Engine Entry Point
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const SkillLoader = require('./skill-loader');
|
|
7
|
+
const LearningEngine = require('./learning-engine');
|
|
8
|
+
const SceneMatcher = require('./scene-matcher');
|
|
9
|
+
const ConfigManager = require('./config-manager');
|
|
10
|
+
const ComponentRegistry = require('./component-registry');
|
|
11
|
+
|
|
12
|
+
class FlowMind {
|
|
13
|
+
constructor(options = {}) {
|
|
14
|
+
this.config = new ConfigManager(options.configPath);
|
|
15
|
+
this.learning = new LearningEngine(this.config);
|
|
16
|
+
this.matcher = new SceneMatcher(this.config, this.learning);
|
|
17
|
+
this.components = new ComponentRegistry(this.config);
|
|
18
|
+
this.skills = new SkillLoader(this.config, this.learning, this.components);
|
|
19
|
+
this.initialized = false;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Initialize FlowMind
|
|
24
|
+
*/
|
|
25
|
+
async init() {
|
|
26
|
+
if (this.initialized) return this;
|
|
27
|
+
|
|
28
|
+
await this.config.load();
|
|
29
|
+
await this.components.init();
|
|
30
|
+
await this.components.initAll();
|
|
31
|
+
await this.learning.init();
|
|
32
|
+
await this.skills.loadAll();
|
|
33
|
+
await this.matcher.loadScenes();
|
|
34
|
+
|
|
35
|
+
this.initialized = true;
|
|
36
|
+
return this;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Process a user request
|
|
41
|
+
*/
|
|
42
|
+
async process(input, context = {}) {
|
|
43
|
+
if (!this.initialized) {
|
|
44
|
+
await this.init();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const startTime = Date.now();
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
// 1. Check for learning patterns (corrections, feedback)
|
|
51
|
+
const learningResult = await this.learning.detectLearning(input, context);
|
|
52
|
+
if (learningResult) {
|
|
53
|
+
return this.formatLearningResponse(learningResult);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// 2. Check scene mappings
|
|
57
|
+
const sceneMatch = await this.matcher.match(input);
|
|
58
|
+
if (sceneMatch && sceneMatch.confidence >= 0.7) {
|
|
59
|
+
return this.executeSceneWorkflow(sceneMatch, input, context);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// 3. Select and execute skill
|
|
63
|
+
const skill = await this.skills.select(input, context);
|
|
64
|
+
if (!skill) {
|
|
65
|
+
return this.formatError('No matching skill found', input);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// 4. Execute with learning applied
|
|
69
|
+
const result = await this.executeWithLearning(skill, input, context);
|
|
70
|
+
|
|
71
|
+
// 5. Format and return
|
|
72
|
+
return this.formatResult(result, {
|
|
73
|
+
skill: skill.name,
|
|
74
|
+
duration: Date.now() - startTime,
|
|
75
|
+
sceneMatch: sceneMatch
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
} catch (error) {
|
|
79
|
+
return this.formatError(error.message, input);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Execute skill with learning applied
|
|
85
|
+
*/
|
|
86
|
+
async executeWithLearning(skill, input, context) {
|
|
87
|
+
// Get learning rules for this skill
|
|
88
|
+
const learnings = await this.learning.getSkillLearnings(skill.name);
|
|
89
|
+
|
|
90
|
+
// Apply learning rules to context
|
|
91
|
+
const enhancedContext = {
|
|
92
|
+
...context,
|
|
93
|
+
learnings: learnings,
|
|
94
|
+
preferences: await this.learning.getPreferences(skill.name)
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// Execute skill
|
|
98
|
+
const result = await skill.execute(input, enhancedContext);
|
|
99
|
+
|
|
100
|
+
return result;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Execute scene workflow
|
|
105
|
+
*/
|
|
106
|
+
async executeSceneWorkflow(sceneMatch, input, context) {
|
|
107
|
+
const { scene, params } = sceneMatch;
|
|
108
|
+
const results = [];
|
|
109
|
+
|
|
110
|
+
for (const step of scene.workflow.skills) {
|
|
111
|
+
const skill = this.skills.get(step.skill);
|
|
112
|
+
if (!skill) continue;
|
|
113
|
+
|
|
114
|
+
const stepContext = {
|
|
115
|
+
...context,
|
|
116
|
+
params: { ...step.params, ...params },
|
|
117
|
+
previousResults: results
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const result = await this.executeWithLearning(skill, input, stepContext);
|
|
121
|
+
results.push({
|
|
122
|
+
skill: step.skill,
|
|
123
|
+
result: result
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return {
|
|
128
|
+
type: 'scene_workflow',
|
|
129
|
+
scene: scene.name,
|
|
130
|
+
results: results,
|
|
131
|
+
preferences: scene.preferences
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Format learning response
|
|
137
|
+
*/
|
|
138
|
+
formatLearningResponse(learningResult) {
|
|
139
|
+
const { type, record, confirmation } = learningResult;
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
type: 'learning',
|
|
143
|
+
learningType: type,
|
|
144
|
+
record: record,
|
|
145
|
+
message: confirmation,
|
|
146
|
+
success: true
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Format result
|
|
152
|
+
*/
|
|
153
|
+
formatResult(result, metadata) {
|
|
154
|
+
return {
|
|
155
|
+
type: 'result',
|
|
156
|
+
success: true,
|
|
157
|
+
data: result,
|
|
158
|
+
metadata: metadata,
|
|
159
|
+
timestamp: new Date().toISOString()
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Format error
|
|
165
|
+
*/
|
|
166
|
+
formatError(message, input) {
|
|
167
|
+
return {
|
|
168
|
+
type: 'error',
|
|
169
|
+
success: false,
|
|
170
|
+
message: message,
|
|
171
|
+
input: input,
|
|
172
|
+
timestamp: new Date().toISOString()
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Get learning statistics
|
|
178
|
+
*/
|
|
179
|
+
async getStats() {
|
|
180
|
+
return this.learning.getStats();
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Get the component registry
|
|
185
|
+
* @returns {ComponentRegistry}
|
|
186
|
+
*/
|
|
187
|
+
getComponentRegistry() {
|
|
188
|
+
return this.components;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Get the active adapter for a component type
|
|
193
|
+
* @param {string} componentType
|
|
194
|
+
* @returns {BaseAdapter|null}
|
|
195
|
+
*/
|
|
196
|
+
getAdapter(componentType) {
|
|
197
|
+
return this.components.getAdapter(componentType);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Get component status summary
|
|
202
|
+
* @returns {object}
|
|
203
|
+
*/
|
|
204
|
+
getComponentStatus() {
|
|
205
|
+
return this.components.getStatus();
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Export learnings
|
|
210
|
+
*/
|
|
211
|
+
async exportLearnings(options) {
|
|
212
|
+
return this.learning.export(options);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Import learnings
|
|
217
|
+
*/
|
|
218
|
+
async importLearnings(data) {
|
|
219
|
+
return this.learning.import(data);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
module.exports = FlowMind;
|