micro-models-agent 0.56.4 → 0.57.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 (3) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/main.js +463 -326
  3. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -2329,7 +2329,7 @@ var init_defaults = __esm(() => {
2329
2329
  maxToolIterations: 1000,
2330
2330
  stuckThreshold: 6,
2331
2331
  autoPlan: true,
2332
- showReasoning: false,
2332
+ showReasoning: true,
2333
2333
  logLevel: "info",
2334
2334
  locale: "en",
2335
2335
  session: {
@@ -2365,8 +2365,6 @@ var init_defaults = __esm(() => {
2365
2365
  },
2366
2366
  ui: {
2367
2367
  spinner: true,
2368
- toolStyle: "inline",
2369
- toolComments: true,
2370
2368
  showContextStats: false,
2371
2369
  showCompaction: true
2372
2370
  },
@@ -2401,8 +2399,8 @@ var init_defaults = __esm(() => {
2401
2399
  lsp: DEFAULT_LSP_CONFIG,
2402
2400
  updater: {
2403
2401
  enabled: true,
2404
- checkOnStart: true,
2405
- autoInstall: true,
2402
+ checkOnStart: false,
2403
+ autoInstall: false,
2406
2404
  intervalMs: 0
2407
2405
  },
2408
2406
  reasoning: {
@@ -2533,6 +2531,7 @@ The path was joined onto the working directory because it does not exist as give
2533
2531
  "tool.friendly.web_fetch": "Fetching page",
2534
2532
  "tool.friendly.web_browse": "Browsing page",
2535
2533
  "tool.friendly.download_file": "Downloading file",
2534
+ "tool.friendly.chunk_query": "Querying chunks",
2536
2535
  "tool.web_fetch_result": "Fetched page: {url} — {chars} chars, {lines} lines{truncated}",
2537
2536
  "tool.web_browse_result": "Browsed page: {url} — {chars} chars, {lines} lines{truncated}",
2538
2537
  "tool.web_search_result": 'Search results for "{query}" — {count} results',
@@ -3297,6 +3296,7 @@ var init_ru = __esm(() => {
3297
3296
  "tool.friendly.web_fetch": "Загрузка страницы",
3298
3297
  "tool.friendly.web_browse": "Просмотр страницы",
3299
3298
  "tool.friendly.download_file": "Скачивание файла",
3299
+ "tool.friendly.chunk_query": "Запрос чанков",
3300
3300
  "tool.web_fetch_result": "Загружена страница: {url} — {chars} симв., {lines} строк{truncated}",
3301
3301
  "tool.web_browse_result": "Просмотрена страница: {url} — {chars} симв., {lines} строк{truncated}",
3302
3302
  "tool.web_search_result": 'Результаты поиска "{query}" — {count} результатов',
@@ -13453,18 +13453,6 @@ function evaluateReasoningPolicy(input, state) {
13453
13453
  var DECAY_THRESHOLD = 5;
13454
13454
 
13455
13455
  // src/core/agent.ts
13456
- function isToolCallJson(text) {
13457
- const trimmed = text.trim();
13458
- if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
13459
- try {
13460
- JSON.parse(trimmed);
13461
- return true;
13462
- } catch {
13463
- return false;
13464
- }
13465
- }
13466
- return false;
13467
- }
13468
13456
  function toolOutputCharLimit(remainingBudget, historyBudget, bounded) {
13469
13457
  if (bounded)
13470
13458
  return Number.MAX_SAFE_INTEGER;
@@ -13687,6 +13675,10 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
13687
13675
  onPhase,
13688
13676
  signal: this.abortController.signal
13689
13677
  }) : await this.executeSingleAgentLoop(input, onChunk, onMeta, countTool, onPhase);
13678
+ const provenance = this.callerProvenance();
13679
+ result.provider = provenance.provider;
13680
+ result.model = provenance.model;
13681
+ result.durationMs = Date.now() - startedAt;
13690
13682
  emitTurnEnd(result);
13691
13683
  return result;
13692
13684
  } catch (err) {
@@ -13730,6 +13722,7 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
13730
13722
  let emptyResponseExhausted = false;
13731
13723
  let auditFailed = false;
13732
13724
  let lastAuditSummary = "";
13725
+ let totalLlmDuration = 0;
13733
13726
  let suppressRepetitionRetry = false;
13734
13727
  let repeatedToolCount = 0;
13735
13728
  const MAX_REPEATED_TOOL_CALLS = 2;
@@ -13868,6 +13861,8 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
13868
13861
  }
13869
13862
  textContent += chunk.content;
13870
13863
  textChunks.push(chunk.content);
13864
+ const textOut = pluginManager.runOnText({ iteration, logger, contextManager }, chunk.content);
13865
+ onChunk?.(textOut);
13871
13866
  }
13872
13867
  if (chunk.type === "reasoning" && chunk.content) {
13873
13868
  reasoningContent += chunk.content;
@@ -13930,6 +13925,7 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
13930
13925
  }
13931
13926
  apiCompletionChars += (textContent || reasoningContent).length;
13932
13927
  logger.logLLMResponse(config.model, (textContent || reasoningContent).length, Date.now() - llmStart, undefined, "agent");
13928
+ totalLlmDuration += Date.now() - llmStart;
13933
13929
  {
13934
13930
  const usagePrompt = apiPromptTokens - promptBefore;
13935
13931
  const usageCompletion = apiCompletionTokens - completionBefore;
@@ -13948,14 +13944,6 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
13948
13944
  if (this.shutdownRequested) {
13949
13945
  break;
13950
13946
  }
13951
- const toolComments = this.deps.config.ui?.toolComments ?? true;
13952
- const showText = textChunks.length > 0 && (!sawToolCall || toolComments && !isToolCallJson(textContent));
13953
- if (showText) {
13954
- for (const chunk of textChunks) {
13955
- const textOut = pluginManager.runOnText({ iteration, logger, contextManager }, chunk);
13956
- onChunk?.(textOut);
13957
- }
13958
- }
13959
13947
  let llmResponse = null;
13960
13948
  if (sawToolCall) {
13961
13949
  llmResponse = { type: "tool_call", calls: toolCalls };
@@ -14349,7 +14337,8 @@ ${warnLine}
14349
14337
  totalCost: this.costTracker.total,
14350
14338
  costBreakdown: this.costTracker.breakdown(),
14351
14339
  compactionCount: contextManager.getCompactionCount(),
14352
- contextQuality: contextManager.getQuality()
14340
+ contextQuality: contextManager.getQuality(),
14341
+ llmDurationMs: totalLlmDuration
14353
14342
  };
14354
14343
  }
14355
14344
  clearContext() {
@@ -15050,12 +15039,15 @@ class FactualCheck {
15050
15039
  for (const f of files)
15051
15040
  this.knownFiles.add(f);
15052
15041
  }
15053
- validate(response) {
15042
+ validate(response, deletedFiles) {
15054
15043
  const filePaths = this.extractFilePaths(response);
15055
15044
  if (filePaths.length === 0)
15056
15045
  return { status: "pass" };
15046
+ const deletedBasenames = deletedFiles ? new Set([...deletedFiles].map((p) => p.split(/[/\\]/).pop() ?? p)) : undefined;
15057
15047
  const nonExistent = [];
15058
15048
  for (const fp of filePaths) {
15049
+ if (deletedBasenames?.has(fp))
15050
+ continue;
15059
15051
  if (!this.pathExists(fp)) {
15060
15052
  nonExistent.push(fp);
15061
15053
  }
@@ -15303,7 +15295,8 @@ class HallucinationDetector {
15303
15295
  if (confidenceResult.status === "retry" || confidenceResult.status === "block") {
15304
15296
  return confidenceResult;
15305
15297
  }
15306
- const factualResult = this.factual?.validate(response);
15298
+ const deletedFiles = new Set(this.consistency.getDeletedFiles());
15299
+ const factualResult = this.factual?.validate(response, deletedFiles);
15307
15300
  if (factualResult && factualResult.status !== "pass") {
15308
15301
  return factualResult;
15309
15302
  }
@@ -16953,22 +16946,29 @@ class MCPClient {
16953
16946
  if (!url)
16954
16947
  throw new Error("SSE transport requires a url");
16955
16948
  this.abortController = new AbortController;
16956
- const response = await fetch(url, {
16957
- method: "GET",
16958
- headers: {
16959
- Accept: "text/event-stream",
16960
- ...this.config.headers
16961
- },
16962
- signal: this.abortController.signal
16963
- });
16964
- if (!response.ok) {
16965
- throw new Error(`SSE connection failed: ${response.status} ${response.statusText}`);
16949
+ const timeout = setTimeout(() => this.abortController?.abort(), this.config.timeout || HTTP_TIMEOUT_MS);
16950
+ try {
16951
+ const response = await fetch(url, {
16952
+ method: "GET",
16953
+ headers: {
16954
+ Accept: "text/event-stream",
16955
+ ...this.config.headers
16956
+ },
16957
+ signal: this.abortController.signal
16958
+ });
16959
+ clearTimeout(timeout);
16960
+ if (!response.ok) {
16961
+ throw new Error(`SSE connection failed: ${response.status} ${response.statusText}`);
16962
+ }
16963
+ this._connected = true;
16964
+ const reader = response.body.getReader();
16965
+ const decoder = new TextDecoder;
16966
+ let buffer = "";
16967
+ this.readSSE(reader, decoder, buffer);
16968
+ } catch (err) {
16969
+ clearTimeout(timeout);
16970
+ throw err;
16966
16971
  }
16967
- this._connected = true;
16968
- const reader = response.body.getReader();
16969
- const decoder = new TextDecoder;
16970
- let buffer = "";
16971
- this.readSSE(reader, decoder, buffer);
16972
16972
  }
16973
16973
  async readSSE(reader, decoder, buffer) {
16974
16974
  try {
@@ -17162,7 +17162,8 @@ class MCPClient {
17162
17162
  "Content-Type": "application/json",
17163
17163
  ...this.config.headers
17164
17164
  },
17165
- body: JSON.stringify(request)
17165
+ body: JSON.stringify(request),
17166
+ signal: AbortSignal.timeout(this.config.timeout || HTTP_TIMEOUT_MS)
17166
17167
  });
17167
17168
  if (!response.ok) {
17168
17169
  const text = await response.text().catch(() => "");
@@ -17248,7 +17249,8 @@ class MCPClient {
17248
17249
  "Content-Type": "application/json",
17249
17250
  ...this.config.headers
17250
17251
  },
17251
- body: JSON.stringify(request)
17252
+ body: JSON.stringify(request),
17253
+ signal: AbortSignal.timeout(this.config.timeout || HTTP_TIMEOUT_MS)
17252
17254
  });
17253
17255
  if (!response.ok) {
17254
17256
  const text = await response.text().catch(() => "");
@@ -17325,6 +17327,7 @@ class MCPClient {
17325
17327
  });
17326
17328
  }
17327
17329
  }
17330
+ var HTTP_TIMEOUT_MS = 1e4;
17328
17331
  var init_client = () => {};
17329
17332
 
17330
17333
  // src/modules/mcp/registry.ts
@@ -23978,9 +23981,11 @@ class MCPModule {
23978
23981
  config;
23979
23982
  name = "mcp";
23980
23983
  connections = new Map;
23984
+ serverConfigs = new Map;
23981
23985
  discovered = [];
23982
23986
  initialized = false;
23983
23987
  initError = null;
23988
+ failedServers = new Set;
23984
23989
  constructor(config) {
23985
23990
  this.config = config;
23986
23991
  }
@@ -24007,13 +24012,58 @@ class MCPModule {
24007
24012
  registry2.register(serverConfig);
24008
24013
  }
24009
24014
  for (const serverName of registry2.list()) {
24010
- const serverConfig = registry2.get(serverName);
24015
+ this.serverConfigs.set(serverName, registry2.get(serverName));
24016
+ }
24017
+ this.discoverAllTools();
24018
+ }
24019
+ async discoverAllTools() {
24020
+ for (const [serverName, serverConfig] of this.serverConfigs) {
24021
+ if (this.failedServers.has(serverName))
24022
+ continue;
24011
24023
  const client = new MCPClient(serverConfig);
24012
24024
  try {
24013
- await client.connect();
24014
- const tools = await client.listTools();
24015
- this.connections.set(serverName, client);
24016
- for (const tool of tools) {
24025
+ await Promise.race([
24026
+ (async () => {
24027
+ await client.connect();
24028
+ const tools = await client.listTools();
24029
+ this.connections.set(serverName, client);
24030
+ for (const tool of tools) {
24031
+ this.discovered.push({
24032
+ serverName,
24033
+ toolName: tool.name,
24034
+ description: tool.description || `Tool on MCP server "${serverName}"`,
24035
+ inputSchema: tool.inputSchema || {}
24036
+ });
24037
+ }
24038
+ })(),
24039
+ new Promise((_, reject) => setTimeout(() => reject(new Error("discovery timeout")), DISCOVERY_TIMEOUT_MS))
24040
+ ]);
24041
+ } catch (e) {
24042
+ this.failedServers.add(serverName);
24043
+ this.initError = `MCP server "${serverName}" init failed: ${e.message}`;
24044
+ await client.disconnect().catch((err) => {
24045
+ logger3.warn(`cleanup disconnect for "${serverName}" failed`, { error: String(err) });
24046
+ });
24047
+ }
24048
+ }
24049
+ }
24050
+ async ensureConnected(serverName) {
24051
+ const existing = this.connections.get(serverName);
24052
+ if (existing?.isConnected())
24053
+ return existing;
24054
+ if (this.failedServers.has(serverName))
24055
+ return null;
24056
+ const serverConfig = this.serverConfigs.get(serverName);
24057
+ if (!serverConfig)
24058
+ return null;
24059
+ const client = new MCPClient(serverConfig);
24060
+ try {
24061
+ await client.connect();
24062
+ const tools = await client.listTools();
24063
+ this.connections.set(serverName, client);
24064
+ for (const tool of tools) {
24065
+ const alreadyDiscovered = this.discovered.some((d) => d.serverName === serverName && d.toolName === tool.name);
24066
+ if (!alreadyDiscovered) {
24017
24067
  this.discovered.push({
24018
24068
  serverName,
24019
24069
  toolName: tool.name,
@@ -24021,16 +24071,18 @@ class MCPModule {
24021
24071
  inputSchema: tool.inputSchema || {}
24022
24072
  });
24023
24073
  }
24024
- } catch (e) {
24025
- this.initError = `MCP server "${serverName}" init failed: ${e.message}`;
24026
- await client.disconnect().catch((err) => {
24027
- logger3.warn(`cleanup disconnect for "${serverName}" failed`, { error: String(err) });
24028
- });
24029
24074
  }
24075
+ return client;
24076
+ } catch (e) {
24077
+ this.failedServers.add(serverName);
24078
+ logger3.warn(`MCP connect failed for "${serverName}": ${e.message}`);
24079
+ await client.disconnect().catch(() => {});
24080
+ return null;
24030
24081
  }
24031
24082
  }
24032
24083
  getSystemPromptBlock() {
24033
- if (this.discovered.length === 0)
24084
+ const serverNames = [...this.serverConfigs.keys()];
24085
+ if (serverNames.length === 0)
24034
24086
  return null;
24035
24087
  const lines = ["---", "MCP servers available:"];
24036
24088
  const byServer = new Map;
@@ -24039,11 +24091,16 @@ class MCPModule {
24039
24091
  list.push(d);
24040
24092
  byServer.set(d.serverName, list);
24041
24093
  }
24042
- for (const [server, tools] of byServer) {
24043
- lines.push(` [${server}]`);
24044
- for (const t2 of tools) {
24045
- const toolRef = sanitizeToolName(server, t2.toolName);
24046
- lines.push(` - ${toolRef}: ${t2.description}`);
24094
+ for (const serverName of serverNames) {
24095
+ lines.push(` [${serverName}]`);
24096
+ const tools = byServer.get(serverName);
24097
+ if (tools && tools.length > 0) {
24098
+ for (const t2 of tools) {
24099
+ const toolRef = sanitizeToolName(serverName, t2.toolName);
24100
+ lines.push(` - ${toolRef}: ${t2.description}`);
24101
+ }
24102
+ } else {
24103
+ lines.push(` (not yet connected — use mcp__${serverName}__connect to discover tools)`);
24047
24104
  }
24048
24105
  }
24049
24106
  lines.push("---");
@@ -24056,33 +24113,60 @@ class MCPModule {
24056
24113
  };
24057
24114
  }
24058
24115
  getToolDefinitions() {
24059
- return this.discovered.map((d) => ({
24060
- name: sanitizeToolName(d.serverName, d.toolName),
24061
- description: `${d.description} [MCP server: ${d.serverName}]`,
24062
- parameters: convertInputSchema(d.inputSchema),
24063
- tags: ["code", "research"],
24064
- handler: async (_ctx, args) => {
24065
- const client = this.connections.get(d.serverName);
24066
- if (!client) {
24067
- return {
24068
- success: false,
24069
- output: `MCP server "${d.serverName}" not connected`
24070
- };
24116
+ const defs = [];
24117
+ for (const d of this.discovered) {
24118
+ defs.push({
24119
+ name: sanitizeToolName(d.serverName, d.toolName),
24120
+ description: `${d.description} [MCP server: ${d.serverName}]`,
24121
+ parameters: convertInputSchema(d.inputSchema),
24122
+ tags: ["code", "research"],
24123
+ handler: async (_ctx, args) => {
24124
+ const client = this.connections.get(d.serverName);
24125
+ if (!client?.isConnected()) {
24126
+ return {
24127
+ success: false,
24128
+ output: `MCP server "${d.serverName}" not connected`
24129
+ };
24130
+ }
24131
+ try {
24132
+ const result = await client.callTool(d.toolName, args);
24133
+ return {
24134
+ success: true,
24135
+ output: typeof result === "string" ? result : JSON.stringify(result, null, 2)
24136
+ };
24137
+ } catch (e) {
24138
+ return { success: false, output: `MCP call failed: ${e.message}` };
24139
+ }
24071
24140
  }
24072
- try {
24073
- if (!client.isConnected()) {
24074
- await client.connect();
24141
+ });
24142
+ }
24143
+ for (const [serverName] of this.serverConfigs) {
24144
+ if (this.failedServers.has(serverName))
24145
+ continue;
24146
+ const alreadyDiscovered = this.discovered.some((d) => d.serverName === serverName);
24147
+ if (alreadyDiscovered)
24148
+ continue;
24149
+ defs.push({
24150
+ name: sanitizeToolName(serverName, "connect"),
24151
+ description: `Connect to MCP server "${serverName}" and discover its tools`,
24152
+ parameters: { type: "object", properties: {} },
24153
+ tags: ["code", "research"],
24154
+ handler: async (_ctx, _args) => {
24155
+ const client = await this.ensureConnected(serverName);
24156
+ if (!client) {
24157
+ return { success: false, output: `MCP server "${serverName}" connection failed` };
24075
24158
  }
24076
- const result = await client.callTool(d.toolName, args);
24159
+ const tools = this.discovered.filter((d) => d.serverName === serverName).map((d) => ` - ${sanitizeToolName(serverName, d.toolName)}: ${d.description}`);
24077
24160
  return {
24078
24161
  success: true,
24079
- output: typeof result === "string" ? result : JSON.stringify(result, null, 2)
24162
+ output: tools.length > 0 ? `Connected to "${serverName}". Tools:
24163
+ ${tools.join(`
24164
+ `)}` : `Connected to "${serverName}" (no tools discovered)`
24080
24165
  };
24081
- } catch (e) {
24082
- return { success: false, output: `MCP call failed: ${e.message}` };
24083
24166
  }
24084
- }
24085
- }));
24167
+ });
24168
+ }
24169
+ return defs;
24086
24170
  }
24087
24171
  getPlugin() {
24088
24172
  return {
@@ -24100,7 +24184,7 @@ class MCPModule {
24100
24184
  };
24101
24185
  }
24102
24186
  }
24103
- var logger3;
24187
+ var logger3, DISCOVERY_TIMEOUT_MS = 5000;
24104
24188
  var init_module7 = __esm(() => {
24105
24189
  init_client();
24106
24190
  init_app_logger();
@@ -24580,6 +24664,12 @@ __export(exports_probe, {
24580
24664
  getCachedProbeResult: () => getCachedProbeResult,
24581
24665
  cacheKey: () => cacheKey
24582
24666
  });
24667
+ import { existsSync as existsSync50, readFileSync as readFileSync31, writeFileSync as writeFileSync19, mkdirSync as mkdirSync20 } from "fs";
24668
+ import { join as join42, dirname as dirname18 } from "path";
24669
+ import { homedir as homedir14 } from "os";
24670
+ function cachePath() {
24671
+ return join42(homedir14(), ".mma", "reasoning-cache.json");
24672
+ }
24583
24673
  async function probeReasoningSupport(provider, strategy, signal) {
24584
24674
  if (strategy === "none")
24585
24675
  return false;
@@ -24602,20 +24692,58 @@ function cacheKey(baseUrl, model) {
24602
24692
  return `${baseUrl}|${model}`;
24603
24693
  }
24604
24694
  function getCachedProbeResult(key) {
24605
- return probeCache.get(key);
24695
+ const mem = memCache.get(key);
24696
+ if (mem && Date.now() - mem.ts < CACHE_TTL_MS) {
24697
+ return mem.result;
24698
+ }
24699
+ const disk = readDiskCache();
24700
+ const entry = disk[key];
24701
+ if (entry) {
24702
+ const age = Date.now() - new Date(entry.ts).getTime();
24703
+ if (age < CACHE_TTL_MS) {
24704
+ memCache.set(key, { result: entry.result, ts: Date.now() });
24705
+ return entry.result;
24706
+ }
24707
+ }
24708
+ return;
24606
24709
  }
24607
24710
  function setCachedProbeResult(key, result) {
24608
- probeCache.set(key, result);
24711
+ const now = new Date().toISOString();
24712
+ memCache.set(key, { result, ts: Date.now() });
24713
+ const disk = readDiskCache();
24714
+ disk[key] = { result, ts: now };
24715
+ writeDiskCache(disk);
24609
24716
  }
24610
24717
  function resetProbeCache() {
24611
- probeCache.clear();
24718
+ memCache.clear();
24719
+ const path = cachePath();
24720
+ if (existsSync50(path)) {
24721
+ writeFileSync19(path, "{}", "utf-8");
24722
+ }
24723
+ }
24724
+ function readDiskCache() {
24725
+ try {
24726
+ const path = cachePath();
24727
+ if (existsSync50(path)) {
24728
+ return JSON.parse(readFileSync31(path, "utf-8"));
24729
+ }
24730
+ } catch {}
24731
+ return {};
24612
24732
  }
24613
- var PROBE_MESSAGES, probeCache;
24733
+ function writeDiskCache(data) {
24734
+ try {
24735
+ const path = cachePath();
24736
+ mkdirSync20(dirname18(path), { recursive: true });
24737
+ writeFileSync19(path, JSON.stringify(data, null, 2), "utf-8");
24738
+ } catch {}
24739
+ }
24740
+ var PROBE_MESSAGES, CACHE_TTL_MS, memCache;
24614
24741
  var init_probe = __esm(() => {
24615
24742
  PROBE_MESSAGES = [
24616
24743
  { role: "user", content: "Reply with exactly: ok" }
24617
24744
  ];
24618
- probeCache = new Map;
24745
+ CACHE_TTL_MS = 24 * 60 * 60 * 1000;
24746
+ memCache = new Map;
24619
24747
  });
24620
24748
 
24621
24749
  // src/tools/set-thinking.ts
@@ -24697,9 +24825,9 @@ __export(exports_bootstrap, {
24697
24825
  buildSystemInfo: () => buildSystemInfo,
24698
24826
  bootstrap: () => bootstrap
24699
24827
  });
24700
- import { homedir as homedir14 } from "os";
24701
- import { join as join42, resolve as resolve22 } from "path";
24702
- import { existsSync as existsSync50, readFileSync as readFileSync31, writeFileSync as writeFileSync19 } from "fs";
24828
+ import { homedir as homedir15 } from "os";
24829
+ import { join as join43, resolve as resolve22 } from "path";
24830
+ import { existsSync as existsSync51, readFileSync as readFileSync32, writeFileSync as writeFileSync20 } from "fs";
24703
24831
  function buildSystemInfo(config, baseDir, profileCompressed) {
24704
24832
  const now = new Date().toISOString().replace("T", " ").slice(0, 19);
24705
24833
  const isWin = profileCompressed.toLowerCase().includes("win32");
@@ -24752,8 +24880,8 @@ function buildSystemInfo(config, baseDir, profileCompressed) {
24752
24880
  `);
24753
24881
  }
24754
24882
  async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete, reasoningLevel) {
24755
- const dir = configDir || process.env.MMA_CONFIG_DIR || join42(homedir14(), ".mma");
24756
- const projectConfigPath = projectDir ? join42(projectDir, ".mmrc") : join42(process.cwd(), ".mmrc");
24883
+ const dir = configDir || process.env.MMA_CONFIG_DIR || join43(homedir15(), ".mma");
24884
+ const projectConfigPath = projectDir ? join43(projectDir, ".mmrc") : join43(process.cwd(), ".mmrc");
24757
24885
  const { config, legacyDetected } = loadConfig({ configDir: dir, projectConfigPath });
24758
24886
  setLocale(config.locale);
24759
24887
  if (reasoningLevel && reasoningLevel !== "auto") {
@@ -24769,7 +24897,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete, reas
24769
24897
  }
24770
24898
  } catch {}
24771
24899
  const logger4 = new Logger(config.logLevel);
24772
- logger4.setLogDir(join42(dir, "logs"));
24900
+ logger4.setLogDir(join43(dir, "logs"));
24773
24901
  logger4.debug("MMA bootstrap", {
24774
24902
  version: config.version,
24775
24903
  model: config.model
@@ -24798,7 +24926,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete, reas
24798
24926
  logger4.info(`Model ${config.model} loaded in ${loadResult.loadTime}s`);
24799
24927
  }
24800
24928
  }
24801
- const profile = new UserProfile(join42(dir));
24929
+ const profile = new UserProfile(join43(dir));
24802
24930
  profile.load() || profile.collect();
24803
24931
  profile.save();
24804
24932
  const providerManager = new ProviderManager(config.provider, {
@@ -24848,7 +24976,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete, reas
24848
24976
  for (const warning of envReport.warnings) {
24849
24977
  logger4.warn(warning);
24850
24978
  }
24851
- const projectMapCacheDir = join42(baseDir, ".mma");
24979
+ const projectMapCacheDir = join43(baseDir, ".mma");
24852
24980
  const indexerModule = new IndexerModule({
24853
24981
  baseDir,
24854
24982
  cacheDir: projectMapCacheDir
@@ -24859,9 +24987,9 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete, reas
24859
24987
  logger4.warn(`Project indexing failed: ${err.message}`);
24860
24988
  }
24861
24989
  const skillsLoader = new SkillsLoader;
24862
- const builtinDir = join42(import.meta.dirname, "skills", "builtin");
24863
- const globalDir = join42(homedir14(), ".agents", "skills");
24864
- const projectSkillsDir = join42(baseDir, ".mma", "skills");
24990
+ const builtinDir = join43(import.meta.dirname, "skills", "builtin");
24991
+ const globalDir = join43(homedir15(), ".agents", "skills");
24992
+ const projectSkillsDir = join43(baseDir, ".mma", "skills");
24865
24993
  const availableSkills = skillsLoader.loadFromAllSources(builtinDir, globalDir, projectSkillsDir);
24866
24994
  const skillsBudget = Math.floor(config.contextWindow * config.skills.budget);
24867
24995
  const skillsModule = new SkillsModule(availableSkills, skillsBudget);
@@ -24877,11 +25005,11 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete, reas
24877
25005
  essential: true,
24878
25006
  estimatedTokens: Math.ceil(systemInfoContent.length / 4)
24879
25007
  };
24880
- const agentsMdGlobal = join42(dir, "AGENTS.md");
24881
- if (!existsSync50(agentsMdGlobal)) {
24882
- writeFileSync19(agentsMdGlobal, "", "utf-8");
25008
+ const agentsMdGlobal = join43(dir, "AGENTS.md");
25009
+ if (!existsSync51(agentsMdGlobal)) {
25010
+ writeFileSync20(agentsMdGlobal, "", "utf-8");
24883
25011
  }
24884
- const sessionDir = join42(dir, "sessions");
25012
+ const sessionDir = join43(dir, "sessions");
24885
25013
  const sessionStore = new SessionStore(sessionDir);
24886
25014
  sessionStore.init();
24887
25015
  const sessionManager = new SessionManager(sessionStore, {
@@ -24955,7 +25083,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete, reas
24955
25083
  const mcpModule = new MCPModule(config);
24956
25084
  await mcpModule.initialize();
24957
25085
  moduleRegistry.register(mcpModule);
24958
- const memoryStore = new MemoryStore(join42(dir, "memory"));
25086
+ const memoryStore = new MemoryStore(join43(dir, "memory"));
24959
25087
  const memoryModule = new MemoryModule(memoryStore);
24960
25088
  moduleRegistry.register(memoryModule);
24961
25089
  if (config.browser.enabled) {
@@ -25009,8 +25137,8 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete, reas
25009
25137
  pluginManager.register(plugin);
25010
25138
  pluginManager.register(plugin2);
25011
25139
  const pluginLoader = new PluginLoader;
25012
- const globalPluginsDir = join42(homedir14(), ".mma", "plugins");
25013
- const projectPluginsDir = join42(baseDir, ".mma", "plugins");
25140
+ const globalPluginsDir = join43(homedir15(), ".mma", "plugins");
25141
+ const projectPluginsDir = join43(baseDir, ".mma", "plugins");
25014
25142
  const mmaVersion = readMmaVersion();
25015
25143
  pluginLoader.loadFromDir(globalPluginsDir, pluginManager, logger4, {
25016
25144
  source: "global",
@@ -25036,13 +25164,13 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete, reas
25036
25164
  const skipAgentsMd = noAgentsMd === true;
25037
25165
  if (!skipAgentsMd) {
25038
25166
  const agentsMdCandidates = [
25039
- join42(baseDir, "AGENTS.md"),
25040
- join42(baseDir, ".mma", "AGENTS.md"),
25041
- join42(dir, "AGENTS.md")
25167
+ join43(baseDir, "AGENTS.md"),
25168
+ join43(baseDir, ".mma", "AGENTS.md"),
25169
+ join43(dir, "AGENTS.md")
25042
25170
  ];
25043
25171
  for (const p of agentsMdCandidates) {
25044
- if (existsSync50(p)) {
25045
- const content = readFileSync31(p, "utf-8").trim();
25172
+ if (existsSync51(p)) {
25173
+ const content = readFileSync32(p, "utf-8").trim();
25046
25174
  if (content) {
25047
25175
  agentsMdBlocks.push({
25048
25176
  content,
@@ -33428,8 +33556,8 @@ var init_scenarios = __esm(() => {
33428
33556
  });
33429
33557
 
33430
33558
  // src/modules/certification/loader.ts
33431
- import { existsSync as existsSync52, readdirSync as readdirSync17, readFileSync as readFileSync33 } from "fs";
33432
- import { join as join45 } from "path";
33559
+ import { existsSync as existsSync53, readdirSync as readdirSync17, readFileSync as readFileSync34 } from "fs";
33560
+ import { join as join46 } from "path";
33433
33561
  function validateScenario(s) {
33434
33562
  const errors2 = [];
33435
33563
  const isSkip = s.mode === "skip";
@@ -33481,12 +33609,12 @@ function loadScenarios(userDir) {
33481
33609
  else
33482
33610
  scenarios.push(s);
33483
33611
  }
33484
- if (userDir && existsSync52(userDir)) {
33612
+ if (userDir && existsSync53(userDir)) {
33485
33613
  for (const file of readdirSync17(userDir)) {
33486
33614
  if (!file.endsWith(".yaml") && !file.endsWith(".yml"))
33487
33615
  continue;
33488
33616
  try {
33489
- const raw = readFileSync33(join45(userDir, file), "utf-8");
33617
+ const raw = readFileSync34(join46(userDir, file), "utf-8");
33490
33618
  const data = $parse(raw);
33491
33619
  const parsed = normalizeScenario(data, file);
33492
33620
  const errs = validateScenario(parsed);
@@ -33549,8 +33677,8 @@ var init_loader3 = __esm(() => {
33549
33677
  });
33550
33678
 
33551
33679
  // src/modules/certification/fact-checker.ts
33552
- import { existsSync as existsSync53, readFileSync as readFileSync34, statSync as statSync9 } from "fs";
33553
- import { join as join46 } from "path";
33680
+ import { existsSync as existsSync54, readFileSync as readFileSync35, statSync as statSync9 } from "fs";
33681
+ import { join as join47 } from "path";
33554
33682
  function checkSandbox(sandboxDir, checks, exitCode, output) {
33555
33683
  const failures = [];
33556
33684
  for (const check of checks) {
@@ -33567,16 +33695,16 @@ function runCheck2(sandboxDir, check, exitCode, output) {
33567
33695
  case "outputContains":
33568
33696
  return output.includes(check.text);
33569
33697
  case "fileExists":
33570
- return isFile(join46(sandboxDir, check.path));
33698
+ return isFile(join47(sandboxDir, check.path));
33571
33699
  case "fileNotExists":
33572
- return !existsSync53(join46(sandboxDir, check.path));
33700
+ return !existsSync54(join47(sandboxDir, check.path));
33573
33701
  case "dirExists":
33574
- return isDir(join46(sandboxDir, check.path));
33702
+ return isDir(join47(sandboxDir, check.path));
33575
33703
  case "fileContent": {
33576
- const abs = join46(sandboxDir, check.path);
33704
+ const abs = join47(sandboxDir, check.path);
33577
33705
  if (!isFile(abs))
33578
33706
  return false;
33579
- const content = readFileSync34(abs, "utf-8");
33707
+ const content = readFileSync35(abs, "utf-8");
33580
33708
  if (check.contains !== undefined)
33581
33709
  return content.includes(check.contains);
33582
33710
  if (check.equals !== undefined)
@@ -33584,10 +33712,10 @@ function runCheck2(sandboxDir, check, exitCode, output) {
33584
33712
  return false;
33585
33713
  }
33586
33714
  case "fileRegex": {
33587
- const abs = join46(sandboxDir, check.path);
33715
+ const abs = join47(sandboxDir, check.path);
33588
33716
  if (!isFile(abs))
33589
33717
  return false;
33590
- return new RegExp(check.pattern).test(readFileSync34(abs, "utf-8"));
33718
+ return new RegExp(check.pattern).test(readFileSync35(abs, "utf-8"));
33591
33719
  }
33592
33720
  default:
33593
33721
  return false;
@@ -33595,14 +33723,14 @@ function runCheck2(sandboxDir, check, exitCode, output) {
33595
33723
  }
33596
33724
  function isFile(p) {
33597
33725
  try {
33598
- return existsSync53(p) && statSync9(p).isFile();
33726
+ return existsSync54(p) && statSync9(p).isFile();
33599
33727
  } catch {
33600
33728
  return false;
33601
33729
  }
33602
33730
  }
33603
33731
  function isDir(p) {
33604
33732
  try {
33605
- return existsSync53(p) && statSync9(p).isDirectory();
33733
+ return existsSync54(p) && statSync9(p).isDirectory();
33606
33734
  } catch {
33607
33735
  return false;
33608
33736
  }
@@ -33633,8 +33761,8 @@ var init_fact_checker = () => {};
33633
33761
 
33634
33762
  // src/modules/certification/runner.ts
33635
33763
  import { spawn as spawn10 } from "child_process";
33636
- import { existsSync as existsSync54, mkdirSync as mkdirSync20, rmSync as rmSync4, cpSync as cpSync2, writeFileSync as writeFileSync20, readdirSync as readdirSync18, readFileSync as readFileSync35 } from "fs";
33637
- import { join as join47, resolve as resolve23, dirname as dirname20, relative as relative7 } from "path";
33764
+ import { existsSync as existsSync55, mkdirSync as mkdirSync21, rmSync as rmSync4, cpSync as cpSync2, writeFileSync as writeFileSync21, readdirSync as readdirSync18, readFileSync as readFileSync36 } from "fs";
33765
+ import { join as join48, resolve as resolve23, dirname as dirname21, relative as relative7 } from "path";
33638
33766
  async function runScenario(scenario, opts) {
33639
33767
  if (scenario.mode === "skip") {
33640
33768
  return {
@@ -33654,7 +33782,7 @@ async function runScenario(scenario, opts) {
33654
33782
  let firstError;
33655
33783
  let lastFailedSandbox;
33656
33784
  for (let i = 1;i <= reps; i++) {
33657
- const sandbox = join47(opts.sandboxBase, `run-${scenario.id}-${i}`);
33785
+ const sandbox = join48(opts.sandboxBase, `run-${scenario.id}-${i}`);
33658
33786
  let failures = [];
33659
33787
  let exitCode = -1;
33660
33788
  let output = "";
@@ -33678,9 +33806,9 @@ async function runScenario(scenario, opts) {
33678
33806
  env3.MMA_PROVIDER_APIKEY = opts.providerKey;
33679
33807
  if (scenario.config && opts.baseConfig) {
33680
33808
  const merged = deepMergeAny(opts.baseConfig, scenario.config);
33681
- const certConfigDir = join47(sandbox, ".mma");
33682
- mkdirSync20(certConfigDir, { recursive: true });
33683
- writeFileSync20(join47(certConfigDir, "config.json"), JSON.stringify(merged, null, 2), "utf-8");
33809
+ const certConfigDir = join48(sandbox, ".mma");
33810
+ mkdirSync21(certConfigDir, { recursive: true });
33811
+ writeFileSync21(join48(certConfigDir, "config.json"), JSON.stringify(merged, null, 2), "utf-8");
33684
33812
  env3.MMA_CONFIG_DIR = certConfigDir;
33685
33813
  }
33686
33814
  const res = await runner(env3, opts.mmaRoot, args, timeoutMs);
@@ -33725,14 +33853,14 @@ ${res.stderr}`;
33725
33853
  }
33726
33854
  function prepareSandbox(sandbox, scenario, mmaRoot) {
33727
33855
  rmSync4(sandbox, { recursive: true, force: true });
33728
- mkdirSync20(sandbox, { recursive: true });
33856
+ mkdirSync21(sandbox, { recursive: true });
33729
33857
  for (const f of scenario.fixtures ?? []) {
33730
- const src = join47(mmaRoot, f.source);
33731
- if (!existsSync54(src)) {
33858
+ const src = join48(mmaRoot, f.source);
33859
+ if (!existsSync55(src)) {
33732
33860
  throw new Error(`fixture missing: ${f.source}`);
33733
33861
  }
33734
- const dest = join47(sandbox, f.dest);
33735
- mkdirSync20(dirname20(dest), { recursive: true });
33862
+ const dest = join48(sandbox, f.dest);
33863
+ mkdirSync21(dirname21(dest), { recursive: true });
33736
33864
  cpSync2(src, dest);
33737
33865
  }
33738
33866
  }
@@ -33744,10 +33872,10 @@ function collectDiagnostics(sandbox) {
33744
33872
  } else {
33745
33873
  lines.push(" Files created: (none)");
33746
33874
  }
33747
- const planPath = join47(sandbox, ".mma", "plans", "active.json");
33748
- if (existsSync54(planPath)) {
33875
+ const planPath = join48(sandbox, ".mma", "plans", "active.json");
33876
+ if (existsSync55(planPath)) {
33749
33877
  try {
33750
- const plan = JSON.parse(readFileSync35(planPath, "utf-8"));
33878
+ const plan = JSON.parse(readFileSync36(planPath, "utf-8"));
33751
33879
  const steps = plan.steps ?? [];
33752
33880
  const done = steps.filter((s) => s.status === "done").length;
33753
33881
  const pending = steps.filter((s) => s.status === "pending" || s.status === "in_progress");
@@ -33766,7 +33894,7 @@ function listFiles(dir, root) {
33766
33894
  for (const entry of readdirSync18(dir, { withFileTypes: true })) {
33767
33895
  if (entry.name === ".mma")
33768
33896
  continue;
33769
- const abs = join47(dir, entry.name);
33897
+ const abs = join48(dir, entry.name);
33770
33898
  const rel = toForwardSlash(relative7(root, abs));
33771
33899
  if (entry.isDirectory()) {
33772
33900
  result.push(...listFiles(abs, root));
@@ -33778,15 +33906,15 @@ function listFiles(dir, root) {
33778
33906
  return result;
33779
33907
  }
33780
33908
  function resolveMmaEntry(mmaRoot) {
33781
- const dev = join47(mmaRoot, "src", "cli", "main.ts");
33782
- if (existsSync54(dev))
33909
+ const dev = join48(mmaRoot, "src", "cli", "main.ts");
33910
+ if (existsSync55(dev))
33783
33911
  return dev;
33784
- return join47(mmaRoot, "dist", "main.js");
33912
+ return join48(mmaRoot, "dist", "main.js");
33785
33913
  }
33786
33914
  function findMmaRoot(fromDir) {
33787
33915
  const candidates = [resolve23(fromDir, "..", "..", ".."), resolve23(fromDir, "..")];
33788
33916
  for (const c of candidates) {
33789
- if (existsSync54(join47(c, "package.json")))
33917
+ if (existsSync55(join48(c, "package.json")))
33790
33918
  return c;
33791
33919
  }
33792
33920
  return process.cwd();
@@ -33853,16 +33981,16 @@ __export(exports_cli, {
33853
33981
  certStatus: () => certStatus,
33854
33982
  certList: () => certList
33855
33983
  });
33856
- import { rmSync as rmSync5, writeFileSync as writeFileSync21 } from "fs";
33857
- import { join as join48, dirname as dirname21 } from "path";
33984
+ import { rmSync as rmSync5, writeFileSync as writeFileSync22 } from "fs";
33985
+ import { join as join49, dirname as dirname22 } from "path";
33858
33986
  import { fileURLToPath as fileURLToPath5 } from "url";
33859
- import { existsSync as existsSync55, readFileSync as readFileSync36 } from "fs";
33987
+ import { existsSync as existsSync56, readFileSync as readFileSync37 } from "fs";
33860
33988
  function readVersion() {
33861
- const candidates = [join48(MMA_ROOT, "package.json")];
33989
+ const candidates = [join49(MMA_ROOT, "package.json")];
33862
33990
  for (const p of candidates) {
33863
- if (existsSync55(p)) {
33991
+ if (existsSync56(p)) {
33864
33992
  try {
33865
- const raw = JSON.parse(readFileSync36(p, "utf-8"));
33993
+ const raw = JSON.parse(readFileSync37(p, "utf-8"));
33866
33994
  if (raw.version)
33867
33995
  return raw.version;
33868
33996
  } catch {}
@@ -33875,7 +34003,7 @@ function parseTags(s) {
33875
34003
  }
33876
34004
  async function certify(opts) {
33877
34005
  const providerUrl = opts.providerUrl || opts.config.provider.baseUrl;
33878
- const { scenarios, errors: errors2 } = loadScenarios(join48(opts.projectDir, ".mma", "certification", "scenarios"));
34006
+ const { scenarios, errors: errors2 } = loadScenarios(join49(opts.projectDir, ".mma", "certification", "scenarios"));
33879
34007
  for (const e of errors2)
33880
34008
  console.error(pc2.yellow(` ${e}`));
33881
34009
  let selected = filterByTags(scenarios, opts.tags);
@@ -33906,7 +34034,7 @@ async function certify(opts) {
33906
34034
  return;
33907
34035
  }
33908
34036
  console.log(t("cli.cert_started", { model: opts.name, provider: providerUrl }));
33909
- const sandboxBase = join48(process.cwd(), ".mma", "certification");
34037
+ const sandboxBase = join49(process.cwd(), ".mma", "certification");
33910
34038
  const results = [];
33911
34039
  const total = selected.length;
33912
34040
  let idx = 0;
@@ -34039,10 +34167,10 @@ function printResults(results) {
34039
34167
  }
34040
34168
  }
34041
34169
  function writeReport(entry, projectDir) {
34042
- const reportDir = join48(projectDir, "certification");
34170
+ const reportDir = join49(projectDir, "certification");
34043
34171
  const ts = entry.certifiedAt.replace(/[:.]/g, "-").slice(0, 19);
34044
34172
  const filename = `report-${entry.model.replace(/[/\\:]/g, "_")}-${ts}.json`;
34045
- const reportPath = join48(reportDir, filename);
34173
+ const reportPath = join49(reportDir, filename);
34046
34174
  const report = {
34047
34175
  model: entry.model,
34048
34176
  providerUrl: entry.providerUrl,
@@ -34061,7 +34189,7 @@ function writeReport(entry, projectDir) {
34061
34189
  }))
34062
34190
  };
34063
34191
  try {
34064
- writeFileSync21(reportPath, JSON.stringify(report, null, 2), "utf-8");
34192
+ writeFileSync22(reportPath, JSON.stringify(report, null, 2), "utf-8");
34065
34193
  console.log(pc2.dim(`
34066
34194
  Report: ${reportPath}`));
34067
34195
  } catch (e) {
@@ -34075,7 +34203,7 @@ var init_cli = __esm(() => {
34075
34203
  init_loader3();
34076
34204
  init_runner2();
34077
34205
  init_manifest();
34078
- HERE = dirname21(fileURLToPath5(import.meta.url));
34206
+ HERE = dirname22(fileURLToPath5(import.meta.url));
34079
34207
  MMA_ROOT = findMmaRoot(HERE);
34080
34208
  });
34081
34209
 
@@ -34085,8 +34213,8 @@ __export(exports_repl_commands, {
34085
34213
  registerAllCommands: () => registerAllCommands,
34086
34214
  COMMAND_GROUPS: () => COMMAND_GROUPS
34087
34215
  });
34088
- import { join as join50, dirname as dirname23 } from "path";
34089
- import { existsSync as existsSync57 } from "fs";
34216
+ import { join as join51, dirname as dirname24 } from "path";
34217
+ import { existsSync as existsSync58 } from "fs";
34090
34218
  function registerAllCommands(ctx) {
34091
34219
  registerBuiltinCommands(ctx);
34092
34220
  registerMmaCommands(ctx);
@@ -34143,7 +34271,7 @@ function registerMmaCommands(ctx) {
34143
34271
  }
34144
34272
  try {
34145
34273
  const { loadFileAsDataUrl: loadFileAsDataUrl2, loadUrlAsDataUrl: loadUrlAsDataUrl2, readClipboardImage: readClipboardImage2 } = await Promise.resolve().then(() => (init_image_utils(), exports_image_utils));
34146
- const { existsSync: existsSync58 } = await import("fs");
34274
+ const { existsSync: existsSync59 } = await import("fs");
34147
34275
  const { resolve: resolve24 } = await import("path");
34148
34276
  let dataUrl;
34149
34277
  let label;
@@ -34163,7 +34291,7 @@ function registerMmaCommands(ctx) {
34163
34291
  label = source;
34164
34292
  } else {
34165
34293
  const absPath = resolve24(process.cwd(), source);
34166
- if (!existsSync58(absPath)) {
34294
+ if (!existsSync59(absPath)) {
34167
34295
  console.log(pc2.red(t("image.not_found", { path: source })));
34168
34296
  return;
34169
34297
  }
@@ -34266,7 +34394,7 @@ function registerMmaCommands(ctx) {
34266
34394
  console.log(pc2.yellow(t("repl.wizard_running")));
34267
34395
  await ctx.withExclusiveInput(async () => {
34268
34396
  const answers = await runSetup(ctx.rl);
34269
- const configPath = join50(ctx.configDir, "config.json");
34397
+ const configPath = join51(ctx.configDir, "config.json");
34270
34398
  ctx.config.provider.type = answers.provider;
34271
34399
  ctx.config.provider.baseUrl = answers.apiBase;
34272
34400
  ctx.config.provider.apiKey = answers.apiKey;
@@ -34274,7 +34402,7 @@ function registerMmaCommands(ctx) {
34274
34402
  ctx.config.contextWindow = answers.contextWindow;
34275
34403
  ctx.config.maxToolIterations = answers.maxToolIterations;
34276
34404
  ctx.config.locale = answers.locale;
34277
- saveConfig(ctx.config, configPath, dirname23(configPath));
34405
+ saveConfig(ctx.config, configPath, dirname24(configPath));
34278
34406
  await ctx.agent.reconfigure(ctx.config);
34279
34407
  console.log(pc2.green(t("cli.config_saved")));
34280
34408
  });
@@ -34388,8 +34516,8 @@ function registerMmaCommands(ctx) {
34388
34516
  return;
34389
34517
  }
34390
34518
  ctx.config.model = name;
34391
- const configPath = join50(ctx.configDir, "config.json");
34392
- saveConfig(ctx.config, configPath, dirname23(configPath));
34519
+ const configPath = join51(ctx.configDir, "config.json");
34520
+ saveConfig(ctx.config, configPath, dirname24(configPath));
34393
34521
  await ctx.agent.reconfigure(ctx.config);
34394
34522
  console.log(pc2.green(t("repl.model_set", { name })));
34395
34523
  return;
@@ -34413,8 +34541,8 @@ function registerMmaCommands(ctx) {
34413
34541
  return;
34414
34542
  }
34415
34543
  ctx.config.contextWindow = size;
34416
- const configPath = join50(ctx.configDir, "config.json");
34417
- saveConfig(ctx.config, configPath, dirname23(configPath));
34544
+ const configPath = join51(ctx.configDir, "config.json");
34545
+ saveConfig(ctx.config, configPath, dirname24(configPath));
34418
34546
  await ctx.agent.reconfigure(ctx.config);
34419
34547
  console.log(pc2.green(t("cli.context_set", { size })));
34420
34548
  }
@@ -34428,10 +34556,10 @@ function registerMmaCommands(ctx) {
34428
34556
  if (ctx.sessionManager && ctx.config.session.autoSave) {}
34429
34557
  ctx.agent.shutdown();
34430
34558
  const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config2(), exports_config));
34431
- const { join: join51 } = await import("path");
34559
+ const { join: join52 } = await import("path");
34432
34560
  const configDir = ctx.configDir;
34433
34561
  const baseDir = ctx.baseDir;
34434
- const projectConfigPath = join51(baseDir, ".mmrc");
34562
+ const projectConfigPath = join52(baseDir, ".mmrc");
34435
34563
  const { config: freshConfig } = loadConfig2({ configDir, projectConfigPath });
34436
34564
  Object.assign(ctx.config, freshConfig);
34437
34565
  const { bootstrap: bootstrap2 } = await Promise.resolve().then(() => (init_bootstrap(), exports_bootstrap));
@@ -34785,21 +34913,21 @@ async function runConfigMigrate(ctx) {
34785
34913
  const { hasDomainFiles: hasDomainFiles3 } = await Promise.resolve().then(() => (init_domains(), exports_domains));
34786
34914
  const { loadConfig: loadCfg } = await Promise.resolve().then(() => (init_config2(), exports_config));
34787
34915
  const configDir = ctx.configDir;
34788
- const configPath = join50(configDir, "config.json");
34916
+ const configPath = join51(configDir, "config.json");
34789
34917
  if (hasDomainFiles3(configDir)) {
34790
34918
  console.log(pc2.yellow(t("config.migrate_no_legacy")));
34791
34919
  return;
34792
34920
  }
34793
- if (!existsSync57(configPath)) {
34921
+ if (!existsSync58(configPath)) {
34794
34922
  console.log(pc2.yellow(t("config.migrate_no_legacy")));
34795
34923
  return;
34796
34924
  }
34797
34925
  console.log(t("config.migrate_start"));
34798
- const { config } = loadCfg({ configDir, projectConfigPath: join50(configDir, ".mmrc") });
34926
+ const { config } = loadCfg({ configDir, projectConfigPath: join51(configDir, ".mmrc") });
34799
34927
  saveConfig(config, configPath, configDir);
34800
34928
  const { renameSync: renameSync4, readdirSync: readdirSync19 } = await import("fs");
34801
34929
  renameSync4(configPath, configPath + ".bak");
34802
- const domainFiles = readdirSync19(join50(configDir, "config")).filter((f) => f.endsWith(".json"));
34930
+ const domainFiles = readdirSync19(join51(configDir, "config")).filter((f) => f.endsWith(".json"));
34803
34931
  console.log(pc2.green(t("config.migrate_done", { count: String(domainFiles.length) })));
34804
34932
  }
34805
34933
  var version2, COMMAND_GROUPS;
@@ -34859,15 +34987,15 @@ init_config2();
34859
34987
  init_setup();
34860
34988
  init_i18n();
34861
34989
  init_colors();
34862
- import { join as join49, dirname as dirname22 } from "path";
34863
- import { homedir as homedir16 } from "os";
34864
- import { existsSync as existsSync56 } from "fs";
34990
+ import { join as join50, dirname as dirname23 } from "path";
34991
+ import { homedir as homedir17 } from "os";
34992
+ import { existsSync as existsSync57 } from "fs";
34865
34993
 
34866
34994
  // src/cli/security-commands.ts
34867
34995
  init_bootstrap();
34868
34996
  init_config2();
34869
- import { join as join43, dirname as dirname18 } from "path";
34870
- import { homedir as homedir15 } from "os";
34997
+ import { join as join44, dirname as dirname19 } from "path";
34998
+ import { homedir as homedir16 } from "os";
34871
34999
 
34872
35000
  // src/modules/security/security-policies.ts
34873
35001
  init_security();
@@ -35392,7 +35520,7 @@ function createSecurityCommand(program2) {
35392
35520
  }
35393
35521
  });
35394
35522
  securityCmd.command("set-policy").argument("<preset>", t("cli.security.preset")).description(t("cli.security.set_policy")).action(async (preset) => {
35395
- const configPath = join43(homedir15(), ".mma", "config.json");
35523
+ const configPath = join44(homedir16(), ".mma", "config.json");
35396
35524
  const { config: appConfig } = await bootstrap();
35397
35525
  const validPresets = ["strict", "balanced", "permissive"];
35398
35526
  if (!validPresets.includes(preset)) {
@@ -35402,40 +35530,40 @@ function createSecurityCommand(program2) {
35402
35530
  const policy = getSecurityPolicy(preset);
35403
35531
  const newSecurityConfig = applySecurityPolicy(preset);
35404
35532
  appConfig.security = newSecurityConfig;
35405
- saveConfig(appConfig, configPath, dirname18(configPath));
35533
+ saveConfig(appConfig, configPath, dirname19(configPath));
35406
35534
  console.log(t("cli.security.policy_applied", { name: policy.name }));
35407
35535
  console.log(t("cli.security.policy_description", { description: policy.description }));
35408
35536
  });
35409
35537
  securityCmd.command("enable-encryption").description(t("cli.security.enable_encryption")).action(async () => {
35410
- const configPath = join43(homedir15(), ".mma", "config.json");
35538
+ const configPath = join44(homedir16(), ".mma", "config.json");
35411
35539
  const { config: appConfig } = await bootstrap();
35412
35540
  const security = appConfig.security = appConfig.security || {};
35413
35541
  toggleSessionEncryption(security, true);
35414
- saveConfig(appConfig, configPath, dirname18(configPath));
35542
+ saveConfig(appConfig, configPath, dirname19(configPath));
35415
35543
  console.log(t("cli.security.encryption_enabled"));
35416
35544
  });
35417
35545
  securityCmd.command("disable-encryption").description(t("cli.security.disable_encryption")).action(async () => {
35418
- const configPath = join43(homedir15(), ".mma", "config.json");
35546
+ const configPath = join44(homedir16(), ".mma", "config.json");
35419
35547
  const { config: appConfig } = await bootstrap();
35420
35548
  const security = appConfig.security = appConfig.security || {};
35421
35549
  toggleSessionEncryption(security, false);
35422
- saveConfig(appConfig, configPath, dirname18(configPath));
35550
+ saveConfig(appConfig, configPath, dirname19(configPath));
35423
35551
  console.log(t("cli.security.encryption_disabled"));
35424
35552
  });
35425
35553
  securityCmd.command("enable-audit").description(t("cli.security.enable_audit")).action(async () => {
35426
- const configPath = join43(homedir15(), ".mma", "config.json");
35554
+ const configPath = join44(homedir16(), ".mma", "config.json");
35427
35555
  const { config: appConfig } = await bootstrap();
35428
35556
  const security = appConfig.security = appConfig.security || {};
35429
35557
  toggleAuditNotifier(security, true);
35430
- saveConfig(appConfig, configPath, dirname18(configPath));
35558
+ saveConfig(appConfig, configPath, dirname19(configPath));
35431
35559
  console.log(t("cli.security.audit_enabled"));
35432
35560
  });
35433
35561
  securityCmd.command("disable-audit").description(t("cli.security.disable_audit")).action(async () => {
35434
- const configPath = join43(homedir15(), ".mma", "config.json");
35562
+ const configPath = join44(homedir16(), ".mma", "config.json");
35435
35563
  const { config: appConfig } = await bootstrap();
35436
35564
  const security = appConfig.security = appConfig.security || {};
35437
35565
  toggleAuditNotifier(security, false);
35438
- saveConfig(appConfig, configPath, dirname18(configPath));
35566
+ saveConfig(appConfig, configPath, dirname19(configPath));
35439
35567
  console.log(t("cli.security.audit_disabled"));
35440
35568
  });
35441
35569
  securityCmd.command("audit-stats").description(t("cli.security.audit_stats")).action(async () => {
@@ -35494,27 +35622,27 @@ init_presets();
35494
35622
  init_version();
35495
35623
 
35496
35624
  // src/modules/updater/changelog-reader.ts
35497
- import { readFileSync as readFileSync32, existsSync as existsSync51 } from "fs";
35498
- import { dirname as dirname19, join as join44 } from "path";
35625
+ import { readFileSync as readFileSync33, existsSync as existsSync52 } from "fs";
35626
+ import { dirname as dirname20, join as join45 } from "path";
35499
35627
  function readChangelog(packageName) {
35500
35628
  try {
35501
- let dir = dirname19(import.meta.url);
35629
+ let dir = dirname20(import.meta.url);
35502
35630
  if (dir.startsWith("file://")) {
35503
35631
  dir = decodeURIComponent(dir.slice(7));
35504
35632
  }
35505
35633
  for (let i = 0;i < 10; i++) {
35506
- const pkgPath = join44(dir, "package.json");
35507
- if (existsSync51(pkgPath)) {
35508
- const pkg = JSON.parse(readFileSync32(pkgPath, "utf-8"));
35634
+ const pkgPath = join45(dir, "package.json");
35635
+ if (existsSync52(pkgPath)) {
35636
+ const pkg = JSON.parse(readFileSync33(pkgPath, "utf-8"));
35509
35637
  if (pkg.name === packageName) {
35510
- const changelogPath = join44(dir, "CHANGELOG.md");
35511
- if (existsSync51(changelogPath)) {
35512
- return readFileSync32(changelogPath, "utf-8");
35638
+ const changelogPath = join45(dir, "CHANGELOG.md");
35639
+ if (existsSync52(changelogPath)) {
35640
+ return readFileSync33(changelogPath, "utf-8");
35513
35641
  }
35514
35642
  return null;
35515
35643
  }
35516
35644
  }
35517
- dir = dirname19(dir);
35645
+ dir = dirname20(dir);
35518
35646
  }
35519
35647
  return null;
35520
35648
  } catch {
@@ -35577,7 +35705,7 @@ function createProgram() {
35577
35705
  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")).option("--reasoning <level>", t("cli.reasoning_level"), "auto");
35578
35706
  program2.command("init").description(t("cli.init")).action(async () => {
35579
35707
  const answers = await runSetup();
35580
- const configPath = join49(homedir16(), ".mma", "config.json");
35708
+ const configPath = join50(homedir17(), ".mma", "config.json");
35581
35709
  const { config } = await bootstrap();
35582
35710
  config.provider.type = answers.provider;
35583
35711
  config.provider.baseUrl = answers.apiBase;
@@ -35617,12 +35745,12 @@ function createProgram() {
35617
35745
  config.security.paths.denied = [];
35618
35746
  }
35619
35747
  }
35620
- saveConfig(config, configPath, dirname22(configPath));
35748
+ saveConfig(config, configPath, dirname23(configPath));
35621
35749
  console.log(t("cli.config_saved"));
35622
35750
  });
35623
35751
  const configCmd = program2.command("config").description(t("cli.manage_config"));
35624
35752
  configCmd.command("set").argument("<key>", t("cli.config_key")).argument("<value>", "Config value").description(t("cli.set_value")).action(async (key, value) => {
35625
- const configPath = join49(homedir16(), ".mma", "config.json");
35753
+ const configPath = join50(homedir17(), ".mma", "config.json");
35626
35754
  const { config } = await bootstrap();
35627
35755
  const keys = key.split(".");
35628
35756
  let obj = config;
@@ -35642,7 +35770,7 @@ function createProgram() {
35642
35770
  obj[lastKey] = parseFloat(value);
35643
35771
  else
35644
35772
  obj[lastKey] = value;
35645
- saveConfig(config, configPath, dirname22(configPath));
35773
+ saveConfig(config, configPath, dirname23(configPath));
35646
35774
  console.log(t("cli.set_done", { key, value }));
35647
35775
  });
35648
35776
  configCmd.command("show").description(t("cli.show_config")).action(async () => {
@@ -35652,24 +35780,24 @@ function createProgram() {
35652
35780
  configCmd.command("migrate").description(t("cli.migrate_config")).action(async () => {
35653
35781
  const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config2(), exports_config));
35654
35782
  const { hasDomainFiles: hasDomainFiles3 } = await Promise.resolve().then(() => (init_domains(), exports_domains));
35655
- const configDir = join49(homedir16(), ".mma");
35656
- const configPath = join49(configDir, "config.json");
35783
+ const configDir = join50(homedir17(), ".mma");
35784
+ const configPath = join50(configDir, "config.json");
35657
35785
  if (hasDomainFiles3(configDir)) {
35658
35786
  console.log(pc2.yellow(t("config.migrate_no_legacy")));
35659
35787
  return;
35660
35788
  }
35661
- if (!existsSync56(configPath)) {
35789
+ if (!existsSync57(configPath)) {
35662
35790
  console.log(pc2.yellow(t("config.migrate_no_legacy")));
35663
35791
  return;
35664
35792
  }
35665
35793
  console.log(t("config.migrate_start"));
35666
- const { config } = loadConfig2({ configDir, projectConfigPath: join49(configDir, ".mmrc") });
35794
+ const { config } = loadConfig2({ configDir, projectConfigPath: join50(configDir, ".mmrc") });
35667
35795
  saveConfig(config, configPath, configDir);
35668
35796
  const bakPath = configPath + ".bak";
35669
35797
  const { renameSync: renameSync4 } = await import("fs");
35670
35798
  renameSync4(configPath, bakPath);
35671
35799
  const { readdirSync: readdirSync19 } = await import("fs");
35672
- const domainFiles = readdirSync19(join49(configDir, "config")).filter((f) => f.endsWith(".json"));
35800
+ const domainFiles = readdirSync19(join50(configDir, "config")).filter((f) => f.endsWith(".json"));
35673
35801
  console.log(pc2.green(t("config.migrate_done", { count: String(domainFiles.length) })));
35674
35802
  });
35675
35803
  const model = program2.command("model").description(t("cli.manage_models"));
@@ -35709,10 +35837,10 @@ function createProgram() {
35709
35837
  console.log(t("cli.model_hint"));
35710
35838
  });
35711
35839
  model.command("use").argument("<name>", "Model name").description(t("cli.set_model")).action(async (name) => {
35712
- const configPath = join49(homedir16(), ".mma", "config.json");
35840
+ const configPath = join50(homedir17(), ".mma", "config.json");
35713
35841
  const { config } = await bootstrap();
35714
35842
  config.model = name;
35715
- saveConfig(config, configPath, dirname22(configPath));
35843
+ saveConfig(config, configPath, dirname23(configPath));
35716
35844
  console.log(t("cli.model_set", { name }));
35717
35845
  });
35718
35846
  model.command("certify").argument("<name>", "Model name").option("--provider-url <url>", t("cli.cert_provider_url")).option("--provider-key <key>", t("cli.cert_provider_key")).option("--context-window <n>", t("cli.cert_context_window")).option("--tags <tags>", t("cli.cert_tags"), "core").option("--scenarios <ids>", t("cli.cert_scenarios")).option("--timeout <ms>", t("cli.cert_timeout")).option("--reps <n>", t("cli.cert_reps")).option("--force", t("cli.cert_force")).option("--clean", t("cli.cert_clean")).description(t("cli.certify")).action(async (name, cmdOpts) => {
@@ -35748,7 +35876,7 @@ function createProgram() {
35748
35876
  await uncertify2(name, config, process.cwd());
35749
35877
  });
35750
35878
  program2.command("context").description(t("cli.manage_context")).argument("<size>", "Context window size in tokens").action(async (size) => {
35751
- const configPath = join49(homedir16(), ".mma", "config.json");
35879
+ const configPath = join50(homedir17(), ".mma", "config.json");
35752
35880
  const { config } = await bootstrap();
35753
35881
  const contextWindow = parseInt(size, 10);
35754
35882
  if (isNaN(contextWindow) || contextWindow < 1024) {
@@ -35756,7 +35884,7 @@ function createProgram() {
35756
35884
  return;
35757
35885
  }
35758
35886
  config.contextWindow = contextWindow;
35759
- saveConfig(config, configPath, dirname22(configPath));
35887
+ saveConfig(config, configPath, dirname23(configPath));
35760
35888
  console.log(t("cli.context_set", { size: contextWindow }));
35761
35889
  });
35762
35890
  const provider = program2.command("provider").description(t("cli.manage_providers"));
@@ -35794,7 +35922,7 @@ function createProgram() {
35794
35922
  console.log(t("cli.base_url"), config.provider.baseUrl);
35795
35923
  });
35796
35924
  provider.command("use").argument("<name>", "Provider name").description(t("cli.set_provider")).action(async (name) => {
35797
- const configPath = join49(homedir16(), ".mma", "config.json");
35925
+ const configPath = join50(homedir17(), ".mma", "config.json");
35798
35926
  const { config, agent } = await bootstrap();
35799
35927
  if (config.provider.entries && config.provider.entries.length > 0) {
35800
35928
  try {
@@ -35810,14 +35938,14 @@ function createProgram() {
35810
35938
  if (baseUrl) {
35811
35939
  config.provider.baseUrl = baseUrl;
35812
35940
  }
35813
- saveConfig(config, configPath, dirname22(configPath));
35941
+ saveConfig(config, configPath, dirname23(configPath));
35814
35942
  console.log(t("cli.provider_set", { name }));
35815
35943
  if (baseUrl) {
35816
35944
  console.log(t("cli.provider_base_hint", { baseUrl }));
35817
35945
  }
35818
35946
  });
35819
35947
  provider.command("add").argument("<name>", "Provider type or label").option("--url <url>", "Base URL").option("--key <key>", "API key").option("--priority <n>", "Fallback priority (lower = tried first)").option("--context-window <n>", "Context window override for this entry").option("--rpm <n>", "Max requests per minute for this entry").option("--parallel <n>", "Max parallel tasks for this entry").description(t("cli.add_provider")).action(async (name, opts) => {
35820
- const configPath = join49(homedir16(), ".mma", "config.json");
35948
+ const configPath = join50(homedir17(), ".mma", "config.json");
35821
35949
  const { config } = await bootstrap();
35822
35950
  const entries = Array.isArray(config.provider.entries) ? config.provider.entries : [];
35823
35951
  if (entries.length === 0) {
@@ -35849,7 +35977,7 @@ function createProgram() {
35849
35977
  });
35850
35978
  config.provider.entries = entries;
35851
35979
  config.provider.active = config.provider.active || config.provider.type;
35852
- saveConfig(config, configPath, dirname22(configPath));
35980
+ saveConfig(config, configPath, dirname23(configPath));
35853
35981
  console.log(pc2.green(t("cli.provider_added", { name })));
35854
35982
  console.log(t("cli.provider_switch_hint"));
35855
35983
  });
@@ -36791,9 +36919,9 @@ class LineEditor {
36791
36919
  }
36792
36920
 
36793
36921
  // src/cli/repl.ts
36794
- import { existsSync as existsSync58, readFileSync as readFileSync39, writeFileSync as writeFileSync22 } from "fs";
36795
- import { join as join51 } from "path";
36796
- import { homedir as homedir17 } from "os";
36922
+ import { existsSync as existsSync59, readFileSync as readFileSync40, writeFileSync as writeFileSync23 } from "fs";
36923
+ import { join as join52 } from "path";
36924
+ import { homedir as homedir18 } from "os";
36797
36925
 
36798
36926
  // src/cli/completer.ts
36799
36927
  class SlashCommandProvider {
@@ -36979,9 +37107,12 @@ class FormattingStream {
36979
37107
  codeLines = [];
36980
37108
  tableBuffer = [];
36981
37109
  onWrite;
37110
+ onRawWrite;
36982
37111
  width;
36983
- constructor(onWrite, width) {
37112
+ partialWritten = 0;
37113
+ constructor(onWrite, width, onRawWrite) {
36984
37114
  this.onWrite = onWrite;
37115
+ this.onRawWrite = onRawWrite ?? onWrite;
36985
37116
  this.width = width ?? getTerminalWidth();
36986
37117
  }
36987
37118
  write(chunk) {
@@ -36991,8 +37122,20 @@ class FormattingStream {
36991
37122
  `)) !== -1) {
36992
37123
  const line = this.buffer.slice(0, idx);
36993
37124
  this.buffer = this.buffer.slice(idx + 1);
37125
+ this.emitPartialRewind();
36994
37126
  this.processLine(line);
36995
37127
  }
37128
+ if (this.buffer.length > 0 && !this.inCodeBlock) {
37129
+ this.onRawWrite(this.buffer);
37130
+ this.partialWritten = this.buffer.length;
37131
+ this.buffer = "";
37132
+ }
37133
+ }
37134
+ emitPartialRewind() {
37135
+ if (this.partialWritten > 0) {
37136
+ this.onRawWrite(`\x1B[${this.partialWritten}D`);
37137
+ this.partialWritten = 0;
37138
+ }
36996
37139
  }
36997
37140
  flush() {
36998
37141
  if (this.tableBuffer.length > 0) {
@@ -37129,7 +37272,6 @@ function formatWarning(text) {
37129
37272
 
37130
37273
  // src/ui/renderer.ts
37131
37274
  init_spinner();
37132
- init_box();
37133
37275
  init_table();
37134
37276
  init_i18n();
37135
37277
  init_prices();
@@ -37156,6 +37298,7 @@ function toDisplayPath(baseDir, p) {
37156
37298
  return rel.split(sep2).join("/");
37157
37299
  }
37158
37300
  var GUTTER = " ";
37301
+ var MAX_OUTPUT_LINES = 50;
37159
37302
  var BUSY_TOOLS = new Set(["lsp_check"]);
37160
37303
  function toolMarker(tool) {
37161
37304
  switch (tool) {
@@ -37207,15 +37350,19 @@ class Renderer {
37207
37350
  out;
37208
37351
  err;
37209
37352
  width;
37210
- toolStyle;
37211
37353
  baseDir;
37212
37354
  card = null;
37355
+ thoughtStarted = false;
37356
+ thoughtStartMs = 0;
37357
+ thoughtHeaderPrinted = false;
37358
+ textStarted = false;
37359
+ outputLineCount = 0;
37360
+ outputSuppressed = false;
37213
37361
  constructor(opts = {}) {
37214
37362
  this.rich = opts.rich ?? isRichTerminal();
37215
37363
  this.out = opts.out ?? process.stdout;
37216
37364
  this.err = opts.err ?? process.stderr;
37217
37365
  this.width = opts.width ?? getTerminalWidth();
37218
- this.toolStyle = opts.toolStyle ?? "inline";
37219
37366
  this.baseDir = opts.baseDir;
37220
37367
  this.spinner = new Spinner({
37221
37368
  enabled: this.rich && (opts.spinner ?? true),
@@ -37223,21 +37370,32 @@ class Renderer {
37223
37370
  width: this.width
37224
37371
  });
37225
37372
  this.fmt = new FormattingStream((line) => this.out.write(`${line}
37226
- `), this.width);
37373
+ `), this.width, (text) => this.out.write(text));
37374
+ }
37375
+ showLoader() {
37376
+ this.spinner.start("thinking");
37227
37377
  }
37228
37378
  text(chunk) {
37229
37379
  this.endCard();
37230
37380
  this.spinner.stop();
37381
+ if (!this.textStarted) {
37382
+ this.textStarted = true;
37383
+ this.out.write(`
37384
+ ${pc2.dim("-")} `);
37385
+ }
37231
37386
  this.fmt.write(chunk);
37232
37387
  }
37233
37388
  meta(chunk) {
37234
37389
  this.spinner.stop();
37235
- if (this.card) {
37236
- if (this.toolStyle === "inline") {
37237
- this.writeInlineBody(chunk);
37238
- } else {
37239
- this.card.body.push(chunk);
37240
- }
37390
+ if (this.thoughtStarted) {
37391
+ if (!this.thoughtHeaderPrinted) {
37392
+ this.out.write(`
37393
+ ${pc2.dim("→")} Thought: `);
37394
+ this.thoughtHeaderPrinted = true;
37395
+ }
37396
+ this.out.write(pc2.dim(chunk));
37397
+ } else if (this.card) {
37398
+ this.writeInlineBody(chunk);
37241
37399
  } else {
37242
37400
  this.out.write(chunk);
37243
37401
  }
@@ -37247,44 +37405,55 @@ class Renderer {
37247
37405
  `)) {
37248
37406
  if (line.trim() === "")
37249
37407
  continue;
37408
+ this.outputLineCount++;
37409
+ if (this.outputLineCount > MAX_OUTPUT_LINES) {
37410
+ this.outputSuppressed = true;
37411
+ continue;
37412
+ }
37250
37413
  this.out.write(`${GUTTER}${line}
37251
37414
  `);
37252
37415
  }
37253
37416
  }
37254
37417
  reasoning(chunk) {
37255
37418
  this.spinner.stop();
37419
+ if (this.thoughtStarted && !this.thoughtHeaderPrinted) {
37420
+ this.out.write(`
37421
+ ${pc2.dim("→")} Thought: `);
37422
+ this.thoughtHeaderPrinted = true;
37423
+ }
37256
37424
  this.out.write(pc2.dim(chunk));
37257
37425
  }
37258
37426
  thinkingStart() {
37259
- this.spinner.start(t("ui.thinking"));
37427
+ this.thoughtStarted = true;
37428
+ this.thoughtStartMs = Date.now();
37429
+ this.thoughtHeaderPrinted = false;
37260
37430
  }
37261
37431
  thinkingEnd() {
37262
37432
  this.spinner.stop();
37433
+ if (this.thoughtStarted && this.thoughtHeaderPrinted) {
37434
+ const duration = Date.now() - this.thoughtStartMs;
37435
+ this.out.write(pc2.dim(` ${duration}ms
37436
+ `));
37437
+ }
37438
+ this.thoughtStarted = false;
37439
+ this.thoughtHeaderPrinted = false;
37263
37440
  }
37264
37441
  toolStart(tool, args, stepContext, icon) {
37265
37442
  this.endCard();
37266
37443
  this.spinner.stop();
37444
+ this.outputLineCount = 0;
37445
+ this.outputSuppressed = false;
37267
37446
  const displayArgs = PATH_TOOLS.has(tool) && typeof args.path === "string" ? { ...args, path: toDisplayPath(this.baseDir, args.path) } : args;
37268
37447
  const summary = summarizeArgs2(displayArgs);
37269
- const step = stepContext ? ` ${pc2.cyan(`← ${stepContext}`)}` : "";
37270
37448
  const marker = icon || toolMarker(tool);
37271
- if (!this.rich) {
37449
+ this.card = { tool, args, start: Date.now() };
37450
+ if (stepContext) {
37272
37451
  this.out.write(`
37273
- ${pc2.dim(marker)} ${friendlyTool(tool)}${summary ? ` ${pc2.dim(summary)}` : ""}${step}
37452
+ ${pc2.dim("↓")} ${pc2.cyan(stepContext)}
37274
37453
  `);
37275
- return;
37276
37454
  }
37277
- this.card = { tool, args, body: [], start: Date.now() };
37278
- if (this.toolStyle === "inline") {
37279
- this.out.write(`
37280
- ${pc2.dim(marker)} ${friendlyTool(tool)}${summary ? ` ${pc2.dim(summary)}` : ""}${step}
37455
+ this.out.write(`${pc2.dim(marker)} ${friendlyTool(tool)}${summary ? ` ${pc2.dim(summary)}` : ""}
37281
37456
  `);
37282
- if (BUSY_TOOLS.has(tool)) {
37283
- this.spinner.start(t("ui.tool_running", { tool: friendlyTool(tool) }));
37284
- }
37285
- return;
37286
- }
37287
- this.spinner.start(`${pc2.dim(marker)} ${friendlyTool(tool)}${summary ? ` ${pc2.dim(summary)}` : ""}${step}`);
37288
37457
  }
37289
37458
  planBlock(lines) {
37290
37459
  this.endCard();
@@ -37294,30 +37463,12 @@ ${pc2.dim(marker)} ${friendlyTool(tool)}${summary ? ` ${pc2.dim(summary)}` : ""}
37294
37463
  `);
37295
37464
  }
37296
37465
  }
37297
- toolEnd(_tool, duration, error, ctxDelta, costUsd, provider, model) {
37466
+ toolEnd(_tool, duration, error, ctxDelta, costUsd) {
37298
37467
  this.spinner.stop();
37299
- const prov = provider && model ? `${pc2.dim(`${provider}·${model}`)}` : undefined;
37300
- if (!this.rich) {
37301
- const parts = [];
37302
- if (ctxDelta !== undefined && ctxDelta !== 0) {
37303
- const deltaStr = ctxDelta > 0 ? pc2.green(`+${ctxDelta}`) : pc2.yellow(`${ctxDelta} ↓`);
37304
- parts.push(`${pc2.dim("ctx")} ${deltaStr}`);
37305
- }
37306
- if (costUsd !== undefined && costUsd > 0) {
37307
- parts.push(`${pc2.dim("cost")} ${pc2.yellow(formatUsd(costUsd))}`);
37308
- }
37309
- if (prov)
37310
- parts.push(prov);
37311
- if (parts.length > 0)
37312
- this.out.write(`${parts.join(" ")}
37313
- `);
37314
- return;
37315
- }
37316
37468
  if (!this.card)
37317
37469
  return;
37318
- const { tool, args, body } = this.card;
37319
37470
  const marker = error ? pc2.red("✗") : pc2.green("✓");
37320
- let footer = `${marker} ${pc2.dim(`${duration}ms`)}`;
37471
+ let footer = `${GUTTER}${marker} ${pc2.dim(`${duration}ms`)}`;
37321
37472
  if (ctxDelta !== undefined && ctxDelta !== 0) {
37322
37473
  const deltaStr = ctxDelta > 0 ? pc2.green(`+${ctxDelta}`) : pc2.yellow(`${ctxDelta} ↓`);
37323
37474
  footer += ` ${pc2.dim("ctx")} ${deltaStr}`;
@@ -37325,32 +37476,10 @@ ${pc2.dim(marker)} ${friendlyTool(tool)}${summary ? ` ${pc2.dim(summary)}` : ""}
37325
37476
  if (costUsd !== undefined && costUsd > 0) {
37326
37477
  footer += ` ${pc2.dim("cost")} ${pc2.yellow(formatUsd(costUsd))}`;
37327
37478
  }
37328
- if (prov) {
37329
- footer += ` ${pc2.dim("via")} ${prov}`;
37330
- }
37331
- if (this.toolStyle === "inline") {
37332
- this.out.write(`${GUTTER}${footer}
37479
+ this.out.write(`${footer}
37333
37480
  `);
37334
- this.out.write(`${divider(this.width)}
37335
- `);
37336
- this.card = null;
37337
- return;
37338
- }
37339
- const lines = [];
37340
- const summary = summarizeArgs2(args);
37341
- if (summary)
37342
- lines.push(pc2.dim(summary));
37343
- for (const chunk of body) {
37344
- for (const line of chunk.split(`
37345
- `)) {
37346
- if (line.trim() !== "")
37347
- lines.push(line);
37348
- }
37349
- }
37350
- lines.push(footer);
37351
- const title = `${marker} ${friendlyTool(tool)}`;
37352
- for (const line of box(lines, { title, width: this.width })) {
37353
- this.out.write(`${line}
37481
+ if (this.outputSuppressed) {
37482
+ this.out.write(`${GUTTER}${pc2.dim(`... (${this.outputLineCount - MAX_OUTPUT_LINES} more lines)`)}
37354
37483
  `);
37355
37484
  }
37356
37485
  this.card = null;
@@ -37370,6 +37499,12 @@ ${pc2.dim(marker)} ${friendlyTool(tool)}${summary ? ` ${pc2.dim(summary)}` : ""}
37370
37499
  this.endCard();
37371
37500
  this.spinner.stop();
37372
37501
  this.fmt.flush();
37502
+ this.textStarted = false;
37503
+ }
37504
+ footer(model, provider, durationMs) {
37505
+ this.out.write(`
37506
+ ${pc2.dim("▣")} ${model} · ${provider} · ${pc2.dim(`${durationMs}ms`)}
37507
+ `);
37373
37508
  }
37374
37509
  endCard() {
37375
37510
  if (!this.card)
@@ -37523,20 +37658,16 @@ function stepContextForTool(plan, tool, args) {
37523
37658
  const argStr = JSON.stringify(args);
37524
37659
  const callPaths = extractFileLikeTokens(stripUrls(argStr)).map((p) => p.toLowerCase());
37525
37660
  if (callPaths.length > 0) {
37526
- for (const step2 of plan.steps) {
37527
- if (step2.status === "done" || step2.status === "skipped")
37661
+ for (const step of plan.steps) {
37662
+ if (step.status === "done" || step.status === "skipped")
37528
37663
  continue;
37529
- const stepPaths = extractFileLikeTokens(stripUrls(step2.description)).map((p) => p.toLowerCase());
37664
+ const stepPaths = extractFileLikeTokens(stripUrls(step.description)).map((p) => p.toLowerCase());
37530
37665
  if (stepPaths.length > 0 && stepPaths.some((s) => callPaths.some((c) => c.includes(s) || s.includes(c)))) {
37531
- return t("ui.step_context", { id: step2.id, desc: truncate4(step2.description) });
37666
+ return t("ui.step_context", { id: step.id, desc: truncate4(step.description) });
37532
37667
  }
37533
37668
  }
37534
37669
  }
37535
- const cur = currentStepIndex(plan);
37536
- const step = plan.steps[cur];
37537
- if (!step)
37538
- return null;
37539
- return t("ui.step_context", { id: step.id, desc: truncate4(step.description) });
37670
+ return null;
37540
37671
  }
37541
37672
 
37542
37673
  // src/cli/repl.ts
@@ -37619,10 +37750,10 @@ class Repl {
37619
37750
  this.envReport = envReport;
37620
37751
  this.execModule = execModule;
37621
37752
  this.slog = new SessionLogger(sessionManager, logger4);
37622
- this.configDir = configDir || join51(homedir17(), ".mma");
37753
+ this.configDir = configDir || join52(homedir18(), ".mma");
37623
37754
  this.baseDir = baseDir || process.cwd();
37624
37755
  this.noAgentsMd = noAgentsMd === true;
37625
- this.historyPath = historyPath ?? join51(homedir17(), ".mma", "repl-history");
37756
+ this.historyPath = historyPath ?? join52(homedir18(), ".mma", "repl-history");
37626
37757
  this.loadHistory();
37627
37758
  this.rl = process.stdin.isTTY ? new LineEditor({
37628
37759
  input: process.stdin,
@@ -37674,9 +37805,9 @@ class Repl {
37674
37805
  }));
37675
37806
  }
37676
37807
  loadHistory() {
37677
- if (existsSync58(this.historyPath)) {
37808
+ if (existsSync59(this.historyPath)) {
37678
37809
  try {
37679
- const raw = readFileSync39(this.historyPath, "utf-8");
37810
+ const raw = readFileSync40(this.historyPath, "utf-8");
37680
37811
  this.history = raw.split(`
37681
37812
  `).filter(Boolean).slice(-this.maxHistory);
37682
37813
  } catch {
@@ -37686,7 +37817,7 @@ class Repl {
37686
37817
  }
37687
37818
  saveHistory() {
37688
37819
  const allHistory = this.history.slice(-this.maxHistory);
37689
- writeFileSync22(this.historyPath, allHistory.join(`
37820
+ writeFileSync23(this.historyPath, allHistory.join(`
37690
37821
  `), "utf-8");
37691
37822
  }
37692
37823
  setupCompleter() {
@@ -37903,14 +38034,14 @@ ${t("image.clipboard_empty")}`));
37903
38034
  ` + pc2.green(t("repl.agent")));
37904
38035
  const renderer = new Renderer({
37905
38036
  spinner: this.config.ui?.spinner ?? true,
37906
- toolStyle: this.config.ui?.toolStyle ?? "inline",
37907
38037
  baseDir: this.baseDir
37908
38038
  });
38039
+ renderer.showLoader();
37909
38040
  const result = await this.agent.run(input, (c) => renderer.text(c), (m) => renderer.meta(m), (ev) => {
37910
38041
  if (ev.type === "start") {
37911
38042
  renderer.toolStart(ev.tool, ev.args, stepContextForTool(this.execModule?.getActivePlan() ?? null, ev.tool, ev.args), ev.icon);
37912
38043
  } else {
37913
- renderer.toolEnd(ev.tool, ev.duration ?? 0, ev.error, ev.ctxDelta, ev.costUsd, ev.provider, ev.model);
38044
+ renderer.toolEnd(ev.tool, ev.duration ?? 0, ev.error, ev.ctxDelta, ev.costUsd);
37914
38045
  if (ev.tool === "plan" || ev.tool === "todo") {
37915
38046
  this.renderPlan(renderer);
37916
38047
  }
@@ -37923,6 +38054,9 @@ ${t("image.clipboard_empty")}`));
37923
38054
  }
37924
38055
  });
37925
38056
  renderer.flush();
38057
+ if (result.provider && result.model) {
38058
+ renderer.footer(result.model, result.provider, result.llmDurationMs ?? result.durationMs ?? 0);
38059
+ }
37926
38060
  process.stdout.write(`
37927
38061
  `);
37928
38062
  this.logger?.logREPL(result.success ? "assistant" : "system", result.text?.slice(0, 400) || result.error || "");
@@ -38074,11 +38208,11 @@ ${t("image.clipboard_empty")}`));
38074
38208
  row(t("repl.agents_label"), pc2.red(t("repl.disabled")));
38075
38209
  } else {
38076
38210
  const agentsMdCandidates = [
38077
- join51(this.baseDir, "AGENTS.md"),
38078
- join51(this.baseDir, ".mma", "AGENTS.md"),
38079
- join51(this.configDir, "AGENTS.md")
38211
+ join52(this.baseDir, "AGENTS.md"),
38212
+ join52(this.baseDir, ".mma", "AGENTS.md"),
38213
+ join52(this.configDir, "AGENTS.md")
38080
38214
  ];
38081
- const foundAgents = agentsMdCandidates.filter((p) => existsSync58(p));
38215
+ const foundAgents = agentsMdCandidates.filter((p) => existsSync59(p));
38082
38216
  if (foundAgents.length > 0) {
38083
38217
  for (const p of foundAgents) {
38084
38218
  row(t("repl.agents_label"), pc2.dim(p));
@@ -38089,7 +38223,7 @@ ${t("image.clipboard_empty")}`));
38089
38223
  }
38090
38224
  const meta = this.sessionManager?.getActiveMeta();
38091
38225
  if (meta) {
38092
- const sessionPath = join51(this.configDir, "sessions", meta.id);
38226
+ const sessionPath = join52(this.configDir, "sessions", meta.id);
38093
38227
  row(t("repl.session_label"), `${pc2.cyan(meta.name)} ${pc2.dim(`(${meta.id.slice(0, 12)})`)} — ${meta.messageCount} msgs ${pc2.dim(sessionPath)}`);
38094
38228
  }
38095
38229
  const isTty2 = process.stdout.isTTY === true;
@@ -38204,9 +38338,9 @@ init_setup();
38204
38338
  init_config2();
38205
38339
  init_i18n();
38206
38340
  init_colors();
38207
- import { existsSync as existsSync59 } from "fs";
38208
- import { join as join53, dirname as dirname24 } from "path";
38209
- import { homedir as homedir19 } from "os";
38341
+ import { existsSync as existsSync60 } from "fs";
38342
+ import { join as join54, dirname as dirname25 } from "path";
38343
+ import { homedir as homedir20 } from "os";
38210
38344
 
38211
38345
  // src/modules/updater/index.ts
38212
38346
  init_checker();
@@ -38318,10 +38452,10 @@ ${t("cli.changelog_title", { version: result.latest })}
38318
38452
  init_environment();
38319
38453
  init_data_sanitizer();
38320
38454
  init_i18n();
38321
- import { appendFileSync as appendFileSync7, mkdirSync as mkdirSync21 } from "fs";
38322
- import { join as join52 } from "path";
38323
- import { homedir as homedir18 } from "os";
38324
- var CRASH_LOG_DIR = join52(homedir18(), ".mma", "logs");
38455
+ import { appendFileSync as appendFileSync7, mkdirSync as mkdirSync22 } from "fs";
38456
+ import { join as join53 } from "path";
38457
+ import { homedir as homedir19 } from "os";
38458
+ var CRASH_LOG_DIR = join53(homedir19(), ".mma", "logs");
38325
38459
  var CRASH_LOG_FILE = "crash.jsonl";
38326
38460
  function formatCrashEntry(type2, err) {
38327
38461
  const message = err instanceof Error ? err.message : String(err);
@@ -38331,13 +38465,13 @@ function formatCrashEntry(type2, err) {
38331
38465
  type: type2,
38332
38466
  message: sanitizeLogMessage(message),
38333
38467
  stack: sanitizeLogMessage(stack),
38334
- environment: collectEnvironment({ configDir: homedir18(), scanTools: false })
38468
+ environment: collectEnvironment({ configDir: homedir19(), scanTools: false })
38335
38469
  };
38336
38470
  }
38337
38471
  function writeCrashEntry(dir, entry) {
38338
38472
  try {
38339
- mkdirSync21(dir, { recursive: true });
38340
- appendFileSync7(join52(dir, CRASH_LOG_FILE), JSON.stringify(entry) + `
38473
+ mkdirSync22(dir, { recursive: true });
38474
+ appendFileSync7(join53(dir, CRASH_LOG_FILE), JSON.stringify(entry) + `
38341
38475
  `, "utf-8");
38342
38476
  } catch {}
38343
38477
  }
@@ -38419,14 +38553,14 @@ async function main() {
38419
38553
  }, null, 2));
38420
38554
  process.stdout.write(`
38421
38555
  `);
38422
- await updater?.waitForIdle();
38556
+ await updater?.waitForIdle(1e4);
38423
38557
  process.exit(result2.success ? 0 : 1);
38424
38558
  }
38425
38559
  const renderer = new Renderer({
38426
38560
  spinner: config.ui?.spinner ?? true,
38427
- toolStyle: config.ui?.toolStyle ?? "inline",
38428
38561
  baseDir
38429
38562
  });
38563
+ renderer.showLoader();
38430
38564
  const result = await agent.run(prompt, (chunk) => renderer.text(chunk), (meta) => renderer.meta(meta), (ev) => {
38431
38565
  if (ev.type === "start") {
38432
38566
  renderer.toolStart(ev.tool, ev.args, undefined, ev.icon);
@@ -38441,14 +38575,17 @@ async function main() {
38441
38575
  }
38442
38576
  });
38443
38577
  renderer.flush();
38578
+ if (result.provider && result.model) {
38579
+ renderer.footer(result.model, result.provider, result.llmDurationMs ?? result.durationMs ?? 0);
38580
+ }
38444
38581
  const exitCode = printRunResult(result, () => renderer.flush());
38445
38582
  agent.shutdown();
38446
38583
  await updater?.waitForIdle();
38447
38584
  process.exit(exitCode);
38448
38585
  } else {
38449
- const mmaDir = join53(homedir19(), ".mma");
38450
- const legacyConfigPath = join53(mmaDir, "config.json");
38451
- let hasAnyConfig = existsSync59(legacyConfigPath);
38586
+ const mmaDir = join54(homedir20(), ".mma");
38587
+ const legacyConfigPath = join54(mmaDir, "config.json");
38588
+ let hasAnyConfig = existsSync60(legacyConfigPath);
38452
38589
  if (!hasAnyConfig) {
38453
38590
  try {
38454
38591
  const { hasDomainFiles: hasDomainFiles3 } = await Promise.resolve().then(() => (init_domains(), exports_domains));
@@ -38511,7 +38648,7 @@ async function main() {
38511
38648
  config.security.paths.denied = [];
38512
38649
  }
38513
38650
  }
38514
- saveConfig(config, legacyConfigPath, dirname24(legacyConfigPath));
38651
+ saveConfig(config, legacyConfigPath, dirname25(legacyConfigPath));
38515
38652
  await agent.reconfigure(config);
38516
38653
  }
38517
38654
  startAutoUpdate(config);