micro-models-agent 0.50.4 → 0.51.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 (218) hide show
  1. package/README.md +358 -358
  2. package/dist/main.js +923 -590
  3. package/dist/modules/browser/bridge-server.mjs +202 -202
  4. package/dist/skills/builtin/git.md +36 -36
  5. package/dist/skills/builtin/typescript.md +35 -35
  6. package/package.json +48 -48
  7. package/dist/cli/commands.js +0 -323
  8. package/dist/cli/completer.js +0 -167
  9. package/dist/cli/index.js +0 -2
  10. package/dist/cli/main.js +0 -165
  11. package/dist/cli/plugin-commands.js +0 -36
  12. package/dist/cli/repl-commands.js +0 -661
  13. package/dist/cli/repl.js +0 -616
  14. package/dist/cli/run-result.js +0 -22
  15. package/dist/cli/security-commands.js +0 -164
  16. package/dist/cli/setup.js +0 -231
  17. package/dist/config/config.js +0 -249
  18. package/dist/config/defaults.js +0 -124
  19. package/dist/config/experts.js +0 -15
  20. package/dist/config/index.js +0 -3
  21. package/dist/config/security.js +0 -193
  22. package/dist/config/types.js +0 -1
  23. package/dist/core/agent-moe.js +0 -102
  24. package/dist/core/agent.js +0 -886
  25. package/dist/core/bootstrap.js +0 -404
  26. package/dist/core/index.js +0 -2
  27. package/dist/core/prompt-builder.js +0 -76
  28. package/dist/core/session-logger.js +0 -197
  29. package/dist/core/types.js +0 -1
  30. package/dist/core/version.js +0 -24
  31. package/dist/core/workspace.js +0 -76
  32. package/dist/i18n/en.json +0 -598
  33. package/dist/i18n/index.js +0 -46
  34. package/dist/i18n/ru.json +0 -598
  35. package/dist/index.js +0 -22
  36. package/dist/llm/image-utils.js +0 -143
  37. package/dist/llm/index.js +0 -4
  38. package/dist/llm/model-loader.js +0 -78
  39. package/dist/llm/openai-compat.js +0 -359
  40. package/dist/llm/orchestrator.js +0 -198
  41. package/dist/llm/provider.js +0 -10
  42. package/dist/llm/response.js +0 -39
  43. package/dist/llm/token-counter.js +0 -39
  44. package/dist/llm/types.js +0 -1
  45. package/dist/logger/app-logger.js +0 -143
  46. package/dist/logger/file-log.js +0 -151
  47. package/dist/logger/index.js +0 -1
  48. package/dist/migration/backup.js +0 -45
  49. package/dist/migration/detect.js +0 -50
  50. package/dist/migration/index.js +0 -2
  51. package/dist/modules/artifacts/store.js +0 -61
  52. package/dist/modules/browser/actions.js +0 -76
  53. package/dist/modules/browser/bridge-client.js +0 -199
  54. package/dist/modules/browser/bridge-path.js +0 -10
  55. package/dist/modules/browser/cookie-store.js +0 -24
  56. package/dist/modules/browser/driver.js +0 -136
  57. package/dist/modules/browser/index.js +0 -7
  58. package/dist/modules/browser/module.js +0 -29
  59. package/dist/modules/browser/session.js +0 -338
  60. package/dist/modules/browser/snapshot.js +0 -148
  61. package/dist/modules/browser/types.js +0 -12
  62. package/dist/modules/certification/cli.js +0 -174
  63. package/dist/modules/certification/fact-checker.js +0 -82
  64. package/dist/modules/certification/loader.js +0 -105
  65. package/dist/modules/certification/manifest.js +0 -50
  66. package/dist/modules/certification/runner.js +0 -159
  67. package/dist/modules/certification/scenarios.js +0 -124
  68. package/dist/modules/certification/types.js +0 -1
  69. package/dist/modules/context/chunk-query.js +0 -100
  70. package/dist/modules/context/fact-extractor.js +0 -162
  71. package/dist/modules/context/history.js +0 -15
  72. package/dist/modules/context/index.js +0 -1
  73. package/dist/modules/context/manager.js +0 -423
  74. package/dist/modules/execution/audit-runners.js +0 -152
  75. package/dist/modules/execution/auditor.js +0 -218
  76. package/dist/modules/execution/execution-plugin.js +0 -272
  77. package/dist/modules/execution/index.js +0 -8
  78. package/dist/modules/execution/module.js +0 -436
  79. package/dist/modules/execution/moe-executor.js +0 -291
  80. package/dist/modules/execution/plan-coverage.js +0 -68
  81. package/dist/modules/execution/plan-persister.js +0 -46
  82. package/dist/modules/execution/plan-store.js +0 -157
  83. package/dist/modules/execution/plan-tool.js +0 -508
  84. package/dist/modules/execution/plan-validator.js +0 -153
  85. package/dist/modules/execution/planner.js +0 -90
  86. package/dist/modules/execution/stuck-detector.js +0 -510
  87. package/dist/modules/execution/tracker.js +0 -67
  88. package/dist/modules/execution/types.js +0 -1
  89. package/dist/modules/execution/verifier.js +0 -222
  90. package/dist/modules/execution/windows-commands.js +0 -41
  91. package/dist/modules/hallucination/confidence.js +0 -66
  92. package/dist/modules/hallucination/consistency.js +0 -26
  93. package/dist/modules/hallucination/detector.js +0 -43
  94. package/dist/modules/hallucination/factual.js +0 -129
  95. package/dist/modules/hallucination/index.js +0 -5
  96. package/dist/modules/hallucination/js-identifiers.js +0 -262
  97. package/dist/modules/hallucination/llm-judge.js +0 -101
  98. package/dist/modules/index.js +0 -5
  99. package/dist/modules/indexer/cache.js +0 -40
  100. package/dist/modules/indexer/index.js +0 -3
  101. package/dist/modules/indexer/module.js +0 -245
  102. package/dist/modules/indexer/project-profile.js +0 -183
  103. package/dist/modules/indexer/walker.js +0 -101
  104. package/dist/modules/lsp/check-tool.js +0 -58
  105. package/dist/modules/lsp/client.js +0 -278
  106. package/dist/modules/lsp/command.js +0 -60
  107. package/dist/modules/lsp/config.js +0 -135
  108. package/dist/modules/lsp/index.js +0 -3
  109. package/dist/modules/lsp/module.js +0 -232
  110. package/dist/modules/lsp/probe.js +0 -76
  111. package/dist/modules/lsp/project-root.js +0 -32
  112. package/dist/modules/lsp/startup-check.js +0 -141
  113. package/dist/modules/lsp/types.js +0 -1
  114. package/dist/modules/mcp/client.js +0 -399
  115. package/dist/modules/mcp/index.js +0 -3
  116. package/dist/modules/mcp/module.js +0 -142
  117. package/dist/modules/mcp/registry.js +0 -15
  118. package/dist/modules/memory/index.js +0 -1
  119. package/dist/modules/memory/module.js +0 -96
  120. package/dist/modules/memory/search.js +0 -42
  121. package/dist/modules/memory/store.js +0 -69
  122. package/dist/modules/pipelines/engine.js +0 -60
  123. package/dist/modules/pipelines/index.js +0 -3
  124. package/dist/modules/pipelines/parser.js +0 -56
  125. package/dist/modules/pipelines/template.js +0 -14
  126. package/dist/modules/plugins/builtin/lint-on-write.js +0 -231
  127. package/dist/modules/plugins/builtin/notify.js +0 -9
  128. package/dist/modules/plugins/index.js +0 -1
  129. package/dist/modules/plugins/loader.js +0 -70
  130. package/dist/modules/plugins/manager.js +0 -217
  131. package/dist/modules/plugins/types.js +0 -1
  132. package/dist/modules/processes/detect.js +0 -34
  133. package/dist/modules/processes/index.js +0 -2
  134. package/dist/modules/processes/registry.js +0 -327
  135. package/dist/modules/processes/runner.js +0 -23
  136. package/dist/modules/registry.js +0 -47
  137. package/dist/modules/security/audit-log.js +0 -136
  138. package/dist/modules/security/audit-notifier.js +0 -292
  139. package/dist/modules/security/command-validator.js +0 -205
  140. package/dist/modules/security/content-scanner.js +0 -53
  141. package/dist/modules/security/data-sanitizer.js +0 -89
  142. package/dist/modules/security/encryption.js +0 -242
  143. package/dist/modules/security/index.js +0 -14
  144. package/dist/modules/security/network-validator.js +0 -71
  145. package/dist/modules/security/path-validator.js +0 -207
  146. package/dist/modules/security/rate-limiter.js +0 -119
  147. package/dist/modules/security/security-policies.js +0 -531
  148. package/dist/modules/security/session-encryption.js +0 -210
  149. package/dist/modules/security/session-isolation.js +0 -95
  150. package/dist/modules/session/index.js +0 -3
  151. package/dist/modules/session/manager.js +0 -172
  152. package/dist/modules/session/module.js +0 -24
  153. package/dist/modules/session/store.js +0 -222
  154. package/dist/modules/session/types.js +0 -1
  155. package/dist/modules/skills/index.js +0 -2
  156. package/dist/modules/skills/loader.js +0 -72
  157. package/dist/modules/skills/matcher.js +0 -27
  158. package/dist/modules/skills/module.js +0 -129
  159. package/dist/modules/types.js +0 -1
  160. package/dist/modules/updater/checker.js +0 -96
  161. package/dist/modules/updater/index.js +0 -2
  162. package/dist/modules/updater/module.js +0 -116
  163. package/dist/modules/user-profile/compressor.js +0 -16
  164. package/dist/modules/user-profile/index.js +0 -1
  165. package/dist/modules/user-profile/profile.js +0 -68
  166. package/dist/tools/approve.js +0 -32
  167. package/dist/tools/attach-image.js +0 -89
  168. package/dist/tools/bash.js +0 -496
  169. package/dist/tools/browser.js +0 -114
  170. package/dist/tools/chunk-query.js +0 -99
  171. package/dist/tools/create-dir.js +0 -55
  172. package/dist/tools/delete-file.js +0 -62
  173. package/dist/tools/download-file.js +0 -116
  174. package/dist/tools/edit-file.js +0 -79
  175. package/dist/tools/enable-tools.js +0 -58
  176. package/dist/tools/executor.js +0 -144
  177. package/dist/tools/file-info.js +0 -46
  178. package/dist/tools/filter-tools.js +0 -17
  179. package/dist/tools/glob-tool.js +0 -26
  180. package/dist/tools/grep-tool.js +0 -84
  181. package/dist/tools/hidden-tools-block.js +0 -37
  182. package/dist/tools/index.js +0 -78
  183. package/dist/tools/list-dir.js +0 -48
  184. package/dist/tools/load-skill.js +0 -42
  185. package/dist/tools/mcp-call.js +0 -68
  186. package/dist/tools/move-file.js +0 -85
  187. package/dist/tools/path-utils.js +0 -51
  188. package/dist/tools/pipeline-run.js +0 -144
  189. package/dist/tools/preview.js +0 -2
  190. package/dist/tools/process-kill.js +0 -29
  191. package/dist/tools/process-list.js +0 -36
  192. package/dist/tools/process-log.js +0 -45
  193. package/dist/tools/question.js +0 -140
  194. package/dist/tools/read-file.js +0 -91
  195. package/dist/tools/recall.js +0 -117
  196. package/dist/tools/registry.js +0 -47
  197. package/dist/tools/remember.js +0 -67
  198. package/dist/tools/scope-check.js +0 -30
  199. package/dist/tools/search-history.js +0 -84
  200. package/dist/tools/subagent.js +0 -196
  201. package/dist/tools/types.js +0 -1
  202. package/dist/tools/user-input.js +0 -123
  203. package/dist/tools/web-browse.js +0 -86
  204. package/dist/tools/web-fetch.js +0 -98
  205. package/dist/tools/web-search.js +0 -78
  206. package/dist/tools/write-file.js +0 -81
  207. package/dist/ui/box.js +0 -77
  208. package/dist/ui/colors.js +0 -4
  209. package/dist/ui/diff.js +0 -178
  210. package/dist/ui/index.js +0 -6
  211. package/dist/ui/line-editor.js +0 -703
  212. package/dist/ui/line-math.js +0 -69
  213. package/dist/ui/md-formatter.js +0 -212
  214. package/dist/ui/output.js +0 -13
  215. package/dist/ui/plan-view.js +0 -103
  216. package/dist/ui/renderer.js +0 -209
  217. package/dist/ui/spinner.js +0 -70
  218. package/dist/ui/table.js +0 -144
