micro-models-agent 0.52.1 → 0.54.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 (232) hide show
  1. package/README.md +358 -358
  2. package/dist/certification/certifications.json +494 -0
  3. package/dist/cli/commands.js +447 -0
  4. package/dist/cli/completer.js +167 -0
  5. package/dist/cli/index.js +2 -0
  6. package/dist/cli/main.js +153 -0
  7. package/dist/cli/plugin-commands.js +36 -0
  8. package/dist/cli/repl-commands.js +761 -0
  9. package/dist/cli/repl.js +702 -0
  10. package/dist/cli/run-result.js +33 -0
  11. package/dist/cli/security-commands.js +164 -0
  12. package/dist/cli/setup.js +237 -0
  13. package/dist/config/config.js +276 -0
  14. package/dist/config/defaults.js +141 -0
  15. package/dist/config/domains.js +179 -0
  16. package/dist/config/experts.js +15 -0
  17. package/dist/config/index.js +4 -0
  18. package/dist/config/security.js +213 -0
  19. package/dist/config/types.js +1 -0
  20. package/dist/core/agent-moe.js +102 -0
  21. package/dist/core/agent.js +1018 -0
  22. package/dist/core/bootstrap.js +481 -0
  23. package/dist/core/crash-handler.js +51 -0
  24. package/dist/core/environment.js +199 -0
  25. package/dist/core/index.js +2 -0
  26. package/dist/core/prompt-builder.js +76 -0
  27. package/dist/core/session-logger.js +251 -0
  28. package/dist/core/types.js +1 -0
  29. package/dist/core/version.js +26 -0
  30. package/dist/core/workspace.js +76 -0
  31. package/dist/i18n/en.json +679 -0
  32. package/dist/i18n/index.js +46 -0
  33. package/dist/i18n/ru.json +679 -0
  34. package/dist/index.js +22 -0
  35. package/dist/llm/image-utils.js +143 -0
  36. package/dist/llm/index.js +4 -0
  37. package/dist/llm/model-loader.js +78 -0
  38. package/dist/llm/openai-compat.js +497 -0
  39. package/dist/llm/orchestrator.js +200 -0
  40. package/dist/llm/provider.js +10 -0
  41. package/dist/llm/response.js +39 -0
  42. package/dist/llm/token-counter.js +39 -0
  43. package/dist/llm/types.js +1 -0
  44. package/dist/logger/app-logger.js +189 -0
  45. package/dist/logger/file-log.js +151 -0
  46. package/dist/logger/index.js +1 -0
  47. package/dist/main.js +304 -157
  48. package/dist/migration/backup.js +45 -0
  49. package/dist/migration/detect.js +50 -0
  50. package/dist/migration/index.js +2 -0
  51. package/dist/modules/artifacts/store.js +61 -0
  52. package/dist/modules/browser/actions.js +76 -0
  53. package/dist/modules/browser/bridge-client.js +199 -0
  54. package/dist/modules/browser/bridge-path.js +10 -0
  55. package/dist/modules/browser/bridge-server.mjs +202 -202
  56. package/dist/modules/browser/cookie-store.js +24 -0
  57. package/dist/modules/browser/driver.js +136 -0
  58. package/dist/modules/browser/index.js +7 -0
  59. package/dist/modules/browser/module.js +29 -0
  60. package/dist/modules/browser/session.js +342 -0
  61. package/dist/modules/browser/snapshot.js +148 -0
  62. package/dist/modules/browser/types.js +12 -0
  63. package/dist/modules/certification/cli.js +213 -0
  64. package/dist/modules/certification/fact-checker.js +82 -0
  65. package/dist/modules/certification/loader.js +106 -0
  66. package/dist/modules/certification/manifest.js +58 -0
  67. package/dist/modules/certification/runner.js +245 -0
  68. package/dist/modules/certification/scenarios.js +407 -0
  69. package/dist/modules/certification/types.js +1 -0
  70. package/dist/modules/context/chunk-query.js +100 -0
  71. package/dist/modules/context/fact-extractor.js +168 -0
  72. package/dist/modules/context/history.js +15 -0
  73. package/dist/modules/context/index.js +1 -0
  74. package/dist/modules/context/manager.js +440 -0
  75. package/dist/modules/execution/audit-runners.js +206 -0
  76. package/dist/modules/execution/auditor.js +218 -0
  77. package/dist/modules/execution/execution-plugin.js +431 -0
  78. package/dist/modules/execution/index.js +8 -0
  79. package/dist/modules/execution/module.js +625 -0
  80. package/dist/modules/execution/moe-executor.js +304 -0
  81. package/dist/modules/execution/plan-coverage.js +68 -0
  82. package/dist/modules/execution/plan-persister.js +46 -0
  83. package/dist/modules/execution/plan-store.js +196 -0
  84. package/dist/modules/execution/plan-tool.js +677 -0
  85. package/dist/modules/execution/plan-validator.js +153 -0
  86. package/dist/modules/execution/planner.js +94 -0
  87. package/dist/modules/execution/stuck-detector.js +746 -0
  88. package/dist/modules/execution/tracker.js +69 -0
  89. package/dist/modules/execution/types.js +1 -0
  90. package/dist/modules/execution/verifier.js +235 -0
  91. package/dist/modules/execution/windows-commands.js +41 -0
  92. package/dist/modules/hallucination/confidence.js +66 -0
  93. package/dist/modules/hallucination/consistency.js +26 -0
  94. package/dist/modules/hallucination/detector.js +47 -0
  95. package/dist/modules/hallucination/factual.js +169 -0
  96. package/dist/modules/hallucination/index.js +5 -0
  97. package/dist/modules/hallucination/js-identifiers.js +262 -0
  98. package/dist/modules/hallucination/llm-judge.js +101 -0
  99. package/dist/modules/index.js +5 -0
  100. package/dist/modules/indexer/cache.js +40 -0
  101. package/dist/modules/indexer/index.js +3 -0
  102. package/dist/modules/indexer/module.js +246 -0
  103. package/dist/modules/indexer/project-profile.js +183 -0
  104. package/dist/modules/indexer/walker.js +101 -0
  105. package/dist/modules/lsp/check-tool.js +58 -0
  106. package/dist/modules/lsp/client.js +389 -0
  107. package/dist/modules/lsp/command.js +60 -0
  108. package/dist/modules/lsp/config.js +135 -0
  109. package/dist/modules/lsp/index.js +3 -0
  110. package/dist/modules/lsp/module.js +260 -0
  111. package/dist/modules/lsp/probe.js +86 -0
  112. package/dist/modules/lsp/project-root.js +32 -0
  113. package/dist/modules/lsp/startup-check.js +144 -0
  114. package/dist/modules/lsp/types.js +1 -0
  115. package/dist/modules/mcp/client.js +399 -0
  116. package/dist/modules/mcp/index.js +3 -0
  117. package/dist/modules/mcp/module.js +142 -0
  118. package/dist/modules/mcp/registry.js +15 -0
  119. package/dist/modules/memory/index.js +1 -0
  120. package/dist/modules/memory/module.js +96 -0
  121. package/dist/modules/memory/search.js +42 -0
  122. package/dist/modules/memory/store.js +69 -0
  123. package/dist/modules/pipelines/engine.js +60 -0
  124. package/dist/modules/pipelines/index.js +3 -0
  125. package/dist/modules/pipelines/parser.js +56 -0
  126. package/dist/modules/pipelines/template.js +14 -0
  127. package/dist/modules/plugins/builtin/lint-on-write.js +334 -0
  128. package/dist/modules/plugins/builtin/notify.js +9 -0
  129. package/dist/modules/plugins/index.js +1 -0
  130. package/dist/modules/plugins/loader.js +70 -0
  131. package/dist/modules/plugins/manager.js +261 -0
  132. package/dist/modules/plugins/types.js +1 -0
  133. package/dist/modules/pricing/index.js +61 -0
  134. package/dist/modules/pricing/prices.js +129 -0
  135. package/dist/modules/processes/detect.js +34 -0
  136. package/dist/modules/processes/index.js +2 -0
  137. package/dist/modules/processes/registry.js +327 -0
  138. package/dist/modules/processes/runner.js +23 -0
  139. package/dist/modules/providers/create.js +22 -0
  140. package/dist/modules/providers/fallback.js +79 -0
  141. package/dist/modules/providers/health.js +46 -0
  142. package/dist/modules/providers/index.js +5 -0
  143. package/dist/modules/providers/manager.js +161 -0
  144. package/dist/modules/providers/presets.js +128 -0
  145. package/dist/modules/providers/registry.js +22 -0
  146. package/dist/modules/providers/types.js +1 -0
  147. package/dist/modules/registry.js +48 -0
  148. package/dist/modules/security/audit-log.js +136 -0
  149. package/dist/modules/security/audit-notifier.js +292 -0
  150. package/dist/modules/security/command-validator.js +219 -0
  151. package/dist/modules/security/content-scanner.js +53 -0
  152. package/dist/modules/security/data-sanitizer.js +89 -0
  153. package/dist/modules/security/encryption.js +242 -0
  154. package/dist/modules/security/index.js +14 -0
  155. package/dist/modules/security/network-validator.js +88 -0
  156. package/dist/modules/security/path-validator.js +203 -0
  157. package/dist/modules/security/rate-limiter.js +119 -0
  158. package/dist/modules/security/security-policies.js +531 -0
  159. package/dist/modules/security/session-encryption.js +210 -0
  160. package/dist/modules/security/session-isolation.js +95 -0
  161. package/dist/modules/session/index.js +3 -0
  162. package/dist/modules/session/manager.js +172 -0
  163. package/dist/modules/session/module.js +24 -0
  164. package/dist/modules/session/store.js +222 -0
  165. package/dist/modules/session/types.js +1 -0
  166. package/dist/modules/skills/index.js +2 -0
  167. package/dist/modules/skills/loader.js +72 -0
  168. package/dist/modules/skills/matcher.js +27 -0
  169. package/dist/modules/skills/module.js +129 -0
  170. package/dist/modules/types.js +1 -0
  171. package/dist/modules/updater/checker.js +96 -0
  172. package/dist/modules/updater/index.js +2 -0
  173. package/dist/modules/updater/module.js +116 -0
  174. package/dist/modules/user-profile/compressor.js +16 -0
  175. package/dist/modules/user-profile/index.js +1 -0
  176. package/dist/modules/user-profile/profile.js +68 -0
  177. package/dist/skills/builtin/git.md +36 -36
  178. package/dist/skills/builtin/typescript.md +35 -35
  179. package/dist/tools/approve.js +33 -0
  180. package/dist/tools/attach-image.js +101 -0
  181. package/dist/tools/bash.js +519 -0
  182. package/dist/tools/browser.js +115 -0
  183. package/dist/tools/chunk-query.js +100 -0
  184. package/dist/tools/create-dir.js +56 -0
  185. package/dist/tools/delete-file.js +63 -0
  186. package/dist/tools/download-file.js +117 -0
  187. package/dist/tools/edit-file.js +80 -0
  188. package/dist/tools/enable-tools.js +59 -0
  189. package/dist/tools/executor.js +154 -0
  190. package/dist/tools/file-info.js +47 -0
  191. package/dist/tools/filter-tools.js +17 -0
  192. package/dist/tools/glob-tool.js +27 -0
  193. package/dist/tools/grep-tool.js +125 -0
  194. package/dist/tools/hidden-tools-block.js +37 -0
  195. package/dist/tools/index.js +78 -0
  196. package/dist/tools/list-dir.js +49 -0
  197. package/dist/tools/load-skill.js +43 -0
  198. package/dist/tools/mcp-call.js +69 -0
  199. package/dist/tools/move-file.js +86 -0
  200. package/dist/tools/path-utils.js +101 -0
  201. package/dist/tools/pipeline-run.js +145 -0
  202. package/dist/tools/preview.js +2 -0
  203. package/dist/tools/process-kill.js +40 -0
  204. package/dist/tools/process-list.js +37 -0
  205. package/dist/tools/process-log.js +54 -0
  206. package/dist/tools/question.js +141 -0
  207. package/dist/tools/read-file.js +179 -0
  208. package/dist/tools/recall.js +118 -0
  209. package/dist/tools/registry.js +47 -0
  210. package/dist/tools/remember.js +68 -0
  211. package/dist/tools/scope-check.js +32 -0
  212. package/dist/tools/search-history.js +85 -0
  213. package/dist/tools/subagent.js +196 -0
  214. package/dist/tools/types.js +1 -0
  215. package/dist/tools/user-input.js +123 -0
  216. package/dist/tools/web-browse.js +87 -0
  217. package/dist/tools/web-fetch.js +119 -0
  218. package/dist/tools/web-search.js +105 -0
  219. package/dist/tools/write-file.js +82 -0
  220. package/dist/ui/box.js +77 -0
  221. package/dist/ui/colors.js +4 -0
  222. package/dist/ui/diff.js +178 -0
  223. package/dist/ui/index.js +6 -0
  224. package/dist/ui/line-editor.js +822 -0
  225. package/dist/ui/line-math.js +73 -0
  226. package/dist/ui/md-formatter.js +212 -0
  227. package/dist/ui/output.js +13 -0
  228. package/dist/ui/plan-view.js +103 -0
  229. package/dist/ui/renderer.js +259 -0
  230. package/dist/ui/spinner.js +70 -0
  231. package/dist/ui/table.js +144 -0
  232. package/package.json +50 -50
