micro-models-agent 0.44.0 → 0.45.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.
Files changed (188) hide show
  1. package/README.md +312 -312
  2. package/bin/mma.mjs +41 -41
  3. package/dist/main.js +241 -56
  4. package/dist/skills/builtin/git.md +36 -36
  5. package/dist/skills/builtin/typescript.md +35 -35
  6. package/package.json +1 -1
  7. package/dist/cli/commands.js +0 -333
  8. package/dist/cli/completer.js +0 -168
  9. package/dist/cli/index.js +0 -2
  10. package/dist/cli/main.js +0 -140
  11. package/dist/cli/repl-commands.js +0 -633
  12. package/dist/cli/repl.js +0 -486
  13. package/dist/cli/security-commands.js +0 -166
  14. package/dist/cli/setup.js +0 -249
  15. package/dist/config/config.js +0 -202
  16. package/dist/config/defaults.js +0 -100
  17. package/dist/config/experts.js +0 -15
  18. package/dist/config/index.js +0 -3
  19. package/dist/config/security.js +0 -200
  20. package/dist/config/types.js +0 -1
  21. package/dist/core/agent-moe.js +0 -110
  22. package/dist/core/agent.js +0 -695
  23. package/dist/core/bootstrap.js +0 -337
  24. package/dist/core/index.js +0 -2
  25. package/dist/core/prompt-builder.js +0 -55
  26. package/dist/core/session-logger.js +0 -155
  27. package/dist/core/types.js +0 -1
  28. package/dist/core/workspace.js +0 -76
  29. package/dist/i18n/en.json +0 -525
  30. package/dist/i18n/index.js +0 -46
  31. package/dist/i18n/ru.json +0 -525
  32. package/dist/index.js +0 -22
  33. package/dist/llm/image-utils.js +0 -144
  34. package/dist/llm/index.js +0 -4
  35. package/dist/llm/model-loader.js +0 -78
  36. package/dist/llm/openai-compat.js +0 -353
  37. package/dist/llm/orchestrator.js +0 -194
  38. package/dist/llm/provider.js +0 -10
  39. package/dist/llm/response.js +0 -39
  40. package/dist/llm/token-counter.js +0 -39
  41. package/dist/llm/types.js +0 -1
  42. package/dist/logger/app-logger.js +0 -143
  43. package/dist/logger/file-log.js +0 -151
  44. package/dist/logger/index.js +0 -1
  45. package/dist/migration/backup.js +0 -45
  46. package/dist/migration/detect.js +0 -50
  47. package/dist/migration/index.js +0 -2
  48. package/dist/modules/browser/actions.js +0 -46
  49. package/dist/modules/browser/cookie-store.js +0 -24
  50. package/dist/modules/browser/index.js +0 -5
  51. package/dist/modules/browser/module.js +0 -28
  52. package/dist/modules/browser/session.js +0 -335
  53. package/dist/modules/browser/snapshot.js +0 -114
  54. package/dist/modules/browser/types.js +0 -9
  55. package/dist/modules/certification/cli.js +0 -176
  56. package/dist/modules/certification/fact-checker.js +0 -84
  57. package/dist/modules/certification/loader.js +0 -111
  58. package/dist/modules/certification/manifest.js +0 -50
  59. package/dist/modules/certification/runner.js +0 -162
  60. package/dist/modules/certification/scenarios.js +0 -124
  61. package/dist/modules/certification/types.js +0 -1
  62. package/dist/modules/context/index.js +0 -1
  63. package/dist/modules/context/manager.js +0 -349
  64. package/dist/modules/execution/auditor.js +0 -66
  65. package/dist/modules/execution/index.js +0 -8
  66. package/dist/modules/execution/module.js +0 -779
  67. package/dist/modules/execution/moe-executor.js +0 -266
  68. package/dist/modules/execution/plan-coverage.js +0 -68
  69. package/dist/modules/execution/plan-persister.js +0 -46
  70. package/dist/modules/execution/plan-store.js +0 -159
  71. package/dist/modules/execution/plan-validator.js +0 -153
  72. package/dist/modules/execution/planner.js +0 -85
  73. package/dist/modules/execution/stuck-detector.js +0 -347
  74. package/dist/modules/execution/tracker.js +0 -67
  75. package/dist/modules/execution/types.js +0 -1
  76. package/dist/modules/execution/verifier.js +0 -178
  77. package/dist/modules/hallucination/confidence.js +0 -59
  78. package/dist/modules/hallucination/consistency.js +0 -26
  79. package/dist/modules/hallucination/detector.js +0 -46
  80. package/dist/modules/hallucination/factual.js +0 -190
  81. package/dist/modules/hallucination/index.js +0 -5
  82. package/dist/modules/hallucination/js-identifiers.js +0 -72
  83. package/dist/modules/hallucination/llm-judge.js +0 -103
  84. package/dist/modules/index.js +0 -5
  85. package/dist/modules/indexer/cache.js +0 -38
  86. package/dist/modules/indexer/index.js +0 -3
  87. package/dist/modules/indexer/module.js +0 -192
  88. package/dist/modules/indexer/walker.js +0 -101
  89. package/dist/modules/lsp/client.js +0 -235
  90. package/dist/modules/lsp/config.js +0 -81
  91. package/dist/modules/lsp/index.js +0 -3
  92. package/dist/modules/lsp/module.js +0 -68
  93. package/dist/modules/lsp/types.js +0 -1
  94. package/dist/modules/mcp/client.js +0 -399
  95. package/dist/modules/mcp/index.js +0 -3
  96. package/dist/modules/mcp/module.js +0 -146
  97. package/dist/modules/mcp/registry.js +0 -15
  98. package/dist/modules/memory/index.js +0 -1
  99. package/dist/modules/memory/module.js +0 -48
  100. package/dist/modules/memory/search.js +0 -40
  101. package/dist/modules/memory/store.js +0 -69
  102. package/dist/modules/pipelines/engine.js +0 -60
  103. package/dist/modules/pipelines/index.js +0 -3
  104. package/dist/modules/pipelines/parser.js +0 -53
  105. package/dist/modules/pipelines/template.js +0 -14
  106. package/dist/modules/plugins/builtin/lint-on-write.js +0 -226
  107. package/dist/modules/plugins/builtin/notify.js +0 -8
  108. package/dist/modules/plugins/index.js +0 -1
  109. package/dist/modules/plugins/loader.js +0 -28
  110. package/dist/modules/plugins/manager.js +0 -161
  111. package/dist/modules/plugins/types.js +0 -1
  112. package/dist/modules/processes/index.js +0 -2
  113. package/dist/modules/processes/registry.js +0 -238
  114. package/dist/modules/processes/runner.js +0 -23
  115. package/dist/modules/registry.js +0 -45
  116. package/dist/modules/security/audit-log.js +0 -136
  117. package/dist/modules/security/audit-notifier.js +0 -292
  118. package/dist/modules/security/command-validator.js +0 -211
  119. package/dist/modules/security/content-scanner.js +0 -53
  120. package/dist/modules/security/data-sanitizer.js +0 -97
  121. package/dist/modules/security/encryption.js +0 -240
  122. package/dist/modules/security/index.js +0 -14
  123. package/dist/modules/security/network-validator.js +0 -79
  124. package/dist/modules/security/path-validator.js +0 -209
  125. package/dist/modules/security/rate-limiter.js +0 -119
  126. package/dist/modules/security/security-policies.js +0 -547
  127. package/dist/modules/security/session-encryption.js +0 -210
  128. package/dist/modules/security/session-isolation.js +0 -95
  129. package/dist/modules/session/index.js +0 -3
  130. package/dist/modules/session/manager.js +0 -172
  131. package/dist/modules/session/module.js +0 -24
  132. package/dist/modules/session/store.js +0 -228
  133. package/dist/modules/session/types.js +0 -1
  134. package/dist/modules/skills/index.js +0 -2
  135. package/dist/modules/skills/loader.js +0 -72
  136. package/dist/modules/skills/module.js +0 -130
  137. package/dist/modules/types.js +0 -1
  138. package/dist/modules/updater/checker.js +0 -32
  139. package/dist/modules/updater/index.js +0 -1
  140. package/dist/modules/user-profile/compressor.js +0 -16
  141. package/dist/modules/user-profile/index.js +0 -1
  142. package/dist/modules/user-profile/profile.js +0 -68
  143. package/dist/tools/approve.js +0 -32
  144. package/dist/tools/attach-image.js +0 -89
  145. package/dist/tools/bash.js +0 -337
  146. package/dist/tools/browser.js +0 -97
  147. package/dist/tools/create-dir.js +0 -55
  148. package/dist/tools/delete-file.js +0 -62
  149. package/dist/tools/edit-file.js +0 -79
  150. package/dist/tools/executor.js +0 -145
  151. package/dist/tools/file-info.js +0 -45
  152. package/dist/tools/filter-tools.js +0 -10
  153. package/dist/tools/glob-tool.js +0 -26
  154. package/dist/tools/grep-tool.js +0 -86
  155. package/dist/tools/index.js +0 -67
  156. package/dist/tools/list-dir.js +0 -47
  157. package/dist/tools/load-skill.js +0 -44
  158. package/dist/tools/mcp-call.js +0 -68
  159. package/dist/tools/move-file.js +0 -85
  160. package/dist/tools/path-utils.js +0 -51
  161. package/dist/tools/pipeline-run.js +0 -144
  162. package/dist/tools/preview.js +0 -2
  163. package/dist/tools/process-kill.js +0 -29
  164. package/dist/tools/process-list.js +0 -38
  165. package/dist/tools/process-log.js +0 -41
  166. package/dist/tools/question.js +0 -142
  167. package/dist/tools/read-file.js +0 -83
  168. package/dist/tools/recall.js +0 -110
  169. package/dist/tools/registry.js +0 -36
  170. package/dist/tools/remember.js +0 -67
  171. package/dist/tools/scope-check.js +0 -30
  172. package/dist/tools/search-history.js +0 -84
  173. package/dist/tools/subagent.js +0 -151
  174. package/dist/tools/types.js +0 -1
  175. package/dist/tools/user-input.js +0 -123
  176. package/dist/tools/web-browse.js +0 -86
  177. package/dist/tools/web-fetch.js +0 -98
  178. package/dist/tools/web-search.js +0 -78
  179. package/dist/tools/write-file.js +0 -83
  180. package/dist/ui/box.js +0 -81
  181. package/dist/ui/colors.js +0 -4
  182. package/dist/ui/diff.js +0 -178
  183. package/dist/ui/index.js +0 -6
  184. package/dist/ui/md-formatter.js +0 -212
  185. package/dist/ui/output.js +0 -13
  186. package/dist/ui/renderer.js +0 -204
  187. package/dist/ui/spinner.js +0 -70
  188. package/dist/ui/table.js +0 -144
