micro-models-agent 0.38.0 → 0.39.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 (2) hide show
  1. package/dist/main.js +524 -386
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -2622,6 +2622,13 @@ Available commands:`,
2622
2622
  "cli.security.recommended_for": "Recommended for",
2623
2623
  "cli.yes": "Yes",
2624
2624
  "cli.no": "No",
2625
+ "cli.plugins.description": "Manage plugins",
2626
+ "cli.plugins.list": "List loaded plugins (name, version, source)",
2627
+ "cli.plugins.all": "Include builtin plugins",
2628
+ "cli.plugins.only_external": "(builtin plugins omitted — use --all to show them)",
2629
+ "cli.plugins.none": "No plugins loaded",
2630
+ "cli.plugins.header": "Plugins: {count} loaded (MMA v{mma})",
2631
+ "cli.plugins.builtin_mark": "●",
2625
2632
  "repl.help": "Show available commands",
2626
2633
  "repl.help_usage": "Usage: /help",
2627
2634
  "repl.exit": "Exit the REPL",
@@ -2831,6 +2838,8 @@ Use this knowledge to answer the user's question.`,
2831
2838
  "pipeline.circular": "Circular dependency: {stepId}",
2832
2839
  "plugin.loaded": "Loaded plugin: {name}",
2833
2840
  "plugin.skipped": "Skipped incompatible plugin: {entry} ({message})",
2841
+ "plugin.incompatible": "Skipped plugin {name}: requires MMA v{min}, current is v{current}",
2842
+ "plugin.dedup_older": "Plugin {name} v{version} skipped: a newer version is already loaded",
2834
2843
  "migration.detected": "[MMA] Detected old config. {summary}",
2835
2844
  "migration.summary": "[MMA] {summary}",
2836
2845
  "migration.config_bak": "- config → config.json.bak",
