micro-models-agent 0.41.2 → 0.42.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 (171) hide show
  1. package/bin/mma.mjs +41 -41
  2. package/dist/cli/commands.js +19 -9
  3. package/dist/cli/completer.js +37 -36
  4. package/dist/cli/index.js +2 -2
  5. package/dist/cli/main.js +23 -48
  6. package/dist/cli/repl-commands.js +12 -40
  7. package/dist/cli/repl.js +87 -217
  8. package/dist/cli/security-commands.js +7 -5
  9. package/dist/cli/setup.js +26 -8
  10. package/dist/config/config.js +5 -52
  11. package/dist/config/defaults.js +5 -29
  12. package/dist/config/experts.js +1 -1
  13. package/dist/config/index.js +3 -3
  14. package/dist/config/security.js +10 -3
  15. package/dist/core/agent-moe.js +10 -2
  16. package/dist/core/agent.js +82 -273
  17. package/dist/core/bootstrap.js +13 -80
  18. package/dist/core/index.js +2 -2
  19. package/dist/core/prompt-builder.js +2 -23
  20. package/dist/core/session-logger.js +4 -46
  21. package/dist/i18n/en.json +2 -75
  22. package/dist/i18n/ru.json +1 -74
  23. package/dist/index.js +1 -1
  24. package/dist/llm/image-utils.js +5 -4
  25. package/dist/llm/index.js +4 -4
  26. package/dist/llm/model-loader.js +6 -6
  27. package/dist/llm/openai-compat.js +34 -40
  28. package/dist/llm/orchestrator.js +29 -33
  29. package/dist/llm/response.js +9 -9
  30. package/dist/logger/app-logger.js +1 -1
  31. package/dist/logger/index.js +1 -1
  32. package/dist/main.js +299 -55
  33. package/dist/migration/backup.js +13 -13
  34. package/dist/migration/detect.js +11 -11
  35. package/dist/migration/index.js +2 -2
  36. package/dist/modules/browser/actions.js +4 -34
  37. package/dist/modules/browser/bridge-server.mjs +202 -202
  38. package/dist/modules/browser/cookie-store.js +6 -6
  39. package/dist/modules/browser/index.js +5 -7
  40. package/dist/modules/browser/module.js +7 -8
  41. package/dist/modules/browser/session.js +84 -87
  42. package/dist/modules/browser/snapshot.js +58 -92
  43. package/dist/modules/browser/types.js +1 -4
  44. package/dist/modules/certification/cli.js +4 -2
  45. package/dist/modules/certification/fact-checker.js +3 -1
  46. package/dist/modules/certification/loader.js +9 -3
  47. package/dist/modules/certification/runner.js +4 -1
  48. package/dist/modules/context/index.js +1 -1
  49. package/dist/modules/context/manager.js +86 -160
  50. package/dist/modules/execution/auditor.js +25 -177
  51. package/dist/modules/execution/module.js +544 -201
  52. package/dist/modules/execution/moe-executor.js +0 -25
  53. package/dist/modules/execution/plan-store.js +3 -1
  54. package/dist/modules/execution/plan-validator.js +10 -10
  55. package/dist/modules/execution/planner.js +1 -6
  56. package/dist/modules/execution/stuck-detector.js +10 -173
  57. package/dist/modules/execution/verifier.js +42 -86
  58. package/dist/modules/hallucination/confidence.js +1 -8
  59. package/dist/modules/hallucination/detector.js +5 -2
  60. package/dist/modules/hallucination/factual.js +64 -3
  61. package/dist/modules/hallucination/index.js +1 -1
  62. package/dist/modules/hallucination/js-identifiers.js +0 -190
  63. package/dist/modules/hallucination/llm-judge.js +3 -1
  64. package/dist/modules/indexer/cache.js +7 -9
  65. package/dist/modules/indexer/index.js +3 -3
  66. package/dist/modules/indexer/module.js +42 -95
  67. package/dist/modules/indexer/walker.js +17 -17
  68. package/dist/modules/lsp/client.js +31 -74
  69. package/dist/modules/lsp/config.js +33 -87
  70. package/dist/modules/lsp/index.js +3 -3
  71. package/dist/modules/lsp/module.js +21 -185
  72. package/dist/modules/mcp/module.js +6 -2
  73. package/dist/modules/memory/index.js +1 -1
  74. package/dist/modules/memory/module.js +23 -71
  75. package/dist/modules/memory/search.js +9 -11
  76. package/dist/modules/memory/store.js +13 -13
  77. package/dist/modules/pipelines/engine.js +10 -10
  78. package/dist/modules/pipelines/index.js +3 -3
  79. package/dist/modules/pipelines/parser.js +14 -17
  80. package/dist/modules/pipelines/template.js +1 -1
  81. package/dist/modules/plugins/builtin/lint-on-write.js +16 -21
  82. package/dist/modules/plugins/builtin/notify.js +2 -3
  83. package/dist/modules/plugins/index.js +1 -1
  84. package/dist/modules/plugins/loader.js +17 -59
  85. package/dist/modules/plugins/manager.js +17 -73
  86. package/dist/modules/processes/index.js +1 -1
  87. package/dist/modules/processes/registry.js +46 -135
  88. package/dist/modules/registry.js +2 -4
  89. package/dist/modules/security/audit-notifier.js +39 -39
  90. package/dist/modules/security/command-validator.js +8 -2
  91. package/dist/modules/security/data-sanitizer.js +9 -1
  92. package/dist/modules/security/encryption.js +56 -58
  93. package/dist/modules/security/network-validator.js +9 -1
  94. package/dist/modules/security/path-validator.js +3 -1
  95. package/dist/modules/security/security-policies.js +19 -3
  96. package/dist/modules/security/session-encryption.js +1 -1
  97. package/dist/modules/security/session-isolation.js +8 -8
  98. package/dist/modules/session/index.js +3 -3
  99. package/dist/modules/session/module.js +5 -5
  100. package/dist/modules/session/store.js +9 -3
  101. package/dist/modules/skills/module.js +2 -1
  102. package/dist/modules/updater/checker.js +6 -70
  103. package/dist/modules/updater/index.js +1 -2
  104. package/dist/modules/user-profile/compressor.js +2 -2
  105. package/dist/modules/user-profile/index.js +1 -1
  106. package/dist/modules/user-profile/profile.js +9 -9
  107. package/dist/tools/attach-image.js +1 -1
  108. package/dist/tools/bash.js +19 -178
  109. package/dist/tools/browser.js +29 -46
  110. package/dist/tools/executor.js +5 -4
  111. package/dist/tools/file-info.js +12 -13
  112. package/dist/tools/filter-tools.js +2 -9
  113. package/dist/tools/glob-tool.js +11 -11
  114. package/dist/tools/grep-tool.js +3 -1
  115. package/dist/tools/index.js +2 -13
  116. package/dist/tools/list-dir.js +17 -18
  117. package/dist/tools/load-skill.js +3 -1
  118. package/dist/tools/path-utils.js +4 -4
  119. package/dist/tools/pipeline-run.js +25 -25
  120. package/dist/tools/process-kill.js +11 -11
  121. package/dist/tools/process-list.js +22 -20
  122. package/dist/tools/process-log.js +18 -22
  123. package/dist/tools/question.js +3 -1
  124. package/dist/tools/read-file.js +2 -10
  125. package/dist/tools/recall.js +37 -44
  126. package/dist/tools/registry.js +4 -15
  127. package/dist/tools/remember.js +29 -29
  128. package/dist/tools/scope-check.js +9 -9
  129. package/dist/tools/subagent.js +9 -54
  130. package/dist/tools/user-input.js +1 -1
  131. package/dist/tools/web-browse.js +3 -3
  132. package/dist/tools/web-fetch.js +3 -3
  133. package/dist/tools/web-search.js +3 -3
  134. package/dist/tools/write-file.js +3 -1
  135. package/dist/ui/box.js +5 -1
  136. package/dist/ui/index.js +6 -6
  137. package/dist/ui/md-formatter.js +33 -33
  138. package/dist/ui/output.js +5 -5
  139. package/dist/ui/renderer.js +10 -15
  140. package/dist/ui/table.js +1 -1
  141. package/package.json +48 -48
  142. package/dist/cli/plugin-commands.js +0 -36
  143. package/dist/cli/run-result.js +0 -22
  144. package/dist/core/version.js +0 -24
  145. package/dist/modules/artifacts/store.js +0 -61
  146. package/dist/modules/browser/bridge-client.js +0 -199
  147. package/dist/modules/browser/bridge-path.js +0 -10
  148. package/dist/modules/browser/driver.js +0 -136
  149. package/dist/modules/context/chunk-query.js +0 -100
  150. package/dist/modules/context/fact-extractor.js +0 -162
  151. package/dist/modules/context/history.js +0 -15
  152. package/dist/modules/execution/audit-runners.js +0 -152
  153. package/dist/modules/execution/execution-plugin.js +0 -272
  154. package/dist/modules/execution/plan-tool.js +0 -508
  155. package/dist/modules/execution/windows-commands.js +0 -41
  156. package/dist/modules/indexer/project-profile.js +0 -183
  157. package/dist/modules/lsp/check-tool.js +0 -58
  158. package/dist/modules/lsp/command.js +0 -60
  159. package/dist/modules/lsp/probe.js +0 -76
  160. package/dist/modules/lsp/project-root.js +0 -32
  161. package/dist/modules/lsp/startup-check.js +0 -141
  162. package/dist/modules/processes/detect.js +0 -34
  163. package/dist/modules/skills/matcher.js +0 -27
  164. package/dist/modules/updater/module.js +0 -116
  165. package/dist/tools/chunk-query.js +0 -99
  166. package/dist/tools/download-file.js +0 -116
  167. package/dist/tools/enable-tools.js +0 -58
  168. package/dist/tools/hidden-tools-block.js +0 -37
  169. package/dist/ui/line-editor.js +0 -703
  170. package/dist/ui/line-math.js +0 -69
  171. package/dist/ui/plan-view.js +0 -103
