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.
Files changed (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +855 -0
  3. package/README_CN.md +854 -0
  4. package/bin/flowmind.js +464 -0
  5. package/core/adapters/api-doc-adapter.js +71 -0
  6. package/core/adapters/base-adapter.js +80 -0
  7. package/core/adapters/database-manager-adapter.js +60 -0
  8. package/core/adapters/database-query-adapter.js +51 -0
  9. package/core/adapters/knowledge-base-adapter.js +75 -0
  10. package/core/adapters/log-service-adapter.js +41 -0
  11. package/core/adapters/mcp-adapter.js +65 -0
  12. package/core/adapters/report-adapter.js +60 -0
  13. package/core/adapters/workflow-adapter.js +62 -0
  14. package/core/component-registry.js +281 -0
  15. package/core/component-types.js +63 -0
  16. package/core/config-manager.js +360 -0
  17. package/core/index.js +223 -0
  18. package/core/learning-engine.js +588 -0
  19. package/core/mcp-compatibility.js +150 -0
  20. package/core/providers/aliyun/dms-adapter.js +98 -0
  21. package/core/providers/aliyun/redis-adapter.js +88 -0
  22. package/core/providers/aliyun/sls-adapter.js +86 -0
  23. package/core/providers/friday/flow-adapter.js +85 -0
  24. package/core/providers/friday/report-adapter.js +83 -0
  25. package/core/providers/yapi/yapi-adapter.js +79 -0
  26. package/core/providers/yuque/yuque-adapter.js +90 -0
  27. package/core/scene-matcher.js +326 -0
  28. package/core/skill-loader.js +291 -0
  29. package/package.json +67 -0
  30. package/scripts/migrate-config.js +153 -0
  31. package/skills/api-sync/SKILL.md +203 -0
  32. package/skills/archive-change/SKILL.md +172 -0
  33. package/skills/auto-flow/SKILL.md +277 -0
  34. package/skills/code-review/SKILL.md +206 -0
  35. package/skills/code-review-audit/SKILL.md +150 -0
  36. package/skills/data-logic-validation/SKILL.md +162 -0
  37. package/skills/data-validation/SKILL.md +210 -0
  38. package/skills/git-review/SKILL.md +190 -0
  39. package/skills/learning-engine/SKILL.md +352 -0
  40. package/skills/learning-feedback/SKILL.md +174 -0
  41. package/skills/log-audit/SKILL.md +226 -0
  42. package/skills/project-review/SKILL.md +196 -0
  43. package/skills/requirement-analyst/SKILL.md +275 -0
  44. package/skills/resource-bind/SKILL.md +222 -0
  45. package/skills/sls-log-audit/SKILL.md +223 -0
  46. package/skills/yapi-sync-interface/SKILL.md +145 -0
  47. package/skills/yuque-sync-design/SKILL.md +157 -0
@@ -0,0 +1,464 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * FlowMind CLI
5
+ * The AI Agent That Learns How You Work
6
+ */
7
+
8
+ const { program } = require('commander');
9
+ const chalk = require('chalk');
10
+ const ora = require('ora');
11
+ const inquirer = require('inquirer');
12
+ const fs = require('fs-extra');
13
+ const path = require('path');
14
+ const FlowMind = require('../core');
15
+
16
+ // Package info
17
+ const packageJson = require('../package.json');
18
+
19
+ // Create FlowMind instance
20
+ let flowmind;
21
+
22
+ /**
23
+ * Initialize FlowMind
24
+ */
25
+ async function initFlowMind(options = {}) {
26
+ flowmind = new FlowMind(options);
27
+ await flowmind.init();
28
+ return flowmind;
29
+ }
30
+
31
+ /**
32
+ * Display banner
33
+ */
34
+ function showBanner() {
35
+ console.log(chalk.cyan(`
36
+ ╔══════════════════════════════════════════════════╗
37
+ ║ ║
38
+ ║ 🧠 FlowMind ║
39
+ ║ The AI Agent That Learns How You Work ║
40
+ ║ ║
41
+ ╚══════════════════════════════════════════════════╝
42
+ `));
43
+ }
44
+
45
+ // CLI Commands
46
+ program
47
+ .name('flowmind')
48
+ .description('The AI Agent That Learns How You Work')
49
+ .version(packageJson.version);
50
+
51
+ // Init command
52
+ program
53
+ .command('init')
54
+ .description('Initialize FlowMind in current directory')
55
+ .action(async () => {
56
+ showBanner();
57
+
58
+ const spinner = ora('Initializing FlowMind...').start();
59
+
60
+ try {
61
+ // Create config directory
62
+ const configDir = path.join(process.env.HOME || process.env.USERPROFILE, '.flowmind');
63
+ await fs.ensureDir(configDir);
64
+ await fs.ensureDir(path.join(configDir, 'learning'));
65
+ await fs.ensureDir(path.join(configDir, 'learning', 'records'));
66
+
67
+ // Create default config
68
+ const configPath = path.join(configDir, 'config.json');
69
+ if (!await fs.pathExists(configPath)) {
70
+ const defaultConfig = {
71
+ version: '1.0.0',
72
+ learning: {
73
+ enabled: true,
74
+ autoApply: true,
75
+ confidenceThreshold: 0.7,
76
+ storagePath: path.join(configDir, 'learning')
77
+ },
78
+ sceneMapping: {
79
+ enabled: true,
80
+ weights: {
81
+ keywordMatch: 0.4,
82
+ patternMatch: 0.3,
83
+ historyScore: 0.2,
84
+ confidence: 0.1
85
+ }
86
+ }
87
+ };
88
+
89
+ await fs.writeJson(configPath, defaultConfig, { spaces: 2 });
90
+ }
91
+
92
+ spinner.succeed('FlowMind initialized successfully!');
93
+
94
+ console.log(chalk.green('\n✓ Configuration created at:'), configDir);
95
+ console.log(chalk.green('✓ Learning system ready'));
96
+ console.log(chalk.green('✓ Scene mapping ready'));
97
+
98
+ console.log(chalk.cyan('\nNext steps:'));
99
+ console.log(' 1. Run', chalk.yellow('flowmind'), 'to start interactive mode');
100
+ console.log(' 2. Or use', chalk.yellow('flowmind "your request"'), 'for single commands');
101
+ console.log(' 3. FlowMind will learn from your corrections automatically');
102
+
103
+ } catch (error) {
104
+ spinner.fail('Failed to initialize FlowMind');
105
+ console.error(chalk.red(error.message));
106
+ }
107
+ });
108
+
109
+ // Process command (default)
110
+ program
111
+ .command('process')
112
+ .alias('p')
113
+ .description('Process a request')
114
+ .argument('[input]', 'Input to process')
115
+ .option('-s, --skill <skill>', 'Use specific skill')
116
+ .option('-v, --verbose', 'Verbose output')
117
+ .action(async (input, options) => {
118
+ try {
119
+ const fm = await initFlowMind();
120
+
121
+ if (!input) {
122
+ // Interactive mode
123
+ await runInteractiveMode(fm);
124
+ } else {
125
+ // Single command mode
126
+ const spinner = ora('Processing...').start();
127
+
128
+ const result = await fm.process(input, {
129
+ skill: options.skill,
130
+ verbose: options.verbose
131
+ });
132
+
133
+ spinner.stop();
134
+ displayResult(result);
135
+ }
136
+ } catch (error) {
137
+ console.error(chalk.red('Error:'), error.message);
138
+ }
139
+ });
140
+
141
+ // Learn command
142
+ program
143
+ .command('learn')
144
+ .description('Manage learning records')
145
+ .option('-l, --list', 'List learning records')
146
+ .option('-s, --skill <skill>', 'Filter by skill')
147
+ .option('-t, --type <type>', 'Filter by type')
148
+ .option('-e, --export [file]', 'Export learnings')
149
+ .option('-i, --import <file>', 'Import learnings')
150
+ .option('-r, --reset <skill>', 'Reset skill learnings')
151
+ .option('-d, --delete <id>', 'Delete learning record')
152
+ .action(async (options) => {
153
+ try {
154
+ const fm = await initFlowMind();
155
+
156
+ if (options.list) {
157
+ const stats = await fm.getStats();
158
+ displayStats(stats);
159
+ } else if (options.export) {
160
+ const exportPath = options.export || 'flowmind-learnings.json';
161
+ await fm.exportLearnings({ output: exportPath });
162
+ console.log(chalk.green('✓ Learnings exported to:'), exportPath);
163
+ } else if (options.import) {
164
+ const data = await fs.readJson(options.import);
165
+ await fm.importLearnings(data);
166
+ console.log(chalk.green('✓ Learnings imported successfully'));
167
+ } else if (options.reset) {
168
+ console.log(chalk.yellow('Resetting learnings for:'), options.reset);
169
+ // Implementation would go here
170
+ } else if (options.delete) {
171
+ console.log(chalk.yellow('Deleting learning:'), options.delete);
172
+ // Implementation would go here
173
+ } else {
174
+ // Default to list
175
+ const stats = await fm.getStats();
176
+ displayStats(stats);
177
+ }
178
+ } catch (error) {
179
+ console.error(chalk.red('Error:'), error.message);
180
+ }
181
+ });
182
+
183
+ // Scenes command
184
+ program
185
+ .command('scenes')
186
+ .description('Manage scene mappings')
187
+ .option('-l, --list', 'List scenes')
188
+ .option('-a, --add', 'Add new scene')
189
+ .option('-r, --remove <id>', 'Remove scene')
190
+ .option('-e, --export [file]', 'Export scenes')
191
+ .action(async (options) => {
192
+ try {
193
+ const fm = await initFlowMind();
194
+
195
+ if (options.list) {
196
+ const scenes = fm.matcher.listScenes();
197
+ displayScenes(scenes);
198
+ } else if (options.add) {
199
+ await addSceneInteractive(fm);
200
+ } else if (options.remove) {
201
+ await fm.matcher.removeScene(options.remove);
202
+ console.log(chalk.green('✓ Scene removed'));
203
+ } else if (options.export) {
204
+ const exportPath = options.export || 'flowmind-scenes.json';
205
+ const scenes = fm.matcher.listScenes();
206
+ await fs.writeJson(exportPath, scenes, { spaces: 2 });
207
+ console.log(chalk.green('✓ Scenes exported to:'), exportPath);
208
+ } else {
209
+ // Default to list
210
+ const scenes = fm.matcher.listScenes();
211
+ displayScenes(scenes);
212
+ }
213
+ } catch (error) {
214
+ console.error(chalk.red('Error:'), error.message);
215
+ }
216
+ });
217
+
218
+ // Skills command
219
+ program
220
+ .command('skills')
221
+ .description('List available skills')
222
+ .action(async () => {
223
+ try {
224
+ const fm = await initFlowMind();
225
+ const skills = fm.skills.list();
226
+ displaySkills(skills);
227
+ } catch (error) {
228
+ console.error(chalk.red('Error:'), error.message);
229
+ }
230
+ });
231
+
232
+ // Stats command
233
+ program
234
+ .command('stats')
235
+ .description('Show FlowMind statistics')
236
+ .action(async () => {
237
+ try {
238
+ const fm = await initFlowMind();
239
+ const stats = await fm.getStats();
240
+ displayStats(stats);
241
+ } catch (error) {
242
+ console.error(chalk.red('Error:'), error.message);
243
+ }
244
+ });
245
+
246
+ // Config command
247
+ program
248
+ .command('config')
249
+ .description('Manage configuration')
250
+ .option('-l, --list', 'List configuration')
251
+ .option('-s, --set <key> <value>', 'Set configuration value')
252
+ .option('-g, --get <key>', 'Get configuration value')
253
+ .action(async (options) => {
254
+ try {
255
+ const fm = await initFlowMind();
256
+
257
+ if (options.list) {
258
+ const config = fm.config.getAll();
259
+ console.log(chalk.cyan('\nFlowMind Configuration:'));
260
+ console.log(JSON.stringify(config, null, 2));
261
+ } else if (options.set && options.value) {
262
+ fm.config.set(options.set, options.value);
263
+ await fm.config.save();
264
+ console.log(chalk.green('✓ Configuration updated'));
265
+ } else if (options.get) {
266
+ const value = fm.config.get(options.get);
267
+ console.log(value);
268
+ } else {
269
+ const config = fm.config.getAll();
270
+ console.log(JSON.stringify(config, null, 2));
271
+ }
272
+ } catch (error) {
273
+ console.error(chalk.red('Error:'), error.message);
274
+ }
275
+ });
276
+
277
+ // Interactive mode
278
+ async function runInteractiveMode(fm) {
279
+ showBanner();
280
+ console.log(chalk.cyan('Interactive mode started. Type "exit" to quit.\n'));
281
+
282
+ while (true) {
283
+ const { input } = await inquirer.prompt([
284
+ {
285
+ type: 'input',
286
+ name: 'input',
287
+ message: chalk.green('You:'),
288
+ prefix: ''
289
+ }
290
+ ]);
291
+
292
+ if (input.toLowerCase() === 'exit' || input.toLowerCase() === 'quit') {
293
+ console.log(chalk.cyan('\nGoodbye! FlowMind will remember your preferences. 👋\n'));
294
+ break;
295
+ }
296
+
297
+ if (!input.trim()) continue;
298
+
299
+ const spinner = ora('Thinking...').start();
300
+
301
+ try {
302
+ const result = await fm.process(input);
303
+ spinner.stop();
304
+ displayResult(result);
305
+ } catch (error) {
306
+ spinner.stop();
307
+ console.error(chalk.red('Error:'), error.message);
308
+ }
309
+
310
+ console.log(''); // Empty line for spacing
311
+ }
312
+ }
313
+
314
+ // Add scene interactive
315
+ async function addSceneInteractive(fm) {
316
+ const answers = await inquirer.prompt([
317
+ {
318
+ type: 'input',
319
+ name: 'name',
320
+ message: 'Scene name:',
321
+ },
322
+ {
323
+ type: 'input',
324
+ name: 'keywords',
325
+ message: 'Keywords (comma separated):',
326
+ },
327
+ {
328
+ type: 'input',
329
+ name: 'patterns',
330
+ message: 'Trigger patterns (comma separated):',
331
+ },
332
+ {
333
+ type: 'input',
334
+ name: 'skills',
335
+ message: 'Skills to execute (comma separated):',
336
+ }
337
+ ]);
338
+
339
+ const scene = {
340
+ name: answers.name,
341
+ keywords: answers.keywords.split(',').map(k => k.trim()),
342
+ patterns: answers.patterns.split(',').map(p => p.trim()),
343
+ workflow: {
344
+ skills: answers.skills.split(',').map(s => ({
345
+ skill: s.trim(),
346
+ params: {}
347
+ }))
348
+ }
349
+ };
350
+
351
+ await fm.matcher.addScene(scene);
352
+ console.log(chalk.green('✓ Scene added successfully'));
353
+ }
354
+
355
+ // Display functions
356
+ function displayResult(result) {
357
+ if (result.type === 'learning') {
358
+ console.log(chalk.cyan(result.message));
359
+ } else if (result.type === 'result') {
360
+ console.log(chalk.white('\n┌─────────────────────────────────────────────────────┐'));
361
+ console.log(chalk.white('│ Result │'));
362
+ console.log(chalk.white('├─────────────────────────────────────────────────────┤'));
363
+
364
+ if (result.metadata?.skill) {
365
+ console.log(chalk.white(`│ Skill: ${result.metadata.skill}`));
366
+ }
367
+ if (result.metadata?.duration) {
368
+ console.log(chalk.white(`│ Duration: ${result.metadata.duration}ms`));
369
+ }
370
+ if (result.metadata?.sceneMatch) {
371
+ console.log(chalk.white(`│ Scene: ${result.metadata.sceneMatch.scene.name}`));
372
+ }
373
+
374
+ console.log(chalk.white('├─────────────────────────────────────────────────────┤'));
375
+ console.log(chalk.white('│'));
376
+
377
+ if (typeof result.data === 'string') {
378
+ console.log(chalk.white(result.data));
379
+ } else {
380
+ console.log(chalk.white(JSON.stringify(result.data, null, 2)));
381
+ }
382
+
383
+ console.log(chalk.white('│'));
384
+ console.log(chalk.white('└─────────────────────────────────────────────────────┘'));
385
+ } else if (result.type === 'error') {
386
+ console.log(chalk.red('\n✗ Error:'), result.message);
387
+ }
388
+ }
389
+
390
+ function displayStats(stats) {
391
+ console.log(chalk.cyan('\n┌─────────────────────────────────────────────────────┐'));
392
+ console.log(chalk.cyan('│ FlowMind Statistics │'));
393
+ console.log(chalk.cyan('├─────────────────────────────────────────────────────┤'));
394
+ console.log(chalk.cyan(`│ Total Learning Records: ${stats.totalRecords || 0}`));
395
+ console.log(chalk.cyan(`│ Last Learning: ${stats.lastLearning || 'Never'}`));
396
+ console.log(chalk.cyan('├─────────────────────────────────────────────────────┤'));
397
+
398
+ if (stats.byType && Object.keys(stats.byType).length > 0) {
399
+ console.log(chalk.cyan('│ By Type:'));
400
+ for (const [type, count] of Object.entries(stats.byType)) {
401
+ console.log(chalk.cyan(`│ ${type}: ${count}`));
402
+ }
403
+ }
404
+
405
+ if (stats.bySkill && Object.keys(stats.bySkill).length > 0) {
406
+ console.log(chalk.cyan('├─────────────────────────────────────────────────────┤'));
407
+ console.log(chalk.cyan('│ By Skill:'));
408
+ for (const [skill, count] of Object.entries(stats.bySkill)) {
409
+ console.log(chalk.cyan(`│ ${skill}: ${count}`));
410
+ }
411
+ }
412
+
413
+ console.log(chalk.cyan('└─────────────────────────────────────────────────────┘'));
414
+ }
415
+
416
+ function displayScenes(scenes) {
417
+ console.log(chalk.cyan('\n┌─────────────────────────────────────────────────────┐'));
418
+ console.log(chalk.cyan('│ Scene Mappings │'));
419
+ console.log(chalk.cyan('├─────────────────────────────────────────────────────┤'));
420
+
421
+ if (scenes.length === 0) {
422
+ console.log(chalk.cyan('│ No scenes defined yet. │'));
423
+ } else {
424
+ for (const scene of scenes) {
425
+ console.log(chalk.cyan(`│ ${scene.name}`));
426
+ console.log(chalk.cyan(`│ Keywords: ${scene.keywords?.join(', ') || 'N/A'}`));
427
+ console.log(chalk.cyan(`│ Used: ${scene.useCount || 0} times`));
428
+ console.log(chalk.cyan('├─────────────────────────────────────────────────────┤'));
429
+ }
430
+ }
431
+
432
+ console.log(chalk.cyan('└─────────────────────────────────────────────────────┘'));
433
+ }
434
+
435
+ function displaySkills(skills) {
436
+ console.log(chalk.cyan('\n┌─────────────────────────────────────────────────────┐'));
437
+ console.log(chalk.cyan('│ Available Skills │'));
438
+ console.log(chalk.cyan('├─────────────────────────────────────────────────────┤'));
439
+
440
+ for (const skill of skills) {
441
+ console.log(chalk.cyan(`│ ${skill.name}`));
442
+ if (skill.description) {
443
+ console.log(chalk.cyan(`│ ${skill.description.substring(0, 50)}...`));
444
+ }
445
+ console.log(chalk.cyan('├─────────────────────────────────────────────────────┤'));
446
+ }
447
+
448
+ console.log(chalk.cyan('└─────────────────────────────────────────────────────┘'));
449
+ }
450
+
451
+ // Parse arguments
452
+ program.parse(process.argv);
453
+
454
+ // Default to interactive mode if no command specified
455
+ if (!process.argv.slice(2).length) {
456
+ (async () => {
457
+ try {
458
+ const fm = await initFlowMind();
459
+ await runInteractiveMode(fm);
460
+ } catch (error) {
461
+ console.error(chalk.red('Error:'), error.message);
462
+ }
463
+ })();
464
+ }
@@ -0,0 +1,71 @@
1
+ /**
2
+ * FlowMind API Doc Adapter Interface
3
+ * Abstract interface for API documentation services (YApi, Swagger Hub, etc.)
4
+ */
5
+
6
+ const McpAdapter = require('./mcp-adapter');
7
+ const { ComponentType } = require('../component-types');
8
+
9
+ class ApiDocAdapter extends McpAdapter {
10
+ get componentType() {
11
+ return ComponentType.API_DOC;
12
+ }
13
+
14
+ /**
15
+ * Search APIs by keyword.
16
+ * @param {object} params - { nameKeyword, pathKeyword, projectKeyword }
17
+ * @returns {Promise<object>}
18
+ */
19
+ async searchApis(params) {
20
+ throw new Error('Subclasses must implement searchApis()');
21
+ }
22
+
23
+ /**
24
+ * Get categories for a project.
25
+ * @param {string} projectId
26
+ * @returns {Promise<object>}
27
+ */
28
+ async getCategories(projectId) {
29
+ throw new Error('Subclasses must implement getCategories()');
30
+ }
31
+
32
+ /**
33
+ * Save (create/update) an API interface.
34
+ * @param {object} apiData
35
+ * @returns {Promise<object>}
36
+ */
37
+ async saveApi(apiData) {
38
+ throw new Error('Subclasses must implement saveApi()');
39
+ }
40
+
41
+ /**
42
+ * Import Swagger/OpenAPI data.
43
+ * @param {string} projectId
44
+ * @param {string} catId
45
+ * @param {string} swaggerData
46
+ * @returns {Promise<object>}
47
+ */
48
+ async importSwagger(projectId, catId, swaggerData) {
49
+ throw new Error('Subclasses must implement importSwagger()');
50
+ }
51
+
52
+ /**
53
+ * Export project data.
54
+ * @param {string} projectId
55
+ * @param {string} type - 'json', 'markdown', 'swagger'
56
+ * @returns {Promise<object>}
57
+ */
58
+ async exportProject(projectId, type) {
59
+ throw new Error('Subclasses must implement exportProject()');
60
+ }
61
+
62
+ /**
63
+ * List projects.
64
+ * @returns {Promise<object>}
65
+ */
66
+ async listProjects() {
67
+ throw new Error('Subclasses must implement listProjects()');
68
+ }
69
+ }
70
+
71
+ module.exports = ApiDocAdapter;
@@ -0,0 +1,80 @@
1
+ /**
2
+ * FlowMind Base Adapter
3
+ * Abstract base class for all component adapters
4
+ */
5
+
6
+ class BaseAdapter {
7
+ constructor(providerName, config = {}) {
8
+ this.providerName = providerName;
9
+ this.config = config;
10
+ this.enabled = config.enabled !== false;
11
+ this._initialized = false;
12
+ }
13
+
14
+ /**
15
+ * Get the component type this adapter implements.
16
+ * Subclasses must override this.
17
+ * @returns {string} ComponentType value
18
+ */
19
+ get componentType() {
20
+ throw new Error('Subclasses must implement componentType getter');
21
+ }
22
+
23
+ /**
24
+ * Get the MCP server name associated with this adapter, if any.
25
+ * @returns {string|null}
26
+ */
27
+ get mcpServer() {
28
+ return this.config.mcpServer || null;
29
+ }
30
+
31
+ /**
32
+ * Initialize the adapter. Called once before first use.
33
+ * @returns {Promise<void>}
34
+ */
35
+ async init() {
36
+ this._initialized = true;
37
+ }
38
+
39
+ /**
40
+ * Check if the adapter is ready to serve requests.
41
+ * @returns {boolean}
42
+ */
43
+ isReady() {
44
+ return this.enabled && this._initialized;
45
+ }
46
+
47
+ /**
48
+ * Get adapter status information.
49
+ * @returns {object}
50
+ */
51
+ getStatus() {
52
+ return {
53
+ provider: this.providerName,
54
+ type: this.componentType,
55
+ enabled: this.enabled,
56
+ initialized: this._initialized,
57
+ mcpServer: this.mcpServer
58
+ };
59
+ }
60
+
61
+ /**
62
+ * Get the list of MCP tool names this adapter provides.
63
+ * Subclasses should override to declare their tools.
64
+ * @returns {string[]}
65
+ */
66
+ getProvidedTools() {
67
+ return [];
68
+ }
69
+
70
+ /**
71
+ * Check if a specific MCP tool is provided by this adapter.
72
+ * @param {string} toolName
73
+ * @returns {boolean}
74
+ */
75
+ hasTool(toolName) {
76
+ return this.getProvidedTools().includes(toolName);
77
+ }
78
+ }
79
+
80
+ module.exports = BaseAdapter;
@@ -0,0 +1,60 @@
1
+ /**
2
+ * FlowMind Database Manager Adapter Interface
3
+ * Abstract interface for database management services (DMS, etc.)
4
+ */
5
+
6
+ const McpAdapter = require('./mcp-adapter');
7
+ const { ComponentType } = require('../component-types');
8
+
9
+ class DatabaseManagerAdapter extends McpAdapter {
10
+ get componentType() {
11
+ return ComponentType.DATABASE_MANAGER;
12
+ }
13
+
14
+ /**
15
+ * List database instances.
16
+ * @param {object} params - Optional filter params
17
+ * @returns {Promise<object>}
18
+ */
19
+ async listInstances(params) {
20
+ throw new Error('Subclasses must implement listInstances()');
21
+ }
22
+
23
+ /**
24
+ * Execute a SQL script against a database.
25
+ * @param {object} params - { database_id, script }
26
+ * @returns {Promise<object>}
27
+ */
28
+ async executeScript(params) {
29
+ throw new Error('Subclasses must implement executeScript()');
30
+ }
31
+
32
+ /**
33
+ * Search for databases by name.
34
+ * @param {string} searchKey
35
+ * @returns {Promise<object>}
36
+ */
37
+ async searchDatabase(searchKey) {
38
+ throw new Error('Subclasses must implement searchDatabase()');
39
+ }
40
+
41
+ /**
42
+ * List tables in a database.
43
+ * @param {string} databaseId
44
+ * @returns {Promise<object>}
45
+ */
46
+ async listTables(databaseId) {
47
+ throw new Error('Subclasses must implement listTables()');
48
+ }
49
+
50
+ /**
51
+ * Get table detail information.
52
+ * @param {string} tableGuid
53
+ * @returns {Promise<object>}
54
+ */
55
+ async getTableDetail(tableGuid) {
56
+ throw new Error('Subclasses must implement getTableDetail()');
57
+ }
58
+ }
59
+
60
+ module.exports = DatabaseManagerAdapter;