micro-models-agent 0.46.3 → 0.47.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 +960 -843
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -2263,7 +2263,9 @@ var init_defaults = __esm(() => {
2263
2263
  retry: {
2264
2264
  maxRetries: 3,
2265
2265
  baseDelay: 1000,
2266
- maxDelay: 30000
2266
+ maxDelay: 30000,
2267
+ maxStreamRetries: 2,
2268
+ noDataTimeoutMs: 60000
2267
2269
  },
2268
2270
  maxToolIterations: 1000,
2269
2271
  stuckThreshold: 6,
@@ -2396,6 +2398,14 @@ Use read_file on {path} to see the current content before editing — the target
2396
2398
  "error.llm_retries": "LLM request failed after retries",
2397
2399
  "error.llm_429": "Rate limit exceeded (HTTP 429) for {model} on {baseUrl}. The provider is throttling requests — free models are especially strict. Get an API key or switch to a paid/faster model: {baseUrl}",
2398
2400
  "error.no_response_body": "No response body stream",
2401
+ "error.llm_stream_idle": "LLM stream stalled — no data for {timeout}ms",
2402
+ "error.llm_timeout": "LLM request timed out ({timeout}ms)",
2403
+ "env.runtime_node": "Running under Node (v{version}) — clipboard image paste, subagent performance and LSP spawn on Windows degrade. Install Bun (https://bun.sh) for full features.",
2404
+ "env.runtime_old": "Runtime version {version} is below the required engines {engine}.",
2405
+ "env.tool_missing": "Tool not found on PATH: {tool}",
2406
+ "env.playwright_missing": "Playwright package is not installed — the browser tool will fail. Install with: bun add playwright",
2407
+ "env.playwright_browsers_missing": "Playwright browsers not downloaded ({dir}). The browser tool will fail. Install with: bunx playwright install chromium",
2408
+ "env.crash_stderr": "MMA crashed ({type}): {message} — crash report written to ~/.mma/logs/crash.jsonl",
2399
2409
  "session.started": "Session started: {id}",
2400
2410
  "session.ended": "Session ended: {id}",
2401
2411
  "session.not_found": "Session not found: {id}",
@@ -2779,6 +2789,19 @@ Available commands:`,
2779
2789
  "repl.lsp_timeout": "timeout",
2780
2790
  "repl.lsp_failed": "did not start",
2781
2791
  "repl.lsp_unknown": "unknown",
2792
+ "repl.lsp": "LSP server management (status, restart, check)",
2793
+ "repl.lsp_usage": "Usage: /lsp [status|restart|check <path>]",
2794
+ "repl.lsp_not_available": "LSP module not available",
2795
+ "repl.lsp_status_header": "LSP Status:",
2796
+ "repl.lsp_enabled": "Enabled:",
2797
+ "repl.lsp_disabled_servers": "Disabled servers:",
2798
+ "repl.lsp_failure_counts": "Failure counts:",
2799
+ "repl.lsp_all_ok": "All servers operational",
2800
+ "repl.lsp_restarting": "Resetting LSP server state...",
2801
+ "repl.lsp_restarted": "LSP servers reset. Failed servers will be retried on next use.",
2802
+ "repl.lsp_check_usage": "Usage: /lsp check <file-or-directory>",
2803
+ "repl.lsp_checking": "Running LSP check on {path}...",
2804
+ "repl.lsp_check_error": "LSP check failed: {error}",
2782
2805
  "repl.work_dir": "Dir:",
2783
2806
  "repl.agents_label": "Instructions:",
2784
2807
  "repl.not_found": "not found",
@@ -3006,10 +3029,6 @@ Apply a matching solution from these results. If none is relevant — do NOT rep
3006
3029
  "tools.hidden_header": "Additional tools (enable on demand via enable_tools or route to subagent tool_tags):",
3007
3030
  "tool.friendly.enable_tools": "Enable tools",
3008
3031
  "cli.provider_base_hint": "Base URL set to: {baseUrl}",
3009
- "cli.add_provider": "Add a provider to the config",
3010
- "cli.provider_no_url": 'No base URL for provider "{name}". Pass --url.',
3011
- "cli.provider_added": "Provider added: {name}",
3012
- "cli.provider_switch_hint": "Switch to it with: mma provider use <name>",
3013
3032
  "repl.cost": "Total cost: {cost}",
3014
3033
  "repl.tokens": "Tokens used: {tokens}"
3015
3034
  };
@@ -3063,6 +3082,14 @@ var init_ru = __esm(() => {
3063
3082
  "error.llm_retries": "Запрос LLM не удался после повторов",
3064
3083
  "error.llm_429": "Превышен лимит запросов (HTTP 429) для {model} на {baseUrl}. Провайдер ограничивает трафик — особенно строгие free-модели. Получите API-ключ или переключитесь на платную/быструю модель: {baseUrl}",
3065
3084
  "error.no_response_body": "Нет потока тела ответа",
3085
+ "error.llm_stream_idle": "Поток LLM завис — нет данных {timeout}мс",
3086
+ "error.llm_timeout": "Время запроса LLM истекло ({timeout}мс)",
3087
+ "env.runtime_node": "Запущено под Node (v{version}) — вставка изображений из буфера и LSP на Windows работают урезанно. Установите Bun (https://bun.sh) для полного функционала.",
3088
+ "env.runtime_old": "Версия рантайма {version} ниже требуемой engines {engine}.",
3089
+ "env.tool_missing": "Инструмент не найден в PATH: {tool}",
3090
+ "env.playwright_missing": "Пакет Playwright не установлен — браузерный инструмент не будет работать. Установите: bun add playwright",
3091
+ "env.playwright_browsers_missing": "Браузеры Playwright не скачаны ({dir}). Браузерный инструмент не будет работать. Установите: bunx playwright install chromium",
3092
+ "env.crash_stderr": "MMA упал ({type}): {message} — отчёт о падении записан в ~/.mma/logs/crash.jsonl",
3066
3093
  "session.started": "Сессия начата: {id}",
3067
3094
  "session.ended": "Сессия завершена: {id}",
3068
3095
  "session.not_found": "Сессия не найдена: {id}",
@@ -3441,6 +3468,19 @@ var init_ru = __esm(() => {
3441
3468
  "repl.lsp_timeout": "таймаут",
3442
3469
  "repl.lsp_failed": "не стартовал",
3443
3470
  "repl.lsp_unknown": "неизвестно",
3471
+ "repl.lsp": "Управление LSP-серверами (status, restart, check)",
3472
+ "repl.lsp_usage": "Использование: /lsp [status|restart|check <путь>]",
3473
+ "repl.lsp_not_available": "Модуль LSP недоступен",
3474
+ "repl.lsp_status_header": "Статус LSP:",
3475
+ "repl.lsp_enabled": "Включён:",
3476
+ "repl.lsp_disabled_servers": "Отключённые серверы:",
3477
+ "repl.lsp_failure_counts": "Количество ошибок:",
3478
+ "repl.lsp_all_ok": "Все серверы работают",
3479
+ "repl.lsp_restarting": "Сброс состояния LSP-серверов...",
3480
+ "repl.lsp_restarted": "LSP-серверы сброшены. Упавшие серверы будут повторно запущены при следующем использовании.",
3481
+ "repl.lsp_check_usage": "Использование: /lsp check <файл-или-каталог>",
3482
+ "repl.lsp_checking": "Запуск LSP-проверки {path}...",
3483
+ "repl.lsp_check_error": "LSP-проверка не удалась: {error}",
3444
3484
  "repl.work_dir": "Директория:",
3445
3485
  "repl.agents_label": "Инструкции:",
3446
3486
  "repl.not_found": "не найден",
@@ -3674,10 +3714,6 @@ var init_ru = __esm(() => {
3674
3714
  "tools.hidden_header": "Дополнительные тулы (включите по требованию через enable_tools или маршрутизируйте через subagent tool_tags):",
3675
3715
  "tool.friendly.enable_tools": "Включить тулы",
3676
3716
  "cli.provider_base_hint": "Базовый URL установлен: {baseUrl}",
3677
- "cli.add_provider": "Добавить провайдера в конфиг",
3678
- "cli.provider_no_url": 'Нет базового URL для провайдера "{name}". Укажите --url.',
3679
- "cli.provider_added": "Провайдер добавлен: {name}",
3680
- "cli.provider_switch_hint": "Переключитесь на него: mma provider use <имя>",
3681
3717
  "repl.cost": "Итого потрачено: {cost}",
3682
3718
  "repl.tokens": "Потрачено токенов: {tokens}"
3683
3719
  };
@@ -4604,6 +4640,20 @@ class Logger {
4604
4640
  }
4605
4641
  return sanitized;
4606
4642
  }
4643
+ logStructured(type, data) {
4644
+ const logTarget = this.sessionDir ?? this.logDir;
4645
+ if (!logTarget)
4646
+ return;
4647
+ try {
4648
+ appendFileSync2(join6(logTarget, "app.jsonl"), JSON.stringify({
4649
+ level: "info",
4650
+ ts: new Date().toISOString(),
4651
+ type,
4652
+ meta: this.sanitizeMeta(data)
4653
+ }) + `
4654
+ `, "utf-8");
4655
+ } catch {}
4656
+ }
4607
4657
  }
4608
4658
  var import_picocolors, LEVELS, LEVEL_COLORS;
4609
4659
  var init_app_logger = __esm(() => {
@@ -4619,26 +4669,6 @@ var init_app_logger = __esm(() => {
4619
4669
  };
4620
4670
  });
4621
4671
 
4622
- // src/modules/providers/registry.ts
4623
- class ProviderRegistry {
4624
- specs = new Map;
4625
- register(spec) {
4626
- this.specs.set(spec.type, spec);
4627
- }
4628
- get(type) {
4629
- return this.specs.get(type);
4630
- }
4631
- has(type) {
4632
- return this.specs.has(type);
4633
- }
4634
- list() {
4635
- return [...this.specs.values()];
4636
- }
4637
- types() {
4638
- return [...this.specs.keys()];
4639
- }
4640
- }
4641
-
4642
4672
  // node_modules/base64-js/index.js
4643
4673
  var require_base64_js = __commonJS((exports) => {
4644
4674
  exports.byteLength = byteLength;
@@ -5200,7 +5230,9 @@ class OpenAICompatProvider {
5200
5230
  this.retryConfig = config.retry ?? {
5201
5231
  maxRetries: 3,
5202
5232
  baseDelay: 1000,
5203
- maxDelay: 30000
5233
+ maxDelay: 30000,
5234
+ maxStreamRetries: 2,
5235
+ noDataTimeoutMs: 60000
5204
5236
  };
5205
5237
  this.rateLimiter = createRateLimiter(config.rateLimits);
5206
5238
  }
@@ -5231,6 +5263,32 @@ class OpenAICompatProvider {
5231
5263
  }
5232
5264
  }
5233
5265
  async* doStream(messages, tools, signal, options) {
5266
+ const { baseDelay, maxDelay, maxStreamRetries, noDataTimeoutMs } = this.retryConfig;
5267
+ const streamRetries = maxStreamRetries ?? 2;
5268
+ const idleTimeoutMs = noDataTimeoutMs ?? 60000;
5269
+ for (let attempt = 0;; attempt++) {
5270
+ let emitted = false;
5271
+ const onEmit = () => {
5272
+ emitted = true;
5273
+ };
5274
+ try {
5275
+ const sawDone = yield* this.streamOnce(messages, tools, signal, options, onEmit, idleTimeoutMs);
5276
+ if (sawDone || emitted)
5277
+ return;
5278
+ if (attempt >= streamRetries)
5279
+ return;
5280
+ } catch (err) {
5281
+ if (err?.name === "AbortError" || err?.llmTerminal || signal?.aborted)
5282
+ throw err;
5283
+ if (emitted || attempt >= streamRetries)
5284
+ throw err;
5285
+ }
5286
+ const delay = Math.min(baseDelay * Math.pow(2, attempt), maxDelay);
5287
+ const jitter = Math.random() * baseDelay * 0.1;
5288
+ await this.sleep(delay + jitter, signal);
5289
+ }
5290
+ }
5291
+ async* streamOnce(messages, tools, signal, options, onEmit, idleTimeoutMs) {
5234
5292
  const body = buildRequestBody({
5235
5293
  model: this.model,
5236
5294
  messages,
@@ -5246,8 +5304,11 @@ class OpenAICompatProvider {
5246
5304
  headers["Authorization"] = `Bearer ${this.config.apiKey}`;
5247
5305
  }
5248
5306
  const controller = new AbortController;
5249
- const totalTimeoutMs = 120000;
5250
- const timeoutId = setTimeout(() => controller.abort(), totalTimeoutMs);
5307
+ let timedOut = false;
5308
+ const timeoutId = setTimeout(() => {
5309
+ timedOut = true;
5310
+ controller.abort();
5311
+ }, REQUEST_TIMEOUT_MS);
5251
5312
  const abortSignal = (() => {
5252
5313
  if (!signal)
5253
5314
  return controller.signal;
@@ -5260,20 +5321,31 @@ class OpenAICompatProvider {
5260
5321
  return controller.signal;
5261
5322
  }
5262
5323
  })();
5263
- const response = await this.fetchWithRetry(`${this.config.baseUrl}/chat/completions`, {
5264
- method: "POST",
5265
- headers,
5266
- body: JSON.stringify(body),
5267
- signal: abortSignal
5268
- });
5324
+ let response;
5325
+ try {
5326
+ response = await this.fetchWithRetry(`${this.config.baseUrl}/chat/completions`, {
5327
+ method: "POST",
5328
+ headers,
5329
+ body: JSON.stringify(body),
5330
+ signal: abortSignal
5331
+ });
5332
+ } catch (err) {
5333
+ if (err?.name === "AbortError")
5334
+ throw err;
5335
+ const wrapped = err instanceof Error ? err : new Error(String(err));
5336
+ wrapped.llmTerminal = true;
5337
+ throw wrapped;
5338
+ }
5269
5339
  if (!response.ok) {
5270
5340
  clearTimeout(timeoutId);
5271
5341
  const errorText = await response.text();
5272
- throw new Error(t("error.llm_api", {
5342
+ const err = new Error(t("error.llm_api", {
5273
5343
  status: response.status,
5274
5344
  statusText: response.statusText,
5275
5345
  errorText
5276
5346
  }));
5347
+ err.llmTerminal = true;
5348
+ throw err;
5277
5349
  }
5278
5350
  const reader = response.body?.getReader();
5279
5351
  if (!reader) {
@@ -5284,9 +5356,29 @@ class OpenAICompatProvider {
5284
5356
  let buffer = "";
5285
5357
  const toolCallAccs = new Map;
5286
5358
  let usage;
5359
+ let sawDone = false;
5360
+ const readIdle = () => new Promise((resolve, reject) => {
5361
+ const idleTimer = setTimeout(() => {
5362
+ timedOut = true;
5363
+ controller.abort();
5364
+ }, idleTimeoutMs);
5365
+ reader.read().then((result) => {
5366
+ clearTimeout(idleTimer);
5367
+ if (timedOut)
5368
+ reject(new Error(t("error.llm_stream_idle", { timeout: idleTimeoutMs })));
5369
+ else
5370
+ resolve(result);
5371
+ }, (err) => {
5372
+ clearTimeout(idleTimer);
5373
+ if (timedOut)
5374
+ reject(new Error(t("error.llm_stream_idle", { timeout: idleTimeoutMs })));
5375
+ else
5376
+ reject(err);
5377
+ });
5378
+ });
5287
5379
  try {
5288
5380
  while (true) {
5289
- const { done, value } = await reader.read();
5381
+ const { done, value } = await readIdle();
5290
5382
  if (done)
5291
5383
  break;
5292
5384
  buffer += decoder.decode(value, { stream: true });
@@ -5298,8 +5390,10 @@ class OpenAICompatProvider {
5298
5390
  if (!trimmed || !trimmed.startsWith("data: "))
5299
5391
  continue;
5300
5392
  const data = trimmed.slice(6);
5301
- if (data === "[DONE]")
5393
+ if (data === "[DONE]") {
5394
+ sawDone = true;
5302
5395
  continue;
5396
+ }
5303
5397
  try {
5304
5398
  const parsed = JSON.parse(data);
5305
5399
  const choice = parsed.choices?.[0];
@@ -5316,6 +5410,7 @@ class OpenAICompatProvider {
5316
5410
  const delta = choice.delta || {};
5317
5411
  const finishReason = choice.finish_reason;
5318
5412
  if (delta.reasoning_content) {
5413
+ onEmit();
5319
5414
  yield { type: "reasoning", content: delta.reasoning_content };
5320
5415
  }
5321
5416
  if (delta.tool_calls) {
@@ -5335,11 +5430,13 @@ class OpenAICompatProvider {
5335
5430
  }
5336
5431
  }
5337
5432
  if (delta.content) {
5433
+ onEmit();
5338
5434
  yield { type: "text", content: delta.content };
5339
5435
  }
5340
5436
  if (finishReason === "tool_calls" && toolCallAccs.size > 0) {
5341
5437
  for (const [, acc] of toolCallAccs) {
5342
5438
  if (acc.name) {
5439
+ onEmit();
5343
5440
  yield {
5344
5441
  type: "tool_call",
5345
5442
  toolCall: {
@@ -5356,12 +5453,14 @@ class OpenAICompatProvider {
5356
5453
  }
5357
5454
  }
5358
5455
  if (usage) {
5456
+ onEmit();
5359
5457
  yield { type: "done", usage };
5360
5458
  }
5361
5459
  } finally {
5362
5460
  clearTimeout(timeoutId);
5363
5461
  reader.releaseLock();
5364
5462
  }
5463
+ return sawDone;
5365
5464
  }
5366
5465
  async doNonStreaming(messages, tools, signal, options) {
5367
5466
  const body = buildRequestBody({
@@ -5378,12 +5477,30 @@ class OpenAICompatProvider {
5378
5477
  if (this.config.apiKey && this.config.apiKey !== "not-needed") {
5379
5478
  headers["Authorization"] = `Bearer ${this.config.apiKey}`;
5380
5479
  }
5480
+ const controller = new AbortController;
5481
+ let timedOut = false;
5482
+ const timeoutId = setTimeout(() => {
5483
+ timedOut = true;
5484
+ controller.abort();
5485
+ }, REQUEST_TIMEOUT_MS);
5486
+ const abortSignal = (() => {
5487
+ if (!signal)
5488
+ return controller.signal;
5489
+ try {
5490
+ return AbortSignal.any([controller.signal, signal]);
5491
+ } catch {
5492
+ signal.addEventListener("abort", () => controller.abort(), {
5493
+ once: true
5494
+ });
5495
+ return controller.signal;
5496
+ }
5497
+ })();
5381
5498
  try {
5382
5499
  const response = await this.fetchWithRetry(`${this.config.baseUrl}/chat/completions`, {
5383
5500
  method: "POST",
5384
5501
  headers,
5385
5502
  body: JSON.stringify(body),
5386
- signal
5503
+ signal: abortSignal
5387
5504
  });
5388
5505
  if (!response.ok) {
5389
5506
  const errorText = await response.text();
@@ -5430,7 +5547,12 @@ class OpenAICompatProvider {
5430
5547
  }
5431
5548
  return chunks;
5432
5549
  } catch (err) {
5550
+ if (timedOut && err?.name === "AbortError") {
5551
+ throw new Error(t("error.llm_timeout", { timeout: REQUEST_TIMEOUT_MS }));
5552
+ }
5433
5553
  throw err instanceof Error ? err : new Error(String(err));
5554
+ } finally {
5555
+ clearTimeout(timeoutId);
5434
5556
  }
5435
5557
  }
5436
5558
  countTokens(text) {
@@ -5514,281 +5636,13 @@ class OpenAICompatProvider {
5514
5636
  });
5515
5637
  }
5516
5638
  }
5639
+ var REQUEST_TIMEOUT_MS = 120000;
5517
5640
  var init_openai_compat = __esm(() => {
5518
5641
  init_token_counter();
5519
5642
  init_i18n();
5520
5643
  init_rate_limiter();
5521
5644
  });
5522
5645
 
5523
- // src/modules/providers/presets.ts
5524
- function openaiCompat(opts) {
5525
- const retry = opts.retry ?? {
5526
- maxRetries: 3,
5527
- baseDelay: 1000,
5528
- maxDelay: 30000
5529
- };
5530
- const rateLimits = opts.rateLimits;
5531
- return new OpenAICompatProvider({
5532
- model: opts.model,
5533
- baseUrl: opts.baseUrl,
5534
- apiKey: opts.apiKey,
5535
- contextWindow: opts.contextWindow,
5536
- retry,
5537
- rateLimits
5538
- });
5539
- }
5540
- var OPENAI_COMPAT, OPENROUTER, OPENAI, ANTHROPIC, OPENCODE_ZEN, OPENCODE_GO, BUILTIN_PROVIDERS, HOSTED_BASE_URLS;
5541
- var init_presets = __esm(() => {
5542
- init_openai_compat();
5543
- OPENAI_COMPAT = {
5544
- type: "openai-compat",
5545
- label: "OpenAI-compatible (LM Studio, Ollama, vLLM, etc.)",
5546
- baseUrl: "",
5547
- capabilities: {
5548
- streaming: true,
5549
- tools: true,
5550
- vision: false,
5551
- reasoningEffort: false,
5552
- listModels: true,
5553
- requiresKey: false,
5554
- auth: "bearer"
5555
- },
5556
- create: openaiCompat
5557
- };
5558
- OPENROUTER = {
5559
- type: "openrouter",
5560
- label: "OpenRouter (openrouter.ai)",
5561
- baseUrl: "https://openrouter.ai/api/v1",
5562
- capabilities: {
5563
- streaming: true,
5564
- tools: true,
5565
- vision: true,
5566
- reasoningEffort: false,
5567
- listModels: true,
5568
- requiresKey: true,
5569
- auth: "bearer"
5570
- },
5571
- create: openaiCompat
5572
- };
5573
- OPENAI = {
5574
- type: "openai",
5575
- label: "OpenAI API",
5576
- baseUrl: "https://api.openai.com/v1",
5577
- capabilities: {
5578
- streaming: true,
5579
- tools: true,
5580
- vision: true,
5581
- reasoningEffort: true,
5582
- listModels: true,
5583
- requiresKey: true,
5584
- auth: "bearer"
5585
- },
5586
- create: openaiCompat
5587
- };
5588
- ANTHROPIC = {
5589
- type: "anthropic",
5590
- label: "Anthropic Claude",
5591
- baseUrl: "https://api.anthropic.com",
5592
- capabilities: {
5593
- streaming: false,
5594
- tools: false,
5595
- vision: true,
5596
- reasoningEffort: false,
5597
- listModels: false,
5598
- requiresKey: true,
5599
- auth: "header"
5600
- },
5601
- create: openaiCompat
5602
- };
5603
- OPENCODE_ZEN = {
5604
- type: "opencode-zen",
5605
- label: "OpenCode Zen (opencode.ai/zen)",
5606
- baseUrl: "https://opencode.ai/zen/v1",
5607
- capabilities: {
5608
- streaming: true,
5609
- tools: true,
5610
- vision: false,
5611
- reasoningEffort: false,
5612
- listModels: true,
5613
- requiresKey: false,
5614
- auth: "bearer"
5615
- },
5616
- create: openaiCompat
5617
- };
5618
- OPENCODE_GO = {
5619
- type: "opencode-go",
5620
- label: "OpenCode Go (opencode.ai/go)",
5621
- baseUrl: "https://opencode.ai/zen/go/v1",
5622
- capabilities: {
5623
- streaming: true,
5624
- tools: true,
5625
- vision: false,
5626
- reasoningEffort: false,
5627
- listModels: true,
5628
- requiresKey: false,
5629
- auth: "bearer"
5630
- },
5631
- create: openaiCompat
5632
- };
5633
- BUILTIN_PROVIDERS = [
5634
- OPENAI_COMPAT,
5635
- OPENROUTER,
5636
- OPENAI,
5637
- ANTHROPIC,
5638
- OPENCODE_ZEN,
5639
- OPENCODE_GO
5640
- ];
5641
- HOSTED_BASE_URLS = {};
5642
- for (const spec of BUILTIN_PROVIDERS) {
5643
- if (spec.baseUrl)
5644
- HOSTED_BASE_URLS[spec.type] = spec.baseUrl;
5645
- }
5646
- });
5647
-
5648
- // src/modules/providers/create.ts
5649
- var exports_create = {};
5650
- __export(exports_create, {
5651
- defaultRegistry: () => defaultRegistry,
5652
- createProvider: () => createProvider
5653
- });
5654
- function createProvider(type, opts, registry = defaultRegistry()) {
5655
- const spec = registry.get(type);
5656
- if (!spec) {
5657
- return BUILTIN_PROVIDERS[0].create(opts);
5658
- }
5659
- return spec.create(opts);
5660
- }
5661
- function defaultRegistry() {
5662
- const registry = new ProviderRegistry;
5663
- for (const spec of BUILTIN_PROVIDERS) {
5664
- registry.register(spec);
5665
- }
5666
- return registry;
5667
- }
5668
- var init_create = __esm(() => {
5669
- init_presets();
5670
- });
5671
-
5672
- // src/modules/providers/manager.ts
5673
- class ProviderManager {
5674
- entries;
5675
- activeProviderName;
5676
- model;
5677
- opts;
5678
- registry;
5679
- cache = new Map;
5680
- constructor(config, opts) {
5681
- this.opts = opts;
5682
- this.registry = opts.registry ?? defaultRegistry();
5683
- this.entries = this.normalizeEntries(config);
5684
- this.activeProviderName = this.resolveActive(config);
5685
- this.model = "";
5686
- }
5687
- get activeModel() {
5688
- return this.model;
5689
- }
5690
- get activeName() {
5691
- return this.activeProviderName;
5692
- }
5693
- get active() {
5694
- return this.build(this.activeProviderName);
5695
- }
5696
- get activeEntry() {
5697
- const entry = this.entryByName(this.activeProviderName);
5698
- if (!entry)
5699
- throw new Error(`Unknown active provider "${this.activeProviderName}"`);
5700
- return entry;
5701
- }
5702
- list() {
5703
- return this.entries.map((e) => {
5704
- const preset = this.registry.get(e.type);
5705
- return { ...e, label: e.label || preset?.label || e.type };
5706
- });
5707
- }
5708
- listNames() {
5709
- return this.list().map((e) => e.label);
5710
- }
5711
- switch(name, model) {
5712
- if (!this.entryByName(name)) {
5713
- throw new Error(`Unknown provider "${name}"`);
5714
- }
5715
- this.activeProviderName = name;
5716
- if (model !== undefined)
5717
- this.model = model;
5718
- return this.active;
5719
- }
5720
- setModel(model) {
5721
- this.model = model;
5722
- return this.active;
5723
- }
5724
- toConfig() {
5725
- const active = this.activeEntry;
5726
- return {
5727
- active: this.activeProviderName,
5728
- entries: this.entries,
5729
- fallback: false,
5730
- type: active.type,
5731
- baseUrl: active.baseUrl,
5732
- apiKey: active.apiKey
5733
- };
5734
- }
5735
- normalizeEntries(config) {
5736
- if (Array.isArray(config.entries) && config.entries.length > 0) {
5737
- return config.entries.map((e) => ({ ...e, label: e.label || e.type }));
5738
- }
5739
- return [
5740
- {
5741
- type: config.type ?? "openai-compat",
5742
- label: config.type ?? "openai-compat",
5743
- baseUrl: config.baseUrl ?? "",
5744
- apiKey: config.apiKey
5745
- }
5746
- ];
5747
- }
5748
- resolveActive(config) {
5749
- if (config.active && this.entryByName(config.active))
5750
- return config.active;
5751
- const first = this.entries[0];
5752
- return first ? first.label ?? "openai-compat" : "openai-compat";
5753
- }
5754
- entryByName(name) {
5755
- return this.entries.find((e) => e.label === name || e.type === name);
5756
- }
5757
- build(name) {
5758
- const entry = this.entryByName(name);
5759
- if (!entry)
5760
- throw new Error(`Unknown provider "${name}"`);
5761
- const key = `${name}|${this.model}`;
5762
- const cached = this.cache.get(key);
5763
- if (cached)
5764
- return cached;
5765
- const provider = createProvider(entry.type, {
5766
- model: this.model,
5767
- baseUrl: entry.baseUrl,
5768
- apiKey: entry.apiKey,
5769
- contextWindow: entry.contextWindow ?? this.opts.contextWindow,
5770
- retry: entry.retry ?? this.opts.retry,
5771
- rateLimits: entry.rateLimits ?? this.opts.rateLimits
5772
- }, this.registry);
5773
- this.cache.set(key, provider);
5774
- return provider;
5775
- }
5776
- resetCache() {
5777
- this.cache.clear();
5778
- }
5779
- }
5780
- var init_manager = __esm(() => {
5781
- init_create();
5782
- init_presets();
5783
- });
5784
-
5785
- // src/modules/providers/index.ts
5786
- var init_providers = __esm(() => {
5787
- init_create();
5788
- init_manager();
5789
- init_presets();
5790
- });
5791
-
5792
5646
  // src/llm/model-loader.ts
5793
5647
  class ModelLoader {
5794
5648
  baseUrl;
@@ -6560,20 +6414,10 @@ var init_audit_log = __esm(() => {
6560
6414
  });
6561
6415
 
6562
6416
  // src/tools/path-utils.ts
6563
- import { resolve as resolve3, normalize as normalize2, dirname as dirname3, basename, sep, isAbsolute } from "path";
6417
+ import { resolve as resolve3, normalize as normalize2, dirname as dirname3, basename, sep } from "path";
6564
6418
  import { existsSync as existsSync9 } from "fs";
6565
6419
  function safeResolvePath(baseDir, userPath) {
6566
6420
  const norm = normalize2(userPath);
6567
- if (isAbsolute(norm)) {
6568
- if (existsSync9(norm) || existsSync9(dirname3(norm)))
6569
- return norm;
6570
- const stripped2 = norm.replace(/^[/\\]/, "");
6571
- const relativeCandidate = resolve3(baseDir, stripped2);
6572
- if (existsSync9(relativeCandidate) || existsSync9(dirname3(relativeCandidate))) {
6573
- return relativeCandidate;
6574
- }
6575
- return norm;
6576
- }
6577
6421
  const stripped = norm.replace(/^[/\\]/, "");
6578
6422
  const resolved = resolve3(baseDir, stripped);
6579
6423
  if (existsSync9(resolved) || existsSync9(dirname3(resolved)))
@@ -8555,13 +8399,14 @@ var init_prompt_builder = __esm(() => {
8555
8399
  });
8556
8400
 
8557
8401
  // src/core/session-logger.ts
8402
+ import { join as join10 } from "path";
8403
+ import { readFileSync as readFileSync9, existsSync as existsSync18 } from "fs";
8404
+
8558
8405
  class SessionLogger {
8559
8406
  session;
8560
- getCaller;
8561
8407
  logger;
8562
- constructor(session, logger, getCaller) {
8408
+ constructor(session, logger) {
8563
8409
  this.session = session;
8564
- this.getCaller = getCaller;
8565
8410
  this.logger = logger;
8566
8411
  this.bindSessionDir();
8567
8412
  }
@@ -8599,15 +8444,12 @@ class SessionLogger {
8599
8444
  });
8600
8445
  }
8601
8446
  logAssistant(content, reasoning, toolCalls, iteration) {
8602
- const caller = this.getCaller?.();
8603
8447
  if (reasoning) {
8604
8448
  this.session?.appendLog({
8605
8449
  ts: new Date().toISOString(),
8606
8450
  type: "reasoning",
8607
8451
  content: reasoning,
8608
- iteration,
8609
- provider: caller?.provider,
8610
- model: caller?.model
8452
+ iteration
8611
8453
  });
8612
8454
  }
8613
8455
  this.session?.appendLog({
@@ -8621,19 +8463,14 @@ class SessionLogger {
8621
8463
  arguments: tc.arguments
8622
8464
  }))
8623
8465
  } : {},
8624
- iteration,
8625
- provider: caller?.provider,
8626
- model: caller?.model
8466
+ iteration
8627
8467
  });
8628
8468
  }
8629
8469
  saveAssistantMessage(content) {
8630
- const caller = this.getCaller?.();
8631
8470
  this.session?.appendMessage({
8632
8471
  role: "assistant",
8633
8472
  content: content.slice(0, 500),
8634
- timestamp: new Date().toISOString(),
8635
- provider: caller?.provider,
8636
- model: caller?.model
8473
+ timestamp: new Date().toISOString()
8637
8474
  });
8638
8475
  }
8639
8476
  logToolDefs(toolCount, toolNames, iteration) {
@@ -8656,14 +8493,11 @@ class SessionLogger {
8656
8493
  });
8657
8494
  }
8658
8495
  logToolResult(call, result, duration, iteration) {
8659
- const caller = this.getCaller?.();
8660
8496
  this.session?.appendMessage({
8661
8497
  role: "tool",
8662
8498
  content: result.output.slice(0, 500),
8663
8499
  name: call.name,
8664
- timestamp: new Date().toISOString(),
8665
- provider: caller?.provider,
8666
- model: caller?.model
8500
+ timestamp: new Date().toISOString()
8667
8501
  });
8668
8502
  this.session?.appendLog({
8669
8503
  ts: new Date().toISOString(),
@@ -8674,9 +8508,7 @@ class SessionLogger {
8674
8508
  content: result.output.slice(0, 1000),
8675
8509
  diff: result.diff,
8676
8510
  duration,
8677
- iteration,
8678
- provider: caller?.provider,
8679
- model: caller?.model
8511
+ iteration
8680
8512
  });
8681
8513
  }
8682
8514
  logCompaction(info) {
@@ -8703,8 +8535,6 @@ class SessionLogger {
8703
8535
  type: "context",
8704
8536
  content: info.kind === "start" ? "context snapshot at session start" : `context at iteration ${info.iteration}`,
8705
8537
  iteration: info.iteration,
8706
- provider: info.provider,
8707
- model: info.model,
8708
8538
  window: info.window,
8709
8539
  systemBudget: info.systemBudget,
8710
8540
  reserveBudget: info.reserveBudget,
@@ -8724,8 +8554,6 @@ class SessionLogger {
8724
8554
  ts: new Date().toISOString(),
8725
8555
  type: "llm_usage",
8726
8556
  iteration,
8727
- provider: usage.provider,
8728
- model: usage.model,
8729
8557
  promptTokens: usage.promptTokens,
8730
8558
  completionTokens: usage.completionTokens,
8731
8559
  totalTokens: usage.totalTokens,
@@ -8757,6 +8585,28 @@ class SessionLogger {
8757
8585
  ...iteration !== undefined ? { iteration } : {}
8758
8586
  });
8759
8587
  }
8588
+ logSessionStart(data) {
8589
+ const meta = this.session?.getActiveMeta();
8590
+ if (meta) {
8591
+ const logPath = join10(this.session.getSessionDirectory(meta.id), "session.jsonl");
8592
+ try {
8593
+ if (existsSync18(logPath)) {
8594
+ const content = readFileSync9(logPath, "utf-8");
8595
+ if (content.includes('"type":"session_start"'))
8596
+ return;
8597
+ }
8598
+ } catch {}
8599
+ }
8600
+ this.session?.appendLog({
8601
+ ts: new Date().toISOString(),
8602
+ type: "session_start",
8603
+ content: "session started",
8604
+ environment: data.environment,
8605
+ lspProbe: data.lspProbe,
8606
+ plugins: data.plugins,
8607
+ skills: data.skills
8608
+ });
8609
+ }
8760
8610
  }
8761
8611
  var init_session_logger = __esm(() => {
8762
8612
  init_audit_log();
@@ -9538,20 +9388,18 @@ class OrchestratorClient {
9538
9388
  this.config = config;
9539
9389
  if (config.model) {
9540
9390
  if (config.provider) {
9541
- this.provider = createProvider(config.provider.type ?? "openai-compat", {
9391
+ this.provider = new OpenAICompatProvider({
9542
9392
  model: config.model,
9543
9393
  baseUrl: config.provider.baseUrl || "http://localhost:1234/v1",
9544
9394
  apiKey: config.provider.apiKey,
9545
- contextWindow: 32768,
9546
9395
  retry: config.retry
9547
9396
  });
9548
9397
  } else if (defaultProvider) {
9549
9398
  this.provider = defaultProvider;
9550
9399
  } else {
9551
- this.provider = createProvider("openai-compat", {
9400
+ this.provider = new OpenAICompatProvider({
9552
9401
  model: config.model,
9553
9402
  baseUrl: "http://localhost:1234/v1",
9554
- contextWindow: 32768,
9555
9403
  retry: config.retry
9556
9404
  });
9557
9405
  }
@@ -9718,7 +9566,7 @@ Respond with JSON only:
9718
9566
 
9719
9567
  Max 3 re-plan cycles. After 3 cycles, return partial result.`;
9720
9568
  var init_orchestrator = __esm(() => {
9721
- init_create();
9569
+ init_openai_compat();
9722
9570
  init_esm();
9723
9571
  });
9724
9572
 
@@ -10415,8 +10263,8 @@ var init_stuck_detector = __esm(() => {
10415
10263
  });
10416
10264
 
10417
10265
  // src/modules/artifacts/store.ts
10418
- import { existsSync as existsSync18, mkdirSync as mkdirSync11, readFileSync as readFileSync9, writeFileSync as writeFileSync7 } from "node:fs";
10419
- import { resolve as resolve10, relative, isAbsolute as isAbsolute2 } from "node:path";
10266
+ import { existsSync as existsSync19, mkdirSync as mkdirSync11, readFileSync as readFileSync10, writeFileSync as writeFileSync7 } from "node:fs";
10267
+ import { resolve as resolve10, relative, isAbsolute } from "node:path";
10420
10268
 
10421
10269
  class ArtifactStore {
10422
10270
  root;
@@ -10436,7 +10284,7 @@ class ArtifactStore {
10436
10284
  const rel = relative(root, candidate);
10437
10285
  if (rel === "")
10438
10286
  return true;
10439
- return !rel.startsWith("..") && !isAbsolute2(rel);
10287
+ return !rel.startsWith("..") && !isAbsolute(rel);
10440
10288
  }
10441
10289
  save(name, content, ext = "md") {
10442
10290
  const safe = ArtifactStore.sanitizeName(name);
@@ -10453,9 +10301,9 @@ class ArtifactStore {
10453
10301
  const abs = resolve10(this.root, path);
10454
10302
  if (!ArtifactStore.isInside(this.root, abs))
10455
10303
  return null;
10456
- if (!existsSync18(abs))
10304
+ if (!existsSync19(abs))
10457
10305
  return null;
10458
- return readFileSync9(abs, "utf8");
10306
+ return readFileSync10(abs, "utf8");
10459
10307
  }
10460
10308
  summary(content, maxChars) {
10461
10309
  if (content.length <= maxChars)
@@ -10769,15 +10617,15 @@ var init_moe_executor = __esm(() => {
10769
10617
  });
10770
10618
 
10771
10619
  // src/modules/lsp/project-root.ts
10772
- import { existsSync as existsSync19 } from "fs";
10773
- import { dirname as dirname6, join as join10 } from "path";
10620
+ import { existsSync as existsSync20 } from "fs";
10621
+ import { dirname as dirname6, join as join11 } from "path";
10774
10622
  function findProjectRoot(filePath, baseDir, markers) {
10775
10623
  if (!markers || markers.length === 0)
10776
10624
  return baseDir;
10777
10625
  let dir = dirname6(filePath);
10778
10626
  const root = baseDir.replace(/[\\/]+$/, "");
10779
10627
  while (true) {
10780
- if (markers.some((m) => existsSync19(join10(dir, m)))) {
10628
+ if (markers.some((m) => existsSync20(join11(dir, m)))) {
10781
10629
  return dir;
10782
10630
  }
10783
10631
  if (dir === root)
@@ -11000,13 +10848,13 @@ var init_js_identifiers = __esm(() => {
11000
10848
  });
11001
10849
 
11002
10850
  // src/modules/execution/audit-runners.ts
11003
- import { existsSync as existsSync20, readdirSync as readdirSync5, readFileSync as readFileSync10 } from "fs";
11004
- import { dirname as dirname7, join as join11, resolve as resolve11 } from "path";
10851
+ import { existsSync as existsSync21, readdirSync as readdirSync5, readFileSync as readFileSync11 } from "fs";
10852
+ import { dirname as dirname7, join as join12, resolve as resolve11 } from "path";
11005
10853
  function resolveTestCommand(dir) {
11006
- const pkgPath = join11(dir, "package.json");
11007
- if (existsSync20(pkgPath)) {
10854
+ const pkgPath = join12(dir, "package.json");
10855
+ if (existsSync21(pkgPath)) {
11008
10856
  try {
11009
- const pkg = JSON.parse(readFileSync10(pkgPath, "utf-8"));
10857
+ const pkg = JSON.parse(readFileSync11(pkgPath, "utf-8"));
11010
10858
  const script = pkg?.scripts?.test;
11011
10859
  if (typeof script === "string" && script.trim())
11012
10860
  return script.trim();
@@ -11022,7 +10870,7 @@ function resolveTestCommand(dir) {
11022
10870
  "jest.config.cjs",
11023
10871
  "bunfig.toml"
11024
10872
  ]) {
11025
- if (existsSync20(join11(dir, f))) {
10873
+ if (existsSync21(join12(dir, f))) {
11026
10874
  if (f.startsWith("vitest"))
11027
10875
  return "bunx vitest run";
11028
10876
  if (f.startsWith("jest"))
@@ -11031,12 +10879,12 @@ function resolveTestCommand(dir) {
11031
10879
  return "bun test";
11032
10880
  }
11033
10881
  }
11034
- if (existsSync20(join11(dir, "pyproject.toml")) || existsSync20(join11(dir, "pytest.ini")) || existsSync20(join11(dir, "conftest.py"))) {
10882
+ if (existsSync21(join12(dir, "pyproject.toml")) || existsSync21(join12(dir, "pytest.ini")) || existsSync21(join12(dir, "conftest.py"))) {
11035
10883
  return "python -m pytest -q";
11036
10884
  }
11037
- if (existsSync20(join11(dir, "go.mod")))
10885
+ if (existsSync21(join12(dir, "go.mod")))
11038
10886
  return "go test ./...";
11039
- if (existsSync20(join11(dir, "Cargo.toml")))
10887
+ if (existsSync21(join12(dir, "Cargo.toml")))
11040
10888
  return "cargo test";
11041
10889
  return "bun test";
11042
10890
  }
@@ -11050,7 +10898,7 @@ function findTestFile(dir, depth = 0) {
11050
10898
  return null;
11051
10899
  }
11052
10900
  for (const e of entries) {
11053
- const full = join11(dir, e.name);
10901
+ const full = join12(dir, e.name);
11054
10902
  if (e.isDirectory()) {
11055
10903
  if (SKIP_DIRS.has(e.name))
11056
10904
  continue;
@@ -11126,7 +10974,7 @@ function findTypecheckRoot(baseDir, existingFiles = []) {
11126
10974
  for (const start of candidates) {
11127
10975
  let dir = resolve11(start);
11128
10976
  for (let depth = 0;depth <= 10; depth++) {
11129
- if (existsSync20(join11(dir, "tsconfig.json"))) {
10977
+ if (existsSync21(join12(dir, "tsconfig.json"))) {
11130
10978
  if (!best || depth < best.depth)
11131
10979
  best = { depth, root: dir };
11132
10980
  break;
@@ -11170,11 +11018,11 @@ var init_audit_runners = __esm(() => {
11170
11018
  });
11171
11019
 
11172
11020
  // src/modules/execution/auditor.ts
11173
- import { existsSync as existsSync21, readdirSync as readdirSync6 } from "fs";
11174
- import { resolve as resolve12, join as join12, basename as basename2 } from "path";
11021
+ import { existsSync as existsSync22, readdirSync as readdirSync6 } from "fs";
11022
+ import { resolve as resolve12, join as join13, basename as basename2 } from "path";
11175
11023
  function findExistingFile(baseDir, filePath) {
11176
11024
  const direct = resolve12(baseDir, filePath);
11177
- if (existsSync21(direct))
11025
+ if (existsSync22(direct))
11178
11026
  return direct;
11179
11027
  const name = basename2(filePath).toLowerCase();
11180
11028
  const suffix = filePath.replace(/\\/g, "/").toLowerCase();
@@ -11191,7 +11039,7 @@ function findExistingFile(baseDir, filePath) {
11191
11039
  for (const e of entries) {
11192
11040
  if (found)
11193
11041
  return;
11194
- const full = join12(dir, e.name);
11042
+ const full = join13(dir, e.name);
11195
11043
  if (e.isDirectory()) {
11196
11044
  if (SKIP_DIRS.has(e.name))
11197
11045
  continue;
@@ -11329,8 +11177,8 @@ var init_auditor = __esm(() => {
11329
11177
  });
11330
11178
 
11331
11179
  // src/modules/execution/verifier.ts
11332
- import { existsSync as existsSync22 } from "fs";
11333
- import { resolve as resolve13, extname as extname2, join as join13 } from "path";
11180
+ import { existsSync as existsSync23 } from "fs";
11181
+ import { resolve as resolve13, extname as extname2, join as join14 } from "path";
11334
11182
  import { spawn as spawn2 } from "child_process";
11335
11183
 
11336
11184
  class StepVerifier {
@@ -11340,7 +11188,7 @@ class StepVerifier {
11340
11188
  }
11341
11189
  async checkFileExists(path) {
11342
11190
  const resolved = resolve13(this.baseDir, path);
11343
- const exists = existsSync22(resolved);
11191
+ const exists = existsSync23(resolved);
11344
11192
  return {
11345
11193
  passed: exists,
11346
11194
  message: exists ? t("verify.file_exists", { path }) : t("verify.file_not_found", { path })
@@ -11359,7 +11207,7 @@ class StepVerifier {
11359
11207
  }
11360
11208
  async runTypeCheck() {
11361
11209
  const tsconfigPath = resolve13(this.baseDir, "tsconfig.json");
11362
- if (!existsSync22(tsconfigPath)) {
11210
+ if (!existsSync23(tsconfigPath)) {
11363
11211
  return { passed: true, message: "No tsconfig.json found — skipping type check" };
11364
11212
  }
11365
11213
  try {
@@ -11372,8 +11220,8 @@ class StepVerifier {
11372
11220
  }
11373
11221
  async runTypeCheckForFile(filePath) {
11374
11222
  const projectRoot = findProjectRoot(filePath, this.baseDir, ["tsconfig.json", "package.json"]);
11375
- const tsconfigPath = join13(projectRoot, "tsconfig.json");
11376
- if (!existsSync22(tsconfigPath)) {
11223
+ const tsconfigPath = join14(projectRoot, "tsconfig.json");
11224
+ if (!existsSync23(tsconfigPath)) {
11377
11225
  return { passed: true, message: "No tsconfig.json found — skipping type check" };
11378
11226
  }
11379
11227
  try {
@@ -11386,7 +11234,7 @@ class StepVerifier {
11386
11234
  }
11387
11235
  async runTests() {
11388
11236
  const pkgPath = resolve13(this.baseDir, "package.json");
11389
- if (!existsSync22(pkgPath)) {
11237
+ if (!existsSync23(pkgPath)) {
11390
11238
  return { passed: true, message: "No package.json found — skipping tests" };
11391
11239
  }
11392
11240
  try {
@@ -11783,8 +11631,6 @@ var init_pricing = __esm(() => {
11783
11631
  });
11784
11632
 
11785
11633
  // src/core/agent.ts
11786
- import { join as join14 } from "path";
11787
- import { homedir as homedir5 } from "os";
11788
11634
  function isToolCallJson(text) {
11789
11635
  const trimmed = text.trim();
11790
11636
  if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
@@ -11849,17 +11695,6 @@ class Agent {
11849
11695
  blocks: result.blocks
11850
11696
  };
11851
11697
  }
11852
- callerProvenance() {
11853
- const manager = this.deps.providerManager;
11854
- if (manager) {
11855
- return {
11856
- provider: manager.activeName,
11857
- model: manager.activeModel || this.deps.config.model
11858
- };
11859
- }
11860
- const p = this.deps.config.provider;
11861
- return { provider: p.type, model: this.deps.config.model };
11862
- }
11863
11698
  logContextStat(kind, iteration, slog, blocks) {
11864
11699
  const cm = this.deps.contextManager;
11865
11700
  if (typeof cm.getSnapshot !== "function")
@@ -11867,12 +11702,9 @@ class Agent {
11867
11702
  const snap = cm.getSnapshot();
11868
11703
  const history = cm.getActiveHistory();
11869
11704
  const systemMsg = history.find((m) => m.role === "system");
11870
- const caller = this.callerProvenance();
11871
11705
  slog.logContext({
11872
11706
  kind,
11873
11707
  iteration,
11874
- provider: caller.provider,
11875
- model: caller.model,
11876
11708
  window: snap.window,
11877
11709
  systemBudget: snap.budget.systemPrompt,
11878
11710
  reserveBudget: snap.budget.responseReserve,
@@ -11931,6 +11763,7 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
11931
11763
  onPhase?.(phase);
11932
11764
  }
11933
11765
  async run(input, onChunk, onMeta, onTool, onPhase) {
11766
+ this.shutdownRequested = false;
11934
11767
  this.setScope();
11935
11768
  const {
11936
11769
  config,
@@ -11942,12 +11775,15 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
11942
11775
  sessionManager,
11943
11776
  baseDir
11944
11777
  } = this.deps;
11945
- const slog = new SessionLogger(sessionManager, logger, () => this.callerProvenance());
11778
+ const slog = new SessionLogger(sessionManager, logger);
11946
11779
  if (sessionManager && !sessionManager.getActive()) {
11947
11780
  sessionManager.create();
11948
11781
  logger.debug(`Session started: ${sessionManager.getActive()}`);
11949
11782
  }
11950
11783
  if (!this.systemPromptAdded && !contextManager.getActiveHistory().some((m) => m.role === "system")) {
11784
+ slog.logSessionStart({
11785
+ environment: this.deps.envReport
11786
+ });
11951
11787
  const lazy = this.deps.lazyPromptBlocks ? await this.deps.lazyPromptBlocks() : [];
11952
11788
  if (lazy.length > 0) {
11953
11789
  this.deps.promptBlocks.push(...lazy);
@@ -11964,17 +11800,6 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
11964
11800
  sessionManager: sessionManager?.getActiveMeta(),
11965
11801
  contextManager
11966
11802
  });
11967
- if (config.session?.baselineCheck !== false) {
11968
- const verifier = new StepVerifier(baseDir);
11969
- verifier.runTypeCheck().then((tc) => {
11970
- if (!tc.passed) {
11971
- logger.warn(`Baseline typecheck has issues: ${tc.message?.slice(0, 500)}`);
11972
- onMeta?.(pc2.yellow(`
11973
- ⚠ Baseline typecheck has issues
11974
- `));
11975
- }
11976
- }).catch(() => {});
11977
- }
11978
11803
  }
11979
11804
  if (typeof contextManager.resetUserTurn === "function") {
11980
11805
  contextManager.resetUserTurn();
@@ -12004,7 +11829,7 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
12004
11829
  sessionManager,
12005
11830
  baseDir
12006
11831
  } = this.deps;
12007
- const slog = new SessionLogger(sessionManager, logger, () => this.callerProvenance());
11832
+ const slog = new SessionLogger(sessionManager, logger);
12008
11833
  this.abortController = new AbortController;
12009
11834
  let iteration = 0;
12010
11835
  let lastText = "";
@@ -12107,7 +11932,7 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
12107
11932
  const llmStart = Date.now();
12108
11933
  const promptBefore = apiPromptTokens;
12109
11934
  const completionBefore = apiCompletionTokens;
12110
- logger.logLLMRequest(config.model, history.length, input, this.callerProvenance().provider);
11935
+ logger.logLLMRequest(config.model, history.length, input, "agent");
12111
11936
  try {
12112
11937
  for await (const chunk of llmProvider.chat(history, allToolsForBudget, this.abortController?.signal)) {
12113
11938
  if (this.shutdownRequested)
@@ -12169,17 +11994,14 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
12169
11994
  this.emitPhase(iteration, "done", onPhase);
12170
11995
  }
12171
11996
  apiCompletionChars += (textContent || reasoningContent).length;
12172
- logger.logLLMResponse(config.model, (textContent || reasoningContent).length, Date.now() - llmStart, undefined, this.callerProvenance().provider);
11997
+ logger.logLLMResponse(config.model, (textContent || reasoningContent).length, Date.now() - llmStart, undefined, "agent");
12173
11998
  {
12174
11999
  const usagePrompt = apiPromptTokens - promptBefore;
12175
12000
  const usageCompletion = apiCompletionTokens - completionBefore;
12176
12001
  const source = usagePrompt > 0 || usageCompletion > 0 ? "api" : "estimate";
12177
12002
  const prompt = source === "api" ? usagePrompt : contextManager.getEstimatedTokens();
12178
12003
  const completion = source === "api" ? usageCompletion : Math.ceil((textContent || reasoningContent).length / 4);
12179
- const caller = this.callerProvenance();
12180
12004
  slog.logLlmUsage(iteration, {
12181
- provider: caller.provider,
12182
- model: caller.model,
12183
12005
  promptTokens: prompt,
12184
12006
  completionTokens: completion,
12185
12007
  totalTokens: prompt + completion,
@@ -12296,7 +12118,6 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
12296
12118
  arguments: call.arguments
12297
12119
  });
12298
12120
  const tokensAfterTool = contextManager.getEstimatedTokens();
12299
- const caller = this.callerProvenance();
12300
12121
  onTool?.({
12301
12122
  type: "end",
12302
12123
  tool: call.name,
@@ -12304,9 +12125,7 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
12304
12125
  duration,
12305
12126
  error: !result.success,
12306
12127
  ctxDelta: tokensAfterTool - tokensBeforeTool,
12307
- costUsd: this.costTracker.total,
12308
- provider: caller.provider,
12309
- model: caller.model
12128
+ costUsd: this.costTracker.total
12310
12129
  });
12311
12130
  summaries.push(`[Tool: ${call.name} (${JSON.stringify(call.arguments)}) → ${truncatedOutput.slice(0, 200)}]`);
12312
12131
  if (config.session.autoSave) {
@@ -12566,57 +12385,23 @@ ${warnLine}
12566
12385
  this.systemPromptAdded = false;
12567
12386
  }
12568
12387
  async reconfigure(config) {
12388
+ const { OpenAICompatProvider: OpenAICompatProvider2 } = await Promise.resolve().then(() => (init_openai_compat(), exports_openai_compat));
12569
12389
  const { TokenCounter: TokenCounter2 } = await Promise.resolve().then(() => (init_token_counter(), exports_token_counter));
12570
- const manager = this.deps.providerManager;
12571
- const newProvider = manager ? manager.setModel(config.model) : await this.buildLegacyProvider(config, config.model);
12572
- this.deps.llmProvider = newProvider;
12573
- this.deps.toolExecutor.updateProvider(newProvider);
12574
- this.deps.toolExecutor.ctx.llmProvider = newProvider;
12575
- const newTokenCounter = new TokenCounter2(config.model);
12576
- this.deps.contextManager.resize(config.contextWindow, config.contextBudget, newTokenCounter);
12577
- this.deps.config = config;
12578
- this.costTracker.setModel(config.model);
12579
- }
12580
- async buildLegacyProvider(config, model) {
12581
- const { createProvider: createProvider2 } = await Promise.resolve().then(() => (init_create(), exports_create));
12582
- return createProvider2(config.provider.type ?? "openai-compat", {
12583
- model,
12584
- baseUrl: config.provider.baseUrl ?? "",
12390
+ const newProvider = new OpenAICompatProvider2({
12391
+ model: config.model,
12392
+ baseUrl: config.provider.baseUrl,
12585
12393
  apiKey: config.provider.apiKey,
12586
12394
  contextWindow: config.contextWindow,
12587
12395
  retry: config.retry,
12588
12396
  rateLimits: config.security?.rateLimits
12589
12397
  });
12590
- }
12591
- async setProvider(name, model) {
12592
- const manager = this.deps.providerManager;
12593
- if (!manager) {
12594
- throw new Error("ProviderManager is not available (legacy single-provider config)");
12595
- }
12596
- const newProvider = manager.switch(name, model ?? this.deps.config.model);
12597
- const config = this.deps.config;
12598
- config.provider.active = name;
12599
- config.provider.type = manager.activeEntry.type;
12600
- config.provider.baseUrl = manager.activeEntry.baseUrl;
12601
- config.provider.apiKey = manager.activeEntry.apiKey;
12602
12398
  this.deps.llmProvider = newProvider;
12603
12399
  this.deps.toolExecutor.updateProvider(newProvider);
12604
12400
  this.deps.toolExecutor.ctx.llmProvider = newProvider;
12605
- this.costTracker.setModel(newProvider.model);
12606
- const configPath = join14(homedir5(), ".mma", "config.json");
12607
- const { saveConfig: saveConfig2 } = await Promise.resolve().then(() => (init_config2(), exports_config));
12608
- saveConfig2(config, configPath);
12609
- }
12610
- listProviders() {
12611
- const manager = this.deps.providerManager;
12612
- if (!manager)
12613
- return [];
12614
- return manager.list().map((e) => ({
12615
- type: e.type,
12616
- label: e.label,
12617
- baseUrl: e.baseUrl,
12618
- active: e.label === manager.activeName
12619
- }));
12401
+ const newTokenCounter = new TokenCounter2(config.model);
12402
+ this.deps.contextManager.resize(config.contextWindow, config.contextBudget, newTokenCounter);
12403
+ this.deps.config = config;
12404
+ this.costTracker.setModel(config.model);
12620
12405
  }
12621
12406
  setContext(messages) {
12622
12407
  const { contextManager } = this.deps;
@@ -12643,7 +12428,6 @@ ${warnLine}
12643
12428
  if (killed > 0) {
12644
12429
  logger.info(`Killed ${killed} background process(es) on shutdown`);
12645
12430
  }
12646
- logger.closeSessionLog();
12647
12431
  pluginManager.runOnSessionEnd({
12648
12432
  logger,
12649
12433
  sessionManager: sessionManager?.getActiveMeta(),
@@ -12659,7 +12443,6 @@ var init_agent = __esm(() => {
12659
12443
  init_processes();
12660
12444
  init_session_logger();
12661
12445
  init_agent_moe();
12662
- init_verifier();
12663
12446
  init_pricing();
12664
12447
  });
12665
12448
 
@@ -13120,7 +12903,7 @@ ${lines.join(`
13120
12903
  }
13121
12904
  }
13122
12905
  var COMPACTION_INTERVAL = 15, KEEP_LAST_N = 6;
13123
- var init_manager2 = __esm(() => {
12906
+ var init_manager = __esm(() => {
13124
12907
  init_fact_extractor();
13125
12908
  });
13126
12909
 
@@ -13216,8 +12999,8 @@ var init_confidence = __esm(() => {
13216
12999
  });
13217
13000
 
13218
13001
  // src/modules/hallucination/factual.ts
13219
- import { existsSync as existsSync23, readdirSync as readdirSync7 } from "fs";
13220
- import { resolve as resolve14, isAbsolute as isAbsolute3, join as join15 } from "path";
13002
+ import { existsSync as existsSync24, readdirSync as readdirSync7 } from "fs";
13003
+ import { resolve as resolve14, isAbsolute as isAbsolute2, join as join15 } from "path";
13221
13004
 
13222
13005
  class FactualCheck {
13223
13006
  baseDir;
@@ -13256,17 +13039,17 @@ class FactualCheck {
13256
13039
  return { status: "pass" };
13257
13040
  }
13258
13041
  pathExists(fp) {
13259
- if (isAbsolute3(fp))
13260
- return existsSync23(fp);
13042
+ if (isAbsolute2(fp))
13043
+ return existsSync24(fp);
13261
13044
  if (this.knownFiles.has(fp))
13262
13045
  return true;
13263
13046
  if (!fp.includes("/") && !fp.includes("\\")) {
13264
13047
  return this.bareNameExists(fp);
13265
13048
  }
13266
- return existsSync23(resolve14(this.baseDir, fp));
13049
+ return existsSync24(resolve14(this.baseDir, fp));
13267
13050
  }
13268
13051
  bareNameExists(name) {
13269
- if (existsSync23(resolve14(this.baseDir, name)))
13052
+ if (existsSync24(resolve14(this.baseDir, name)))
13270
13053
  return true;
13271
13054
  if (this.indexHas(name))
13272
13055
  return true;
@@ -13486,7 +13269,7 @@ var init_detector = __esm(() => {
13486
13269
 
13487
13270
  // src/modules/lsp/command.ts
13488
13271
  import { delimiter, join as join16 } from "path";
13489
- import { existsSync as existsSync24 } from "fs";
13272
+ import { existsSync as existsSync25 } from "fs";
13490
13273
  import { platform as platform3 } from "os";
13491
13274
  function resolveSpawnCommand(command, platformName = platform3(), pathEnv = process.env.PATH ?? "") {
13492
13275
  if (platformName !== "win32")
@@ -13498,7 +13281,7 @@ function resolveSpawnCommand(command, platformName = platform3(), pathEnv = proc
13498
13281
  for (const dir of dirs) {
13499
13282
  for (const ext of WIN_EXTS) {
13500
13283
  const candidate = join16(dir, `${command}${ext}`);
13501
- if (existsSync24(candidate))
13284
+ if (existsSync25(candidate))
13502
13285
  return `${command}${ext}`;
13503
13286
  }
13504
13287
  }
@@ -13775,7 +13558,7 @@ class PluginManager {
13775
13558
  return chunk;
13776
13559
  }
13777
13560
  }
13778
- var init_manager3 = __esm(() => {
13561
+ var init_manager2 = __esm(() => {
13779
13562
  init_checker();
13780
13563
  });
13781
13564
 
@@ -13795,9 +13578,9 @@ Workflow rules:
13795
13578
  var init_subagent = __esm(() => {
13796
13579
  init_i18n();
13797
13580
  init_agent();
13798
- init_manager2();
13581
+ init_manager();
13799
13582
  init_detector();
13800
- init_manager3();
13583
+ init_manager2();
13801
13584
  init_audit_log();
13802
13585
  init_session_isolation();
13803
13586
  init_store();
@@ -14094,7 +13877,7 @@ ${joined}` }
14094
13877
  var DEFAULT_CHUNK_SYSTEM_PROMPT = 'Answer the query using ONLY the provided text. Be concise. If the text does not contain the answer, say "NO_EVIDENCE".', DEFAULT_SYNTHESIS_SYSTEM_PROMPT = "You are given a query and per-chunk answers over a large text. Produce the final answer to the query, combining evidence from the chunks. If no chunk had evidence, say so.";
14095
13878
 
14096
13879
  // src/tools/chunk-query.ts
14097
- import { readFileSync as readFileSync11 } from "node:fs";
13880
+ import { readFileSync as readFileSync12 } from "node:fs";
14098
13881
  import { resolve as resolve16 } from "node:path";
14099
13882
  var chunkQueryTool;
14100
13883
  var init_chunk_query = __esm(() => {
@@ -14164,7 +13947,7 @@ var init_chunk_query = __esm(() => {
14164
13947
  return { success: false, output: `[SCOPE] ${check.reason || "Path not allowed"}` };
14165
13948
  }
14166
13949
  try {
14167
- content = readFileSync11(resolve16(ctx.baseDir, inputPath), "utf8");
13950
+ content = readFileSync12(resolve16(ctx.baseDir, inputPath), "utf8");
14168
13951
  } catch (e) {
14169
13952
  return { success: false, output: `Cannot read ${inputPath}: ${e.message}` };
14170
13953
  }
@@ -14870,8 +14653,8 @@ var init_pipeline_run = __esm(() => {
14870
14653
  init_engine();
14871
14654
  init_parser();
14872
14655
  init_agent();
14656
+ init_manager();
14873
14657
  init_manager2();
14874
- init_manager3();
14875
14658
  init_detector();
14876
14659
  init_audit_log();
14877
14660
  init_session_isolation();
@@ -15458,7 +15241,7 @@ ${JSON.stringify(result, null, 2)}`
15458
15241
  // src/tools/search-history.ts
15459
15242
  import * as fs from "fs";
15460
15243
  import { join as join17 } from "path";
15461
- import { homedir as homedir6 } from "os";
15244
+ import { homedir as homedir5 } from "os";
15462
15245
  function searchFile(filePath, query, maxResults, results) {
15463
15246
  if (!fs.existsSync(filePath))
15464
15247
  return;
@@ -15502,7 +15285,7 @@ var init_search_history = __esm(() => {
15502
15285
  const query = String(args.query || "").toLowerCase();
15503
15286
  const maxResults = Number(args.maxResults) || 5;
15504
15287
  const sessionId = args.sessionId ? String(args.sessionId) : null;
15505
- const sessionDir = join17(homedir6(), ".mma", "sessions");
15288
+ const sessionDir = join17(homedir5(), ".mma", "sessions");
15506
15289
  const results = [];
15507
15290
  try {
15508
15291
  if (!fs.existsSync(sessionDir)) {
@@ -15544,7 +15327,7 @@ var init_search_history = __esm(() => {
15544
15327
  });
15545
15328
 
15546
15329
  // src/modules/memory/search.ts
15547
- import { readFileSync as readFileSync13, existsSync as existsSync26 } from "fs";
15330
+ import { readFileSync as readFileSync14, existsSync as existsSync27 } from "fs";
15548
15331
  import { join as join18 } from "path";
15549
15332
 
15550
15333
  class MemorySearch {
@@ -15557,9 +15340,9 @@ class MemorySearch {
15557
15340
  const lowerQuery = query.toLowerCase();
15558
15341
  for (const name of MEMORY_FILES) {
15559
15342
  const path = join18(this.memoryDir, `${name}.md`);
15560
- if (!existsSync26(path))
15343
+ if (!existsSync27(path))
15561
15344
  continue;
15562
- const content = readFileSync13(path, "utf-8");
15345
+ const content = readFileSync14(path, "utf-8");
15563
15346
  const lines = content.split(`
15564
15347
  `);
15565
15348
  for (const line of lines) {
@@ -15569,9 +15352,9 @@ class MemorySearch {
15569
15352
  }
15570
15353
  }
15571
15354
  const prefsPath = join18(this.memoryDir, "preferences.json");
15572
- if (existsSync26(prefsPath)) {
15355
+ if (existsSync27(prefsPath)) {
15573
15356
  try {
15574
- const prefs = JSON.parse(readFileSync13(prefsPath, "utf-8"));
15357
+ const prefs = JSON.parse(readFileSync14(prefsPath, "utf-8"));
15575
15358
  for (const [key, value] of Object.entries(prefs)) {
15576
15359
  const searchStr = `${key}=${value}`;
15577
15360
  if (searchStr.toLowerCase().includes(lowerQuery)) {
@@ -15589,7 +15372,7 @@ var init_search = __esm(() => {
15589
15372
  });
15590
15373
 
15591
15374
  // src/modules/memory/store.ts
15592
- import { readFileSync as readFileSync14, writeFileSync as writeFileSync9, appendFileSync as appendFileSync5, existsSync as existsSync27, mkdirSync as mkdirSync13 } from "fs";
15375
+ import { readFileSync as readFileSync15, writeFileSync as writeFileSync9, appendFileSync as appendFileSync5, existsSync as existsSync28, mkdirSync as mkdirSync13 } from "fs";
15593
15376
  import { join as join19 } from "path";
15594
15377
 
15595
15378
  class MemoryStore {
@@ -15599,7 +15382,7 @@ class MemoryStore {
15599
15382
  this.ensureDir();
15600
15383
  for (const name of MEMORY_FILES2) {
15601
15384
  const path = join19(this.memoryDir, `${name}.md`);
15602
- if (!existsSync27(path)) {
15385
+ if (!existsSync28(path)) {
15603
15386
  writeFileSync9(path, `# ${name.charAt(0).toUpperCase() + name.slice(1)}
15604
15387
 
15605
15388
  `, "utf-8");
@@ -15607,15 +15390,15 @@ class MemoryStore {
15607
15390
  }
15608
15391
  }
15609
15392
  ensureDir() {
15610
- if (!existsSync27(this.memoryDir)) {
15393
+ if (!existsSync28(this.memoryDir)) {
15611
15394
  mkdirSync13(this.memoryDir, { recursive: true });
15612
15395
  }
15613
15396
  }
15614
15397
  read(name) {
15615
15398
  const path = join19(this.memoryDir, `${name}.md`);
15616
- if (!existsSync27(path))
15399
+ if (!existsSync28(path))
15617
15400
  return "";
15618
- return readFileSync14(path, "utf-8");
15401
+ return readFileSync15(path, "utf-8");
15619
15402
  }
15620
15403
  append(name, entry) {
15621
15404
  const path = join19(this.memoryDir, `${name}.md`);
@@ -15633,10 +15416,10 @@ class MemoryStore {
15633
15416
  }
15634
15417
  getPreferences() {
15635
15418
  const path = this.prefsPath();
15636
- if (!existsSync27(path))
15419
+ if (!existsSync28(path))
15637
15420
  return {};
15638
15421
  try {
15639
- return JSON.parse(readFileSync14(path, "utf-8"));
15422
+ return JSON.parse(readFileSync15(path, "utf-8"));
15640
15423
  } catch {
15641
15424
  return {};
15642
15425
  }
@@ -15668,7 +15451,7 @@ var init_store2 = __esm(() => {
15668
15451
  });
15669
15452
 
15670
15453
  // src/tools/remember.ts
15671
- import { homedir as homedir7 } from "os";
15454
+ import { homedir as homedir6 } from "os";
15672
15455
  import { join as join20 } from "path";
15673
15456
  var CATEGORIES, rememberTool;
15674
15457
  var init_remember = __esm(() => {
@@ -15708,7 +15491,7 @@ var init_remember = __esm(() => {
15708
15491
  if (!CATEGORIES.includes(category)) {
15709
15492
  return { success: false, output: t("tool.invalid_params") };
15710
15493
  }
15711
- const memoryDir = join20(homedir7(), ".mma", "memory");
15494
+ const memoryDir = join20(homedir6(), ".mma", "memory");
15712
15495
  const store = new MemoryStore(memoryDir);
15713
15496
  try {
15714
15497
  if (category === "preferences") {
@@ -15740,7 +15523,7 @@ var init_remember = __esm(() => {
15740
15523
  });
15741
15524
 
15742
15525
  // src/tools/recall.ts
15743
- import { homedir as homedir8 } from "os";
15526
+ import { homedir as homedir7 } from "os";
15744
15527
  import { join as join21 } from "path";
15745
15528
  function formatAll(store) {
15746
15529
  const parts = [];
@@ -15825,7 +15608,7 @@ var init_recall = __esm(() => {
15825
15608
  handler: async (_ctx, args) => {
15826
15609
  const query = args.query ? String(args.query) : "";
15827
15610
  const category = args.category ? String(args.category) : "";
15828
- const memoryDir = join21(homedir8(), ".mma", "memory");
15611
+ const memoryDir = join21(homedir7(), ".mma", "memory");
15829
15612
  const store = new MemoryStore(memoryDir);
15830
15613
  try {
15831
15614
  if (!query && !category) {
@@ -15863,9 +15646,9 @@ var init_recall = __esm(() => {
15863
15646
  });
15864
15647
 
15865
15648
  // src/modules/browser/bridge-path.ts
15866
- import { existsSync as existsSync28 } from "fs";
15649
+ import { existsSync as existsSync29 } from "fs";
15867
15650
  function pickExistingPath(candidates, fallback = candidates[0]) {
15868
- return candidates.find((p) => existsSync28(p)) ?? fallback;
15651
+ return candidates.find((p) => existsSync29(p)) ?? fallback;
15869
15652
  }
15870
15653
  var init_bridge_path = () => {};
15871
15654
 
@@ -16928,7 +16711,7 @@ __export(exports_image_utils, {
16928
16711
  detectMime: () => detectMime,
16929
16712
  bufferToDataUrl: () => bufferToDataUrl
16930
16713
  });
16931
- import { readFileSync as readFileSync15 } from "fs";
16714
+ import { readFileSync as readFileSync16 } from "fs";
16932
16715
  import { extname as extname3 } from "path";
16933
16716
  function detectMime(filePath) {
16934
16717
  const ext = extname3(filePath).toLowerCase();
@@ -16949,7 +16732,7 @@ async function readClipboardImage() {
16949
16732
  async function readClipboardFallback() {
16950
16733
  const { platform: platform5 } = await import("os");
16951
16734
  const { execSync } = await import("child_process");
16952
- const { readFileSync: readFileSync16, unlinkSync: unlinkSync4 } = await import("fs");
16735
+ const { readFileSync: readFileSync17, unlinkSync: unlinkSync4 } = await import("fs");
16953
16736
  const { join: join25 } = await import("path");
16954
16737
  const tmpPath = join25(process.env.TEMP || process.env.TMP || "/tmp", `mma-clip-${Date.now()}.png`);
16955
16738
  try {
@@ -16960,7 +16743,7 @@ async function readClipboardFallback() {
16960
16743
  } else {
16961
16744
  return null;
16962
16745
  }
16963
- const buf = readFileSync16(tmpPath);
16746
+ const buf = readFileSync17(tmpPath);
16964
16747
  unlinkSync4(tmpPath);
16965
16748
  return buf.length > 0 ? buf : null;
16966
16749
  } catch {
@@ -16971,7 +16754,7 @@ async function readClipboardFallback() {
16971
16754
  }
16972
16755
  }
16973
16756
  async function loadFileAsDataUrl(filePath) {
16974
- const buf = readFileSync15(filePath);
16757
+ const buf = readFileSync16(filePath);
16975
16758
  if (typeof Bun !== "undefined" && typeof Bun.Image !== "undefined") {
16976
16759
  try {
16977
16760
  const img = new Bun.Image(buf);
@@ -17031,7 +16814,7 @@ var init_image_utils = __esm(() => {
17031
16814
  });
17032
16815
 
17033
16816
  // src/tools/attach-image.ts
17034
- import { existsSync as existsSync29 } from "fs";
16817
+ import { existsSync as existsSync30 } from "fs";
17035
16818
  import { resolve as resolve17 } from "path";
17036
16819
  var attachImageTool;
17037
16820
  var init_attach_image = __esm(() => {
@@ -17075,7 +16858,7 @@ var init_attach_image = __esm(() => {
17075
16858
  dataUrl = result.dataUrl;
17076
16859
  } else {
17077
16860
  const absPath = resolve17(ctx.baseDir, source);
17078
- if (!existsSync29(absPath)) {
16861
+ if (!existsSync30(absPath)) {
17079
16862
  return {
17080
16863
  success: false,
17081
16864
  output: t("image.not_found", { path: source })
@@ -17332,12 +17115,12 @@ class ModuleRegistry {
17332
17115
  }
17333
17116
 
17334
17117
  // src/modules/plugins/loader.ts
17335
- import { readdirSync as readdirSync9, existsSync as existsSync30, statSync as statSync5 } from "fs";
17118
+ import { readdirSync as readdirSync9, existsSync as existsSync31, statSync as statSync5 } from "fs";
17336
17119
  import { join as join25, basename as basename3 } from "path";
17337
17120
 
17338
17121
  class PluginLoader {
17339
17122
  loadFromDir(dirPath, pluginManager, logger, options) {
17340
- if (!existsSync30(dirPath))
17123
+ if (!existsSync31(dirPath))
17341
17124
  return;
17342
17125
  const entries = readdirSync9(dirPath).sort();
17343
17126
  for (const entry of entries) {
@@ -17358,7 +17141,7 @@ class PluginLoader {
17358
17141
  findEntryFile(dir) {
17359
17142
  for (const name of FOLDER_ENTRY_NAMES) {
17360
17143
  const candidate = join25(dir, name);
17361
- if (existsSync30(candidate))
17144
+ if (existsSync31(candidate))
17362
17145
  return candidate;
17363
17146
  }
17364
17147
  return null;
@@ -17400,7 +17183,7 @@ var init_loader = __esm(() => {
17400
17183
 
17401
17184
  // src/modules/plugins/builtin/lint-on-write.ts
17402
17185
  import { spawn as spawn5, execSync } from "child_process";
17403
- import { existsSync as existsSync31, readFileSync as readFileSync16 } from "fs";
17186
+ import { existsSync as existsSync32, readFileSync as readFileSync17 } from "fs";
17404
17187
  import { resolve as resolve18, extname as extname4, join as join26 } from "path";
17405
17188
  import { platform as platform5 } from "os";
17406
17189
  function contentHash(content) {
@@ -17448,7 +17231,7 @@ class LintOnWritePlugin {
17448
17231
  if (!path)
17449
17232
  return;
17450
17233
  const fullPath = resolve18(ctx.baseDir, path);
17451
- if (!existsSync31(fullPath))
17234
+ if (!existsSync32(fullPath))
17452
17235
  return;
17453
17236
  const signal = ctx.signal;
17454
17237
  if (signal?.aborted)
@@ -17472,7 +17255,7 @@ class LintOnWritePlugin {
17472
17255
  if (ext === ".ts" || ext === ".tsx" || ext === ".cts" || ext === ".mts") {
17473
17256
  let content = "";
17474
17257
  try {
17475
- content = readFileSync16(filePath, "utf-8");
17258
+ content = readFileSync17(filePath, "utf-8");
17476
17259
  } catch {
17477
17260
  return null;
17478
17261
  }
@@ -17514,10 +17297,10 @@ class LintOnWritePlugin {
17514
17297
  async runProjectLint(ctx, result, signal) {
17515
17298
  try {
17516
17299
  const packageJsonPath = join26(ctx.baseDir, "package.json");
17517
- if (!existsSync31(packageJsonPath)) {
17300
+ if (!existsSync32(packageJsonPath)) {
17518
17301
  return;
17519
17302
  }
17520
- const packageJson = JSON.parse(readFileSync16(packageJsonPath, "utf-8"));
17303
+ const packageJson = JSON.parse(readFileSync17(packageJsonPath, "utf-8"));
17521
17304
  const lintScript = packageJson.scripts?.lint;
17522
17305
  if (!lintScript) {
17523
17306
  return;
@@ -17540,7 +17323,7 @@ class LintOnWritePlugin {
17540
17323
  async runProjectTypeCheck(filePath, baseDir, result, signal) {
17541
17324
  const projectRoot = findProjectRoot(filePath, baseDir, ["tsconfig.json", "package.json"]);
17542
17325
  const tsconfigPath = join26(projectRoot, "tsconfig.json");
17543
- if (!existsSync31(tsconfigPath)) {
17326
+ if (!existsSync32(tsconfigPath)) {
17544
17327
  return;
17545
17328
  }
17546
17329
  const now = Date.now();
@@ -17786,11 +17569,11 @@ class PlanTracker {
17786
17569
  var init_tracker = () => {};
17787
17570
 
17788
17571
  // src/modules/execution/plan-store.ts
17789
- import { readFileSync as readFileSync17, writeFileSync as writeFileSync10, mkdirSync as mkdirSync14, existsSync as existsSync32, readdirSync as readdirSync10, rmSync } from "fs";
17572
+ import { readFileSync as readFileSync18, writeFileSync as writeFileSync10, mkdirSync as mkdirSync14, existsSync as existsSync33, readdirSync as readdirSync10, rmSync } from "fs";
17790
17573
  import { join as join27 } from "path";
17791
17574
  function readPlanFile(path, fallbackBaseDir) {
17792
17575
  try {
17793
- const raw = readFileSync17(path, "utf-8");
17576
+ const raw = readFileSync18(path, "utf-8");
17794
17577
  if (!raw.trim())
17795
17578
  return null;
17796
17579
  const parsed = JSON.parse(raw);
@@ -17812,7 +17595,7 @@ function writePlanFile(path, plan) {
17812
17595
  writeFileSync10(path, JSON.stringify(plan, null, 2), "utf-8");
17813
17596
  }
17814
17597
  function listDir(dir, baseDir) {
17815
- if (!existsSync32(dir))
17598
+ if (!existsSync33(dir))
17816
17599
  return [];
17817
17600
  const files = readdirSync10(dir).filter((f) => f.endsWith(".json"));
17818
17601
  return files.map((f) => readPlanFile(join27(dir, f), baseDir)).filter((p) => p !== null);
@@ -17837,7 +17620,7 @@ class PlanStore {
17837
17620
  legacyPath;
17838
17621
  constructor(baseDir) {
17839
17622
  const mmaDir = join27(baseDir, ".mma");
17840
- if (!existsSync32(mmaDir))
17623
+ if (!existsSync33(mmaDir))
17841
17624
  mkdirSync14(mmaDir, { recursive: true });
17842
17625
  this.baseDir = baseDir;
17843
17626
  this.plansDir = join27(mmaDir, "plans");
@@ -17845,7 +17628,7 @@ class PlanStore {
17845
17628
  this.archiveDir = join27(this.plansDir, "archive");
17846
17629
  this.legacyPath = join27(mmaDir, LEGACY_FILE);
17847
17630
  for (const dir of [this.plansDir, this.draftsDir, this.archiveDir]) {
17848
- if (!existsSync32(dir))
17631
+ if (!existsSync33(dir))
17849
17632
  mkdirSync14(dir, { recursive: true });
17850
17633
  }
17851
17634
  }
@@ -17857,12 +17640,12 @@ class PlanStore {
17857
17640
  }
17858
17641
  loadActive() {
17859
17642
  const activePath = this.activePath();
17860
- if (existsSync32(activePath)) {
17643
+ if (existsSync33(activePath)) {
17861
17644
  const plan = readPlanFile(activePath, this.baseDir);
17862
17645
  if (plan)
17863
17646
  return plan;
17864
17647
  }
17865
- if (existsSync32(this.legacyPath)) {
17648
+ if (existsSync33(this.legacyPath)) {
17866
17649
  const legacy = readPlanFile(this.legacyPath, this.baseDir);
17867
17650
  if (legacy) {
17868
17651
  this.saveActive(legacy);
@@ -17876,7 +17659,7 @@ class PlanStore {
17876
17659
  }
17877
17660
  clearActive() {
17878
17661
  const p = this.activePath();
17879
- if (existsSync32(p))
17662
+ if (existsSync33(p))
17880
17663
  rmSync(p, { force: true });
17881
17664
  }
17882
17665
  saveDraft(plan) {
@@ -17884,11 +17667,11 @@ class PlanStore {
17884
17667
  }
17885
17668
  loadDraft(id) {
17886
17669
  const p = join27(this.draftsDir, `${id}.json`);
17887
- return existsSync32(p) ? readPlanFile(p, this.baseDir) : null;
17670
+ return existsSync33(p) ? readPlanFile(p, this.baseDir) : null;
17888
17671
  }
17889
17672
  removeDraft(id) {
17890
17673
  const p = join27(this.draftsDir, `${id}.json`);
17891
- if (existsSync32(p))
17674
+ if (existsSync33(p))
17892
17675
  rmSync(p, { force: true });
17893
17676
  }
17894
17677
  listDrafts() {
@@ -17907,7 +17690,7 @@ class PlanStore {
17907
17690
  }
17908
17691
  removeArchived(id) {
17909
17692
  const p = join27(this.archiveDir, `${id}.json`);
17910
- if (existsSync32(p))
17693
+ if (existsSync33(p))
17911
17694
  rmSync(p, { force: true });
17912
17695
  }
17913
17696
  listAll() {
@@ -17940,12 +17723,12 @@ class PlanStore {
17940
17723
  return "active";
17941
17724
  }
17942
17725
  const draftPath = join27(this.draftsDir, `${id}.json`);
17943
- if (existsSync32(draftPath)) {
17726
+ if (existsSync33(draftPath)) {
17944
17727
  rmSync(draftPath, { force: true });
17945
17728
  return "draft";
17946
17729
  }
17947
17730
  const archivedPath = join27(this.archiveDir, `${id}.json`);
17948
- if (existsSync32(archivedPath)) {
17731
+ if (existsSync33(archivedPath)) {
17949
17732
  rmSync(archivedPath, { force: true });
17950
17733
  return "archived";
17951
17734
  }
@@ -18948,7 +18731,7 @@ var init_plan_tool = __esm(() => {
18948
18731
  });
18949
18732
 
18950
18733
  // src/modules/execution/module.ts
18951
- import { existsSync as existsSync33, readFileSync as readFileSync18 } from "fs";
18734
+ import { existsSync as existsSync34, readFileSync as readFileSync19 } from "fs";
18952
18735
  import { resolve as resolve19 } from "path";
18953
18736
 
18954
18737
  class ExecutionModule {
@@ -19277,7 +19060,7 @@ class ExecutionModule {
19277
19060
  "poetry.lock",
19278
19061
  "requirements.txt"
19279
19062
  ];
19280
- const hasLockFile = lockFiles.some((f) => existsSync33(resolve19(this.baseDir, f)));
19063
+ const hasLockFile = lockFiles.some((f) => existsSync34(resolve19(this.baseDir, f)));
19281
19064
  if (!hasLockFile) {
19282
19065
  if (contextManager) {
19283
19066
  const hints = this.state.depsGateHints.get(step.id) || 0;
@@ -19309,7 +19092,7 @@ class ExecutionModule {
19309
19092
  if (!r)
19310
19093
  continue;
19311
19094
  try {
19312
- const content = readFileSync18(r, "utf-8");
19095
+ const content = readFileSync19(r, "utf-8");
19313
19096
  if (content.trim().length < 10) {
19314
19097
  emptyFiles.push(r);
19315
19098
  }
@@ -19417,9 +19200,9 @@ var init_module = __esm(() => {
19417
19200
  });
19418
19201
 
19419
19202
  // src/modules/security/session-encryption.ts
19420
- import { readFileSync as readFileSync19, writeFileSync as writeFileSync11, existsSync as existsSync34, readdirSync as readdirSync11, unlinkSync as unlinkSync4 } from "fs";
19203
+ import { readFileSync as readFileSync20, writeFileSync as writeFileSync11, existsSync as existsSync35, readdirSync as readdirSync11, unlinkSync as unlinkSync4 } from "fs";
19421
19204
  import { join as join28 } from "path";
19422
- import { homedir as homedir9 } from "os";
19205
+ import { homedir as homedir8 } from "os";
19423
19206
 
19424
19207
  class SessionFileEncryptor {
19425
19208
  config;
@@ -19427,7 +19210,7 @@ class SessionFileEncryptor {
19427
19210
  constructor(config) {
19428
19211
  this.config = { ...DEFAULT_SESSION_ENCRYPTION, ...config };
19429
19212
  this.encryptor = new ConfigEncryptor({
19430
- keyPath: config?.keyPath || join28(homedir9(), ".mma", ".session-encryption-key")
19213
+ keyPath: config?.keyPath || join28(homedir8(), ".mma", ".session-encryption-key")
19431
19214
  });
19432
19215
  }
19433
19216
  isEnabled() {
@@ -19472,7 +19255,7 @@ class SessionFileEncryptor {
19472
19255
  return lines.map((line) => this.decryptFileContent(line));
19473
19256
  }
19474
19257
  readSessionFile(filePath) {
19475
- const content = readFileSync19(filePath, "utf8");
19258
+ const content = readFileSync20(filePath, "utf8");
19476
19259
  return this.decryptFileContent(content);
19477
19260
  }
19478
19261
  writeSessionFile(filePath, content) {
@@ -19480,7 +19263,7 @@ class SessionFileEncryptor {
19480
19263
  writeFileSync11(filePath, encrypted, "utf8");
19481
19264
  }
19482
19265
  readSessionJSON(filePath) {
19483
- const content = readFileSync19(filePath, "utf8");
19266
+ const content = readFileSync20(filePath, "utf8");
19484
19267
  return this.decryptJSON(content);
19485
19268
  }
19486
19269
  writeSessionJSON(filePath, obj) {
@@ -19488,7 +19271,7 @@ class SessionFileEncryptor {
19488
19271
  writeFileSync11(filePath, content, "utf8");
19489
19272
  }
19490
19273
  readSessionJSONL(filePath) {
19491
- const content = readFileSync19(filePath, "utf8");
19274
+ const content = readFileSync20(filePath, "utf8");
19492
19275
  const lines = content.split(`
19493
19276
  `).filter((line) => line.trim());
19494
19277
  const decryptedLines = this.decryptJSONL(lines);
@@ -19514,9 +19297,9 @@ class SessionFileEncryptor {
19514
19297
  const files = readdirSync11(sessionDir);
19515
19298
  for (const file of files) {
19516
19299
  const filePath = join28(sessionDir, file);
19517
- if (existsSync34(filePath) && !file.endsWith(".enc")) {
19300
+ if (existsSync35(filePath) && !file.endsWith(".enc")) {
19518
19301
  try {
19519
- const content = readFileSync19(filePath, "utf8");
19302
+ const content = readFileSync20(filePath, "utf8");
19520
19303
  const encrypted = this.encryptFileContent(content);
19521
19304
  writeFileSync11(filePath + ".enc", encrypted, "utf8");
19522
19305
  unlinkSync4(filePath);
@@ -19533,7 +19316,7 @@ class SessionFileEncryptor {
19533
19316
  const encFilePath = join28(sessionDir, file);
19534
19317
  const decFilePath = encFilePath.slice(0, -4);
19535
19318
  try {
19536
- const content = readFileSync19(encFilePath, "utf8");
19319
+ const content = readFileSync20(encFilePath, "utf8");
19537
19320
  const decrypted = this.decryptFileContent(content);
19538
19321
  writeFileSync11(decFilePath, decrypted, "utf8");
19539
19322
  unlinkSync4(encFilePath);
@@ -19555,10 +19338,10 @@ var init_session_encryption = __esm(() => {
19555
19338
 
19556
19339
  // src/modules/session/store.ts
19557
19340
  import {
19558
- existsSync as existsSync35,
19341
+ existsSync as existsSync36,
19559
19342
  mkdirSync as mkdirSync15,
19560
19343
  readdirSync as readdirSync12,
19561
- readFileSync as readFileSync20,
19344
+ readFileSync as readFileSync21,
19562
19345
  rmSync as rmSync2,
19563
19346
  writeFileSync as writeFileSync12,
19564
19347
  appendFileSync as appendFileSync6
@@ -19605,7 +19388,7 @@ class SessionStore {
19605
19388
  return join29(this.sessionDir(id), "session.jsonl");
19606
19389
  }
19607
19390
  sessionExists(id) {
19608
- return existsSync35(this.metaPath(id));
19391
+ return existsSync36(this.metaPath(id));
19609
19392
  }
19610
19393
  saveMeta(id, meta) {
19611
19394
  this._metaCache.set(id, meta);
@@ -19623,10 +19406,10 @@ class SessionStore {
19623
19406
  if (cached)
19624
19407
  return cached;
19625
19408
  const path = this.metaPath(id);
19626
- if (!existsSync35(path))
19409
+ if (!existsSync36(path))
19627
19410
  return null;
19628
19411
  try {
19629
- const raw = readFileSync20(path, "utf-8");
19412
+ const raw = readFileSync21(path, "utf-8");
19630
19413
  const content = this.encryptor ? this.encryptor.decryptFileContent(raw) : raw;
19631
19414
  const meta = JSON.parse(content);
19632
19415
  this._metaCache.set(id, meta);
@@ -19655,10 +19438,10 @@ class SessionStore {
19655
19438
  }
19656
19439
  loadHistory(id) {
19657
19440
  const path = this.historyPath(id);
19658
- if (!existsSync35(path))
19441
+ if (!existsSync36(path))
19659
19442
  return [];
19660
19443
  try {
19661
- const raw = readFileSync20(path, "utf-8");
19444
+ const raw = readFileSync21(path, "utf-8");
19662
19445
  const lines = raw.split(`
19663
19446
  `).filter(Boolean);
19664
19447
  const parseLine = (line) => {
@@ -19696,10 +19479,10 @@ class SessionStore {
19696
19479
  }
19697
19480
  loadSessionLog(id) {
19698
19481
  const path = this.sessionLogPath(id);
19699
- if (!existsSync35(path))
19482
+ if (!existsSync36(path))
19700
19483
  return [];
19701
19484
  try {
19702
- const raw = readFileSync20(path, "utf-8");
19485
+ const raw = readFileSync21(path, "utf-8");
19703
19486
  const lines = raw.split(`
19704
19487
  `).filter(Boolean);
19705
19488
  const parseLine = (line) => {
@@ -19724,7 +19507,7 @@ class SessionStore {
19724
19507
  }
19725
19508
  }
19726
19509
  listSessions() {
19727
- if (!existsSync35(this.baseDir))
19510
+ if (!existsSync36(this.baseDir))
19728
19511
  return [];
19729
19512
  const entries = readdirSync12(this.baseDir, { withFileTypes: true });
19730
19513
  const sessions = [];
@@ -19741,7 +19524,7 @@ class SessionStore {
19741
19524
  deleteSession(id) {
19742
19525
  this._metaCache.delete(id);
19743
19526
  const dir = this.sessionDir(id);
19744
- if (existsSync35(dir)) {
19527
+ if (existsSync36(dir)) {
19745
19528
  rmSync2(dir, { recursive: true, force: true });
19746
19529
  }
19747
19530
  }
@@ -19753,8 +19536,8 @@ class SessionStore {
19753
19536
  const updatedAt = new Date(session2.updatedAt);
19754
19537
  if (updatedAt < thirtyDaysAgo) {
19755
19538
  const historyPath = this.historyPath(session2.id);
19756
- if (existsSync35(historyPath)) {
19757
- const content = readFileSync20(historyPath, "utf-8");
19539
+ if (existsSync36(historyPath)) {
19540
+ const content = readFileSync21(historyPath, "utf-8");
19758
19541
  const compressed = gzipSync(content);
19759
19542
  const gzPath = join29(this.baseDir, `${session2.id}.jsonl.gz`);
19760
19543
  writeFileSync12(gzPath, compressed);
@@ -19909,7 +19692,7 @@ class SessionManager {
19909
19692
  }
19910
19693
  }
19911
19694
  }
19912
- var init_manager4 = __esm(() => {
19695
+ var init_manager3 = __esm(() => {
19913
19696
  init_i18n();
19914
19697
  init_session_isolation();
19915
19698
  });
@@ -19945,7 +19728,7 @@ var init_module2 = __esm(() => {
19945
19728
  // src/modules/session/index.ts
19946
19729
  var init_session2 = __esm(() => {
19947
19730
  init_store3();
19948
- init_manager4();
19731
+ init_manager3();
19949
19732
  init_module2();
19950
19733
  });
19951
19734
 
@@ -19966,9 +19749,9 @@ class ProfileCompressor {
19966
19749
  }
19967
19750
 
19968
19751
  // src/modules/user-profile/profile.ts
19969
- import { readFileSync as readFileSync21, writeFileSync as writeFileSync13, existsSync as existsSync36, mkdirSync as mkdirSync16 } from "fs";
19752
+ import { readFileSync as readFileSync22, writeFileSync as writeFileSync13, existsSync as existsSync37, mkdirSync as mkdirSync16 } from "fs";
19970
19753
  import { join as join30 } from "path";
19971
- import { homedir as homedir10, hostname, platform as platform7, type } from "os";
19754
+ import { homedir as homedir9, hostname, platform as platform7, type } from "os";
19972
19755
  import { env } from "process";
19973
19756
 
19974
19757
  class UserProfile {
@@ -19984,24 +19767,24 @@ class UserProfile {
19984
19767
  os: `${type()} ${hostname()}`,
19985
19768
  hostname: hostname(),
19986
19769
  shell: env.SHELL || env.ComSpec || "unknown",
19987
- home: homedir10(),
19770
+ home: homedir9(),
19988
19771
  nodeVersion: process.version,
19989
19772
  preferences: { ...this.preferences }
19990
19773
  };
19991
19774
  return this.info;
19992
19775
  }
19993
19776
  save() {
19994
- if (!existsSync36(this.profileDir)) {
19777
+ if (!existsSync37(this.profileDir)) {
19995
19778
  mkdirSync16(this.profileDir, { recursive: true });
19996
19779
  }
19997
19780
  writeFileSync13(join30(this.profileDir, "profile.json"), JSON.stringify({ ...this.info, preferences: this.preferences }, null, 2), "utf-8");
19998
19781
  }
19999
19782
  load() {
20000
19783
  const path = join30(this.profileDir, "profile.json");
20001
- if (!existsSync36(path))
19784
+ if (!existsSync37(path))
20002
19785
  return null;
20003
19786
  try {
20004
- const data = JSON.parse(readFileSync21(path, "utf-8"));
19787
+ const data = JSON.parse(readFileSync22(path, "utf-8"));
20005
19788
  this.info = {
20006
19789
  platform: data.platform,
20007
19790
  os: data.os,
@@ -20036,12 +19819,12 @@ class UserProfile {
20036
19819
  var init_profile = () => {};
20037
19820
 
20038
19821
  // src/modules/skills/loader.ts
20039
- import { readdirSync as readdirSync13, readFileSync as readFileSync22, existsSync as existsSync37, statSync as statSync6 } from "fs";
19822
+ import { readdirSync as readdirSync13, readFileSync as readFileSync23, existsSync as existsSync38, statSync as statSync6 } from "fs";
20040
19823
  import { join as join31 } from "path";
20041
19824
 
20042
19825
  class SkillsLoader {
20043
19826
  loadFromDir(dirPath) {
20044
- if (!existsSync37(dirPath))
19827
+ if (!existsSync38(dirPath))
20045
19828
  return [];
20046
19829
  const skills = [];
20047
19830
  this.scanDir(dirPath, skills);
@@ -20058,7 +19841,7 @@ class SkillsLoader {
20058
19841
  }
20059
19842
  if (!entry.endsWith(".md") && !entry.endsWith(".skill.md"))
20060
19843
  continue;
20061
- const content = readFileSync22(fullPath, "utf-8");
19844
+ const content = readFileSync23(fullPath, "utf-8");
20062
19845
  const parsed = this.parseSkillFile(content, fullPath);
20063
19846
  if (parsed)
20064
19847
  skills.push(parsed);
@@ -20299,6 +20082,10 @@ import { resolve as resolve20 } from "path";
20299
20082
  import { platform as platform8 } from "os";
20300
20083
 
20301
20084
  class LspClient {
20085
+ logger = null;
20086
+ setLogger(logger) {
20087
+ this.logger = logger;
20088
+ }
20302
20089
  process = null;
20303
20090
  requestId = 0;
20304
20091
  pending = new Map;
@@ -20358,11 +20145,25 @@ class LspClient {
20358
20145
  try {
20359
20146
  await this.sendRequest("initialize", initParams, timeout);
20360
20147
  } catch (e) {
20148
+ const msg = e instanceof Error ? e.message : String(e);
20149
+ this.logger?.warn(`LSP initialize failed (attempt 1): ${msg}`, {
20150
+ command: config.command,
20151
+ projectRoot
20152
+ });
20361
20153
  if (!(e instanceof Error) || !e.message.includes("initialize"))
20362
20154
  throw e;
20363
20155
  await this.shutdown();
20364
20156
  await this.startServer(config, projectRoot);
20365
- await this.sendRequest("initialize", initParams, timeout);
20157
+ try {
20158
+ await this.sendRequest("initialize", initParams, timeout);
20159
+ } catch (retryErr) {
20160
+ const retryMsg = retryErr instanceof Error ? retryErr.message : String(retryErr);
20161
+ this.logger?.error(`LSP initialize failed (attempt 2, giving up): ${retryMsg}`, {
20162
+ command: config.command,
20163
+ projectRoot
20164
+ });
20165
+ throw retryErr;
20166
+ }
20366
20167
  }
20367
20168
  this.initialized = true;
20368
20169
  }
@@ -20400,8 +20201,11 @@ class LspClient {
20400
20201
  });
20401
20202
  this.process = proc;
20402
20203
  setTimeout(() => {
20403
- if (!this.initialized && this.process)
20404
- reject(new Error("LSP server start timeout"));
20204
+ if (!this.initialized && this.process) {
20205
+ const msg = "LSP server start timeout";
20206
+ this.logger?.error(msg, { command: config.command, projectRoot, timeout: config.timeout ?? 1e4 });
20207
+ reject(new Error(msg));
20208
+ }
20405
20209
  }, config.timeout ?? 1e4);
20406
20210
  });
20407
20211
  }
@@ -20440,7 +20244,9 @@ class LspClient {
20440
20244
  try {
20441
20245
  const msg = JSON.parse(body);
20442
20246
  this.handleMessage(msg);
20443
- } catch {}
20247
+ } catch (e) {
20248
+ this.logger?.debug(`LSP JSON parse error: ${e instanceof Error ? e.message : String(e)}`);
20249
+ }
20444
20250
  }
20445
20251
  }
20446
20252
  handleMessage(msg) {
@@ -20478,7 +20284,9 @@ class LspClient {
20478
20284
  setTimeout(() => {
20479
20285
  if (this.pending.has(id)) {
20480
20286
  this.pending.delete(id);
20481
- reject(new Error(`LSP request timeout: ${method}`));
20287
+ const msg = `LSP request timeout: ${method}`;
20288
+ this.logger?.warn(msg, { method, timeout });
20289
+ reject(new Error(msg));
20482
20290
  }
20483
20291
  }, timeout);
20484
20292
  });
@@ -20488,27 +20296,39 @@ class LspClient {
20488
20296
  this.write(message);
20489
20297
  }
20490
20298
  write(message) {
20491
- if (!this.process?.stdin?.writable)
20299
+ if (!this.process?.stdin?.writable) {
20300
+ this.logger?.debug("LSP write failed: process stdin not writable");
20492
20301
  return;
20302
+ }
20493
20303
  const header = `Content-Length: ${Buffer.byteLength(message)}\r
20494
20304
  \r
20495
20305
  `;
20496
20306
  try {
20497
20307
  this.process.stdin.write(header + message);
20498
- } catch {}
20308
+ } catch (e) {
20309
+ this.logger?.debug(`LSP write error: ${e instanceof Error ? e.message : String(e)}`);
20310
+ }
20499
20311
  }
20500
20312
  async shutdown() {
20501
20313
  try {
20502
20314
  if (this.process && this.initialized && this.process.stdin?.writable) {
20503
- this.sendRequest("shutdown", null, 3000).catch(() => {});
20315
+ try {
20316
+ await this.sendRequest("shutdown", null, 3000);
20317
+ } catch (e) {
20318
+ this.logger?.debug(`LSP shutdown request failed: ${e instanceof Error ? e.message : String(e)}`);
20319
+ }
20504
20320
  this.sendNotification("exit", null);
20505
20321
  await new Promise((r) => setTimeout(r, 200));
20506
20322
  }
20507
- } catch {} finally {
20323
+ } catch (e) {
20324
+ this.logger?.debug(`LSP shutdown error: ${e instanceof Error ? e.message : String(e)}`);
20325
+ } finally {
20508
20326
  if (this.process) {
20509
20327
  try {
20510
20328
  killTree(this.process);
20511
- } catch {}
20329
+ } catch (e) {
20330
+ this.logger?.debug(`LSP killTree error: ${e instanceof Error ? e.message : String(e)}`);
20331
+ }
20512
20332
  this.process = null;
20513
20333
  }
20514
20334
  this.initialized = false;
@@ -20607,7 +20427,7 @@ var init_check_tool = __esm(() => {
20607
20427
  });
20608
20428
 
20609
20429
  // src/modules/lsp/module.ts
20610
- import { existsSync as existsSync38 } from "fs";
20430
+ import { existsSync as existsSync39 } from "fs";
20611
20431
  import { relative as relative3, resolve as resolve22 } from "path";
20612
20432
 
20613
20433
  class LspModule {
@@ -20616,9 +20436,26 @@ class LspModule {
20616
20436
  client;
20617
20437
  failuresByServer = new Map;
20618
20438
  disabledServers = new Set;
20619
- constructor(config, client) {
20439
+ logger = null;
20440
+ constructor(config, client, logger) {
20620
20441
  this.config = { ...DEFAULT_LSP_CONFIG, ...config };
20621
20442
  this.client = client ?? new LspClient;
20443
+ this.logger = logger ?? null;
20444
+ this.client.setLogger(this.logger);
20445
+ }
20446
+ setLogger(logger) {
20447
+ this.logger = logger;
20448
+ this.client.setLogger(logger);
20449
+ }
20450
+ resetDisabledServers() {
20451
+ this.failuresByServer.clear();
20452
+ this.disabledServers.clear();
20453
+ }
20454
+ getDisabledServers() {
20455
+ return Array.from(this.disabledServers);
20456
+ }
20457
+ getFailureCounts() {
20458
+ return new Map(this.failuresByServer);
20622
20459
  }
20623
20460
  isLspDisabled() {
20624
20461
  return this.disabledServers.size > 0;
@@ -20645,7 +20482,7 @@ class LspModule {
20645
20482
  if (!filePath)
20646
20483
  return;
20647
20484
  const fullPath = resolve22(_ctx.baseDir, filePath);
20648
- if (!existsSync38(fullPath))
20485
+ if (!existsSync39(fullPath))
20649
20486
  return;
20650
20487
  const serverConfig = getServerForFile(fullPath, self.config);
20651
20488
  if (!serverConfig)
@@ -20737,7 +20574,7 @@ ${items}`;
20737
20574
  })
20738
20575
  };
20739
20576
  }
20740
- if (!existsSync38(resolved)) {
20577
+ if (!existsSync39(resolved)) {
20741
20578
  return { success: false, output: t("lsp.check_notfound", { path }) };
20742
20579
  }
20743
20580
  const files = await collectCheckFiles(resolved, this.config);
@@ -20837,7 +20674,7 @@ var init_lsp = __esm(() => {
20837
20674
  });
20838
20675
 
20839
20676
  // src/modules/lsp/startup-check.ts
20840
- import { existsSync as existsSync39 } from "fs";
20677
+ import { existsSync as existsSync40 } from "fs";
20841
20678
  import { join as join32 } from "path";
20842
20679
  import { spawn as spawn7 } from "child_process";
20843
20680
  async function runStartupHealthCheck(config, baseDir, deps = {}) {
@@ -20865,7 +20702,7 @@ ${result.lines.join(`
20865
20702
  }
20866
20703
  async function runCheck(config, baseDir, deps) {
20867
20704
  const projectRoot = findProjectRoot(baseDir, baseDir, ["tsconfig.json", "package.json"]);
20868
- if (existsSync39(join32(projectRoot, "tsconfig.json"))) {
20705
+ if (existsSync40(join32(projectRoot, "tsconfig.json"))) {
20869
20706
  const runTsc = deps.runTsc ?? runTscDefault;
20870
20707
  const errors = await runTsc(projectRoot, STARTUP_CHECK_TIMEOUT_MS);
20871
20708
  if (errors.length === 0)
@@ -20873,6 +20710,8 @@ async function runCheck(config, baseDir, deps) {
20873
20710
  return { lines: errors.slice(0, STARTUP_CHECK_ERROR_CAP) };
20874
20711
  }
20875
20712
  const client = deps.client ?? new LspClient;
20713
+ if (!deps.client)
20714
+ client.setLogger(deps.logger ?? null);
20876
20715
  const files = await collectCheckFiles(baseDir, config);
20877
20716
  const lines = [];
20878
20717
  let checked = 0;
@@ -20889,7 +20728,9 @@ async function runCheck(config, baseDir, deps) {
20889
20728
  lines.push(formatStartupError(file, baseDir, d));
20890
20729
  }
20891
20730
  }
20892
- } catch {}
20731
+ } catch (e) {
20732
+ deps.logger?.debug(`Startup LSP check failed for ${file}: ${e instanceof Error ? e.message : String(e)}`);
20733
+ }
20893
20734
  }
20894
20735
  if (checked === 0 || lines.length === 0)
20895
20736
  return null;
@@ -20961,7 +20802,7 @@ var init_startup_check = __esm(() => {
20961
20802
  });
20962
20803
 
20963
20804
  // src/modules/indexer/walker.ts
20964
- import { readdirSync as readdirSync14, readFileSync as readFileSync23, statSync as statSync7, existsSync as existsSync40, watch } from "fs";
20805
+ import { readdirSync as readdirSync14, readFileSync as readFileSync24, statSync as statSync7, existsSync as existsSync41, watch } from "fs";
20965
20806
  import { join as join33, relative as relative4, extname as extname5 } from "path";
20966
20807
 
20967
20808
  class Indexer {
@@ -20989,7 +20830,7 @@ class Indexer {
20989
20830
  let totalSize = 0;
20990
20831
  let count = 0;
20991
20832
  const walkDir2 = (dir) => {
20992
- if (!existsSync40(dir))
20833
+ if (!existsSync41(dir))
20993
20834
  return;
20994
20835
  let entries;
20995
20836
  try {
@@ -21011,7 +20852,7 @@ class Indexer {
21011
20852
  const ext = extname5(entry).toLowerCase();
21012
20853
  const language = LANGUAGES[ext];
21013
20854
  if (language) {
21014
- const content = readFileSync23(fullPath, "utf-8");
20855
+ const content = readFileSync24(fullPath, "utf-8");
21015
20856
  const exports = this.extractExports(content, language);
21016
20857
  files.push({ path: relPath, language, exports, size: stat2.size });
21017
20858
  totalSize += stat2.size;
@@ -21063,7 +20904,7 @@ var init_walker = __esm(() => {
21063
20904
  });
21064
20905
 
21065
20906
  // src/modules/indexer/cache.ts
21066
- import { readFileSync as readFileSync24, writeFileSync as writeFileSync14, existsSync as existsSync41, mkdirSync as mkdirSync17, rmSync as rmSync3 } from "fs";
20907
+ import { readFileSync as readFileSync25, writeFileSync as writeFileSync14, existsSync as existsSync42, mkdirSync as mkdirSync17, rmSync as rmSync3 } from "fs";
21067
20908
  import { join as join34 } from "path";
21068
20909
 
21069
20910
  class IndexCache {
@@ -21075,10 +20916,10 @@ class IndexCache {
21075
20916
  load() {
21076
20917
  if (this.cache)
21077
20918
  return this.cache;
21078
- if (!existsSync41(this.cachePath))
20919
+ if (!existsSync42(this.cachePath))
21079
20920
  return null;
21080
20921
  try {
21081
- this.cache = JSON.parse(readFileSync24(this.cachePath, "utf-8"));
20922
+ this.cache = JSON.parse(readFileSync25(this.cachePath, "utf-8"));
21082
20923
  return this.cache;
21083
20924
  } catch {
21084
20925
  return null;
@@ -21087,13 +20928,13 @@ class IndexCache {
21087
20928
  save(result) {
21088
20929
  this.cache = result;
21089
20930
  const dir = join34(this.cachePath, "..");
21090
- if (!existsSync41(dir))
20931
+ if (!existsSync42(dir))
21091
20932
  mkdirSync17(dir, { recursive: true });
21092
20933
  writeFileSync14(this.cachePath, JSON.stringify(result), "utf-8");
21093
20934
  }
21094
20935
  invalidate() {
21095
20936
  this.cache = null;
21096
- if (existsSync41(this.cachePath)) {
20937
+ if (existsSync42(this.cachePath)) {
21097
20938
  try {
21098
20939
  rmSync3(this.cachePath);
21099
20940
  } catch {}
@@ -21103,11 +20944,11 @@ class IndexCache {
21103
20944
  var init_cache = () => {};
21104
20945
 
21105
20946
  // src/modules/indexer/project-profile.ts
21106
- import { readFileSync as readFileSync25, existsSync as existsSync42 } from "fs";
20947
+ import { readFileSync as readFileSync26, existsSync as existsSync43 } from "fs";
21107
20948
  import { join as join35 } from "path";
21108
20949
  function detectManifest(baseDir) {
21109
20950
  for (const manifest of MANIFEST_ORDER) {
21110
- if (existsSync42(join35(baseDir, manifest)))
20951
+ if (existsSync43(join35(baseDir, manifest)))
21111
20952
  return manifest;
21112
20953
  }
21113
20954
  return null;
@@ -21124,7 +20965,7 @@ function cleanDependency(entry) {
21124
20965
  }
21125
20966
  function readPackageJson(baseDir) {
21126
20967
  try {
21127
- const raw = JSON.parse(readFileSync25(join35(baseDir, "package.json"), "utf-8"));
20968
+ const raw = JSON.parse(readFileSync26(join35(baseDir, "package.json"), "utf-8"));
21128
20969
  if (!raw || typeof raw !== "object")
21129
20970
  return null;
21130
20971
  const profile = {
@@ -21148,7 +20989,7 @@ function readPackageJson(baseDir) {
21148
20989
  }
21149
20990
  function readPyproject(baseDir) {
21150
20991
  try {
21151
- const content = readFileSync25(join35(baseDir, "pyproject.toml"), "utf-8");
20992
+ const content = readFileSync26(join35(baseDir, "pyproject.toml"), "utf-8");
21152
20993
  const profile = { runtime: "python", deps: [], devDeps: [], scripts: {} };
21153
20994
  const nameMatch = content.match(/^\s*name\s*=\s*"([^"]+)"/m);
21154
20995
  if (nameMatch)
@@ -21164,7 +21005,7 @@ function readPyproject(baseDir) {
21164
21005
  }
21165
21006
  function readCargo(baseDir) {
21166
21007
  try {
21167
- const content = readFileSync25(join35(baseDir, "Cargo.toml"), "utf-8");
21008
+ const content = readFileSync26(join35(baseDir, "Cargo.toml"), "utf-8");
21168
21009
  const profile = { runtime: "rust", deps: [], devDeps: [], scripts: {} };
21169
21010
  const nameMatch = content.match(/^\s*name\s*=\s*"([^"]+)"/m);
21170
21011
  if (nameMatch)
@@ -21188,7 +21029,7 @@ function readCargo(baseDir) {
21188
21029
  }
21189
21030
  function readGoMod(baseDir) {
21190
21031
  try {
21191
- const content = readFileSync25(join35(baseDir, "go.mod"), "utf-8");
21032
+ const content = readFileSync26(join35(baseDir, "go.mod"), "utf-8");
21192
21033
  const profile = { runtime: "go", deps: [], devDeps: [], scripts: {} };
21193
21034
  const moduleMatch = content.match(/^module\s+(\S+)/m);
21194
21035
  if (moduleMatch)
@@ -21206,7 +21047,7 @@ function readGoMod(baseDir) {
21206
21047
  }
21207
21048
  function readRequirements(baseDir) {
21208
21049
  try {
21209
- const content = readFileSync25(join35(baseDir, "requirements.txt"), "utf-8");
21050
+ const content = readFileSync26(join35(baseDir, "requirements.txt"), "utf-8");
21210
21051
  const profile = { runtime: "python", deps: [], devDeps: [], scripts: {} };
21211
21052
  for (const line of content.split(`
21212
21053
  `)) {
@@ -21664,7 +21505,7 @@ var init_mcp = __esm(() => {
21664
21505
  });
21665
21506
 
21666
21507
  // src/modules/memory/module.ts
21667
- import { homedir as homedir11 } from "os";
21508
+ import { homedir as homedir10 } from "os";
21668
21509
  import { join as join36 } from "path";
21669
21510
 
21670
21511
  class MemoryModule {
@@ -21674,7 +21515,7 @@ class MemoryModule {
21674
21515
  if (storeOrDir instanceof MemoryStore) {
21675
21516
  this.store = storeOrDir;
21676
21517
  } else {
21677
- const dir = storeOrDir || join36(homedir11(), ".mma", "memory");
21518
+ const dir = storeOrDir || join36(homedir10(), ".mma", "memory");
21678
21519
  this.store = new MemoryStore(dir);
21679
21520
  }
21680
21521
  }
@@ -21760,16 +21601,16 @@ var init_module8 = __esm(() => {
21760
21601
  });
21761
21602
 
21762
21603
  // src/core/version.ts
21763
- import { existsSync as existsSync43, readFileSync as readFileSync26 } from "fs";
21604
+ import { existsSync as existsSync44, readFileSync as readFileSync27 } from "fs";
21764
21605
  import { join as join37, dirname as dirname13 } from "path";
21765
21606
  import { fileURLToPath as fileURLToPath2 } from "url";
21766
21607
  function readMmaVersion() {
21767
21608
  const here = dirname13(fileURLToPath2(import.meta.url));
21768
21609
  const candidates = [join37(here, "..", "..", "package.json"), join37(here, "..", "package.json")];
21769
21610
  for (const p of candidates) {
21770
- if (existsSync43(p)) {
21611
+ if (existsSync44(p)) {
21771
21612
  try {
21772
- const raw = JSON.parse(readFileSync26(p, "utf8"));
21613
+ const raw = JSON.parse(readFileSync27(p, "utf8"));
21773
21614
  if (raw.version)
21774
21615
  return raw.version;
21775
21616
  } catch {}
@@ -21779,6 +21620,188 @@ function readMmaVersion() {
21779
21620
  }
21780
21621
  var init_version = () => {};
21781
21622
 
21623
+ // src/core/environment.ts
21624
+ import { existsSync as existsSync45, readFileSync as readFileSync28, readdirSync as readdirSync15 } from "fs";
21625
+ import { spawnSync as spawnSync2 } from "child_process";
21626
+ import { createRequire as createRequire2 } from "module";
21627
+ import { join as join38, dirname as dirname14 } from "path";
21628
+ import { fileURLToPath as fileURLToPath3 } from "url";
21629
+ import { arch, homedir as homedir11, hostname as hostname2, platform as platform9, release } from "os";
21630
+ import { env as env2 } from "process";
21631
+ function readEngineRequirement() {
21632
+ const here = dirname14(fileURLToPath3(import.meta.url));
21633
+ const candidates = [join38(here, "..", "..", "package.json"), join38(here, "..", "package.json")];
21634
+ for (const p of candidates) {
21635
+ if (!existsSync45(p))
21636
+ continue;
21637
+ try {
21638
+ const raw = JSON.parse(readFileSync28(p, "utf8"));
21639
+ if (raw.engines?.node)
21640
+ return String(raw.engines.node);
21641
+ } catch {}
21642
+ }
21643
+ return ">=20";
21644
+ }
21645
+ function satisfiesMinimum(version, requirement) {
21646
+ const minMatch = requirement.match(/(\d+)(?:\.(\d+))?(?:\.(\d+))?/);
21647
+ if (!minMatch)
21648
+ return true;
21649
+ const min = [
21650
+ parseInt(minMatch[1], 10),
21651
+ minMatch[2] ? parseInt(minMatch[2], 10) : 0,
21652
+ minMatch[3] ? parseInt(minMatch[3], 10) : 0
21653
+ ];
21654
+ const parts = version.replace(/^v/i, "").split(".");
21655
+ const got = [
21656
+ parts[0] ? parseInt(parts[0], 10) : 0,
21657
+ parts[1] ? parseInt(parts[1], 10) : 0,
21658
+ parts[2] ? parseInt(parts[2], 10) : 0
21659
+ ];
21660
+ for (let i = 0;i < 3; i++) {
21661
+ if (got[i] > min[i])
21662
+ return true;
21663
+ if (got[i] < min[i])
21664
+ return false;
21665
+ }
21666
+ return true;
21667
+ }
21668
+ function detectRuntime() {
21669
+ const bun = globalThis.Bun;
21670
+ const isBun = typeof bun !== "undefined" && typeof bun?.version !== "undefined";
21671
+ const engine2 = readEngineRequirement();
21672
+ const runtime = isBun ? "bun" : "node";
21673
+ const runtimeVersion = isBun ? String(bun.version) : process.version;
21674
+ return {
21675
+ runtime,
21676
+ runtimeVersion,
21677
+ nodeVersion: process.version,
21678
+ engine: engine2,
21679
+ engineOk: satisfiesMinimum(process.version, engine2)
21680
+ };
21681
+ }
21682
+ function toolVersion(cmd) {
21683
+ try {
21684
+ const res = spawnSync2(cmd, ["--version"], {
21685
+ encoding: "utf8",
21686
+ timeout: 3000,
21687
+ windowsHide: true,
21688
+ stdio: ["ignore", "pipe", "pipe"]
21689
+ });
21690
+ if (res.error || res.status !== 0)
21691
+ return "missing";
21692
+ const out = ((res.stdout || "") + (res.stderr || "")).trim();
21693
+ return out.split(/\r?\n/)[0].slice(0, 40) || "ok";
21694
+ } catch {
21695
+ return "missing";
21696
+ }
21697
+ }
21698
+ function playwrightBrowsersDir() {
21699
+ if (process.env.PLAYWRIGHT_BROWSERS_PATH)
21700
+ return process.env.PLAYWRIGHT_BROWSERS_PATH;
21701
+ return process.platform === "win32" ? join38(homedir11(), "AppData", "Local", "ms-playwright") : join38(homedir11(), ".cache", "ms-playwright");
21702
+ }
21703
+ function playwrightInfo() {
21704
+ let installed = false;
21705
+ let version = "";
21706
+ const browsersDir = playwrightBrowsersDir();
21707
+ try {
21708
+ const require2 = createRequire2(import.meta.url);
21709
+ const pkgPath = require2.resolve("playwright/package.json");
21710
+ installed = existsSync45(pkgPath);
21711
+ version = JSON.parse(readFileSync28(pkgPath, "utf8")).version || "";
21712
+ } catch {
21713
+ installed = false;
21714
+ }
21715
+ let browsersInstalled = false;
21716
+ try {
21717
+ if (existsSync45(browsersDir)) {
21718
+ browsersInstalled = readdirSync15(browsersDir).some((d) => /chrom/i.test(d));
21719
+ }
21720
+ } catch {
21721
+ browsersInstalled = false;
21722
+ }
21723
+ return { installed, version, browsersDir, browsersInstalled };
21724
+ }
21725
+ function checkEnvironmentRequirements(report) {
21726
+ const warnings = [];
21727
+ if (report.runtime.runtime === "node") {
21728
+ warnings.push(t("env.runtime_node", { version: report.runtime.nodeVersion }));
21729
+ }
21730
+ if (!report.runtime.engineOk) {
21731
+ warnings.push(t("env.runtime_old", {
21732
+ version: report.runtime.nodeVersion,
21733
+ engine: report.runtime.engine
21734
+ }));
21735
+ }
21736
+ if (report.tools.bun === "missing") {
21737
+ warnings.push(t("env.tool_missing", { tool: "bun" }));
21738
+ }
21739
+ if (report.tools.git === "missing") {
21740
+ warnings.push(t("env.tool_missing", { tool: "git" }));
21741
+ }
21742
+ if (report.features.browser && report.playwright) {
21743
+ if (!report.playwright.installed) {
21744
+ warnings.push(t("env.playwright_missing"));
21745
+ } else if (!report.playwright.browsersInstalled) {
21746
+ warnings.push(t("env.playwright_browsers_missing", { dir: report.playwright.browsersDir }));
21747
+ }
21748
+ }
21749
+ return warnings;
21750
+ }
21751
+ function collectEnvironment(opts) {
21752
+ const runtime = detectRuntime();
21753
+ const tools = {};
21754
+ if (opts.scanTools) {
21755
+ for (const tool of TOOL_CHECKS)
21756
+ tools[tool] = toolVersion(tool);
21757
+ }
21758
+ const provider = opts.config ? {
21759
+ model: opts.config.model,
21760
+ baseUrl: sanitizeUrl(opts.config.provider?.baseUrl || ""),
21761
+ contextWindow: opts.config.contextWindow,
21762
+ retry: {
21763
+ maxRetries: opts.config.retry?.maxRetries ?? 0,
21764
+ baseDelay: opts.config.retry?.baseDelay ?? 0,
21765
+ maxDelay: opts.config.retry?.maxDelay ?? 0,
21766
+ maxStreamRetries: opts.config.retry?.maxStreamRetries ?? 0,
21767
+ noDataTimeoutMs: opts.config.retry?.noDataTimeoutMs ?? 0
21768
+ }
21769
+ } : null;
21770
+ const report = {
21771
+ ts: new Date().toISOString(),
21772
+ mmaVersion: readMmaVersion(),
21773
+ runtime,
21774
+ os: {
21775
+ platform: platform9(),
21776
+ arch: arch(),
21777
+ release: release(),
21778
+ hostname: hostname2(),
21779
+ shell: env2.SHELL || env2.ComSpec || "unknown",
21780
+ home: homedir11(),
21781
+ cwd: process.cwd()
21782
+ },
21783
+ paths: { configDir: opts.configDir, baseDir: opts.baseDir || process.cwd() },
21784
+ tools,
21785
+ provider,
21786
+ features: { browser: Boolean(opts.config?.browser?.enabled) },
21787
+ playwright: playwrightInfo(),
21788
+ warnings: []
21789
+ };
21790
+ report.warnings = checkEnvironmentRequirements(report);
21791
+ return report;
21792
+ }
21793
+ function logEnvironment(report, logger) {
21794
+ logger.info(`Environment: ${report.os.platform} ${report.os.arch} | ${report.runtime.runtime} ${report.runtime.runtimeVersion} (node ${report.runtime.nodeVersion}) | mma ${report.mmaVersion} | ${report.provider?.model ?? "no provider"}`);
21795
+ logger.logStructured("environment", report);
21796
+ }
21797
+ var TOOL_CHECKS;
21798
+ var init_environment = __esm(() => {
21799
+ init_version();
21800
+ init_network_validator();
21801
+ init_i18n();
21802
+ TOOL_CHECKS = ["bun", "node", "git", "python"];
21803
+ });
21804
+
21782
21805
  // src/core/bootstrap.ts
21783
21806
  var exports_bootstrap = {};
21784
21807
  __export(exports_bootstrap, {
@@ -21786,8 +21809,8 @@ __export(exports_bootstrap, {
21786
21809
  bootstrap: () => bootstrap
21787
21810
  });
21788
21811
  import { homedir as homedir12 } from "os";
21789
- import { join as join38, resolve as resolve23 } from "path";
21790
- import { existsSync as existsSync44, readFileSync as readFileSync27, writeFileSync as writeFileSync15 } from "fs";
21812
+ import { join as join39, resolve as resolve23 } from "path";
21813
+ import { existsSync as existsSync46, readFileSync as readFileSync29, writeFileSync as writeFileSync15 } from "fs";
21791
21814
  function buildSystemInfo(config, baseDir, profileCompressed) {
21792
21815
  const now = new Date().toISOString().replace("T", " ").slice(0, 19);
21793
21816
  const isWin = profileCompressed.toLowerCase().includes("win32");
@@ -21813,8 +21836,8 @@ function buildSystemInfo(config, baseDir, profileCompressed) {
21813
21836
  `);
21814
21837
  }
21815
21838
  async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
21816
- const dir = configDir || join38(homedir12(), ".mma");
21817
- const projectConfigPath = projectDir ? join38(projectDir, ".mmrc") : join38(process.cwd(), ".mmrc");
21839
+ const dir = configDir || join39(homedir12(), ".mma");
21840
+ const projectConfigPath = projectDir ? join39(projectDir, ".mmrc") : join39(process.cwd(), ".mmrc");
21818
21841
  const config = loadConfig({ configDir: dir, projectConfigPath });
21819
21842
  setLocale(config.locale);
21820
21843
  try {
@@ -21824,7 +21847,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
21824
21847
  }
21825
21848
  } catch {}
21826
21849
  const logger = new Logger(config.logLevel);
21827
- logger.setLogDir(join38(dir, "logs"));
21850
+ logger.setLogDir(join39(dir, "logs"));
21828
21851
  logger.debug("MMA bootstrap", {
21829
21852
  version: config.version,
21830
21853
  model: config.model
@@ -21846,18 +21869,29 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
21846
21869
  logger.info(`Model ${config.model} loaded in ${loadResult.loadTime}s`);
21847
21870
  }
21848
21871
  }
21849
- const profile = new UserProfile(join38(dir));
21872
+ const profile = new UserProfile(join39(dir));
21850
21873
  profile.load() || profile.collect();
21851
21874
  profile.save();
21852
- const providerManager = new ProviderManager(config.provider, {
21875
+ const llmProvider = new OpenAICompatProvider({
21876
+ model: config.model,
21877
+ baseUrl: config.provider.baseUrl,
21878
+ apiKey: config.provider.apiKey,
21853
21879
  contextWindow: config.contextWindow,
21854
21880
  retry: config.retry,
21855
21881
  rateLimits: config.security?.rateLimits
21856
21882
  });
21857
- providerManager.setModel(config.model);
21858
- const llmProvider = providerManager.active;
21859
21883
  const baseDir = projectDir ? resolve23(projectDir) : process.cwd();
21860
- const projectMapCacheDir = join38(baseDir, ".mma");
21884
+ const envReport = collectEnvironment({
21885
+ configDir: dir,
21886
+ baseDir,
21887
+ config,
21888
+ scanTools: true
21889
+ });
21890
+ logEnvironment(envReport, logger);
21891
+ for (const warning of envReport.warnings) {
21892
+ logger.warn(warning);
21893
+ }
21894
+ const projectMapCacheDir = join39(baseDir, ".mma");
21861
21895
  const indexerModule = new IndexerModule({
21862
21896
  baseDir,
21863
21897
  cacheDir: projectMapCacheDir
@@ -21868,9 +21902,9 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
21868
21902
  logger.warn(`Project indexing failed: ${err.message}`);
21869
21903
  }
21870
21904
  const skillsLoader = new SkillsLoader;
21871
- const builtinDir = join38(import.meta.dirname, "skills", "builtin");
21872
- const globalDir = join38(homedir12(), ".agents", "skills");
21873
- const projectSkillsDir = join38(baseDir, ".mma", "skills");
21905
+ const builtinDir = join39(import.meta.dirname, "skills", "builtin");
21906
+ const globalDir = join39(homedir12(), ".agents", "skills");
21907
+ const projectSkillsDir = join39(baseDir, ".mma", "skills");
21874
21908
  const availableSkills = skillsLoader.loadFromAllSources(builtinDir, globalDir, projectSkillsDir);
21875
21909
  const skillsBudget = Math.floor(config.contextWindow * config.skills.budget);
21876
21910
  const skillsModule = new SkillsModule(availableSkills, skillsBudget);
@@ -21886,11 +21920,11 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
21886
21920
  essential: true,
21887
21921
  estimatedTokens: Math.ceil(systemInfoContent.length / 4)
21888
21922
  };
21889
- const agentsMdGlobal = join38(dir, "AGENTS.md");
21890
- if (!existsSync44(agentsMdGlobal)) {
21923
+ const agentsMdGlobal = join39(dir, "AGENTS.md");
21924
+ if (!existsSync46(agentsMdGlobal)) {
21891
21925
  writeFileSync15(agentsMdGlobal, "", "utf-8");
21892
21926
  }
21893
- const sessionDir = join38(dir, "sessions");
21927
+ const sessionDir = join39(dir, "sessions");
21894
21928
  const sessionStore = new SessionStore(sessionDir);
21895
21929
  sessionStore.init();
21896
21930
  const sessionManager = new SessionManager(sessionStore, {
@@ -21967,7 +22001,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
21967
22001
  const mcpModule = new MCPModule(config);
21968
22002
  await mcpModule.initialize();
21969
22003
  moduleRegistry.register(mcpModule);
21970
- const memoryStore = new MemoryStore(join38(dir, "memory"));
22004
+ const memoryStore = new MemoryStore(join39(dir, "memory"));
21971
22005
  const memoryModule = new MemoryModule(memoryStore);
21972
22006
  moduleRegistry.register(memoryModule);
21973
22007
  if (config.browser.enabled) {
@@ -21979,7 +22013,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
21979
22013
  pluginManager.register(browserPlugin);
21980
22014
  }
21981
22015
  }
21982
- const lspModule = new LspModule(config.lsp);
22016
+ const lspModule = new LspModule(config.lsp, undefined, logger);
21983
22017
  moduleRegistry.register(lspModule);
21984
22018
  const lspPlugin = lspModule.getPlugin();
21985
22019
  if (lspPlugin) {
@@ -21987,7 +22021,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
21987
22021
  pluginManager.register(lspPlugin);
21988
22022
  }
21989
22023
  let startupCheckBlock = null;
21990
- const startupCheckPromise = !exitOnComplete ? runStartupHealthCheck(config.lsp ?? DEFAULT_LSP_CONFIG, baseDir) : Promise.resolve(null);
22024
+ const startupCheckPromise = !exitOnComplete ? runStartupHealthCheck(config.lsp ?? DEFAULT_LSP_CONFIG, baseDir, { logger }) : Promise.resolve(null);
21991
22025
  const moduleTools = moduleRegistry.collectToolDefinitions();
21992
22026
  for (const tool of moduleTools) {
21993
22027
  toolRegistry.register(tool);
@@ -22020,8 +22054,8 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
22020
22054
  pluginManager.register(plugin);
22021
22055
  pluginManager.register(plugin2);
22022
22056
  const pluginLoader = new PluginLoader;
22023
- const globalPluginsDir = join38(homedir12(), ".mma", "plugins");
22024
- const projectPluginsDir = join38(baseDir, ".mma", "plugins");
22057
+ const globalPluginsDir = join39(homedir12(), ".mma", "plugins");
22058
+ const projectPluginsDir = join39(baseDir, ".mma", "plugins");
22025
22059
  const mmaVersion = readMmaVersion();
22026
22060
  pluginLoader.loadFromDir(globalPluginsDir, pluginManager, logger, {
22027
22061
  source: "global",
@@ -22047,13 +22081,13 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
22047
22081
  const skipAgentsMd = noAgentsMd === true;
22048
22082
  if (!skipAgentsMd) {
22049
22083
  const agentsMdCandidates = [
22050
- join38(baseDir, "AGENTS.md"),
22051
- join38(baseDir, ".mma", "AGENTS.md"),
22052
- join38(dir, "AGENTS.md")
22084
+ join39(baseDir, "AGENTS.md"),
22085
+ join39(baseDir, ".mma", "AGENTS.md"),
22086
+ join39(dir, "AGENTS.md")
22053
22087
  ];
22054
22088
  for (const p of agentsMdCandidates) {
22055
- if (existsSync44(p)) {
22056
- const content = readFileSync27(p, "utf-8").trim();
22089
+ if (existsSync46(p)) {
22090
+ const content = readFileSync29(p, "utf-8").trim();
22057
22091
  if (content) {
22058
22092
  agentsMdBlocks.push({
22059
22093
  content,
@@ -22073,7 +22107,6 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
22073
22107
  const agentDeps = {
22074
22108
  config,
22075
22109
  llmProvider,
22076
- providerManager,
22077
22110
  toolExecutor,
22078
22111
  pluginManager,
22079
22112
  contextManager,
@@ -22082,6 +22115,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
22082
22115
  baseDir,
22083
22116
  toolTags: activeToolTags,
22084
22117
  promptBlocks,
22118
+ envReport,
22085
22119
  getDynamicPromptBlocks: () => {
22086
22120
  const blocks = [];
22087
22121
  const planBlock = execModule.getSystemPromptBlock();
@@ -22126,21 +22160,22 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
22126
22160
  toolCtx,
22127
22161
  configDir: dir,
22128
22162
  baseDir,
22129
- noAgentsMd: skipAgentsMd
22163
+ noAgentsMd: skipAgentsMd,
22164
+ envReport
22130
22165
  };
22131
22166
  }
22132
22167
  var init_bootstrap = __esm(() => {
22133
22168
  init_config2();
22134
22169
  init_app_logger();
22135
- init_providers();
22170
+ init_openai_compat();
22136
22171
  init_tools();
22137
22172
  init_hidden_tools_block();
22138
22173
  init_executor();
22139
- init_manager3();
22174
+ init_manager2();
22140
22175
  init_loader();
22141
22176
  init_lint_on_write();
22142
22177
  init_notify();
22143
- init_manager2();
22178
+ init_manager();
22144
22179
  init_token_counter();
22145
22180
  init_detector();
22146
22181
  init_module();
@@ -22157,6 +22192,7 @@ var init_bootstrap = __esm(() => {
22157
22192
  init_i18n();
22158
22193
  init_agent();
22159
22194
  init_version();
22195
+ init_environment();
22160
22196
  });
22161
22197
 
22162
22198
  // node_modules/ansi-regex/index.js
@@ -22883,24 +22919,35 @@ async function runSetup(externalRl) {
22883
22919
  console.log(l);
22884
22920
  return answers;
22885
22921
  }
22886
- var PROVIDER_TYPES, KNOWN_PORTS;
22922
+ var PROVIDER_TYPES, KNOWN_PORTS, HOSTED_BASE_URLS;
22887
22923
  var init_setup = __esm(() => {
22888
22924
  init_colors();
22889
22925
  init_i18n();
22890
22926
  init_spinner();
22891
- init_presets();
22892
22927
  init_box();
22893
22928
  init_table();
22894
- PROVIDER_TYPES = BUILTIN_PROVIDERS.map((spec) => ({
22895
- value: spec.type,
22896
- label: spec.label
22897
- }));
22929
+ PROVIDER_TYPES = [
22930
+ {
22931
+ value: "openai-compat",
22932
+ label: "OpenAI-compatible (LM Studio, Ollama, vLLM, etc.)"
22933
+ },
22934
+ { value: "openai", label: "OpenAI API" },
22935
+ { value: "anthropic", label: "Anthropic Claude" },
22936
+ { value: "opencode-zen", label: "OpenCode Zen (opencode.ai/zen)" },
22937
+ { value: "opencode-go", label: "OpenCode Go (opencode.ai/go)" }
22938
+ ];
22898
22939
  KNOWN_PORTS = [
22899
22940
  { port: 1234, label: "LM Studio" },
22900
22941
  { port: 11434, label: "Ollama" },
22901
22942
  { port: 8080, label: "vLLM / custom" },
22902
22943
  { port: 4891, label: "GPT4All" }
22903
22944
  ];
22945
+ HOSTED_BASE_URLS = {
22946
+ openai: "https://api.openai.com/v1",
22947
+ anthropic: "https://api.anthropic.com",
22948
+ "opencode-zen": "https://opencode.ai/zen/v1",
22949
+ "opencode-go": "https://opencode.ai/zen/go/v1"
22950
+ };
22904
22951
  });
22905
22952
 
22906
22953
  // src/modules/certification/manifest.ts
@@ -22914,20 +22961,20 @@ __export(exports_manifest, {
22914
22961
  getCertMark: () => getCertMark,
22915
22962
  MANIFEST_PATH: () => MANIFEST_PATH
22916
22963
  });
22917
- import { existsSync as existsSync45, readFileSync as readFileSync28, mkdirSync as mkdirSync18, writeFileSync as writeFileSync16 } from "fs";
22964
+ import { existsSync as existsSync47, readFileSync as readFileSync30, mkdirSync as mkdirSync18, writeFileSync as writeFileSync16 } from "fs";
22918
22965
  import { homedir as homedir14 } from "os";
22919
- import { join as join40 } from "path";
22966
+ import { join as join41 } from "path";
22920
22967
  function readManifest(path = MANIFEST_PATH) {
22921
22968
  try {
22922
- if (existsSync45(path)) {
22923
- const raw = JSON.parse(readFileSync28(path, "utf-8"));
22969
+ if (existsSync47(path)) {
22970
+ const raw = JSON.parse(readFileSync30(path, "utf-8"));
22924
22971
  return { version: 1, certifications: raw.certifications ?? [] };
22925
22972
  }
22926
22973
  } catch {}
22927
22974
  return { version: 1, certifications: [] };
22928
22975
  }
22929
22976
  function saveManifest(m, path = MANIFEST_PATH) {
22930
- mkdirSync18(join40(homedir14(), ".mma"), { recursive: true });
22977
+ mkdirSync18(join41(homedir14(), ".mma"), { recursive: true });
22931
22978
  writeFileSync16(path, JSON.stringify(m, null, 2), "utf-8");
22932
22979
  }
22933
22980
  function upsertCertification(entry, path = MANIFEST_PATH) {
@@ -22962,7 +23009,7 @@ function getCertMark(model, providerUrl, currentVersion, path = MANIFEST_PATH) {
22962
23009
  }
22963
23010
  var MANIFEST_PATH;
22964
23011
  var init_manifest = __esm(() => {
22965
- MANIFEST_PATH = join40(homedir14(), ".mma", "certifications.json");
23012
+ MANIFEST_PATH = join41(homedir14(), ".mma", "certifications.json");
22966
23013
  });
22967
23014
 
22968
23015
  // node_modules/yaml/dist/nodes/identity.js
@@ -30085,8 +30132,8 @@ var init_scenarios = __esm(() => {
30085
30132
  });
30086
30133
 
30087
30134
  // src/modules/certification/loader.ts
30088
- import { existsSync as existsSync46, readdirSync as readdirSync15, readFileSync as readFileSync29 } from "fs";
30089
- import { join as join41 } from "path";
30135
+ import { existsSync as existsSync48, readdirSync as readdirSync16, readFileSync as readFileSync31 } from "fs";
30136
+ import { join as join42 } from "path";
30090
30137
  function validateScenario(s) {
30091
30138
  const errors2 = [];
30092
30139
  const isSkip = s.mode === "skip";
@@ -30135,12 +30182,12 @@ function loadScenarios(userDir) {
30135
30182
  else
30136
30183
  scenarios.push(s);
30137
30184
  }
30138
- if (userDir && existsSync46(userDir)) {
30139
- for (const file of readdirSync15(userDir)) {
30185
+ if (userDir && existsSync48(userDir)) {
30186
+ for (const file of readdirSync16(userDir)) {
30140
30187
  if (!file.endsWith(".yaml") && !file.endsWith(".yml"))
30141
30188
  continue;
30142
30189
  try {
30143
- const raw = readFileSync29(join41(userDir, file), "utf-8");
30190
+ const raw = readFileSync31(join42(userDir, file), "utf-8");
30144
30191
  const data = $parse(raw);
30145
30192
  const parsed = normalizeScenario(data, file);
30146
30193
  const errs = validateScenario(parsed);
@@ -30193,8 +30240,8 @@ var init_loader3 = __esm(() => {
30193
30240
  });
30194
30241
 
30195
30242
  // src/modules/certification/fact-checker.ts
30196
- import { existsSync as existsSync47, readFileSync as readFileSync30, statSync as statSync8 } from "fs";
30197
- import { join as join42 } from "path";
30243
+ import { existsSync as existsSync49, readFileSync as readFileSync32, statSync as statSync8 } from "fs";
30244
+ import { join as join43 } from "path";
30198
30245
  function checkSandbox(sandboxDir, checks, exitCode, output) {
30199
30246
  const failures = [];
30200
30247
  for (const check of checks) {
@@ -30211,16 +30258,16 @@ function runCheck2(sandboxDir, check, exitCode, output) {
30211
30258
  case "outputContains":
30212
30259
  return output.includes(check.text);
30213
30260
  case "fileExists":
30214
- return isFile(join42(sandboxDir, check.path));
30261
+ return isFile(join43(sandboxDir, check.path));
30215
30262
  case "fileNotExists":
30216
- return !existsSync47(join42(sandboxDir, check.path));
30263
+ return !existsSync49(join43(sandboxDir, check.path));
30217
30264
  case "dirExists":
30218
- return isDir(join42(sandboxDir, check.path));
30265
+ return isDir(join43(sandboxDir, check.path));
30219
30266
  case "fileContent": {
30220
- const abs = join42(sandboxDir, check.path);
30267
+ const abs = join43(sandboxDir, check.path);
30221
30268
  if (!isFile(abs))
30222
30269
  return false;
30223
- const content = readFileSync30(abs, "utf-8");
30270
+ const content = readFileSync32(abs, "utf-8");
30224
30271
  if (check.contains !== undefined)
30225
30272
  return content.includes(check.contains);
30226
30273
  if (check.equals !== undefined)
@@ -30228,10 +30275,10 @@ function runCheck2(sandboxDir, check, exitCode, output) {
30228
30275
  return false;
30229
30276
  }
30230
30277
  case "fileRegex": {
30231
- const abs = join42(sandboxDir, check.path);
30278
+ const abs = join43(sandboxDir, check.path);
30232
30279
  if (!isFile(abs))
30233
30280
  return false;
30234
- return new RegExp(check.pattern).test(readFileSync30(abs, "utf-8"));
30281
+ return new RegExp(check.pattern).test(readFileSync32(abs, "utf-8"));
30235
30282
  }
30236
30283
  default:
30237
30284
  return false;
@@ -30239,14 +30286,14 @@ function runCheck2(sandboxDir, check, exitCode, output) {
30239
30286
  }
30240
30287
  function isFile(p) {
30241
30288
  try {
30242
- return existsSync47(p) && statSync8(p).isFile();
30289
+ return existsSync49(p) && statSync8(p).isFile();
30243
30290
  } catch {
30244
30291
  return false;
30245
30292
  }
30246
30293
  }
30247
30294
  function isDir(p) {
30248
30295
  try {
30249
- return existsSync47(p) && statSync8(p).isDirectory();
30296
+ return existsSync49(p) && statSync8(p).isDirectory();
30250
30297
  } catch {
30251
30298
  return false;
30252
30299
  }
@@ -30277,9 +30324,9 @@ var init_fact_checker = () => {};
30277
30324
 
30278
30325
  // src/modules/certification/runner.ts
30279
30326
  import { spawn as spawn8 } from "child_process";
30280
- import { existsSync as existsSync48, mkdirSync as mkdirSync19, rmSync as rmSync4, cpSync as cpSync2 } from "fs";
30281
- import { platform as platform9 } from "os";
30282
- import { join as join43, resolve as resolve24, dirname as dirname14 } from "path";
30327
+ import { existsSync as existsSync50, mkdirSync as mkdirSync19, rmSync as rmSync4, cpSync as cpSync2 } from "fs";
30328
+ import { platform as platform10 } from "os";
30329
+ import { join as join44, resolve as resolve24, dirname as dirname15 } from "path";
30283
30330
  async function runScenario(scenario, opts) {
30284
30331
  if (scenario.mode === "skip") {
30285
30332
  return {
@@ -30298,7 +30345,7 @@ async function runScenario(scenario, opts) {
30298
30345
  let passed = 0;
30299
30346
  let firstError;
30300
30347
  for (let i = 1;i <= reps; i++) {
30301
- const sandbox = join43(opts.sandboxBase, `run-${scenario.id}-${i}`);
30348
+ const sandbox = join44(opts.sandboxBase, `run-${scenario.id}-${i}`);
30302
30349
  let failures = [];
30303
30350
  let exitCode = -1;
30304
30351
  let output = "";
@@ -30312,15 +30359,15 @@ async function runScenario(scenario, opts) {
30312
30359
  sandbox,
30313
30360
  scenario.prompt
30314
30361
  ];
30315
- const env2 = {
30362
+ const env3 = {
30316
30363
  ...process.env,
30317
30364
  MMA_MODEL: opts.model,
30318
30365
  MMA_PROVIDER_BASEURL: opts.providerUrl,
30319
30366
  MMA_CONTEXT_WINDOW: String(opts.contextWindow ?? 32000)
30320
30367
  };
30321
30368
  if (opts.providerKey)
30322
- env2.MMA_PROVIDER_APIKEY = opts.providerKey;
30323
- const res = await runner(env2, opts.mmaRoot, args, timeoutMs);
30369
+ env3.MMA_PROVIDER_APIKEY = opts.providerKey;
30370
+ const res = await runner(env3, opts.mmaRoot, args, timeoutMs);
30324
30371
  output = `${res.stdout}
30325
30372
  ${res.stderr}`;
30326
30373
  exitCode = res.code ?? -1;
@@ -30359,25 +30406,25 @@ function prepareSandbox(sandbox, scenario, mmaRoot) {
30359
30406
  rmSync4(sandbox, { recursive: true, force: true });
30360
30407
  mkdirSync19(sandbox, { recursive: true });
30361
30408
  for (const f of scenario.fixtures ?? []) {
30362
- const src = join43(mmaRoot, f.source);
30363
- if (!existsSync48(src)) {
30409
+ const src = join44(mmaRoot, f.source);
30410
+ if (!existsSync50(src)) {
30364
30411
  throw new Error(`fixture missing: ${f.source}`);
30365
30412
  }
30366
- const dest = join43(sandbox, f.dest);
30367
- mkdirSync19(dirname14(dest), { recursive: true });
30413
+ const dest = join44(sandbox, f.dest);
30414
+ mkdirSync19(dirname15(dest), { recursive: true });
30368
30415
  cpSync2(src, dest);
30369
30416
  }
30370
30417
  }
30371
30418
  function resolveMmaEntry(mmaRoot) {
30372
- const dev = join43(mmaRoot, "src", "cli", "main.ts");
30373
- if (existsSync48(dev))
30419
+ const dev = join44(mmaRoot, "src", "cli", "main.ts");
30420
+ if (existsSync50(dev))
30374
30421
  return dev;
30375
- return join43(mmaRoot, "dist", "main.js");
30422
+ return join44(mmaRoot, "dist", "main.js");
30376
30423
  }
30377
30424
  function findMmaRoot(fromDir) {
30378
30425
  const candidates = [resolve24(fromDir, "..", "..", ".."), resolve24(fromDir, "..")];
30379
30426
  for (const c of candidates) {
30380
- if (existsSync48(join43(c, "package.json")))
30427
+ if (existsSync50(join44(c, "package.json")))
30381
30428
  return c;
30382
30429
  }
30383
30430
  return process.cwd();
@@ -30386,7 +30433,7 @@ function killTree2(child) {
30386
30433
  const pid = child.pid;
30387
30434
  if (!pid)
30388
30435
  return;
30389
- if (platform9() === "win32") {
30436
+ if (platform10() === "win32") {
30390
30437
  spawn8("taskkill", ["/pid", String(pid), "/T", "/F"], {
30391
30438
  windowsHide: true,
30392
30439
  stdio: "ignore"
@@ -30401,10 +30448,10 @@ function killTree2(child) {
30401
30448
  } catch {}
30402
30449
  }
30403
30450
  }
30404
- var defaultRunner2 = (env2, cwd, args, timeoutMs) => new Promise((resolvePromise) => {
30451
+ var defaultRunner2 = (env3, cwd, args, timeoutMs) => new Promise((resolvePromise) => {
30405
30452
  const child = spawn8(process.execPath, args, {
30406
30453
  cwd,
30407
- env: env2,
30454
+ env: env3,
30408
30455
  windowsHide: true,
30409
30456
  stdio: ["ignore", "pipe", "pipe"]
30410
30457
  });
@@ -30445,15 +30492,15 @@ __export(exports_cli, {
30445
30492
  });
30446
30493
  import { rmSync as rmSync5 } from "fs";
30447
30494
  import { homedir as homedir15 } from "os";
30448
- import { join as join44, dirname as dirname15 } from "path";
30449
- import { fileURLToPath as fileURLToPath3 } from "url";
30450
- import { existsSync as existsSync49, readFileSync as readFileSync31 } from "fs";
30495
+ import { join as join45, dirname as dirname16 } from "path";
30496
+ import { fileURLToPath as fileURLToPath4 } from "url";
30497
+ import { existsSync as existsSync51, readFileSync as readFileSync33 } from "fs";
30451
30498
  function readVersion() {
30452
- const candidates = [join44(MMA_ROOT, "package.json")];
30499
+ const candidates = [join45(MMA_ROOT, "package.json")];
30453
30500
  for (const p of candidates) {
30454
- if (existsSync49(p)) {
30501
+ if (existsSync51(p)) {
30455
30502
  try {
30456
- const raw = JSON.parse(readFileSync31(p, "utf-8"));
30503
+ const raw = JSON.parse(readFileSync33(p, "utf-8"));
30457
30504
  if (raw.version)
30458
30505
  return raw.version;
30459
30506
  } catch {}
@@ -30489,7 +30536,7 @@ async function certify(opts) {
30489
30536
  return;
30490
30537
  }
30491
30538
  console.log(t("cli.cert_started", { model: opts.name, provider: providerUrl }));
30492
- const sandboxBase = join44(process.cwd(), ".mma", "certification");
30539
+ const sandboxBase = join45(process.cwd(), ".mma", "certification");
30493
30540
  const results = [];
30494
30541
  const total = selected.length;
30495
30542
  let idx = 0;
@@ -30601,9 +30648,9 @@ var init_cli = __esm(() => {
30601
30648
  init_loader3();
30602
30649
  init_runner2();
30603
30650
  init_manifest();
30604
- HERE = dirname15(fileURLToPath3(import.meta.url));
30651
+ HERE = dirname16(fileURLToPath4(import.meta.url));
30605
30652
  MMA_ROOT = findMmaRoot(HERE);
30606
- USER_SCENARIO_DIR = join44(homedir15(), ".mma", "certification", "scenarios");
30653
+ USER_SCENARIO_DIR = join45(homedir15(), ".mma", "certification", "scenarios");
30607
30654
  });
30608
30655
 
30609
30656
  // src/cli/repl-commands.ts
@@ -30612,17 +30659,17 @@ __export(exports_repl_commands, {
30612
30659
  registerAllCommands: () => registerAllCommands,
30613
30660
  COMMAND_GROUPS: () => COMMAND_GROUPS
30614
30661
  });
30615
- import { join as join46, dirname as dirname17 } from "path";
30662
+ import { join as join47, dirname as dirname18 } from "path";
30616
30663
  import { homedir as homedir17 } from "os";
30617
- import { existsSync as existsSync51, readFileSync as readFileSync33 } from "fs";
30618
- import { fileURLToPath as fileURLToPath5 } from "url";
30664
+ import { existsSync as existsSync53, readFileSync as readFileSync35 } from "fs";
30665
+ import { fileURLToPath as fileURLToPath6 } from "url";
30619
30666
  function readVersion3() {
30620
- const here = dirname17(fileURLToPath5(import.meta.url));
30621
- const candidates = [join46(here, "..", "..", "package.json"), join46(here, "..", "package.json")];
30667
+ const here = dirname18(fileURLToPath6(import.meta.url));
30668
+ const candidates = [join47(here, "..", "..", "package.json"), join47(here, "..", "package.json")];
30622
30669
  for (const p of candidates) {
30623
- if (existsSync51(p)) {
30670
+ if (existsSync53(p)) {
30624
30671
  try {
30625
- const raw = JSON.parse(readFileSync33(p, "utf8"));
30672
+ const raw = JSON.parse(readFileSync35(p, "utf8"));
30626
30673
  if (raw.version)
30627
30674
  return raw.version;
30628
30675
  } catch {}
@@ -30686,7 +30733,7 @@ function registerMmaCommands(ctx) {
30686
30733
  }
30687
30734
  try {
30688
30735
  const { loadFileAsDataUrl: loadFileAsDataUrl2, loadUrlAsDataUrl: loadUrlAsDataUrl2, readClipboardImage: readClipboardImage2 } = await Promise.resolve().then(() => (init_image_utils(), exports_image_utils));
30689
- const { existsSync: existsSync52 } = await import("fs");
30736
+ const { existsSync: existsSync54 } = await import("fs");
30690
30737
  const { resolve: resolve25 } = await import("path");
30691
30738
  let dataUrl;
30692
30739
  let label;
@@ -30706,7 +30753,7 @@ function registerMmaCommands(ctx) {
30706
30753
  label = source;
30707
30754
  } else {
30708
30755
  const absPath = resolve25(process.cwd(), source);
30709
- if (!existsSync52(absPath)) {
30756
+ if (!existsSync54(absPath)) {
30710
30757
  console.log(pc2.red(t("image.not_found", { path: source })));
30711
30758
  return;
30712
30759
  }
@@ -30740,13 +30787,7 @@ function registerMmaCommands(ctx) {
30740
30787
  const sys = Math.floor(ctxW * cfg.contextBudget.systemPrompt);
30741
30788
  const res = Math.floor(ctxW * cfg.contextBudget.responseReserve);
30742
30789
  console.log(`${t("repl.model")} ${cfg.model}`);
30743
- const providers = ctx.agent.listProviders();
30744
- const active = providers.find((p) => p.active);
30745
- if (active) {
30746
- console.log(`${t("repl.provider")} ${active.label} (${pc2.dim(active.type)}) → ${pc2.dim(active.baseUrl)}`);
30747
- } else {
30748
- console.log(`${t("repl.provider")} ${cfg.provider.type} → ${cfg.provider.baseUrl}`);
30749
- }
30790
+ console.log(`${t("repl.provider")} ${cfg.provider.type} → ${cfg.provider.baseUrl}`);
30750
30791
  console.log(`${t("repl.context")} ${ctxW} (sys:${sys} res:${res} hist:${ctxW - sys - res})`);
30751
30792
  console.log(`${t("repl.max_iters")} ${cfg.maxToolIterations}`);
30752
30793
  console.log(`${t("repl.stuck_thresh")} ${cfg.stuckThreshold}`);
@@ -30774,14 +30815,8 @@ function registerMmaCommands(ctx) {
30774
30815
  description: t("repl.status"),
30775
30816
  usage: t("repl.status_usage"),
30776
30817
  action: () => {
30777
- const providers = ctx.agent.listProviders();
30778
- const active = providers.find((p) => p.active);
30779
30818
  console.log(`${t("repl.model")} ${ctx.config.model}`);
30780
- if (active) {
30781
- console.log(`${t("repl.provider")} ${active.label} (${pc2.dim(active.type)}) @ ${pc2.dim(active.baseUrl)}`);
30782
- } else {
30783
- console.log(`${t("repl.provider")} ${ctx.config.provider.type} @ ${ctx.config.provider.baseUrl}`);
30784
- }
30819
+ console.log(`${t("repl.provider")} ${ctx.config.provider.type} @ ${ctx.config.provider.baseUrl}`);
30785
30820
  const meta = ctx.sessionManager?.getActiveMeta();
30786
30821
  if (meta) {
30787
30822
  console.log(`${t("repl.session_label")} ${meta.name} (${meta.id}) — ${meta.messageCount} messages`);
@@ -30797,7 +30832,7 @@ function registerMmaCommands(ctx) {
30797
30832
  console.log(pc2.yellow(t("repl.wizard_running")));
30798
30833
  await ctx.withExclusiveInput(async () => {
30799
30834
  const answers = await runSetup(ctx.rl);
30800
- const configPath = join46(homedir17(), ".mma", "config.json");
30835
+ const configPath = join47(homedir17(), ".mma", "config.json");
30801
30836
  ctx.config.provider.type = answers.provider;
30802
30837
  ctx.config.provider.baseUrl = answers.apiBase;
30803
30838
  ctx.config.provider.apiKey = answers.apiKey;
@@ -30840,17 +30875,8 @@ Excluded blocks: ${info.excluded.length}`));
30840
30875
  action: async (args) => {
30841
30876
  const subcmd = args[0];
30842
30877
  if (!subcmd || subcmd === "list") {
30843
- const providers = ctx.agent.listProviders();
30844
- if (providers.length === 0) {
30845
- console.log(`${t("repl.provider_current")} ${ctx.config.provider.type}`);
30846
- console.log(` ${ctx.config.provider.baseUrl}`);
30847
- } else {
30848
- console.log(t("repl.provider_current"));
30849
- for (const p of providers) {
30850
- const marker = p.active ? pc2.green("* ") : " ";
30851
- console.log(` ${marker}${p.label} (${pc2.dim(p.type)}) ${pc2.dim(p.baseUrl)}`);
30852
- }
30853
- }
30878
+ console.log(`${t("repl.provider_current")} ${ctx.config.provider.type}`);
30879
+ console.log(` ${ctx.config.provider.baseUrl}`);
30854
30880
  return;
30855
30881
  }
30856
30882
  if (subcmd === "use") {
@@ -30859,12 +30885,11 @@ Excluded blocks: ${info.excluded.length}`));
30859
30885
  console.log(t("repl.provider_usage"));
30860
30886
  return;
30861
30887
  }
30862
- try {
30863
- await ctx.agent.setProvider(name);
30864
- console.log(pc2.green(t("repl.provider_set", { name })));
30865
- } catch (e) {
30866
- console.log(pc2.red(e.message));
30867
- }
30888
+ ctx.config.provider.type = name;
30889
+ const configPath = join47(homedir17(), ".mma", "config.json");
30890
+ saveConfig(ctx.config, configPath);
30891
+ await ctx.agent.reconfigure(ctx.config);
30892
+ console.log(pc2.green(t("repl.provider_set", { name })));
30868
30893
  return;
30869
30894
  }
30870
30895
  console.log(t("repl.provider_usage"));
@@ -30917,7 +30942,7 @@ Excluded blocks: ${info.excluded.length}`));
30917
30942
  return;
30918
30943
  }
30919
30944
  ctx.config.model = name;
30920
- const configPath = join46(homedir17(), ".mma", "config.json");
30945
+ const configPath = join47(homedir17(), ".mma", "config.json");
30921
30946
  saveConfig(ctx.config, configPath);
30922
30947
  await ctx.agent.reconfigure(ctx.config);
30923
30948
  console.log(pc2.green(t("repl.model_set", { name })));
@@ -30942,7 +30967,7 @@ Excluded blocks: ${info.excluded.length}`));
30942
30967
  return;
30943
30968
  }
30944
30969
  ctx.config.contextWindow = size;
30945
- const configPath = join46(homedir17(), ".mma", "config.json");
30970
+ const configPath = join47(homedir17(), ".mma", "config.json");
30946
30971
  saveConfig(ctx.config, configPath);
30947
30972
  await ctx.agent.reconfigure(ctx.config);
30948
30973
  console.log(pc2.green(t("cli.context_set", { size })));
@@ -30961,10 +30986,10 @@ Excluded blocks: ${info.excluded.length}`));
30961
30986
  ctx.agent.shutdown();
30962
30987
  const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config2(), exports_config));
30963
30988
  const { homedir: homedir18 } = await import("os");
30964
- const { join: join47 } = await import("path");
30989
+ const { join: join48 } = await import("path");
30965
30990
  const configDir = ctx.configDir;
30966
30991
  const baseDir = ctx.baseDir;
30967
- const projectConfigPath = join47(baseDir, ".mmrc");
30992
+ const projectConfigPath = join48(baseDir, ".mmrc");
30968
30993
  const freshConfig = loadConfig2({ configDir, projectConfigPath });
30969
30994
  Object.assign(ctx.config, freshConfig);
30970
30995
  const { bootstrap: bootstrap2 } = await Promise.resolve().then(() => (init_bootstrap(), exports_bootstrap));
@@ -31015,6 +31040,70 @@ Excluded blocks: ${info.excluded.length}`));
31015
31040
  }
31016
31041
  }
31017
31042
  });
31043
+ ctx.registerCommand({
31044
+ name: "lsp",
31045
+ description: t("repl.lsp"),
31046
+ usage: t("repl.lsp_usage"),
31047
+ action: async (args) => {
31048
+ const subcommand = args[0] || "status";
31049
+ const lspModule = ctx.agent.deps?.moduleRegistry?.getModules?.()?.find((m) => m.name === "lsp");
31050
+ if (!lspModule) {
31051
+ console.log(pc2.yellow(t("repl.lsp_not_available")));
31052
+ return;
31053
+ }
31054
+ switch (subcommand) {
31055
+ case "status": {
31056
+ const disabled = lspModule.getDisabledServers();
31057
+ const failures = lspModule.getFailureCounts();
31058
+ const config = ctx.config.lsp;
31059
+ console.log(pc2.bold(t("repl.lsp_status_header")));
31060
+ console.log(`${t("repl.lsp_enabled")} ${config?.enabled ? pc2.green("yes") : pc2.red("no")}`);
31061
+ if (disabled.length > 0) {
31062
+ console.log(pc2.yellow(`${t("repl.lsp_disabled_servers")} ${disabled.join(", ")}`));
31063
+ }
31064
+ if (failures.size > 0) {
31065
+ console.log(pc2.dim(t("repl.lsp_failure_counts")));
31066
+ for (const [server, count] of failures) {
31067
+ console.log(pc2.dim(` ${server}: ${count}`));
31068
+ }
31069
+ }
31070
+ if (disabled.length === 0 && failures.size === 0) {
31071
+ console.log(pc2.green(t("repl.lsp_all_ok")));
31072
+ }
31073
+ break;
31074
+ }
31075
+ case "restart": {
31076
+ console.log(pc2.yellow(t("repl.lsp_restarting")));
31077
+ lspModule.resetDisabledServers();
31078
+ console.log(pc2.green(t("repl.lsp_restarted")));
31079
+ break;
31080
+ }
31081
+ case "check": {
31082
+ const path = args[1];
31083
+ if (!path) {
31084
+ console.log(pc2.yellow(t("repl.lsp_check_usage")));
31085
+ return;
31086
+ }
31087
+ console.log(pc2.dim(t("repl.lsp_checking", { path })));
31088
+ try {
31089
+ const result = await ctx.agent.deps?.toolExecutor?.execute("lsp_check", { path }, ctx.agent.deps?.toolCtx);
31090
+ if (result?.output) {
31091
+ console.log(result.output);
31092
+ }
31093
+ } catch (e) {
31094
+ console.log(pc2.red(t("repl.lsp_check_error", {
31095
+ error: e instanceof Error ? e.message : String(e)
31096
+ })));
31097
+ }
31098
+ break;
31099
+ }
31100
+ default: {
31101
+ console.log(pc2.dim(t("repl.lsp_usage")));
31102
+ break;
31103
+ }
31104
+ }
31105
+ }
31106
+ });
31018
31107
  }
31019
31108
  function registerSessionCommands(ctx) {
31020
31109
  if (!ctx.sessionManager)
@@ -31269,6 +31358,7 @@ var init_repl_commands = __esm(() => {
31269
31358
  reload: "agent",
31270
31359
  wizard: "agent",
31271
31360
  sysprompt: "agent",
31361
+ lsp: "agent",
31272
31362
  sessions: "session",
31273
31363
  new: "session",
31274
31364
  resume: "session",
@@ -31300,15 +31390,14 @@ init_bootstrap();
31300
31390
  init_config2();
31301
31391
  init_setup();
31302
31392
  init_i18n();
31303
- init_colors();
31304
- import { join as join45, dirname as dirname16 } from "path";
31393
+ import { join as join46, dirname as dirname17 } from "path";
31305
31394
  import { homedir as homedir16 } from "os";
31306
- import { existsSync as existsSync50, readFileSync as readFileSync32 } from "fs";
31395
+ import { existsSync as existsSync52, readFileSync as readFileSync34 } from "fs";
31307
31396
 
31308
31397
  // src/cli/security-commands.ts
31309
31398
  init_bootstrap();
31310
31399
  init_config2();
31311
- import { join as join39 } from "path";
31400
+ import { join as join40 } from "path";
31312
31401
  import { homedir as homedir13 } from "os";
31313
31402
 
31314
31403
  // src/modules/security/security-policies.ts
@@ -31822,7 +31911,7 @@ function createSecurityCommand(program2) {
31822
31911
  }
31823
31912
  });
31824
31913
  securityCmd.command("set-policy").argument("<preset>", t("cli.security.preset")).description(t("cli.security.set_policy")).action(async (preset) => {
31825
- const configPath = join39(homedir13(), ".mma", "config.json");
31914
+ const configPath = join40(homedir13(), ".mma", "config.json");
31826
31915
  const { config: appConfig } = await bootstrap();
31827
31916
  const validPresets = ["strict", "balanced", "permissive"];
31828
31917
  if (!validPresets.includes(preset)) {
@@ -31837,7 +31926,7 @@ function createSecurityCommand(program2) {
31837
31926
  console.log(t("cli.security.policy_description", { description: policy.description }));
31838
31927
  });
31839
31928
  securityCmd.command("enable-encryption").description(t("cli.security.enable_encryption")).action(async () => {
31840
- const configPath = join39(homedir13(), ".mma", "config.json");
31929
+ const configPath = join40(homedir13(), ".mma", "config.json");
31841
31930
  const { config: appConfig } = await bootstrap();
31842
31931
  appConfig.security = appConfig.security || {};
31843
31932
  appConfig.security.sessionEncryption = {
@@ -31849,7 +31938,7 @@ function createSecurityCommand(program2) {
31849
31938
  console.log(t("cli.security.encryption_enabled"));
31850
31939
  });
31851
31940
  securityCmd.command("disable-encryption").description(t("cli.security.disable_encryption")).action(async () => {
31852
- const configPath = join39(homedir13(), ".mma", "config.json");
31941
+ const configPath = join40(homedir13(), ".mma", "config.json");
31853
31942
  const { config: appConfig } = await bootstrap();
31854
31943
  appConfig.security = appConfig.security || {};
31855
31944
  appConfig.security.sessionEncryption = {
@@ -31861,7 +31950,7 @@ function createSecurityCommand(program2) {
31861
31950
  console.log(t("cli.security.encryption_disabled"));
31862
31951
  });
31863
31952
  securityCmd.command("enable-audit").description(t("cli.security.enable_audit")).action(async () => {
31864
- const configPath = join39(homedir13(), ".mma", "config.json");
31953
+ const configPath = join40(homedir13(), ".mma", "config.json");
31865
31954
  const { config: appConfig } = await bootstrap();
31866
31955
  appConfig.security = appConfig.security || {};
31867
31956
  appConfig.security.auditNotifier = {
@@ -31875,7 +31964,7 @@ function createSecurityCommand(program2) {
31875
31964
  console.log(t("cli.security.audit_enabled"));
31876
31965
  });
31877
31966
  securityCmd.command("disable-audit").description(t("cli.security.disable_audit")).action(async () => {
31878
- const configPath = join39(homedir13(), ".mma", "config.json");
31967
+ const configPath = join40(homedir13(), ".mma", "config.json");
31879
31968
  const { config: appConfig } = await bootstrap();
31880
31969
  appConfig.security = appConfig.security || {};
31881
31970
  appConfig.security.auditNotifier = {
@@ -31938,15 +32027,15 @@ function createPluginCommand(program2) {
31938
32027
  }
31939
32028
 
31940
32029
  // src/cli/commands.ts
31941
- init_presets();
31942
- import { fileURLToPath as fileURLToPath4 } from "url";
32030
+ init_setup();
32031
+ import { fileURLToPath as fileURLToPath5 } from "url";
31943
32032
  function readVersion2() {
31944
- const here = dirname16(fileURLToPath4(import.meta.url));
31945
- const candidates = [join45(here, "..", "..", "package.json"), join45(here, "..", "package.json")];
32033
+ const here = dirname17(fileURLToPath5(import.meta.url));
32034
+ const candidates = [join46(here, "..", "..", "package.json"), join46(here, "..", "package.json")];
31946
32035
  for (const p of candidates) {
31947
- if (existsSync50(p)) {
32036
+ if (existsSync52(p)) {
31948
32037
  try {
31949
- const raw = JSON.parse(readFileSync32(p, "utf8"));
32038
+ const raw = JSON.parse(readFileSync34(p, "utf8"));
31950
32039
  if (raw.version)
31951
32040
  return raw.version;
31952
32041
  } catch {}
@@ -31959,7 +32048,7 @@ function createProgram() {
31959
32048
  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"));
31960
32049
  program2.command("init").description(t("cli.init")).action(async () => {
31961
32050
  const answers = await runSetup();
31962
- const configPath = join45(homedir16(), ".mma", "config.json");
32051
+ const configPath = join46(homedir16(), ".mma", "config.json");
31963
32052
  const { config } = await bootstrap();
31964
32053
  config.provider.type = answers.provider;
31965
32054
  config.provider.baseUrl = answers.apiBase;
@@ -32004,7 +32093,7 @@ function createProgram() {
32004
32093
  });
32005
32094
  const configCmd = program2.command("config").description(t("cli.manage_config"));
32006
32095
  configCmd.command("set").argument("<key>", t("cli.config_key")).argument("<value>", "Config value").description(t("cli.set_value")).action(async (key, value) => {
32007
- const configPath = join45(homedir16(), ".mma", "config.json");
32096
+ const configPath = join46(homedir16(), ".mma", "config.json");
32008
32097
  const { config } = await bootstrap();
32009
32098
  const keys = key.split(".");
32010
32099
  let obj = config;
@@ -32035,8 +32124,8 @@ function createProgram() {
32035
32124
  model.command("list").description(t("cli.list_models")).action(async () => {
32036
32125
  const { config } = await bootstrap();
32037
32126
  console.log(t("cli.current_model"), config.model);
32038
- const { createProvider: createProvider2 } = await Promise.resolve().then(() => (init_create(), exports_create));
32039
- const provider2 = createProvider2(config.provider.type, {
32127
+ const { OpenAICompatProvider: OpenAICompatProvider2 } = await Promise.resolve().then(() => (init_openai_compat(), exports_openai_compat));
32128
+ const provider2 = new OpenAICompatProvider2({
32040
32129
  model: config.model,
32041
32130
  baseUrl: config.provider.baseUrl,
32042
32131
  apiKey: config.provider.apiKey,
@@ -32067,7 +32156,7 @@ function createProgram() {
32067
32156
  console.log(t("cli.model_hint"));
32068
32157
  });
32069
32158
  model.command("use").argument("<name>", "Model name").description(t("cli.set_model")).action(async (name) => {
32070
- const configPath = join45(homedir16(), ".mma", "config.json");
32159
+ const configPath = join46(homedir16(), ".mma", "config.json");
32071
32160
  const { config } = await bootstrap();
32072
32161
  config.model = name;
32073
32162
  saveConfig(config, configPath);
@@ -32103,7 +32192,7 @@ function createProgram() {
32103
32192
  await uncertify2(name, config);
32104
32193
  });
32105
32194
  program2.command("context").description(t("cli.manage_context")).argument("<size>", "Context window size in tokens").action(async (size) => {
32106
- const configPath = join45(homedir16(), ".mma", "config.json");
32195
+ const configPath = join46(homedir16(), ".mma", "config.json");
32107
32196
  const { config } = await bootstrap();
32108
32197
  const contextWindow = parseInt(size, 10);
32109
32198
  if (isNaN(contextWindow) || contextWindow < 1024) {
@@ -32116,31 +32205,13 @@ function createProgram() {
32116
32205
  });
32117
32206
  const provider = program2.command("provider").description(t("cli.manage_providers"));
32118
32207
  provider.command("list").description(t("cli.list_providers")).action(async () => {
32119
- const { config, agent } = await bootstrap();
32120
- const providers = agent.listProviders();
32121
- if (providers.length > 0) {
32122
- console.log(t("cli.current_provider"));
32123
- for (const p of providers) {
32124
- const marker = p.active ? pc2.green("* ") : " ";
32125
- console.log(` ${marker}${p.label} (${pc2.dim(p.type)}) ${pc2.dim(p.baseUrl)}`);
32126
- }
32127
- return;
32128
- }
32208
+ const { config } = await bootstrap();
32129
32209
  console.log(t("cli.current_provider"), config.provider.type);
32130
32210
  console.log(t("cli.base_url"), config.provider.baseUrl);
32131
32211
  });
32132
32212
  provider.command("use").argument("<name>", "Provider name").description(t("cli.set_provider")).action(async (name) => {
32133
- const configPath = join45(homedir16(), ".mma", "config.json");
32134
- const { config, agent } = await bootstrap();
32135
- if (config.provider.entries && config.provider.entries.length > 0) {
32136
- try {
32137
- await agent.setProvider(name);
32138
- console.log(t("cli.provider_set", { name }));
32139
- } catch (e) {
32140
- console.log(pc2.red(e.message));
32141
- }
32142
- return;
32143
- }
32213
+ const configPath = join46(homedir16(), ".mma", "config.json");
32214
+ const { config } = await bootstrap();
32144
32215
  config.provider.type = name;
32145
32216
  const baseUrl = HOSTED_BASE_URLS[name];
32146
32217
  if (baseUrl) {
@@ -32152,35 +32223,6 @@ function createProgram() {
32152
32223
  console.log(t("cli.provider_base_hint", { baseUrl }));
32153
32224
  }
32154
32225
  });
32155
- provider.command("add").argument("<name>", "Provider type or label").option("--url <url>", "Base URL").option("--key <key>", "API key").description(t("cli.add_provider")).action(async (name, opts) => {
32156
- const configPath = join45(homedir16(), ".mma", "config.json");
32157
- const { config } = await bootstrap();
32158
- const entries = Array.isArray(config.provider.entries) ? config.provider.entries : [];
32159
- if (entries.length === 0) {
32160
- entries.push({
32161
- type: config.provider.type,
32162
- label: config.provider.type,
32163
- baseUrl: config.provider.baseUrl,
32164
- apiKey: config.provider.apiKey
32165
- });
32166
- }
32167
- const baseUrl = opts.url || HOSTED_BASE_URLS[name] || HOSTED_BASE_URLS[`opencode-${name}`] || "";
32168
- if (!baseUrl) {
32169
- console.log(pc2.red(t("cli.provider_no_url", { name })));
32170
- return;
32171
- }
32172
- entries.push({
32173
- type: name,
32174
- label: name,
32175
- baseUrl,
32176
- apiKey: opts.key
32177
- });
32178
- config.provider.entries = entries;
32179
- config.provider.active = config.provider.active || config.provider.type;
32180
- saveConfig(config, configPath);
32181
- console.log(pc2.green(t("cli.provider_added", { name })));
32182
- console.log(t("cli.provider_switch_hint"));
32183
- });
32184
32226
  const session2 = program2.command("session").description(t("cli.manage_sessions"));
32185
32227
  session2.command("list").description(t("cli.list_sessions")).action(async () => {
32186
32228
  const { sessionManager } = await bootstrap();
@@ -32983,8 +33025,8 @@ class LineEditor {
32983
33025
  }
32984
33026
 
32985
33027
  // src/cli/repl.ts
32986
- import { existsSync as existsSync53, readFileSync as readFileSync35, writeFileSync as writeFileSync17 } from "fs";
32987
- import { join as join48 } from "path";
33028
+ import { existsSync as existsSync55, readFileSync as readFileSync37, writeFileSync as writeFileSync17 } from "fs";
33029
+ import { join as join49 } from "path";
32988
33030
  import { homedir as homedir18 } from "os";
32989
33031
 
32990
33032
  // src/cli/completer.ts
@@ -33429,9 +33471,8 @@ ${pc2.dim(marker)} ${friendlyTool(tool)}${summary ? ` ${pc2.dim(summary)}` : ""}
33429
33471
  `);
33430
33472
  }
33431
33473
  }
33432
- toolEnd(_tool, duration, error, ctxDelta, costUsd, provider, model) {
33474
+ toolEnd(_tool, duration, error, ctxDelta, costUsd) {
33433
33475
  this.spinner.stop();
33434
- const prov = provider && model ? `${pc2.dim(`${provider}·${model}`)}` : undefined;
33435
33476
  if (!this.rich) {
33436
33477
  const parts = [];
33437
33478
  if (ctxDelta !== undefined && ctxDelta !== 0) {
@@ -33441,8 +33482,6 @@ ${pc2.dim(marker)} ${friendlyTool(tool)}${summary ? ` ${pc2.dim(summary)}` : ""}
33441
33482
  if (costUsd !== undefined && costUsd > 0) {
33442
33483
  parts.push(`${pc2.dim("cost")} ${pc2.yellow(formatUsd(costUsd))}`);
33443
33484
  }
33444
- if (prov)
33445
- parts.push(prov);
33446
33485
  if (parts.length > 0)
33447
33486
  this.out.write(`${parts.join(" ")}
33448
33487
  `);
@@ -33460,9 +33499,6 @@ ${pc2.dim(marker)} ${friendlyTool(tool)}${summary ? ` ${pc2.dim(summary)}` : ""}
33460
33499
  if (costUsd !== undefined && costUsd > 0) {
33461
33500
  footer += ` ${pc2.dim("cost")} ${pc2.yellow(formatUsd(costUsd))}`;
33462
33501
  }
33463
- if (prov) {
33464
- footer += ` ${pc2.dim("via")} ${prov}`;
33465
- }
33466
33502
  if (this.toolStyle === "inline") {
33467
33503
  this.out.write(`${GUTTER}${footer}
33468
33504
  `);
@@ -33558,20 +33594,30 @@ async function probeLspServers(config, baseDir, deps = {}) {
33558
33594
  const serverTimeout = Math.min(server.timeout ?? timeoutCap, timeoutCap);
33559
33595
  const started = Date.now();
33560
33596
  const probeClient = deps.client ?? new LspClient;
33597
+ if (!deps.client)
33598
+ probeClient.setLogger(deps.logger ?? null);
33561
33599
  try {
33562
33600
  await probeClient.probe(server, projectRoot, serverTimeout);
33563
33601
  ok.push({ language, ok: true, durationMs: Date.now() - started });
33564
33602
  } catch (e) {
33603
+ const errorMsg = e instanceof Error ? e.message : String(e);
33604
+ deps.logger?.warn(`LSP probe failed for ${language}: ${errorMsg}`, {
33605
+ command: server.command,
33606
+ timeout: serverTimeout,
33607
+ durationMs: Date.now() - started
33608
+ });
33565
33609
  failed.push({
33566
33610
  language,
33567
33611
  ok: false,
33568
- error: e instanceof Error ? e.message : String(e),
33612
+ error: errorMsg,
33569
33613
  durationMs: Date.now() - started
33570
33614
  });
33571
33615
  }
33572
33616
  };
33573
33617
  for (let i = 0;i < servers.length; i += maxParallel) {
33574
33618
  if (Date.now() >= deadline) {
33619
+ const remaining = servers.slice(i).map((s) => s.language);
33620
+ deps.logger?.warn(`LSP probe deadline reached, skipping: ${remaining.join(", ")}`);
33575
33621
  for (const { language } of servers.slice(i)) {
33576
33622
  failed.push({ language, ok: false, error: "timeout", durationMs: 0 });
33577
33623
  }
@@ -33585,19 +33631,20 @@ async function probeLspServers(config, baseDir, deps = {}) {
33585
33631
 
33586
33632
  // src/cli/repl.ts
33587
33633
  init_config();
33634
+ init_session_logger();
33588
33635
 
33589
33636
  // src/ui/plan-view.ts
33590
33637
  init_colors();
33591
33638
  init_js_identifiers();
33592
33639
  init_i18n();
33593
- import { existsSync as existsSync52, readFileSync as readFileSync34 } from "fs";
33594
- import { join as join47 } from "path";
33640
+ import { existsSync as existsSync54, readFileSync as readFileSync36 } from "fs";
33641
+ import { join as join48 } from "path";
33595
33642
  function readActivePlan(baseDir) {
33596
- const p = join47(baseDir, ".mma", "plans", "active.json");
33597
- if (!existsSync52(p))
33643
+ const p = join48(baseDir, ".mma", "plans", "active.json");
33644
+ if (!existsSync54(p))
33598
33645
  return null;
33599
33646
  try {
33600
- const raw = readFileSync34(p, "utf-8");
33647
+ const raw = readFileSync36(p, "utf-8");
33601
33648
  if (!raw.trim())
33602
33649
  return null;
33603
33650
  const parsed = JSON.parse(raw);
@@ -33732,7 +33779,9 @@ class Repl {
33732
33779
  skillsModule;
33733
33780
  pluginManager;
33734
33781
  logger;
33735
- constructor(agent, config, sessionManager, skillsModule, pluginManager, configDir, baseDir, noAgentsMd, logger, exitOnClose) {
33782
+ slog;
33783
+ envReport;
33784
+ constructor(agent, config, sessionManager, skillsModule, pluginManager, configDir, baseDir, noAgentsMd, logger, exitOnClose, envReport) {
33736
33785
  this.agent = agent;
33737
33786
  this.config = config;
33738
33787
  this.exitOnClose = exitOnClose === true;
@@ -33740,10 +33789,12 @@ class Repl {
33740
33789
  this.skillsModule = skillsModule;
33741
33790
  this.pluginManager = pluginManager;
33742
33791
  this.logger = logger;
33743
- this.configDir = configDir || join48(homedir18(), ".mma");
33792
+ this.envReport = envReport;
33793
+ this.slog = new SessionLogger(sessionManager, logger);
33794
+ this.configDir = configDir || join49(homedir18(), ".mma");
33744
33795
  this.baseDir = baseDir || process.cwd();
33745
33796
  this.noAgentsMd = noAgentsMd === true;
33746
- this.historyPath = join48(homedir18(), ".mma", "repl-history");
33797
+ this.historyPath = join49(homedir18(), ".mma", "repl-history");
33747
33798
  this.loadHistory();
33748
33799
  this.rl = process.stdin.isTTY ? new LineEditor({
33749
33800
  input: process.stdin,
@@ -33776,9 +33827,9 @@ class Repl {
33776
33827
  this.setupListeners();
33777
33828
  }
33778
33829
  loadHistory() {
33779
- if (existsSync53(this.historyPath)) {
33830
+ if (existsSync55(this.historyPath)) {
33780
33831
  try {
33781
- const raw = readFileSync35(this.historyPath, "utf-8");
33832
+ const raw = readFileSync37(this.historyPath, "utf-8");
33782
33833
  this.history = raw.split(`
33783
33834
  `).filter(Boolean).slice(-this.maxHistory);
33784
33835
  } catch {
@@ -33854,6 +33905,7 @@ class Repl {
33854
33905
  return;
33855
33906
  }
33856
33907
  if (!trimmed) {
33908
+ this.rl.setPrompt(pc2.cyan(t("repl.you")));
33857
33909
  this.rl.prompt();
33858
33910
  return;
33859
33911
  }
@@ -33863,6 +33915,7 @@ class Repl {
33863
33915
  await this.runAgent(trimmed);
33864
33916
  }
33865
33917
  if (this.running) {
33918
+ this.rl.setPrompt(pc2.cyan(t("repl.you")));
33866
33919
  this.rl.prompt();
33867
33920
  }
33868
33921
  });
@@ -33870,6 +33923,7 @@ class Repl {
33870
33923
  this.running = false;
33871
33924
  this.saveHistory();
33872
33925
  this.agent.shutdown();
33926
+ this.logger?.closeSessionLog();
33873
33927
  if (this.exitOnClose)
33874
33928
  process.exit(0);
33875
33929
  });
@@ -33878,6 +33932,7 @@ class Repl {
33878
33932
  this.running = false;
33879
33933
  this.saveHistory();
33880
33934
  this.agent.shutdown();
33935
+ this.logger?.closeSessionLog();
33881
33936
  process.exit(0);
33882
33937
  });
33883
33938
  }
@@ -33982,7 +34037,7 @@ ${t("image.clipboard_empty")}`));
33982
34037
  if (ev.type === "start") {
33983
34038
  renderer.toolStart(ev.tool, ev.args, stepContextForTool(this.activePlan, ev.tool, ev.args), ev.icon);
33984
34039
  } else {
33985
- renderer.toolEnd(ev.tool, ev.duration ?? 0, ev.error, ev.ctxDelta, ev.costUsd, ev.provider, ev.model);
34040
+ renderer.toolEnd(ev.tool, ev.duration ?? 0, ev.error, ev.ctxDelta, ev.costUsd);
33986
34041
  if (ev.tool === "plan" || ev.tool === "todo") {
33987
34042
  this.refreshActivePlan(renderer);
33988
34043
  }
@@ -34154,11 +34209,11 @@ ${t("image.clipboard_empty")}`));
34154
34209
  row(t("repl.agents_label"), pc2.red(t("repl.disabled")));
34155
34210
  } else {
34156
34211
  const agentsMdCandidates = [
34157
- join48(this.baseDir, "AGENTS.md"),
34158
- join48(this.baseDir, ".mma", "AGENTS.md"),
34159
- join48(this.configDir, "AGENTS.md")
34212
+ join49(this.baseDir, "AGENTS.md"),
34213
+ join49(this.baseDir, ".mma", "AGENTS.md"),
34214
+ join49(this.configDir, "AGENTS.md")
34160
34215
  ];
34161
- const foundAgents = agentsMdCandidates.filter((p) => existsSync53(p));
34216
+ const foundAgents = agentsMdCandidates.filter((p) => existsSync55(p));
34162
34217
  if (foundAgents.length > 0) {
34163
34218
  for (const p of foundAgents) {
34164
34219
  row(t("repl.agents_label"), pc2.dim(p));
@@ -34169,7 +34224,7 @@ ${t("image.clipboard_empty")}`));
34169
34224
  }
34170
34225
  const meta = this.sessionManager?.getActiveMeta();
34171
34226
  if (meta) {
34172
- const sessionPath = join48(this.configDir, "sessions", meta.id);
34227
+ const sessionPath = join49(this.configDir, "sessions", meta.id);
34173
34228
  row(t("repl.session_label"), `${pc2.cyan(meta.name)} ${pc2.dim(`(${meta.id.slice(0, 12)})`)} — ${meta.messageCount} msgs ${pc2.dim(sessionPath)}`);
34174
34229
  }
34175
34230
  const headerWidth = Math.max(50, Math.min(96, process.stdout.columns || 96));
@@ -34204,7 +34259,19 @@ ${t("image.clipboard_empty")}`));
34204
34259
  async probeLspBanner() {
34205
34260
  const config = this.config.lsp ?? DEFAULT_LSP_CONFIG;
34206
34261
  try {
34207
- const summary = await probeLspServers(config, this.baseDir);
34262
+ const summary = await probeLspServers(config, this.baseDir, { logger: this.logger });
34263
+ this.slog.logSessionStart({
34264
+ environment: this.envReport,
34265
+ lspProbe: {
34266
+ ok: summary.ok.map((r) => ({ language: r.language, durationMs: r.durationMs })),
34267
+ failed: summary.failed.map((r) => ({
34268
+ language: r.language,
34269
+ error: r.error,
34270
+ durationMs: r.durationMs
34271
+ })),
34272
+ noneApplicable: summary.noneApplicable
34273
+ }
34274
+ });
34208
34275
  if (summary.noneApplicable)
34209
34276
  return null;
34210
34277
  const parts = [];
@@ -34224,6 +34291,7 @@ ${t("image.clipboard_empty")}`));
34224
34291
  this.running = false;
34225
34292
  this.saveHistory();
34226
34293
  this.agent.shutdown();
34294
+ this.logger?.closeSessionLog();
34227
34295
  this.rl.close();
34228
34296
  }
34229
34297
  }
@@ -34254,10 +34322,10 @@ init_setup();
34254
34322
  init_config2();
34255
34323
  init_i18n();
34256
34324
  init_colors();
34257
- import { existsSync as existsSync54, readFileSync as readFileSync36 } from "fs";
34258
- import { join as join49, dirname as dirname18 } from "path";
34259
- import { homedir as homedir19 } from "os";
34260
- import { fileURLToPath as fileURLToPath6 } from "url";
34325
+ import { existsSync as existsSync56, readFileSync as readFileSync38 } from "fs";
34326
+ import { join as join51, dirname as dirname19 } from "path";
34327
+ import { homedir as homedir20 } from "os";
34328
+ import { fileURLToPath as fileURLToPath7 } from "url";
34261
34329
 
34262
34330
  // src/modules/updater/index.ts
34263
34331
  init_checker();
@@ -34356,14 +34424,61 @@ class UpdaterModule {
34356
34424
  await this.runOnce();
34357
34425
  }
34358
34426
  }
34427
+ // src/core/crash-handler.ts
34428
+ init_environment();
34429
+ init_data_sanitizer();
34430
+ init_i18n();
34431
+ import { appendFileSync as appendFileSync7, mkdirSync as mkdirSync20 } from "fs";
34432
+ import { join as join50 } from "path";
34433
+ import { homedir as homedir19 } from "os";
34434
+ var CRASH_LOG_DIR = join50(homedir19(), ".mma", "logs");
34435
+ var CRASH_LOG_FILE = "crash.jsonl";
34436
+ function formatCrashEntry(type2, err) {
34437
+ const message = err instanceof Error ? err.message : String(err);
34438
+ const stack = err instanceof Error && err.stack ? err.stack : message;
34439
+ return {
34440
+ ts: new Date().toISOString(),
34441
+ type: type2,
34442
+ message: sanitizeLogMessage(message),
34443
+ stack: sanitizeLogMessage(stack),
34444
+ environment: collectEnvironment({ configDir: homedir19(), scanTools: false })
34445
+ };
34446
+ }
34447
+ function writeCrashEntry(dir, entry) {
34448
+ try {
34449
+ mkdirSync20(dir, { recursive: true });
34450
+ appendFileSync7(join50(dir, CRASH_LOG_FILE), JSON.stringify(entry) + `
34451
+ `, "utf-8");
34452
+ } catch {}
34453
+ }
34454
+ var installed = false;
34455
+ function installCrashHandlers() {
34456
+ if (installed)
34457
+ return;
34458
+ installed = true;
34459
+ process.on("uncaughtException", (err) => {
34460
+ const entry = formatCrashEntry("uncaughtException", err);
34461
+ writeCrashEntry(CRASH_LOG_DIR, entry);
34462
+ process.stderr.write(`${t("env.crash_stderr", { type: entry.type, message: entry.message })}
34463
+ `);
34464
+ process.exit(1);
34465
+ });
34466
+ process.on("unhandledRejection", (reason) => {
34467
+ const entry = formatCrashEntry("unhandledRejection", reason);
34468
+ writeCrashEntry(CRASH_LOG_DIR, entry);
34469
+ process.stderr.write(`${t("env.crash_stderr", { type: entry.type, message: entry.message })}
34470
+ `);
34471
+ });
34472
+ }
34473
+
34359
34474
  // src/cli/main.ts
34360
34475
  function readVersion4() {
34361
- const here = dirname18(fileURLToPath6(import.meta.url));
34362
- const candidates = [join49(here, "..", "..", "package.json"), join49(here, "..", "package.json")];
34476
+ const here = dirname19(fileURLToPath7(import.meta.url));
34477
+ const candidates = [join51(here, "..", "..", "package.json"), join51(here, "..", "package.json")];
34363
34478
  for (const p of candidates) {
34364
- if (existsSync54(p)) {
34479
+ if (existsSync56(p)) {
34365
34480
  try {
34366
- const raw = JSON.parse(readFileSync36(p, "utf8"));
34481
+ const raw = JSON.parse(readFileSync38(p, "utf8"));
34367
34482
  if (raw.version)
34368
34483
  return raw.version;
34369
34484
  } catch {}
@@ -34388,6 +34503,7 @@ function startAutoUpdate(config) {
34388
34503
  }
34389
34504
  }
34390
34505
  async function main() {
34506
+ installCrashHandlers();
34391
34507
  const program2 = createProgram();
34392
34508
  program2.parse(process.argv);
34393
34509
  const cmdNames = new Set(program2.commands.map((c) => c.name()));
@@ -34447,15 +34563,15 @@ async function main() {
34447
34563
  await updater?.waitForIdle();
34448
34564
  process.exit(exitCode);
34449
34565
  } else {
34450
- const configPath = join49(homedir19(), ".mma", "config.json");
34451
- if (!existsSync54(configPath)) {
34566
+ const configPath = join51(homedir20(), ".mma", "config.json");
34567
+ if (!existsSync56(configPath)) {
34452
34568
  console.log(pc2.yellow(`
34453
34569
  ` + t("cli.first_run") + `
34454
34570
  `));
34455
34571
  const answers = await runSetup();
34456
34572
  const config2 = loadConfig({
34457
- configDir: join49(homedir19(), ".mma"),
34458
- projectConfigPath: projectDir ? join49(projectDir, ".mmrc") : join49(process.cwd(), ".mmrc")
34573
+ configDir: join51(homedir20(), ".mma"),
34574
+ projectConfigPath: projectDir ? join51(projectDir, ".mmrc") : join51(process.cwd(), ".mmrc")
34459
34575
  });
34460
34576
  config2.provider.type = answers.provider;
34461
34577
  config2.provider.baseUrl = answers.apiBase;
@@ -34505,10 +34621,11 @@ async function main() {
34505
34621
  pluginManager,
34506
34622
  configDir,
34507
34623
  baseDir,
34508
- logger
34624
+ logger,
34625
+ envReport
34509
34626
  } = await bootstrap(undefined, projectDir, noAgentsMd, exitOnComplete);
34510
34627
  startAutoUpdate(config);
34511
- const repl = new Repl(agent, config, sessionManager, skillsModule, pluginManager, configDir, baseDir, noAgentsMd, logger, true);
34628
+ const repl = new Repl(agent, config, sessionManager, skillsModule, pluginManager, configDir, baseDir, noAgentsMd, logger, true, envReport);
34512
34629
  await repl.start();
34513
34630
  }
34514
34631
  }