micro-models-agent 0.28.0 → 0.28.2

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 (167) hide show
  1. package/dist/main.js +826 -650
  2. package/package.json +1 -1
  3. package/dist/cli/commands.js +0 -220
  4. package/dist/cli/completer.js +0 -168
  5. package/dist/cli/index.js +0 -2
  6. package/dist/cli/main.js +0 -113
  7. package/dist/cli/repl.js +0 -987
  8. package/dist/cli/security-commands.js +0 -166
  9. package/dist/cli/setup.js +0 -229
  10. package/dist/config/config.js +0 -186
  11. package/dist/config/defaults.js +0 -91
  12. package/dist/config/experts.js +0 -15
  13. package/dist/config/index.js +0 -3
  14. package/dist/config/security.js +0 -193
  15. package/dist/config/types.js +0 -1
  16. package/dist/core/agent-moe.js +0 -98
  17. package/dist/core/agent.js +0 -461
  18. package/dist/core/bootstrap.js +0 -321
  19. package/dist/core/index.js +0 -2
  20. package/dist/core/prompt-builder.js +0 -55
  21. package/dist/core/session-logger.js +0 -122
  22. package/dist/core/types.js +0 -1
  23. package/dist/i18n/en.json +0 -461
  24. package/dist/i18n/index.js +0 -43
  25. package/dist/i18n/ru.json +0 -461
  26. package/dist/index.js +0 -22
  27. package/dist/llm/image-utils.js +0 -144
  28. package/dist/llm/index.js +0 -4
  29. package/dist/llm/model-loader.js +0 -78
  30. package/dist/llm/openai-compat.js +0 -324
  31. package/dist/llm/orchestrator.js +0 -194
  32. package/dist/llm/provider.js +0 -10
  33. package/dist/llm/response.js +0 -39
  34. package/dist/llm/token-counter.js +0 -39
  35. package/dist/llm/types.js +0 -1
  36. package/dist/logger/app-logger.js +0 -76
  37. package/dist/logger/index.js +0 -1
  38. package/dist/migration/backup.js +0 -45
  39. package/dist/migration/detect.js +0 -50
  40. package/dist/migration/index.js +0 -2
  41. package/dist/modules/browser/actions.js +0 -46
  42. package/dist/modules/browser/cookie-store.js +0 -24
  43. package/dist/modules/browser/index.js +0 -5
  44. package/dist/modules/browser/module.js +0 -28
  45. package/dist/modules/browser/session.js +0 -287
  46. package/dist/modules/browser/snapshot.js +0 -114
  47. package/dist/modules/browser/types.js +0 -9
  48. package/dist/modules/context/history.js +0 -15
  49. package/dist/modules/context/index.js +0 -1
  50. package/dist/modules/context/manager.js +0 -240
  51. package/dist/modules/execution/auditor.js +0 -72
  52. package/dist/modules/execution/index.js +0 -6
  53. package/dist/modules/execution/module.js +0 -337
  54. package/dist/modules/execution/moe-executor.js +0 -209
  55. package/dist/modules/execution/plan-validator.js +0 -153
  56. package/dist/modules/execution/planner.js +0 -35
  57. package/dist/modules/execution/stuck-detector.js +0 -134
  58. package/dist/modules/execution/tracker.js +0 -53
  59. package/dist/modules/execution/types.js +0 -1
  60. package/dist/modules/execution/verifier.js +0 -149
  61. package/dist/modules/hallucination/confidence.js +0 -54
  62. package/dist/modules/hallucination/consistency.js +0 -60
  63. package/dist/modules/hallucination/detector.js +0 -41
  64. package/dist/modules/hallucination/factual.js +0 -170
  65. package/dist/modules/hallucination/index.js +0 -4
  66. package/dist/modules/index.js +0 -5
  67. package/dist/modules/indexer/cache.js +0 -38
  68. package/dist/modules/indexer/index.js +0 -3
  69. package/dist/modules/indexer/module.js +0 -192
  70. package/dist/modules/indexer/walker.js +0 -101
  71. package/dist/modules/mcp/client.js +0 -393
  72. package/dist/modules/mcp/index.js +0 -3
  73. package/dist/modules/mcp/module.js +0 -146
  74. package/dist/modules/mcp/registry.js +0 -15
  75. package/dist/modules/memory/index.js +0 -1
  76. package/dist/modules/memory/module.js +0 -48
  77. package/dist/modules/memory/search.js +0 -40
  78. package/dist/modules/memory/store.js +0 -65
  79. package/dist/modules/pipelines/engine.js +0 -60
  80. package/dist/modules/pipelines/index.js +0 -3
  81. package/dist/modules/pipelines/parser.js +0 -53
  82. package/dist/modules/pipelines/template.js +0 -14
  83. package/dist/modules/plugins/builtin/lint-on-write.js +0 -121
  84. package/dist/modules/plugins/builtin/notify.js +0 -8
  85. package/dist/modules/plugins/index.js +0 -1
  86. package/dist/modules/plugins/loader.js +0 -28
  87. package/dist/modules/plugins/manager.js +0 -161
  88. package/dist/modules/plugins/types.js +0 -1
  89. package/dist/modules/processes/detect.js +0 -34
  90. package/dist/modules/processes/index.js +0 -3
  91. package/dist/modules/processes/registry.js +0 -148
  92. package/dist/modules/processes/runner.js +0 -124
  93. package/dist/modules/registry.js +0 -45
  94. package/dist/modules/security/audit-log.js +0 -116
  95. package/dist/modules/security/audit-notifier.js +0 -292
  96. package/dist/modules/security/command-validator.js +0 -185
  97. package/dist/modules/security/content-scanner.js +0 -52
  98. package/dist/modules/security/data-sanitizer.js +0 -97
  99. package/dist/modules/security/encryption.js +0 -240
  100. package/dist/modules/security/index.js +0 -14
  101. package/dist/modules/security/network-validator.js +0 -79
  102. package/dist/modules/security/path-validator.js +0 -155
  103. package/dist/modules/security/rate-limiter.js +0 -119
  104. package/dist/modules/security/security-policies.js +0 -393
  105. package/dist/modules/security/session-encryption.js +0 -193
  106. package/dist/modules/security/session-isolation.js +0 -95
  107. package/dist/modules/session/index.js +0 -3
  108. package/dist/modules/session/manager.js +0 -167
  109. package/dist/modules/session/module.js +0 -24
  110. package/dist/modules/session/store.js +0 -174
  111. package/dist/modules/session/types.js +0 -1
  112. package/dist/modules/skills/index.js +0 -3
  113. package/dist/modules/skills/loader.js +0 -72
  114. package/dist/modules/skills/matcher.js +0 -27
  115. package/dist/modules/skills/module.js +0 -143
  116. package/dist/modules/types.js +0 -1
  117. package/dist/modules/updater/checker.js +0 -32
  118. package/dist/modules/updater/index.js +0 -1
  119. package/dist/modules/user-profile/compressor.js +0 -16
  120. package/dist/modules/user-profile/index.js +0 -1
  121. package/dist/modules/user-profile/profile.js +0 -68
  122. package/dist/tools/approve.js +0 -32
  123. package/dist/tools/attach-image.js +0 -89
  124. package/dist/tools/bash.js +0 -140
  125. package/dist/tools/browser.js +0 -97
  126. package/dist/tools/create-dir.js +0 -56
  127. package/dist/tools/delete-file.js +0 -63
  128. package/dist/tools/edit-file.js +0 -77
  129. package/dist/tools/executor.js +0 -95
  130. package/dist/tools/file-info.js +0 -45
  131. package/dist/tools/filter-tools.js +0 -10
  132. package/dist/tools/glob-tool.js +0 -26
  133. package/dist/tools/grep-tool.js +0 -64
  134. package/dist/tools/index.js +0 -52
  135. package/dist/tools/list-dir.js +0 -47
  136. package/dist/tools/load-skill.js +0 -48
  137. package/dist/tools/mcp-call.js +0 -68
  138. package/dist/tools/move-file.js +0 -84
  139. package/dist/tools/path-utils.js +0 -51
  140. package/dist/tools/pipeline-run.js +0 -144
  141. package/dist/tools/preview.js +0 -2
  142. package/dist/tools/process-kill.js +0 -29
  143. package/dist/tools/process-list.js +0 -38
  144. package/dist/tools/process-log.js +0 -41
  145. package/dist/tools/question.js +0 -142
  146. package/dist/tools/read-file.js +0 -73
  147. package/dist/tools/recall.js +0 -110
  148. package/dist/tools/registry.js +0 -36
  149. package/dist/tools/remember.js +0 -67
  150. package/dist/tools/scope-check.js +0 -30
  151. package/dist/tools/search-history.js +0 -64
  152. package/dist/tools/subagent.js +0 -142
  153. package/dist/tools/types.js +0 -1
  154. package/dist/tools/user-input.js +0 -123
  155. package/dist/tools/web-browse.js +0 -57
  156. package/dist/tools/web-fetch.js +0 -72
  157. package/dist/tools/web-search.js +0 -59
  158. package/dist/tools/write-file.js +0 -80
  159. package/dist/ui/box.js +0 -81
  160. package/dist/ui/colors.js +0 -4
  161. package/dist/ui/diff.js +0 -185
  162. package/dist/ui/index.js +0 -6
  163. package/dist/ui/md-formatter.js +0 -212
  164. package/dist/ui/output.js +0 -13
  165. package/dist/ui/renderer.js +0 -141
  166. package/dist/ui/spinner.js +0 -70
  167. package/dist/ui/table.js +0 -144