@@ -1,69 +0,0 @@
1
- import { readFileSync, writeFileSync, appendFileSync, existsSync, mkdirSync } from 'fs';
2
- import { join } from 'path';
3
- import { MemorySearch } from './search';
4
- const MEMORY_FILES = ['conventions', 'decisions', 'errors', 'facts'];
5
- export class MemoryStore {
6
- memoryDir;
7
- constructor(memoryDir) {
8
- this.memoryDir = memoryDir;
9
- this.ensureDir();
10
- for (const name of MEMORY_FILES) {
11
- const path = join(this.memoryDir, `${name}.md`);
12
- if (!existsSync(path)) {
13
- writeFileSync(path, `# ${name.charAt(0).toUpperCase() + name.slice(1)}\n\n`, 'utf-8');
14
- }
15
- }
16
- }
17
- ensureDir() {
18
- if (!existsSync(this.memoryDir)) {
19
- mkdirSync(this.memoryDir, { recursive: true });
20
- }
21
- }
22
- read(name) {
23
- const path = join(this.memoryDir, `${name}.md`);
24
- if (!existsSync(path))
25
- return '';
26
- return readFileSync(path, 'utf-8');
27
- }
28
- append(name, entry) {
29
- const path = join(this.memoryDir, `${name}.md`);
30
- const timestamp = new Date().toISOString().replace('T', ' ').slice(0, 19);
31
- const formatted = `- **${timestamp}** — ${entry}\n`;
32
- appendFileSync(path, formatted, 'utf-8');
33
- }
34
- search(query) {
35
- const searchModule = new MemorySearch(this.memoryDir);
36
- return searchModule.query(query);
37
- }
38
- prefsPath() {
39
- return join(this.memoryDir, 'preferences.json');
40
- }
41
- getPreferences() {
42
- const path = this.prefsPath();
43
- if (!existsSync(path))
44
- return {};
45
- try {
46
- return JSON.parse(readFileSync(path, 'utf-8'));
47
- }
48
- catch {
49
- return {};
50
- }
51
- }
52
- setPreference(key, value) {
53
- const prefs = this.getPreferences();
54
- prefs[key] = value;
55
- writeFileSync(this.prefsPath(), JSON.stringify(prefs, null, 2), 'utf-8');
56
- }
57
- deletePreference(key) {
58
- const prefs = this.getPreferences();
59
- if (!(key in prefs))
60
- return false;
61
- delete prefs[key];
62
- writeFileSync(this.prefsPath(), JSON.stringify(prefs, null, 2), 'utf-8');
63
- return true;
64
- }
65
- appendRule(category, pattern, cause, solution) {
66
- const entry = `**pattern:** ${pattern}\n **cause:** ${cause}\n **solution:** ${solution}`;
67
- this.append(category, entry);
68
- }
69
- }
@@ -1,60 +0,0 @@
1
- import { t } from '../../i18n/index';
2
- export class PipelineEngine {
3
- stepStatus = new Map();
4
- resolveDependencies(steps) {
5
- const visited = new Set();
6
- const inStack = new Set();
7
- const order = [];
8
- function visit(stepId, stepMap) {
9
- if (inStack.has(stepId))
10
- throw new Error(t('pipeline.circular', { stepId }));
11
- if (visited.has(stepId))
12
- return;
13
- inStack.add(stepId);
14
- const step = stepMap.get(stepId);
15
- if (step?.depends_on) {
16
- for (const dep of step.depends_on) {
17
- visit(dep, stepMap);
18
- }
19
- }
20
- inStack.delete(stepId);
21
- visited.add(stepId);
22
- order.push(stepId);
23
- }
24
- const stepMap = new Map(steps.map(s => [s.id, s]));
25
- for (const step of steps) {
26
- if (!visited.has(step.id)) {
27
- visit(step.id, stepMap);
28
- }
29
- }
30
- return order;
31
- }
32
- getReadySteps(steps, completed) {
33
- return steps.filter(s => {
34
- if (completed.has(s.id))
35
- return false;
36
- if (this.stepStatus.get(s.id) === 'running')
37
- return false;
38
- if (this.stepStatus.get(s.id) === 'failed')
39
- return false;
40
- if (!s.depends_on || s.depends_on.length === 0)
41
- return true;
42
- return s.depends_on.every(d => completed.has(d));
43
- });
44
- }
45
- setStepStatus(stepId, status) {
46
- this.stepStatus.set(stepId, status);
47
- }
48
- getStepStatus(stepId) {
49
- return this.stepStatus.get(stepId) || 'pending';
50
- }
51
- isComplete(stepIds) {
52
- return stepIds.every(id => {
53
- const s = this.stepStatus.get(id);
54
- return s === 'done' || s === 'skipped';
55
- });
56
- }
57
- reset() {
58
- this.stepStatus.clear();
59
- }
60
- }
@@ -1,3 +0,0 @@
1
- export { PipelineParser } from './parser';
2
- export { PipelineEngine } from './engine';
3
- export { TemplateEngine } from './template';
@@ -1,53 +0,0 @@
1
- import { t } from '../../i18n/index';
2
- export class PipelineParser {
3
- static parse(yaml) {
4
- const lines = yaml.split('\n').filter(l => l.trim());
5
- const result = {};
6
- let currentSection = null;
7
- let currentSteps = [];
8
- for (const line of lines) {
9
- if (line.match(/^\w+:/) && !line.startsWith(' ') && !line.startsWith(' -')) {
10
- const [key, ...valParts] = line.split(':');
11
- const val = valParts.join(':').trim();
12
- if (key === 'steps') {
13
- currentSection = 'steps';
14
- }
15
- else {
16
- result[key] = val;
17
- currentSection = null;
18
- }
19
- }
20
- else if (currentSection === 'steps') {
21
- const stepMatch = line.match(/^\s+- id:\s*(\S+)/);
22
- if (stepMatch) {
23
- currentSteps.push({ id: stepMatch[1] });
24
- }
25
- else if (currentSteps.length > 0) {
26
- const lastStep = currentSteps[currentSteps.length - 1];
27
- const kvMatch = line.match(/^\s+(\w+):\s*(.+)$/);
28
- if (kvMatch) {
29
- const key = kvMatch[1];
30
- let val = kvMatch[2].trim();
31
- if (val === 'true')
32
- val = true;
33
- else if (val === 'false')
34
- val = false;
35
- else if (val.startsWith('[') && val.endsWith(']')) {
36
- val = val.slice(1, -1).split(',').map((s) => s.trim().replace(/^['"]|['"]$/g, ''));
37
- }
38
- lastStep[key] = val;
39
- }
40
- }
41
- }
42
- }
43
- if (!result.name || currentSteps.length === 0) {
44
- throw new Error(t('pipeline.invalid'));
45
- }
46
- for (const step of currentSteps) {
47
- if (!step.id || !step.agent || !step.prompt) {
48
- throw new Error(t('pipeline.step_missing_fields', { step: JSON.stringify(step) }));
49
- }
50
- }
51
- return { name: result.name, steps: currentSteps };
52
- }
53
- }
@@ -1,14 +0,0 @@
1
- export class TemplateEngine {
2
- static render(template, params, stepOutputs) {
3
- let result = template;
4
- for (const [key, val] of Object.entries(params)) {
5
- result = result.replace(new RegExp(`\\{${key}\\}`, 'g'), val);
6
- }
7
- if (stepOutputs) {
8
- result = result.replace(/\{\{steps\.(\w+)\.output\}\}/g, (_, stepId) => {
9
- return stepOutputs[stepId]?.output || `{{steps.${stepId}.output}}`;
10
- });
11
- }
12
- return result;
13
- }
14
- }
@@ -1,226 +0,0 @@
1
- import { spawn, execSync } from "child_process";
2
- import { existsSync, readFileSync } from "fs";
3
- import { resolve, extname, join } from "path";
4
- import { platform } from "os";
5
- const TYPE_CHECK_DEBOUNCE_MS = 2000;
6
- // Per-file syntax checks are cached by (path, content hash): re-writing a file
7
- // with identical content skips the (expensive) check. Content changes → cache
8
- // miss → fresh check.
9
- const syntaxCache = new Map();
10
- function contentHash(content) {
11
- let h = 5381;
12
- for (let i = 0; i < content.length; i++) {
13
- h = ((h << 5) + h + content.charCodeAt(i)) | 0;
14
- }
15
- return String(h);
16
- }
17
- let _winDecoder;
18
- function getWinDecoder() {
19
- if (_winDecoder === undefined) {
20
- if (platform() !== "win32") {
21
- _winDecoder = null;
22
- }
23
- else {
24
- try {
25
- const cpOut = execSync("chcp.com", {
26
- encoding: "buffer",
27
- timeout: 2000,
28
- windowsHide: true,
29
- }).toString("latin1");
30
- const m = cpOut.match(/(\d+)/);
31
- _winDecoder = m ? new TextDecoder("ibm" + m[1]) : null;
32
- }
33
- catch {
34
- _winDecoder = null;
35
- }
36
- }
37
- }
38
- return _winDecoder ?? new TextDecoder("utf-8");
39
- }
40
- export class LintOnWritePlugin {
41
- name = "lint-on-write";
42
- priority = 10;
43
- _checkPromise = null;
44
- _checkTimestamp = 0;
45
- async onAfterTool(ctx, call, result) {
46
- if (call.name !== "write_file" && call.name !== "edit_file") {
47
- return;
48
- }
49
- if (!result.success) {
50
- return;
51
- }
52
- const path = String(call.arguments.path || "");
53
- if (!path)
54
- return;
55
- const fullPath = resolve(ctx.baseDir, path);
56
- if (!existsSync(fullPath))
57
- return;
58
- const ext = extname(fullPath);
59
- const syntaxError = await this.checkSyntax(fullPath, ext, ctx.baseDir);
60
- if (syntaxError) {
61
- result.output += `\n\n[Syntax check failed]: ${syntaxError}`;
62
- return;
63
- }
64
- await this.runProjectLint(ctx, result);
65
- await this.runProjectTypeCheck(ctx, result);
66
- }
67
- async checkSyntax(filePath, ext, baseDir) {
68
- if (ext === ".ts" || ext === ".tsx") {
69
- // Syntax-only check via bun's parser (~200ms) instead of `npx tsc`
70
- // (~3-5s per write). Full type errors are still surfaced by the
71
- // debounced project typecheck below when a tsconfig exists.
72
- let content = "";
73
- try {
74
- content = readFileSync(filePath, "utf-8");
75
- }
76
- catch {
77
- return null;
78
- }
79
- const hash = contentHash(content);
80
- const cached = syntaxCache.get(filePath);
81
- if (cached && cached.hash === hash) {
82
- return cached.error;
83
- }
84
- try {
85
- await runAsync(`bun build --no-bundle --target=bun "${filePath}"`, baseDir, 10000);
86
- syntaxCache.set(filePath, { hash, error: null });
87
- return null;
88
- }
89
- catch (err) {
90
- if (err.status === 127 ||
91
- err.message.includes("not found") ||
92
- err.message.includes("ENOENT")) {
93
- return null;
94
- }
95
- const stderr = err.stderr?.toString() || err.stdout?.toString() || "";
96
- const firstError = stderr.split("\n").find((line) => line.trim()) ||
97
- "TypeScript syntax error";
98
- syntaxCache.set(filePath, { hash, error: firstError.trim() });
99
- return firstError.trim();
100
- }
101
- }
102
- if (ext === ".js" || ext === ".jsx") {
103
- try {
104
- await runAsync(`node --check "${filePath}"`, baseDir, 5000);
105
- return null;
106
- }
107
- catch (err) {
108
- const stderr = err.stderr?.toString() || "";
109
- const firstError = stderr.split("\n").find((line) => line.trim()) ||
110
- "JavaScript syntax error";
111
- return firstError.trim();
112
- }
113
- }
114
- return null;
115
- }
116
- async runProjectLint(ctx, result) {
117
- try {
118
- const packageJsonPath = join(ctx.baseDir, "package.json");
119
- if (!existsSync(packageJsonPath)) {
120
- return;
121
- }
122
- const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
123
- const lintScript = packageJson.scripts?.lint;
124
- if (!lintScript) {
125
- return;
126
- }
127
- ctx.logger.debug(`Running lint: ${lintScript}`);
128
- await runAsync(lintScript, ctx.baseDir, 30_000);
129
- ctx.logger.debug("Lint passed");
130
- }
131
- catch (err) {
132
- ctx.logger.warn(`Lint failed: ${err.message}`);
133
- result.output += `\n\n[Project lint failed]: ${err.message}`;
134
- }
135
- }
136
- async runProjectTypeCheck(ctx, result) {
137
- const tsconfigPath = join(ctx.baseDir, "tsconfig.json");
138
- if (!existsSync(tsconfigPath)) {
139
- return;
140
- }
141
- const now = Date.now();
142
- if (this._checkPromise &&
143
- now - this._checkTimestamp < TYPE_CHECK_DEBOUNCE_MS) {
144
- const error = await this._checkPromise;
145
- if (error) {
146
- result.output += `\n\n[Project typecheck failed]: ${error}`;
147
- }
148
- return;
149
- }
150
- this._checkTimestamp = now;
151
- this._checkPromise = this.runTscCheck(ctx.baseDir);
152
- const error = await this._checkPromise;
153
- if (error) {
154
- result.output += `\n\n[Project typecheck failed]: ${error}`;
155
- }
156
- }
157
- async runTscCheck(baseDir) {
158
- try {
159
- await runAsync(`npx tsc --noEmit --skipLibCheck`, baseDir, 30000);
160
- return null;
161
- }
162
- catch (err) {
163
- if (err.status === 127 ||
164
- err.message.includes("not found") ||
165
- err.message.includes("ENOENT")) {
166
- return null;
167
- }
168
- const stderr = err.stderr?.toString() || err.stdout?.toString() || "";
169
- if (stderr.includes("error TS")) {
170
- const firstError = stderr
171
- .split("\n")
172
- .find((line) => line.includes("error TS")) ||
173
- "TypeScript type error";
174
- return firstError.trim();
175
- }
176
- return null;
177
- }
178
- }
179
- }
180
- /**
181
- * Run a command asynchronously (non-blocking event loop) and resolve when it
182
- * exits. Rejects with captured stderr/stdout on non-zero exit or timeout.
183
- */
184
- function runAsync(command, cwd, timeoutMs) {
185
- return new Promise((resolve, reject) => {
186
- const child = spawn(command, {
187
- cwd,
188
- shell: true,
189
- windowsHide: true,
190
- stdio: ["ignore", "pipe", "pipe"],
191
- });
192
- let stdout = "";
193
- let stderr = "";
194
- const decoder = getWinDecoder();
195
- child.stdout?.on("data", (d) => {
196
- stdout += decoder.decode(d, { stream: true });
197
- });
198
- child.stderr?.on("data", (d) => {
199
- stderr += decoder.decode(d, { stream: true });
200
- });
201
- const timer = setTimeout(() => {
202
- child.kill();
203
- reject(new Error(`Command timed out after ${timeoutMs}ms`));
204
- }, timeoutMs);
205
- child.on("error", (err) => {
206
- clearTimeout(timer);
207
- reject(err);
208
- });
209
- child.on("close", (code) => {
210
- clearTimeout(timer);
211
- stdout += decoder.decode();
212
- stderr += decoder.decode();
213
- if (code === 0) {
214
- resolve({ stdout, stderr });
215
- }
216
- else {
217
- const err = new Error(`Command failed with exit code ${code}`);
218
- err.stdout = stdout;
219
- err.stderr = stderr;
220
- err.status = code;
221
- reject(err);
222
- }
223
- });
224
- });
225
- }
226
- export const plugin = new LintOnWritePlugin();
@@ -1,8 +0,0 @@
1
- export class NotifyPlugin {
2
- name = 'notify';
3
- priority = 5;
4
- onSessionEnd(ctx) {
5
- ctx.logger.info('Session ended');
6
- }
7
- }
8
- export const plugin = new NotifyPlugin();
@@ -1 +0,0 @@
1
- export { PluginManager } from './manager';
@@ -1,28 +0,0 @@
1
- import { readdirSync, existsSync, statSync } from 'fs';
2
- import { join } from 'path';
3
- import { t } from '../../i18n/index';
4
- export class PluginLoader {
5
- loadFromDir(dirPath, pluginManager, logger) {
6
- if (!existsSync(dirPath))
7
- return;
8
- const entries = readdirSync(dirPath);
9
- for (const entry of entries) {
10
- const fullPath = join(dirPath, entry);
11
- if (!statSync(fullPath).isFile())
12
- continue;
13
- if (!entry.endsWith('.ts') && !entry.endsWith('.js'))
14
- continue;
15
- try {
16
- const mod = require(fullPath);
17
- const plugin = mod.default || mod.plugin;
18
- if (plugin && plugin.name) {
19
- pluginManager.register(plugin);
20
- logger?.warn(t('plugin.loaded', { name: plugin.name }));
21
- }
22
- }
23
- catch (e) {
24
- logger?.warn(t('plugin.skipped', { entry, message: e.message }));
25
- }
26
- }
27
- }
28
- }
@@ -1,161 +0,0 @@
1
- export class PluginManager {
2
- plugins = [];
3
- register(plugin) {
4
- this.plugins.push(plugin);
5
- this.plugins.sort((a, b) => (b.priority || 0) - (a.priority || 0));
6
- }
7
- getAllPlugins() {
8
- return [...this.plugins];
9
- }
10
- runOnBuildPrompt() {
11
- return this.plugins.map(p => {
12
- try {
13
- return p.onBuildPrompt?.() ?? null;
14
- }
15
- catch {
16
- return null;
17
- }
18
- });
19
- }
20
- async runOnBeforeTool(ctx, call) {
21
- for (const plugin of this.plugins) {
22
- if (plugin.onBeforeTool) {
23
- try {
24
- const result = await plugin.onBeforeTool(ctx, call);
25
- if (result === false)
26
- return false;
27
- }
28
- catch { /* error isolation */ }
29
- }
30
- }
31
- return true;
32
- }
33
- async runOnAfterTool(ctx, call, result) {
34
- for (const plugin of this.plugins) {
35
- if (plugin.onAfterTool) {
36
- try {
37
- await plugin.onAfterTool(ctx, call, result);
38
- }
39
- catch { /* error isolation */ }
40
- }
41
- }
42
- }
43
- async runOnError(ctx, error) {
44
- for (const plugin of this.plugins) {
45
- if (plugin.onError) {
46
- try {
47
- await plugin.onError(ctx, error);
48
- }
49
- catch { /* error isolation */ }
50
- }
51
- }
52
- }
53
- runOnSessionStart(ctx) {
54
- for (const plugin of this.plugins) {
55
- if (plugin.onSessionStart) {
56
- try {
57
- plugin.onSessionStart(ctx);
58
- }
59
- catch { /* error isolation */ }
60
- }
61
- }
62
- }
63
- runOnBeforeThink(ctx) {
64
- for (const plugin of this.plugins) {
65
- if (plugin.onBeforeThink) {
66
- try {
67
- plugin.onBeforeThink(ctx);
68
- }
69
- catch { /* error isolation */ }
70
- }
71
- }
72
- }
73
- runOnAfterThink(ctx, response) {
74
- for (const plugin of this.plugins) {
75
- if (plugin.onAfterThink) {
76
- try {
77
- plugin.onAfterThink(ctx, response);
78
- }
79
- catch { /* error isolation */ }
80
- }
81
- }
82
- }
83
- runOnSessionEnd(ctx) {
84
- for (const plugin of this.plugins) {
85
- if (plugin.onSessionEnd) {
86
- try {
87
- plugin.onSessionEnd(ctx);
88
- }
89
- catch { /* error isolation */ }
90
- }
91
- }
92
- }
93
- runOnToolCall(ctx) {
94
- for (const plugin of this.plugins) {
95
- if (plugin.onToolCall) {
96
- try {
97
- plugin.onToolCall(ctx);
98
- }
99
- catch { /* error isolation */ }
100
- }
101
- }
102
- }
103
- runOnPhase(ctx, phase) {
104
- for (const plugin of this.plugins) {
105
- if (plugin.onPhase) {
106
- try {
107
- plugin.onPhase(ctx, phase);
108
- }
109
- catch { /* error isolation */ }
110
- }
111
- }
112
- }
113
- runOnToolStart(ctx, call) {
114
- for (const plugin of this.plugins) {
115
- if (plugin.onToolStart) {
116
- try {
117
- plugin.onToolStart(ctx, call);
118
- }
119
- catch { /* error isolation */ }
120
- }
121
- }
122
- }
123
- runOnToolEnd(ctx, call, result, durationMs) {
124
- for (const plugin of this.plugins) {
125
- if (plugin.onToolEnd) {
126
- try {
127
- plugin.onToolEnd(ctx, call, result, durationMs);
128
- }
129
- catch { /* error isolation */ }
130
- }
131
- }
132
- }
133
- /** Pipe a text chunk through plugin transforms; returns the (possibly replaced) chunk. */
134
- runOnText(ctx, chunk) {
135
- for (const plugin of this.plugins) {
136
- if (plugin.onText) {
137
- try {
138
- const out = plugin.onText(ctx, chunk);
139
- if (typeof out === 'string')
140
- chunk = out;
141
- }
142
- catch { /* error isolation */ }
143
- }
144
- }
145
- return chunk;
146
- }
147
- /** Pipe a meta chunk through plugin transforms; returns the (possibly replaced) chunk. */
148
- runOnMeta(ctx, chunk) {
149
- for (const plugin of this.plugins) {
150
- if (plugin.onMeta) {
151
- try {
152
- const out = plugin.onMeta(ctx, chunk);
153
- if (typeof out === 'string')
154
- chunk = out;
155
- }
156
- catch { /* error isolation */ }
157
- }
158
- }
159
- return chunk;
160
- }
161
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,2 +0,0 @@
1
- export { registerKillable, unregisterKillable, killByCallId, } from "./runner";
2
- export { processRegistry } from "./registry";