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