@@ -3,7 +3,6 @@ import { Logger } from "../logger/app-logger";
3
3
  import { OpenAICompatProvider } from "../llm/openai-compat";
4
4
  import { ModelLoader } from "../llm/model-loader";
5
5
  import { ToolRegistry, registerAllTools } from "../tools/index";
6
- import { buildHiddenToolsBlock } from "../tools/hidden-tools-block";
7
6
  import { ToolExecutor } from "../tools/executor";
8
7
  import { ModuleRegistry } from "../modules/registry";
9
8
  import { PluginManager } from "../modules/plugins/manager";
@@ -14,22 +13,19 @@ import { ContextManager } from "../modules/context/manager";
14
13
  import { TokenCounter } from "../llm/token-counter";
15
14
  import { HallucinationDetector } from "../modules/hallucination/detector";
16
15
  import { ExecutionModule } from "../modules/execution/module";
17
- import { SessionStore, SessionManager, SessionModule } from "../modules/session/index";
16
+ import { SessionStore, SessionManager, SessionModule, } from "../modules/session/index";
18
17
  import { UserProfile } from "../modules/user-profile/profile";
19
18
  import { SkillsLoader, SkillsModule } from "../modules/skills/index";
20
19
  import { BrowserModule } from "../modules/browser/index";
21
- import { LspModule, DEFAULT_LSP_CONFIG } from "../modules/lsp/index";
22
- import { runStartupHealthCheck } from "../modules/lsp/startup-check";
20
+ import { LspModule } from "../modules/lsp/index";
23
21
  import { IndexerModule } from "../modules/indexer/index";
24
22
  import { MCPModule } from "../modules/mcp/index";
25
23
  import { MemoryModule } from "../modules/memory/module";
26
- import { MemoryStore } from "../modules/memory/store";
27
24
  import { setLocale } from "../i18n/index";
28
25
  import { Agent } from "./agent";
29
26
  import { homedir } from "os";
30
27
  import { join, resolve } from "path";
