@codragraph/cli 2.1.0 → 2.1.1
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/README.md +58 -20
- package/dist/_shared/cgdb/schema-constants.d.ts +2 -2
- package/dist/_shared/cgdb/schema-constants.d.ts.map +1 -1
- package/dist/_shared/cgdb/schema-constants.js +3 -0
- package/dist/_shared/cgdb/schema-constants.js.map +1 -1
- package/dist/_shared/feature-clusters.d.ts +99 -0
- package/dist/_shared/feature-clusters.d.ts.map +1 -0
- package/dist/_shared/feature-clusters.js +2 -0
- package/dist/_shared/feature-clusters.js.map +1 -0
- package/dist/_shared/graph/types.d.ts +16 -2
- package/dist/_shared/graph/types.d.ts.map +1 -1
- package/dist/_shared/index.d.ts +1 -0
- package/dist/_shared/index.d.ts.map +1 -1
- package/dist/_shared/index.js.map +1 -1
- package/dist/_shared/pipeline.d.ts +1 -1
- package/dist/_shared/pipeline.d.ts.map +1 -1
- package/dist/cli/ai-context.js +4 -0
- package/dist/cli/analyze.js +27 -24
- package/dist/cli/index.js +37 -0
- package/dist/cli/setup.js +9 -5
- package/dist/cli/tool.d.ts +25 -0
- package/dist/cli/tool.js +74 -0
- package/dist/config/supported-languages.d.ts +3 -3
- package/dist/config/supported-languages.js +3 -3
- package/dist/core/cgdb/cgdb-adapter.js +19 -3
- package/dist/core/cgdb/csv-generator.js +33 -2
- package/dist/core/cgdb/schema.d.ts +2 -1
- package/dist/core/cgdb/schema.js +55 -0
- package/dist/core/embeddings/embedder.js +4 -2
- package/dist/core/graphstore/index.d.ts +1 -1
- package/dist/core/graphstore/index.js +1 -1
- package/dist/core/group/service.d.ts +16 -0
- package/dist/core/group/service.js +360 -0
- package/dist/core/ingestion/emit-references.d.ts +1 -1
- package/dist/core/ingestion/emit-references.js +1 -1
- package/dist/core/ingestion/feature-cluster-processor.d.ts +62 -0
- package/dist/core/ingestion/feature-cluster-processor.js +626 -0
- package/dist/core/ingestion/finalize-orchestrator.js +1 -1
- package/dist/core/ingestion/model/registration-table.js +1 -0
- package/dist/core/ingestion/model/resolve.d.ts +2 -2
- package/dist/core/ingestion/model/resolve.js +3 -3
- package/dist/core/ingestion/model/semantic-model.d.ts +1 -1
- package/dist/core/ingestion/model/semantic-model.js +1 -1
- package/dist/core/ingestion/model/symbol-table.d.ts +1 -1
- package/dist/core/ingestion/model/symbol-table.js +1 -1
- package/dist/core/ingestion/pipeline-phases/feature-clusters.d.ts +17 -0
- package/dist/core/ingestion/pipeline-phases/feature-clusters.js +88 -0
- package/dist/core/ingestion/pipeline-phases/index.d.ts +1 -0
- package/dist/core/ingestion/pipeline-phases/index.js +1 -0
- package/dist/core/ingestion/pipeline.d.ts +4 -0
- package/dist/core/ingestion/pipeline.js +9 -5
- package/dist/core/run-analyze.d.ts +1 -0
- package/dist/core/run-analyze.js +12 -6
- package/dist/mcp/core/embedder.js +5 -2
- package/dist/mcp/local/local-backend.d.ts +12 -0
- package/dist/mcp/local/local-backend.js +381 -3
- package/dist/mcp/resources.js +139 -0
- package/dist/mcp/tools.js +174 -2
- package/dist/server/api.js +116 -0
- package/dist/storage/repo-manager.d.ts +6 -1
- package/dist/storage/repo-manager.js +5 -1
- package/dist/types/pipeline.d.ts +2 -0
- package/package.json +13 -4
- package/scripts/build.js +13 -12
- package/skills/codragraph-cli.md +17 -1
- package/skills/codragraph-guide.md +6 -2
- package/skills/codragraph-onboarding.md +2 -2
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase: featureClusters
|
|
3
|
+
*
|
|
4
|
+
* Creates human-facing FeatureCluster nodes above algorithmic Community nodes.
|
|
5
|
+
* This is the layer agents query for product/domain areas such as Settings,
|
|
6
|
+
* AI, Auth, MCP, or Ingestion before drilling into exact symbols.
|
|
7
|
+
*
|
|
8
|
+
* @deps processes, structure
|
|
9
|
+
* @reads graph (all nodes and relationships)
|
|
10
|
+
* @writes graph (FeatureCluster nodes, FEATURE_MEMBER_OF, FEATURE_DEPENDS_ON)
|
|
11
|
+
*/
|
|
12
|
+
import type { PipelinePhase } from './types.js';
|
|
13
|
+
import { type FeatureClusterDetectionResult } from '../feature-cluster-processor.js';
|
|
14
|
+
export interface FeatureClustersOutput {
|
|
15
|
+
featureClusterResult: FeatureClusterDetectionResult;
|
|
16
|
+
}
|
|
17
|
+
export declare const featureClustersPhase: PipelinePhase<FeatureClustersOutput>;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase: featureClusters
|
|
3
|
+
*
|
|
4
|
+
* Creates human-facing FeatureCluster nodes above algorithmic Community nodes.
|
|
5
|
+
* This is the layer agents query for product/domain areas such as Settings,
|
|
6
|
+
* AI, Auth, MCP, or Ingestion before drilling into exact symbols.
|
|
7
|
+
*
|
|
8
|
+
* @deps processes, structure
|
|
9
|
+
* @reads graph (all nodes and relationships)
|
|
10
|
+
* @writes graph (FeatureCluster nodes, FEATURE_MEMBER_OF, FEATURE_DEPENDS_ON)
|
|
11
|
+
*/
|
|
12
|
+
import { getPhaseOutput } from './types.js';
|
|
13
|
+
import { processFeatureClusters, } from '../feature-cluster-processor.js';
|
|
14
|
+
import { generateId } from '../../../lib/utils.js';
|
|
15
|
+
import { isDev } from '../utils/env.js';
|
|
16
|
+
export const featureClustersPhase = {
|
|
17
|
+
name: 'featureClusters',
|
|
18
|
+
deps: ['processes', 'structure'],
|
|
19
|
+
async execute(ctx, deps) {
|
|
20
|
+
const { totalFiles } = getPhaseOutput(deps, 'structure');
|
|
21
|
+
ctx.onProgress({
|
|
22
|
+
phase: 'feature_clusters',
|
|
23
|
+
percent: 99,
|
|
24
|
+
message: 'Building feature clusters...',
|
|
25
|
+
stats: { filesProcessed: totalFiles, totalFiles, nodesCreated: ctx.graph.nodeCount },
|
|
26
|
+
});
|
|
27
|
+
const featureClusterResult = await processFeatureClusters(ctx.graph, (message, progress) => {
|
|
28
|
+
ctx.onProgress({
|
|
29
|
+
phase: 'feature_clusters',
|
|
30
|
+
percent: Math.round(99 + progress * 0.009),
|
|
31
|
+
message,
|
|
32
|
+
stats: { filesProcessed: totalFiles, totalFiles, nodesCreated: ctx.graph.nodeCount },
|
|
33
|
+
});
|
|
34
|
+
}, {
|
|
35
|
+
repo: ctx.options?.featureClusterRepo,
|
|
36
|
+
lastIndexedCommit: ctx.options?.lastIndexedCommit,
|
|
37
|
+
});
|
|
38
|
+
if (isDev) {
|
|
39
|
+
console.log(`Feature clustering: ${featureClusterResult.stats.totalClusters} clusters, ${featureClusterResult.stats.totalMemberships} memberships`);
|
|
40
|
+
}
|
|
41
|
+
featureClusterResult.clusters.forEach((cluster) => {
|
|
42
|
+
ctx.graph.addNode({
|
|
43
|
+
id: cluster.id,
|
|
44
|
+
label: 'FeatureCluster',
|
|
45
|
+
properties: {
|
|
46
|
+
name: cluster.name,
|
|
47
|
+
filePath: '',
|
|
48
|
+
slug: cluster.slug,
|
|
49
|
+
featureKind: cluster.featureKind,
|
|
50
|
+
summary: cluster.summary,
|
|
51
|
+
description: cluster.description,
|
|
52
|
+
repo: cluster.repo,
|
|
53
|
+
service: cluster.service,
|
|
54
|
+
signals: cluster.signals,
|
|
55
|
+
memberCount: cluster.memberCount,
|
|
56
|
+
entryPointIds: cluster.entryPointIds,
|
|
57
|
+
routes: cluster.routes,
|
|
58
|
+
tools: cluster.tools,
|
|
59
|
+
testCoverageHints: cluster.testCoverageHints,
|
|
60
|
+
lastIndexedCommit: cluster.lastIndexedCommit,
|
|
61
|
+
confidence: cluster.confidence,
|
|
62
|
+
source: 'heuristic',
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
featureClusterResult.memberships.forEach((membership) => {
|
|
67
|
+
ctx.graph.addRelationship({
|
|
68
|
+
id: generateId('FEATURE_MEMBER_OF', `${membership.nodeId}->${membership.clusterId}`),
|
|
69
|
+
sourceId: membership.nodeId,
|
|
70
|
+
targetId: membership.clusterId,
|
|
71
|
+
type: 'FEATURE_MEMBER_OF',
|
|
72
|
+
confidence: membership.confidence,
|
|
73
|
+
reason: membership.signals.join('|'),
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
featureClusterResult.dependencies.forEach((dependency) => {
|
|
77
|
+
ctx.graph.addRelationship({
|
|
78
|
+
id: generateId('FEATURE_DEPENDS_ON', `${dependency.sourceClusterId}->${dependency.targetClusterId}`),
|
|
79
|
+
sourceId: dependency.sourceClusterId,
|
|
80
|
+
targetId: dependency.targetClusterId,
|
|
81
|
+
type: 'FEATURE_DEPENDS_ON',
|
|
82
|
+
confidence: dependency.confidence,
|
|
83
|
+
reason: `member-dependency|edges:${dependency.edgeCount}|types:${dependency.relationshipTypes.join(',')}`,
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
return { featureClusterResult };
|
|
87
|
+
},
|
|
88
|
+
};
|
|
@@ -17,6 +17,7 @@ export { scopeResolutionPhase, type ScopeResolutionOutput, } from '../scope-reso
|
|
|
17
17
|
export { mroPhase, type MROOutput } from './mro.js';
|
|
18
18
|
export { communitiesPhase, type CommunitiesOutput } from './communities.js';
|
|
19
19
|
export { processesPhase, type ProcessesOutput } from './processes.js';
|
|
20
|
+
export { featureClustersPhase, type FeatureClustersOutput } from './feature-clusters.js';
|
|
20
21
|
export { runPipeline } from './runner.js';
|
|
21
22
|
export type { PipelinePhase, PipelineContext, PhaseResult } from './types.js';
|
|
22
23
|
export { getPhaseOutput } from './types.js';
|
|
@@ -18,6 +18,7 @@ export { scopeResolutionPhase, } from '../scope-resolution/pipeline/phase.js';
|
|
|
18
18
|
export { mroPhase } from './mro.js';
|
|
19
19
|
export { communitiesPhase } from './communities.js';
|
|
20
20
|
export { processesPhase } from './processes.js';
|
|
21
|
+
export { featureClustersPhase } from './feature-clusters.js';
|
|
21
22
|
// ── Infrastructure ─────────────────────────────────────────────────────────
|
|
22
23
|
export { runPipeline } from './runner.js';
|
|
23
24
|
export { getPhaseOutput } from './types.js';
|
|
@@ -21,6 +21,10 @@ export interface PipelineOptions {
|
|
|
21
21
|
skipGraphPhases?: boolean;
|
|
22
22
|
/** Force sequential parsing (no worker pool). Useful for testing the sequential path. */
|
|
23
23
|
skipWorkers?: boolean;
|
|
24
|
+
/** Repo label written onto FeatureCluster metadata. */
|
|
25
|
+
featureClusterRepo?: string;
|
|
26
|
+
/** Indexed source commit written onto FeatureCluster metadata. */
|
|
27
|
+
lastIndexedCommit?: string;
|
|
24
28
|
/**
|
|
25
29
|
* @internal Test-only override for worker-pool gating thresholds.
|
|
26
30
|
* When unset, production defaults apply (15 files OR 512 KB total bytes).
|
|
@@ -15,15 +15,16 @@
|
|
|
15
15
|
* See ARCHITECTURE.md for the full phase dependency diagram.
|
|
16
16
|
*/
|
|
17
17
|
import { createKnowledgeGraph } from '../graph/graph.js';
|
|
18
|
-
import { runPipeline, getPhaseOutput, scanPhase, structurePhase, markdownPhase, cobolPhase, parsePhase, routesPhase, toolsPhase, ormPhase, crossFilePhase, scopeResolutionPhase, mroPhase, communitiesPhase, processesPhase, } from './pipeline-phases/index.js';
|
|
18
|
+
import { runPipeline, getPhaseOutput, scanPhase, structurePhase, markdownPhase, cobolPhase, parsePhase, routesPhase, toolsPhase, ormPhase, crossFilePhase, scopeResolutionPhase, mroPhase, communitiesPhase, processesPhase, featureClustersPhase, } from './pipeline-phases/index.js';
|
|
19
19
|
// ── Phase registry ─────────────────────────────────────────────────────────
|
|
20
20
|
/**
|
|
21
21
|
* All pipeline phases with their dependency relationships.
|
|
22
22
|
*
|
|
23
23
|
* Phase dependency graph:
|
|
24
24
|
*
|
|
25
|
-
* scan
|
|
26
|
-
*
|
|
25
|
+
* scan -> structure -> [markdown, cobol] -> parse -> [routes, tools, orm]
|
|
26
|
+
* -> crossFile -> scopeResolution -> mro -> communities -> processes
|
|
27
|
+
* -> featureClusters
|
|
27
28
|
*
|
|
28
29
|
* To add a new phase: create a file in pipeline-phases/, export the phase
|
|
29
30
|
* object, and add it to the appropriate position in this array.
|
|
@@ -42,7 +43,7 @@ function buildPhaseList(options) {
|
|
|
42
43
|
scopeResolutionPhase,
|
|
43
44
|
];
|
|
44
45
|
if (!options?.skipGraphPhases) {
|
|
45
|
-
phases.push(mroPhase, communitiesPhase, processesPhase);
|
|
46
|
+
phases.push(mroPhase, communitiesPhase, processesPhase, featureClustersPhase);
|
|
46
47
|
}
|
|
47
48
|
return phases;
|
|
48
49
|
}
|
|
@@ -62,15 +63,17 @@ export const runPipelineFromRepo = async (repoPath, onProgress, options) => {
|
|
|
62
63
|
const { totalFiles, usedWorkerPool } = getPhaseOutput(results, 'parse');
|
|
63
64
|
let communityResult;
|
|
64
65
|
let processResult;
|
|
66
|
+
let featureClusterResult;
|
|
65
67
|
if (!options?.skipGraphPhases) {
|
|
66
68
|
communityResult = getPhaseOutput(results, 'communities').communityResult;
|
|
67
69
|
processResult = getPhaseOutput(results, 'processes').processResult;
|
|
70
|
+
featureClusterResult = getPhaseOutput(results, 'featureClusters').featureClusterResult;
|
|
68
71
|
}
|
|
69
72
|
onProgress({
|
|
70
73
|
phase: 'complete',
|
|
71
74
|
percent: 100,
|
|
72
75
|
message: communityResult && processResult
|
|
73
|
-
? `Graph complete! ${communityResult.stats.totalCommunities} communities, ${processResult.stats.totalProcesses} processes detected.`
|
|
76
|
+
? `Graph complete! ${communityResult.stats.totalCommunities} communities, ${processResult.stats.totalProcesses} processes, ${featureClusterResult?.stats.totalClusters ?? 0} feature clusters detected.`
|
|
74
77
|
: 'Graph complete! (graph phases skipped)',
|
|
75
78
|
stats: {
|
|
76
79
|
filesProcessed: totalFiles,
|
|
@@ -84,6 +87,7 @@ export const runPipelineFromRepo = async (repoPath, onProgress, options) => {
|
|
|
84
87
|
totalFileCount: totalFiles,
|
|
85
88
|
communityResult,
|
|
86
89
|
processResult,
|
|
90
|
+
featureClusterResult,
|
|
87
91
|
usedWorkerPool,
|
|
88
92
|
};
|
|
89
93
|
};
|
package/dist/core/run-analyze.js
CHANGED
|
@@ -31,6 +31,7 @@ export const PHASE_LABELS = {
|
|
|
31
31
|
heritage: 'Extracting inheritance',
|
|
32
32
|
communities: 'Detecting communities',
|
|
33
33
|
processes: 'Detecting processes',
|
|
34
|
+
feature_clusters: 'Building feature clusters',
|
|
34
35
|
complete: 'Pipeline complete',
|
|
35
36
|
cgdb: 'Loading into LadybugDB',
|
|
36
37
|
fts: 'Creating search indexes',
|
|
@@ -129,10 +130,10 @@ export async function runFullAnalysis(repoPath, options, callbacks) {
|
|
|
129
130
|
// ── Early-return: already up to date ──────────────────────────────
|
|
130
131
|
// Schema-version mismatch forces a full re-analyze regardless of commit
|
|
131
132
|
// equality: existing 1.7.x indexes have no `schemaVersion` field at all,
|
|
132
|
-
// and
|
|
133
|
-
//
|
|
134
|
-
//
|
|
135
|
-
//
|
|
133
|
+
// and current readers expect contentEncoding plus rich FeatureCluster
|
|
134
|
+
// context-pack columns. LadybugDB ALTER on existing tables is not validated
|
|
135
|
+
// end-to-end yet, so the supported migration path is re-analyze via a fresh
|
|
136
|
+
// CREATE NODE TABLE.
|
|
136
137
|
const schemaUpToDate = !!existingMeta && (existingMeta.schemaVersion ?? 0) >= INDEX_SCHEMA_VERSION;
|
|
137
138
|
if (existingMeta &&
|
|
138
139
|
schemaUpToDate &&
|
|
@@ -150,7 +151,7 @@ export async function runFullAnalysis(repoPath, options, callbacks) {
|
|
|
150
151
|
}
|
|
151
152
|
if (existingMeta && !schemaUpToDate) {
|
|
152
153
|
log(`Index schema version ${existingMeta.schemaVersion ?? '<missing>'} is older than ` +
|
|
153
|
-
`${INDEX_SCHEMA_VERSION} (
|
|
154
|
+
`${INDEX_SCHEMA_VERSION} (FeatureCluster context-pack schema). ` +
|
|
154
155
|
`Re-analyzing.`);
|
|
155
156
|
}
|
|
156
157
|
// ── Cache embeddings from existing index before rebuild ────────────
|
|
@@ -175,10 +176,14 @@ export async function runFullAnalysis(repoPath, options, callbacks) {
|
|
|
175
176
|
}
|
|
176
177
|
}
|
|
177
178
|
// ── Phase 1: Full Pipeline (0–60%) ────────────────────────────────
|
|
179
|
+
const repoNameForFeatureClusters = options.registryName ?? getInferredRepoName(repoPath) ?? path.basename(repoPath);
|
|
178
180
|
const pipelineResult = await runPipelineFromRepo(repoPath, (p) => {
|
|
179
181
|
const phaseLabel = PHASE_LABELS[p.phase] || p.phase;
|
|
180
182
|
const scaled = Math.round(p.percent * 0.6);
|
|
181
183
|
progress(p.phase, scaled, phaseLabel);
|
|
184
|
+
}, {
|
|
185
|
+
featureClusterRepo: repoNameForFeatureClusters,
|
|
186
|
+
lastIndexedCommit: currentCommit || undefined,
|
|
182
187
|
});
|
|
183
188
|
// ── Phase 2: LadybugDB (60–85%) ──────────────────────────────────
|
|
184
189
|
progress('cgdb', 60, 'Loading into LadybugDB...');
|
|
@@ -334,6 +339,7 @@ export async function runFullAnalysis(repoPath, options, callbacks) {
|
|
|
334
339
|
nodes: stats.nodes,
|
|
335
340
|
edges: stats.edges,
|
|
336
341
|
communities: pipelineResult.communityResult?.stats.totalCommunities,
|
|
342
|
+
featureClusters: pipelineResult.featureClusterResult?.stats.totalClusters,
|
|
337
343
|
processes: pipelineResult.processResult?.stats.totalProcesses,
|
|
338
344
|
embeddings: embeddingCount,
|
|
339
345
|
},
|
|
@@ -372,7 +378,7 @@ export async function runFullAnalysis(repoPath, options, callbacks) {
|
|
|
372
378
|
nodes: stats.nodes,
|
|
373
379
|
edges: stats.edges,
|
|
374
380
|
communities: pipelineResult.communityResult?.stats.totalCommunities,
|
|
375
|
-
clusters: aggregatedClusterCount,
|
|
381
|
+
clusters: pipelineResult.featureClusterResult?.stats.totalClusters ?? aggregatedClusterCount,
|
|
376
382
|
processes: pipelineResult.processResult?.stats.totalProcesses,
|
|
377
383
|
}, undefined, { skipAgentsMd: options.skipAgentsMd, noStats: options.noStats });
|
|
378
384
|
}
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { pipeline, env } from '@huggingface/transformers';
|
|
8
8
|
import { isHttpMode, getHttpDimensions, httpEmbedQuery, } from '../../core/embeddings/http-client.js';
|
|
9
|
+
import { homedir } from 'os';
|
|
10
|
+
import { join } from 'path';
|
|
9
11
|
import { silenceStdout, restoreStdout, realStderrWrite } from '../../core/cgdb/pool-adapter.js';
|
|
10
12
|
// Model config
|
|
11
13
|
const MODEL_ID = 'Snowflake/snowflake-arctic-embed-xs';
|
|
@@ -33,8 +35,9 @@ export const initEmbedder = async () => {
|
|
|
33
35
|
// Default cache to user-writable location. transformers.js defaults to
|
|
34
36
|
// ./node_modules/.cache inside its own install dir, which is unwritable
|
|
35
37
|
// when codragraph is installed globally (e.g. /usr/lib/node_modules/).
|
|
36
|
-
// Respect HF_HOME if set, otherwise fall back to
|
|
37
|
-
|
|
38
|
+
// Respect HF_HOME if set, otherwise fall back to a user-writable cache
|
|
39
|
+
// path using Node's OS-aware home directory resolution.
|
|
40
|
+
env.cacheDir = process.env.HF_HOME ?? join(homedir(), '.cache', 'huggingface');
|
|
38
41
|
console.error('CodraGraph: Loading embedding model (first search may take a moment)...');
|
|
39
42
|
// Try GPU first (DirectML on Windows, CUDA on Linux), fall back to CPU
|
|
40
43
|
const isWindows = process.platform === 'win32';
|
|
@@ -323,6 +323,18 @@ export declare class LocalBackend {
|
|
|
323
323
|
* Query clusters (communities) directly from graph.
|
|
324
324
|
* Used by getClustersResource — avoids legacy overview() dispatch.
|
|
325
325
|
*/
|
|
326
|
+
/**
|
|
327
|
+
* Query feature clusters directly from graph.
|
|
328
|
+
* FeatureCluster is the human-facing project area layer above Communities.
|
|
329
|
+
*/
|
|
330
|
+
queryFeatureClusters(repoName?: string, limit?: number, query?: string): Promise<{
|
|
331
|
+
clusters: any[];
|
|
332
|
+
}>;
|
|
333
|
+
/**
|
|
334
|
+
* Query one feature cluster with members, dependencies, and process links.
|
|
335
|
+
*/
|
|
336
|
+
queryFeatureContext(name: string, repoName?: string, limit?: number): Promise<any>;
|
|
337
|
+
queryFeatureImpact(name: string, repoName?: string, direction?: 'upstream' | 'downstream' | 'both', limit?: number): Promise<any>;
|
|
326
338
|
queryClusters(repoName?: string, limit?: number): Promise<{
|
|
327
339
|
clusters: any[];
|
|
328
340
|
}>;
|