closed-loop-cli 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.

Potentially problematic release.


This version of closed-loop-cli might be problematic. Click here for more details.

Files changed (86) hide show
  1. package/dist/dashboard/server.js +237 -0
  2. package/dist/index.js +272 -0
  3. package/dist/orchestrator/agent-prompts.js +42 -0
  4. package/dist/orchestrator/autogenesis.js +973 -0
  5. package/dist/orchestrator/dgm-archive.js +223 -0
  6. package/dist/orchestrator/event-stream.js +103 -0
  7. package/dist/orchestrator/fitness-evaluator.js +99 -0
  8. package/dist/orchestrator/meta-agent.js +421 -0
  9. package/dist/orchestrator/microagent-registry.js +134 -0
  10. package/dist/orchestrator/mutation-strategies.js +174 -0
  11. package/dist/orchestrator/prompt-benchmark.js +102 -0
  12. package/dist/orchestrator/prompt-optimizer.js +169 -0
  13. package/dist/orchestrator/refactor-scanner.js +222 -0
  14. package/dist/orchestrator/research-manager.js +104 -0
  15. package/dist/orchestrator/rulez.js +135 -0
  16. package/dist/orchestrator/sahoo-gateway.js +261 -0
  17. package/dist/orchestrator/state-manager.js +121 -0
  18. package/dist/orchestrator/task-agent.js +444 -0
  19. package/dist/orchestrator/telegram-bot.js +374 -0
  20. package/dist/orchestrator/types.js +2 -0
  21. package/dist/tests/dynamic/dependencies.test.js +37 -0
  22. package/dist/tests/dynamic/dummy.test.js +7 -0
  23. package/dist/tests/dynamic/fuzzy-patch.test.js +68 -0
  24. package/dist/tests/dynamic/indexer.test.js +60 -0
  25. package/dist/tests/dynamic/openhands.test.js +83 -0
  26. package/dist/tests/dynamic/skills.test.js +88 -0
  27. package/dist/tests/run-tests.js +294 -0
  28. package/dist/tools/diff-tools.js +24 -0
  29. package/dist/tools/file-tools.js +191 -0
  30. package/dist/tools/indexer.js +301 -0
  31. package/dist/tools/math-helper.js +6 -0
  32. package/dist/tools/repo-map.js +122 -0
  33. package/dist/tools/search-tools.js +271 -0
  34. package/dist/tools/shell-tools.js +75 -0
  35. package/dist/tools/skills.js +122 -0
  36. package/dist/tools/tui-tools.js +82 -0
  37. package/docs/AI_Arch_Opt_Anti_Gaming.md +227 -0
  38. package/docs/AI_Self_Improvement_Safety.md +457 -0
  39. package/docs/Anthropic AI Agents_ Capabilities and Concerns.md +134 -0
  40. package/docs/Auto_ClosedLoop_AI_Agent.md +415 -0
  41. package/docs/Autonomous AI Agents_ Closing the Loop.docx +0 -0
  42. package/docs/Secure_AI_Sandbox_Framework.md +358 -0
  43. package/docs/skills/add-file-existence-check-utility.json +9 -0
  44. package/docs/skills/add-utility-function-for-file-existence-check.json +9 -0
  45. package/docs/skills/add-utility-function-to-module.json +9 -0
  46. package/docs/skills/extract-command-runner-utility.json +9 -0
  47. package/docs/skills/file-existence-check-utility.json +9 -0
  48. package/package.json +36 -0
  49. package/src/dashboard/public/index.css +1334 -0
  50. package/src/dashboard/public/index.html +385 -0
  51. package/src/dashboard/public/index.js +1059 -0
  52. package/src/dashboard/server.ts +209 -0
  53. package/src/index.ts +256 -0
  54. package/src/orchestrator/agent-prompts.ts +43 -0
  55. package/src/orchestrator/autogenesis.ts +1078 -0
  56. package/src/orchestrator/dgm-archive.ts +257 -0
  57. package/src/orchestrator/event-stream.ts +90 -0
  58. package/src/orchestrator/fitness-evaluator.ts +154 -0
  59. package/src/orchestrator/meta-agent.ts +434 -0
  60. package/src/orchestrator/microagent-registry.ts +115 -0
  61. package/src/orchestrator/microagents/git-helper.md +11 -0
  62. package/src/orchestrator/microagents/test-fixer.md +10 -0
  63. package/src/orchestrator/microagents/typescript-expert.md +11 -0
  64. package/src/orchestrator/mutation-strategies.ts +214 -0
  65. package/src/orchestrator/research-manager.ts +88 -0
  66. package/src/orchestrator/rulez.ts +118 -0
  67. package/src/orchestrator/sahoo-gateway.ts +300 -0
  68. package/src/orchestrator/state-manager.ts +161 -0
  69. package/src/orchestrator/system-prompt.txt +1 -0
  70. package/src/orchestrator/task-agent.ts +461 -0
  71. package/src/orchestrator/telegram-bot.ts +358 -0
  72. package/src/tests/dynamic/dependencies.test.ts +48 -0
  73. package/src/tests/dynamic/dummy.test.ts +4 -0
  74. package/src/tests/dynamic/fuzzy-patch.test.ts +42 -0
  75. package/src/tests/dynamic/indexer.test.ts +31 -0
  76. package/src/tests/dynamic/openhands.test.ts +59 -0
  77. package/src/tests/dynamic/skills.test.ts +63 -0
  78. package/src/tests/run-tests.ts +296 -0
  79. package/src/tools/diff-tools.ts +27 -0
  80. package/src/tools/file-tools.ts +187 -0
  81. package/src/tools/indexer.ts +325 -0
  82. package/src/tools/repo-map.ts +96 -0
  83. package/src/tools/search-tools.ts +258 -0
  84. package/src/tools/shell-tools.ts +90 -0
  85. package/src/tools/skills.ts +101 -0
  86. package/src/tools/tui-tools.ts +87 -0