@@ -1,170 +0,0 @@
1
- import { t } from "../../i18n/index";
2
- import { existsSync } from "fs";
3
- import { join } from "path";
4
- const FILE_EXTENSIONS = new Set([
5
- "ts",
6
- "tsx",
7
- "js",
8
- "jsx",
9
- "mjs",
10
- "cjs",
11
- "mts",
12
- "cts",
13
- "json",
14
- "md",
15
- "yaml",
16
- "yml",
17
- "py",
18
- "rs",
19
- "go",
20
- "java",
21
- "c",
22
- "cpp",
23
- "h",
24
- "hpp",
25
- "html",
26
- "css",
27
- "scss",
28
- "less",
29
- "vue",
30
- "svelte",
31
- "sh",
32
- "bash",
33
- "zsh",
34
- "ps1",
35
- "bat",
36
- "cmd",
37
- "txt",
38
- "env",
39
- "env.local",
40
- "env.production",
41
- "gitignore",
42
- "dockerignore",
43
- "dockerfile",
44
- "makefile",
45
- "cmake",
46
- "toml",
47
- "lock",
48
- "config",
49
- "log",
50
- "xml",
51
- "sql",
52
- "graphql",
53
- "proto",
54
- "wasm",
55
- ]);
56
- const VERSION_PATTERN = /^\d+(\.\d+)*$/;
57
- const COMMON_WORDS = new Set([
58
- "node.js", "Node.js",
59
- "console.log", "console.error", "console.warn", "console.info",
60
- "Math.floor", "Math.ceil", "Math.round", "Math.max", "Math.min",
61
- "JSON.parse", "JSON.stringify",
62
- "Object.keys", "Object.values", "Object.entries",
63
- "Array.from", "Array.isArray",
64
- "Date.now", "Date.parse",
65
- "RegExp", "Promise",
66
- ]);
67
- export class FactualCheck {
68
- knownPaths = new Set();
69
- createdPaths = new Set();
70
- readFiles = new Set();
71
- baseDir = process.cwd();
72
- setBaseDir(dir) {
73
- this.baseDir = dir;
74
- }
75
- trackReadPath(path) {
76
- this.knownPaths.add(path);
77
- const base = path.split(/[/\\]/).pop();
78
- if (base && base !== path)
79
- this.knownPaths.add(base);
80
- // Track that this file was actually read by the agent
81
- this.readFiles.add(base || path);
82
- }
83
- trackCreatedPath(path) {
84
- this.knownPaths.add(path);
85
- const base = path.split(/[/\\]/).pop();
86
- if (base && base !== path)
87
- this.knownPaths.add(base);
88
- this.createdPaths.add(path);
89
- }
90
- trackDeletedPath(path) {
91
- this.knownPaths.add(path);
92
- const base = path.split(/[/\\]/).pop();
93
- if (base && base !== path)
94
- this.knownPaths.add(base);
95
- this.createdPaths.delete(path);
96
- }
97
- /**
98
- * Register file paths found in a document (e.g. structure.md, README).
99
- * Files mentioned in project documentation are not hallucinations.
100
- */
101
- trackDocumentContent(content) {
102
- // Match common path patterns in documentation
103
- const pathPatterns = /(?:^|\s)([\w\-./]+\.\w{1,10})(?:\s|$|[,;)])/gm;
104
- let match;
105
- while ((match = pathPatterns.exec(content)) !== null) {
106
- const file = match[1];
107
- if (file.includes('/') || file.includes('\\')) {
108
- this.knownPaths.add(file);
109
- }
110
- const base = file.split(/[/\\]/).pop();
111
- if (base)
112
- this.knownPaths.add(base);
113
- }
114
- }
115
- pathExistsOnDisk(path) {
116
- try {
117
- // Skip absolute paths — they're either system paths or outside the project.
118
- // On Windows, existsSync('/...') can hang on certain paths.
119
- if (path.startsWith("/") || path.startsWith("~") || /^[A-Za-z]:/.test(path)) {
120
- return false;
121
- }
122
- return existsSync(join(this.baseDir, path));
123
- }
124
- catch {
125
- return false;
126
- }
127
- }
128
- validate(response) {
129
- const pathRegex = /[\w\-./]+\.\w+/g;
130
- const mentionedPaths = response.match(pathRegex) || [];
131
- const unknownPaths = mentionedPaths.filter((p) => {
132
- if (this.knownPaths.has(p))
133
- return false;
134
- if (VERSION_PATTERN.test(p))
135
- return false;
136
- if (COMMON_WORDS.has(p))
137
- return false;
138
- // Skip absolute paths — agent responses use relative paths; absolute
139
- // paths are either system paths or URLs, and existsSync can hang on
140
- // Windows for root-relative paths like "/page.html".
141
- if (p.startsWith("/") || p.startsWith("~") || /^[A-Za-z]:/.test(p))
142
- return false;
143
- if (this.pathExistsOnDisk(p))
144
- return false;
145
- const ext = p.split(".").pop()?.toLowerCase() || "";
146
- if (!FILE_EXTENSIONS.has(ext))
147
- return false;
148
- const basename = p
149
- .split("/")
150
- .pop()
151
- ?.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
152
- if (basename) {
153
- const urlPattern = new RegExp(`(https?|file)://[^\\s]*${basename}`);
154
- if (urlPattern.test(response))
155
- return false;
156
- }
157
- return true;
158
- });
159
- if (unknownPaths.length > 0) {
160
- const uniquePaths = [...new Set(unknownPaths)];
161
- return {
162
- status: "warn",
163
- reason: t("hall.unknown_paths", {
164
- paths: uniquePaths.slice(0, 3).join(", "),
165
- }),
166
- };
167
- }
168
- return { status: "pass" };
169
- }
170
- }
@@ -1,4 +0,0 @@
1
- export { HallucinationDetector } from './detector';
2
- export { FactualCheck } from './factual';
3
- export { ConsistencyCheck } from './consistency';
4
- export { ConfidenceCheck } from './confidence';
@@ -1,5 +0,0 @@
1
- export { ModuleRegistry } from './registry';
2
- export { SkillsLoader, SkillsMatcher, SkillsModule } from './skills';
3
- export { PluginManager } from './plugins';
4
- export { PluginLoader } from './plugins/loader';
5
- export { MCPClient, MCPRegistry } from './mcp';
@@ -1,38 +0,0 @@
1
- import { readFileSync, writeFileSync, existsSync, mkdirSync, rmSync } from 'fs';
2
- import { join } from 'path';
3
- export class IndexCache {
4
- cachePath;
5
- cache = null;
6
- constructor(cacheDir) {
7
- this.cachePath = join(cacheDir, 'index-cache.json');
8
- }
9
- load() {
10
- if (this.cache)
11
- return this.cache;
12
- if (!existsSync(this.cachePath))
13
- return null;
14
- try {
15
- this.cache = JSON.parse(readFileSync(this.cachePath, 'utf-8'));
16
- return this.cache;
17
- }
18
- catch {
19
- return null;
20
- }
21
- }
22
- save(result) {
23
- this.cache = result;
24
- const dir = join(this.cachePath, '..');
25
- if (!existsSync(dir))
26
- mkdirSync(dir, { recursive: true });
27
- writeFileSync(this.cachePath, JSON.stringify(result), 'utf-8');
28
- }
29
- invalidate() {
30
- this.cache = null;
31
- if (existsSync(this.cachePath)) {
32
- try {
33
- rmSync(this.cachePath);
34
- }
35
- catch { /* ignore */ }
36
- }
37
- }
38
- }
@@ -1,3 +0,0 @@
1
- export { Indexer } from './walker';
2
- export { IndexCache } from './cache';
3
- export { IndexerModule } from './module';
@@ -1,192 +0,0 @@
1
- import { dirname } from 'path';
2
- import { Indexer } from './walker';
3
- import { IndexCache } from './cache';
4
- import { t } from '../../i18n/index';
5
- export class IndexerModule {
6
- name = 'indexer';
7
- indexer;
8
- cache;
9
- baseDir;
10
- index = null;
11
- rebuildTimeout = null;
12
- constructor(opts) {
13
- this.baseDir = opts.baseDir;
14
- this.indexer = new Indexer(opts.baseDir);
15
- this.cache = new IndexCache(opts.cacheDir);
16
- }
17
- async buildIndex() {
18
- if (this.index)
19
- return this.index;
20
- const cached = this.cache.load();
21
- if (cached) {
22
- this.index = cached;
23
- return cached;
24
- }
25
- try {
26
- const result = await this.indexer.walk();
27
- this.cache.save(result);
28
- this.index = result;
29
- return result;
30
- }
31
- catch {
32
- return null;
33
- }
34
- }
35
- async refresh() {
36
- this.cache.invalidate();
37
- this.index = null;
38
- return this.buildIndex();
39
- }
40
- find(query) {
41
- if (!this.index)
42
- return [];
43
- const q = query.toLowerCase();
44
- return this.index.files.filter((f) => {
45
- const path = f.path.toLowerCase();
46
- return path.includes(q) || f.exports.some((e) => e.toLowerCase().includes(q));
47
- });
48
- }
49
- watch() {
50
- this.unwatch();
51
- try {
52
- this.indexer.watch((_event, filename) => {
53
- if (!filename)
54
- return;
55
- if (this.rebuildTimeout)
56
- clearTimeout(this.rebuildTimeout);
57
- this.rebuildTimeout = setTimeout(() => {
58
- this.refresh().catch(() => { });
59
- }, 2000);
60
- });
61
- }
62
- catch {
63
- // Watching is best-effort; manual refresh still works.
64
- }
65
- }
66
- unwatch() {
67
- if (this.rebuildTimeout) {
68
- clearTimeout(this.rebuildTimeout);
69
- this.rebuildTimeout = null;
70
- }
71
- this.indexer.unwatch();
72
- }
73
- getSystemPromptBlock() {
74
- if (!this.index)
75
- return null;
76
- const content = this.formatMap(this.index);
77
- return {
78
- content,
79
- priority: 'normal',
80
- essential: false,
81
- estimatedTokens: this.estimateTokens(content),
82
- };
83
- }
84
- getToolDefinitions() {
85
- return [this.createProjectMapTool()];
86
- }
87
- getPlugin() {
88
- return {
89
- name: 'indexer',
90
- onSessionStart: () => {
91
- this.buildIndex().catch(() => { });
92
- this.watch();
93
- },
94
- onSessionEnd: () => {
95
- this.unwatch();
96
- },
97
- };
98
- }
99
- formatMap(result) {
100
- const summary = this.indexer.summarize(result);
101
- const dirCounts = this.getDirectoryCounts(result);
102
- const topDirs = Object.entries(dirCounts)
103
- .sort((a, b) => b[1] - a[1])
104
- .slice(0, 10)
105
- .map(([dir, count]) => `${dir} (${count})`)
106
- .join(', ') || '-';
107
- const fileLines = result.files.slice(0, 100).map((f) => {
108
- const path = f.path.replace(/\\/g, '/');
109
- const exports = f.exports.length > 0 ? `: ${f.exports.join(', ')}` : '';
110
- return `- ${path}${exports}`;
111
- });
112
- const more = result.files.length > 100
113
- ? `\n${t('indexer.and_more', { count: result.files.length - 100 })}`
114
- : '';
115
- return [
116
- `${t('indexer.map_header')} (${this.baseDir})`,
117
- summary,
118
- `${t('indexer.top_directories')}: ${topDirs}`,
119
- `${t('indexer.files')}:` + (fileLines.length > 0 ? '' : ' ' + t('indexer.empty')),
120
- ...fileLines,
121
- more,
122
- ].join('\n');
123
- }
124
- getDirectoryCounts(result) {
125
- const counts = {};
126
- for (const f of result.files) {
127
- const normalized = f.path.replace(/\\/g, '/');
128
- const dir = dirname(normalized);
129
- const key = dir === '.' ? '(root)' : dir;
130
- counts[key] = (counts[key] || 0) + 1;
131
- }
132
- return counts;
133
- }
134
- estimateTokens(content) {
135
- return Math.ceil(content.length / 4);
136
- }
137
- createProjectMapTool() {
138
- return {
139
- name: 'project_map',
140
- description: t('indexer.project_map_desc'),
141
- parameters: {
142
- type: 'object',
143
- properties: {
144
- action: {
145
- type: 'string',
146
- enum: ['summary', 'refresh', 'find'],
147
- description: t('indexer.project_map_action_desc'),
148
- },
149
- query: {
150
- type: 'string',
151
- description: t('indexer.project_map_query_desc'),
152
- },
153
- },
154
- required: ['action'],
155
- },
156
- handler: async (_ctx, args) => {
157
- const action = String(args.action || 'summary');
158
- if (action === 'refresh') {
159
- const result = await this.refresh();
160
- const summary = result ? this.indexer.summarize(result) : t('indexer.empty');
161
- return this.makeResult(t('indexer.refreshed', { summary }));
162
- }
163
- if (action === 'find') {
164
- const query = String(args.query || '').toLowerCase();
165
- if (!query)
166
- return { success: false, output: t('tool.invalid_params') };
167
- const matches = this.find(query);
168
- if (matches.length === 0) {
169
- return this.makeResult(t('indexer.no_matches', { query }));
170
- }
171
- const lines = matches.map((f) => {
172
- const path = f.path.replace(/\\/g, '/');
173
- const exports = f.exports.length > 0 ? `: ${f.exports.join(', ')}` : '';
174
- return `- ${path}${exports}`;
175
- }).join('\n');
176
- return this.makeResult(t('indexer.find_results', { count: matches.length, results: lines }));
177
- }
178
- if (!this.index) {
179
- await this.buildIndex();
180
- }
181
- if (!this.index) {
182
- return this.makeResult(t('indexer.not_indexed'));
183
- }
184
- const summary = this.indexer.summarize(this.index);
185
- return this.makeResult(t('indexer.summary', { summary }));
186
- },
187
- };
188
- }
189
- makeResult(output) {
190
- return { success: true, output, display: output };
191
- }
192
- }
@@ -1,101 +0,0 @@
1
- import { readdirSync, readFileSync, statSync, existsSync, watch } from 'fs';
2
- import { join, relative, extname } from 'path';
3
- const LANGUAGES = {
4
- '.ts': 'typescript',
5
- '.tsx': 'typescript-react',
6
- '.js': 'javascript',
7
- '.jsx': 'javascript-react',
8
- '.json': 'json',
9
- '.md': 'markdown',
10
- '.yaml': 'yaml',
11
- '.yml': 'yaml',
12
- '.py': 'python',
13
- '.rs': 'rust',
14
- '.go': 'go',
15
- };
16
- const IGNORE_DIRS = new Set(['node_modules', '.git', 'dist', 'build', '.mma', 'coverage']);
17
- export class Indexer {
18
- baseDir;
19
- MAX_FILES = 1000;
20
- watcher = null;
21
- constructor(baseDir) {
22
- this.baseDir = baseDir;
23
- }
24
- watch(callback) {
25
- this.watcher = watch(this.baseDir, { recursive: true }, (event, filename) => {
26
- if (filename && !Array.from(IGNORE_DIRS).some((dir) => filename.includes(dir))) {
27
- callback(event, filename);
28
- }
29
- });
30
- }
31
- unwatch() {
32
- if (this.watcher) {
33
- this.watcher.close();
34
- this.watcher = null;
35
- }
36
- }
37
- async walk() {
38
- const files = [];
39
- let totalSize = 0;
40
- let count = 0;
41
- const walkDir = (dir) => {
42
- if (!existsSync(dir))
43
- return;
44
- let entries;
45
- try {
46
- entries = readdirSync(dir);
47
- }
48
- catch {
49
- return;
50
- }
51
- for (const entry of entries) {
52
- if (count >= this.MAX_FILES)
53
- return;
54
- const fullPath = join(dir, entry);
55
- const relPath = relative(this.baseDir, fullPath);
56
- const stat = statSync(fullPath);
57
- if (stat.isDirectory()) {
58
- if (!IGNORE_DIRS.has(entry)) {
59
- walkDir(fullPath);
60
- }
61
- }
62
- else if (stat.isFile()) {
63
- const ext = extname(entry).toLowerCase();
64
- const language = LANGUAGES[ext];
65
- if (language) {
66
- const content = readFileSync(fullPath, 'utf-8');
67
- const exports = this.extractExports(content, language);
68
- files.push({ path: relPath, language, exports, size: stat.size });
69
- totalSize += stat.size;
70
- count++;
71
- }
72
- }
73
- }
74
- };
75
- walkDir(this.baseDir);
76
- return { files, totalSize };
77
- }
78
- extractExports(content, language) {
79
- if (language === 'typescript' || language === 'javascript') {
80
- const exports = [];
81
- const exportRegex = /export\s+(?:const|function|class|interface|type|enum|default\s+(?:class|function))\s+(\w+)/g;
82
- let match;
83
- while ((match = exportRegex.exec(content)) !== null) {
84
- exports.push(match[1]);
85
- }
86
- return exports;
87
- }
88
- return [];
89
- }
90
- summarize(result) {
91
- const byLang = {};
92
- for (const f of result.files) {
93
- byLang[f.language] = (byLang[f.language] || 0) + 1;
94
- }
95
- const langs = Object.entries(byLang)
96
- .sort((a, b) => b[1] - a[1])
97
- .map(([lang, count]) => `${lang}:${count}`)
98
- .join(', ');
99
- return `[Index: ${result.files.length} files, ${(result.totalSize / 1024).toFixed(1)}KB (${langs})]`;
100
- }
101
- }