@@ -1,164 +0,0 @@
1
- import { bootstrap } from "../core/bootstrap";
2
- import { saveConfig } from "../config/config";
3
- import { join } from "path";
4
- import { homedir } from "os";
5
- import { SECURITY_POLICIES, applySecurityPolicy, getSecurityPolicy, } from "../modules/security/security-policies";
6
- import { globalAuditNotifier } from "../modules/security/audit-notifier";
7
- import { t } from "../i18n/index";
8
- /**
9
- * Create security subcommand
10
- */
11
- export function createSecurityCommand(program) {
12
- const securityCmd = program.command("security").description(t("cli.security.description"));
13
- // security status - show current security configuration
14
- securityCmd
15
- .command("status")
16
- .description(t("cli.security.status"))
17
- .action(async () => {
18
- const { config } = await bootstrap();
19
- const security = config.security || {};
20
- const bash = security.bash || {};
21
- const paths = security.paths || {};
22
- const network = security.network || {};
23
- const contentScan = security.contentScan || {};
24
- const rateLimits = security.rateLimits || {};
25
- const sessionEncryption = security.sessionEncryption || {};
26
- const auditNotifier = security.auditNotifier || {};
27
- console.log(t("cli.security.current_policy"));
28
- console.log(` ${t("cli.security.bash_enabled")}: ${bash.blacklist?.length > 0 ? t("cli.yes") : t("cli.no")}`);
29
- console.log(` ${t("cli.security.path_validation")}: ${paths.denied?.length > 0 ? t("cli.yes") : t("cli.no")}`);
30
- console.log(` ${t("cli.security.network_validation")}: ${network.deniedDomains?.length > 0 || network.allowedDomains?.length > 0 ? t("cli.yes") : t("cli.no")}`);
31
- console.log(` ${t("cli.security.content_scanning")}: ${contentScan.enabled ? t("cli.yes") : t("cli.no")}`);
32
- console.log(` ${t("cli.security.max_recursion")}: ${security.maxRecursionDepth ?? 3}`);
33
- console.log(` ${t("cli.security.max_file_ops")}: ${security.maxFileOperations ?? 100}`);
34
- console.log(` ${t("cli.security.rate_limit")}: ${rateLimits.maxRequestsPerMinute ?? 60}/min`);
35
- console.log(` ${t("cli.security.session_encryption")}: ${sessionEncryption.enabled ? t("cli.yes") : t("cli.no")}`);
36
- console.log(` ${t("cli.security.audit_notifier")}: ${auditNotifier.enabled ? t("cli.yes") : t("cli.no")}`);
37
- });
38
- // security policies - manage security policies
39
- securityCmd
40
- .command("policies")
41
- .description(t("cli.security.policies"))
42
- .action(async () => {
43
- console.log(t("cli.security.available_policies"));
44
- console.log("");
45
- for (const [preset, policy] of Object.entries(SECURITY_POLICIES)) {
46
- if (preset === "custom")
47
- continue;
48
- const marker = " ";
49
- console.log(` ${marker}${preset.padEnd(12)} ${policy.name}`);
50
- console.log(` ${policy.description}`);
51
- console.log(` ${t("cli.security.recommended_for")}: ${policy.recommendedFor.join(", ")}`);
52
- console.log("");
53
- }
54
- });
55
- // security set-policy - apply a security policy
56
- securityCmd
57
- .command("set-policy")
58
- .argument("<preset>", t("cli.security.preset"))
59
- .description(t("cli.security.set_policy"))
60
- .action(async (preset) => {
61
- const configPath = join(homedir(), ".mma", "config.json");
62
- const { config: appConfig } = await bootstrap();
63
- const validPresets = ["strict", "balanced", "permissive"];
64
- if (!validPresets.includes(preset)) {
65
- console.log(t("cli.security.invalid_preset", { presets: validPresets.join(", ") }));
66
- return;
67
- }
68
- const policy = getSecurityPolicy(preset);
69
- const newSecurityConfig = applySecurityPolicy(preset);
70
- // Merge with existing config
71
- appConfig.security = newSecurityConfig;
72
- saveConfig(appConfig, configPath);
73
- console.log(t("cli.security.policy_applied", { name: policy.name }));
74
- console.log(t("cli.security.policy_description", { description: policy.description }));
75
- });
76
- // security enable-encryption - enable session file encryption
77
- securityCmd
78
- .command("enable-encryption")
79
- .description(t("cli.security.enable_encryption"))
80
- .action(async () => {
81
- const configPath = join(homedir(), ".mma", "config.json");
82
- const { config: appConfig } = await bootstrap();
83
- appConfig.security = appConfig.security || {};
84
- appConfig.security.sessionEncryption = {
85
- enabled: true,
86
- encryptHistory: true,
87
- encryptSessionLog: true,
88
- };
89
- saveConfig(appConfig, configPath);
90
- console.log(t("cli.security.encryption_enabled"));
91
- });
92
- // security disable-encryption - disable session file encryption
93
- securityCmd
94
- .command("disable-encryption")
95
- .description(t("cli.security.disable_encryption"))
96
- .action(async () => {
97
- const configPath = join(homedir(), ".mma", "config.json");
98
- const { config: appConfig } = await bootstrap();
99
- appConfig.security = appConfig.security || {};
100
- appConfig.security.sessionEncryption = {
101
- enabled: false,
102
- encryptHistory: false,
103
- encryptSessionLog: false,
104
- };
105
- saveConfig(appConfig, configPath);
106
- console.log(t("cli.security.encryption_disabled"));
107
- });
108
- // security enable-audit - enable audit notifications
109
- securityCmd
110
- .command("enable-audit")
111
- .description(t("cli.security.enable_audit"))
112
- .action(async () => {
113
- const configPath = join(homedir(), ".mma", "config.json");
114
- const { config: appConfig } = await bootstrap();
115
- appConfig.security = appConfig.security || {};
116
- appConfig.security.auditNotifier = {
117
- enabled: true,
118
- minSeverity: "medium",
119
- eventTypes: ["security_block", "bash_command", "file_operation", "network_request"],
120
- maxRetries: 3,
121
- webhookTimeout: 5000,
122
- };
123
- saveConfig(appConfig, configPath);
124
- console.log(t("cli.security.audit_enabled"));
125
- });
126
- // security disable-audit - disable audit notifications
127
- securityCmd
128
- .command("disable-audit")
129
- .description(t("cli.security.disable_audit"))
130
- .action(async () => {
131
- const configPath = join(homedir(), ".mma", "config.json");
132
- const { config: appConfig } = await bootstrap();
133
- appConfig.security = appConfig.security || {};
134
- appConfig.security.auditNotifier = {
135
- enabled: false,
136
- maxRetries: 3,
137
- webhookTimeout: 5000,
138
- };
139
- saveConfig(appConfig, configPath);
140
- console.log(t("cli.security.audit_disabled"));
141
- });
142
- // security audit-stats - show audit notification statistics
143
- securityCmd
144
- .command("audit-stats")
145
- .description(t("cli.security.audit_stats"))
146
- .action(async () => {
147
- const stats = globalAuditNotifier.getStats();
148
- console.log(t("cli.security.audit_stats_title"));
149
- console.log(` ${t("cli.security.total_notifications")}: ${stats.total}`);
150
- console.log("");
151
- console.log(t("cli.security.by_severity"));
152
- console.log(` ${t("cli.security.low")}: ${stats.bySeverity.low}`);
153
- console.log(` ${t("cli.security.medium")}: ${stats.bySeverity.medium}`);
154
- console.log(` ${t("cli.security.high")}: ${stats.bySeverity.high}`);
155
- console.log(` ${t("cli.security.critical")}: ${stats.bySeverity.critical}`);
156
- console.log("");
157
- console.log(t("cli.security.by_type"));
158
- for (const [type, count] of Object.entries(stats.byType)) {
159
- if (count > 0) {
160
- console.log(` ${type}: ${count}`);
161
- }
162
- }
163
- });
164
- }
package/dist/cli/setup.js DELETED
@@ -1,231 +0,0 @@
1
- import * as readline from "readline";
2
- import { pc } from "../ui/colors";
3
- import { t, setLocale } from "../i18n/index";
4
- import { Spinner } from "../ui/spinner";
5
- import { box } from "../ui/box";
6
- import { renderTable } from "../ui/table";
7
- async function withSpinner(message, fn) {
8
- const spinner = new Spinner();
9
- spinner.start(message);
10
- try {
11
- return await fn();
12
- }
13
- finally {
14
- spinner.stop();
15
- }
16
- }
17
- /** Render a numbered list inside a box. */
18
- function menuList(items) {
19
- const lines = items.map((it, i) => ` ${pc.cyan(`[${i + 1}]`)} ${it.label}${it.url ? ` ${pc.dim(it.url)}` : ""}`);
20
- for (const l of box(lines, { width: 72 }))
21
- console.log(l);
22
- }
23
- function ask(rl, question, defaultValue) {
24
- return new Promise((resolve) => {
25
- const prompt = defaultValue ? `${question} [${defaultValue}]: ` : `${question}: `;
26
- rl.question(prompt, (answer) => {
27
- resolve(answer.trim() || defaultValue || "");
28
- });
29
- });
30
- }
31
- const PROVIDER_TYPES = [
32
- {
33
- value: "openai-compat",
34
- label: "OpenAI-compatible (LM Studio, Ollama, vLLM, etc.)",
35
- },
36
- { value: "openai", label: "OpenAI API" },
37
- { value: "anthropic", label: "Anthropic Claude" },
38
- ];
39
- const KNOWN_PORTS = [
40
- { port: 1234, label: "LM Studio" },
41
- { port: 11434, label: "Ollama" },
42
- { port: 8080, label: "vLLM / custom" },
43
- { port: 4891, label: "GPT4All" },
44
- ];
45
- async function scanPorts() {
46
- const found = [];
47
- for (const { port, label } of KNOWN_PORTS) {
48
- try {
49
- const controller = new AbortController();
50
- const timeout = setTimeout(() => controller.abort(), 2000);
51
- const resp = await fetch(`http://localhost:${port}/v1/models`, {
52
- signal: controller.signal,
53
- });
54
- clearTimeout(timeout);
55
- if (resp.ok) {
56
- found.push({ label, url: `http://localhost:${port}/v1` });
57
- }
58
- }
59
- catch {
60
- /* port not available */
61
- }
62
- }
63
- return found;
64
- }
65
- async function fetchModels(apiBase, apiKey) {
66
- try {
67
- const url = `${apiBase.replace(/\/+$/, "")}/models`;
68
- const controller = new AbortController();
69
- const timeout = setTimeout(() => controller.abort(), 5000);
70
- const resp = await fetch(url, {
71
- headers: {
72
- Authorization: `Bearer ${apiKey}`,
73
- "Content-Type": "application/json",
74
- },
75
- signal: controller.signal,
76
- });
77
- clearTimeout(timeout);
78
- if (!resp.ok)
79
- return [];
80
- const data = (await resp.json());
81
- const models = (data.data || data || [])
82
- .map((m) => m.id || m.name || m.model || "")
83
- .filter(Boolean);
84
- return models;
85
- }
86
- catch {
87
- return [];
88
- }
89
- }
90
- async function testChat(apiBase, apiKey, model) {
91
- try {
92
- const url = `${apiBase.replace(/\/+$/, "")}/chat/completions`;
93
- const controller = new AbortController();
94
- const timeout = setTimeout(() => controller.abort(), 10000);
95
- const resp = await fetch(url, {
96
- method: "POST",
97
- headers: {
98
- Authorization: `Bearer ${apiKey}`,
99
- "Content-Type": "application/json",
100
- },
101
- body: JSON.stringify({
102
- model,
103
- messages: [{ role: "user", content: 'Say "ok"' }],
104
- max_tokens: 20,
105
- }),
106
- signal: controller.signal,
107
- });
108
- clearTimeout(timeout);
109
- if (!resp.ok)
110
- return false;
111
- const data = (await resp.json());
112
- const msg = data.choices?.[0]?.message;
113
- const text = msg?.content || msg?.reasoning_content || "";
114
- return text.length > 0;
115
- }
116
- catch {
117
- return false;
118
- }
119
- }
120
- export async function runSetup(externalRl) {
121
- console.log(t("setup.title"));
122
- const rl = externalRl ||
123
- readline.createInterface({
124
- input: process.stdin,
125
- output: process.stdout,
126
- });
127
- const ownRl = !externalRl;
128
- console.log(t("setup.language"));
129
- const locale = await ask(rl, t("setup.ui_lang"), "en");
130
- setLocale(locale);
131
- console.log(t("setup.select_provider"));
132
- menuList(PROVIDER_TYPES);
133
- const providerChoice = await ask(rl, t("setup.select_provider_num", { max: PROVIDER_TYPES.length }), "1");
134
- const providerIdx = Math.max(0, Math.min(PROVIDER_TYPES.length - 1, (parseInt(providerChoice) || 1) - 1));
135
- const provider = PROVIDER_TYPES[providerIdx].value;
136
- let apiBase = "";
137
- if (provider === "openai-compat") {
138
- const found = await withSpinner(t("setup.scanning_spinner"), async () => scanPorts());
139
- if (found.length > 0) {
140
- console.log(t("setup.found_servers", { count: found.length }));
141
- menuList([
142
- ...found.map((f) => ({ label: f.label, url: f.url })),
143
- { label: t("setup.custom_url") },
144
- ]);
145
- const choice = await ask(rl, t("setup.select_server", { max: found.length + 1 }), "1");
146
- const idx = (parseInt(choice) || 1) - 1;
147
- if (idx >= found.length) {
148
- apiBase = await ask(rl, t("setup.api_base"), "http://localhost:1234/v1");
149
- }
150
- else {
151
- apiBase = found[Math.max(0, Math.min(found.length - 1, idx))].url;
152
- }
153
- }
154
- else {
155
- console.log(t("setup.no_servers"));
156
- apiBase = await ask(rl, t("setup.api_base"), "http://localhost:1234/v1");
157
- }
158
- }
159
- else if (provider === "openai") {
160
- apiBase = "https://api.openai.com/v1";
161
- }
162
- else if (provider === "anthropic") {
163
- apiBase = "https://api.anthropic.com";
164
- }
165
- const defaultKey = provider === "openai-compat" ? "not-needed" : "";
166
- const apiKey = await ask(rl, t("setup.api_key"), defaultKey);
167
- const models = await withSpinner(t("setup.fetching_spinner"), () => fetchModels(apiBase, apiKey));
168
- let model = "";
169
- if (models.length > 0) {
170
- console.log(t("setup.available_models"));
171
- menuList(models.slice(0, 10).map((m) => ({ label: m })));
172
- const choice = await ask(rl, t("setup.select_model", { max: Math.min(models.length, 10) }), "1");
173
- const idx = Math.max(0, Math.min(models.length - 1, (parseInt(choice) || 1) - 1));
174
- model = models[idx];
175
- }
176
- else {
177
- model = await ask(rl, t("setup.model_name"), "qwen/qwen3.5-9b");
178
- }
179
- const connected = await withSpinner(t("setup.testing_spinner", { model }), () => testChat(apiBase, apiKey, model));
180
- if (connected) {
181
- console.log(pc.green(t("setup.ok")));
182
- }
183
- else {
184
- console.log(pc.yellow(t("setup.warning")));
185
- }
186
- console.log(t("setup.agent_settings"));
187
- const contextWindow = parseInt(await ask(rl, t("setup.context_window"), "32768"));
188
- const maxIterations = parseInt(await ask(rl, t("setup.max_iters"), "1000"));
189
- // Security settings
190
- console.log(t("setup.security_header"));
191
- console.log(pc.dim(t("setup.security_status_off")));
192
- const configureSecurity = await ask(rl, t("setup.security_configure"), "n");
193
- let securityBashBlock = false;
194
- let securityFlagsBlock = false;
195
- let securityPathsDeny = true;
196
- if (configureSecurity.toLowerCase() === "y" || configureSecurity.toLowerCase() === "yes") {
197
- securityBashBlock = (await ask(rl, t("setup.security_bash_block"), "n")).toLowerCase() === "y";
198
- securityFlagsBlock =
199
- (await ask(rl, t("setup.security_flags_block"), "n")).toLowerCase() === "y";
200
- securityPathsDeny = (await ask(rl, t("setup.security_paths_deny"), "Y")).toLowerCase() !== "n";
201
- }
202
- if (ownRl)
203
- rl.close();
204
- const answers = {
205
- provider,
206
- apiBase,
207
- apiKey: apiKey || "not-needed",
208
- model,
209
- contextWindow,
210
- maxToolIterations: maxIterations,
211
- locale,
212
- securityBashBlock,
213
- securityFlagsBlock,
214
- securityPathsDeny,
215
- };
216
- console.log(pc.green(pc.bold(t("setup.complete"))));
217
- const summary = renderTable([
218
- t("setup.summary_setting"),
219
- t("setup.summary_value"),
220
- t("setup.summary_setting"),
221
- t("setup.summary_value"),
222
- ], [
223
- [t("setup.provider_type"), provider, t("setup.model_name"), model],
224
- ["API Base URL", apiBase, t("setup.context_window"), String(contextWindow)],
225
- [t("setup.api_key"), apiKey || "not-needed", t("setup.max_iters"), String(maxIterations)],
226
- [t("setup.ui_lang"), locale, "", ""],
227
- ], { maxColumns: 4 });
228
- for (const l of summary)
229
- console.log(l);
230
- return answers;
231
- }
@@ -1,249 +0,0 @@
1
- import { existsSync, readFileSync, unlinkSync, writeFileSync, mkdirSync } from "fs";
2
- import { join, dirname } from "path";
3
- import { DEFAULTS } from "./defaults";
4
- import { DEFAULT_SECURITY_CONFIG } from "./security";
5
- import { DEFAULT_LSP_CONFIG } from "../modules/lsp/config";
6
- import { t } from "../i18n/index";
7
- import { MigrationDetector } from "../migration/detect";
8
- import { BackupManager } from "../migration/backup";
9
- import { validateExpertConfig } from "./experts";
10
- import { ConfigEncryptor } from "../modules/security/encryption";
11
- /**
12
- * Restore RegExp instances in dangerousPatterns that were serialized as {}
13
- * (pre-0.8.0 configs) or as {__regex, source, flags} (new format).
14
- * Falls back to default patterns for any entry that is not a real RegExp.
15
- */
16
- function restoreDangerousPatterns(patterns, defaults) {
17
- const fallback = (Array.isArray(defaults) ? defaults : []);
18
- if (!Array.isArray(patterns) || patterns.length === 0) {
19
- return fallback;
20
- }
21
- return patterns.map((p, i) => {
22
- if (p instanceof RegExp)
23
- return p;
24
- // If the pattern was serialized as {__regex, source, flags}, revive it
25
- if (p && typeof p === "object") {
26
- const { source, flags } = p;
27
- if (source && typeof source === "string") {
28
- try {
29
- return new RegExp(source, flags || "");
30
- }
31
- catch {
32
- // fall through
33
- }
34
- }
35
- }
36
- // Corrupted entry (e.g. serialized as {} pre-0.8.0): use default by index
37
- return fallback[i] || fallback[0] || p;
38
- });
39
- }
40
- function deepMerge(target, source) {
41
- const result = { ...target };
42
- for (const key of Object.keys(source)) {
43
- const srcVal = source[key];
44
- const tgtVal = target[key];
45
- if (srcVal !== null &&
46
- srcVal !== undefined &&
47
- typeof srcVal === "object" &&
48
- !Array.isArray(srcVal) &&
49
- typeof tgtVal === "object" &&
50
- !Array.isArray(tgtVal)) {
51
- result[key] = deepMerge(tgtVal, srcVal);
52
- }
53
- else if (srcVal !== undefined) {
54
- result[key] = srcVal;
55
- }
56
- }
57
- return result;
58
- }
59
- /**
60
- * JSON replacer that serializes RegExp objects as {__regex, source, flags}
61
- * so they survive JSON.stringify/parse round-trips.
62
- */
63
- function regexReplacer(_key, value) {
64
- if (value instanceof RegExp) {
65
- return { __regex: true, source: value.source, flags: value.flags };
66
- }
67
- return value;
68
- }
69
- /**
70
- * JSON reviver that restores RegExp objects serialized by regexReplacer.
71
- */
72
- function regexReviver(_key, value) {
73
- if (value && typeof value === "object" && value.__regex === true) {
74
- const { source, flags } = value;
75
- try {
76
- return new RegExp(source, flags);
77
- }
78
- catch {
79
- return value;
80
- }
81
- }
82
- return value;
83
- }
84
- /**
85
- * Legacy npx `args` for LSP servers that predate the fixed invocation
86
- * (`--yes --package <server> --package typescript@5 …`). These exact arrays
87
- * are unsafe: without `--yes`/`--package` the servers fail to bootstrap
88
- * (`Could not find a valid TypeScript installation`) or the package name is
89
- * wrong, so the server hangs until the initialize timeout. When a stored
90
- * server's `args` matches one of these (or is missing) it is replaced with the
91
- * current default args — user-customized arrays that differ are left alone.
92
- */
93
- const LEGACY_LSP_SERVER_ARGS = {
94
- typescript: { args: ["typescript-language-server", "--stdio"], timeout: 30000 },
95
- javascript: { args: ["typescript-language-server", "--stdio"], timeout: 30000 },
96
- json: { args: ["vscode-json-languageserver", "--stdio"], timeout: 30000 },
97
- html: { args: ["vscode-html-languageserver", "--stdio"], timeout: 60000 },
98
- css: { args: ["vscode-css-languageserver", "--stdio"], timeout: 60000 },
99
- };
100
- /**
101
- * Replace stale pre-0.41.1 LSP server invocations (npx bootstrap args) with
102
- * the current defaults, so an old `~/.mma/config.json` that overrides the
103
- * fixed server args can't silently re-break every LSP server. In-memory only —
104
- * mirrors the `restoreDangerousPatterns` precedent; the file keeps the old
105
- * args and is normalized again on every load.
106
- */
107
- function normalizeLspServerArgs(config) {
108
- const servers = config.lsp?.servers;
109
- if (!servers)
110
- return;
111
- for (const [lang, legacy] of Object.entries(LEGACY_LSP_SERVER_ARGS)) {
112
- const server = servers[lang];
113
- const def = DEFAULT_LSP_CONFIG.servers[lang];
114
- if (!server || server.command !== "npx" || !def)
115
- continue;
116
- const storedArgs = Array.isArray(server.args) ? server.args : null;
117
- const isLegacy = storedArgs === null || JSON.stringify(storedArgs) === JSON.stringify(legacy.args);
118
- if (isLegacy) {
119
- server.args = def.args;
120
- server.timeout = def.timeout;
121
- }
122
- }
123
- }
124
- function loadJSON(path) {
125
- try {
126
- if (existsSync(path)) {
127
- return JSON.parse(readFileSync(path, "utf-8"), regexReviver);
128
- }
129
- }
130
- catch {
131
- /* ignore malformed files */
132
- }
133
- return null;
134
- }
135
- function applyEnvVars(config) {
136
- const env = process.env;
137
- const result = { ...config };
138
- if (env.MMA_MODEL)
139
- result.model = env.MMA_MODEL;
140
- if (env.MMA_PROVIDER_TYPE)
141
- result.provider = { ...result.provider, type: env.MMA_PROVIDER_TYPE };
142
- if (env.MMA_PROVIDER_BASEURL)
143
- result.provider = { ...result.provider, baseUrl: env.MMA_PROVIDER_BASEURL };
144
- if (env.MMA_PROVIDER_APIKEY)
145
- result.provider = { ...result.provider, apiKey: env.MMA_PROVIDER_APIKEY };
146
- if (env.MMA_LOG_LEVEL)
147
- result.logLevel = env.MMA_LOG_LEVEL;
148
- if (env.MMA_LOCALE)
149
- result.locale = env.MMA_LOCALE;
150
- if (env.MMA_CONTEXT_WINDOW) {
151
- const v = parseInt(env.MMA_CONTEXT_WINDOW, 10);
152
- if (!isNaN(v))
153
- result.contextWindow = v;
154
- }
155
- if (env.MMA_MAX_TOOL_ITERATIONS) {
156
- const v = parseInt(env.MMA_MAX_TOOL_ITERATIONS, 10);
157
- if (!isNaN(v))
158
- result.maxToolIterations = v;
159
- }
160
- if (env.MMA_STUCK_THRESHOLD) {
161
- const v = parseInt(env.MMA_STUCK_THRESHOLD, 10);
162
- if (!isNaN(v))
163
- result.stuckThreshold = v;
164
- }
165
- if (env.MMA_AUTO_PLAN)
166
- result.autoPlan = env.MMA_AUTO_PLAN === "true";
167
- if (env.MMA_MOE_ENABLED)
168
- result.moe = { ...result.moe, enabled: env.MMA_MOE_ENABLED === "true" };
169
- return result;
170
- }
171
- export function loadConfig(options) {
172
- const globalPath = join(options.configDir, "config.json");
173
- mkdirSync(options.configDir, { recursive: true });
174
- const detector = new MigrationDetector(options.configDir);
175
- if (detector.needsMigration()) {
176
- const backup = new BackupManager(options.configDir);
177
- backup.backupConfig();
178
- const summary = backup.getBackupSummary();
179
- console.log(t("migration.detected", { summary }));
180
- try {
181
- unlinkSync(globalPath);
182
- }
183
- catch { }
184
- }
185
- let config = { ...DEFAULTS };
186
- const globalData = loadJSON(globalPath);
187
- if (globalData) {
188
- config = deepMerge(config, globalData);
189
- }
190
- if (!existsSync(globalPath)) {
191
- saveConfig(config, globalPath);
192
- }
193
- const projectData = loadJSON(options.projectConfigPath);
194
- if (projectData) {
195
- config = deepMerge(config, projectData);
196
- }
197
- // Restore RegExp patterns in contentScan that may have been serialized
198
- // as {} in pre-0.8.0 config files, or merged from user config.
199
- if (config.security?.contentScan?.dangerousPatterns) {
200
- config.security.contentScan.dangerousPatterns = restoreDangerousPatterns(config.security.contentScan.dangerousPatterns, DEFAULT_SECURITY_CONFIG.contentScan.dangerousPatterns);
201
- }
202
- // Replace stale pre-0.41.1 LSP server args with the current defaults.
203
- normalizeLspServerArgs(config);
204
- config = applyEnvVars(config);
205
- // Decrypt sensitive fields in the loaded config
206
- try {
207
- const encryptor = new ConfigEncryptor();
208
- const decrypted = encryptor.decrypt(config);
209
- // Merge decrypted sensitive fields back into config
210
- for (const key of Object.keys(decrypted)) {
211
- config[key] = decrypted[key];
212
- }
213
- }
214
- catch (e) {
215
- // If decryption fails, log a warning but continue with the config
216
- console.warn(t("config.decryption_warning", { error: e.message }));
217
- }
218
- // Update global audit notifier with config (done in bootstrap.ts)
219
- return config;
220
- }
221
- export function validateConfig(config, allToolTags) {
222
- const errors = validateExpertConfig(config, allToolTags);
223
- const knownTags = new Set(allToolTags);
224
- for (const tag of config.tools?.defaultTags ?? []) {
225
- if (!knownTags.has(tag)) {
226
- errors.push(`tools.defaultTags references unknown tag "${tag}". Known tags: ${Array.from(knownTags).join(", ")}`);
227
- }
228
- }
229
- if (errors.length > 0) {
230
- throw new Error(`Config validation failed:\n${errors.join("\n")}`);
231
- }
232
- }
233
- export function saveConfig(config, configPath) {
234
- const dir = dirname(configPath);
235
- mkdirSync(dir, { recursive: true });
236
- // Encrypt sensitive fields before saving
237
- try {
238
- const encryptor = new ConfigEncryptor();
239
- const encryptedConfig = encryptor.encrypt({
240
- ...config,
241
- });
242
- writeFileSync(configPath, JSON.stringify(encryptedConfig, regexReplacer, 2), "utf-8");
243
- }
244
- catch (e) {
245
- // If encryption fails, save without encryption
246
- console.warn(t("config.encryption_warning", { error: e.message }));
247
- writeFileSync(configPath, JSON.stringify(config, regexReplacer, 2), "utf-8");
248
- }
249
- }