package/dist/main.js CHANGED
@@ -2659,7 +2659,11 @@ Fix the error and re-edit the file (a clean write clears the failure), or mark t
2659
2659
  "cli.cert_provider_key": "Provider API key (optional)",
2660
2660
  "cli.cert_context_window": "Context window size in tokens",
2661
2661
  "cli.cert_tags": "Comma-separated scenario tags (core, security, image, network, browser, shell, research)",
2662
+ "cli.cert_scenarios": "Comma-separated scenario ids to (re-)run (e.g. 3.5-data-pipeline); other results are preserved",
2663
+ "cli.cert_scenarios_unknown": "Unknown scenario(s): {ids}. Available: {available}",
2664
+ "cli.cert_partial_merge": "Preserved {kept} result(s) from the previous certification",
2662
2665
  "cli.cert_reps": "Default repetitions per scenario (overridden by scenario)",
2666
+ "cli.cert_timeout": "Per-rep timeout in ms (default 300000; overridden by scenario)",
2663
2667
  "cli.cert_force": "Re-run an existing certification",
2664
2668
  "cli.cert_clean": "Remove sandbox directories after a successful run",
2665
2669
  "cli.cert_security_required": "Security is disabled. Enable it first (e.g. `mma security set-policy balanced`) to run the security suite.",
@@ -3382,7 +3386,11 @@ var init_ru = __esm(() => {
3382
3386
  "cli.cert_provider_key": "API-ключ провайдера (необязательно)",
3383
3387
  "cli.cert_context_window": "Размер контекстного окна в токенах",
3384
3388
  "cli.cert_tags": "Теги сценариев через запятую (core, security, image, network, browser, shell, research)",
3389
+ "cli.cert_scenarios": "ID сценариев через запятую для (пере)запуска (напр. 3.5-data-pipeline); остальные результаты сохраняются",
3390
+ "cli.cert_scenarios_unknown": "Неизвестные сценарии: {ids}. Доступны: {available}",
3391
+ "cli.cert_partial_merge": "Сохранено результатов из предыдущей сертификации: {kept}",
3385
3392
  "cli.cert_reps": "Повторов по умолчанию на сценарий (переопределяется сценарием)",
3393
+ "cli.cert_timeout": "Таймаут на реп в мс (по умолчанию 300000; переопределяется сценарием)",
3386
3394
  "cli.cert_force": "Перепрогнать существующую сертификацию",
3387
3395
  "cli.cert_clean": "Удалить песочницы после успешного прогона",
3388
3396
  "cli.cert_security_required": "Безопасность отключена. Включите её (например `mma security set-policy balanced`), чтобы запустить security-сьют.",
@@ -13305,7 +13313,7 @@ ${warnLine}
13305
13313
  }
13306
13314
  }
