flowmind 1.5.1 → 1.5.3
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/CHANGELOG.md +9 -0
- package/core/adapters/mcp-adapter.js +25 -0
- package/core/adapters/workflow-adapter.js +26 -0
- package/core/component-registry.js +19 -1
- package/core/config-manager.js +7 -2
- package/core/index.js +14 -1
- package/core/mcp-http-client.js +63 -0
- package/core/providers/aliyun/rds-query-adapter.js +70 -0
- package/core/providers/friday/flow-adapter.js +19 -30
- package/core/sdd-agent-sync.js +341 -17
- package/core/source-inference.js +324 -0
- package/package.json +1 -1
- package/skills/auto-flow/index.js +528 -52
- package/skills/data-logic-validation/index.js +133 -12
- package/skills/resource-bind/index.js +61 -18
- package/tui/app.jsx +2 -1
- package/tui/format-result.js +43 -4
package/core/sdd-agent-sync.js
CHANGED
|
@@ -2,10 +2,14 @@ const fs = require('fs-extra');
|
|
|
2
2
|
const os = require('os');
|
|
3
3
|
const path = require('path');
|
|
4
4
|
|
|
5
|
-
const
|
|
6
|
-
'
|
|
7
|
-
'
|
|
8
|
-
|
|
5
|
+
const SDD_SOURCE_SYNC_FILES = Object.freeze([
|
|
6
|
+
'RESOURCE_INDEX.md',
|
|
7
|
+
'project-db-configs.json',
|
|
8
|
+
'project-git-map.json',
|
|
9
|
+
'feign-link-map.json',
|
|
10
|
+
'auto-flow-apis.md',
|
|
11
|
+
'auto-flow-pipeline-map.json'
|
|
12
|
+
]);
|
|
9
13
|
|
|
10
14
|
const RESOURCE_BINDING_SPECS = Object.freeze({
|
|
11
15
|
yapi: { componentType: 'apiDoc', provider: 'yapi' },
|
|
@@ -23,7 +27,9 @@ function getHomeDir() {
|
|
|
23
27
|
|
|
24
28
|
function normalizeMcpServer(name) {
|
|
25
29
|
if (!name) return null;
|
|
26
|
-
|
|
30
|
+
if (/^[^-]+-yapi-mcp$/i.test(name)) return 'yapi-mcp';
|
|
31
|
+
if (/^[^-]+-yuque-mcp$/i.test(name)) return 'yuque-mcp';
|
|
32
|
+
return name;
|
|
27
33
|
}
|
|
28
34
|
|
|
29
35
|
function deepMerge(target, source) {
|
|
@@ -46,11 +52,19 @@ function isObject(value) {
|
|
|
46
52
|
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
47
53
|
}
|
|
48
54
|
|
|
49
|
-
function sanitizeResourceConfig(sddConfig) {
|
|
55
|
+
function sanitizeResourceConfig(sddConfig, skillBindingData = {}) {
|
|
56
|
+
const resources = { ...(sddConfig.resources || {}) };
|
|
57
|
+
if (!resources.workflow) {
|
|
58
|
+
const workflowResource = buildWorkflowResource(skillBindingData);
|
|
59
|
+
if (workflowResource) {
|
|
60
|
+
resources.workflow = workflowResource;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
50
64
|
return {
|
|
51
65
|
version: sddConfig.version || '1.0',
|
|
52
66
|
lastUpdated: new Date().toISOString(),
|
|
53
|
-
resources
|
|
67
|
+
resources,
|
|
54
68
|
mcpServers: sddConfig.mcpServers || {},
|
|
55
69
|
aliases: sddConfig.aliases || {},
|
|
56
70
|
metadata: {
|
|
@@ -171,7 +185,169 @@ function buildLogBindings(resourceConfig = {}) {
|
|
|
171
185
|
}));
|
|
172
186
|
}
|
|
173
187
|
|
|
174
|
-
function
|
|
188
|
+
function buildWorkflowResource(skillBindingData = {}) {
|
|
189
|
+
const workflowBinding = skillBindingData.bindings?.['auto-flow'];
|
|
190
|
+
if (!workflowBinding) return null;
|
|
191
|
+
|
|
192
|
+
const learningCount = workflowBinding.learningCount || (workflowBinding.records || []).length || (workflowBinding.rules || []).length;
|
|
193
|
+
|
|
194
|
+
return {
|
|
195
|
+
enabled: true,
|
|
196
|
+
mcpServer: 'friday-auto-flow',
|
|
197
|
+
bindings: {
|
|
198
|
+
'auto-flow': {
|
|
199
|
+
name: '自动部署',
|
|
200
|
+
skill: 'auto-flow',
|
|
201
|
+
provider: 'friday-flow',
|
|
202
|
+
mcpServer: 'friday-auto-flow',
|
|
203
|
+
learningCount,
|
|
204
|
+
lastLearning: workflowBinding.lastLearning || null,
|
|
205
|
+
records: workflowBinding.records || [],
|
|
206
|
+
rules: workflowBinding.rules || []
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
defaultBinding: 'auto-flow'
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function normalizeWorkflowTransport(transport) {
|
|
214
|
+
if (!transport || !transport.url) return null;
|
|
215
|
+
|
|
216
|
+
const headers = transport.headers || {};
|
|
217
|
+
const normalizedHeaders = {};
|
|
218
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
219
|
+
if (value === undefined || value === null || value === '') continue;
|
|
220
|
+
normalizedHeaders[key] = value;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return {
|
|
224
|
+
url: transport.url,
|
|
225
|
+
type: transport.type || 'http',
|
|
226
|
+
headers: normalizedHeaders,
|
|
227
|
+
description: transport.description || 'Workflow MCP server'
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
async function discoverWorkflowTransport(options = {}) {
|
|
232
|
+
const direct = normalizeWorkflowTransport(options.workflowTransport);
|
|
233
|
+
if (direct) return direct;
|
|
234
|
+
|
|
235
|
+
const envUrl = process.env.FLOWMIND_AUTO_FLOW_MCP_URL;
|
|
236
|
+
if (envUrl) {
|
|
237
|
+
return normalizeWorkflowTransport({
|
|
238
|
+
url: envUrl,
|
|
239
|
+
type: 'http',
|
|
240
|
+
headers: process.env.FLOWMIND_AUTO_FLOW_MCP_TOKEN
|
|
241
|
+
? { mcp_token: process.env.FLOWMIND_AUTO_FLOW_MCP_TOKEN }
|
|
242
|
+
: {},
|
|
243
|
+
description: 'Workflow MCP server from environment'
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const debugDir = path.join(os.homedir(), '.claude', 'debug');
|
|
248
|
+
if (!await fs.pathExists(debugDir)) return null;
|
|
249
|
+
|
|
250
|
+
const entries = await fs.readdir(debugDir);
|
|
251
|
+
const candidates = [];
|
|
252
|
+
for (const entry of entries) {
|
|
253
|
+
const filePath = path.join(debugDir, entry);
|
|
254
|
+
try {
|
|
255
|
+
const stat = await fs.stat(filePath);
|
|
256
|
+
if (stat.isFile()) {
|
|
257
|
+
candidates.push({ filePath, mtimeMs: stat.mtimeMs });
|
|
258
|
+
}
|
|
259
|
+
} catch (error) {
|
|
260
|
+
// skip unreadable files
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
candidates.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
265
|
+
|
|
266
|
+
for (const { filePath } of candidates.slice(0, 10)) {
|
|
267
|
+
try {
|
|
268
|
+
const content = await fs.readFile(filePath, 'utf8');
|
|
269
|
+
const match = content.match(/MCP server "friday-auto-flow": HTTP transport options: (\{[^\n]+\})/);
|
|
270
|
+
if (!match) continue;
|
|
271
|
+
|
|
272
|
+
const parsed = JSON.parse(match[1]);
|
|
273
|
+
return normalizeWorkflowTransport({
|
|
274
|
+
url: parsed.url,
|
|
275
|
+
type: parsed.type || 'http',
|
|
276
|
+
headers: parsed.headers || {},
|
|
277
|
+
description: 'Workflow MCP server discovered from Claude debug logs'
|
|
278
|
+
});
|
|
279
|
+
} catch (error) {
|
|
280
|
+
// continue scanning other files
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function buildWorkflowBindings(skillBindingData = {}, workflowTransport = null) {
|
|
288
|
+
const workflowBinding = skillBindingData.bindings?.['auto-flow'];
|
|
289
|
+
if (!workflowBinding) return [];
|
|
290
|
+
|
|
291
|
+
const ruleSummaries = (workflowBinding.records || []).map((record) => record.summary).filter(Boolean);
|
|
292
|
+
const ruleActions = (workflowBinding.rules || []).map((rule) => rule.action).filter(Boolean);
|
|
293
|
+
const keywords = [
|
|
294
|
+
'auto-flow',
|
|
295
|
+
'workflow',
|
|
296
|
+
'pipeline',
|
|
297
|
+
'deploy',
|
|
298
|
+
'deployment',
|
|
299
|
+
'部署',
|
|
300
|
+
'发布',
|
|
301
|
+
'上线',
|
|
302
|
+
'流水线',
|
|
303
|
+
...ruleSummaries,
|
|
304
|
+
...ruleActions
|
|
305
|
+
];
|
|
306
|
+
|
|
307
|
+
return [{
|
|
308
|
+
id: 'sdd-workflow-auto-flow',
|
|
309
|
+
timestamp: new Date().toISOString(),
|
|
310
|
+
business: '自动部署',
|
|
311
|
+
aliases: [
|
|
312
|
+
'auto-flow',
|
|
313
|
+
'workflow',
|
|
314
|
+
'pipeline',
|
|
315
|
+
'飞流',
|
|
316
|
+
'飞流部署',
|
|
317
|
+
'部署',
|
|
318
|
+
'发布',
|
|
319
|
+
'上线',
|
|
320
|
+
'流水线'
|
|
321
|
+
],
|
|
322
|
+
componentType: 'workflow',
|
|
323
|
+
provider: 'friday-flow',
|
|
324
|
+
mcpServer: 'friday-auto-flow',
|
|
325
|
+
source: 'sdd-agent-sync',
|
|
326
|
+
keywords: [...new Set(keywords.filter(Boolean))],
|
|
327
|
+
connection: {
|
|
328
|
+
skill: 'auto-flow',
|
|
329
|
+
learningCount: workflowBinding.learningCount || 0,
|
|
330
|
+
lastLearning: workflowBinding.lastLearning || null,
|
|
331
|
+
records: workflowBinding.records || [],
|
|
332
|
+
rules: workflowBinding.rules || [],
|
|
333
|
+
transport: workflowTransport ? {
|
|
334
|
+
url: workflowTransport.url,
|
|
335
|
+
type: workflowTransport.type
|
|
336
|
+
} : undefined
|
|
337
|
+
},
|
|
338
|
+
metadata: {
|
|
339
|
+
source: 'sdd-agent',
|
|
340
|
+
resourceType: 'workflow',
|
|
341
|
+
bindingKey: 'auto-flow'
|
|
342
|
+
},
|
|
343
|
+
stats: {
|
|
344
|
+
useCount: 0,
|
|
345
|
+
lastUsed: null
|
|
346
|
+
}
|
|
347
|
+
}];
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
function convertResourceBindings(sddConfig, skillBindingData = {}, workflowTransport = null) {
|
|
175
351
|
const resources = sddConfig.resources || {};
|
|
176
352
|
const aliasIndex = buildAliasIndex(sddConfig.aliases);
|
|
177
353
|
const bindings = [];
|
|
@@ -189,6 +365,8 @@ function convertResourceBindings(sddConfig) {
|
|
|
189
365
|
}
|
|
190
366
|
}
|
|
191
367
|
|
|
368
|
+
bindings.push(...buildWorkflowBindings(skillBindingData, workflowTransport));
|
|
369
|
+
|
|
192
370
|
return bindings;
|
|
193
371
|
}
|
|
194
372
|
|
|
@@ -223,9 +401,13 @@ function convertSceneMappings(sceneData = {}) {
|
|
|
223
401
|
}));
|
|
224
402
|
}
|
|
225
403
|
|
|
226
|
-
function buildComponentConfig(sddConfig) {
|
|
404
|
+
function buildComponentConfig(sddConfig, skillBindingData = {}, workflowTransport = null) {
|
|
227
405
|
const resources = sddConfig.resources || {};
|
|
406
|
+
const workflowResource = resources.workflow || buildWorkflowResource(skillBindingData);
|
|
228
407
|
const components = {};
|
|
408
|
+
const directQueryServer = resources.database?.mcpServers?.directQuery
|
|
409
|
+
|| resources.redis?.mcpServers?.directQuery
|
|
410
|
+
|| null;
|
|
229
411
|
|
|
230
412
|
if (resources.sls?.enabled) {
|
|
231
413
|
const defaultEnv = resources.sls.defaultEnv || 'uat';
|
|
@@ -261,6 +443,18 @@ function buildComponentConfig(sddConfig) {
|
|
|
261
443
|
};
|
|
262
444
|
}
|
|
263
445
|
|
|
446
|
+
if ((resources.database?.enabled || resources.redis?.enabled) && directQueryServer) {
|
|
447
|
+
components.databaseQuery = {
|
|
448
|
+
default: 'aliyun-rds-query',
|
|
449
|
+
providers: {
|
|
450
|
+
'aliyun-rds-query': {
|
|
451
|
+
enabled: true,
|
|
452
|
+
mcpServer: normalizeMcpServer(directQueryServer)
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
|
|
264
458
|
if (resources.redis?.enabled && resources.redis.mcpServers?.monitor) {
|
|
265
459
|
components.redisMonitor = {
|
|
266
460
|
default: 'aliyun-redis',
|
|
@@ -297,13 +491,14 @@ function buildComponentConfig(sddConfig) {
|
|
|
297
491
|
};
|
|
298
492
|
}
|
|
299
493
|
|
|
300
|
-
if (
|
|
494
|
+
if (workflowResource?.enabled && workflowResource.mcpServer) {
|
|
301
495
|
components.workflow = {
|
|
302
496
|
default: 'friday-flow',
|
|
303
497
|
providers: {
|
|
304
498
|
'friday-flow': {
|
|
305
499
|
enabled: true,
|
|
306
|
-
mcpServer: normalizeMcpServer(
|
|
500
|
+
mcpServer: normalizeMcpServer(workflowResource.mcpServer),
|
|
501
|
+
...(workflowTransport ? { transport: workflowTransport } : {})
|
|
307
502
|
}
|
|
308
503
|
}
|
|
309
504
|
};
|
|
@@ -388,11 +583,124 @@ async function readJsonIfExists(filePath, fallback) {
|
|
|
388
583
|
return fs.readJson(filePath);
|
|
389
584
|
}
|
|
390
585
|
|
|
586
|
+
async function statIfExists(filePath) {
|
|
587
|
+
try {
|
|
588
|
+
return await fs.stat(filePath);
|
|
589
|
+
} catch (error) {
|
|
590
|
+
return null;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
async function copySelectedSourceFiles(sourceDir, targetDir) {
|
|
595
|
+
const sourceRoot = path.join(sourceDir, 'source');
|
|
596
|
+
const copied = [];
|
|
597
|
+
|
|
598
|
+
if (!(await fs.pathExists(sourceRoot))) {
|
|
599
|
+
return copied;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
await fs.ensureDir(targetDir);
|
|
603
|
+
|
|
604
|
+
for (const fileName of SDD_SOURCE_SYNC_FILES) {
|
|
605
|
+
const sourcePath = path.join(sourceRoot, fileName);
|
|
606
|
+
if (!(await fs.pathExists(sourcePath))) {
|
|
607
|
+
continue;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
const targetPath = path.join(targetDir, fileName);
|
|
611
|
+
await fs.copy(sourcePath, targetPath, { overwrite: true, dereference: true });
|
|
612
|
+
copied.push({
|
|
613
|
+
name: fileName,
|
|
614
|
+
sourcePath,
|
|
615
|
+
targetPath
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
return copied;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
async function buildSyncSignature(sourceDir) {
|
|
623
|
+
const trackedFiles = [
|
|
624
|
+
path.join(sourceDir, 'resource-config.json'),
|
|
625
|
+
path.join(sourceDir, 'learning', 'scene-mappings.json'),
|
|
626
|
+
path.join(sourceDir, 'learning', 'skill-bindings.json'),
|
|
627
|
+
...SDD_SOURCE_SYNC_FILES.map((fileName) => path.join(sourceDir, 'source', fileName))
|
|
628
|
+
];
|
|
629
|
+
|
|
630
|
+
const entries = [];
|
|
631
|
+
for (const filePath of trackedFiles) {
|
|
632
|
+
const stat = await statIfExists(filePath);
|
|
633
|
+
if (!stat) continue;
|
|
634
|
+
entries.push({
|
|
635
|
+
path: filePath,
|
|
636
|
+
size: stat.size,
|
|
637
|
+
mtimeMs: stat.mtimeMs
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
entries.sort((a, b) => a.path.localeCompare(b.path));
|
|
642
|
+
return JSON.stringify(entries);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
async function autoSyncSddAgentToFlowMind(options = {}) {
|
|
646
|
+
if (process.env.FLOWMIND_DISABLE_SDD_AGENT_AUTO_SYNC === '1') {
|
|
647
|
+
return { synced: false, skipped: true, reason: 'disabled' };
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
const sourceDir = options.sourceDir || path.join(os.homedir(), '.sdd-agent');
|
|
651
|
+
const targetHome = options.targetHome || getHomeDir();
|
|
652
|
+
const sourceConfigPath = path.join(sourceDir, 'resource-config.json');
|
|
653
|
+
|
|
654
|
+
if (!(await fs.pathExists(sourceConfigPath))) {
|
|
655
|
+
return { synced: false, skipped: true, reason: 'missing-source-config' };
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
const targetDir = path.join(targetHome, '.flowmind');
|
|
659
|
+
const statePath = path.join(targetDir, 'sdd-agent-sync-state.json');
|
|
660
|
+
const signature = await buildSyncSignature(sourceDir);
|
|
661
|
+
const previousState = await readJsonIfExists(statePath, null);
|
|
662
|
+
|
|
663
|
+
if (previousState?.signature === signature) {
|
|
664
|
+
return {
|
|
665
|
+
synced: false,
|
|
666
|
+
skipped: true,
|
|
667
|
+
reason: 'up-to-date',
|
|
668
|
+
sourceDir,
|
|
669
|
+
targetDir,
|
|
670
|
+
statePath
|
|
671
|
+
};
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
const summary = await syncSddAgentToFlowMind({
|
|
675
|
+
...options,
|
|
676
|
+
sourceDir,
|
|
677
|
+
targetHome
|
|
678
|
+
});
|
|
679
|
+
|
|
680
|
+
await fs.ensureDir(targetDir);
|
|
681
|
+
await fs.writeJson(statePath, {
|
|
682
|
+
sourceDir,
|
|
683
|
+
targetDir,
|
|
684
|
+
signature,
|
|
685
|
+
syncedAt: new Date().toISOString(),
|
|
686
|
+
files: summary.files,
|
|
687
|
+
counts: summary.counts
|
|
688
|
+
}, { spaces: 2 });
|
|
689
|
+
|
|
690
|
+
return {
|
|
691
|
+
synced: true,
|
|
692
|
+
skipped: false,
|
|
693
|
+
statePath,
|
|
694
|
+
...summary
|
|
695
|
+
};
|
|
696
|
+
}
|
|
697
|
+
|
|
391
698
|
async function syncSddAgentToFlowMind(options = {}) {
|
|
392
699
|
const sourceDir = options.sourceDir || path.join(os.homedir(), '.sdd-agent');
|
|
393
700
|
const targetHome = options.targetHome || getHomeDir();
|
|
394
701
|
const sourceConfigPath = path.join(sourceDir, 'resource-config.json');
|
|
395
702
|
const sourceScenesPath = path.join(sourceDir, 'learning', 'scene-mappings.json');
|
|
703
|
+
const sourceSkillBindingsPath = path.join(sourceDir, 'learning', 'skill-bindings.json');
|
|
396
704
|
const targetDir = path.join(targetHome, '.flowmind');
|
|
397
705
|
const targetLearningDir = path.join(targetDir, 'learning');
|
|
398
706
|
|
|
@@ -402,20 +710,30 @@ async function syncSddAgentToFlowMind(options = {}) {
|
|
|
402
710
|
|
|
403
711
|
const sddConfig = await fs.readJson(sourceConfigPath);
|
|
404
712
|
const sddScenes = await readJsonIfExists(sourceScenesPath, { mappings: [] });
|
|
713
|
+
const sddSkillBindings = await readJsonIfExists(sourceSkillBindingsPath, { version: '1.0', bindings: {} });
|
|
714
|
+
sddConfig.skillBindings = sddSkillBindings;
|
|
715
|
+
const workflowTransport = await discoverWorkflowTransport(options);
|
|
716
|
+
if (workflowTransport) {
|
|
717
|
+
sddConfig.mcpServers = {
|
|
718
|
+
...(sddConfig.mcpServers || {}),
|
|
719
|
+
'friday-auto-flow': workflowTransport
|
|
720
|
+
};
|
|
721
|
+
}
|
|
405
722
|
|
|
406
723
|
const targetResourceConfigPath = path.join(targetDir, 'resource-config.json');
|
|
407
724
|
const targetComponentConfigPath = path.join(targetDir, 'component-config.json');
|
|
408
725
|
const targetBindingsPath = path.join(targetLearningDir, 'resource-bindings.json');
|
|
409
726
|
const targetScenesPath = path.join(targetLearningDir, 'scenes.json');
|
|
727
|
+
const targetSourceDir = path.join(targetDir, 'source');
|
|
410
728
|
|
|
411
729
|
const existingResourceConfig = await readJsonIfExists(targetResourceConfigPath, {});
|
|
412
730
|
const existingComponentConfig = await readJsonIfExists(targetComponentConfigPath, { version: '1.0.0', components: {} });
|
|
413
731
|
const existingBindings = await readJsonIfExists(targetBindingsPath, { version: '1.0', bindings: [] });
|
|
414
732
|
const existingScenes = await readJsonIfExists(targetScenesPath, { version: '1.0', mappings: [] });
|
|
415
733
|
|
|
416
|
-
const nextResourceConfig = deepMerge(existingResourceConfig, sanitizeResourceConfig(sddConfig));
|
|
417
|
-
const nextComponentConfig = deepMerge(existingComponentConfig, buildComponentConfig(sddConfig));
|
|
418
|
-
const importedBindings = convertResourceBindings(sddConfig);
|
|
734
|
+
const nextResourceConfig = deepMerge(existingResourceConfig, sanitizeResourceConfig(sddConfig, sddSkillBindings));
|
|
735
|
+
const nextComponentConfig = deepMerge(existingComponentConfig, buildComponentConfig(sddConfig, sddSkillBindings, workflowTransport));
|
|
736
|
+
const importedBindings = convertResourceBindings(sddConfig, sddSkillBindings, workflowTransport);
|
|
419
737
|
const nextBindings = {
|
|
420
738
|
version: existingBindings.version || '1.0',
|
|
421
739
|
lastUpdated: new Date().toISOString(),
|
|
@@ -433,6 +751,7 @@ async function syncSddAgentToFlowMind(options = {}) {
|
|
|
433
751
|
await fs.writeJson(targetComponentConfigPath, nextComponentConfig, { spaces: 2 });
|
|
434
752
|
await fs.writeJson(targetBindingsPath, nextBindings, { spaces: 2 });
|
|
435
753
|
await fs.writeJson(targetScenesPath, nextScenes, { spaces: 2 });
|
|
754
|
+
const copiedSourceFiles = await copySelectedSourceFiles(sourceDir, targetSourceDir);
|
|
436
755
|
|
|
437
756
|
return {
|
|
438
757
|
sourceDir,
|
|
@@ -441,14 +760,16 @@ async function syncSddAgentToFlowMind(options = {}) {
|
|
|
441
760
|
resourceConfig: targetResourceConfigPath,
|
|
442
761
|
componentConfig: targetComponentConfigPath,
|
|
443
762
|
resourceBindings: targetBindingsPath,
|
|
444
|
-
scenes: targetScenesPath
|
|
763
|
+
scenes: targetScenesPath,
|
|
764
|
+
sourceFiles: copiedSourceFiles.map((item) => item.targetPath)
|
|
445
765
|
},
|
|
446
766
|
counts: {
|
|
447
767
|
importedBindings: importedBindings.length,
|
|
448
768
|
totalBindings: nextBindings.bindings.length,
|
|
449
769
|
importedScenes: importedScenes.length,
|
|
450
770
|
totalScenes: nextScenes.mappings.length,
|
|
451
|
-
components: Object.keys(nextComponentConfig.components || {}).length
|
|
771
|
+
components: Object.keys(nextComponentConfig.components || {}).length,
|
|
772
|
+
copiedSourceFiles: copiedSourceFiles.length
|
|
452
773
|
}
|
|
453
774
|
};
|
|
454
775
|
}
|
|
@@ -461,7 +782,10 @@ module.exports = {
|
|
|
461
782
|
deepMerge,
|
|
462
783
|
mergeBindings,
|
|
463
784
|
mergeScenes,
|
|
785
|
+
buildWorkflowBindings,
|
|
786
|
+
buildWorkflowResource,
|
|
464
787
|
normalizeMcpServer,
|
|
465
788
|
sanitizeResourceConfig,
|
|
466
|
-
syncSddAgentToFlowMind
|
|
789
|
+
syncSddAgentToFlowMind,
|
|
790
|
+
autoSyncSddAgentToFlowMind
|
|
467
791
|
};
|