31
28
  import { existsSync, readFileSync, writeFileSync } from "fs";
32
- import { readMmaVersion } from "./version";
33
29
  export function buildSystemInfo(config, baseDir, profileCompressed) {
34
30
  const now = new Date().toISOString().replace("T", " ").slice(0, 19);
35
31
  const isWin = profileCompressed.toLowerCase().includes("win32");
@@ -46,20 +42,12 @@ export function buildSystemInfo(config, baseDir, profileCompressed) {
46
42
  // files and tests (observed: model wasted 10+ iterations installing tsx
47
43
  // instead of running `bun file.ts`).
48
44
  lines.push(`Runtime: Bun is available — run TypeScript directly with "bun <file.ts>" and tests with "bun test" (no tsx/ts-node/npm install needed for that).`);
49
- lines.push(`Bash: use "workdir" param instead of "cd dir && cmd". One command per call. Long-running processes: pass "background: true" (id immediately), otherwise auto-backgrounded after a few seconds — check with process_log.`, `DEVELOPMENT RULES (strict): 1) install deps BEFORE writing source (npm/pip/cargo, verify lockfile exists; never import uninstalled packages); 2) framework/toolkit init BEFORE app code; 3) follow plan sequentially, after each step verify deliverables exist with real content, then "plan update step=N status=done"; 4) verify work on disk + command output — don't assume success; 5) no premature work (no files/imports for future steps); 6) stuck after 2+ failures: STOP, try a different approach, write files directly, ask the user.`, `VERIFY EVERY WRITE: after write_file or edit_file, if the tool result contains NO [LSP errors], [LSP warnings], [Syntax check failed], or [Project typecheck failed] feedback, call the "lsp_check" tool on the file you just wrote BEFORE marking the step done. Never assume a written file is valid — prove it.`, `PLAN QUALITY: each step = CONCRETE deliverables (exact file paths with extensions, exact packages, exact commands). Vague steps ("Setup the project") forbidden. Cover init → deps → framework → code → verification. 5-8 steps.`, `For "check/fix errors" tasks, each verification step must name the exact command that proves the errors are gone — "bun run build", "bun test", or the "lsp_check" tool — and the step is done only after that check reports clean.`);
45
+ lines.push(`Bash: use "workdir" param instead of "cd dir && cmd". One command per call. Long-running processes: pass "background: true" (id immediately), otherwise auto-backgrounded after a few seconds — check with process_log.`, `DEVELOPMENT RULES (strict): 1) install deps BEFORE writing source (npm/pip/cargo, verify lockfile exists; never import uninstalled packages); 2) framework/toolkit init BEFORE app code; 3) follow plan sequentially, after each step verify deliverables exist with real content, then "plan update step=N status=done"; 4) verify work on disk + command output — don't assume success; 5) no premature work (no files/imports for future steps); 6) stuck after 2+ failures: STOP, try a different approach, write files directly, ask the user.`, `PLAN QUALITY: each step = CONCRETE deliverables (exact file paths with extensions, exact packages, exact commands). Vague steps ("Setup the project") forbidden. Cover init → deps → framework → code → verification. 5-8 steps.`);
50
46
  if (config.autoPlan) {
51
47
  lines.push(`Plan rule (MANDATORY): any task creating files, installing packages, or requiring multiple actions MUST create a plan with the "plan" tool BEFORE starting. Each step = a concrete deliverable.`);
52
48
  }
53
- // When a bug is described in terms of runtime behavior (what happens when
54
- // the app runs), the fix is only provable by REPRODUCING it — running the
55
- // app/build/browser and comparing against actual output. The model decides
56
- // when this applies (no keyword classification). Stale dev servers started
57
- // before a config/deps change keep the OLD pipeline in memory and still
58
- // throw the original error (observed: old vite on 5173-5176 kept failing
59
- // postcss after the fix was on disk, while a fresh server on 5177 was
60
- // clean) — the fix is only real when the USER's running server is clean.
61
- lines.push(`Runtime verification: when a bug is described in terms of runtime behavior (what happens when the app runs), reproduce it — run the app / build / browser tool — and confirm the fix against actual runtime output before calling "plan update step=N status=done". Check existing servers first with process_list/process_log: a stale dev server started BEFORE your change still runs the old pipeline and keeps failing even after the files on disk are fixed. Restart or kill it (process_kill) and verify the exact endpoint/port the user reported — a fresh server on a new port does NOT prove the user's error is gone.`);
62
- const hasMCP = config.mcpServers && Object.values(config.mcpServers).some((s) => s.enabled !== false);
49
+ const hasMCP = config.mcpServers &&
50
+ Object.values(config.mcpServers).some((s) => s.enabled !== false);
63
51
  if (hasMCP) {
64
52
  lines.push(`MCP servers are available — use the named MCP tools (prefixed mcp__) to query external services.`);
65
53
  }
@@ -67,7 +55,9 @@ export function buildSystemInfo(config, baseDir, profileCompressed) {
67
55
  }
68
56
  export async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
69
57
  const dir = configDir || join(homedir(), ".mma");
70
- const projectConfigPath = projectDir ? join(projectDir, ".mmrc") : join(process.cwd(), ".mmrc");
58
+ const projectConfigPath = projectDir
59
+ ? join(projectDir, ".mmrc")
60
+ : join(process.cwd(), ".mmrc");
71
61
  const config = loadConfig({ configDir: dir, projectConfigPath });
72
62
  setLocale(config.locale);
73
63
  // Update global audit notifier with config
@@ -136,9 +126,7 @@ export async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplet
136
126
  const skillsBudget = Math.floor(config.contextWindow * config.skills.budget);
137
127
  const skillsModule = new SkillsModule(availableSkills, skillsBudget);
138
128
  const toolRegistry = new ToolRegistry();
139
- registerAllTools(toolRegistry, skillsModule, {
140
- enableOnDemand: config.tools?.enableOnDemand,
141
- });
129
+ registerAllTools(toolRegistry, skillsModule);
142
130
  const pluginManager = new PluginManager();
143
131
  const systemInfoContent = buildSystemInfo(config, baseDir, profile.compress());
144
132
  const systemInfoPrompt = {
@@ -165,17 +153,6 @@ export async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplet
165
153
  sessionManager.create();
166
154
  }
167
155
  const tokenCounter = new TokenCounter(config.model);
168
- // Mutable set of active tool tags, shared between the agent loop and the
169
- // `enable_tools` tool. The loop re-reads it every iteration to recompute the
170
- // LLM-visible tool set; enable_tools pushes tags into it. When on-demand
171
- // enabling is disabled the tag set stays empty, which restores the legacy
172
- // all-tools behavior (getAllForLLM returns everything for empty tags).
173
- const enableOnDemand = config.tools?.enableOnDemand !== false;
174
- const activeToolTags = enableOnDemand
175
- ? config.tools?.defaultTags
176
- ? [...config.tools.defaultTags]
177
- : []
178
- : [];
179
156
  const contextManager = new ContextManager(config.contextWindow, config.contextBudget, tokenCounter);
180
157
  const toolCtx = {
181
158
  config,
@@ -183,7 +160,6 @@ export async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplet
183
160
  logger,
184
161
  exitOnComplete,
185
162
  contextManager,
186
- activeToolTags,
187
163
  sessionId: sessionManager.getActiveMeta()?.id,
188
164
  sessionContext: sessionManager.getSessionContext() ?? undefined,
189
165
  recursionDepth: 0,
@@ -230,8 +206,7 @@ export async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplet
230
206
  const mcpModule = new MCPModule(config);
231
207
  await mcpModule.initialize();
232
208
  moduleRegistry.register(mcpModule);
233
- const memoryStore = new MemoryStore(join(dir, "memory"));
234
- const memoryModule = new MemoryModule(memoryStore);
209
+ const memoryModule = new MemoryModule(join(dir, "memory"));
235
210
  moduleRegistry.register(memoryModule);
236
211
  if (config.browser.enabled) {
237
212
  const browserModule = new BrowserModule();
@@ -249,16 +224,6 @@ export async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplet
249
224
  lspPlugin.isBuiltin = true;
250
225
  pluginManager.register(lspPlugin);
251
226
  }
252
- // Startup health check: scan project for existing errors so the model
253
- // knows the baseline before it starts working. Skip for one-shot runs and
254
- // test environments. Started in the background (never awaited) so the REPL
255
- // banner is not blocked by `npx tsc` on the whole project; the Agent awaits
256
- // it before the first LLM call via `lazyPromptBlocks` (already resolved by
257
- // the time the user types in the interactive REPL).
258
- let startupCheckBlock = null;
259
- const startupCheckPromise = !exitOnComplete && process.env.NODE_ENV !== "test"
260
- ? runStartupHealthCheck(config.lsp ?? DEFAULT_LSP_CONFIG, baseDir)
261
- : Promise.resolve(null);
262
227
  const moduleTools = moduleRegistry.collectToolDefinitions();
263
228
  for (const tool of moduleTools) {
264
229
  toolRegistry.register(tool);
@@ -293,15 +258,8 @@ export async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplet
293
258
  const pluginLoader = new PluginLoader();
294
259
  const globalPluginsDir = join(homedir(), ".mma", "plugins");
295
260
  const projectPluginsDir = join(baseDir, ".mma", "plugins");
296
- const mmaVersion = readMmaVersion();
297
- pluginLoader.loadFromDir(globalPluginsDir, pluginManager, logger, {
298
- source: "global",
299
- mmaVersion,
300
- });
301
- pluginLoader.loadFromDir(projectPluginsDir, pluginManager, logger, {
302
- source: "project",
303
- mmaVersion,
304
- });
261
+ pluginLoader.loadFromDir(globalPluginsDir, pluginManager, logger);
262
+ pluginLoader.loadFromDir(projectPluginsDir, pluginManager, logger);
305
263
  contextManager.onCompact = (summary) => {
306
264
  const meta = sessionManager.getActiveMeta();
307
265
  if (!meta || !config.session.autoSave)
@@ -313,11 +271,6 @@ export async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplet
313
271
  timestamp: new Date().toISOString(),
314
272
  });
315
273
  };
316
- // Carry the active plan (id, progress, current step) into the compaction
317
- // summary so a 9B model doesn't re-create the plan from scratch right after
318
- // compaction (observed: ses_msvuao0h — plan_e07pb2 (1/6) discarded for a
319
- // fresh plan_xzq9xe the same iteration the old plan was still visible).
320
- contextManager.setPlanSummaryProvider(() => execModule.getPlanSummary());
321
274
  const agentsMdBlocks = [];
322
275
  const skipAgentsMd = noAgentsMd === true;
323
276
  if (!skipAgentsMd) {
@@ -342,7 +295,7 @@ export async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplet
342
295
  }
343
296
  const promptBlocks = [
344
297
  systemInfoPrompt,
345
- ...moduleRegistry.collectPromptBlocks(["indexer"]),
298
+ ...moduleRegistry.collectPromptBlocks(),
346
299
  ...agentsMdBlocks,
347
300
  ];
348
301
  const agentDeps = {
@@ -354,7 +307,6 @@ export async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplet
354
307
  hallucinationDetector,
355
308
  logger,
356
309
  baseDir,
357
- toolTags: activeToolTags,
358
310
  promptBlocks,
359
311
  getDynamicPromptBlocks: () => {
360
312
  const blocks = [];
@@ -364,29 +316,10 @@ export async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplet
364
316
  const skillsBlock = skillsModule.getSystemPromptBlock();
365
317
  if (skillsBlock)
366
318
  blocks.push(skillsBlock);
367
- const mapBlock = indexerModule.getSystemPromptBlock();
368
- if (mapBlock)
369
- blocks.push(mapBlock);
370
- const hiddenToolsBlock = buildHiddenToolsBlock(toolRegistry.getAll(), activeToolTags);
371
- if (hiddenToolsBlock) {
372
- blocks.push({
373
- content: hiddenToolsBlock,
374
- priority: "low",
375
- essential: false,
376
- estimatedTokens: Math.ceil(hiddenToolsBlock.length / 4),
377
- });
378
- }
379
319
  return blocks;
380
320
  },
381
321
  finalAudit: () => execModule.runFinalAudit(),
382
- lazyPromptBlocks: async () => {
383
- if (startupCheckBlock)
384
- return [startupCheckBlock];
385
- startupCheckBlock = (await startupCheckPromise) ?? null;
386
- return startupCheckBlock ? [startupCheckBlock] : [];
387
- },
388
322
  sessionManager,
389
- memoryStore,
390
323
  exitOnComplete,
391
324
  };
392
325
  const agent = new Agent(agentDeps);
@@ -1,2 +1,2 @@
1
- export { PromptBuilder } from "./prompt-builder";
2
- export { Agent } from "./agent";
1
+ export { PromptBuilder } from './prompt-builder';
2
+ export { Agent } from './agent';
@@ -4,10 +4,6 @@ const PRIORITY_ORDER = {
4
4
  normal: 2,
5
5
  low: 3,
6
6
  };
7
- function blockLabel(content) {
8
- const firstLine = content.split("\n")[0].trim();
9
- return firstLine.length > 70 ? firstLine.slice(0, 67) + "..." : firstLine;
10
- }
11
7
  export class PromptBuilder {
12
8
  blocks = [];
13
9
  budget;
@@ -37,40 +33,23 @@ export class PromptBuilder {
37
33
  let usedTokens = 0;
38
34
  const included = [];
39
35
  const excluded = [];
40
- const blocks = [];
41
36
  for (const block of essential) {
42
37
  included.push(block.content);
43
38
  usedTokens += block.estimatedTokens;
44
- blocks.push({
45
- label: blockLabel(block.content),
46
- priority: block.priority,
47
- essential: true,
48
- tokens: block.estimatedTokens,
49
- included: true,
50
- });
51
39
  }
52
40
  for (const block of nonEssential) {
53
41
  const tokens = block.estimatedTokens;
54
- const fits = usedTokens + tokens <= this.budget;
55
- if (fits) {
42
+ if (usedTokens + tokens <= this.budget) {
56
43
  included.push(block.content);
57
44
  usedTokens += tokens;
58
45
  }
59
46
  else {
60
47
  excluded.push(block.content);
61
48
  }
62
- blocks.push({
63
- label: blockLabel(block.content),
64
- priority: block.priority,
65
- essential: false,
66
- tokens,
67
- included: fits,
68
- });
69
49
  }
70
50
  return {
71
- prompt: included.join("\n\n"),
51
+ prompt: included.join('\n\n'),
72
52
  excluded,
73
- blocks,
74
53
  };
75
54
  }
76
55
  }
@@ -118,56 +118,14 @@ export class SessionLogger {
118
118
  iteration,
119
119
  });
120
120
  }
121
- logCompaction(info) {
121
+ logCompaction(content, iteration, contextTokens, contextLimit) {
122
122
  this.session?.appendLog({
123
123
  ts: new Date().toISOString(),
124
124
  type: "compaction",
125
- content: `${info.reason}, iteration ${info.iteration}`,
126
- iteration: info.iteration,
127
- reason: info.reason,
128
- tokensBefore: info.tokensBefore,
129
- tokensAfter: info.tokensAfter,
130
- qualityBefore: info.qualityBefore,
131
- qualityAfter: info.qualityAfter,
132
- messagesBefore: info.messagesBefore,
133
- messagesAfter: info.messagesAfter,
134
- removedTurns: info.removedTurns,
135
- keptTurns: info.keptTurns,
136
- summary: info.summary,
137
- });
138
- }
139
- logContext(info) {
140
- this.session?.appendLog({
141
- ts: new Date().toISOString(),
142
- type: "context",
143
- content: info.kind === "start"
144
- ? "context snapshot at session start"
145
- : `context at iteration ${info.iteration}`,
146
- iteration: info.iteration,
147
- window: info.window,
148
- systemBudget: info.systemBudget,
149
- reserveBudget: info.reserveBudget,
150
- historyBudget: info.historyBudget,
151
- systemTokens: info.systemTokens,
152
- toolTokens: info.toolTokens,
153
- contextTokens: info.tokens,
154
- quality: info.quality,
155
- messageCount: info.messageCount,
156
- compactionCount: info.compactionCount,
157
- iterationsSinceCompaction: info.iterationsSinceCompaction,
158
- blocks: info.blocks,
159
- });
160
- }
161
- logLlmUsage(iteration, usage) {
162
- this.session?.appendLog({
163
- ts: new Date().toISOString(),
164
- type: "llm_usage",
125
+ content,
165
126
  iteration,
166
- promptTokens: usage.promptTokens,
167
- completionTokens: usage.completionTokens,
168
- totalTokens: usage.totalTokens,
169
- source: usage.source,
170
- durationMs: usage.durationMs,
127
+ ...(contextTokens !== undefined ? { contextTokens } : {}),
128
+ ...(contextLimit !== undefined ? { contextLimit } : {}),
171
129
  });
172
130
  }
173
131
  logError(message) {
package/dist/i18n/en.json CHANGED
@@ -28,7 +28,6 @@
28
28
  "error.response_blocked": "Response blocked: {reason}",
29
29
  "error.max_iters": "Max iterations ({max}) reached",
30
30
  "error.empty_response": "Model returned an empty response after retries",
31
- "error.audit_failed": "Task could not be verified as complete: {summary}",
32
31
  "error.grep_failed": "Grep failed: {message}",
33
32
  "error.search_failed": "Search failed: {message}",
34
33
  "error.fetch_failed": "Fetch failed: {message}",
@@ -87,12 +86,9 @@
87
86
  "tool.friendly.web_search": "Web search",
88
87
  "tool.friendly.web_fetch": "Fetching page",
89
88
  "tool.friendly.web_browse": "Browsing page",
90
- "tool.friendly.download_file": "Downloading file",
91
89
  "tool.web_fetch_result": "Fetched page: {url} — {chars} chars, {lines} lines{truncated}",
92
90
  "tool.web_browse_result": "Browsed page: {url} — {chars} chars, {lines} lines{truncated}",
93
91
  "tool.web_search_result": "Search results for \"{query}\" — {count} results",
94
- "tool.downloaded": "Downloaded {url} \u2192 {path} ({size} bytes, {type})",
95
- "tool.download_too_large": "Download blocked: file exceeds the {max} bytes limit",
96
92
  "tool.friendly.browser": "Browser",
97
93
  "tool.friendly.subagent": "Sub-agent task",
98
94
  "tool.friendly.question": "Question to user",
@@ -100,10 +96,8 @@
100
96
  "tool.friendly.search_history": "Searching history",
101
97
  "tool.friendly.pipeline_run": "Running pipeline",
102
98
  "tool.friendly.mcp_call": "MCP call",
103
- "tool.friendly.lsp_check": "Checking code",
104
99
  "tool.truncated": "[Truncated: {tokens} tokens removed]",
105
100
  "tool.subagent_queued": "Sub-agent task queued: {task}",
106
- "tool.subagent_artifact": "Sub-agent completed. Full result saved to artifact: {path}\nIterations: {iterations}\nSummary:\n{summary}",
107
101
  "tool.pipeline_started": "Pipeline \"{name}\" execution started. Pipeline engine is a stub \u2014 run dispatched.",
108
102
  "tool.mcp_call": "MCP call: {server}/{tool} with {args}",
109
103
  "tool.action_required": "Action is required.",
@@ -124,8 +118,6 @@
124
118
  "tool.question.unanswered": "Unanswered",
125
119
  "tool.question.answered": "User has answered your questions: {formatted}. You can now continue with the user's answers in mind.",
126
120
  "tool.name_or_task": "Provide either \"name\" or \"task\" parameter",
127
- "tool.chunk_query_no_query": "chunk_query: a query string is required.",
128
- "tool.chunk_query_no_input": "chunk_query: provide input_path or text.",
129
121
  "tool.invalid_params": "Invalid parameters",
130
122
  "tool.skill_budget": "Skill \"{name}\" loaded ({tokens} tokens, {remaining} remaining in skills budget). Skill content is now in system prompt — no need to reload after context compaction.",
131
123
  "tool.skill_available_hint": "Available skills",
@@ -143,7 +135,6 @@
143
135
  "proc.started": "Started background process {id} (PID {pid}).\nCommand: {command}",
144
136
  "proc.promoted_hint": "Command still running after {ms} ms — moved to the background",
145
137
  "proc.manage_hint": "Check output: process_log id={id}. Stop it: process_kill id={id}. List all: process_list.",
146
- "proc.output_preview": "First output:\n{lines}",
147
138
  "proc.none": "No background processes running.",
148
139
  "proc.not_found": "Process not found: {id}",
149
140
  "proc.killed": "Process {id} (PID {pid}) killed.",
@@ -166,20 +157,12 @@
166
157
  "plan.title_steps": "Plan \"{title}\" created with {count} steps",
167
158
  "plan.step_marked": "Step {step} marked as {status}",
168
159
  "plan.aborted": "Plan aborted",
169
- "plan.completed_archived": "Plan {id} is complete ({done}/{total} steps) — archived. You may create a new plan for new work (plan create), or reply with your final answer.",
170
160
  "plan.unknown_action": "Unknown plan action: {action}",
171
161
  "plan.updated": "Plan updated: {title} ({steps} steps)",
172
162
  "plan.acknowledged": "Plan {action}: acknowledged",
173
163
  "plan.step_status": "Step {step}: {status}",
174
164
  "plan.no_active": "No active plan",
175
165
  "plan.step_not_found": "Step not found",
176
- "plan.step_already_done": "Step {step} is already done — nothing to do. Plan progress:",
177
- "plan.order_blocked": "Cannot mark step {step} done: step {first} (\"{desc}\") is not finished yet. Complete earlier steps first, or mark step {first} status=skipped if it is not needed.",
178
- "plan.deliverables_missing": "Cannot mark step {step} done: the files it names do not exist yet: {files}. Create these files first (or mark the step status=skipped if they are not actually needed).",
179
- "plan.kinds_mismatch": "kinds array length must match steps",
180
- "plan.kinds_invalid": "Invalid step kind(s): {kinds}. Use \"create\" or \"delete\".",
181
- "plan.kinds_not_array": "kinds must be an array of \"create\" or \"delete\"",
182
- "plan.deliverables_remain": "Cannot mark step {step} done: the files it names still exist: {files}. This step is kind=delete — delete these files first (or set status=skipped if they should stay).",
183
166
  "plan.show_header": "Plan status:",
184
167
  "plan.show_empty": "(plan has no steps)",
185
168
  "plan.list_header": "Plans:",
@@ -189,14 +172,9 @@
189
172
  "plan.switched": "Switched to plan {id}: {title}",
190
173
  "plan.replanned": "Plan re-planned: {kept} completed steps kept, {steps} new steps added",
191
174
  "plan.replan_no_steps": "Provide new steps for re-planning",
192
- "plan.active_in_progress": "Cannot create a new plan: active plan {id} already has progress ({done}/{total} done, current: step {current}). Resume it — use \"plan show\" to view, then continue working. To replace it, call \"plan abort\" first, then \"plan create\" again.",
193
- "plan.id_ignored": "note: plan ids are auto-generated; use \"plan switch\" to activate an existing plan by id.",
194
- "plan.existing_fresh": "note: the previous active plan had no progress and was preserved as a draft.",
195
175
  "todo.added": "Added {count} todo(s): {items}",
196
176
  "todo.marked_done": "Marked {count} item(s) as done",
197
177
  "todo.no_active": "No active todos",
198
- "todo.no_items": "No todo items specified — provide items to mark done",
199
- "todo.subtask_not_found": "No matching sub-task(s) found for: {items}",
200
178
  "todo.unknown_action": "Unknown todo action: {action}",
201
179
  "todo.acknowledged": "Todo acknowledged",
202
180
  "verify.passed": "Verification passed",
@@ -206,14 +184,6 @@
206
184
  "verify.script_passed": "Script '{script}' passed",
207
185
  "verify.script_failed": "Script '{script}' failed: {message}",
208
186
  "verify.syntax_error": "Syntax error in: {path}",
209
- "verify.no_files": "Step {step} has no named files to verify — run a real check instead (bash: bun run build / bun test / lsp_check) and confirm the result.",
210
- "lsp.unavailable": "static checks are unavailable (server not found). Verify via the project's own build/test instead.",
211
- "lsp.check_disabled": "LSP checks are disabled in the config.",
212
- "lsp.check_no_path": "Provide a path (file or directory) to check.",
213
- "lsp.check_notfound": "Path not found: {path}",
214
- "lsp.check_unsupported": "No LSP server configured for: {path}",
215
- "lsp.check_clean": "No errors or warnings detected ({count} file(s) checked).",
216
- "lsp.startup_header": "[Existing project errors (checked at session start) — fix these before continuing]:",
217
187
  "cli.description": "Micro Models Agent \u2014 AI coding agent for small models",
218
188
  "cli.init": "Run interactive setup wizard",
219
189
  "cli.config_saved": "Configuration saved to ~/.mma/config.json",
@@ -326,13 +296,6 @@
326
296
  "cli.security.recommended_for": "Recommended for",
327
297
  "cli.yes": "Yes",
328
298
  "cli.no": "No",
329
- "cli.plugins.description": "Manage plugins",
330
- "cli.plugins.list": "List loaded plugins (name, version, source)",
331
- "cli.plugins.all": "Include builtin plugins",
332
- "cli.plugins.only_external": "(builtin plugins omitted — use --all to show them)",
333
- "cli.plugins.none": "No plugins loaded",
334
- "cli.plugins.header": "Plugins: {count} loaded (MMA v{mma})",
335
- "cli.plugins.builtin_mark": "●",
336
299
  "repl.help": "Show available commands",
337
300
  "repl.help_usage": "Usage: /help",
338
301
  "repl.exit": "Exit the REPL",
@@ -347,8 +310,6 @@
347
310
  "repl.reasoning_usage": "Usage: /reasoning",
348
311
  "repl.status": "Show agent status",
349
312
  "repl.status_usage": "Usage: /status",
350
- "repl.plugins": "List loaded plugins",
351
- "repl.plugins_usage": "Usage: /plugins [--all]",
352
313
  "repl.sessions": "List all sessions (* active)",
353
314
  "repl.sessions_usage": "Usage: /sessions",
354
315
  "repl.new": "Create a new session",
@@ -375,7 +336,6 @@
375
336
  "repl.skill_unknown_sub": "Unknown skill subcommand: {subcmd}",
376
337
  "repl.skill_usage": "Usage: /skill [list|loaded|load|unload|search]",
377
338
  "repl.agent": "Agent: ",
378
- "repl.you": "You: ",
379
339
  "repl.interrupt": "Interrupted (Esc)",
380
340
  "repl.title": "MMA REPL v{version}",
381
341
  "repl.model": "Model:",
@@ -393,10 +353,6 @@
393
353
  "repl.skills_label": "Skills:",
394
354
  "repl.plugins_label": "Plugins:",
395
355
  "repl.mcp_label": "MCP:",
396
- "repl.lsp_label": "LSP:",
397
- "repl.lsp_timeout": "timeout",
398
- "repl.lsp_failed": "did not start",
399
- "repl.lsp_unknown": "unknown",
400
356
  "repl.work_dir": "Dir:",
401
357
  "repl.agents_label": "Instructions:",
402
358
  "repl.not_found": "not found",
@@ -471,8 +427,6 @@
471
427
  "exec.tool_errors_recovery": "Tool {tool} has failed {count} times in a row. Try an alternative: create files directly via write_file, use a different command, or if nothing works — skip this step via plan update step=N status=skipped with a note explaining why.",
472
428
  "exec.repetitive_tool": "Called {tool} {count} times with identical arguments and result. Try a different approach — create files directly, change arguments, or check process status via process_log.",
473
429
  "exec.consecutive_failures_recovery": "{count} consecutive tool failures. Create files directly via write_file instead of terminal commands. Check that dependencies are installed (npm install). Do not run build/tests until all files are created.",
474
- "exec.read_only_loop": "No write/exec for {count} tool calls — the agent is only reading/exploring.",
475
- "exec.read_only_loop_recovery": "{count} consecutive read-only tool calls (read_file/glob/grep/browser) with no writes. STOP exploring and make the edit the task requires: read the file, then call write_file or edit_file. If you cannot finish the task, ask the user instead of re-reading the same files.",
476
430
  "exec.plan_warning": "Current plan step {step} is \"{description}\", but {tool} is being called for files outside this step. Complete the current step first, then call plan update step={step} status=done before moving to the next step.",
477
431
  "exec.plan_blocked": "{max} consecutive calls outside the current step. Finish step {step} before proceeding — other steps should wait until this one is complete.",
478
432
  "exec.off_track": "Step {stepId} — \"{description}\" — but you are using {tool} on a different path. Return to the current step.",
@@ -482,18 +436,13 @@
482
436
  "exec.step_gate_ok": "[\u2713] Step {step} completed and verified. MOVING to step {nextStep}: \"{nextDesc}\". Work ONLY on this step.",
483
437
  "exec.step_gate_last": "[\u2713] Step {step} completed — that was the final step. Verify everything together and provide the final answer.]",
484
438
  "exec.audit_pass": "[\u2713] Task complete: {done}/{total} steps done, {files} files verified",
485
- "exec.audit_pending": "[\u2717] Task incomplete: {done}/{total} steps done — remaining steps are not marked done",
486
439
  "exec.audit_fail": "[\u2717] Task incomplete: {done}/{total} steps done, {files} files missing",
487
- "exec.audit_leftovers": "[\u2717] Task incomplete: {done}/{total} steps done, {files} files from delete-steps still exist",
488
- "exec.audit_fail_tests": "[\u2717] Task incomplete: {done}/{total} steps done, tests FAILING: {failed} failed / {passed} passed — {detail}",
489
440
  "exec.audit_fail_typecheck": "[\u2717] Task incomplete: {done}/{total} steps done, {missing} files missing, typecheck error: {typeError}",
490
441
  "exec.audit_incomplete": "[\u26a0 Final audit incomplete: {summary}. Task is NOT finished \u2014 continue working. Remaining steps: {steps}]",
491
442
  "exec.mass_edit_warning": "\u26a0\ufe0f Plan affects {count} files \u2014 review the full list before proceeding.",
492
443
  "exec.escalation": "\n\n\u26a0\ufe0f Agent stuck on step {stepId} ({description}). Escalating to user \u2014 please provide guidance.",
493
444
  "exec.hints": "\n[Hints]\n{hints}",
494
445
  "exec.file_rewrite_warning": "\u26a0\ufe0f File {file} has been rewritten {count} times. Consider a different approach \u2014 the current fix strategy is not working.",
495
- "exec.forbidden_cmd": "STOP using \"{cmd}\" via the bash tool \u2014 it is not a native Windows cmd.exe command and has failed repeatedly this session. Use the dedicated tool instead: grep \u2192 the grep tool, ls/dir \u2192 list_dir, find \u2192 glob, rm \u2192 delete_file, sed \u2192 edit_file, touch \u2192 write_file, which \u2192 `where`, cp/mv \u2192 move_file, diff \u2192 read_file. Do NOT call bash for this purpose again.",
496
- "exec.npm_exec_hint": "\"could not determine executable to run\" \u2014 no \"bin\" for that package/script. Use \"npm run <script>\" (script must exist in package.json) or \"bunx <pkg>\" for a package that declares a bin.",
497
446
  "hall.max_retries_exhausted": "Model returned empty or insufficient responses after multiple retries",
498
447
  "hall.short_response": "Response too short or empty",
499
448
  "hall.repetitive": "Response too repetitive ({pct}% overlap)",
@@ -519,17 +468,11 @@
519
468
  "browser.no_page_short": "No page",
520
469
  "browser.no_elements": "(no interactive elements on page)",
521
470
  "browser.more_elements": "... and more elements not shown. Use scroll or search to find others.",
522
- "browser.content_header": "Content:",
523
- "browser.console_header": "Console:",
524
- "browser.network_errors_header": "Network errors:",
525
- "browser.truncated": "... (truncated)",
526
471
  "pipeline.invalid": "Invalid pipeline: name and steps required",
527
472
  "pipeline.step_missing_fields": "Step missing required fields (id, agent, prompt): {step}",
528
473
  "pipeline.circular": "Circular dependency: {stepId}",
529
474
  "plugin.loaded": "Loaded plugin: {name}",
530
475
  "plugin.skipped": "Skipped incompatible plugin: {entry} ({message})",
531
- "plugin.incompatible": "Skipped plugin {name}: requires MMA v{min}, current is v{current}",
532
- "plugin.dedup_older": "Plugin {name} v{version} skipped: a newer version is already loaded",
533
476
  "migration.detected": "[MMA] Detected old config. {summary}",
534
477
  "migration.summary": "[MMA] {summary}",
535
478
  "migration.config_bak": "- config \u2192 config.json.bak",
@@ -540,7 +483,6 @@
540
483
  "ui.success_prefix": "\u2713 ",
541
484
  "ui.warning_prefix": "\u26a0 ",
542
485
  "ui.thinking": "Thinking…",
543
- "ui.step_context": "step {id}: {desc}",
544
486
  "indexer.map_header": "Project map",
545
487
  "indexer.top_directories": "Top directories",
546
488
  "indexer.files": "Files",
@@ -554,10 +496,6 @@
554
496
  "indexer.not_indexed": "Project has not been indexed yet",
555
497
  "indexer.find_results": "Found {count} matching files:\n{results}",
556
498
  "indexer.no_matches": "No matching files for \"{query}\"",
557
- "indexer.duplicates": "Duplicate basenames (verify which file is the real source): {names}",
558
- "indexer.stack_deps": "deps",
559
- "indexer.stack_dev": "dev",
560
- "indexer.stack_scripts": "scripts",
561
499
  "tool.friendly.project_map": "Project map",
562
500
  "config.decryption_warning": "Warning: Failed to decrypt config: {error}",
563
501
  "config.encryption_warning": "Warning: Failed to encrypt config: {error}",
@@ -582,17 +520,6 @@
582
520
  "ctx.compactions": "compactions: {count}",
583
521
  "ctx.quality": "quality: {percent}%",
584
522
  "ctx.delta_pos": "ctx +{tokens}",
585
- "ctx.delta_neg": "ctx -{tokens} ",
586
- "ctx.delta_zero": "ctx +0",
587
- "updater.check_error": "[updater] update check failed: {error}",
588
- "updater.available": "[updater] Update available: {current} → {latest}. Run `npm install -g micro-models-agent` to upgrade.",
589
- "updater.installing": "[updater] Installing {latest} globally (current: {current})…",
590
- "updater.installed": "[updater] Installed {latest}. Restart MMA to use it (was {current}).",
591
- "updater.install_failed": "[updater] Failed to install {latest}: {error}. Update manually with `npm install -g micro-models-agent`.",
592
- "tools.enable_no_tags": "enable_tools requires at least one tag in the \"tags\" array.",
593
- "tools.enable_no_executor": "Tool executor is not available — cannot enumerate enabled tools.",
594
- "tools.enable_already_active": "Tool tags already active: {tags}.",
595
- "tools.enable_added": "Enabled tool tags: {tags}. Available tools now: {tools}",
596
- "tools.hidden_header": "Additional tools (enable on demand via enable_tools or route to subagent tool_tags):",
597
- "tool.friendly.enable_tools": "Enable tools"
523
+ "ctx.delta_neg": "ctx -{tokens}",
524
+ "ctx.delta_zero": "ctx ±0"
598
525
  }