13307
13315
  if (hallucinationResult.status === "retry") {
13308
- if (this.deps.exitOnComplete && textContent?.trim()) {
13316
+ if (this.deps.exitOnComplete && textContent?.trim() && !this.deps.finalAudit) {
13309
13317
  logger.debug("Exit-on-complete: stopping on first response");
13310
13318
  lastText = textContent;
13311
13319
  break;
@@ -23173,15 +23181,175 @@ var init_environment = __esm(() => {
23173
23181
  TOOL_CHECKS = ["bun", "node", "git", "python"];
23174
23182
  });
23175
23183
 
23184
+ // src/modules/certification/manifest.ts
23185
+ var exports_manifest = {};
23186
+ __export(exports_manifest, {
23187
+ upsertCertification: () => upsertCertification,
23188
+ syncGlobalManifest: () => syncGlobalManifest,
23189
+ saveManifest: () => saveManifest,
23190
+ saveGlobalManifest: () => saveGlobalManifest,
23191
+ removeCertification: () => removeCertification,
23192
+ readMergedManifest: () => readMergedManifest,
23193
+ readManifest: () => readManifest,
23194
+ readGlobalManifest: () => readGlobalManifest,
23195
+ manifestPath: () => manifestPath,
23196
+ isStale: () => isStale,
23197
+ isFullyPassed: () => isFullyPassed,
23198
+ globalManifestPath: () => globalManifestPath,
23199
+ globalManifestDir: () => globalManifestDir,
23200
+ getCertMark: () => getCertMark,
23201
+ bundledManifestPath: () => bundledManifestPath
23202
+ });
23203
+ import { existsSync as existsSync47, readFileSync as readFileSync30, mkdirSync as mkdirSync19, writeFileSync as writeFileSync16 } from "fs";
23204
+ import { dirname as dirname15, join as join40 } from "path";
23205
+ import { fileURLToPath as fileURLToPath4 } from "url";
23206
+ import { homedir as homedir13 } from "os";
23207
+ function manifestPath(projectDir) {
23208
+ return join40(projectDir, "certification", "certifications.json");
23209
+ }
23210
+ function globalManifestDir(override) {
23211
+ return override || process.env.MMA_CERT_HOME || join40(homedir13(), ".mma");
23212
+ }
23213
+ function globalManifestPath(override) {
23214
+ return join40(globalManifestDir(override), "certifications.json");
23215
+ }
23216
+ function readManifest(projectDir) {
23217
+ const path = manifestPath(projectDir);
23218
+ try {
23219
+ if (existsSync47(path)) {
23220
+ const raw = JSON.parse(readFileSync30(path, "utf-8"));
23221
+ return { version: 1, certifications: raw.certifications ?? [] };
23222
+ }
23223
+ } catch {}
23224
+ return { version: 1, certifications: [] };
23225
+ }
23226
+ function saveManifest(m, projectDir) {
23227
+ const path = manifestPath(projectDir);
23228
+ mkdirSync19(join40(projectDir, "certification"), { recursive: true });
23229
+ writeFileSync16(path, JSON.stringify(m, null, 2), "utf-8");
23230
+ }
23231
+ function readGlobalManifest(override) {
23232
+ const path = globalManifestPath(override);
23233
+ try {
23234
+ if (existsSync47(path)) {
23235
+ const raw = JSON.parse(readFileSync30(path, "utf-8"));
23236
+ return { version: 1, certifications: raw.certifications ?? [] };
23237
+ }
23238
+ } catch {}
23239
+ return { version: 1, certifications: [] };
23240
+ }
23241
+ function saveGlobalManifest(m, override) {
23242
+ const dir = globalManifestDir(override);
23243
+ mkdirSync19(dir, { recursive: true });
23244
+ writeFileSync16(globalManifestPath(override), JSON.stringify(m, null, 2), "utf-8");
23245
+ }
23246
+ function readMergedManifest(projectDir, override) {
23247
+ const merged = new Map;
23248
+ for (const e of readGlobalManifest(override).certifications)
23249
+ merged.set(certKey(e), e);
23250
+ for (const e of readManifest(projectDir).certifications)
23251
+ merged.set(certKey(e), e);
23252
+ return { version: 1, certifications: [...merged.values()] };
23253
+ }
23254
+ function upsertCertification(entry, override) {
23255
+ const m = readGlobalManifest(override);
23256
+ const idx = m.certifications.findIndex((e) => certKey(e) === certKey(entry));
23257
+ if (idx >= 0)
23258
+ m.certifications[idx] = entry;
23259
+ else
23260
+ m.certifications.push(entry);
23261
+ saveGlobalManifest(m, override);
23262
+ return m;
23263
+ }
23264
+ function removeCertification(model, providerUrl, opts) {
23265
+ const key = `${model}::${providerUrl}`;
23266
+ const g = readGlobalManifest(opts?.globalDir);
23267
+ const beforeG = g.certifications.length;
23268
+ g.certifications = g.certifications.filter((e) => certKey(e) !== key);
23269
+ const removedGlobal = g.certifications.length !== beforeG;
23270
+ if (removedGlobal)
23271
+ saveGlobalManifest(g, opts?.globalDir);
23272
+ let removedProject = false;
23273
+ try {
23274
+ const projectDir = opts?.projectDir ?? process.cwd();
23275
+ const p = readManifest(projectDir);
23276
+ const beforeP = p.certifications.length;
23277
+ p.certifications = p.certifications.filter((e) => certKey(e) !== key);
23278
+ if (p.certifications.length !== beforeP) {
23279
+ saveManifest(p, projectDir);
23280
+ removedProject = true;
23281
+ }
23282
+ } catch {}
23283
+ return { global: removedGlobal, project: removedProject };
23284
+ }
23285
+ function isStale(entry, currentVersion) {
23286
+ return entry.mmaVersion !== currentVersion;
23287
+ }
23288
+ function isFullyPassed(entry) {
23289
+ return entry.suite.failed === 0 && entry.suite.passed > 0;
23290
+ }
23291
+ function getCertMark(model, providerUrl, currentVersion, projectDir, globalOverride) {
23292
+ const m = readMergedManifest(projectDir, globalOverride);
23293
+ const entry = m.certifications.find((e) => e.model === model && e.providerUrl === providerUrl);
23294
+ if (!entry)
23295
+ return "none";
23296
+ if (isStale(entry, currentVersion))
23297
+ return "stale";
23298
+ return isFullyPassed(entry) ? "certified" : "none";
23299
+ }
23300
+ function syncSnapshotPath(override) {
23301
+ return join40(globalManifestDir(override), "certifications.synced.json");
23302
+ }
23303
+ function bundledManifestPath() {
23304
+ const here = dirname15(fileURLToPath4(import.meta.url));
23305
+ const candidates = [
23306
+ join40(here, "certification", "certifications.json"),
23307
+ join40(here, "..", "certification", "certifications.json"),
23308
+ join40(here, "..", "..", "..", "certification", "certifications.json")
23309
+ ];
23310
+ for (const p of candidates) {
23311
+ if (existsSync47(p))
23312
+ return p;
23313
+ }
23314
+ return null;
23315
+ }
23316
+ function syncGlobalManifest(override, bundledPathOverride) {
23317
+ try {
23318
+ const bundledPath = bundledPathOverride ?? bundledManifestPath();
23319
+ if (!bundledPath || !existsSync47(bundledPath))
23320
+ return { synced: false, reason: "no-bundled" };
23321
+ const raw = readFileSync30(bundledPath, "utf-8");
23322
+ const snapshotPath = syncSnapshotPath(override);
23323
+ if (existsSync47(snapshotPath) && readFileSync30(snapshotPath, "utf-8") === raw) {
23324
+ return { synced: false, reason: "unchanged" };
23325
+ }
23326
+ const bundled = JSON.parse(raw);
23327
+ const current = readGlobalManifest(override);
23328
+ const merged = new Map;
23329
+ for (const e of current.certifications)
23330
+ merged.set(certKey(e), e);
23331
+ for (const e of bundled.certifications ?? [])
23332
+ merged.set(certKey(e), e);
23333
+ saveGlobalManifest({ version: 1, certifications: [...merged.values()] }, override);
23334
+ mkdirSync19(globalManifestDir(override), { recursive: true });
23335
+ writeFileSync16(snapshotPath, raw, "utf-8");
23336
+ return { synced: true, reason: "synced" };
23337
+ } catch {
23338
+ return { synced: false, reason: "error" };
23339
+ }
23340
+ }
23341
+ var certKey = (e) => `${e.model}::${e.providerUrl}`;
23342
+ var init_manifest = () => {};
23343
+
23176
23344
  // src/core/bootstrap.ts
23177
23345
  var exports_bootstrap = {};
23178
23346
  __export(exports_bootstrap, {
23179
23347
  buildSystemInfo: () => buildSystemInfo,
23180
23348
  bootstrap: () => bootstrap
23181
23349
  });
23182
- import { homedir as homedir13 } from "os";
23183
- import { join as join40, resolve as resolve23 } from "path";
23184
- import { existsSync as existsSync47, readFileSync as readFileSync30, writeFileSync as writeFileSync16 } from "fs";
23350
+ import { homedir as homedir14 } from "os";
23351
+ import { join as join41, resolve as resolve23 } from "path";
23352
+ import { existsSync as existsSync48, readFileSync as readFileSync31, writeFileSync as writeFileSync17 } from "fs";
23185
23353
  function buildSystemInfo(config, baseDir, profileCompressed) {
23186
23354
  const now = new Date().toISOString().replace("T", " ").slice(0, 19);
23187
23355
  const isWin = profileCompressed.toLowerCase().includes("win32");
@@ -23234,8 +23402,8 @@ function buildSystemInfo(config, baseDir, profileCompressed) {
23234
23402
  `);
23235
23403
  }
23236
23404
  async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
23237
- const dir = configDir || process.env.MMA_CONFIG_DIR || join40(homedir13(), ".mma");
23238
- const projectConfigPath = projectDir ? join40(projectDir, ".mmrc") : join40(process.cwd(), ".mmrc");
23405
+ const dir = configDir || process.env.MMA_CONFIG_DIR || join41(homedir14(), ".mma");
23406
+ const projectConfigPath = projectDir ? join41(projectDir, ".mmrc") : join41(process.cwd(), ".mmrc");
23239
23407
  const { config, legacyDetected } = loadConfig({ configDir: dir, projectConfigPath });
23240
23408
  setLocale(config.locale);
23241
23409
  try {
@@ -23245,11 +23413,18 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
23245
23413
  }
23246
23414
  } catch {}
23247
23415
  const logger = new Logger(config.logLevel);
23248
- logger.setLogDir(join40(dir, "logs"));
23416
+ logger.setLogDir(join41(dir, "logs"));
23249
23417
  logger.debug("MMA bootstrap", {
23250
23418
  version: config.version,
23251
23419
  model: config.model
23252
23420
  });
23421
+ try {
23422
+ const { syncGlobalManifest: syncGlobalManifest2 } = await Promise.resolve().then(() => (init_manifest(), exports_manifest));
23423
+ const syncResult = syncGlobalManifest2();
23424
+ if (syncResult.synced) {
23425
+ logger.debug("Certification manifest synced from package");
23426
+ }
23427
+ } catch {}
23253
23428
  if (config.modelLoad.autoLoad) {
23254
23429
  const modelLoader = new ModelLoader(config.provider.baseUrl, logger);
23255
23430
  const loadResult = await modelLoader.ensureModelLoaded({
@@ -23267,7 +23442,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
23267
23442
  logger.info(`Model ${config.model} loaded in ${loadResult.loadTime}s`);
23268
23443
  }
23269
23444
  }
23270
- const profile = new UserProfile(join40(dir));
23445
+ const profile = new UserProfile(join41(dir));
23271
23446
  profile.load() || profile.collect();
23272
23447
  profile.save();
23273
23448
  const providerManager = new ProviderManager(config.provider, {
@@ -23293,7 +23468,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
23293
23468
  for (const warning of envReport.warnings) {
23294
23469
  logger.warn(warning);
23295
23470
  }
23296
- const projectMapCacheDir = join40(baseDir, ".mma");
23471
+ const projectMapCacheDir = join41(baseDir, ".mma");
23297
23472
  const indexerModule = new IndexerModule({
23298
23473
  baseDir,
23299
23474
  cacheDir: projectMapCacheDir
@@ -23304,9 +23479,9 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
23304
23479
  logger.warn(`Project indexing failed: ${err.message}`);
23305
23480
  }
23306
23481
  const skillsLoader = new SkillsLoader;
23307
- const builtinDir = join40(import.meta.dirname, "skills", "builtin");
23308
- const globalDir = join40(homedir13(), ".agents", "skills");
23309
- const projectSkillsDir = join40(baseDir, ".mma", "skills");
23482
+ const builtinDir = join41(import.meta.dirname, "skills", "builtin");
23483
+ const globalDir = join41(homedir14(), ".agents", "skills");
23484
+ const projectSkillsDir = join41(baseDir, ".mma", "skills");
23310
23485
  const availableSkills = skillsLoader.loadFromAllSources(builtinDir, globalDir, projectSkillsDir);
23311
23486
  const skillsBudget = Math.floor(config.contextWindow * config.skills.budget);
23312
23487
  const skillsModule = new SkillsModule(availableSkills, skillsBudget);
@@ -23322,11 +23497,11 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
23322
23497
  essential: true,
23323
23498
  estimatedTokens: Math.ceil(systemInfoContent.length / 4)
23324
23499
  };
23325
- const agentsMdGlobal = join40(dir, "AGENTS.md");
23326
- if (!existsSync47(agentsMdGlobal)) {
23327
- writeFileSync16(agentsMdGlobal, "", "utf-8");
23500
+ const agentsMdGlobal = join41(dir, "AGENTS.md");
23501
+ if (!existsSync48(agentsMdGlobal)) {
23502
+ writeFileSync17(agentsMdGlobal, "", "utf-8");
23328
23503
  }
23329
- const sessionDir = join40(dir, "sessions");
23504
+ const sessionDir = join41(dir, "sessions");
23330
23505
  const sessionStore = new SessionStore(sessionDir);
23331
23506
  sessionStore.init();
23332
23507
  const sessionManager = new SessionManager(sessionStore, {
@@ -23400,7 +23575,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
23400
23575
  const mcpModule = new MCPModule(config);
23401
23576
  await mcpModule.initialize();
23402
23577
  moduleRegistry.register(mcpModule);
23403
- const memoryStore = new MemoryStore(join40(dir, "memory"));
23578
+ const memoryStore = new MemoryStore(join41(dir, "memory"));
23404
23579
  const memoryModule = new MemoryModule(memoryStore);
23405
23580
  moduleRegistry.register(memoryModule);
23406
23581
  if (config.browser.enabled) {
@@ -23454,8 +23629,8 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
23454
23629
  pluginManager.register(plugin);
23455
23630
  pluginManager.register(plugin2);
23456
23631
  const pluginLoader = new PluginLoader;
23457
- const globalPluginsDir = join40(homedir13(), ".mma", "plugins");
23458
- const projectPluginsDir = join40(baseDir, ".mma", "plugins");
23632
+ const globalPluginsDir = join41(homedir14(), ".mma", "plugins");
23633
+ const projectPluginsDir = join41(baseDir, ".mma", "plugins");
23459
23634
  const mmaVersion = readMmaVersion();
23460
23635
  pluginLoader.loadFromDir(globalPluginsDir, pluginManager, logger, {
23461
23636
  source: "global",
@@ -23481,13 +23656,13 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
23481
23656
  const skipAgentsMd = noAgentsMd === true;
23482
23657
  if (!skipAgentsMd) {
23483
23658
  const agentsMdCandidates = [
23484
- join40(baseDir, "AGENTS.md"),
23485
- join40(baseDir, ".mma", "AGENTS.md"),
23486
- join40(dir, "AGENTS.md")
23659
+ join41(baseDir, "AGENTS.md"),
23660
+ join41(baseDir, ".mma", "AGENTS.md"),
23661
+ join41(dir, "AGENTS.md")
23487
23662
  ];
23488
23663
  for (const p of agentsMdCandidates) {
23489
- if (existsSync47(p)) {
23490
- const content = readFileSync30(p, "utf-8").trim();
23664
+ if (existsSync48(p)) {
23665
+ const content = readFileSync31(p, "utf-8").trim();
23491
23666
  if (content) {
23492
23667
  agentsMdBlocks.push({
23493
23668
  content,
@@ -24350,75 +24525,6 @@ var init_setup = __esm(() => {
24350
24525
  ];
24351
24526
  });
24352
24527
 
24353
- // src/modules/certification/manifest.ts
24354
- var exports_manifest = {};
24355
- __export(exports_manifest, {
24356
- upsertCertification: () => upsertCertification,
24357
- saveManifest: () => saveManifest,
24358
- removeCertification: () => removeCertification,
24359
- readManifest: () => readManifest,
24360
- manifestPath: () => manifestPath,
24361
- isStale: () => isStale,
24362
- isFullyPassed: () => isFullyPassed,
24363
- getCertMark: () => getCertMark
24364
- });
24365
- import { existsSync as existsSync48, readFileSync as readFileSync31, mkdirSync as mkdirSync19, writeFileSync as writeFileSync17 } from "fs";
24366
- import { join as join42 } from "path";
24367
- function manifestPath(projectDir) {
24368
- return join42(projectDir, "certification", "certifications.json");
24369
- }
24370
- function readManifest(projectDir) {
24371
- const path = manifestPath(projectDir);
24372
- try {
24373
- if (existsSync48(path)) {
24374
- const raw = JSON.parse(readFileSync31(path, "utf-8"));
24375
- return { version: 1, certifications: raw.certifications ?? [] };
24376
- }
24377
- } catch {}
24378
- return { version: 1, certifications: [] };
24379
- }
24380
- function saveManifest(m, projectDir) {
24381
- const path = manifestPath(projectDir);
24382
- mkdirSync19(join42(projectDir, "certification"), { recursive: true });
24383
- writeFileSync17(path, JSON.stringify(m, null, 2), "utf-8");
24384
- }
24385
- function upsertCertification(entry, projectDir) {
24386
- const m = readManifest(projectDir);
24387
- const idx = m.certifications.findIndex((e) => e.model === entry.model && e.providerUrl === entry.providerUrl);
24388
- if (idx >= 0)
24389
- m.certifications[idx] = entry;
24390
- else
24391
- m.certifications.push(entry);
24392
- saveManifest(m, projectDir);
24393
- return m;
24394
- }
24395
- function removeCertification(model, providerUrl, projectDir) {
24396
- const m = readManifest(projectDir);
24397
- const before = m.certifications.length;
24398
- m.certifications = m.certifications.filter((e) => !(e.model === model && e.providerUrl === providerUrl));
24399
- if (m.certifications.length !== before) {
24400
- saveManifest(m, projectDir);
24401
- return true;
24402
- }
24403
- return false;
24404
- }
24405
- function isStale(entry, currentVersion) {
24406
- return entry.mmaVersion !== currentVersion;
24407
- }
24408
- function isFullyPassed(entry) {
24409
- return entry.suite.failed === 0 && entry.suite.passed > 0;
24410
- }
24411
- function getCertMark(model, providerUrl, currentVersion, projectDir) {
24412
- const m = readManifest(projectDir);
24413
- const entry = m.certifications.find((e) => e.model === model && e.providerUrl === providerUrl);
24414
- if (!entry)
24415
- return "none";
24416
- if (isStale(entry, currentVersion))
24417
- return "stale";
24418
- return isFullyPassed(entry) ? "certified" : "none";
24419
- }
24420
- var init_manifest = () => {};
24421
-
24422
24528
  // node_modules/yaml/dist/nodes/identity.js
24423
24529
  var require_identity = __commonJS((exports) => {
24424
24530
  var ALIAS = Symbol.for("yaml.alias");
@@ -31603,6 +31709,7 @@ var init_scenarios = __esm(() => {
31603
31709
  title: "Data processing pipeline",
31604
31710
  tags: ["core"],
31605
31711
  mode: "run",
31712
+ timeoutMs: 600000,
31606
31713
  prompt: "Create a data processing script: 1. Create data/input.json with an array of 10 objects {id, name, value}. 2. Create src/process.ts that reads input, filters value > 50, writes output.json AT THE PROJECT ROOT (not inside data/). 3. Run the script and verify output.json has filtered results.",
31607
31714
  checks: [
31608
31715
  { type: "fileExists", path: "data/input.json" },
@@ -31964,6 +32071,9 @@ function validateScenario(s) {
31964
32071
  if (s.reps !== undefined && (!Number.isInteger(s.reps) || s.reps < 1)) {
31965
32072
  errors2.push(`[${s.id}] reps must be a positive integer`);
31966
32073
  }
32074
+ if (s.timeoutMs !== undefined && (!Number.isInteger(s.timeoutMs) || s.timeoutMs < 1000)) {
32075
+ errors2.push(`[${s.id}] timeoutMs must be an integer >= 1000`);
32076
+ }
31967
32077
  if (s.passThreshold !== undefined && (!Number.isInteger(s.passThreshold) || s.passThreshold < 1)) {
31968
32078
  errors2.push(`[${s.id}] passThreshold must be a positive integer`);
31969
32079
  }
@@ -32012,6 +32122,7 @@ function normalizeScenario(data, file) {
32012
32122
  prompt: String(d.prompt ?? ""),
32013
32123
  reps: typeof d.reps === "number" ? d.reps : undefined,
32014
32124
  passThreshold: typeof d.passThreshold === "number" ? d.passThreshold : undefined,
32125
+ timeoutMs: typeof d.timeoutMs === "number" ? d.timeoutMs : undefined,
32015
32126
  fixtures: Array.isArray(d.fixtures) ? d.fixtures : undefined,
32016
32127
  checks: Array.isArray(d.checks) ? d.checks : [],
32017
32128
  skipReason: typeof d.skipReason === "string" ? d.skipReason : undefined,
@@ -32024,6 +32135,14 @@ function filterByTags(scenarios, tags) {
32024
32135
  }
32025
32136
  return scenarios.filter((s) => s.tags.some((t2) => tags.includes(t2)));
32026
32137
  }
32138
+ function filterByScenarios(scenarios, ids) {
32139
+ const wanted = new Set(ids.map((id) => id.toLowerCase()));
32140
+ return scenarios.filter((s) => wanted.has(s.id.toLowerCase()));
32141
+ }
32142
+ function unknownScenarioIds(scenarios, ids) {
32143
+ const known = new Set(scenarios.map((s) => s.id.toLowerCase()));
32144
+ return ids.filter((id) => !known.has(id.toLowerCase()));
32145
+ }
32027
32146
  var TAGS, CHECK_TYPES;
32028
32147
  var init_loader3 = __esm(() => {
32029
32148
  init_dist2();
@@ -32126,7 +32245,7 @@ var init_fact_checker = () => {};
32126
32245
  // src/modules/certification/runner.ts
32127
32246
  import { spawn as spawn9 } from "child_process";
32128
32247
  import { existsSync as existsSync51, mkdirSync as mkdirSync20, rmSync as rmSync4, cpSync as cpSync2, writeFileSync as writeFileSync18, readdirSync as readdirSync18, readFileSync as readFileSync34 } from "fs";
32129
- import { join as join45, resolve as resolve24, dirname as dirname16, relative as relative6 } from "path";
32248
+ import { join as join45, resolve as resolve24, dirname as dirname17, relative as relative6 } from "path";
32130
32249
  async function runScenario(scenario, opts) {
32131
32250
  if (scenario.mode === "skip") {
32132
32251
  return {
@@ -32140,7 +32259,7 @@ async function runScenario(scenario, opts) {
32140
32259
  const reps = scenario.reps ?? opts.defaultReps;
32141
32260
  const threshold = Math.min(scenario.passThreshold ?? opts.defaultThreshold, reps);
32142
32261
  const runner = opts.runner ?? defaultRunner2;
32143
- const timeoutMs = opts.timeoutMs ?? 300000;
32262
+ const timeoutMs = scenario.timeoutMs ?? opts.timeoutMs ?? 300000;
32144
32263
  const entryPoint = resolveMmaEntry(opts.mmaRoot);
32145
32264
  let passed = 0;
32146
32265
  let firstError;
@@ -32224,7 +32343,7 @@ function prepareSandbox(sandbox, scenario, mmaRoot) {
32224
32343
  throw new Error(`fixture missing: ${f.source}`);
32225
32344
  }
32226
32345
  const dest = join45(sandbox, f.dest);
32227
- mkdirSync20(dirname16(dest), { recursive: true });
32346
+ mkdirSync20(dirname17(dest), { recursive: true });
32228
32347
  cpSync2(src, dest);
32229
32348
  }
32230
32349
  }
@@ -32340,13 +32459,14 @@ var exports_cli = {};
32340
32459
  __export(exports_cli, {
32341
32460
  uncertify: () => uncertify,
32342
32461
  parseTags: () => parseTags,
32462
+ mergePartialResults: () => mergePartialResults,
32343
32463
  certify: () => certify,
32344
32464
  certStatus: () => certStatus,
32345
32465
  certList: () => certList
32346
32466
  });
32347
32467
  import { rmSync as rmSync5, writeFileSync as writeFileSync19 } from "fs";
32348
- import { join as join46, dirname as dirname17 } from "path";
32349
- import { fileURLToPath as fileURLToPath4 } from "url";
32468
+ import { join as join46, dirname as dirname18 } from "path";
32469
+ import { fileURLToPath as fileURLToPath5 } from "url";
32350
32470
  import { existsSync as existsSync52, readFileSync as readFileSync35 } from "fs";
32351
32471
  function readVersion() {
32352
32472
  const candidates = [join46(MMA_ROOT, "package.json")];
@@ -32369,15 +32489,28 @@ async function certify(opts) {
32369
32489
  const { scenarios, errors: errors2 } = loadScenarios(join46(opts.projectDir, ".mma", "certification", "scenarios"));
32370
32490
  for (const e of errors2)
32371
32491
  console.error(pc2.yellow(` ${e}`));
32372
- const selected = filterByTags(scenarios, opts.tags);
32492
+ let selected = filterByTags(scenarios, opts.tags);
32493
+ const isPartial = Array.isArray(opts.scenarios) && opts.scenarios.length > 0;
32494
+ if (isPartial) {
32495
+ const unknown = unknownScenarioIds(scenarios, opts.scenarios);
32496
+ if (unknown.length > 0) {
32497
+ console.error(pc2.red(t("cli.cert_scenarios_unknown", {
32498
+ ids: unknown.join(", "),
32499
+ available: scenarios.map((s) => s.id).join(", ")
32500
+ })));
32501
+ process.exitCode = 1;
32502
+ return;
32503
+ }
32504
+ selected = filterByScenarios(selected, opts.scenarios);
32505
+ }
32373
32506
  if (selected.length === 0) {
32374
32507
  console.error(pc2.red(t("cli.cert_no_scenarios", { tags: opts.tags.join(",") })));
32375
32508
  process.exitCode = 1;
32376
32509
  return;
32377
32510
  }
32378
- const manifest = readManifest(opts.projectDir);
32511
+ const manifest = readMergedManifest(opts.projectDir);
32379
32512
  const existing = manifest.certifications.find((e) => e.model === opts.name && e.providerUrl === providerUrl);
32380
- if (existing && !opts.force) {
32513
+ if (existing && !opts.force && !isPartial) {
32381
32514
  console.error(pc2.yellow(t("cli.cert_exists", { model: opts.name })));
32382
32515
  console.error(pc2.yellow(t("cli.cert_exists_hint")));
32383
32516
  process.exitCode = 1;
@@ -32410,6 +32543,7 @@ async function certify(opts) {
32410
32543
  sandboxBase,
32411
32544
  defaultReps: opts.reps,
32412
32545
  defaultThreshold: 2,
32546
+ timeoutMs: opts.timeout,
32413
32547
  baseConfig: opts.config,
32414
32548
  onRep: (id, rep, reps, passed, failures) => {
32415
32549
  const word = passed ? pc2.green(t("cli.cert_rep_pass")) : pc2.red(t("cli.cert_rep_fail"));
@@ -32425,23 +32559,25 @@ async function certify(opts) {
32425
32559
  rmSync5(sandboxBase, { recursive: true, force: true });
32426
32560
  } catch {}
32427
32561
  }
32428
- const suite = summarize(results);
32562
+ const runIds = new Set(selected.map((s) => s.id));
32563
+ const finalResults = isPartial && existing ? mergePartialResults(results, existing.results, runIds) : results;
32564
+ const suite = summarize(finalResults);
32429
32565
  const entry = {
32430
32566
  model: opts.name,
32431
32567
  providerUrl,
32432
32568
  mmaVersion: readVersion(),
32433
32569
  certifiedAt: new Date().toISOString(),
32434
32570
  suite,
32435
- results
32571
+ results: finalResults
32436
32572
  };
32437
- upsertCertification(entry, opts.projectDir);
32573
+ upsertCertification(entry);
32438
32574
  console.log(t("cli.cert_done", {
32439
32575
  passed: String(suite.passed),
32440
32576
  failed: String(suite.failed),
32441
32577
  skipped: String(suite.skipped),
32442
32578
  total: String(suite.total)
32443
32579
  }));
32444
- printResults(results);
32580
+ printResults(finalResults);
32445
32581
  if (isFullyPassed(entry)) {
32446
32582
  console.log(pc2.green(`
32447
32583
  ✔ ${opts.name} is certified`));
@@ -32452,7 +32588,7 @@ async function certify(opts) {
32452
32588
  writeReport(entry, opts.projectDir);
32453
32589
  }
32454
32590
  async function certStatus(name, config, projectDir) {
32455
- const m = readManifest(projectDir);
32591
+ const m = readMergedManifest(projectDir);
32456
32592
  const providerUrl = config.provider.baseUrl;
32457
32593
  const entry = m.certifications.find((e) => e.model === name && e.providerUrl === providerUrl);
32458
32594
  if (!entry) {
@@ -32467,7 +32603,7 @@ async function certStatus(name, config, projectDir) {
32467
32603
  printResults(entry.results);
32468
32604
  }
32469
32605
  async function certList(projectDir) {
32470
- const m = readManifest(projectDir);
32606
+ const m = readMergedManifest(projectDir);
32471
32607
  if (m.certifications.length === 0) {
32472
32608
  console.log(t("cli.cert_empty"));
32473
32609
  return;
@@ -32478,8 +32614,10 @@ async function certList(projectDir) {
32478
32614
  }
32479
32615
  }
32480
32616
  async function uncertify(name, config, projectDir) {
32481
- const removed = removeCertification(name, config.provider.baseUrl, projectDir);
32482
- if (removed)
32617
+ const removed = removeCertification(name, config.provider.baseUrl, {
32618
+ projectDir
32619
+ });
32620
+ if (removed.global || removed.project)
32483
32621
  console.log(t("cli.cert_uncertified", { model: name }));
32484
32622
  else
32485
32623
  console.log(t("cli.cert_not_found", { model: name }));
@@ -32492,6 +32630,13 @@ function summarize(results) {
32492
32630
  total: results.length
32493
32631
  };
32494
32632
  }
32633
+ function mergePartialResults(fresh, previous, rerunIds) {
32634
+ const preserved = previous.filter((r) => !rerunIds.has(r.id));
32635
+ if (preserved.length > 0) {
32636
+ console.log(pc2.dim(t("cli.cert_partial_merge", { kept: String(preserved.length) })));
32637
+ }
32638
+ return [...fresh, ...preserved];
32639
+ }
32495
32640
  function printResults(results) {
32496
32641
  for (const r of results) {
32497
32642
  const icon = r.status === "pass" ? pc2.green("✔") : r.status === "fail" ? pc2.red("✘") : r.status === "skipped" ? pc2.dim("–") : pc2.yellow("!");
@@ -32540,7 +32685,7 @@ var init_cli = __esm(() => {
32540
32685
  init_loader3();
32541
32686
  init_runner2();
32542
32687
  init_manifest();
32543
- HERE = dirname17(fileURLToPath4(import.meta.url));
32688
+ HERE = dirname18(fileURLToPath5(import.meta.url));
32544
32689
  MMA_ROOT = findMmaRoot(HERE);
32545
32690
  });
32546
32691
 
@@ -32550,8 +32695,8 @@ __export(exports_repl_commands, {
32550
32695
  registerAllCommands: () => registerAllCommands,
32551
32696
  COMMAND_GROUPS: () => COMMAND_GROUPS
32552
32697
  });
32553
- import { join as join48, dirname as dirname19 } from "path";
32554
- import { homedir as homedir16 } from "os";
32698
+ import { join as join48, dirname as dirname20 } from "path";
32699
+ import { homedir as homedir17 } from "os";
32555
32700
  import { existsSync as existsSync54 } from "fs";
32556
32701
  function registerAllCommands(ctx) {
32557
32702
  registerBuiltinCommands(ctx);
@@ -32745,7 +32890,7 @@ function registerMmaCommands(ctx) {
32745
32890
  console.log(pc2.yellow(t("repl.wizard_running")));
32746
32891
  await ctx.withExclusiveInput(async () => {
32747
32892
  const answers = await runSetup(ctx.rl);
32748
- const configPath = join48(homedir16(), ".mma", "config.json");
32893
+ const configPath = join48(homedir17(), ".mma", "config.json");
32749
32894
  ctx.config.provider.type = answers.provider;
32750
32895
  ctx.config.provider.baseUrl = answers.apiBase;
32751
32896
  ctx.config.provider.apiKey = answers.apiKey;
@@ -32753,7 +32898,7 @@ function registerMmaCommands(ctx) {
32753
32898
  ctx.config.contextWindow = answers.contextWindow;
32754
32899
  ctx.config.maxToolIterations = answers.maxToolIterations;
32755
32900
  ctx.config.locale = answers.locale;
32756
- saveConfig(ctx.config, configPath, dirname19(configPath));
32901
+ saveConfig(ctx.config, configPath, dirname20(configPath));
32757
32902
  await ctx.agent.reconfigure(ctx.config);
32758
32903
  console.log(pc2.green(t("cli.config_saved")));
32759
32904
  });
@@ -32868,8 +33013,8 @@ Excluded blocks: ${info.excluded.length}`));
32868
33013
  return;
32869
33014
  }
32870
33015
  ctx.config.model = name;
32871
- const configPath = join48(homedir16(), ".mma", "config.json");
32872
- saveConfig(ctx.config, configPath, dirname19(configPath));
33016
+ const configPath = join48(homedir17(), ".mma", "config.json");
33017
+ saveConfig(ctx.config, configPath, dirname20(configPath));
32873
33018
  await ctx.agent.reconfigure(ctx.config);
32874
33019
  console.log(pc2.green(t("repl.model_set", { name })));
32875
33020
  return;
@@ -32893,8 +33038,8 @@ Excluded blocks: ${info.excluded.length}`));
32893
33038
  return;
32894
33039
  }
32895
33040
  ctx.config.contextWindow = size;
32896
- const configPath = join48(homedir16(), ".mma", "config.json");
32897
- saveConfig(ctx.config, configPath, dirname19(configPath));
33041
+ const configPath = join48(homedir17(), ".mma", "config.json");
33042
+ saveConfig(ctx.config, configPath, dirname20(configPath));
32898
33043
  await ctx.agent.reconfigure(ctx.config);
32899
33044
  console.log(pc2.green(t("cli.context_set", { size })));
32900
33045
  }
@@ -32908,7 +33053,7 @@ Excluded blocks: ${info.excluded.length}`));
32908
33053
  if (ctx.sessionManager && ctx.config.session.autoSave) {}
