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,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FlowMind Database Query Adapter Interface
|
|
3
|
+
* Abstract interface for direct database query services
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const McpAdapter = require('./mcp-adapter');
|
|
7
|
+
const { ComponentType } = require('../component-types');
|
|
8
|
+
|
|
9
|
+
class DatabaseQueryAdapter extends McpAdapter {
|
|
10
|
+
get componentType() {
|
|
11
|
+
return ComponentType.DATABASE_QUERY;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Get available data sources.
|
|
16
|
+
* @returns {Promise<object>}
|
|
17
|
+
*/
|
|
18
|
+
async fetchSources() {
|
|
19
|
+
throw new Error('Subclasses must implement fetchSources()');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Get databases for a data source.
|
|
24
|
+
* @param {string} sourceId
|
|
25
|
+
* @returns {Promise<object>}
|
|
26
|
+
*/
|
|
27
|
+
async fetchDatabases(sourceId) {
|
|
28
|
+
throw new Error('Subclasses must implement fetchDatabases()');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Get tables in a database.
|
|
33
|
+
* @param {string} sourceId
|
|
34
|
+
* @param {string} schema
|
|
35
|
+
* @returns {Promise<object>}
|
|
36
|
+
*/
|
|
37
|
+
async fetchTables(sourceId, schema) {
|
|
38
|
+
throw new Error('Subclasses must implement fetchTables()');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Execute a SELECT query.
|
|
43
|
+
* @param {object} params - { source_id, schema, sql }
|
|
44
|
+
* @returns {Promise<object>}
|
|
45
|
+
*/
|
|
46
|
+
async queryExec(params) {
|
|
47
|
+
throw new Error('Subclasses must implement queryExec()');
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
module.exports = DatabaseQueryAdapter;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FlowMind Knowledge Base Adapter Interface
|
|
3
|
+
* Abstract interface for knowledge base services (Yuque, Notion, Confluence, etc.)
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const McpAdapter = require('./mcp-adapter');
|
|
7
|
+
const { ComponentType } = require('../component-types');
|
|
8
|
+
|
|
9
|
+
class KnowledgeBaseAdapter extends McpAdapter {
|
|
10
|
+
get componentType() {
|
|
11
|
+
return ComponentType.KNOWLEDGE_BASE;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Get user's repositories/knowledge bases.
|
|
16
|
+
* @param {object} params
|
|
17
|
+
* @returns {Promise<object>}
|
|
18
|
+
*/
|
|
19
|
+
async getRepos(params) {
|
|
20
|
+
throw new Error('Subclasses must implement getRepos()');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Get documents in a repository.
|
|
25
|
+
* @param {string} namespace
|
|
26
|
+
* @param {object} params
|
|
27
|
+
* @returns {Promise<object>}
|
|
28
|
+
*/
|
|
29
|
+
async getDocs(namespace, params) {
|
|
30
|
+
throw new Error('Subclasses must implement getDocs()');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Get a specific document.
|
|
35
|
+
* @param {string} namespace
|
|
36
|
+
* @param {string} slug
|
|
37
|
+
* @returns {Promise<object>}
|
|
38
|
+
*/
|
|
39
|
+
async getDoc(namespace, slug) {
|
|
40
|
+
throw new Error('Subclasses must implement getDoc()');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Create a new document.
|
|
45
|
+
* @param {string} namespace
|
|
46
|
+
* @param {object} docData - { slug, title, body, format }
|
|
47
|
+
* @returns {Promise<object>}
|
|
48
|
+
*/
|
|
49
|
+
async createDoc(namespace, docData) {
|
|
50
|
+
throw new Error('Subclasses must implement createDoc()');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Update an existing document.
|
|
55
|
+
* @param {string} namespace
|
|
56
|
+
* @param {string} slug
|
|
57
|
+
* @param {object} docData
|
|
58
|
+
* @returns {Promise<object>}
|
|
59
|
+
*/
|
|
60
|
+
async updateDoc(namespace, slug, docData) {
|
|
61
|
+
throw new Error('Subclasses must implement updateDoc()');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Search documents or repositories.
|
|
66
|
+
* @param {string} query
|
|
67
|
+
* @param {string} type - 'doc' or 'repo'
|
|
68
|
+
* @returns {Promise<object>}
|
|
69
|
+
*/
|
|
70
|
+
async search(query, type) {
|
|
71
|
+
throw new Error('Subclasses must implement search()');
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
module.exports = KnowledgeBaseAdapter;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FlowMind Log Service Adapter Interface
|
|
3
|
+
* Abstract interface for cloud log service providers (SLS, ELK, etc.)
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const McpAdapter = require('./mcp-adapter');
|
|
7
|
+
const { ComponentType } = require('../component-types');
|
|
8
|
+
|
|
9
|
+
class LogServiceAdapter extends McpAdapter {
|
|
10
|
+
get componentType() {
|
|
11
|
+
return ComponentType.LOG_SERVICE;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Get available log store endpoints.
|
|
16
|
+
* @returns {object} Map of environment to endpoint
|
|
17
|
+
*/
|
|
18
|
+
getEndpoints() {
|
|
19
|
+
return this.config.endpoints || {};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Query logs with parameters.
|
|
24
|
+
* Subclasses must implement the actual MCP tool call.
|
|
25
|
+
* @param {object} params - { project, logstore, query, from, to, line }
|
|
26
|
+
* @returns {Promise<object>}
|
|
27
|
+
*/
|
|
28
|
+
async queryLogs(params) {
|
|
29
|
+
throw new Error('Subclasses must implement queryLogs()');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* List available projects.
|
|
34
|
+
* @returns {Promise<object>}
|
|
35
|
+
*/
|
|
36
|
+
async listProjects() {
|
|
37
|
+
throw new Error('Subclasses must implement listProjects()');
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
module.exports = LogServiceAdapter;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FlowMind MCP Adapter
|
|
3
|
+
* Base class for adapters that wrap MCP server tools
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const BaseAdapter = require('./base-adapter');
|
|
7
|
+
|
|
8
|
+
class McpAdapter extends BaseAdapter {
|
|
9
|
+
constructor(providerName, config = {}) {
|
|
10
|
+
super(providerName, config);
|
|
11
|
+
this.mcpTools = new Map();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Register an MCP tool mapping.
|
|
16
|
+
* @param {string} localName - The abstract tool name used by skills
|
|
17
|
+
* @param {string} mcpToolName - The actual MCP tool name on the server
|
|
18
|
+
*/
|
|
19
|
+
registerTool(localName, mcpToolName) {
|
|
20
|
+
this.mcpTools.set(localName, mcpToolName);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Get the actual MCP tool name for a local tool name.
|
|
25
|
+
* @param {string} localName
|
|
26
|
+
* @returns {string|null}
|
|
27
|
+
*/
|
|
28
|
+
resolveTool(localName) {
|
|
29
|
+
return this.mcpTools.get(localName) || null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Get all registered tool mappings.
|
|
34
|
+
* @returns {object}
|
|
35
|
+
*/
|
|
36
|
+
getToolMappings() {
|
|
37
|
+
const mappings = {};
|
|
38
|
+
for (const [local, mcp] of this.mcpTools) {
|
|
39
|
+
mappings[local] = mcp;
|
|
40
|
+
}
|
|
41
|
+
return mappings;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Get the list of abstract tool names this adapter provides.
|
|
46
|
+
* @returns {string[]}
|
|
47
|
+
*/
|
|
48
|
+
getProvidedTools() {
|
|
49
|
+
return Array.from(this.mcpTools.keys());
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Get the MCP server name for tool invocation context.
|
|
54
|
+
* Skills use this to know which MCP server to call.
|
|
55
|
+
* @returns {string}
|
|
56
|
+
*/
|
|
57
|
+
getMcpServerContext() {
|
|
58
|
+
return {
|
|
59
|
+
server: this.mcpServer,
|
|
60
|
+
tools: this.getToolMappings()
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
module.exports = McpAdapter;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FlowMind Report Adapter Interface
|
|
3
|
+
* Abstract interface for automated reporting services
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const McpAdapter = require('./mcp-adapter');
|
|
7
|
+
const { ComponentType } = require('../component-types');
|
|
8
|
+
|
|
9
|
+
class ReportAdapter extends McpAdapter {
|
|
10
|
+
get componentType() {
|
|
11
|
+
return ComponentType.REPORT;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* List Jenkins builds.
|
|
16
|
+
* @param {object} params
|
|
17
|
+
* @returns {Promise<object>}
|
|
18
|
+
*/
|
|
19
|
+
async listBuilds(params) {
|
|
20
|
+
throw new Error('Subclasses must implement listBuilds()');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Get build details.
|
|
25
|
+
* @param {string} buildId
|
|
26
|
+
* @returns {Promise<object>}
|
|
27
|
+
*/
|
|
28
|
+
async getBuildInfo(buildId) {
|
|
29
|
+
throw new Error('Subclasses must implement getBuildInfo()');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* List Jacoco coverage reports.
|
|
34
|
+
* @param {object} params
|
|
35
|
+
* @returns {Promise<object>}
|
|
36
|
+
*/
|
|
37
|
+
async listJacocoReports(params) {
|
|
38
|
+
throw new Error('Subclasses must implement listJacocoReports()');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* List unit test reports.
|
|
43
|
+
* @param {object} params
|
|
44
|
+
* @returns {Promise<object>}
|
|
45
|
+
*/
|
|
46
|
+
async listUnitReports(params) {
|
|
47
|
+
throw new Error('Subclasses must implement listUnitReports()');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Get Jenkins job details.
|
|
52
|
+
* @param {string} jobName
|
|
53
|
+
* @returns {Promise<object>}
|
|
54
|
+
*/
|
|
55
|
+
async getJobDetails(jobName) {
|
|
56
|
+
throw new Error('Subclasses must implement getJobDetails()');
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
module.exports = ReportAdapter;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FlowMind Workflow Adapter Interface
|
|
3
|
+
* Abstract interface for workflow/pipeline services
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const McpAdapter = require('./mcp-adapter');
|
|
7
|
+
const { ComponentType } = require('../component-types');
|
|
8
|
+
|
|
9
|
+
class WorkflowAdapter extends McpAdapter {
|
|
10
|
+
get componentType() {
|
|
11
|
+
return ComponentType.WORKFLOW;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* List pipeline groups.
|
|
16
|
+
* @param {object} params
|
|
17
|
+
* @returns {Promise<object>}
|
|
18
|
+
*/
|
|
19
|
+
async listPipelineGroups(params) {
|
|
20
|
+
throw new Error('Subclasses must implement listPipelineGroups()');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* List pipelines.
|
|
25
|
+
* @param {object} params
|
|
26
|
+
* @returns {Promise<object>}
|
|
27
|
+
*/
|
|
28
|
+
async listPipelines(params) {
|
|
29
|
+
throw new Error('Subclasses must implement listPipelines()');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Start a pipeline run.
|
|
34
|
+
* @param {string} pipelineId
|
|
35
|
+
* @returns {Promise<object>}
|
|
36
|
+
*/
|
|
37
|
+
async startPipelineRun(pipelineId) {
|
|
38
|
+
throw new Error('Subclasses must implement startPipelineRun()');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Get pipeline run status.
|
|
43
|
+
* @param {string} pipelineId
|
|
44
|
+
* @param {string} runId
|
|
45
|
+
* @returns {Promise<object>}
|
|
46
|
+
*/
|
|
47
|
+
async getPipelineRun(pipelineId, runId) {
|
|
48
|
+
throw new Error('Subclasses must implement getPipelineRun()');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* List pipeline runs.
|
|
53
|
+
* @param {string} pipelineId
|
|
54
|
+
* @param {object} params
|
|
55
|
+
* @returns {Promise<object>}
|
|
56
|
+
*/
|
|
57
|
+
async listPipelineRuns(pipelineId, params) {
|
|
58
|
+
throw new Error('Subclasses must implement listPipelineRuns()');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
module.exports = WorkflowAdapter;
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FlowMind Component Registry
|
|
3
|
+
* Central registry for pluggable component adapters.
|
|
4
|
+
* Manages component discovery, registration, and provider switching.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { ComponentType, ComponentTypeMeta } = require('./component-types');
|
|
8
|
+
const McpCompatibility = require('./mcp-compatibility');
|
|
9
|
+
|
|
10
|
+
class ComponentRegistry {
|
|
11
|
+
constructor(config) {
|
|
12
|
+
this.config = config;
|
|
13
|
+
// Map<ComponentType, Map<providerName, adapter>>
|
|
14
|
+
this.adapters = new Map();
|
|
15
|
+
// Map<ComponentType, providerName> - which provider is active for each type
|
|
16
|
+
this.activeProviders = new Map();
|
|
17
|
+
// Built-in provider factories
|
|
18
|
+
this.providerFactories = new Map();
|
|
19
|
+
this.initialized = false;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Initialize the registry: register built-in providers and load config.
|
|
24
|
+
*/
|
|
25
|
+
async init() {
|
|
26
|
+
this.registerBuiltinProviders();
|
|
27
|
+
await this.loadFromConfig();
|
|
28
|
+
this.initialized = true;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Register built-in provider factories.
|
|
33
|
+
*/
|
|
34
|
+
registerBuiltinProviders() {
|
|
35
|
+
// Aliyun providers
|
|
36
|
+
this.registerFactory('aliyun-sls', () => {
|
|
37
|
+
const AliyunSlsAdapter = require('./providers/aliyun/sls-adapter');
|
|
38
|
+
return new AliyunSlsAdapter(this.getProviderConfig('logService', 'aliyun-sls'));
|
|
39
|
+
});
|
|
40
|
+
this.registerFactory('aliyun-dms', () => {
|
|
41
|
+
const AliyunDmsAdapter = require('./providers/aliyun/dms-adapter');
|
|
42
|
+
return new AliyunDmsAdapter(this.getProviderConfig('databaseManager', 'aliyun-dms'));
|
|
43
|
+
});
|
|
44
|
+
this.registerFactory('aliyun-redis', () => {
|
|
45
|
+
const AliyunRedisAdapter = require('./providers/aliyun/redis-adapter');
|
|
46
|
+
return new AliyunRedisAdapter(this.getProviderConfig('redisMonitor', 'aliyun-redis'));
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// YApi provider
|
|
50
|
+
this.registerFactory('yapi', () => {
|
|
51
|
+
const YapiAdapter = require('./providers/yapi/yapi-adapter');
|
|
52
|
+
return new YapiAdapter(this.getProviderConfig('apiDoc', 'yapi'));
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Yuque provider
|
|
56
|
+
this.registerFactory('yuque', () => {
|
|
57
|
+
const YuqueAdapter = require('./providers/yuque/yuque-adapter');
|
|
58
|
+
return new YuqueAdapter(this.getProviderConfig('knowledgeBase', 'yuque'));
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Friday providers
|
|
62
|
+
this.registerFactory('friday-flow', () => {
|
|
63
|
+
const FridayFlowAdapter = require('./providers/friday/flow-adapter');
|
|
64
|
+
return new FridayFlowAdapter(this.getProviderConfig('workflow', 'friday-flow'));
|
|
65
|
+
});
|
|
66
|
+
this.registerFactory('friday-report', () => {
|
|
67
|
+
const FridayReportAdapter = require('./providers/friday/report-adapter');
|
|
68
|
+
return new FridayReportAdapter(this.getProviderConfig('report', 'friday-report'));
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Get provider config from the component config.
|
|
74
|
+
* @param {string} componentType
|
|
75
|
+
* @param {string} providerName
|
|
76
|
+
* @returns {object}
|
|
77
|
+
*/
|
|
78
|
+
getProviderConfig(componentType, providerName) {
|
|
79
|
+
const components = this.config.get('components', {});
|
|
80
|
+
const typeConfig = components[componentType] || {};
|
|
81
|
+
const providers = typeConfig.providers || {};
|
|
82
|
+
return providers[providerName] || {};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Register a provider factory function.
|
|
87
|
+
* @param {string} providerName
|
|
88
|
+
* @param {function} factory - Function that returns an adapter instance
|
|
89
|
+
*/
|
|
90
|
+
registerFactory(providerName, factory) {
|
|
91
|
+
this.providerFactories.set(providerName, factory);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Load and activate providers based on configuration.
|
|
96
|
+
*/
|
|
97
|
+
async loadFromConfig() {
|
|
98
|
+
const components = this.config.get('components', {});
|
|
99
|
+
|
|
100
|
+
for (const type of Object.values(ComponentType)) {
|
|
101
|
+
const typeConfig = components[type];
|
|
102
|
+
if (!typeConfig) continue;
|
|
103
|
+
|
|
104
|
+
const defaultProvider = typeConfig.default;
|
|
105
|
+
const providers = typeConfig.providers || {};
|
|
106
|
+
|
|
107
|
+
for (const [providerName, providerConfig] of Object.entries(providers)) {
|
|
108
|
+
if (providerConfig.enabled === false) continue;
|
|
109
|
+
|
|
110
|
+
const adapter = this.createAdapter(providerName, providerConfig);
|
|
111
|
+
if (adapter) {
|
|
112
|
+
this.register(type, providerName, adapter);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Set default provider
|
|
117
|
+
if (defaultProvider && this.adapters.get(type)?.has(defaultProvider)) {
|
|
118
|
+
this.activeProviders.set(type, defaultProvider);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Create an adapter instance from a provider name.
|
|
125
|
+
* @param {string} providerName
|
|
126
|
+
* @param {object} providerConfig
|
|
127
|
+
* @returns {BaseAdapter|null}
|
|
128
|
+
*/
|
|
129
|
+
createAdapter(providerName, providerConfig) {
|
|
130
|
+
const factory = this.providerFactories.get(providerName);
|
|
131
|
+
if (!factory) {
|
|
132
|
+
console.warn(`No factory registered for provider: ${providerName}`);
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
try {
|
|
136
|
+
return factory();
|
|
137
|
+
} catch (error) {
|
|
138
|
+
console.warn(`Failed to create adapter for ${providerName}:`, error.message);
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Register an adapter for a component type.
|
|
145
|
+
* @param {string} componentType - ComponentType value
|
|
146
|
+
* @param {string} providerName
|
|
147
|
+
* @param {BaseAdapter} adapter
|
|
148
|
+
*/
|
|
149
|
+
register(componentType, providerName, adapter) {
|
|
150
|
+
if (!this.adapters.has(componentType)) {
|
|
151
|
+
this.adapters.set(componentType, new Map());
|
|
152
|
+
}
|
|
153
|
+
this.adapters.get(componentType).set(providerName, adapter);
|
|
154
|
+
|
|
155
|
+
// If this is the first provider for this type, make it active
|
|
156
|
+
if (!this.activeProviders.has(componentType)) {
|
|
157
|
+
this.activeProviders.set(componentType, providerName);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Get the active adapter for a component type.
|
|
163
|
+
* @param {string} componentType
|
|
164
|
+
* @returns {BaseAdapter|null}
|
|
165
|
+
*/
|
|
166
|
+
getAdapter(componentType) {
|
|
167
|
+
const providerName = this.activeProviders.get(componentType);
|
|
168
|
+
if (!providerName) return null;
|
|
169
|
+
const typeAdapters = this.adapters.get(componentType);
|
|
170
|
+
return typeAdapters ? typeAdapters.get(providerName) || null : null;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Get a specific adapter by type and provider name.
|
|
175
|
+
* @param {string} componentType
|
|
176
|
+
* @param {string} providerName
|
|
177
|
+
* @returns {BaseAdapter|null}
|
|
178
|
+
*/
|
|
179
|
+
getAdapterByProvider(componentType, providerName) {
|
|
180
|
+
const typeAdapters = this.adapters.get(componentType);
|
|
181
|
+
return typeAdapters ? typeAdapters.get(providerName) || null : null;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Set the active provider for a component type.
|
|
186
|
+
* @param {string} componentType
|
|
187
|
+
* @param {string} providerName
|
|
188
|
+
*/
|
|
189
|
+
setActiveProvider(componentType, providerName) {
|
|
190
|
+
const typeAdapters = this.adapters.get(componentType);
|
|
191
|
+
if (!typeAdapters || !typeAdapters.has(providerName)) {
|
|
192
|
+
throw new Error(`Provider ${providerName} not registered for ${componentType}`);
|
|
193
|
+
}
|
|
194
|
+
this.activeProviders.set(componentType, providerName);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Get the MCP server name for a component type.
|
|
199
|
+
* @param {string} componentType
|
|
200
|
+
* @returns {string|null}
|
|
201
|
+
*/
|
|
202
|
+
getMcpServer(componentType) {
|
|
203
|
+
const adapter = this.getAdapter(componentType);
|
|
204
|
+
return adapter ? adapter.mcpServer : null;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Get the MCP server name by looking up from MCP compatibility layer.
|
|
209
|
+
* Used for backward compatibility with existing MCP server names.
|
|
210
|
+
* @param {string} mcpServerName
|
|
211
|
+
* @returns {object|null} - { type, provider, adapter }
|
|
212
|
+
*/
|
|
213
|
+
resolveMcpServer(mcpServerName) {
|
|
214
|
+
return McpCompatibility.resolve(mcpServerName);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Get all registered providers for a component type.
|
|
219
|
+
* @param {string} componentType
|
|
220
|
+
* @returns {object[]}
|
|
221
|
+
*/
|
|
222
|
+
getProviders(componentType) {
|
|
223
|
+
const typeAdapters = this.adapters.get(componentType);
|
|
224
|
+
if (!typeAdapters) return [];
|
|
225
|
+
const result = [];
|
|
226
|
+
for (const [name, adapter] of typeAdapters) {
|
|
227
|
+
result.push({
|
|
228
|
+
name,
|
|
229
|
+
active: this.activeProviders.get(componentType) === name,
|
|
230
|
+
...adapter.getStatus()
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
return result;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Get the active provider name for a component type.
|
|
238
|
+
* @param {string} componentType
|
|
239
|
+
* @returns {string|null}
|
|
240
|
+
*/
|
|
241
|
+
getActiveProvider(componentType) {
|
|
242
|
+
return this.activeProviders.get(componentType) || null;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Get a summary of all component types and their status.
|
|
247
|
+
* @returns {object}
|
|
248
|
+
*/
|
|
249
|
+
getStatus() {
|
|
250
|
+
const status = {};
|
|
251
|
+
for (const type of Object.values(ComponentType)) {
|
|
252
|
+
const adapter = this.getAdapter(type);
|
|
253
|
+
status[type] = {
|
|
254
|
+
active: this.activeProviders.get(type) || null,
|
|
255
|
+
providers: this.getProviders(type).map(p => ({
|
|
256
|
+
name: p.name,
|
|
257
|
+
enabled: p.enabled,
|
|
258
|
+
mcpServer: p.mcpServer
|
|
259
|
+
}))
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
return status;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Initialize all registered adapters.
|
|
267
|
+
*/
|
|
268
|
+
async initAll() {
|
|
269
|
+
for (const [type, typeAdapters] of this.adapters) {
|
|
270
|
+
for (const [name, adapter] of typeAdapters) {
|
|
271
|
+
try {
|
|
272
|
+
await adapter.init();
|
|
273
|
+
} catch (error) {
|
|
274
|
+
console.warn(`Failed to init adapter ${name} for ${type}:`, error.message);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
module.exports = ComponentRegistry;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FlowMind Component Types
|
|
3
|
+
* Defines all pluggable component type constants
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const ComponentType = Object.freeze({
|
|
7
|
+
LOG_SERVICE: 'logService',
|
|
8
|
+
DATABASE_MANAGER: 'databaseManager',
|
|
9
|
+
DATABASE_QUERY: 'databaseQuery',
|
|
10
|
+
REDIS_MONITOR: 'redisMonitor',
|
|
11
|
+
API_DOC: 'apiDoc',
|
|
12
|
+
KNOWLEDGE_BASE: 'knowledgeBase',
|
|
13
|
+
WORKFLOW: 'workflow',
|
|
14
|
+
REPORT: 'report'
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Component type metadata - describes each component type
|
|
19
|
+
*/
|
|
20
|
+
const ComponentTypeMeta = Object.freeze({
|
|
21
|
+
[ComponentType.LOG_SERVICE]: {
|
|
22
|
+
name: 'Log Service',
|
|
23
|
+
description: 'Cloud log querying and analysis',
|
|
24
|
+
requiredCapabilities: ['queryLogs', 'listProjects']
|
|
25
|
+
},
|
|
26
|
+
[ComponentType.DATABASE_MANAGER]: {
|
|
27
|
+
name: 'Database Manager',
|
|
28
|
+
description: 'Database instance management and DDL/DML execution',
|
|
29
|
+
requiredCapabilities: ['listInstances', 'executeScript', 'searchDatabase']
|
|
30
|
+
},
|
|
31
|
+
[ComponentType.DATABASE_QUERY]: {
|
|
32
|
+
name: 'Database Query',
|
|
33
|
+
description: 'Direct database querying via SQL',
|
|
34
|
+
requiredCapabilities: ['queryExec', 'fetchSource', 'fetchTables']
|
|
35
|
+
},
|
|
36
|
+
[ComponentType.REDIS_MONITOR]: {
|
|
37
|
+
name: 'Redis Monitor',
|
|
38
|
+
description: 'Redis monitoring and key inspection',
|
|
39
|
+
requiredCapabilities: ['query', 'queryRange', 'getLabelValues']
|
|
40
|
+
},
|
|
41
|
+
[ComponentType.API_DOC]: {
|
|
42
|
+
name: 'API Documentation',
|
|
43
|
+
description: 'API documentation management and sync',
|
|
44
|
+
requiredCapabilities: ['searchApis', 'saveApi', 'getCategories']
|
|
45
|
+
},
|
|
46
|
+
[ComponentType.KNOWLEDGE_BASE]: {
|
|
47
|
+
name: 'Knowledge Base',
|
|
48
|
+
description: 'Knowledge base and document management',
|
|
49
|
+
requiredCapabilities: ['getRepos', 'getDocs', 'createDoc', 'updateDoc']
|
|
50
|
+
},
|
|
51
|
+
[ComponentType.WORKFLOW]: {
|
|
52
|
+
name: 'Workflow',
|
|
53
|
+
description: 'Automated workflow and pipeline management',
|
|
54
|
+
requiredCapabilities: ['listPipelines', 'startPipelineRun']
|
|
55
|
+
},
|
|
56
|
+
[ComponentType.REPORT]: {
|
|
57
|
+
name: 'Report',
|
|
58
|
+
description: 'Automated test and coverage reporting',
|
|
59
|
+
requiredCapabilities: ['listBuilds', 'getBuildInfo']
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
module.exports = { ComponentType, ComponentTypeMeta };
|