@@ -3226,6 +3235,13 @@ var init_ru = __esm(() => {
3226
3235
  "cli.security.recommended_for": "Рекомендуется для",
3227
3236
  "cli.yes": "Да",
3228
3237
  "cli.no": "Нет",
3238
+ "cli.plugins.description": "Управление плагинами",
3239
+ "cli.plugins.list": "Список загруженных плагинов (имя, версия, источник)",
3240
+ "cli.plugins.all": "Включить встроенные плагины",
3241
+ "cli.plugins.only_external": "(встроенные плагины скрыты — используйте --all)",
3242
+ "cli.plugins.none": "Плагины не загружены",
3243
+ "cli.plugins.header": "Плагины: {count} загружено (MMA v{mma})",
3244
+ "cli.plugins.builtin_mark": "●",
3229
3245
  "repl.help": "Показать доступные команды",
3230
3246
  "repl.help_usage": "Использование: /help",
3231
3247
  "repl.exit": "Выйти из REPL",
@@ -3439,6 +3455,8 @@ var init_ru = __esm(() => {
3439
3455
  "pipeline.circular": "Циклическая зависимость: {stepId}",
3440
3456
  "plugin.loaded": "Загружен плагин: {name}",
3441
3457
  "plugin.skipped": "Пропущен несовместимый плагин: {entry} ({message})",
3458
+ "plugin.incompatible": "Пропущен плагин {name}: требуется MMA v{min}, текущая v{current}",
3459
+ "plugin.dedup_older": "Плагин {name} v{version} пропущен: уже загружена более новая версия",
3442
3460
  "migration.detected": "[MMA] Обнаружен старый конфиг. {summary}",
3443
3461
  "migration.summary": "[MMA] {summary}",
3444
3462
  "migration.config_bak": "- config → config.json.bak",
@@ -12222,16 +12240,157 @@ var init_detector = __esm(() => {
12222
12240
  init_llm_judge();
12223
12241
  });
12224
12242
 
12243
+ // src/modules/lsp/command.ts
12244
+ import { delimiter, join as join13 } from "path";
12245
+ import { existsSync as existsSync22 } from "fs";
12246
+ import { platform as platform3 } from "os";
12247
+ function resolveSpawnCommand(command, platformName = platform3(), pathEnv = process.env.PATH ?? "") {
12248
+ if (platformName !== "win32")
12249
+ return command;
12250
+ if (command.includes("/") || command.includes("\\") || WIN_EXTS.some((ext) => command.toLowerCase().endsWith(ext))) {
12251
+ return command;
12252
+ }
12253
+ const dirs = pathEnv.split(delimiter).filter(Boolean);
12254
+ for (const dir of dirs) {
12255
+ for (const ext of WIN_EXTS) {
12256
+ const candidate = join13(dir, `${command}${ext}`);
12257
+ if (existsSync22(candidate))
12258
+ return `${command}${ext}`;
12259
+ }
12260
+ }
12261
+ return command;
12262
+ }
12263
+ function buildWinCommandLine(command, args) {
12264
+ const quote = (part) => {
12265
+ if (part === "")
12266
+ return '""';
12267
+ if (!/[\s"&|^<>()%!]/.test(part))
12268
+ return part;
12269
+ return `"${part.replace(/"/g, "\\\"")}"`;
12270
+ };
12271
+ return [command, ...args].map(quote).join(" ");
12272
+ }
12273
+ var WIN_EXTS;
12274
+ var init_command = __esm(() => {
12275
+ WIN_EXTS = [".cmd", ".bat", ".exe", ".com"];
12276
+ });
12277
+
12278
+ // src/modules/updater/checker.ts
12279
+ import { platform as platform4 } from "os";
12280
+ function semverGt(a, b) {
12281
+ const pa = a.replace(/^v/, "").split(/[.-]/).map((p) => Number.parseInt(p, 10) || 0);
12282
+ const pb = b.replace(/^v/, "").split(/[.-]/).map((p) => Number.parseInt(p, 10) || 0);
12283
+ for (let i = 0;i < 3; i++) {
12284
+ const na = pa[i] ?? 0;
12285
+ const nb = pb[i] ?? 0;
12286
+ if (na !== nb)
12287
+ return na > nb;
12288
+ }
12289
+ return false;
12290
+ }
12291
+
12292
+ class Updater {
12293
+ currentVersion;
12294
+ packageName;
12295
+ runner;
12296
+ constructor(currentVersion, packageName, runner) {
12297
+ this.currentVersion = currentVersion;
12298
+ this.packageName = packageName;
12299
+ this.runner = runner ?? defaultRunner;
12300
+ }
12301
+ getCurrentVersion() {
12302
+ return this.currentVersion;
12303
+ }
12304
+ getPackageName() {
12305
+ return this.packageName;
12306
+ }
12307
+ async check() {
12308
+ try {
12309
+ const response = await fetch(`https://registry.npmjs.org/${this.packageName}`, {
12310
+ headers: { Accept: "application/vnd.npm.install-v1+json" },
12311
+ signal: AbortSignal.timeout(5000)
12312
+ });
12313
+ if (!response.ok) {
12314
+ return { updateAvailable: false, current: this.currentVersion, error: `HTTP ${response.status}` };
12315
+ }
12316
+ const data = await response.json();
12317
+ const latest = data["dist-tags"]?.latest;
12318
+ if (!latest) {
12319
+ return { updateAvailable: false, current: this.currentVersion, error: "No latest tag" };
12320
+ }
12321
+ const updateAvailable = semverGt(latest, this.currentVersion);
12322
+ return { updateAvailable, current: this.currentVersion, latest };
12323
+ } catch (e) {
12324
+ return { updateAvailable: false, current: this.currentVersion, error: e.message };
12325
+ }
12326
+ }
12327
+ async install(latest) {
12328
+ try {
12329
+ const { command, args } = this.buildInstallCommand(latest);
12330
+ const res = await this.runner(command, args, {
12331
+ timeout: 120000,
12332
+ windowsHide: true
12333
+ });
12334
+ if (res.error)
12335
+ return { success: false, error: res.error };
12336
+ return { success: true, installed: latest };
12337
+ } catch (e) {
12338
+ const msg = e?.message ?? String(e);
12339
+ return { success: false, error: msg.split(`
12340
+ `)[0] };
12341
+ }
12342
+ }
12343
+ buildInstallCommand(latest) {
12344
+ const npmArgs = ["install", "-g", `${this.packageName}@${latest}`];
12345
+ const command = resolveSpawnCommand("npm");
12346
+ if (platform4() === "win32" && /\.(cmd|bat)$/i.test(command)) {
12347
+ return { command: "cmd.exe", args: ["/c", command, ...npmArgs] };
12348
+ }
12349
+ return { command, args: npmArgs };
12350
+ }
12351
+ }
12352
+ var defaultRunner = async (command, args, options) => {
12353
+ const { execFile } = await import("child_process");
12354
+ return new Promise((resolve13) => {
12355
+ execFile(command, args, options, (err) => resolve13({ error: err?.message }));
12356
+ });
12357
+ };
12358
+ var init_checker = __esm(() => {
12359
+ init_command();
12360
+ });
12361
+
12225
12362
  // src/modules/plugins/manager.ts
12226
12363
  class PluginManager {
12227
12364
  plugins = [];
12228
- register(plugin) {
12365
+ register(plugin, source) {
12366
+ if (source)
12367
+ plugin.source = source;
12368
+ const existing = this.plugins.find((p) => p.name === plugin.name);
12369
+ if (existing) {
12370
+ if (semverGt(plugin.version || "0.0.0", existing.version || "0.0.0")) {
12371
+ this.plugins = this.plugins.filter((p) => p.name !== plugin.name);
12372
+ this.plugins.push(plugin);
12373
+ this.sort();
12374
+ return { status: "registered" };
12375
+ }
12376
+ return { status: "skipped_older", existing };
12377
+ }
12229
12378
  this.plugins.push(plugin);
12379
+ this.sort();
12380
+ return { status: "registered" };
12381
+ }
12382
+ sort() {
12230
12383
  this.plugins.sort((a, b) => (b.priority || 0) - (a.priority || 0));
12231
12384
  }
12232
12385
  getAllPlugins() {
12233
12386
  return [...this.plugins];
12234
12387
  }
12388
+ getPluginInfos() {
12389
+ return [...this.plugins].map((plugin) => ({ plugin, source: plugin.source }));
12390
+ }
12391
+ getPlugin(name) {
12392
+ return this.plugins.find((p) => p.name === name) ?? null;
12393
+ }
12235
12394
  runOnBuildPrompt() {
12236
12395
  return this.plugins.map((p) => {
12237
12396
  try {
@@ -12368,6 +12527,9 @@ class PluginManager {
12368
12527
  return chunk;
12369
12528
  }
12370
12529
  }
12530
+ var init_manager2 = __esm(() => {
12531
+ init_checker();
12532
+ });
12371
12533
 
12372
12534
  // src/tools/subagent.ts
12373
12535
  function buildSubagentSystemPrompt(context, stable) {
@@ -12387,6 +12549,7 @@ var init_subagent = __esm(() => {
12387
12549
  init_agent();
12388
12550
  init_manager();
12389
12551
  init_detector();
12552
+ init_manager2();
12390
12553
  init_audit_log();
12391
12554
  init_session_isolation();
12392
12555
  init_store();
@@ -13441,6 +13604,7 @@ var init_pipeline_run = __esm(() => {
13441
13604
  init_parser();
13442
13605
  init_agent();
13443
13606
  init_manager();
13607
+ init_manager2();
13444
13608
  init_detector();
13445
13609
  init_audit_log();
13446
13610
  init_session_isolation();
@@ -14024,7 +14188,7 @@ ${JSON.stringify(result, null, 2)}`
14024
14188
 
14025
14189
  // src/tools/search-history.ts
14026
14190
  import * as fs from "fs";
14027
- import { join as join13 } from "path";
14191
+ import { join as join14 } from "path";
14028
14192
  import { homedir as homedir5 } from "os";
14029
14193
  function searchFile(filePath, query, maxResults, results) {
14030
14194
  if (!fs.existsSync(filePath))
@@ -14068,7 +14232,7 @@ var init_search_history = __esm(() => {
14068
14232
  const query = String(args.query || "").toLowerCase();
14069
14233
  const maxResults = Number(args.maxResults) || 5;
14070
14234
  const sessionId = args.sessionId ? String(args.sessionId) : null;
14071
- const sessionDir = join13(homedir5(), ".mma", "sessions");
14235
+ const sessionDir = join14(homedir5(), ".mma", "sessions");
14072
14236
  const results = [];
14073
14237
  try {
14074
14238
  if (!fs.existsSync(sessionDir)) {
@@ -14083,7 +14247,7 @@ var init_search_history = __esm(() => {
14083
14247
  continue;
14084
14248
  if (sessionId && entry.name !== sessionId)
14085
14249
  continue;
14086
- const historyFile = join13(sessionDir, entry.name, "history.jsonl");
14250
+ const historyFile = join14(sessionDir, entry.name, "history.jsonl");
14087
14251
  searchFile(historyFile, query, maxResults, results);
14088
14252
  if (results.length >= maxResults)
14089
14253
  break;
@@ -14110,8 +14274,8 @@ var init_search_history = __esm(() => {
14110
14274
  });
14111
14275
 
14112
14276
  // src/modules/memory/search.ts
14113
- import { readFileSync as readFileSync12, existsSync as existsSync23 } from "fs";
14114
- import { join as join14 } from "path";
14277
+ import { readFileSync as readFileSync12, existsSync as existsSync24 } from "fs";
14278
+ import { join as join15 } from "path";
14115
14279
 
14116
14280
  class MemorySearch {
14117
14281
  memoryDir;
@@ -14122,8 +14286,8 @@ class MemorySearch {
14122
14286
  const results = [];
14123
14287
  const lowerQuery = query.toLowerCase();
14124
14288
  for (const name of MEMORY_FILES) {
14125
- const path = join14(this.memoryDir, `${name}.md`);
14126
- if (!existsSync23(path))
14289
+ const path = join15(this.memoryDir, `${name}.md`);
14290
+ if (!existsSync24(path))
14127
14291
  continue;
14128
14292
  const content = readFileSync12(path, "utf-8");
14129
14293
  const lines = content.split(`
@@ -14134,8 +14298,8 @@ class MemorySearch {
14134
14298
  }
14135
14299
  }
14136
14300
  }
14137
- const prefsPath = join14(this.memoryDir, "preferences.json");
14138
- if (existsSync23(prefsPath)) {
14301
+ const prefsPath = join15(this.memoryDir, "preferences.json");
14302
+ if (existsSync24(prefsPath)) {
14139
14303
  try {
14140
14304
  const prefs = JSON.parse(readFileSync12(prefsPath, "utf-8"));
14141
14305
  for (const [key, value] of Object.entries(prefs)) {
@@ -14155,8 +14319,8 @@ var init_search = __esm(() => {
14155
14319
  });
14156
14320
 
14157
14321
  // src/modules/memory/store.ts
14158
- import { readFileSync as readFileSync13, writeFileSync as writeFileSync9, appendFileSync as appendFileSync5, existsSync as existsSync24, mkdirSync as mkdirSync13 } from "fs";
14159
- import { join as join15 } from "path";
14322
+ import { readFileSync as readFileSync13, writeFileSync as writeFileSync9, appendFileSync as appendFileSync5, existsSync as existsSync25, mkdirSync as mkdirSync13 } from "fs";
14323
+ import { join as join16 } from "path";
14160
14324
 
14161
14325
  class MemoryStore {
14162
14326
  memoryDir;
@@ -14164,8 +14328,8 @@ class MemoryStore {
14164
14328
  this.memoryDir = memoryDir;
14165
14329
  this.ensureDir();
14166
14330
  for (const name of MEMORY_FILES2) {
14167
- const path = join15(this.memoryDir, `${name}.md`);
14168
- if (!existsSync24(path)) {
14331
+ const path = join16(this.memoryDir, `${name}.md`);
14332
+ if (!existsSync25(path)) {
14169
14333
  writeFileSync9(path, `# ${name.charAt(0).toUpperCase() + name.slice(1)}
14170
14334
 
14171
14335
  `, "utf-8");
@@ -14173,18 +14337,18 @@ class MemoryStore {
14173
14337
  }
14174
14338
  }
14175
14339
  ensureDir() {
14176
- if (!existsSync24(this.memoryDir)) {
14340
+ if (!existsSync25(this.memoryDir)) {
14177
14341
  mkdirSync13(this.memoryDir, { recursive: true });
14178
14342
  }
14179
14343
  }
14180
14344
  read(name) {
14181
- const path = join15(this.memoryDir, `${name}.md`);
14182
- if (!existsSync24(path))
14345
+ const path = join16(this.memoryDir, `${name}.md`);
14346
+ if (!existsSync25(path))
14183
14347
  return "";
14184
14348
  return readFileSync13(path, "utf-8");
14185
14349
  }
14186
14350
  append(name, entry) {
14187
- const path = join15(this.memoryDir, `${name}.md`);
14351
+ const path = join16(this.memoryDir, `${name}.md`);
14188
14352
  const timestamp = new Date().toISOString().replace("T", " ").slice(0, 19);
14189
14353
  const formatted = `- **${timestamp}** — ${entry}
14190
14354
  `;
@@ -14195,11 +14359,11 @@ class MemoryStore {
14195
14359
  return searchModule.query(query);
14196
14360
  }
14197
14361
  prefsPath() {
14198
- return join15(this.memoryDir, "preferences.json");
14362
+ return join16(this.memoryDir, "preferences.json");
14199
14363
  }
14200
14364
  getPreferences() {
14201
14365
  const path = this.prefsPath();
14202
- if (!existsSync24(path))
14366
+ if (!existsSync25(path))
14203
14367
  return {};
14204
14368
  try {
14205
14369
  return JSON.parse(readFileSync13(path, "utf-8"));
@@ -14235,7 +14399,7 @@ var init_store2 = __esm(() => {
14235
14399
 
14236
14400
  // src/tools/remember.ts
14237
14401
  import { homedir as homedir6 } from "os";
14238
- import { join as join16 } from "path";
14402
+ import { join as join17 } from "path";
14239
14403
  var CATEGORIES, rememberTool;
14240
14404
  var init_remember = __esm(() => {
14241
14405
  init_i18n();
@@ -14273,7 +14437,7 @@ var init_remember = __esm(() => {
14273
14437
  if (!CATEGORIES.includes(category)) {
14274
14438
  return { success: false, output: t("tool.invalid_params") };
14275
14439
  }
14276
- const memoryDir = join16(homedir6(), ".mma", "memory");
14440
+ const memoryDir = join17(homedir6(), ".mma", "memory");
14277
14441
  const store = new MemoryStore(memoryDir);
14278
14442
  try {
14279
14443
  if (category === "preferences") {
@@ -14306,7 +14470,7 @@ var init_remember = __esm(() => {
14306
14470
 
14307
14471
  // src/tools/recall.ts
14308
14472
  import { homedir as homedir7 } from "os";
14309
- import { join as join17 } from "path";
14473
+ import { join as join18 } from "path";
14310
14474
  function formatAll(store) {
14311
14475
  const parts = [];
14312
14476
  const prefs = store.getPreferences();
@@ -14389,7 +14553,7 @@ var init_recall = __esm(() => {
14389
14553
  handler: async (_ctx, args) => {
14390
14554
  const query = args.query ? String(args.query) : "";
14391
14555
  const category = args.category ? String(args.category) : "";
14392
- const memoryDir = join17(homedir7(), ".mma", "memory");
14556
+ const memoryDir = join18(homedir7(), ".mma", "memory");
14393
14557
  const store = new MemoryStore(memoryDir);
14394
14558
  try {
14395
14559
  if (!query && !category) {
@@ -14421,9 +14585,9 @@ var init_recall = __esm(() => {
14421
14585
  });
14422
14586
 
14423
14587
  // src/modules/browser/bridge-path.ts
14424
- import { existsSync as existsSync25 } from "fs";
14588
+ import { existsSync as existsSync26 } from "fs";
14425
14589
  function pickExistingPath(candidates, fallback = candidates[0]) {
14426
- return candidates.find((p) => existsSync25(p)) ?? fallback;
14590
+ return candidates.find((p) => existsSync26(p)) ?? fallback;
14427
14591
  }
14428
14592
  var init_bridge_path = () => {};
14429
14593
 
@@ -14434,13 +14598,13 @@ __export(exports_bridge_client, {
14434
14598
  });
14435
14599
  import { spawn as spawn4 } from "child_process";
14436
14600
  import { createInterface } from "readline";
14437
- import { dirname as dirname9, join as join18 } from "path";
14601
+ import { dirname as dirname9, join as join19 } from "path";
14438
14602
  import { fileURLToPath } from "url";
14439
14603
  function bridgeScriptPath() {
14440
14604
  const dir = dirname9(fileURLToPath(import.meta.url));
14441
14605
  const candidates = [
14442
- join18(dir, "bridge-server.mjs"),
14443
- join18(dir, "modules", "browser", "bridge-server.mjs")
14606
+ join19(dir, "bridge-server.mjs"),
14607
+ join19(dir, "modules", "browser", "bridge-server.mjs")
14444
14608
  ];
14445
14609
  return pickExistingPath(candidates);
14446
14610
  }
@@ -15000,15 +15164,15 @@ function buildTextExtractionScript() {
15000
15164
 
15001
15165
  // src/modules/browser/cookie-store.ts
15002
15166
  import { readFile, writeFile, mkdir } from "fs/promises";
15003
- import { join as join19 } from "path";
15167
+ import { join as join20 } from "path";
15004
15168
 
15005
15169
  class CookieStore {
15006
15170
  filePath;
15007
15171
  constructor(cookieDir) {
15008
- this.filePath = join19(cookieDir, "cookies.json");
15172
+ this.filePath = join20(cookieDir, "cookies.json");
15009
15173
  }
15010
15174
  async save(cookies) {
15011
- await mkdir(join19(this.filePath, ".."), { recursive: true });
15175
+ await mkdir(join20(this.filePath, ".."), { recursive: true });
15012
15176
  await writeFile(this.filePath, JSON.stringify(cookies, null, 2), "utf-8");
15013
15177
  }
15014
15178
  async load() {
@@ -15363,10 +15527,10 @@ var init_session = __esm(() => {
15363
15527
  });
15364
15528
 
15365
15529
  // src/tools/browser.ts
15366
- import { join as join20 } from "path";
15530
+ import { join as join21 } from "path";
15367
15531
  function getSession(ctx) {
15368
15532
  if (!session) {
15369
- const cookieDir = join20(ctx.baseDir, ".mma", "browser");
15533
+ const cookieDir = join21(ctx.baseDir, ".mma", "browser");
15370
15534
  session = new BrowserSession({
15371
15535
  ...DEFAULT_BROWSER_CONFIG,
15372
15536
  headless: ctx.config.browser?.headless ?? true,
@@ -15499,13 +15663,13 @@ async function readClipboardImage() {
15499
15663
  return readClipboardFallback();
15500
15664
  }
15501
15665
  async function readClipboardFallback() {
15502
- const { platform: platform3 } = await import("os");
15666
+ const { platform: platform5 } = await import("os");
15503
15667
  const { execSync } = await import("child_process");
15504
15668
  const { readFileSync: readFileSync15, unlinkSync: unlinkSync4 } = await import("fs");
15505
- const { join: join21 } = await import("path");
15506
- const tmpPath = join21(process.env.TEMP || process.env.TMP || "/tmp", `mma-clip-${Date.now()}.png`);
15669
+ const { join: join22 } = await import("path");
15670
+ const tmpPath = join22(process.env.TEMP || process.env.TMP || "/tmp", `mma-clip-${Date.now()}.png`);
15507
15671
  try {
15508
- if (platform3() === "linux") {
15672
+ if (platform5() === "linux") {
15509
15673
  execSync(`xclip -selection clipboard -t image/png -o > "${tmpPath}" 2>/dev/null`, { timeout: 5000 });
15510
15674
  } else {
15511
15675
  return null;
@@ -15581,7 +15745,7 @@ var init_image_utils = __esm(() => {
15581
15745
  });
15582
15746
 
15583
15747
  // src/tools/attach-image.ts
15584
- import { existsSync as existsSync26 } from "fs";
15748
+ import { existsSync as existsSync27 } from "fs";
15585
15749
  import { resolve as resolve15 } from "path";
15586
15750
  var attachImageTool;
15587
15751
  var init_attach_image = __esm(() => {
@@ -15624,7 +15788,7 @@ var init_attach_image = __esm(() => {
15624
15788
  dataUrl = result.dataUrl;
15625
15789
  } else {
15626
15790
  const absPath = resolve15(ctx.baseDir, source);
15627
- if (!existsSync26(absPath)) {
15791
+ if (!existsSync27(absPath)) {
15628
15792
  return {
15629
15793
  success: false,
15630
15794
  output: t("image.not_found", { path: source })
@@ -15786,44 +15950,59 @@ class ModuleRegistry {
15786
15950
  }
15787
15951
 
15788
15952
  // src/modules/plugins/loader.ts
15789
- import { readdirSync as readdirSync7, existsSync as existsSync27, statSync as statSync5 } from "fs";
15790
- import { join as join21, basename as basename2 } from "path";
15953
+ import { readdirSync as readdirSync7, existsSync as existsSync28, statSync as statSync5 } from "fs";
15954
+ import { join as join22, basename as basename2 } from "path";
15791
15955
 
15792
15956
  class PluginLoader {
15793
- loadFromDir(dirPath, pluginManager, logger) {
15794
- if (!existsSync27(dirPath))
15957
+ loadFromDir(dirPath, pluginManager, logger, options) {
15958
+ if (!existsSync28(dirPath))
15795
15959
  return;
15796
15960
  const entries = readdirSync7(dirPath).sort();
15797
15961
  for (const entry of entries) {
15798
- const fullPath = join21(dirPath, entry);
15962
+ const fullPath = join22(dirPath, entry);
15799
15963
  const stat = statSync5(fullPath);
15800
15964
  if (stat.isFile()) {
15801
15965
  if (!entry.endsWith(".ts") && !entry.endsWith(".js"))
15802
15966
  continue;
15803
- this.tryLoad(fullPath, entry, pluginManager, logger);
15967
+ this.tryLoad(fullPath, entry, pluginManager, logger, options);
15804
15968
  } else if (stat.isDirectory()) {
15805
15969
  const entryFile = this.findEntryFile(fullPath);
15806
15970
  if (entryFile) {
15807
- this.tryLoad(entryFile, `${entry}/${basename2(entryFile)}`, pluginManager, logger);
15971
+ this.tryLoad(entryFile, `${entry}/${basename2(entryFile)}`, pluginManager, logger, options);
15808
15972
  }
15809
15973
  }
15810
15974
  }
15811
15975
  }
15812
15976
  findEntryFile(dir) {
15813
15977
  for (const name of FOLDER_ENTRY_NAMES) {
15814
- const candidate = join21(dir, name);
15815
- if (existsSync27(candidate))
15978
+ const candidate = join22(dir, name);
15979
+ if (existsSync28(candidate))
15816
15980
  return candidate;
15817
15981
  }
15818
15982
  return null;
15819
15983
  }
15820
- tryLoad(fullPath, label, pluginManager, logger) {
15984
+ tryLoad(fullPath, label, pluginManager, logger, options) {
15821
15985
  try {
15822
15986
  const mod = __require(fullPath);
15823
15987
  const plugin = mod.default || mod.plugin;
15824
15988
  if (plugin && plugin.name) {
15825
- pluginManager.register(plugin);
15826
- logger?.warn(t("plugin.loaded", { name: plugin.name }));
15989
+ if (plugin.minMmaVersion && options?.mmaVersion && semverGt(plugin.minMmaVersion, options.mmaVersion)) {
15990
+ logger?.warn(t("plugin.incompatible", {
15991
+ name: plugin.name,
15992
+ min: plugin.minMmaVersion,
15993
+ current: options.mmaVersion
15994
+ }));
15995
+ return;
15996
+ }
15997
+ const result = pluginManager.register(plugin, options?.source);
15998
+ if (result.status === "registered") {
15999
+ logger?.warn(t("plugin.loaded", { name: plugin.name }));
16000
+ } else if (result.status === "skipped_older") {
16001
+ logger?.warn(t("plugin.dedup_older", {
16002
+ name: plugin.name,
16003
+ version: plugin.version || "0.0.0"
16004
+ }));
16005
+ }
15827
16006
  }
15828
16007
  } catch (e) {
15829
16008
  logger?.warn(t("plugin.skipped", { entry: label, message: e.message }));
@@ -15833,14 +16012,15 @@ class PluginLoader {
15833
16012
  var FOLDER_ENTRY_NAMES;
15834
16013
  var init_loader = __esm(() => {
15835
16014
  init_i18n();
16015
+ init_checker();
15836
16016
  FOLDER_ENTRY_NAMES = ["plugin.ts", "plugin.js", "index.ts", "index.js"];
15837
16017
  });
15838
16018
 
15839
16019
  // src/modules/plugins/builtin/lint-on-write.ts
15840
16020
  import { spawn as spawn5, execSync } from "child_process";
15841
- import { existsSync as existsSync28, readFileSync as readFileSync15 } from "fs";
15842
- import { resolve as resolve16, extname as extname4, join as join22 } from "path";
15843
- import { platform as platform3 } from "os";
16021
+ import { existsSync as existsSync29, readFileSync as readFileSync15 } from "fs";
16022
+ import { resolve as resolve16, extname as extname4, join as join23 } from "path";
16023
+ import { platform as platform5 } from "os";
15844
16024
  function contentHash(content) {
15845
16025
  let h = 5381;
15846
16026
  for (let i = 0;i < content.length; i++) {
@@ -15850,7 +16030,7 @@ function contentHash(content) {
15850
16030
  }
15851
16031
  function getWinDecoder() {
15852
16032
  if (_winDecoder === undefined) {
15853
- if (platform3() !== "win32") {
16033
+ if (platform5() !== "win32") {
15854
16034
  _winDecoder = null;
15855
16035
  } else {
15856
16036
  try {
@@ -15872,6 +16052,7 @@ function getWinDecoder() {
15872
16052
  class LintOnWritePlugin {
15873
16053
  name = "lint-on-write";
15874
16054
  priority = 10;
16055
+ isBuiltin = true;
15875
16056
  _checkPromise = null;
15876
16057
  _checkTimestamp = 0;
15877
16058
  async onAfterTool(ctx, call, result) {
@@ -15885,7 +16066,7 @@ class LintOnWritePlugin {
15885
16066
  if (!path)
15886
16067
  return;
15887
16068
  const fullPath = resolve16(ctx.baseDir, path);
15888
- if (!existsSync28(fullPath))
16069
+ if (!existsSync29(fullPath))
15889
16070
  return;
15890
16071
  const ext = extname4(fullPath);
15891
16072
  const syntaxError = await this.checkSyntax(fullPath, ext, ctx.baseDir);
@@ -15941,8 +16122,8 @@ class LintOnWritePlugin {
15941
16122
  }
15942
16123
  async runProjectLint(ctx, result) {
15943
16124
  try {
15944
- const packageJsonPath = join22(ctx.baseDir, "package.json");
15945
- if (!existsSync28(packageJsonPath)) {
16125
+ const packageJsonPath = join23(ctx.baseDir, "package.json");
16126
+ if (!existsSync29(packageJsonPath)) {
15946
16127
  return;
15947
16128
  }
15948
16129
  const packageJson = JSON.parse(readFileSync15(packageJsonPath, "utf-8"));
@@ -15965,8 +16146,8 @@ class LintOnWritePlugin {
15965
16146
  "tsconfig.json",
15966
16147
  "package.json"
15967
16148
  ]);
15968
- const tsconfigPath = join22(projectRoot, "tsconfig.json");
15969
- if (!existsSync28(tsconfigPath)) {
16149
+ const tsconfigPath = join23(projectRoot, "tsconfig.json");
16150
+ if (!existsSync29(tsconfigPath)) {
15970
16151
  return;
15971
16152
  }
15972
16153
  const now = Date.now();
@@ -16058,6 +16239,7 @@ var init_lint_on_write = __esm(() => {
16058
16239
  class NotifyPlugin {
16059
16240
  name = "notify";
16060
16241
  priority = 5;
16242
+ isBuiltin = true;
16061
16243
  onSessionEnd(ctx) {
16062
16244
  ctx.logger.info("Session ended");
16063
16245
  }
@@ -16214,8 +16396,8 @@ class PlanTracker {
16214
16396
  var init_tracker = () => {};
16215
16397
 
16216
16398
  // src/modules/execution/audit-runners.ts
16217
- import { existsSync as existsSync29, readdirSync as readdirSync8 } from "fs";
16218
- import { dirname as dirname10, join as join23, resolve as resolve17 } from "path";
16399
+ import { existsSync as existsSync30, readdirSync as readdirSync8 } from "fs";
16400
+ import { dirname as dirname10, join as join24, resolve as resolve17 } from "path";
16219
16401
  function findTestFile(dir, depth = 0) {
16220
16402
  if (depth > 5)
16221
16403
  return null;
@@ -16226,7 +16408,7 @@ function findTestFile(dir, depth = 0) {
16226
16408
  return null;
16227
16409
  }
16228
16410
  for (const e of entries) {
16229
- const full = join23(dir, e.name);
16411
+ const full = join24(dir, e.name);
16230
16412
  if (e.isDirectory()) {
16231
16413
  if (SKIP_DIRS.has(e.name))
16232
16414
  continue;
@@ -16301,7 +16483,7 @@ function findTypecheckRoot(baseDir, existingFiles = []) {
16301
16483
  for (const start of candidates) {
16302
16484
  let dir = resolve17(start);
16303
16485
  for (let depth = 0;depth <= 10; depth++) {
16304
- if (existsSync29(join23(dir, "tsconfig.json"))) {
16486
+ if (existsSync30(join24(dir, "tsconfig.json"))) {
16305
16487
  if (!best || depth < best.depth)
16306
16488
  best = { depth, root: dir };
16307
16489
  break;
@@ -16344,11 +16526,11 @@ var init_audit_runners = __esm(() => {
16344
16526
  });
16345
16527
 
16346
16528
  // src/modules/execution/auditor.ts
16347
- import { existsSync as existsSync30, readdirSync as readdirSync9 } from "fs";
16348
- import { resolve as resolve18, join as join24, basename as basename3 } from "path";
16529
+ import { existsSync as existsSync31, readdirSync as readdirSync9 } from "fs";
16530
+ import { resolve as resolve18, join as join25, basename as basename3 } from "path";
16349
16531
  function findExistingFile(baseDir, filePath) {
16350
16532
  const direct = resolve18(baseDir, filePath);
16351
- if (existsSync30(direct))
16533
+ if (existsSync31(direct))
16352
16534
  return direct;
16353
16535
  const name = basename3(filePath).toLowerCase();
16354
16536
  const suffix = filePath.replace(/\\/g, "/").toLowerCase();
@@ -16365,7 +16547,7 @@ function findExistingFile(baseDir, filePath) {
16365
16547
  for (const e of entries) {
16366
16548
  if (found)
16367
16549
  return;
16368
- const full = join24(dir, e.name);
16550
+ const full = join25(dir, e.name);
16369
16551
  if (e.isDirectory()) {
16370
16552
  if (SKIP_DIRS.has(e.name))
16371
16553
  continue;
@@ -16503,8 +16685,8 @@ var init_auditor = __esm(() => {
16503
16685
  });
16504
16686
 
16505
16687
  // src/modules/execution/plan-store.ts
16506
- import { readFileSync as readFileSync16, writeFileSync as writeFileSync10, mkdirSync as mkdirSync14, existsSync as existsSync31, readdirSync as readdirSync10, rmSync } from "fs";
16507
- import { join as join25 } from "path";
16688
+ import { readFileSync as readFileSync16, writeFileSync as writeFileSync10, mkdirSync as mkdirSync14, existsSync as existsSync32, readdirSync as readdirSync10, rmSync } from "fs";
16689
+ import { join as join26 } from "path";
16508
16690
  function readPlanFile(path, fallbackBaseDir) {
16509
16691
  try {
16510
16692
  const raw = readFileSync16(path, "utf-8");
@@ -16529,10 +16711,10 @@ function writePlanFile(path, plan) {
16529
16711
  writeFileSync10(path, JSON.stringify(plan, null, 2), "utf-8");
16530
16712
  }
16531
16713
  function listDir(dir, baseDir) {
16532
- if (!existsSync31(dir))
16714
+ if (!existsSync32(dir))
16533
16715
  return [];
16534
16716
  const files = readdirSync10(dir).filter((f) => f.endsWith(".json"));
16535
- return files.map((f) => readPlanFile(join25(dir, f), baseDir)).filter((p) => p !== null);
16717
+ return files.map((f) => readPlanFile(join26(dir, f), baseDir)).filter((p) => p !== null);
16536
16718
  }
16537
16719
  function toMeta(plan, status) {
16538
16720
  return {
@@ -16553,33 +16735,33 @@ class PlanStore {
16553
16735
  archiveDir;
16554
16736
  legacyPath;
16555
16737
  constructor(baseDir) {
16556
- const mmaDir = join25(baseDir, ".mma");
16557
- if (!existsSync31(mmaDir))
16738
+ const mmaDir = join26(baseDir, ".mma");
16739
+ if (!existsSync32(mmaDir))
16558
16740
  mkdirSync14(mmaDir, { recursive: true });
16559
16741
  this.baseDir = baseDir;
16560
- this.plansDir = join25(mmaDir, "plans");
16561
- this.draftsDir = join25(this.plansDir, "drafts");
16562
- this.archiveDir = join25(this.plansDir, "archive");
16563
- this.legacyPath = join25(mmaDir, LEGACY_FILE);
16742
+ this.plansDir = join26(mmaDir, "plans");
16743
+ this.draftsDir = join26(this.plansDir, "drafts");
16744
+ this.archiveDir = join26(this.plansDir, "archive");
16745
+ this.legacyPath = join26(mmaDir, LEGACY_FILE);
16564
16746
  for (const dir of [this.plansDir, this.draftsDir, this.archiveDir]) {
16565
- if (!existsSync31(dir))
16747
+ if (!existsSync32(dir))
16566
16748
  mkdirSync14(dir, { recursive: true });
16567
16749
  }
16568
16750
  }
16569
16751
  activePath() {
16570
- return join25(this.plansDir, "active.json");
16752
+ return join26(this.plansDir, "active.json");
16571
16753
  }
16572
16754
  saveActive(plan) {
16573
16755
  writePlanFile(this.activePath(), plan);
16574
16756
  }
16575
16757
  loadActive() {
16576
16758
  const activePath = this.activePath();
16577
- if (existsSync31(activePath)) {
16759
+ if (existsSync32(activePath)) {
16578
16760
  const plan = readPlanFile(activePath, this.baseDir);
16579
16761
  if (plan)
16580
16762
  return plan;
16581
16763
  }
16582
- if (existsSync31(this.legacyPath)) {
16764
+ if (existsSync32(this.legacyPath)) {
16583
16765
  const legacy = readPlanFile(this.legacyPath, this.baseDir);
16584
16766
  if (legacy) {
16585
16767
  this.saveActive(legacy);
@@ -16593,26 +16775,26 @@ class PlanStore {
16593
16775
  }
16594
16776
  clearActive() {
16595
16777
  const p = this.activePath();
16596
- if (existsSync31(p))
16778
+ if (existsSync32(p))
16597
16779
  rmSync(p, { force: true });
16598
16780
  }
16599
16781
  saveDraft(plan) {
16600
- writePlanFile(join25(this.draftsDir, `${plan.id}.json`), plan);
16782
+ writePlanFile(join26(this.draftsDir, `${plan.id}.json`), plan);
16601
16783
  }
16602
16784
  loadDraft(id) {
16603
- const p = join25(this.draftsDir, `${id}.json`);
16604
- return existsSync31(p) ? readPlanFile(p, this.baseDir) : null;
16785
+ const p = join26(this.draftsDir, `${id}.json`);
16786
+ return existsSync32(p) ? readPlanFile(p, this.baseDir) : null;
16605
16787
  }
16606
16788
  removeDraft(id) {
16607
- const p = join25(this.draftsDir, `${id}.json`);
16608
- if (existsSync31(p))
16789
+ const p = join26(this.draftsDir, `${id}.json`);
16790
+ if (existsSync32(p))
16609
16791
  rmSync(p, { force: true });
16610
16792
  }
16611
16793
  listDrafts() {
16612
16794
  return listDir(this.draftsDir, this.baseDir);
16613
16795
  }
16614
16796
  archivePlan(plan) {
16615
- writePlanFile(join25(this.archiveDir, `${plan.id}.json`), plan);
16797
+ writePlanFile(join26(this.archiveDir, `${plan.id}.json`), plan);
16616
16798
  this.removeDraft(plan.id);
16617
16799
  const active = this.loadActive();
16618
16800
  if (active && active.id === plan.id) {
@@ -16623,8 +16805,8 @@ class PlanStore {
16623
16805
  return listDir(this.archiveDir, this.baseDir);
16624
16806
  }
16625
16807
  removeArchived(id) {
16626
- const p = join25(this.archiveDir, `${id}.json`);
16627
- if (existsSync31(p))
16808
+ const p = join26(this.archiveDir, `${id}.json`);
16809
+ if (existsSync32(p))
16628
16810
  rmSync(p, { force: true });
16629
16811
  }
16630
16812
  listAll() {
@@ -17203,7 +17385,7 @@ var init_windows_commands = __esm(() => {
17203
17385
  });
17204
17386
 
17205
17387
  // src/modules/execution/execution-plugin.ts
17206
- import { platform as platform4 } from "os";
17388
+ import { platform as platform6 } from "os";
17207
17389
  function createExecutionPlugin(deps) {
17208
17390
  return {
17209
17391
  name: "execution",
@@ -17347,7 +17529,7 @@ Tool "${deps.stuckDetector.getLastFailedTool()}" is failing. Try "${alternative}
17347
17529
  deps.stuckDetector.recordToolError(call.name, toolText.slice(0, 300));
17348
17530
  }
17349
17531
  if (!result.success) {
17350
- if (call.name === "bash" && platform4() === "win32") {
17532
+ if (call.name === "bash" && platform6() === "win32") {
17351
17533
  const cmd = String(call.arguments?.command ?? "");
17352
17534
  const forbidden = forbiddenWindowsCommand(cmd);
17353
17535
  if (forbidden) {
@@ -17426,7 +17608,7 @@ var init_execution_plugin = __esm(() => {
17426
17608
  });
17427
17609
 
17428
17610
  // src/modules/execution/module.ts
17429
- import { existsSync as existsSync32, readFileSync as readFileSync17 } from "fs";
17611
+ import { existsSync as existsSync33, readFileSync as readFileSync17 } from "fs";
17430
17612
  import { resolve as resolve19 } from "path";
17431
17613
 
17432
17614
  class ExecutionModule {
@@ -17629,7 +17811,7 @@ class ExecutionModule {
17629
17811
  "poetry.lock",
17630
17812
  "requirements.txt"
17631
17813
  ];
17632
- const hasLockFile = lockFiles.some((f) => existsSync32(resolve19(this.baseDir, f)));
17814
+ const hasLockFile = lockFiles.some((f) => existsSync33(resolve19(this.baseDir, f)));
17633
17815
  if (!hasLockFile) {
17634
17816
  if (contextManager) {
17635
17817
  const hints = this.state.depsGateHints.get(step.id) || 0;
@@ -17649,8 +17831,8 @@ class ExecutionModule {
17649
17831
  }
17650
17832
  if (stepPaths.length === 0)
17651
17833
  return;
17652
- const allExist = stepPaths.every((p) => existsSync32(resolve19(this.baseDir, p)));
17653
- const allGone = stepPaths.every((p) => !existsSync32(resolve19(this.baseDir, p)));
17834
+ const allExist = stepPaths.every((p) => existsSync33(resolve19(this.baseDir, p)));
17835
+ const allGone = stepPaths.every((p) => !existsSync33(resolve19(this.baseDir, p)));
17654
17836
  const satisfied = step.kind === "delete" ? allGone && !allExist : allExist;
17655
17837
  if (!satisfied)
17656
17838
  return;
@@ -17756,11 +17938,11 @@ var init_module = __esm(() => {
17756
17938
  import {
17757
17939
  readFileSync as readFileSync18,
17758
17940
  writeFileSync as writeFileSync11,
17759
- existsSync as existsSync33,
17941
+ existsSync as existsSync34,
17760
17942
  readdirSync as readdirSync11,
17761
17943
  unlinkSync as unlinkSync4
17762
17944
  } from "fs";
17763
- import { join as join26 } from "path";
17945
+ import { join as join27 } from "path";
17764
17946
  import { homedir as homedir8 } from "os";
17765
17947
 
17766
17948
  class SessionFileEncryptor {
@@ -17769,7 +17951,7 @@ class SessionFileEncryptor {
17769
17951
  constructor(config) {
17770
17952
  this.config = { ...DEFAULT_SESSION_ENCRYPTION, ...config };
17771
17953
  this.encryptor = new ConfigEncryptor({
17772
- keyPath: config?.keyPath || join26(homedir8(), ".mma", ".session-encryption-key")
17954
+ keyPath: config?.keyPath || join27(homedir8(), ".mma", ".session-encryption-key")
17773
17955
  });
17774
17956
  }
17775
17957
  isEnabled() {
@@ -17855,8 +18037,8 @@ class SessionFileEncryptor {
17855
18037
  return;
17856
18038
  const files = readdirSync11(sessionDir);
17857
18039
  for (const file of files) {
17858
- const filePath = join26(sessionDir, file);
17859
- if (existsSync33(filePath) && !file.endsWith(".enc")) {
18040
+ const filePath = join27(sessionDir, file);
18041
+ if (existsSync34(filePath) && !file.endsWith(".enc")) {
17860
18042
  try {
17861
18043
  const content = readFileSync18(filePath, "utf8");
17862
18044
  const encrypted = this.encryptFileContent(content);
@@ -17872,7 +18054,7 @@ class SessionFileEncryptor {
17872
18054
  const files = readdirSync11(sessionDir);
17873
18055
  for (const file of files) {
17874
18056
  if (file.endsWith(".enc")) {
17875
- const encFilePath = join26(sessionDir, file);
18057
+ const encFilePath = join27(sessionDir, file);
17876
18058
  const decFilePath = encFilePath.slice(0, -4);
17877
18059
  try {
17878
18060
  const content = readFileSync18(encFilePath, "utf8");
@@ -17897,7 +18079,7 @@ var init_session_encryption = __esm(() => {
17897
18079
 
17898
18080
  // src/modules/session/store.ts
17899
18081
  import {
17900
- existsSync as existsSync34,
18082
+ existsSync as existsSync35,
17901
18083
  mkdirSync as mkdirSync15,
17902
18084
  readdirSync as readdirSync12,
17903
18085
  readFileSync as readFileSync19,
@@ -17905,7 +18087,7 @@ import {
17905
18087
  writeFileSync as writeFileSync12,
17906
18088
  appendFileSync as appendFileSync6
17907
18089
  } from "fs";
17908
- import { join as join27 } from "path";
18090
+ import { join as join28 } from "path";
17909
18091
  import { gzipSync } from "zlib";
17910
18092
 
17911
18093
  class SessionStore {
@@ -17919,7 +18101,7 @@ class SessionStore {
17919
18101
  }
17920
18102
  }
17921
18103
  getSessionDir(id) {
17922
- return join27(this.baseDir, id);
18104
+ return join28(this.baseDir, id);
17923
18105
  }
17924
18106
  updateEncryption(config) {
17925
18107
  if (config?.enabled) {
@@ -17935,19 +18117,19 @@ class SessionStore {
17935
18117
  mkdirSync15(this.baseDir, { recursive: true });
17936
18118
  }
17937
18119
  sessionDir(id) {
17938
- return join27(this.baseDir, id);
18120
+ return join28(this.baseDir, id);
17939
18121
  }
17940
18122
  metaPath(id) {
17941
- return join27(this.sessionDir(id), "meta.json");
18123
+ return join28(this.sessionDir(id), "meta.json");
17942
18124
  }
17943
18125
  historyPath(id) {
17944
- return join27(this.sessionDir(id), "history.jsonl");
18126
+ return join28(this.sessionDir(id), "history.jsonl");
17945
18127
  }
17946
18128
  sessionLogPath(id) {
17947
- return join27(this.sessionDir(id), "session.jsonl");
18129
+ return join28(this.sessionDir(id), "session.jsonl");
17948
18130
  }
17949
18131
  sessionExists(id) {
17950
- return existsSync34(this.metaPath(id));
18132
+ return existsSync35(this.metaPath(id));
17951
18133
  }
17952
18134
  saveMeta(id, meta) {
17953
18135
  this._metaCache.set(id, meta);
@@ -17965,7 +18147,7 @@ class SessionStore {
17965
18147
  if (cached)
17966
18148
  return cached;
17967
18149
  const path = this.metaPath(id);
17968
- if (!existsSync34(path))
18150
+ if (!existsSync35(path))
17969
18151
  return null;
17970
18152
  try {
17971
18153
  const raw = readFileSync19(path, "utf-8");
@@ -17997,7 +18179,7 @@ class SessionStore {
17997
18179
  }
17998
18180
  loadHistory(id) {
17999
18181
  const path = this.historyPath(id);
18000
- if (!existsSync34(path))
18182
+ if (!existsSync35(path))
18001
18183
  return [];
18002
18184
  try {
18003
18185
  const raw = readFileSync19(path, "utf-8");
@@ -18038,7 +18220,7 @@ class SessionStore {
18038
18220
  }
18039
18221
  loadSessionLog(id) {
18040
18222
  const path = this.sessionLogPath(id);
18041
- if (!existsSync34(path))
18223
+ if (!existsSync35(path))
18042
18224
  return [];
18043
18225
  try {
18044
18226
  const raw = readFileSync19(path, "utf-8");
@@ -18066,7 +18248,7 @@ class SessionStore {
18066
18248
  }
18067
18249
  }
18068
18250
  listSessions() {
18069
- if (!existsSync34(this.baseDir))
18251
+ if (!existsSync35(this.baseDir))
18070
18252
  return [];
18071
18253
  const entries = readdirSync12(this.baseDir, { withFileTypes: true });
18072
18254
  const sessions = [];
@@ -18083,7 +18265,7 @@ class SessionStore {
18083
18265
  deleteSession(id) {
18084
18266
  this._metaCache.delete(id);
18085
18267
  const dir = this.sessionDir(id);
18086
- if (existsSync34(dir)) {
18268
+ if (existsSync35(dir)) {
18087
18269
  rmSync2(dir, { recursive: true, force: true });
18088
18270
  }
18089
18271
  }
@@ -18095,10 +18277,10 @@ class SessionStore {
18095
18277
  const updatedAt = new Date(session2.updatedAt);
18096
18278
  if (updatedAt < thirtyDaysAgo) {
18097
18279
  const historyPath = this.historyPath(session2.id);
18098
- if (existsSync34(historyPath)) {
18280
+ if (existsSync35(historyPath)) {
18099
18281
  const content = readFileSync19(historyPath, "utf-8");
18100
18282
  const compressed = gzipSync(content);
18101
- const gzPath = join27(this.baseDir, `${session2.id}.jsonl.gz`);
18283
+ const gzPath = join28(this.baseDir, `${session2.id}.jsonl.gz`);
18102
18284
  writeFileSync12(gzPath, compressed);
18103
18285
  rmSync2(historyPath);
18104
18286
  }
@@ -18251,7 +18433,7 @@ class SessionManager {
18251
18433
  }
18252
18434
  }
18253
18435
  }
18254
- var init_manager2 = __esm(() => {
18436
+ var init_manager3 = __esm(() => {
18255
18437
  init_i18n();
18256
18438
  init_session_isolation();
18257
18439
  });
@@ -18287,7 +18469,7 @@ var init_module2 = __esm(() => {
18287
18469
  // src/modules/session/index.ts
18288
18470
  var init_session2 = __esm(() => {
18289
18471
  init_store3();
18290
- init_manager2();
18472
+ init_manager3();
18291
18473
  init_module2();
18292
18474
  });
18293
18475
 
@@ -18308,9 +18490,9 @@ class ProfileCompressor {
18308
18490
  }
18309
18491
 
18310
18492
  // src/modules/user-profile/profile.ts
18311
- import { readFileSync as readFileSync20, writeFileSync as writeFileSync13, existsSync as existsSync35, mkdirSync as mkdirSync16 } from "fs";
18312
- import { join as join28 } from "path";
18313
- import { homedir as homedir9, hostname, platform as platform5, type } from "os";
18493
+ import { readFileSync as readFileSync20, writeFileSync as writeFileSync13, existsSync as existsSync36, mkdirSync as mkdirSync16 } from "fs";
18494
+ import { join as join29 } from "path";
18495
+ import { homedir as homedir9, hostname, platform as platform7, type } from "os";
18314
18496
  import { env } from "process";
18315
18497
 
18316
18498
  class UserProfile {
@@ -18322,7 +18504,7 @@ class UserProfile {
18322
18504
  }
18323
18505
  collect() {
18324
18506
  this.info = {
18325
- platform: platform5(),
18507
+ platform: platform7(),
18326
18508
  os: `${type()} ${hostname()}`,
18327
18509
  hostname: hostname(),
18328
18510
  shell: env.SHELL || env.ComSpec || "unknown",
@@ -18333,14 +18515,14 @@ class UserProfile {
18333
18515
  return this.info;
18334
18516
  }
18335
18517
  save() {
18336
- if (!existsSync35(this.profileDir)) {
18518
+ if (!existsSync36(this.profileDir)) {
18337
18519
  mkdirSync16(this.profileDir, { recursive: true });
18338
18520
  }
18339
- writeFileSync13(join28(this.profileDir, "profile.json"), JSON.stringify({ ...this.info, preferences: this.preferences }, null, 2), "utf-8");
18521
+ writeFileSync13(join29(this.profileDir, "profile.json"), JSON.stringify({ ...this.info, preferences: this.preferences }, null, 2), "utf-8");
18340
18522
  }
18341
18523
  load() {
18342
- const path = join28(this.profileDir, "profile.json");
18343
- if (!existsSync35(path))
18524
+ const path = join29(this.profileDir, "profile.json");
18525
+ if (!existsSync36(path))
18344
18526
  return null;
18345
18527
  try {
18346
18528
  const data = JSON.parse(readFileSync20(path, "utf-8"));
@@ -18378,12 +18560,12 @@ class UserProfile {
18378
18560
  var init_profile = () => {};
18379
18561
 
18380
18562
  // src/modules/skills/loader.ts
18381
- import { readdirSync as readdirSync13, readFileSync as readFileSync21, existsSync as existsSync36, statSync as statSync6 } from "fs";
18382
- import { join as join29 } from "path";
18563
+ import { readdirSync as readdirSync13, readFileSync as readFileSync21, existsSync as existsSync37, statSync as statSync6 } from "fs";
18564
+ import { join as join30 } from "path";
18383
18565
 
18384
18566
  class SkillsLoader {
18385
18567
  loadFromDir(dirPath) {
18386
- if (!existsSync36(dirPath))
18568
+ if (!existsSync37(dirPath))
18387
18569
  return [];
18388
18570
  const skills = [];
18389
18571
  this.scanDir(dirPath, skills);
@@ -18392,7 +18574,7 @@ class SkillsLoader {
18392
18574
  scanDir(dirPath, skills) {
18393
18575
  const entries = readdirSync13(dirPath);
18394
18576
  for (const entry of entries) {
18395
- const fullPath = join29(dirPath, entry);
18577
+ const fullPath = join30(dirPath, entry);
18396
18578
  const stat = statSync6(fullPath);
18397
18579
  if (stat.isDirectory()) {
18398
18580
  this.scanDir(fullPath, skills);
@@ -18635,45 +18817,10 @@ var init_browser2 = __esm(() => {
18635
18817
  init_types();
18636
18818
  });
18637
18819
 
18638
- // src/modules/lsp/command.ts
18639
- import { delimiter, join as join30 } from "path";
18640
- import { existsSync as existsSync37 } from "fs";
18641
- import { platform as platform6 } from "os";
18642
- function resolveSpawnCommand(command, platformName = platform6(), pathEnv = process.env.PATH ?? "") {
18643
- if (platformName !== "win32")
18644
- return command;
18645
- if (command.includes("/") || command.includes("\\") || WIN_EXTS.some((ext) => command.toLowerCase().endsWith(ext))) {
18646
- return command;
18647
- }
18648
- const dirs = pathEnv.split(delimiter).filter(Boolean);
18649
- for (const dir of dirs) {
18650
- for (const ext of WIN_EXTS) {
18651
- const candidate = join30(dir, `${command}${ext}`);
18652
- if (existsSync37(candidate))
18653
- return `${command}${ext}`;
18654
- }
18655
- }
18656
- return command;
18657
- }
18658
- function buildWinCommandLine(command, args) {
18659
- const quote = (part) => {
18660
- if (part === "")
18661
- return '""';
18662
- if (!/[\s"&|^<>()%!]/.test(part))
18663
- return part;
18664
- return `"${part.replace(/"/g, "\\\"")}"`;
18665
- };
18666
- return [command, ...args].map(quote).join(" ");
18667
- }
18668
- var WIN_EXTS;
18669
- var init_command = __esm(() => {
18670
- WIN_EXTS = [".cmd", ".bat", ".exe", ".com"];
18671
- });
18672
-
18673
18820
  // src/modules/lsp/client.ts
18674
18821
  import { spawn as spawn6, execSync as execSync2 } from "child_process";
18675
18822
  import { resolve as resolve20 } from "path";
18676
- import { platform as platform7 } from "os";
18823
+ import { platform as platform8 } from "os";
18677
18824
 
18678
18825
  class LspClient {
18679
18826
  process = null;
@@ -18743,7 +18890,7 @@ class LspClient {
18743
18890
  }
18744
18891
  return new Promise((resolve21, reject) => {
18745
18892
  const args = config.args ?? [];
18746
- const isWin = platform7() === "win32";
18893
+ const isWin = platform8() === "win32";
18747
18894
  let spawnCommand = resolveSpawnCommand(config.command);
18748
18895
  let spawnArgs = args;
18749
18896
  const spawnOpts = {
@@ -19984,6 +20131,29 @@ var init_module8 = __esm(() => {
19984
20131
  MEMORY_MD_FILES = ["errors", "conventions", "decisions", "facts"];
19985
20132
  });
19986
20133
 
20134
+ // src/core/version.ts
20135
+ import { existsSync as existsSync42, readFileSync as readFileSync25 } from "fs";
20136
+ import { join as join35, dirname as dirname13 } from "path";
20137
+ import { fileURLToPath as fileURLToPath2 } from "url";
20138
+ function readMmaVersion() {
20139
+ const here = dirname13(fileURLToPath2(import.meta.url));
20140
+ const candidates = [
20141
+ join35(here, "..", "..", "package.json"),
20142
+ join35(here, "..", "package.json")
20143
+ ];
20144
+ for (const p of candidates) {
20145
+ if (existsSync42(p)) {
20146
+ try {
20147
+ const raw = JSON.parse(readFileSync25(p, "utf8"));
20148
+ if (raw.version)
20149
+ return raw.version;
20150
+ } catch {}
20151
+ }
20152
+ }
20153
+ return "0.0.0";
20154
+ }
20155
+ var init_version = () => {};
20156
+
19987
20157
  // src/core/bootstrap.ts
19988
20158
  var exports_bootstrap = {};
19989
20159
  __export(exports_bootstrap, {
@@ -19991,8 +20161,8 @@ __export(exports_bootstrap, {
19991
20161
  bootstrap: () => bootstrap
19992
20162
  });
19993
20163
  import { homedir as homedir11 } from "os";
19994
- import { join as join35, resolve as resolve23 } from "path";
19995
- import { existsSync as existsSync42, readFileSync as readFileSync25, writeFileSync as writeFileSync15 } from "fs";
20164
+ import { join as join36, resolve as resolve23 } from "path";
20165
+ import { existsSync as existsSync43, readFileSync as readFileSync26, writeFileSync as writeFileSync15 } from "fs";
19996
20166
  function buildSystemInfo(config, baseDir, profileCompressed) {
19997
20167
  const now = new Date().toISOString().replace("T", " ").slice(0, 19);
19998
20168
  const isWin = profileCompressed.toLowerCase().includes("win32");
@@ -20018,8 +20188,8 @@ function buildSystemInfo(config, baseDir, profileCompressed) {
20018
20188
  `);
20019
20189
  }
20020
20190
  async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
20021
- const dir = configDir || join35(homedir11(), ".mma");
20022
- const projectConfigPath = projectDir ? join35(projectDir, ".mmrc") : join35(process.cwd(), ".mmrc");
20191
+ const dir = configDir || join36(homedir11(), ".mma");
20192
+ const projectConfigPath = projectDir ? join36(projectDir, ".mmrc") : join36(process.cwd(), ".mmrc");
20023
20193
  const config = loadConfig({ configDir: dir, projectConfigPath });
20024
20194
  setLocale(config.locale);
20025
20195
  try {
@@ -20029,7 +20199,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
20029
20199
  }
20030
20200
  } catch {}
20031
20201
  const logger = new Logger(config.logLevel);
20032
- logger.setLogDir(join35(dir, "logs"));
20202
+ logger.setLogDir(join36(dir, "logs"));
20033
20203
  logger.debug("MMA bootstrap", {
20034
20204
  version: config.version,
20035
20205
  model: config.model
@@ -20051,7 +20221,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
20051
20221
  logger.info(`Model ${config.model} loaded in ${loadResult.loadTime}s`);
20052
20222
  }
20053
20223
  }
20054
- const profile = new UserProfile(join35(dir));
20224
+ const profile = new UserProfile(join36(dir));
20055
20225
  profile.load() || profile.collect();
20056
20226
  profile.save();
20057
20227
  const llmProvider = new OpenAICompatProvider({
@@ -20063,7 +20233,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
20063
20233
  rateLimits: config.security?.rateLimits
20064
20234
  });
20065
20235
  const baseDir = projectDir ? resolve23(projectDir) : process.cwd();
20066
- const projectMapCacheDir = join35(baseDir, ".mma");
20236
+ const projectMapCacheDir = join36(baseDir, ".mma");
20067
20237
  const indexerModule = new IndexerModule({
20068
20238
  baseDir,
20069
20239
  cacheDir: projectMapCacheDir
@@ -20074,9 +20244,9 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
20074
20244
  logger.warn(`Project indexing failed: ${err.message}`);
20075
20245
  }
20076
20246
  const skillsLoader = new SkillsLoader;
20077
- const builtinDir = join35(import.meta.dirname, "skills", "builtin");
20078
- const globalDir = join35(homedir11(), ".agents", "skills");
20079
- const projectSkillsDir = join35(baseDir, ".mma", "skills");
20247
+ const builtinDir = join36(import.meta.dirname, "skills", "builtin");
20248
+ const globalDir = join36(homedir11(), ".agents", "skills");
20249
+ const projectSkillsDir = join36(baseDir, ".mma", "skills");
20080
20250
  const availableSkills = skillsLoader.loadFromAllSources(builtinDir, globalDir, projectSkillsDir);
20081
20251
  const skillsBudget = Math.floor(config.contextWindow * config.skills.budget);
20082
20252
  const skillsModule = new SkillsModule(availableSkills, skillsBudget);
@@ -20090,11 +20260,11 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
20090
20260
  essential: true,
20091
20261
  estimatedTokens: Math.ceil(systemInfoContent.length / 4)
20092
20262
  };
20093
- const agentsMdGlobal = join35(dir, "AGENTS.md");
20094
- if (!existsSync42(agentsMdGlobal)) {
20263
+ const agentsMdGlobal = join36(dir, "AGENTS.md");
20264
+ if (!existsSync43(agentsMdGlobal)) {
20095
20265
  writeFileSync15(agentsMdGlobal, "", "utf-8");
20096
20266
  }
20097
- const sessionDir = join35(dir, "sessions");
20267
+ const sessionDir = join36(dir, "sessions");
20098
20268
  const sessionStore = new SessionStore(sessionDir);
20099
20269
  sessionStore.init();
20100
20270
  const sessionManager = new SessionManager(sessionStore, {
@@ -20161,7 +20331,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
20161
20331
  const mcpModule = new MCPModule(config);
20162
20332
  await mcpModule.initialize();
20163
20333
  moduleRegistry.register(mcpModule);
20164
- const memoryStore = new MemoryStore(join35(dir, "memory"));
20334
+ const memoryStore = new MemoryStore(join36(dir, "memory"));
20165
20335
  const memoryModule = new MemoryModule(memoryStore);
20166
20336
  moduleRegistry.register(memoryModule);
20167
20337
  if (config.browser.enabled) {
@@ -20212,10 +20382,17 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
20212
20382
  pluginManager.register(plugin);
20213
20383
  pluginManager.register(plugin2);
20214
20384
  const pluginLoader = new PluginLoader;
20215
- const globalPluginsDir = join35(homedir11(), ".mma", "plugins");
20216
- const projectPluginsDir = join35(baseDir, ".mma", "plugins");
20217
- pluginLoader.loadFromDir(globalPluginsDir, pluginManager, logger);
20218
- pluginLoader.loadFromDir(projectPluginsDir, pluginManager, logger);
20385
+ const globalPluginsDir = join36(homedir11(), ".mma", "plugins");
20386
+ const projectPluginsDir = join36(baseDir, ".mma", "plugins");
20387
+ const mmaVersion = readMmaVersion();
20388
+ pluginLoader.loadFromDir(globalPluginsDir, pluginManager, logger, {
20389
+ source: "global",
20390
+ mmaVersion
20391
+ });
20392
+ pluginLoader.loadFromDir(projectPluginsDir, pluginManager, logger, {
20393
+ source: "project",
20394
+ mmaVersion
20395
+ });
20219
20396
  contextManager.onCompact = (summary) => {
20220
20397
  const meta = sessionManager.getActiveMeta();
20221
20398
  if (!meta || !config.session.autoSave)
@@ -20232,13 +20409,13 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
20232
20409
  const skipAgentsMd = noAgentsMd === true;
20233
20410
  if (!skipAgentsMd) {
20234
20411
  const agentsMdCandidates = [
20235
- join35(baseDir, "AGENTS.md"),
20236
- join35(baseDir, ".mma", "AGENTS.md"),
20237
- join35(dir, "AGENTS.md")
20412
+ join36(baseDir, "AGENTS.md"),
20413
+ join36(baseDir, ".mma", "AGENTS.md"),
20414
+ join36(dir, "AGENTS.md")
20238
20415
  ];
20239
20416
  for (const p of agentsMdCandidates) {
20240
- if (existsSync42(p)) {
20241
- const content = readFileSync25(p, "utf-8").trim();
20417
+ if (existsSync43(p)) {
20418
+ const content = readFileSync26(p, "utf-8").trim();
20242
20419
  if (content) {
20243
20420
  agentsMdBlocks.push({
20244
20421
  content,
@@ -20302,6 +20479,7 @@ var init_bootstrap = __esm(() => {
20302
20479
  init_openai_compat();
20303
20480
  init_tools();
20304
20481
  init_executor();
20482
+ init_manager2();
20305
20483
  init_loader();
20306
20484
  init_lint_on_write();
20307
20485
  init_notify();
@@ -20320,6 +20498,7 @@ var init_bootstrap = __esm(() => {
20320
20498
  init_store2();
20321
20499
  init_i18n();
20322
20500
  init_agent();
20501
+ init_version();
20323
20502
  });
20324
20503
 
20325
20504
  // node_modules/ansi-regex/index.js
@@ -21092,20 +21271,20 @@ __export(exports_manifest, {
21092
21271
  getCertMark: () => getCertMark,
21093
21272
  MANIFEST_PATH: () => MANIFEST_PATH
21094
21273
  });
21095
- import { existsSync as existsSync43, readFileSync as readFileSync26, mkdirSync as mkdirSync18, writeFileSync as writeFileSync16 } from "fs";
21274
+ import { existsSync as existsSync44, readFileSync as readFileSync27, mkdirSync as mkdirSync18, writeFileSync as writeFileSync16 } from "fs";
21096
21275
  import { homedir as homedir13 } from "os";
21097
- import { join as join37 } from "path";
21276
+ import { join as join38 } from "path";
21098
21277
  function readManifest(path = MANIFEST_PATH) {
21099
21278
  try {
21100
- if (existsSync43(path)) {
21101
- const raw = JSON.parse(readFileSync26(path, "utf-8"));
21279
+ if (existsSync44(path)) {
21280
+ const raw = JSON.parse(readFileSync27(path, "utf-8"));
21102
21281
  return { version: 1, certifications: raw.certifications ?? [] };
21103
21282
  }
21104
21283
  } catch {}
21105
21284
  return { version: 1, certifications: [] };
21106
21285
  }
21107
21286
  function saveManifest(m, path = MANIFEST_PATH) {
21108
- mkdirSync18(join37(homedir13(), ".mma"), { recursive: true });
21287
+ mkdirSync18(join38(homedir13(), ".mma"), { recursive: true });
21109
21288
  writeFileSync16(path, JSON.stringify(m, null, 2), "utf-8");
21110
21289
  }
21111
21290
  function upsertCertification(entry, path = MANIFEST_PATH) {
@@ -21140,7 +21319,7 @@ function getCertMark(model, providerUrl, currentVersion, path = MANIFEST_PATH) {
21140
21319
  }
21141
21320
  var MANIFEST_PATH;
21142
21321
  var init_manifest = __esm(() => {
21143
- MANIFEST_PATH = join37(homedir13(), ".mma", "certifications.json");
21322
+ MANIFEST_PATH = join38(homedir13(), ".mma", "certifications.json");
21144
21323
  });
21145
21324
 
21146
21325
  // node_modules/yaml/dist/nodes/identity.js
@@ -28263,8 +28442,8 @@ var init_scenarios = __esm(() => {
28263
28442
  });
28264
28443
 
28265
28444
  // src/modules/certification/loader.ts
28266
- import { existsSync as existsSync44, readdirSync as readdirSync15, readFileSync as readFileSync27 } from "fs";
28267
- import { join as join38 } from "path";
28445
+ import { existsSync as existsSync45, readdirSync as readdirSync15, readFileSync as readFileSync28 } from "fs";
28446
+ import { join as join39 } from "path";
28268
28447
  function validateScenario(s) {
28269
28448
  const errors2 = [];
28270
28449
  const isSkip = s.mode === "skip";
@@ -28313,12 +28492,12 @@ function loadScenarios(userDir) {
28313
28492
  else
28314
28493
  scenarios.push(s);
28315
28494
  }
28316
- if (userDir && existsSync44(userDir)) {
28495
+ if (userDir && existsSync45(userDir)) {
28317
28496
  for (const file of readdirSync15(userDir)) {
28318
28497
  if (!file.endsWith(".yaml") && !file.endsWith(".yml"))
28319
28498
  continue;
28320
28499
  try {
28321
- const raw = readFileSync27(join38(userDir, file), "utf-8");
28500
+ const raw = readFileSync28(join39(userDir, file), "utf-8");
28322
28501
  const data = $parse(raw);
28323
28502
  const parsed = normalizeScenario(data, file);
28324
28503
  const errs = validateScenario(parsed);
@@ -28371,8 +28550,8 @@ var init_loader3 = __esm(() => {
28371
28550
  });
28372
28551
 
28373
28552
  // src/modules/certification/fact-checker.ts
28374
- import { existsSync as existsSync45, readFileSync as readFileSync28, statSync as statSync8 } from "fs";
28375
- import { join as join39 } from "path";
28553
+ import { existsSync as existsSync46, readFileSync as readFileSync29, statSync as statSync8 } from "fs";
28554
+ import { join as join40 } from "path";
28376
28555
  function checkSandbox(sandboxDir, checks, exitCode, output) {
28377
28556
  const failures = [];
28378
28557
  for (const check of checks) {
@@ -28389,16 +28568,16 @@ function runCheck(sandboxDir, check, exitCode, output) {
28389
28568
  case "outputContains":
28390
28569
  return output.includes(check.text);
28391
28570
  case "fileExists":
28392
- return isFile(join39(sandboxDir, check.path));
28571
+ return isFile(join40(sandboxDir, check.path));
28393
28572
  case "fileNotExists":
28394
- return !existsSync45(join39(sandboxDir, check.path));
28573
+ return !existsSync46(join40(sandboxDir, check.path));
28395
28574
  case "dirExists":
28396
- return isDir(join39(sandboxDir, check.path));
28575
+ return isDir(join40(sandboxDir, check.path));
28397
28576
  case "fileContent": {
28398
- const abs = join39(sandboxDir, check.path);
28577
+ const abs = join40(sandboxDir, check.path);
28399
28578
  if (!isFile(abs))
28400
28579
  return false;
28401
- const content = readFileSync28(abs, "utf-8");
28580
+ const content = readFileSync29(abs, "utf-8");
28402
28581
  if (check.contains !== undefined)
28403
28582
  return content.includes(check.contains);
28404
28583
  if (check.equals !== undefined)
@@ -28406,10 +28585,10 @@ function runCheck(sandboxDir, check, exitCode, output) {
28406
28585
  return false;
28407
28586
  }
28408
28587
  case "fileRegex": {
28409
- const abs = join39(sandboxDir, check.path);
28588
+ const abs = join40(sandboxDir, check.path);
28410
28589
  if (!isFile(abs))
28411
28590
  return false;
28412
- return new RegExp(check.pattern).test(readFileSync28(abs, "utf-8"));
28591
+ return new RegExp(check.pattern).test(readFileSync29(abs, "utf-8"));
28413
28592
  }
28414
28593
  default:
28415
28594
  return false;
@@ -28417,14 +28596,14 @@ function runCheck(sandboxDir, check, exitCode, output) {
28417
28596
  }
28418
28597
  function isFile(p) {
28419
28598
  try {
28420
- return existsSync45(p) && statSync8(p).isFile();
28599
+ return existsSync46(p) && statSync8(p).isFile();
28421
28600
  } catch {
28422
28601
  return false;
28423
28602
  }
28424
28603
  }
28425
28604
  function isDir(p) {
28426
28605
  try {
28427
- return existsSync45(p) && statSync8(p).isDirectory();
28606
+ return existsSync46(p) && statSync8(p).isDirectory();
28428
28607
  } catch {
28429
28608
  return false;
28430
28609
  }
@@ -28455,9 +28634,9 @@ var init_fact_checker = () => {};
28455
28634
 
28456
28635
  // src/modules/certification/runner.ts
28457
28636
  import { spawn as spawn7 } from "child_process";
28458
- import { existsSync as existsSync46, mkdirSync as mkdirSync19, rmSync as rmSync4, cpSync as cpSync2 } from "fs";
28459
- import { platform as platform8 } from "os";
28460
- import { join as join40, resolve as resolve24, dirname as dirname13 } from "path";
28637
+ import { existsSync as existsSync47, mkdirSync as mkdirSync19, rmSync as rmSync4, cpSync as cpSync2 } from "fs";
28638
+ import { platform as platform9 } from "os";
28639
+ import { join as join41, resolve as resolve24, dirname as dirname14 } from "path";
28461
28640
  async function runScenario(scenario, opts) {
28462
28641
  if (scenario.mode === "skip") {
28463
28642
  return {
@@ -28470,13 +28649,13 @@ async function runScenario(scenario, opts) {
28470
28649
  }
28471
28650
  const reps = scenario.reps ?? opts.defaultReps;
28472
28651
  const threshold = Math.min(scenario.passThreshold ?? opts.defaultThreshold, reps);
28473
- const runner = opts.runner ?? defaultRunner;
28652
+ const runner = opts.runner ?? defaultRunner2;
28474
28653
  const timeoutMs = opts.timeoutMs ?? 120000;
28475
28654
  const entryPoint = resolveMmaEntry(opts.mmaRoot);
28476
28655
  let passed = 0;
28477
28656
  let firstError;
28478
28657
  for (let i = 1;i <= reps; i++) {
28479
- const sandbox = join40(opts.sandboxBase, `run-${scenario.id}-${i}`);
28658
+ const sandbox = join41(opts.sandboxBase, `run-${scenario.id}-${i}`);
28480
28659
  let failures = [];
28481
28660
  let exitCode = -1;
28482
28661
  let output = "";
@@ -28537,20 +28716,20 @@ function prepareSandbox(sandbox, scenario, mmaRoot) {
28537
28716
  rmSync4(sandbox, { recursive: true, force: true });
28538
28717
  mkdirSync19(sandbox, { recursive: true });
28539
28718
  for (const f of scenario.fixtures ?? []) {
28540
- const src = join40(mmaRoot, f.source);
28541
- if (!existsSync46(src)) {
28719
+ const src = join41(mmaRoot, f.source);
28720
+ if (!existsSync47(src)) {
28542
28721
  throw new Error(`fixture missing: ${f.source}`);
28543
28722
  }
28544
- const dest = join40(sandbox, f.dest);
28545
- mkdirSync19(dirname13(dest), { recursive: true });
28723
+ const dest = join41(sandbox, f.dest);
28724
+ mkdirSync19(dirname14(dest), { recursive: true });
28546
28725
  cpSync2(src, dest);
28547
28726
  }
28548
28727
  }
28549
28728
  function resolveMmaEntry(mmaRoot) {
28550
- const dev = join40(mmaRoot, "src", "cli", "main.ts");
28551
- if (existsSync46(dev))
28729
+ const dev = join41(mmaRoot, "src", "cli", "main.ts");
28730
+ if (existsSync47(dev))
28552
28731
  return dev;
28553
- return join40(mmaRoot, "dist", "main.js");
28732
+ return join41(mmaRoot, "dist", "main.js");
28554
28733
  }
28555
28734
  function findMmaRoot(fromDir) {
28556
28735
  const candidates = [
@@ -28558,7 +28737,7 @@ function findMmaRoot(fromDir) {
28558
28737
  resolve24(fromDir, "..")
28559
28738
  ];
28560
28739
  for (const c of candidates) {
28561
- if (existsSync46(join40(c, "package.json")))
28740
+ if (existsSync47(join41(c, "package.json")))
28562
28741
  return c;
28563
28742
  }
28564
28743
  return process.cwd();
@@ -28567,7 +28746,7 @@ function killTree2(child) {
28567
28746
  const pid = child.pid;
28568
28747
  if (!pid)
28569
28748
  return;
28570
- if (platform8() === "win32") {
28749
+ if (platform9() === "win32") {
28571
28750
  spawn7("taskkill", ["/pid", String(pid), "/T", "/F"], {
28572
28751
  windowsHide: true,
28573
28752
  stdio: "ignore"
@@ -28582,7 +28761,7 @@ function killTree2(child) {
28582
28761
  } catch {}
28583
28762
  }
28584
28763
  }
28585
- var defaultRunner = (env2, cwd, args, timeoutMs) => new Promise((resolvePromise) => {
28764
+ var defaultRunner2 = (env2, cwd, args, timeoutMs) => new Promise((resolvePromise) => {
28586
28765
  const child = spawn7(process.execPath, args, {
28587
28766
  cwd,
28588
28767
  env: env2,
@@ -28626,15 +28805,15 @@ __export(exports_cli, {
28626
28805
  });
28627
28806
  import { rmSync as rmSync5 } from "fs";
28628
28807
  import { homedir as homedir14 } from "os";
28629
- import { join as join41, dirname as dirname14 } from "path";
28630
- import { fileURLToPath as fileURLToPath2 } from "url";
28631
- import { existsSync as existsSync47, readFileSync as readFileSync29 } from "fs";
28808
+ import { join as join42, dirname as dirname15 } from "path";
28809
+ import { fileURLToPath as fileURLToPath3 } from "url";
28810
+ import { existsSync as existsSync48, readFileSync as readFileSync30 } from "fs";
28632
28811
  function readVersion() {
28633
- const candidates = [join41(MMA_ROOT, "package.json")];
28812
+ const candidates = [join42(MMA_ROOT, "package.json")];
28634
28813
  for (const p of candidates) {
28635
- if (existsSync47(p)) {
28814
+ if (existsSync48(p)) {
28636
28815
  try {
28637
- const raw = JSON.parse(readFileSync29(p, "utf-8"));
28816
+ const raw = JSON.parse(readFileSync30(p, "utf-8"));
28638
28817
  if (raw.version)
28639
28818
  return raw.version;
28640
28819
  } catch {}
@@ -28670,7 +28849,7 @@ async function certify(opts) {
28670
28849
  return;
28671
28850
  }
28672
28851
  console.log(t("cli.cert_started", { model: opts.name, provider: providerUrl }));
28673
- const sandboxBase = join41(process.cwd(), ".mma", "certification");
28852
+ const sandboxBase = join42(process.cwd(), ".mma", "certification");
28674
28853
  const results = [];
28675
28854
  const total = selected.length;
28676
28855
  let idx = 0;
@@ -28782,9 +28961,9 @@ var init_cli = __esm(() => {
28782
28961
  init_loader3();
28783
28962
  init_runner2();
28784
28963
  init_manifest();
28785
- HERE = dirname14(fileURLToPath2(import.meta.url));
28964
+ HERE = dirname15(fileURLToPath3(import.meta.url));
28786
28965
  MMA_ROOT = findMmaRoot(HERE);
28787
- USER_SCENARIO_DIR = join41(homedir14(), ".mma", "certification", "scenarios");
28966
+ USER_SCENARIO_DIR = join42(homedir14(), ".mma", "certification", "scenarios");
28788
28967
  });
28789
28968
 
28790
28969
  // src/cli/repl-commands.ts
@@ -28793,20 +28972,20 @@ __export(exports_repl_commands, {
28793
28972
  registerAllCommands: () => registerAllCommands,
28794
28973
  COMMAND_GROUPS: () => COMMAND_GROUPS
28795
28974
  });
28796
- import { join as join43, dirname as dirname16 } from "path";
28975
+ import { join as join44, dirname as dirname17 } from "path";
28797
28976
  import { homedir as homedir16 } from "os";
28798
- import { existsSync as existsSync49, readFileSync as readFileSync31 } from "fs";
28799
- import { fileURLToPath as fileURLToPath4 } from "url";
28977
+ import { existsSync as existsSync50, readFileSync as readFileSync32 } from "fs";
28978
+ import { fileURLToPath as fileURLToPath5 } from "url";
28800
28979
  function readVersion3() {
28801
- const here = dirname16(fileURLToPath4(import.meta.url));
28980
+ const here = dirname17(fileURLToPath5(import.meta.url));
28802
28981
  const candidates = [
28803
- join43(here, "..", "..", "package.json"),
28804
- join43(here, "..", "package.json")
28982
+ join44(here, "..", "..", "package.json"),
28983
+ join44(here, "..", "package.json")
28805
28984
  ];
28806
28985
  for (const p of candidates) {
28807
- if (existsSync49(p)) {
28986
+ if (existsSync50(p)) {
28808
28987
  try {
28809
- const raw = JSON.parse(readFileSync31(p, "utf8"));
28988
+ const raw = JSON.parse(readFileSync32(p, "utf8"));
28810
28989
  if (raw.version)
28811
28990
  return raw.version;
28812
28991
  } catch {}
@@ -28870,7 +29049,7 @@ function registerMmaCommands(ctx) {
28870
29049
  }
28871
29050
  try {
28872
29051
  const { loadFileAsDataUrl: loadFileAsDataUrl2, loadUrlAsDataUrl: loadUrlAsDataUrl2, readClipboardImage: readClipboardImage2 } = await Promise.resolve().then(() => (init_image_utils(), exports_image_utils));
28873
- const { existsSync: existsSync50 } = await import("fs");
29052
+ const { existsSync: existsSync51 } = await import("fs");
28874
29053
  const { resolve: resolve25 } = await import("path");
28875
29054
  let dataUrl;
28876
29055
  let label;
@@ -28890,7 +29069,7 @@ function registerMmaCommands(ctx) {
28890
29069
  label = source;
28891
29070
  } else {
28892
29071
  const absPath = resolve25(process.cwd(), source);
28893
- if (!existsSync50(absPath)) {
29072
+ if (!existsSync51(absPath)) {
28894
29073
  console.log(pc2.red(t("image.not_found", { path: source })));
28895
29074
  return;
28896
29075
  }
@@ -28969,7 +29148,7 @@ function registerMmaCommands(ctx) {
28969
29148
  console.log(pc2.yellow(t("repl.wizard_running")));
28970
29149
  await ctx.withExclusiveInput(async () => {
28971
29150
  const answers = await runSetup(ctx.rl);
28972
- const configPath = join43(homedir16(), ".mma", "config.json");
29151
+ const configPath = join44(homedir16(), ".mma", "config.json");
28973
29152
  ctx.config.provider.type = answers.provider;
28974
29153
  ctx.config.provider.baseUrl = answers.apiBase;
28975
29154
  ctx.config.provider.apiKey = answers.apiKey;
@@ -29023,7 +29202,7 @@ Excluded blocks: ${info.excluded.length}`));
29023
29202
  return;
29024
29203
  }
29025
29204
  ctx.config.provider.type = name;
29026
- const configPath = join43(homedir16(), ".mma", "config.json");
29205
+ const configPath = join44(homedir16(), ".mma", "config.json");
29027
29206
  saveConfig(ctx.config, configPath);
29028
29207
  await ctx.agent.reconfigure(ctx.config);
29029
29208
  console.log(pc2.green(t("repl.provider_set", { name })));
@@ -29079,7 +29258,7 @@ Excluded blocks: ${info.excluded.length}`));
29079
29258
  return;
29080
29259
  }
29081
29260
  ctx.config.model = name;
29082
- const configPath = join43(homedir16(), ".mma", "config.json");
29261
+ const configPath = join44(homedir16(), ".mma", "config.json");
29083
29262
  saveConfig(ctx.config, configPath);
29084
29263
  await ctx.agent.reconfigure(ctx.config);
29085
29264
  console.log(pc2.green(t("repl.model_set", { name })));
@@ -29104,7 +29283,7 @@ Excluded blocks: ${info.excluded.length}`));
29104
29283
  return;
29105
29284
  }
29106
29285
  ctx.config.contextWindow = size;
29107
- const configPath = join43(homedir16(), ".mma", "config.json");
29286
+ const configPath = join44(homedir16(), ".mma", "config.json");
29108
29287
  saveConfig(ctx.config, configPath);
29109
29288
  await ctx.agent.reconfigure(ctx.config);
29110
29289
  console.log(pc2.green(t("cli.context_set", { size })));
@@ -29123,10 +29302,10 @@ Excluded blocks: ${info.excluded.length}`));
29123
29302
  ctx.agent.shutdown();
29124
29303
  const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config2(), exports_config));
29125
29304
  const { homedir: homedir17 } = await import("os");
29126
- const { join: join44 } = await import("path");
29305
+ const { join: join45 } = await import("path");
29127
29306
  const configDir = ctx.configDir;
29128
29307
  const baseDir = ctx.baseDir;
29129
- const projectConfigPath = join44(baseDir, ".mmrc");
29308
+ const projectConfigPath = join45(baseDir, ".mmrc");
29130
29309
  const freshConfig = loadConfig2({ configDir, projectConfigPath });
29131
29310
  Object.assign(ctx.config, freshConfig);
29132
29311
  const { bootstrap: bootstrap2 } = await Promise.resolve().then(() => (init_bootstrap(), exports_bootstrap));
@@ -29426,14 +29605,14 @@ init_bootstrap();
29426
29605
  init_config2();
29427
29606
  init_setup();
29428
29607
  init_i18n();
29429
- import { join as join42, dirname as dirname15 } from "path";
29608
+ import { join as join43, dirname as dirname16 } from "path";
29430
29609
  import { homedir as homedir15 } from "os";
29431
- import { existsSync as existsSync48, readFileSync as readFileSync30 } from "fs";
29610
+ import { existsSync as existsSync49, readFileSync as readFileSync31 } from "fs";
29432
29611
 
29433
29612
  // src/cli/security-commands.ts
29434
29613
  init_bootstrap();
29435
29614
  init_config2();
29436
- import { join as join36 } from "path";
29615
+ import { join as join37 } from "path";
29437
29616
  import { homedir as homedir12 } from "os";
29438
29617
 
29439
29618
  // src/modules/security/security-policies.ts
@@ -29963,7 +30142,7 @@ function createSecurityCommand(program2) {
29963
30142
  }
29964
30143
  });
29965
30144
  securityCmd.command("set-policy").argument("<preset>", t("cli.security.preset")).description(t("cli.security.set_policy")).action(async (preset) => {
29966
- const configPath = join36(homedir12(), ".mma", "config.json");
30145
+ const configPath = join37(homedir12(), ".mma", "config.json");
29967
30146
  const { config: appConfig } = await bootstrap();
29968
30147
  const validPresets = ["strict", "balanced", "permissive"];
29969
30148
  if (!validPresets.includes(preset)) {
@@ -29978,7 +30157,7 @@ function createSecurityCommand(program2) {
29978
30157
  console.log(t("cli.security.policy_description", { description: policy.description }));
29979
30158
  });
29980
30159
  securityCmd.command("enable-encryption").description(t("cli.security.enable_encryption")).action(async () => {
29981
- const configPath = join36(homedir12(), ".mma", "config.json");
30160
+ const configPath = join37(homedir12(), ".mma", "config.json");
29982
30161
  const { config: appConfig } = await bootstrap();
29983
30162
  appConfig.security = appConfig.security || {};
29984
30163
  appConfig.security.sessionEncryption = {
@@ -29990,7 +30169,7 @@ function createSecurityCommand(program2) {
29990
30169
  console.log(t("cli.security.encryption_enabled"));
29991
30170
  });
29992
30171
  securityCmd.command("disable-encryption").description(t("cli.security.disable_encryption")).action(async () => {
29993
- const configPath = join36(homedir12(), ".mma", "config.json");
30172
+ const configPath = join37(homedir12(), ".mma", "config.json");
29994
30173
  const { config: appConfig } = await bootstrap();
29995
30174
  appConfig.security = appConfig.security || {};
29996
30175
  appConfig.security.sessionEncryption = {
@@ -30002,7 +30181,7 @@ function createSecurityCommand(program2) {
30002
30181
  console.log(t("cli.security.encryption_disabled"));
30003
30182
  });
30004
30183
  securityCmd.command("enable-audit").description(t("cli.security.enable_audit")).action(async () => {
30005
- const configPath = join36(homedir12(), ".mma", "config.json");
30184
+ const configPath = join37(homedir12(), ".mma", "config.json");
30006
30185
  const { config: appConfig } = await bootstrap();
30007
30186
  appConfig.security = appConfig.security || {};
30008
30187
  appConfig.security.auditNotifier = {
@@ -30016,7 +30195,7 @@ function createSecurityCommand(program2) {
30016
30195
  console.log(t("cli.security.audit_enabled"));
30017
30196
  });
30018
30197
  securityCmd.command("disable-audit").description(t("cli.security.disable_audit")).action(async () => {
30019
- const configPath = join36(homedir12(), ".mma", "config.json");
30198
+ const configPath = join37(homedir12(), ".mma", "config.json");
30020
30199
  const { config: appConfig } = await bootstrap();
30021
30200
  appConfig.security = appConfig.security || {};
30022
30201
  appConfig.security.auditNotifier = {
@@ -30047,18 +30226,49 @@ function createSecurityCommand(program2) {
30047
30226
  });
30048
30227
  }
30049
30228
 
30229
+ // src/cli/plugin-commands.ts
30230
+ init_bootstrap();
30231
+ init_version();
30232
+ init_i18n();
30233
+ function createPluginCommand(program2) {
30234
+ const pluginsCmd = program2.command("plugins").description(t("cli.plugins.description"));
30235
+ pluginsCmd.command("list").description(t("cli.plugins.list")).option("-a, --all", t("cli.plugins.all")).action(async (cmdOpts) => {
30236
+ const { pluginManager } = await bootstrap();
30237
+ const all = cmdOpts.all === true;
30238
+ let infos = pluginManager.getPluginInfos();
30239
+ if (!all) {
30240
+ infos = infos.filter(({ plugin: plugin3 }) => !plugin3.isBuiltin);
30241
+ }
30242
+ if (infos.length === 0) {
30243
+ console.log(t("cli.plugins.none"));
30244
+ return;
30245
+ }
30246
+ const mmaVersion = readMmaVersion();
30247
+ console.log(t("cli.plugins.header", { count: String(infos.length), mma: mmaVersion }));
30248
+ for (const { plugin: plugin3, source } of infos) {
30249
+ const version = plugin3.version || "-";
30250
+ const origin = source || "builtin";
30251
+ const builtin = plugin3.isBuiltin ? t("cli.plugins.builtin_mark") : " ";
30252
+ console.log(` ${builtin} ${plugin3.name} v${version} [${origin}]`);
30253
+ }
30254
+ if (!all) {
30255
+ console.log(t("cli.plugins.only_external"));
30256
+ }
30257
+ });
30258
+ }
30259
+
30050
30260
  // src/cli/commands.ts
30051
- import { fileURLToPath as fileURLToPath3 } from "url";
30261
+ import { fileURLToPath as fileURLToPath4 } from "url";
30052
30262
  function readVersion2() {
30053
- const here = dirname15(fileURLToPath3(import.meta.url));
30263
+ const here = dirname16(fileURLToPath4(import.meta.url));
30054
30264
  const candidates = [
30055
- join42(here, "..", "..", "package.json"),
30056
- join42(here, "..", "package.json")
30265
+ join43(here, "..", "..", "package.json"),
30266
+ join43(here, "..", "package.json")
30057
30267
  ];
30058
30268
  for (const p of candidates) {
30059
- if (existsSync48(p)) {
30269
+ if (existsSync49(p)) {
30060
30270
  try {
30061
- const raw = JSON.parse(readFileSync30(p, "utf8"));
30271
+ const raw = JSON.parse(readFileSync31(p, "utf8"));
30062
30272
  if (raw.version)
30063
30273
  return raw.version;
30064
30274
  } catch {}
@@ -30071,7 +30281,7 @@ function createProgram() {
30071
30281
  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"));
30072
30282
  program2.command("init").description(t("cli.init")).action(async () => {
30073
30283
  const answers = await runSetup();
30074
- const configPath = join42(homedir15(), ".mma", "config.json");
30284
+ const configPath = join43(homedir15(), ".mma", "config.json");
30075
30285
  const { config } = await bootstrap();
30076
30286
  config.provider.type = answers.provider;
30077
30287
  config.provider.baseUrl = answers.apiBase;
@@ -30116,7 +30326,7 @@ function createProgram() {
30116
30326
  });
30117
30327
  const configCmd = program2.command("config").description(t("cli.manage_config"));
30118
30328
  configCmd.command("set").argument("<key>", t("cli.config_key")).argument("<value>", "Config value").description(t("cli.set_value")).action(async (key, value) => {
30119
- const configPath = join42(homedir15(), ".mma", "config.json");
30329
+ const configPath = join43(homedir15(), ".mma", "config.json");
30120
30330
  const { config } = await bootstrap();
30121
30331
  const keys = key.split(".");
30122
30332
  let obj = config;
@@ -30179,7 +30389,7 @@ function createProgram() {
30179
30389
  console.log(t("cli.model_hint"));
30180
30390
  });
30181
30391
  model.command("use").argument("<name>", "Model name").description(t("cli.set_model")).action(async (name) => {
30182
- const configPath = join42(homedir15(), ".mma", "config.json");
30392
+ const configPath = join43(homedir15(), ".mma", "config.json");
30183
30393
  const { config } = await bootstrap();
30184
30394
  config.model = name;
30185
30395
  saveConfig(config, configPath);
@@ -30215,7 +30425,7 @@ function createProgram() {
30215
30425
  await uncertify2(name, config);
30216
30426
  });
30217
30427
  program2.command("context").description(t("cli.manage_context")).argument("<size>", "Context window size in tokens").action(async (size) => {
30218
- const configPath = join42(homedir15(), ".mma", "config.json");
30428
+ const configPath = join43(homedir15(), ".mma", "config.json");
30219
30429
  const { config } = await bootstrap();
30220
30430
  const contextWindow = parseInt(size, 10);
30221
30431
  if (isNaN(contextWindow) || contextWindow < 1024) {
@@ -30233,7 +30443,7 @@ function createProgram() {
30233
30443
  console.log(t("cli.base_url"), config.provider.baseUrl);
30234
30444
  });
30235
30445
  provider.command("use").argument("<name>", "Provider name").description(t("cli.set_provider")).action(async (name) => {
30236
- const configPath = join42(homedir15(), ".mma", "config.json");
30446
+ const configPath = join43(homedir15(), ".mma", "config.json");
30237
30447
  const { config } = await bootstrap();
30238
30448
  config.provider.type = name;
30239
30449
  saveConfig(config, configPath);
@@ -30275,6 +30485,7 @@ function createProgram() {
30275
30485
  console.log(t("session.deleted", { id }));
30276
30486
  });
30277
30487
  createSecurityCommand(program2);
30488
+ createPluginCommand(program2);
30278
30489
  program2.argument("[prompt...]", "Prompt to execute").description("Run a single prompt").action((prompt) => {});
30279
30490
  return program2;
30280
30491
  }
@@ -31040,10 +31251,10 @@ class LineEditor {
31040
31251
  }
31041
31252
 
31042
31253
  // src/cli/repl.ts
31043
- import { existsSync as existsSync50, readFileSync as readFileSync32, writeFileSync as writeFileSync17 } from "fs";
31044
- import { join as join44, dirname as dirname17 } from "path";
31254
+ import { existsSync as existsSync51, readFileSync as readFileSync33, writeFileSync as writeFileSync17 } from "fs";
31255
+ import { join as join45, dirname as dirname18 } from "path";
31045
31256
  import { homedir as homedir17 } from "os";
31046
- import { fileURLToPath as fileURLToPath5 } from "url";
31257
+ import { fileURLToPath as fileURLToPath6 } from "url";
31047
31258
 
31048
31259
  // src/cli/completer.ts
31049
31260
  class SlashCommandProvider {
@@ -31545,15 +31756,15 @@ init_box();
31545
31756
  init_i18n();
31546
31757
  init_repl_commands();
31547
31758
  function readVersion4() {
31548
- const here = dirname17(fileURLToPath5(import.meta.url));
31759
+ const here = dirname18(fileURLToPath6(import.meta.url));
31549
31760
  const candidates = [
31550
- join44(here, "..", "..", "package.json"),
31551
- join44(here, "..", "package.json")
31761
+ join45(here, "..", "..", "package.json"),
31762
+ join45(here, "..", "package.json")
31552
31763
  ];
31553
31764
  for (const p of candidates) {
31554
- if (existsSync50(p)) {
31765
+ if (existsSync51(p)) {
31555
31766
  try {
31556
- const raw = JSON.parse(readFileSync32(p, "utf8"));
31767
+ const raw = JSON.parse(readFileSync33(p, "utf8"));
31557
31768
  if (raw.version)
31558
31769
  return raw.version;
31559
31770
  } catch {}
@@ -31609,10 +31820,10 @@ class Repl {
31609
31820
  this.skillsModule = skillsModule;
31610
31821
  this.pluginManager = pluginManager;
31611
31822
  this.logger = logger;
31612
- this.configDir = configDir || join44(homedir17(), ".mma");
31823
+ this.configDir = configDir || join45(homedir17(), ".mma");
31613
31824
  this.baseDir = baseDir || process.cwd();
31614
31825
  this.noAgentsMd = noAgentsMd === true;
31615
- this.historyPath = join44(homedir17(), ".mma", "repl-history");
31826
+ this.historyPath = join45(homedir17(), ".mma", "repl-history");
31616
31827
  this.loadHistory();
31617
31828
  this.rl = process.stdin.isTTY ? new LineEditor({
31618
31829
  input: process.stdin,
@@ -31645,9 +31856,9 @@ class Repl {
31645
31856
  this.setupListeners();
31646
31857
  }
31647
31858
  loadHistory() {
31648
- if (existsSync50(this.historyPath)) {
31859
+ if (existsSync51(this.historyPath)) {
31649
31860
  try {
31650
- const raw = readFileSync32(this.historyPath, "utf-8");
31861
+ const raw = readFileSync33(this.historyPath, "utf-8");
31651
31862
  this.history = raw.split(`
31652
31863
  `).filter(Boolean).slice(-this.maxHistory);
31653
31864
  } catch {
@@ -31986,10 +32197,14 @@ ${t("image.clipboard_empty")}`));
31986
32197
  row(t("repl.skills_label"), `${pc2.white(String(this.skillsModule.getAvailable().length))} available, ${pc2.dim(`budget: ${budget.total} tokens`)}`);
31987
32198
  }
31988
32199
  if (this.pluginManager) {
31989
- const plugins = this.pluginManager.getAllPlugins().filter((p) => !p.isBuiltin);
31990
- if (plugins.length > 0) {
31991
- const pluginNames = plugins.map((p) => p.name).join(", ");
31992
- row(t("repl.plugins_label"), `${pc2.white(String(plugins.length))} active ${pc2.dim(`(${pluginNames})`)}`);
32200
+ const infos = this.pluginManager.getPluginInfos().filter(({ plugin: plugin3 }) => !plugin3.isBuiltin);
32201
+ if (infos.length > 0) {
32202
+ const pluginNames = infos.map(({ plugin: plugin3, source }) => {
32203
+ const version4 = plugin3.version ? `${pc2.dim(plugin3.version)}` : "";
32204
+ const origin = source ? pc2.dim(` [${source}]`) : "";
32205
+ return `${plugin3.name}${version4}${origin}`;
32206
+ }).join(", ");
32207
+ row(t("repl.plugins_label"), `${pc2.white(String(infos.length))} active ${pc2.dim(`(${pluginNames})`)}`);
31993
32208
  }
31994
32209
  }
31995
32210
  const mcpServers = this.config.mcpServers || {};
@@ -32004,11 +32219,11 @@ ${t("image.clipboard_empty")}`));
32004
32219
  row(t("repl.agents_label"), pc2.red(t("repl.disabled")));
32005
32220
  } else {
32006
32221
  const agentsMdCandidates = [
32007
- join44(this.baseDir, "AGENTS.md"),
32008
- join44(this.baseDir, ".mma", "AGENTS.md"),
32009
- join44(this.configDir, "AGENTS.md")
32222
+ join45(this.baseDir, "AGENTS.md"),
32223
+ join45(this.baseDir, ".mma", "AGENTS.md"),
32224
+ join45(this.configDir, "AGENTS.md")
32010
32225
  ];
32011
- const foundAgents = agentsMdCandidates.filter((p) => existsSync50(p));
32226
+ const foundAgents = agentsMdCandidates.filter((p) => existsSync51(p));
32012
32227
  if (foundAgents.length > 0) {
32013
32228
  for (const p of foundAgents) {
32014
32229
  row(t("repl.agents_label"), pc2.dim(p));
@@ -32019,7 +32234,7 @@ ${t("image.clipboard_empty")}`));
32019
32234
  }
32020
32235
  const meta = this.sessionManager?.getActiveMeta();
32021
32236
  if (meta) {
32022
- const sessionPath = join44(this.configDir, "sessions", meta.id);
32237
+ const sessionPath = join45(this.configDir, "sessions", meta.id);
32023
32238
  row(t("repl.session_label"), `${pc2.cyan(meta.name)} ${pc2.dim(`(${meta.id.slice(0, 12)})`)} — ${meta.messageCount} msgs ${pc2.dim(sessionPath)}`);
32024
32239
  }
32025
32240
  const headerWidth = Math.max(50, Math.min(96, process.stdout.columns || 96));
@@ -32060,93 +32275,16 @@ init_setup();
32060
32275
  init_config2();
32061
32276
  init_i18n();
32062
32277
  init_colors();
32063
- import { existsSync as existsSync51, readFileSync as readFileSync33 } from "fs";
32064
- import { join as join45, dirname as dirname18 } from "path";
32278
+ import { existsSync as existsSync52, readFileSync as readFileSync34 } from "fs";
32279
+ import { join as join46, dirname as dirname19 } from "path";
32065
32280
  import { homedir as homedir18 } from "os";
32066
- import { fileURLToPath as fileURLToPath6 } from "url";
32281
+ import { fileURLToPath as fileURLToPath7 } from "url";
32067
32282
 
32068
- // src/modules/updater/checker.ts
32069
- init_command();
32070
- import { platform as platform9 } from "os";
32071
- function semverGt(a, b) {
32072
- const pa = a.replace(/^v/, "").split(/[.-]/).map((p) => Number.parseInt(p, 10) || 0);
32073
- const pb = b.replace(/^v/, "").split(/[.-]/).map((p) => Number.parseInt(p, 10) || 0);
32074
- for (let i = 0;i < 3; i++) {
32075
- const na = pa[i] ?? 0;
32076
- const nb = pb[i] ?? 0;
32077
- if (na !== nb)
32078
- return na > nb;
32079
- }
32080
- return false;
32081
- }
32082
- var defaultRunner2 = async (command, args, options) => {
32083
- const { execFile } = await import("child_process");
32084
- return new Promise((resolve25) => {
32085
- execFile(command, args, options, (err) => resolve25({ error: err?.message }));
32086
- });
32087
- };
32283
+ // src/modules/updater/index.ts
32284
+ init_checker();
32088
32285
 
32089
- class Updater {
32090
- currentVersion;
32091
- packageName;
32092
- runner;
32093
- constructor(currentVersion, packageName, runner) {
32094
- this.currentVersion = currentVersion;
32095
- this.packageName = packageName;
32096
- this.runner = runner ?? defaultRunner2;
32097
- }
32098
- getCurrentVersion() {
32099
- return this.currentVersion;
32100
- }
32101
- getPackageName() {
32102
- return this.packageName;
32103
- }
32104
- async check() {
32105
- try {
32106
- const response = await fetch(`https://registry.npmjs.org/${this.packageName}`, {
32107
- headers: { Accept: "application/vnd.npm.install-v1+json" },
32108
- signal: AbortSignal.timeout(5000)
32109
- });
32110
- if (!response.ok) {
32111
- return { updateAvailable: false, current: this.currentVersion, error: `HTTP ${response.status}` };
32112
- }
32113
- const data = await response.json();
32114
- const latest = data["dist-tags"]?.latest;
32115
- if (!latest) {
32116
- return { updateAvailable: false, current: this.currentVersion, error: "No latest tag" };
32117
- }
32118
- const updateAvailable = semverGt(latest, this.currentVersion);
32119
- return { updateAvailable, current: this.currentVersion, latest };
32120
- } catch (e) {
32121
- return { updateAvailable: false, current: this.currentVersion, error: e.message };
32122
- }
32123
- }
32124
- async install(latest) {
32125
- try {
32126
- const { command, args } = this.buildInstallCommand(latest);
32127
- const res = await this.runner(command, args, {
32128
- timeout: 120000,
32129
- windowsHide: true
32130
- });
32131
- if (res.error)
32132
- return { success: false, error: res.error };
32133
- return { success: true, installed: latest };
32134
- } catch (e) {
32135
- const msg = e?.message ?? String(e);
32136
- return { success: false, error: msg.split(`
32137
- `)[0] };
32138
- }
32139
- }
32140
- buildInstallCommand(latest) {
32141
- const npmArgs = ["install", "-g", `${this.packageName}@${latest}`];
32142
- const command = resolveSpawnCommand("npm");
32143
- if (platform9() === "win32" && /\.(cmd|bat)$/i.test(command)) {
32144
- return { command: "cmd.exe", args: ["/c", command, ...npmArgs] };
32145
- }
32146
- return { command, args: npmArgs };
32147
- }
32148
- }
32149
32286
  // src/modules/updater/module.ts
32287
+ init_checker();
32150
32288
  init_i18n();
32151
32289
  init_colors();
32152
32290
 
@@ -32241,15 +32379,15 @@ class UpdaterModule {
32241
32379
  }
32242
32380
  // src/cli/main.ts
32243
32381
  function readVersion5() {
32244
- const here = dirname18(fileURLToPath6(import.meta.url));
32382
+ const here = dirname19(fileURLToPath7(import.meta.url));
32245
32383
  const candidates = [
32246
- join45(here, "..", "..", "package.json"),
32247
- join45(here, "..", "package.json")
32384
+ join46(here, "..", "..", "package.json"),
32385
+ join46(here, "..", "package.json")
32248
32386
  ];
32249
32387
  for (const p of candidates) {
32250
- if (existsSync51(p)) {
32388
+ if (existsSync52(p)) {
32251
32389
  try {
32252
- const raw = JSON.parse(readFileSync33(p, "utf8"));
32390
+ const raw = JSON.parse(readFileSync34(p, "utf8"));
32253
32391
  if (raw.version)
32254
32392
  return raw.version;
32255
32393
  } catch {}
@@ -32332,15 +32470,15 @@ async function main() {
32332
32470
  await updater?.waitForIdle();
32333
32471
  process.exit(exitCode);
32334
32472
  } else {
32335
- const configPath = join45(homedir18(), ".mma", "config.json");
32336
- if (!existsSync51(configPath)) {
32473
+ const configPath = join46(homedir18(), ".mma", "config.json");
32474
+ if (!existsSync52(configPath)) {
32337
32475
  console.log(pc2.yellow(`
32338
32476
  ` + t("cli.first_run") + `
32339
32477
  `));
32340
32478
  const answers = await runSetup();
32341
32479
  const config2 = loadConfig({
32342
- configDir: join45(homedir18(), ".mma"),
32343
- projectConfigPath: projectDir ? join45(projectDir, ".mmrc") : join45(process.cwd(), ".mmrc")
32480
+ configDir: join46(homedir18(), ".mma"),
32481
+ projectConfigPath: projectDir ? join46(projectDir, ".mmrc") : join46(process.cwd(), ".mmrc")
32344
32482
  });
32345
32483
  config2.provider.type = answers.provider;
32346
32484
  config2.provider.baseUrl = answers.apiBase;