32909
33054
  ctx.agent.shutdown();
32910
33055
  const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config2(), exports_config));
32911
- const { homedir: homedir17 } = await import("os");
33056
+ const { homedir: homedir18 } = await import("os");
32912
33057
  const { join: join49 } = await import("path");
32913
33058
  const configDir = ctx.configDir;
32914
33059
  const baseDir = ctx.baseDir;
@@ -33315,15 +33460,15 @@ init_config2();
33315
33460
  init_setup();
33316
33461
  init_i18n();
33317
33462
  init_colors();
33318
- import { join as join47, dirname as dirname18 } from "path";
33319
- import { homedir as homedir15 } from "os";
33463
+ import { join as join47, dirname as dirname19 } from "path";
33464
+ import { homedir as homedir16 } from "os";
33320
33465
  import { existsSync as existsSync53 } from "fs";
33321
33466
 
33322
33467
  // src/cli/security-commands.ts
33323
33468
  init_bootstrap();
33324
33469
  init_config2();
33325
- import { join as join41, dirname as dirname15 } from "path";
33326
- import { homedir as homedir14 } from "os";
33470
+ import { join as join42, dirname as dirname16 } from "path";
33471
+ import { homedir as homedir15 } from "os";
33327
33472
 
33328
33473
  // src/modules/security/security-policies.ts