@@ -0,0 +1,301 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.generateCodeIndex = generateCodeIndex;
37
+ exports.getDependents = getDependents;
38
+ exports.queryCodeIndex = queryCodeIndex;
39
+ const fs = __importStar(require("fs"));
40
+ const path = __importStar(require("path"));
41
+ const ts = __importStar(require("typescript"));
42
+ /**
43
+ * Resolves relative module import paths to standardized workspace-relative paths.
44
+ */
45
+ function resolveImportPath(fromFile, importPath, workspaceRoot = process.cwd()) {
46
+ const fromDir = path.dirname(path.join(workspaceRoot, fromFile));
47
+ const absoluteTarget = path.resolve(fromDir, importPath);
48
+ const relativeTarget = path.relative(workspaceRoot, absoluteTarget).replace(/\\/g, '/');
49
+ // Try standard file extensions
50
+ const extensions = ['.ts', '.js', '/index.ts', '/index.js'];
51
+ for (const ext of extensions) {
52
+ const targetWithExt = absoluteTarget + ext;
53
+ if (fs.existsSync(targetWithExt)) {
54
+ return (relativeTarget + ext).replace(/\/index\.(ts|js)$/, '');
55
+ }
56
+ }
57
+ // If file exists as-is
58
+ if (fs.existsSync(absoluteTarget)) {
59
+ return relativeTarget;
60
+ }
61
+ // Fallback target path
62
+ return relativeTarget + '.ts';
63
+ }
64
+ /**
65
+ * Generates the code index database and writes it to code-index.json.
66
+ */
67
+ function generateCodeIndex(workspaceRoot = process.cwd()) {
68
+ const index = [];
69
+ function walk(currentDir) {
70
+ const files = fs.readdirSync(currentDir);
71
+ for (const file of files) {
72
+ const fullPath = path.join(currentDir, file);
73
+ // Skip ignorable folders
74
+ if (file === 'node_modules' || file === '.git' || file === 'dist' || file === '.gemini') {
75
+ continue;
76
+ }
77
+ const stats = fs.statSync(fullPath);
78
+ if (stats.isDirectory()) {
79
+ walk(fullPath);
80
+ }
81
+ else if (stats.isFile()) {
82
+ const ext = path.extname(file).toLowerCase();
83
+ if (ext === '.ts' || ext === '.js') {
84
+ const relativePath = path.relative(workspaceRoot, fullPath).replace(/\\/g, '/');
85
+ const content = fs.readFileSync(fullPath, 'utf-8');
86
+ const fileIndex = parseFileAST(relativePath, content);
87
+ index.push(fileIndex);
88
+ }
89
+ }
90
+ }
91
+ }
92
+ walk(workspaceRoot);
93
+ const indexPath = path.join(workspaceRoot, 'code-index.json');
94
+ fs.writeFileSync(indexPath, JSON.stringify(index, null, 2), 'utf-8');
95
+ return index;
96
+ }
97
+ /**
98
+ * Parses file AST to extract structured metadata.
99
+ */
100
+ function parseFileAST(filePath, content) {
101
+ const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
102
+ const fileIndex = {
103
+ filePath,
104
+ classes: [],
105
+ interfaces: [],
106
+ functions: [],
107
+ imports: [],
108
+ exports: []
109
+ };
110
+ let currentClass = null;
111
+ function visit(node) {
112
+ const isExport = (node.modifiers?.some((m) => m.kind === ts.SyntaxKind.ExportKeyword)) || false;
113
+ // Capture Imports
114
+ if (ts.isImportDeclaration(node) && node.moduleSpecifier) {
115
+ if (ts.isStringLiteral(node.moduleSpecifier)) {
116
+ const importPath = node.moduleSpecifier.text;
117
+ if (importPath.startsWith('.')) {
118
+ const resolved = resolveImportPath(filePath, importPath);
119
+ if (resolved) {
120
+ fileIndex.imports.push(resolved);
121
+ }
122
+ }
123
+ else {
124
+ fileIndex.imports.push(importPath); // NPM library import
125
+ }
126
+ }
127
+ }
128
+ // Capture Named and Default Export statements
129
+ if (ts.isExportDeclaration(node)) {
130
+ if (node.exportClause && ts.isNamedExports(node.exportClause)) {
131
+ for (const element of node.exportClause.elements) {
132
+ fileIndex.exports.push(element.name.text);
133
+ }
134
+ }
135
+ }
136
+ else if (ts.isExportAssignment(node)) {
137
+ fileIndex.exports.push('default');
138
+ }
139
+ // Capture Classes and Methods
140
+ if (ts.isClassDeclaration(node) && node.name) {
141
+ if (isExport) {
142
+ fileIndex.exports.push(node.name.text);
143
+ }
144
+ const classObj = {
145
+ name: node.name.text,
146
+ methods: []
147
+ };
148
+ fileIndex.classes.push(classObj);
149
+ const oldClass = currentClass;
150
+ currentClass = classObj;
151
+ ts.forEachChild(node, visit);
152
+ currentClass = oldClass;
153
+ }
154
+ else if (ts.isInterfaceDeclaration(node) && node.name) {
155
+ if (isExport) {
156
+ fileIndex.exports.push(node.name.text);
157
+ }
158
+ fileIndex.interfaces.push({ name: node.name.text });
159
+ }
160
+ else if (ts.isFunctionDeclaration(node) && node.name) {
161
+ if (isExport) {
162
+ fileIndex.exports.push(node.name.text);
163
+ }
164
+ const isAsync = (node.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword)) || false;
165
+ const params = node.parameters.map(p => p.name.getText(sourceFile));
166
+ fileIndex.functions.push({
167
+ name: node.name.text,
168
+ isAsync,
169
+ parameters: params
170
+ });
171
+ }
172
+ else if (ts.isVariableStatement(node)) {
173
+ if (isExport) {
174
+ for (const decl of node.declarationList.declarations) {
175
+ fileIndex.exports.push(decl.name.getText(sourceFile));
176
+ }
177
+ }
178
+ for (const decl of node.declarationList.declarations) {
179
+ if (decl.initializer && (ts.isArrowFunction(decl.initializer) || ts.isFunctionExpression(decl.initializer))) {
180
+ const func = decl.initializer;
181
+ const isAsync = (func.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword)) || false;
182
+ const params = func.parameters.map(p => p.name.getText(sourceFile));
183
+ fileIndex.functions.push({
184
+ name: decl.name.getText(sourceFile),
185
+ isAsync,
186
+ parameters: params
187
+ });
188
+ }
189
+ }
190
+ }
191
+ else if (currentClass && ts.isMethodDeclaration(node) && node.name) {
192
+ const isAsync = (node.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword)) || false;
193
+ const isStatic = (node.modifiers?.some((m) => m.kind === ts.SyntaxKind.StaticKeyword)) || false;
194
+ const params = node.parameters.map(p => p.name.getText(sourceFile));
195
+ currentClass.methods.push({
196
+ name: node.name.getText(sourceFile),
197
+ isStatic,
198
+ isAsync,
199
+ parameters: params
200
+ });
201
+ }
202
+ else {
203
+ ts.forEachChild(node, visit);
204
+ }
205
+ }
206
+ ts.forEachChild(sourceFile, visit);
207
+ return fileIndex;
208
+ }
209
+ /**
210
+ * Queries code-index.json to find all files that import a given target file.
211
+ */
212
+ function getDependents(targetFile, workspaceRoot = process.cwd()) {
213
+ const indexPath = path.join(workspaceRoot, 'code-index.json');
214
+ if (!fs.existsSync(indexPath)) {
215
+ return [];
216
+ }
217
+ let index = [];
218
+ try {
219
+ index = JSON.parse(fs.readFileSync(indexPath, 'utf-8'));
220
+ }
221
+ catch (e) {
222
+ return [];
223
+ }
224
+ const targetNormalized = targetFile.replace(/\\/g, '/').replace(/^\.\//, '');
225
+ const targetBase = targetNormalized.replace(/\.(ts|js)$/, '');
226
+ const dependents = [];
227
+ for (const file of index) {
228
+ const hasImport = file.imports.some(imp => {
229
+ const impNormalized = imp.replace(/\.(ts|js)$/, '');
230
+ return impNormalized === targetBase || impNormalized === targetNormalized;
231
+ });
232
+ if (hasImport && file.filePath !== targetNormalized) {
233
+ dependents.push(file.filePath);
234
+ }
235
+ }
236
+ return dependents;
237
+ }
238
+ /**
239
+ * Queries the code-index.json database for keyword matches.
240
+ */
241
+ function queryCodeIndex(query, workspaceRoot = process.cwd()) {
242
+ const indexPath = path.join(workspaceRoot, 'code-index.json');
243
+ if (!fs.existsSync(indexPath)) {
244
+ generateCodeIndex(workspaceRoot);
245
+ }
246
+ let index = [];
247
+ try {
248
+ index = JSON.parse(fs.readFileSync(indexPath, 'utf-8'));
249
+ }
250
+ catch (e) {
251
+ return `Error reading code-index.json: ${e.message}`;
252
+ }
253
+ const queryLower = query.toLowerCase();
254
+ const matches = [];
255
+ for (const file of index) {
256
+ let fileHasMatch = false;
257
+ const fileLines = [];
258
+ // Check class names and methods
259
+ for (const cls of file.classes) {
260
+ let classMatched = cls.name.toLowerCase().includes(queryLower);
261
+ const matchedMethods = cls.methods.filter(m => m.name.toLowerCase().includes(queryLower));
262
+ if (classMatched || matchedMethods.length > 0) {
263
+ fileHasMatch = true;
264
+ fileLines.push(` class ${cls.name}`);
265
+ for (const m of cls.methods) {
266
+ const isMatched = m.name.toLowerCase().includes(queryLower);
267
+ const highlight = isMatched ? ' <-- MATCH' : '';
268
+ fileLines.push(` - method ${m.isStatic ? 'static ' : ''}${m.isAsync ? 'async ' : ''}${m.name}(${m.parameters.join(', ')})${highlight}`);
269
+ }
270
+ }
271
+ }
272
+ // Check interfaces
273
+ for (const intf of file.interfaces) {
274
+ if (intf.name.toLowerCase().includes(queryLower)) {
275
+ fileHasMatch = true;
276
+ fileLines.push(` interface ${intf.name} <-- MATCH`);
277
+ }
278
+ }
279
+ // Check functions
280
+ for (const fn of file.functions) {
281
+ if (fn.name.toLowerCase().includes(queryLower)) {
282
+ fileHasMatch = true;
283
+ fileLines.push(` function ${fn.isAsync ? 'async ' : ''}${fn.name}(${fn.parameters.join(', ')}) <-- MATCH`);
284
+ }
285
+ }
286
+ // Check filepath match
287
+ if (file.filePath.toLowerCase().includes(queryLower) && !fileHasMatch) {
288
+ fileHasMatch = true;
289
+ fileLines.push(` [File matched by name]`);
290
+ }
291
+ if (fileHasMatch) {
292
+ matches.push(`File: ${file.filePath}`);
293
+ matches.push(...fileLines);
294
+ matches.push('');
295
+ }
296
+ }
297
+ if (matches.length === 0) {
298
+ return `No matches found in code index for query "${query}".`;
299
+ }
300
+ return matches.join('\n').trim();
301
+ }
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sum = sum;
4
+ function sum(a, b) {
5
+ return a + b;
6
+ }
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.generateRepoMap = generateRepoMap;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const ts = __importStar(require("typescript"));
40
+ function generateRepoMap(workspaceRoot = process.cwd()) {
41
+ const mapLines = [];
42
+ function walk(currentDir) {
43
+ const files = fs.readdirSync(currentDir);
44
+ for (const file of files) {
45
+ const fullPath = path.join(currentDir, file);
46
+ // Skip ignorable folders
47
+ if (file === 'node_modules' || file === '.git' || file === 'dist' || file === '.gemini') {
48
+ continue;
49
+ }
50
+ const stats = fs.statSync(fullPath);
51
+ if (stats.isDirectory()) {
52
+ walk(fullPath);
53
+ }
54
+ else if (stats.isFile()) {
55
+ const ext = path.extname(file).toLowerCase();
56
+ if (ext === '.ts' || ext === '.js') {
57
+ const relativePath = path.relative(workspaceRoot, fullPath).replace(/\\/g, '/');
58
+ const content = fs.readFileSync(fullPath, 'utf-8');
59
+ const signatures = extractSignatures(relativePath, content);
60
+ if (signatures.length > 0) {
61
+ mapLines.push(`File: ${relativePath}`);
62
+ signatures.forEach(sig => mapLines.push(` - ${sig}`));
63
+ mapLines.push('');
64
+ }
65
+ }
66
+ }
67
+ }
68
+ }
69
+ walk(workspaceRoot);
70
+ return mapLines.join('\n').trim();
71
+ }
72
+ /**
73
+ * Extracts class, interface, function, and method signatures using the TypeScript Compiler AST API.
74
+ */
75
+ function extractSignatures(filePath, content) {
76
+ const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
77
+ const signatures = [];
78
+ let currentClass = null;
79
+ function visit(node) {
80
+ if (ts.isClassDeclaration(node) && node.name) {
81
+ const className = node.name.text;
82
+ signatures.push(`class ${className}`);
83
+ const oldClass = currentClass;
84
+ currentClass = className;
85
+ ts.forEachChild(node, visit);
86
+ currentClass = oldClass;
87
+ }
88
+ else if (ts.isInterfaceDeclaration(node) && node.name) {
89
+ signatures.push(`interface ${node.name.text}`);
90
+ }
91
+ else if (ts.isFunctionDeclaration(node) && node.name) {
92
+ const isAsync = node.modifiers?.some(m => m.kind === ts.SyntaxKind.AsyncKeyword) ? 'async ' : '';
93
+ const params = node.parameters.map(p => p.name.getText(sourceFile)).join(', ');
94
+ signatures.push(`${isAsync}function ${node.name.text}(${params})`);
95
+ }
96
+ else if (ts.isVariableStatement(node)) {
97
+ // Check if it is an exported const arrow/expression function
98
+ const isExport = node.modifiers?.some(m => m.kind === ts.SyntaxKind.ExportKeyword);
99
+ if (isExport) {
100
+ for (const decl of node.declarationList.declarations) {
101
+ if (decl.initializer && (ts.isArrowFunction(decl.initializer) || ts.isFunctionExpression(decl.initializer))) {
102
+ const func = decl.initializer;
103
+ const isAsync = func.modifiers?.some(m => m.kind === ts.SyntaxKind.AsyncKeyword) ? 'async ' : '';
104
+ const params = func.parameters.map(p => p.name.getText(sourceFile)).join(', ');
105
+ signatures.push(`${isAsync}const ${decl.name.getText(sourceFile)} = (${params}) =>`);
106
+ }
107
+ }
108
+ }
109
+ }
110
+ else if (currentClass && ts.isMethodDeclaration(node) && node.name) {
111
+ const isAsync = node.modifiers?.some(m => m.kind === ts.SyntaxKind.AsyncKeyword) ? 'async ' : '';
112
+ const isStatic = node.modifiers?.some(m => m.kind === ts.SyntaxKind.StaticKeyword) ? 'static ' : '';
113
+ const params = node.parameters.map(p => p.name.getText(sourceFile)).join(', ');
114
+ signatures.push(`method ${isStatic}${isAsync}${node.name.getText(sourceFile)}(${params})`);
115
+ }
116
+ else {
117
+ ts.forEachChild(node, visit);
118
+ }
119
+ }
120
+ ts.forEachChild(sourceFile, visit);
121
+ return signatures;
122
+ }