micro-models-agent 0.46.1 → 0.46.3

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 +312 -312
  2. package/dist/main.js +724 -530
  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,661 +0,0 @@
1
- import { pc } from "../ui/colors";
2
- import { renderTable } from "../ui/table";
3
- import { t } from "../i18n/index";
4
- import { runSetup } from "./setup";
5
- import { saveConfig } from "../config/config";
6
- import { getMessageText } from "../llm/provider";
7
- import { join, dirname } from "path";
8
- import { homedir } from "os";
9
- import { existsSync, readFileSync } from "fs";
10
- import { fileURLToPath } from "url";
11
- function readVersion() {
12
- const here = dirname(fileURLToPath(import.meta.url));
13
- const candidates = [join(here, "..", "..", "package.json"), join(here, "..", "package.json")];
14
- for (const p of candidates) {
15
- if (existsSync(p)) {
16
- try {
17
- const raw = JSON.parse(readFileSync(p, "utf8"));
18
- if (raw.version)
19
- return raw.version;
20
- }
21
- catch {
22
- // Broken package.json — fall through to the next candidate
23
- }
24
- }
25
- }
26
- return "0.0.0";
27
- }
28
- const version = readVersion();
29
- export const COMMAND_GROUPS = {
30
- help: "general",
31
- exit: "general",
32
- clear: "general",
33
- run: "general",
34
- image: "general",
35
- config: "agent",
36
- status: "agent",
37
- reasoning: "agent",
38
- provider: "agent",
39
- model: "agent",
40
- context: "agent",
41
- reload: "agent",
42
- wizard: "agent",
43
- sysprompt: "agent",
44
- sessions: "session",
45
- new: "session",
46
- resume: "session",
47
- rename: "session",
48
- delete: "session",
49
- skill: "skill",
50
- plugins: "agent",
51
- };
52
- export function registerAllCommands(ctx) {
53
- registerBuiltinCommands(ctx);
54
- registerMmaCommands(ctx);
55
- registerSessionCommands(ctx);
56
- registerSkillCommands(ctx);
57
- }
58
- function registerBuiltinCommands(ctx) {
59
- ctx.registerCommand({
60
- name: "help",
61
- description: t("repl.help"),
62
- usage: t("repl.help_usage"),
63
- action: () => ctx.showHelp(),
64
- });
65
- ctx.registerCommand({
66
- name: "exit",
67
- description: t("repl.exit"),
68
- aliases: ["quit", "q"],
69
- usage: t("repl.exit_usage"),
70
- action: () => ctx.stop(),
71
- });
72
- ctx.registerCommand({
73
- name: "clear",
74
- description: t("repl.clear"),
75
- usage: t("repl.clear_usage"),
76
- action: () => {
77
- console.clear();
78
- },
79
- });
80
- }
81
- function registerMmaCommands(ctx) {
82
- ctx.registerCommand({
83
- name: "run",
84
- description: t("repl.run"),
85
- usage: t("repl.run_usage"),
86
- action: async (args) => {
87
- if (args.length === 0) {
88
- console.log(t("repl.run_usage"));
89
- return;
90
- }
91
- const prompt = args.join(" ");
92
- await ctx.runAgent(prompt);
93
- },
94
- });
95
- ctx.registerCommand({
96
- name: "image",
97
- description: t("repl.image"),
98
- aliases: ["img"],
99
- usage: t("repl.image_usage"),
100
- action: async (args) => {
101
- const source = args.join(" ");
102
- if (!source) {
103
- console.log(t("repl.image_usage"));
104
- return;
105
- }
106
- try {
107
- const { loadFileAsDataUrl, loadUrlAsDataUrl, readClipboardImage } = await import("../llm/image-utils");
108
- const { existsSync } = await import("fs");
109
- const { resolve } = await import("path");
110
- let dataUrl;
111
- let label;
112
- if (source.toLowerCase() === "clipboard") {
113
- const clipBuf = await readClipboardImage();
114
- if (!clipBuf) {
115
- console.log(pc.yellow(t("image.clipboard_empty")));
116
- return;
117
- }
118
- const { bufferToDataUrl } = await import("../llm/image-utils");
119
- const result = await bufferToDataUrl(clipBuf);
120
- dataUrl = result.dataUrl;
121
- label = "clipboard";
122
- }
123
- else if (source.startsWith("http://") || source.startsWith("https://")) {
124
- const result = await loadUrlAsDataUrl(source);
125
- dataUrl = result.dataUrl;
126
- label = source;
127
- }
128
- else {
129
- const absPath = resolve(process.cwd(), source);
130
- if (!existsSync(absPath)) {
131
- console.log(pc.red(t("image.not_found", { path: source })));
132
- return;
133
- }
134
- const result = await loadFileAsDataUrl(absPath);
135
- dataUrl = result.dataUrl;
136
- label = source;
137
- }
138
- const contextManager = ctx.agent.contextManager;
139
- if (!contextManager) {
140
- console.log(pc.red(t("image.no_context")));
141
- return;
142
- }
143
- contextManager.addPendingImage({
144
- type: "image_url",
145
- image_url: { url: dataUrl },
146
- });
147
- const sizeKb = Math.round((dataUrl.length * 3) / 4 / 1024);
148
- console.log(pc.green(t("image.attached", { source: label, size: `${sizeKb} KB` })));
149
- }
150
- catch (err) {
151
- console.log(pc.red(t("image.error", { message: err.message })));
152
- }
153
- },
154
- });
155
- ctx.registerCommand({
156
- name: "config",
157
- description: t("repl.config"),
158
- usage: t("repl.config_usage"),
159
- action: () => {
160
- const cfg = ctx.config;
161
- const ctxW = cfg.contextWindow;
162
- const sys = Math.floor(ctxW * cfg.contextBudget.systemPrompt);
163
- const res = Math.floor(ctxW * cfg.contextBudget.responseReserve);
164
- console.log(`${t("repl.model")} ${cfg.model}`);
165
- console.log(`${t("repl.provider")} ${cfg.provider.type} → ${cfg.provider.baseUrl}`);
166
- console.log(`${t("repl.context")} ${ctxW} (sys:${sys} res:${res} hist:${ctxW - sys - res})`);
167
- console.log(`${t("repl.max_iters")} ${cfg.maxToolIterations}`);
168
- console.log(`${t("repl.stuck_thresh")} ${cfg.stuckThreshold}`);
169
- console.log(`${t("repl.reasoning_label")} ${cfg.showReasoning ? pc.green(t("repl.show")) : pc.dim(t("repl.hide"))}`);
170
- console.log(`${t("repl.log_level")} ${cfg.logLevel}`);
171
- console.log(`${t("repl.locale")} ${cfg.locale}`);
172
- const meta = ctx.sessionManager?.getActiveMeta();
173
- if (meta) {
174
- console.log(`${t("repl.session_label")} ${meta.name} (${meta.id}) — ${meta.messageCount} msgs`);
175
- }
176
- },
177
- });
178
- ctx.registerCommand({
179
- name: "reasoning",
180
- description: t("repl.reasoning"),
181
- usage: t("repl.reasoning_usage"),
182
- action: () => {
183
- ctx.config.showReasoning = !ctx.config.showReasoning;
184
- const status = ctx.config.showReasoning ? pc.green(t("repl.show")) : pc.dim(t("repl.hide"));
185
- console.log(t("repl.reasoning_status", { status }));
186
- },
187
- });
188
- ctx.registerCommand({
189
- name: "status",
190
- description: t("repl.status"),
191
- usage: t("repl.status_usage"),
192
- action: () => {
193
- console.log(`${t("repl.model")} ${ctx.config.model}`);
194
- console.log(`${t("repl.provider")} ${ctx.config.provider.type} @ ${ctx.config.provider.baseUrl}`);
195
- const meta = ctx.sessionManager?.getActiveMeta();
196
- if (meta) {
197
- console.log(`${t("repl.session_label")} ${meta.name} (${meta.id}) — ${meta.messageCount} messages`);
198
- }
199
- },
200
- });
201
- ctx.registerCommand({
202
- name: "wizard",
203
- description: t("repl.wizard"),
204
- aliases: ["setup"],
205
- usage: t("repl.wizard_usage"),
206
- action: async () => {
207
- console.log(pc.yellow(t("repl.wizard_running")));
208
- await ctx.withExclusiveInput(async () => {
209
- const answers = await runSetup(ctx.rl);
210
- const configPath = join(homedir(), ".mma", "config.json");
211
- ctx.config.provider.type = answers.provider;
212
- ctx.config.provider.baseUrl = answers.apiBase;
213
- ctx.config.provider.apiKey = answers.apiKey;
214
- ctx.config.model = answers.model;
215
- ctx.config.contextWindow = answers.contextWindow;
216
- ctx.config.maxToolIterations = answers.maxToolIterations;
217
- ctx.config.locale = answers.locale;
218
- saveConfig(ctx.config, configPath);
219
- await ctx.agent.reconfigure(ctx.config);
220
- console.log(pc.green(t("cli.config_saved")));
221
- });
222
- },
223
- });
224
- ctx.registerCommand({
225
- name: "sysprompt",
226
- description: t("repl.sysprompt_desc"),
227
- usage: t("repl.sysprompt_desc"),
228
- action: () => {
229
- const info = ctx.agent.getSystemPromptInfo();
230
- console.log(pc.bold(`System prompt (${info.tokenCount} tokens):`));
231
- console.log(pc.dim("─".repeat(60)));
232
- for (const line of info.text.split("\n")) {
233
- console.log(line);
234
- }
235
- console.log(pc.dim("─".repeat(60)));
236
- if (info.excluded.length > 0) {
237
- console.log(pc.yellow(`\nExcluded blocks: ${info.excluded.length}`));
238
- for (const e of info.excluded) {
239
- console.log(pc.dim(` - ${e.slice(0, 80)}${e.length > 80 ? "..." : ""}`));
240
- }
241
- }
242
- },
243
- });
244
- ctx.registerCommand({
245
- name: "provider",
246
- description: t("repl.provider_list"),
247
- usage: t("repl.provider_usage"),
248
- action: async (args) => {
249
- const subcmd = args[0];
250
- if (!subcmd || subcmd === "list") {
251
- console.log(`${t("repl.provider_current")} ${ctx.config.provider.type}`);
252
- console.log(` ${ctx.config.provider.baseUrl}`);
253
- return;
254
- }
255
- if (subcmd === "use") {
256
- const name = args[1];
257
- if (!name) {
258
- console.log(t("repl.provider_usage"));
259
- return;
260
- }
261
- ctx.config.provider.type = name;
262
- const configPath = join(homedir(), ".mma", "config.json");
263
- saveConfig(ctx.config, configPath);
264
- await ctx.agent.reconfigure(ctx.config);
265
- console.log(pc.green(t("repl.provider_set", { name })));
266
- return;
267
- }
268
- console.log(t("repl.provider_usage"));
269
- },
270
- });
271
- ctx.registerCommand({
272
- name: "model",
273
- description: t("repl.model_list"),
274
- usage: t("repl.model_usage"),
275
- action: async (args) => {
276
- const subcmd = args[0];
277
- if (!subcmd || subcmd === "list") {
278
- console.log(`${t("repl.model_current")} ${ctx.config.model}`);
279
- const { OpenAICompatProvider } = await import("../llm/openai-compat");
280
- const provider = new OpenAICompatProvider({
281
- model: ctx.config.model,
282
- baseUrl: ctx.config.provider.baseUrl,
283
- apiKey: ctx.config.provider.apiKey,
284
- contextWindow: ctx.config.contextWindow,
285
- });
286
- const { Spinner } = await import("../ui/spinner");
287
- const s = new Spinner();
288
- s.start(t("cli.fetching_models"));
289
- try {
290
- const models = await provider.listModels();
291
- s.stop();
292
- if (models.length > 0) {
293
- console.log(t("cli.available_models"));
294
- const { getCertMark } = await import("../modules/certification/manifest");
295
- for (const m of models) {
296
- const marker = m === ctx.config.model ? pc.green("* ") : " ";
297
- const mark = getCertMark(m, ctx.config.provider.baseUrl, version);
298
- const cert = mark === "certified"
299
- ? pc.green("✔")
300
- : mark === "stale"
301
- ? pc.yellow("○")
302
- : pc.dim("·");
303
- console.log(` ${marker}${cert} ${m}`);
304
- }
305
- }
306
- else {
307
- console.log(t("cli.no_models_found"));
308
- }
309
- }
310
- catch (err) {
311
- s.stop();
312
- console.log(t("cli.model_fetch_failed", { error: String(err) }));
313
- }
314
- console.log(t("cli.model_hint"));
315
- return;
316
- }
317
- if (subcmd === "use") {
318
- const name = args[1];
319
- if (!name) {
320
- console.log(t("repl.model_usage"));
321
- return;
322
- }
323
- ctx.config.model = name;
324
- const configPath = join(homedir(), ".mma", "config.json");
325
- saveConfig(ctx.config, configPath);
326
- await ctx.agent.reconfigure(ctx.config);
327
- console.log(pc.green(t("repl.model_set", { name })));
328
- return;
329
- }
330
- console.log(t("repl.model_usage"));
331
- },
332
- });
333
- ctx.registerCommand({
334
- name: "context",
335
- description: t("cli.manage_context"),
336
- usage: "/context <size>",
337
- action: async (args) => {
338
- if (args.length === 0) {
339
- console.log(`/context ${t("repl.context")} ${ctx.config.contextWindow}`);
340
- console.log(`Usage: /context <size> (min 1024)`);
341
- return;
342
- }
343
- const size = parseInt(args[0], 10);
344
- if (isNaN(size) || size < 1024) {
345
- console.log(t("cli.invalid_context_size"));
346
- return;
347
- }
348
- ctx.config.contextWindow = size;
349
- const configPath = join(homedir(), ".mma", "config.json");
350
- saveConfig(ctx.config, configPath);
351
- await ctx.agent.reconfigure(ctx.config);
352
- console.log(pc.green(t("cli.context_set", { size })));
353
- },
354
- });
355
- ctx.registerCommand({
356
- name: "reload",
357
- description: t("repl.reload"),
358
- usage: t("repl.reload_usage"),
359
- action: async () => {
360
- console.log(pc.yellow(t("repl.reloading")));
361
- if (ctx.sessionManager && ctx.config.session.autoSave) {
362
- const active = ctx.sessionManager.getActiveMeta();
363
- if (active) {
364
- // Session is already auto-saved on each message
365
- }
366
- }
367
- ctx.agent.shutdown();
368
- const { loadConfig } = await import("../config/config");
369
- const { homedir } = await import("os");
370
- const { join } = await import("path");
371
- const configDir = ctx.configDir;
372
- const baseDir = ctx.baseDir;
373
- const projectConfigPath = join(baseDir, ".mmrc");
374
- const freshConfig = loadConfig({ configDir, projectConfigPath });
375
- Object.assign(ctx.config, freshConfig);
376
- const { bootstrap } = await import("../core/bootstrap");
377
- const result = await bootstrap(configDir, baseDir, false, false);
378
- ctx.agent = result.agent;
379
- ctx.sessionManager = result.sessionManager;
380
- ctx.skillsModule = result.skillsModule;
381
- ctx.pluginManager = result.pluginManager;
382
- ctx.setupCompleter();
383
- console.log(pc.green(t("repl.reloaded")));
384
- console.log(`${t("repl.model")} ${ctx.config.model}`);
385
- console.log(`${t("repl.context")} ${ctx.config.contextWindow}`);
386
- console.log(`${t("repl.provider")} ${ctx.config.provider.type} @ ${ctx.config.provider.baseUrl}`);
387
- },
388
- });
389
- ctx.registerCommand({
390
- name: "plugins",
391
- description: t("repl.plugins"),
392
- usage: t("repl.plugins_usage"),
393
- action: (args) => {
394
- if (!ctx.pluginManager) {
395
- console.log(t("cli.plugins.none"));
396
- return;
397
- }
398
- const showAll = args.includes("--all");
399
- const infos = ctx.pluginManager.getPluginInfos();
400
- const filtered = showAll ? infos : infos.filter(({ plugin }) => !plugin.isBuiltin);
401
- if (filtered.length === 0) {
402
- console.log(t("cli.plugins.none"));
403
- return;
404
- }
405
- const mmaVersion = version;
406
- console.log(t("cli.plugins.header", {
407
- count: String(filtered.length),
408
- mma: mmaVersion,
409
- }));
410
- for (const { plugin, source } of filtered) {
411
- const v = plugin.version || "-";
412
- const origin = source || "builtin";
413
- const mark = plugin.isBuiltin ? t("cli.plugins.builtin_mark") : " ";
414
- console.log(` ${mark} ${plugin.name} v${v} [${origin}]`);
415
- }
416
- if (!showAll) {
417
- const builtinCount = infos.filter(({ plugin }) => plugin.isBuiltin).length;
418
- if (builtinCount > 0) {
419
- console.log(pc.dim(` (${builtinCount} builtin hidden — /plugins --all to show)`));
420
- }
421
- }
422
- },
423
- });
424
- }
425
- function registerSessionCommands(ctx) {
426
- if (!ctx.sessionManager)
427
- return;
428
- ctx.registerCommand({
429
- name: "sessions",
430
- description: t("repl.sessions"),
431
- aliases: ["ls"],
432
- usage: t("repl.sessions_usage"),
433
- action: () => {
434
- const sessions = ctx.sessionManager.list();
435
- const active = ctx.sessionManager.getActive();
436
- if (sessions.length === 0) {
437
- console.log(t("session.no_sessions_hint"));
438
- return;
439
- }
440
- const rows = sessions.map((s) => [
441
- s.id === active ? pc.green("●") : "",
442
- s.id.slice(0, 12),
443
- s.name,
444
- s.updatedAt.slice(0, 19).replace("T", " "),
445
- String(s.messageCount),
446
- ]);
447
- for (const line of renderTable([
448
- t("session.col_active"),
449
- t("session.col_id"),
450
- t("session.col_name"),
451
- t("session.col_updated"),
452
- t("session.col_msgs"),
453
- ], rows)) {
454
- console.log(line);
455
- }
456
- console.log(pc.dim(`\n ${t("repl.resume_hint")}`));
457
- },
458
- });
459
- ctx.registerCommand({
460
- name: "new",
461
- description: t("repl.new"),
462
- aliases: ["create"],
463
- usage: t("repl.new_usage"),
464
- action: (args) => {
465
- const name = args.join(" ") || undefined;
466
- const meta = ctx.sessionManager.create(name);
467
- ctx.agent.clearContext();
468
- console.clear();
469
- console.log(`${t("session.created", { name: meta.name })} (${pc.dim(meta.id.slice(0, 12))})`);
470
- console.log(pc.dim(` ${t("session.chat_cleared")}\n`));
471
- },
472
- });
473
- ctx.registerCommand({
474
- name: "resume",
475
- description: t("repl.resume"),
476
- aliases: ["switch", "use"],
477
- usage: t("repl.resume_usage"),
478
- action: (args) => {
479
- const query = args.join(" ");
480
- const sessions = ctx.sessionManager.list();
481
- if (!query) {
482
- console.log(pc.dim(t("session.available")));
483
- const active = ctx.sessionManager.getActive();
484
- for (const s of sessions) {
485
- const marker = s.id === active ? pc.green(" *") : " ";
486
- console.log(pc.dim(` ${marker} ${s.id.slice(0, 12)} ${s.name}`));
487
- }
488
- console.log(pc.dim(`\n ${t("repl.resume_usage")}`));
489
- return;
490
- }
491
- const match = sessions.find((s) => s.id === query ||
492
- s.id.startsWith(query) ||
493
- s.name.toLowerCase().includes(query.toLowerCase()));
494
- if (!match) {
495
- console.log(t("session.no_match", { query }));
496
- return;
497
- }
498
- ctx.sessionManager.setActive(match.id);
499
- const history = ctx.sessionManager.loadHistory();
500
- ctx.agent.setContext(history);
501
- console.clear();
502
- console.log(pc.bold(pc.green(t("session.resumed", { name: match.name }))) +
503
- " " +
504
- pc.dim(`(${match.id.slice(0, 12)})`) +
505
- " — " +
506
- match.messageCount +
507
- " msgs");
508
- console.log(pc.dim("─".repeat(50)));
509
- if (history.length === 0) {
510
- console.log(pc.dim(t("session.no_history")));
511
- }
512
- else {
513
- console.log(pc.dim(t("session.chat_history")));
514
- console.log();
515
- for (const msg of history) {
516
- if (msg.role === "user") {
517
- console.log(pc.cyan(t("session.user_label") + ":"));
518
- console.log(getMessageText(msg.content));
519
- console.log();
520
- }
521
- else if (msg.role === "assistant") {
522
- console.log(pc.green(t("session.assistant_label") + ":"));
523
- console.log(getMessageText(msg.content));
524
- console.log();
525
- }
526
- }
527
- }
528
- console.log(pc.dim("─".repeat(50)));
529
- console.log(pc.dim(` ${t("session.chat_loaded")}`));
530
- },
531
- });
532
- ctx.registerCommand({
533
- name: "rename",
534
- description: t("repl.rename"),
535
- usage: t("repl.rename_usage"),
536
- action: (args) => {
537
- const name = args.join(" ");
538
- if (!name) {
539
- console.log(t("repl.rename_usage"));
540
- return;
541
- }
542
- const active = ctx.sessionManager.getActive();
543
- if (!active) {
544
- console.log(t("session.no_active"));
545
- return;
546
- }
547
- ctx.sessionManager.rename(active, name);
548
- console.log(t("session.renamed", { name }));
549
- },
550
- });
551
- ctx.registerCommand({
552
- name: "delete",
553
- description: t("repl.delete"),
554
- aliases: ["rm"],
555
- usage: t("repl.delete_usage"),
556
- action: (args) => {
557
- const query = args[0];
558
- if (!query) {
559
- console.log(t("repl.delete_usage"));
560
- return;
561
- }
562
- const sessions = ctx.sessionManager.list();
563
- const match = sessions.find((s) => s.id === query || s.id.startsWith(query));
564
- if (!match) {
565
- console.log(t("session.no_match", { query }));
566
- return;
567
- }
568
- ctx.sessionManager.delete(match.id);
569
- console.log(`${t("session.deleted", { id: match.id })}: ${match.name}`);
570
- },
571
- });
572
- }
573
- function registerSkillCommands(ctx) {
574
- if (!ctx.skillsModule)
575
- return;
576
- ctx.registerCommand({
577
- name: "skill",
578
- description: t("repl.skill"),
579
- usage: t("repl.skill_usage"),
580
- action: (args) => {
581
- const subcmd = args[0];
582
- const arg = args.slice(1).join(" ");
583
- if (!subcmd || subcmd === "list") {
584
- const available = ctx.skillsModule.getAvailable();
585
- if (available.length === 0) {
586
- console.log(t("repl.no_skills"));
587
- return;
588
- }
589
- console.log(pc.bold(t("repl.available_skills")));
590
- for (const skill of available) {
591
- const tokens = Math.ceil(skill.content.length / 4);
592
- const loaded = ctx.skillsModule.getLoaded().some((s) => s.name === skill.name);
593
- const marker = loaded ? pc.green(" [loaded]") : "";
594
- console.log(` ${pc.cyan(skill.name)}${marker} ${pc.dim(`(${tokens} tokens)`)} ${skill.description.slice(0, 60)}`);
595
- }
596
- return;
597
- }
598
- if (subcmd === "loaded") {
599
- const loaded = ctx.skillsModule.getLoaded();
600
- const budget = ctx.skillsModule.getBudget();
601
- if (loaded.length === 0) {
602
- console.log(t("repl.no_loaded"));
603
- return;
604
- }
605
- console.log(pc.bold(t("repl.loaded_skills")));
606
- for (const skill of loaded) {
607
- const tokens = Math.ceil(skill.content.length / 4);
608
- console.log(` ${pc.cyan(skill.name)} ${pc.dim(`(${tokens} tokens)`)} ${skill.description.slice(0, 60)}`);
609
- }
610
- console.log(pc.dim(`\n ${t("repl.budget", { used: budget.used, total: budget.total, remaining: budget.remaining })}`));
611
- return;
612
- }
613
- if (subcmd === "load") {
614
- if (!arg) {
615
- console.log(t("repl.skill_load_usage"));
616
- return;
617
- }
618
- const result = ctx.skillsModule.loadByName(arg);
619
- if (result.success) {
620
- console.log(pc.green(result.message));
621
- }
622
- else {
623
- console.log(pc.red(result.message));
624
- }
625
- return;
626
- }
627
- if (subcmd === "unload") {
628
- if (!arg) {
629
- console.log(t("repl.skill_unload_usage"));
630
- return;
631
- }
632
- if (ctx.skillsModule.unload(arg)) {
633
- console.log(pc.green(t("repl.skill_unloaded", { name: arg })));
634
- }
635
- else {
636
- console.log(pc.red(t("repl.skill_not_loaded", { name: arg })));
637
- }
638
- return;
639
- }
640
- if (subcmd === "search") {
641
- if (!arg) {
642
- console.log(t("repl.skill_search_usage"));
643
- return;
644
- }
645
- const results = ctx.skillsModule.search(arg);
646
- if (results.length === 0) {
647
- console.log(t("repl.no_skill_match", { query: arg }));
648
- return;
649
- }
650
- console.log(pc.bold(t("repl.skills_matching", { query: arg })));
651
- for (const skill of results) {
652
- const tokens = Math.ceil(skill.content.length / 4);
653
- console.log(` ${pc.cyan(skill.name)} ${pc.dim(`(${tokens} tokens)`)} ${skill.description.slice(0, 60)}`);
654
- }
655
- return;
656
- }
657
- console.log(pc.red(t("repl.skill_unknown_sub", { subcmd })));
658
- console.log(t("repl.skill_usage"));
659
- },
660
- });
661
- }