33329
33474
  init_security();
@@ -33836,7 +33981,7 @@ function createSecurityCommand(program2) {
33836
33981
  }
33837
33982
  });
33838
33983
  securityCmd.command("set-policy").argument("<preset>", t("cli.security.preset")).description(t("cli.security.set_policy")).action(async (preset) => {
33839
- const configPath = join41(homedir14(), ".mma", "config.json");
33984
+ const configPath = join42(homedir15(), ".mma", "config.json");
33840
33985
  const { config: appConfig } = await bootstrap();
33841
33986
  const validPresets = ["strict", "balanced", "permissive"];
33842
33987
  if (!validPresets.includes(preset)) {
@@ -33846,12 +33991,12 @@ function createSecurityCommand(program2) {
33846
33991
  const policy = getSecurityPolicy(preset);
33847
33992
  const newSecurityConfig = applySecurityPolicy(preset);
33848
33993
  appConfig.security = newSecurityConfig;
33849
- saveConfig(appConfig, configPath, dirname15(configPath));
33994
+ saveConfig(appConfig, configPath, dirname16(configPath));
33850
33995
  console.log(t("cli.security.policy_applied", { name: policy.name }));
33851
33996
  console.log(t("cli.security.policy_description", { description: policy.description }));
33852
33997
  });
33853
33998
  securityCmd.command("enable-encryption").description(t("cli.security.enable_encryption")).action(async () => {
33854
- const configPath = join41(homedir14(), ".mma", "config.json");
33999
+ const configPath = join42(homedir15(), ".mma", "config.json");
33855
34000
  const { config: appConfig } = await bootstrap();
33856
34001
  appConfig.security = appConfig.security || {};
33857
34002
  appConfig.security.sessionEncryption = {
@@ -33859,11 +34004,11 @@ function createSecurityCommand(program2) {
33859
34004
  encryptHistory: true,
33860
34005
  encryptSessionLog: true
33861
34006
  };
33862
- saveConfig(appConfig, configPath, dirname15(configPath));
34007
+ saveConfig(appConfig, configPath, dirname16(configPath));
33863
34008
  console.log(t("cli.security.encryption_enabled"));
33864
34009
  });
33865
34010
  securityCmd.command("disable-encryption").description(t("cli.security.disable_encryption")).action(async () => {
33866
- const configPath = join41(homedir14(), ".mma", "config.json");
34011
+ const configPath = join42(homedir15(), ".mma", "config.json");
33867
34012
  const { config: appConfig } = await bootstrap();
33868
34013
  appConfig.security = appConfig.security || {};
33869
34014
  appConfig.security.sessionEncryption = {
@@ -33871,11 +34016,11 @@ function createSecurityCommand(program2) {
33871
34016
  encryptHistory: false,
33872
34017
  encryptSessionLog: false
33873
34018
  };
33874
- saveConfig(appConfig, configPath, dirname15(configPath));
34019
+ saveConfig(appConfig, configPath, dirname16(configPath));
33875
34020
  console.log(t("cli.security.encryption_disabled"));
33876
34021
  });
33877
34022
  securityCmd.command("enable-audit").description(t("cli.security.enable_audit")).action(async () => {
33878
- const configPath = join41(homedir14(), ".mma", "config.json");
34023
+ const configPath = join42(homedir15(), ".mma", "config.json");
33879
34024
  const { config: appConfig } = await bootstrap();
33880
34025
  appConfig.security = appConfig.security || {};
33881
34026
  appConfig.security.auditNotifier = {
@@ -33885,11 +34030,11 @@ function createSecurityCommand(program2) {
33885
34030
  maxRetries: 3,
33886
34031
  webhookTimeout: 5000
33887
34032
  };
33888
- saveConfig(appConfig, configPath, dirname15(configPath));
34033
+ saveConfig(appConfig, configPath, dirname16(configPath));
33889
34034
  console.log(t("cli.security.audit_enabled"));
33890
34035
  });
33891
34036
  securityCmd.command("disable-audit").description(t("cli.security.disable_audit")).action(async () => {
33892
- const configPath = join41(homedir14(), ".mma", "config.json");
34037
+ const configPath = join42(homedir15(), ".mma", "config.json");
33893
34038
  const { config: appConfig } = await bootstrap();
33894
34039
  appConfig.security = appConfig.security || {};
33895
34040
  appConfig.security.auditNotifier = {
@@ -33897,7 +34042,7 @@ function createSecurityCommand(program2) {
33897
34042
  maxRetries: 3,
33898
34043
  webhookTimeout: 5000
33899
34044
  };
33900
- saveConfig(appConfig, configPath, dirname15(configPath));
34045
+ saveConfig(appConfig, configPath, dirname16(configPath));
33901
34046
  console.log(t("cli.security.audit_disabled"));
33902
34047
  });
33903
34048
  securityCmd.command("audit-stats").description(t("cli.security.audit_stats")).action(async () => {
@@ -33959,7 +34104,7 @@ function createProgram() {
33959
34104
  const program2 = new Command().name("mma").description(t("cli.description")).version(version).option("--no-agents-md", t("cli.no_agents_md")).option("-d, --dir <path>", t("cli.dir")).option("-e, --exit-on-complete", t("cli.exit_on_complete")).option("-j, --json", t("cli.json"));
33960
34105
  program2.command("init").description(t("cli.init")).action(async () => {
33961
34106
  const answers = await runSetup();
33962
- const configPath = join47(homedir15(), ".mma", "config.json");
34107
+ const configPath = join47(homedir16(), ".mma", "config.json");
33963
34108
  const { config } = await bootstrap();
33964
34109
  config.provider.type = answers.provider;
33965
34110
  config.provider.baseUrl = answers.apiBase;
@@ -33999,12 +34144,12 @@ function createProgram() {
33999
34144
  config.security.paths.denied = [];
34000
34145
  }
34001
34146
  }
34002
- saveConfig(config, configPath, dirname18(configPath));
34147
+ saveConfig(config, configPath, dirname19(configPath));
34003
34148
  console.log(t("cli.config_saved"));
34004
34149
  });
34005
34150
  const configCmd = program2.command("config").description(t("cli.manage_config"));
34006
34151
  configCmd.command("set").argument("<key>", t("cli.config_key")).argument("<value>", "Config value").description(t("cli.set_value")).action(async (key, value) => {
34007
- const configPath = join47(homedir15(), ".mma", "config.json");
34152
+ const configPath = join47(homedir16(), ".mma", "config.json");
34008
34153
  const { config } = await bootstrap();
34009
34154
  const keys = key.split(".");
34010
34155
  let obj = config;
@@ -34024,7 +34169,7 @@ function createProgram() {
34024
34169
  obj[lastKey] = parseFloat(value);
34025
34170
  else
34026
34171
  obj[lastKey] = value;
34027
- saveConfig(config, configPath, dirname18(configPath));
34172
+ saveConfig(config, configPath, dirname19(configPath));
34028
34173
  console.log(t("cli.set_done", { key, value }));
34029
34174
  });
34030
34175
  configCmd.command("show").description(t("cli.show_config")).action(async () => {
@@ -34034,7 +34179,7 @@ function createProgram() {
34034
34179
  configCmd.command("migrate").description(t("cli.migrate_config")).action(async () => {
34035
34180
  const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config2(), exports_config));
34036
34181
  const { hasDomainFiles: hasDomainFiles3 } = await Promise.resolve().then(() => (init_domains(), exports_domains));
34037
- const configDir = join47(homedir15(), ".mma");
34182
+ const configDir = join47(homedir16(), ".mma");
34038
34183
  const configPath = join47(configDir, "config.json");
34039
34184
  if (hasDomainFiles3(configDir)) {
34040
34185
  console.log(pc2.yellow(t("config.migrate_no_legacy")));
@@ -34091,13 +34236,13 @@ function createProgram() {
34091
34236
  console.log(t("cli.model_hint"));
34092
34237
  });
34093
34238
  model.command("use").argument("<name>", "Model name").description(t("cli.set_model")).action(async (name) => {
34094
- const configPath = join47(homedir15(), ".mma", "config.json");
34239
+ const configPath = join47(homedir16(), ".mma", "config.json");
34095
34240
  const { config } = await bootstrap();
34096
34241
  config.model = name;
34097
- saveConfig(config, configPath, dirname18(configPath));
34242
+ saveConfig(config, configPath, dirname19(configPath));
34098
34243
  console.log(t("cli.model_set", { name }));
34099
34244
  });
34100
- model.command("certify").argument("<name>", "Model name").option("--provider-url <url>", t("cli.cert_provider_url")).option("--provider-key <key>", t("cli.cert_provider_key")).option("--context-window <n>", t("cli.cert_context_window")).option("--tags <tags>", t("cli.cert_tags"), "core").option("--reps <n>", t("cli.cert_reps")).option("--force", t("cli.cert_force")).option("--clean", t("cli.cert_clean")).description(t("cli.certify")).action(async (name, cmdOpts) => {
34245
+ model.command("certify").argument("<name>", "Model name").option("--provider-url <url>", t("cli.cert_provider_url")).option("--provider-key <key>", t("cli.cert_provider_key")).option("--context-window <n>", t("cli.cert_context_window")).option("--tags <tags>", t("cli.cert_tags"), "core").option("--scenarios <ids>", t("cli.cert_scenarios")).option("--timeout <ms>", t("cli.cert_timeout")).option("--reps <n>", t("cli.cert_reps")).option("--force", t("cli.cert_force")).option("--clean", t("cli.cert_clean")).description(t("cli.certify")).action(async (name, cmdOpts) => {
34101
34246
  const { config } = await bootstrap();
34102
34247
  const { certify: certify2, parseTags: parseTags2 } = await Promise.resolve().then(() => (init_cli(), exports_cli));
34103
34248
  await certify2({
@@ -34106,7 +34251,9 @@ function createProgram() {
34106
34251
  providerKey: cmdOpts.providerKey,
34107
34252
  contextWindow: cmdOpts.contextWindow ? parseInt(cmdOpts.contextWindow, 10) : undefined,
34108
34253
  tags: parseTags2(cmdOpts.tags),
34254
+ scenarios: cmdOpts.scenarios ? String(cmdOpts.scenarios).split(",").map((x) => x.trim()).filter(Boolean) : undefined,
34109
34255
  reps: cmdOpts.reps ? parseInt(cmdOpts.reps, 10) : 3,
34256
+ timeout: cmdOpts.timeout ? parseInt(cmdOpts.timeout, 10) : undefined,
34110
34257
  force: cmdOpts.force === true,
34111
34258
  clean: cmdOpts.clean === true,
34112
34259
  config,
@@ -34128,7 +34275,7 @@ function createProgram() {
34128
34275
  await uncertify2(name, config, process.cwd());
34129
34276
  });
34130
34277
  program2.command("context").description(t("cli.manage_context")).argument("<size>", "Context window size in tokens").action(async (size) => {
34131
- const configPath = join47(homedir15(), ".mma", "config.json");
34278
+ const configPath = join47(homedir16(), ".mma", "config.json");
34132
34279
  const { config } = await bootstrap();
34133
34280
  const contextWindow = parseInt(size, 10);
34134
34281
  if (isNaN(contextWindow) || contextWindow < 1024) {
@@ -34136,7 +34283,7 @@ function createProgram() {
34136
34283
  return;
34137
34284
  }
34138
34285
  config.contextWindow = contextWindow;
34139
- saveConfig(config, configPath, dirname18(configPath));
34286
+ saveConfig(config, configPath, dirname19(configPath));
34140
34287
  console.log(t("cli.context_set", { size: contextWindow }));
34141
34288
  });
34142
34289
  const provider = program2.command("provider").description(t("cli.manage_providers"));
@@ -34174,7 +34321,7 @@ function createProgram() {
34174
34321
  console.log(t("cli.base_url"), config.provider.baseUrl);
34175
34322
  });
34176
34323
  provider.command("use").argument("<name>", "Provider name").description(t("cli.set_provider")).action(async (name) => {
34177
- const configPath = join47(homedir15(), ".mma", "config.json");
34324
+ const configPath = join47(homedir16(), ".mma", "config.json");
34178
34325
  const { config, agent } = await bootstrap();
34179
34326
  if (config.provider.entries && config.provider.entries.length > 0) {
34180
34327
  try {
@@ -34190,14 +34337,14 @@ function createProgram() {
34190
34337
  if (baseUrl) {
34191
34338
  config.provider.baseUrl = baseUrl;
34192
34339
  }
34193
- saveConfig(config, configPath, dirname18(configPath));
34340
+ saveConfig(config, configPath, dirname19(configPath));
34194
34341
  console.log(t("cli.provider_set", { name }));
34195
34342
  if (baseUrl) {
34196
34343
  console.log(t("cli.provider_base_hint", { baseUrl }));
34197
34344
  }
34198
34345
  });
34199
34346
  provider.command("add").argument("<name>", "Provider type or label").option("--url <url>", "Base URL").option("--key <key>", "API key").option("--priority <n>", "Fallback priority (lower = tried first)").option("--context-window <n>", "Context window override for this entry").option("--rpm <n>", "Max requests per minute for this entry").option("--parallel <n>", "Max parallel tasks for this entry").description(t("cli.add_provider")).action(async (name, opts) => {
34200
- const configPath = join47(homedir15(), ".mma", "config.json");
34347
+ const configPath = join47(homedir16(), ".mma", "config.json");
34201
34348
  const { config } = await bootstrap();
34202
34349
  const entries = Array.isArray(config.provider.entries) ? config.provider.entries : [];
34203
34350
  if (entries.length === 0) {
@@ -34229,7 +34376,7 @@ function createProgram() {
34229
34376
  });
34230
34377
  config.provider.entries = entries;
34231
34378
  config.provider.active = config.provider.active || config.provider.type;
34232
- saveConfig(config, configPath, dirname18(configPath));
34379
+ saveConfig(config, configPath, dirname19(configPath));
34233
34380
  console.log(pc2.green(t("cli.provider_added", { name })));
34234
34381
  console.log(t("cli.provider_switch_hint"));
34235
34382
  });
@@ -35108,7 +35255,7 @@ class LineEditor {
35108
35255
  // src/cli/repl.ts
35109
35256
  import { existsSync as existsSync55, readFileSync as readFileSync38, writeFileSync as writeFileSync20 } from "fs";
35110
35257
  import { join as join49 } from "path";
35111
- import { homedir as homedir17 } from "os";
35258
+ import { homedir as homedir18 } from "os";
35112
35259
 
35113
35260
  // src/cli/completer.ts
35114
35261
  class SlashCommandProvider {
@@ -35931,10 +36078,10 @@ class Repl {
35931
36078
  this.envReport = envReport;
35932
36079
  this.execModule = execModule;
35933
36080
  this.slog = new SessionLogger(sessionManager, logger);
35934
- this.configDir = configDir || join49(homedir17(), ".mma");
36081
+ this.configDir = configDir || join49(homedir18(), ".mma");
35935
36082
  this.baseDir = baseDir || process.cwd();
35936
36083
  this.noAgentsMd = noAgentsMd === true;
35937
- this.historyPath = historyPath ?? join49(homedir17(), ".mma", "repl-history");
36084
+ this.historyPath = historyPath ?? join49(homedir18(), ".mma", "repl-history");
35938
36085
  this.loadHistory();
35939
36086
  this.rl = process.stdin.isTTY ? new LineEditor({
35940
36087
  input: process.stdin,
@@ -36510,8 +36657,8 @@ init_config2();
36510
36657
  init_i18n();
36511
36658
  init_colors();
36512
36659
  import { existsSync as existsSync56 } from "fs";
36513
- import { join as join51, dirname as dirname20 } from "path";
36514
- import { homedir as homedir19 } from "os";
36660
+ import { join as join51, dirname as dirname21 } from "path";
36661
+ import { homedir as homedir20 } from "os";
36515
36662
 
36516
36663
  // src/modules/updater/index.ts
36517
36664
  init_checker();
@@ -36616,8 +36763,8 @@ init_data_sanitizer();
36616
36763
  init_i18n();
36617
36764
  import { appendFileSync as appendFileSync7, mkdirSync as mkdirSync21 } from "fs";
36618
36765
  import { join as join50 } from "path";
36619
- import { homedir as homedir18 } from "os";
36620
- var CRASH_LOG_DIR = join50(homedir18(), ".mma", "logs");
36766
+ import { homedir as homedir19 } from "os";
36767
+ var CRASH_LOG_DIR = join50(homedir19(), ".mma", "logs");
36621
36768
  var CRASH_LOG_FILE = "crash.jsonl";
36622
36769
  function formatCrashEntry(type2, err) {
36623
36770
  const message = err instanceof Error ? err.message : String(err);
@@ -36627,7 +36774,7 @@ function formatCrashEntry(type2, err) {
36627
36774
  type: type2,
36628
36775
  message: sanitizeLogMessage(message),
36629
36776
  stack: sanitizeLogMessage(stack),
36630
- environment: collectEnvironment({ configDir: homedir18(), scanTools: false })
36777
+ environment: collectEnvironment({ configDir: homedir19(), scanTools: false })
36631
36778
  };
36632
36779
  }
36633
36780
  function writeCrashEntry(dir, entry) {
@@ -36741,7 +36888,7 @@ async function main() {
36741
36888
  await updater?.waitForIdle();
36742
36889
  process.exit(exitCode);
36743
36890
  } else {
36744
- const mmaDir = join51(homedir19(), ".mma");
36891
+ const mmaDir = join51(homedir20(), ".mma");
36745
36892
  const legacyConfigPath = join51(mmaDir, "config.json");
36746
36893
  let hasAnyConfig = existsSync56(legacyConfigPath);
36747
36894
  if (!hasAnyConfig) {
@@ -36806,7 +36953,7 @@ async function main() {
36806
36953
  config.security.paths.denied = [];
36807
36954
  }
36808
36955
  }
36809
- saveConfig(config, legacyConfigPath, dirname20(legacyConfigPath));
36956
+ saveConfig(config, legacyConfigPath, dirname21(legacyConfigPath));
36810
36957
  await agent.reconfigure(config);
36811
36958
  }
36812
36959
  startAutoUpdate(config);