micro-models-agent 0.24.12 → 0.25.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 (167) hide show
  1. package/dist/cli/commands.js +220 -0
  2. package/dist/cli/completer.js +168 -0
  3. package/dist/cli/index.js +2 -0
  4. package/dist/cli/main.js +113 -0
  5. package/dist/cli/repl.js +987 -0
  6. package/dist/cli/security-commands.js +166 -0
  7. package/dist/cli/setup.js +229 -0
  8. package/dist/config/config.js +186 -0
  9. package/dist/config/defaults.js +91 -0
  10. package/dist/config/experts.js +15 -0
  11. package/dist/config/index.js +3 -0
  12. package/dist/config/security.js +193 -0
  13. package/dist/config/types.js +1 -0
  14. package/dist/core/agent-moe.js +98 -0
  15. package/dist/core/agent.js +461 -0
  16. package/dist/core/bootstrap.js +321 -0
  17. package/dist/core/index.js +2 -0
  18. package/dist/core/prompt-builder.js +55 -0
  19. package/dist/core/session-logger.js +122 -0
  20. package/dist/core/types.js +1 -0
  21. package/dist/i18n/en.json +461 -0
  22. package/dist/i18n/index.js +43 -0
  23. package/dist/i18n/ru.json +461 -0
  24. package/dist/index.js +22 -0
  25. package/dist/llm/image-utils.js +144 -0
  26. package/dist/llm/index.js +4 -0
  27. package/dist/llm/model-loader.js +78 -0
  28. package/dist/llm/openai-compat.js +324 -0
  29. package/dist/llm/orchestrator.js +194 -0
  30. package/dist/llm/provider.js +10 -0
  31. package/dist/llm/response.js +39 -0
  32. package/dist/llm/token-counter.js +39 -0
  33. package/dist/llm/types.js +1 -0
  34. package/dist/logger/app-logger.js +76 -0
  35. package/dist/logger/index.js +1 -0
  36. package/dist/main.js +733 -551
  37. package/dist/migration/backup.js +45 -0
  38. package/dist/migration/detect.js +50 -0
  39. package/dist/migration/index.js +2 -0
  40. package/dist/modules/browser/actions.js +46 -0
  41. package/dist/modules/browser/cookie-store.js +24 -0
  42. package/dist/modules/browser/index.js +5 -0
  43. package/dist/modules/browser/module.js +28 -0
  44. package/dist/modules/browser/session.js +287 -0
  45. package/dist/modules/browser/snapshot.js +114 -0
  46. package/dist/modules/browser/types.js +9 -0
  47. package/dist/modules/context/history.js +15 -0
  48. package/dist/modules/context/index.js +1 -0
  49. package/dist/modules/context/manager.js +240 -0
  50. package/dist/modules/execution/auditor.js +72 -0
  51. package/dist/modules/execution/index.js +6 -0
  52. package/dist/modules/execution/module.js +337 -0
  53. package/dist/modules/execution/moe-executor.js +209 -0
  54. package/dist/modules/execution/plan-validator.js +153 -0
  55. package/dist/modules/execution/planner.js +35 -0
  56. package/dist/modules/execution/stuck-detector.js +134 -0
  57. package/dist/modules/execution/tracker.js +53 -0
  58. package/dist/modules/execution/types.js +1 -0
  59. package/dist/modules/execution/verifier.js +149 -0
  60. package/dist/modules/hallucination/confidence.js +54 -0
  61. package/dist/modules/hallucination/consistency.js +60 -0
  62. package/dist/modules/hallucination/detector.js +41 -0
  63. package/dist/modules/hallucination/factual.js +170 -0
  64. package/dist/modules/hallucination/index.js +4 -0
  65. package/dist/modules/index.js +5 -0
  66. package/dist/modules/indexer/cache.js +38 -0
  67. package/dist/modules/indexer/index.js +3 -0
  68. package/dist/modules/indexer/module.js +192 -0
  69. package/dist/modules/indexer/walker.js +101 -0
  70. package/dist/modules/mcp/client.js +393 -0
  71. package/dist/modules/mcp/index.js +3 -0
  72. package/dist/modules/mcp/module.js +146 -0
  73. package/dist/modules/mcp/registry.js +15 -0
  74. package/dist/modules/memory/index.js +1 -0
  75. package/dist/modules/memory/module.js +48 -0
  76. package/dist/modules/memory/search.js +40 -0
  77. package/dist/modules/memory/store.js +65 -0
  78. package/dist/modules/pipelines/engine.js +60 -0
  79. package/dist/modules/pipelines/index.js +3 -0
  80. package/dist/modules/pipelines/parser.js +53 -0
  81. package/dist/modules/pipelines/template.js +14 -0
  82. package/dist/modules/plugins/builtin/lint-on-write.js +121 -0
  83. package/dist/modules/plugins/builtin/notify.js +8 -0
  84. package/dist/modules/plugins/index.js +1 -0
  85. package/dist/modules/plugins/loader.js +28 -0
  86. package/dist/modules/plugins/manager.js +161 -0
  87. package/dist/modules/plugins/types.js +1 -0
  88. package/dist/modules/processes/detect.js +34 -0
  89. package/dist/modules/processes/index.js +3 -0
  90. package/dist/modules/processes/registry.js +148 -0
  91. package/dist/modules/processes/runner.js +124 -0
  92. package/dist/modules/registry.js +45 -0
  93. package/dist/modules/security/audit-log.js +116 -0
  94. package/dist/modules/security/audit-notifier.js +292 -0
  95. package/dist/modules/security/command-validator.js +185 -0
  96. package/dist/modules/security/content-scanner.js +52 -0
  97. package/dist/modules/security/data-sanitizer.js +97 -0
  98. package/dist/modules/security/encryption.js +240 -0
  99. package/dist/modules/security/index.js +14 -0
  100. package/dist/modules/security/network-validator.js +79 -0
  101. package/dist/modules/security/path-validator.js +155 -0
  102. package/dist/modules/security/rate-limiter.js +119 -0
  103. package/dist/modules/security/security-policies.js +393 -0
  104. package/dist/modules/security/session-encryption.js +193 -0
  105. package/dist/modules/security/session-isolation.js +95 -0
  106. package/dist/modules/session/index.js +3 -0
  107. package/dist/modules/session/manager.js +167 -0
  108. package/dist/modules/session/module.js +24 -0
  109. package/dist/modules/session/store.js +174 -0
  110. package/dist/modules/session/types.js +1 -0
  111. package/dist/modules/skills/index.js +3 -0
  112. package/dist/modules/skills/loader.js +72 -0
  113. package/dist/modules/skills/matcher.js +27 -0
  114. package/dist/modules/skills/module.js +143 -0
  115. package/dist/modules/types.js +1 -0
  116. package/dist/modules/updater/checker.js +32 -0
  117. package/dist/modules/updater/index.js +1 -0
  118. package/dist/modules/user-profile/compressor.js +16 -0
  119. package/dist/modules/user-profile/index.js +1 -0
  120. package/dist/modules/user-profile/profile.js +68 -0
  121. package/dist/tools/approve.js +32 -0
  122. package/dist/tools/attach-image.js +89 -0
  123. package/dist/tools/bash.js +140 -0
  124. package/dist/tools/browser.js +97 -0
  125. package/dist/tools/create-dir.js +56 -0
  126. package/dist/tools/delete-file.js +63 -0
  127. package/dist/tools/edit-file.js +77 -0
  128. package/dist/tools/executor.js +95 -0
  129. package/dist/tools/file-info.js +45 -0
  130. package/dist/tools/filter-tools.js +10 -0
  131. package/dist/tools/glob-tool.js +26 -0
  132. package/dist/tools/grep-tool.js +64 -0
  133. package/dist/tools/index.js +52 -0
  134. package/dist/tools/list-dir.js +47 -0
  135. package/dist/tools/load-skill.js +48 -0
  136. package/dist/tools/mcp-call.js +68 -0
  137. package/dist/tools/move-file.js +84 -0
  138. package/dist/tools/path-utils.js +51 -0
  139. package/dist/tools/pipeline-run.js +144 -0
  140. package/dist/tools/preview.js +2 -0
  141. package/dist/tools/process-kill.js +29 -0
  142. package/dist/tools/process-list.js +38 -0
  143. package/dist/tools/process-log.js +41 -0
  144. package/dist/tools/question.js +142 -0
  145. package/dist/tools/read-file.js +73 -0
  146. package/dist/tools/recall.js +110 -0
  147. package/dist/tools/registry.js +36 -0
  148. package/dist/tools/remember.js +67 -0
  149. package/dist/tools/scope-check.js +30 -0
  150. package/dist/tools/search-history.js +64 -0
  151. package/dist/tools/subagent.js +142 -0
  152. package/dist/tools/types.js +1 -0
  153. package/dist/tools/user-input.js +123 -0
  154. package/dist/tools/web-browse.js +57 -0
  155. package/dist/tools/web-fetch.js +72 -0
  156. package/dist/tools/web-search.js +59 -0
  157. package/dist/tools/write-file.js +80 -0
  158. package/dist/ui/box.js +81 -0
  159. package/dist/ui/colors.js +4 -0
  160. package/dist/ui/diff.js +185 -0
  161. package/dist/ui/index.js +6 -0
  162. package/dist/ui/md-formatter.js +212 -0
  163. package/dist/ui/output.js +13 -0
  164. package/dist/ui/renderer.js +141 -0
  165. package/dist/ui/spinner.js +70 -0
  166. package/dist/ui/table.js +144 -0
  167. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -2076,10 +2076,90 @@ var init_security = __esm(() => {
2076
2076
  };
2077
2077
  });
2078
2078
 
2079
+ // src/modules/lsp/config.ts
2080
+ function getServerForFile(filePath, config) {
2081
+ const ext = filePath.split(".").pop()?.toLowerCase();
2082
+ if (!ext)
2083
+ return null;
2084
+ const lang = LANGUAGE_MAP[ext];
2085
+ if (!lang)
2086
+ return null;
2087
+ return config.servers[lang] ?? null;
2088
+ }
2089
+ var DEFAULT_LSP_CONFIG, LANGUAGE_MAP;
2090
+ var init_config = __esm(() => {
2091
+ DEFAULT_LSP_CONFIG = {
2092
+ enabled: true,
2093
+ timeout: 15000,
2094
+ servers: {
2095
+ typescript: {
2096
+ command: "npx",
2097
+ args: ["typescript-language-server", "--stdio"],
2098
+ timeout: 20000,
2099
+ autoInstall: true
2100
+ },
2101
+ javascript: {
2102
+ command: "npx",
2103
+ args: ["typescript-language-server", "--stdio"],
2104
+ timeout: 15000,
2105
+ autoInstall: true
2106
+ },
2107
+ python: {
2108
+ command: "npx",
2109
+ args: ["pyright", "--stdio"],
2110
+ timeout: 15000,
2111
+ autoInstall: true
2112
+ },
2113
+ rust: {
2114
+ command: "rust-analyzer",
2115
+ timeout: 15000,
2116
+ autoInstall: false
2117
+ },
2118
+ go: {
2119
+ command: "gopls",
2120
+ timeout: 15000,
2121
+ autoInstall: false
2122
+ },
2123
+ json: {
2124
+ command: "npx",
2125
+ args: ["vscode-json-languageserver", "--stdio"],
2126
+ timeout: 1e4,
2127
+ autoInstall: true
2128
+ },
2129
+ html: {
2130
+ command: "npx",
2131
+ args: ["vscode-html-languageserver", "--stdio"],
2132
+ timeout: 1e4,
2133
+ autoInstall: true
2134
+ },
2135
+ css: {
2136
+ command: "npx",
2137
+ args: ["vscode-css-languageserver", "--stdio"],
2138
+ timeout: 1e4,
2139
+ autoInstall: true
2140
+ }
2141
+ }
2142
+ };
2143
+ LANGUAGE_MAP = {
2144
+ ts: "typescript",
2145
+ tsx: "typescript",
2146
+ js: "javascript",
2147
+ jsx: "javascript",
2148
+ py: "python",
2149
+ rs: "rust",
2150
+ go: "go",
2151
+ json: "json",
2152
+ html: "html",
2153
+ css: "css",
2154
+ scss: "css"
2155
+ };
2156
+ });
2157
+
2079
2158
  // src/config/defaults.ts
2080
2159
  var DEFAULTS;
2081
2160
  var init_defaults = __esm(() => {
2082
2161
  init_security();
2162
+ init_config();
2083
2163
  DEFAULTS = {
2084
2164
  version: "2.0.0",
2085
2165
  model: "qwen3.5-9b",
@@ -2125,9 +2205,9 @@ var init_defaults = __esm(() => {
2125
2205
  offloadKvCacheToGpu: true
2126
2206
  },
2127
2207
  retry: {
2128
- maxRetries: 5,
2129
- baseDelay: 5000,
2130
- maxDelay: 120000
2208
+ maxRetries: 3,
2209
+ baseDelay: 1000,
2210
+ maxDelay: 30000
2131
2211
  },
2132
2212
  maxToolIterations: 1000,
2133
2213
  stuckThreshold: 8,
@@ -2168,7 +2248,8 @@ var init_defaults = __esm(() => {
2168
2248
  enabled: false,
2169
2249
  isolatePlugins: true,
2170
2250
  isolateTempFiles: true
2171
- }
2251
+ },
2252
+ lsp: DEFAULT_LSP_CONFIG
2172
2253
  };
2173
2254
  });
2174
2255
 
@@ -3751,7 +3832,7 @@ function saveConfig(config, configPath) {
3751
3832
  writeFileSync3(configPath, JSON.stringify(config, regexReplacer, 2), "utf-8");
3752
3833
  }
3753
3834
  }
3754
- var init_config = __esm(() => {
3835
+ var init_config2 = __esm(() => {
3755
3836
  init_defaults();
3756
3837
  init_security();
3757
3838
  init_i18n();
@@ -3810,6 +3891,10 @@ var init_data_sanitizer = __esm(() => {
3810
3891
  {
3811
3892
  pattern: /Bearer\s+[a-zA-Z0-9_-]{20,}/gi,
3812
3893
  replacement: "Bearer [REDACTED]"
3894
+ },
3895
+ {
3896
+ pattern: /\b([a-zA-Z0-9_-]{30,})\b/g,
3897
+ replacement: "[REDACTED]"
3813
3898
  }
3814
3899
  ];
3815
3900
  });
@@ -4431,12 +4516,12 @@ class OpenAICompatProvider {
4431
4516
  };
4432
4517
  this.rateLimiter = createRateLimiter(config.rateLimits);
4433
4518
  }
4434
- async* chat(messages, tools, signal) {
4519
+ async* chat(messages, tools) {
4435
4520
  if (!this.rateLimiter.canMakeRequest()) {
4436
4521
  throw new Error(`Rate limit exceeded: ${this.rateLimiter.getConfig().maxRequestsPerMinute} requests per minute`);
4437
4522
  }
4438
4523
  this.rateLimiter.recordRequest();
4439
- const streamResult = this.doStream(messages, tools, signal);
4524
+ const streamResult = this.doStream(messages, tools);
4440
4525
  let hasToolCall = false;
4441
4526
  let hasText = false;
4442
4527
  let reasoningAcc = "";
@@ -4451,13 +4536,13 @@ class OpenAICompatProvider {
4451
4536
  yield chunk;
4452
4537
  }
4453
4538
  if (!hasToolCall && !hasText) {
4454
- const fallback = await this.doNonStreaming(messages, tools, signal);
4539
+ const fallback = await this.doNonStreaming(messages, tools);
4455
4540
  for (const chunk of fallback) {
4456
4541
  yield chunk;
4457
4542
  }
4458
4543
  }
4459
4544
  }
4460
- async* doStream(messages, tools, externalSignal) {
4545
+ async* doStream(messages, tools) {
4461
4546
  const body = {
4462
4547
  model: this.model,
4463
4548
  messages,
@@ -4484,15 +4569,6 @@ class OpenAICompatProvider {
4484
4569
  const controller = new AbortController;
4485
4570
  const totalTimeoutMs = 120000;
4486
4571
  const timeoutId = setTimeout(() => controller.abort(), totalTimeoutMs);
4487
- if (externalSignal) {
4488
- if (externalSignal.aborted) {
4489
- controller.abort();
4490
- } else {
4491
- externalSignal.addEventListener("abort", () => controller.abort(), {
4492
- once: true
4493
- });
4494
- }
4495
- }
4496
4572
  const response = await this.fetchWithRetry(`${this.config.baseUrl}/chat/completions`, {
4497
4573
  method: "POST",
4498
4574
  headers,
@@ -4596,7 +4672,7 @@ class OpenAICompatProvider {
4596
4672
  reader.releaseLock();
4597
4673
  }
4598
4674
  }
4599
- async doNonStreaming(messages, tools, externalSignal) {
4675
+ async doNonStreaming(messages, tools) {
4600
4676
  const body = {
4601
4677
  model: this.model,
4602
4678
  messages,
@@ -4621,15 +4697,11 @@ class OpenAICompatProvider {
4621
4697
  headers["Authorization"] = `Bearer ${this.config.apiKey}`;
4622
4698
  }
4623
4699
  try {
4624
- const fetchInit = {
4700
+ const response = await this.fetchWithRetry(`${this.config.baseUrl}/chat/completions`, {
4625
4701
  method: "POST",
4626
4702
  headers,
4627
4703
  body: JSON.stringify(body)
4628
- };
4629
- if (externalSignal) {
4630
- fetchInit.signal = externalSignal;
4631
- }
4632
- const response = await this.fetchWithRetry(`${this.config.baseUrl}/chat/completions`, fetchInit);
4704
+ });
4633
4705
  if (!response.ok) {
4634
4706
  const errorText = await response.text();
4635
4707
  throw new Error(t("error.llm_api", {
@@ -4893,8 +4965,7 @@ function runCommand(command, options = {}) {
4893
4965
  cwd,
4894
4966
  callId,
4895
4967
  timeoutMs = 120000,
4896
- maxBuffer = 10 * 1024 * 1024,
4897
- onOutput
4968
+ maxBuffer = 10 * 1024 * 1024
4898
4969
  } = options;
4899
4970
  return new Promise((resolve) => {
4900
4971
  let timedOut = false;
@@ -4913,7 +4984,6 @@ function runCommand(command, options = {}) {
4913
4984
  const decodeChunk = (chunk) => decoder ? decoder.decode(chunk, { stream: true }) : chunk.toString("utf-8");
4914
4985
  child.stdout?.on("data", (chunk) => {
4915
4986
  const text = decodeChunk(chunk);
4916
- onOutput?.(text);
4917
4987
  const next = stdoutRef.value.length + text.length;
4918
4988
  if (next > maxBuffer) {
4919
4989
  stdoutRef.value = stdoutRef.value.slice(stdoutRef.value.length + text.length - maxBuffer) + text;
@@ -4923,7 +4993,6 @@ function runCommand(command, options = {}) {
4923
4993
  });
4924
4994
  child.stderr?.on("data", (chunk) => {
4925
4995
  const text = decodeChunk(chunk);
4926
- onOutput?.(text);
4927
4996
  const next = stderrRef.value.length + text.length;
4928
4997
  if (next > maxBuffer) {
4929
4998
  stderrRef.value = stderrRef.value.slice(stderrRef.value.length + text.length - maxBuffer) + text;
@@ -4957,13 +5026,7 @@ function runCommand(command, options = {}) {
4957
5026
  clearTimeout(timer);
4958
5027
  if (callId)
4959
5028
  activeChildren.delete(callId);
4960
- resolve({
4961
- stdout: stdoutRef.value,
4962
- stderr: stderrRef.value,
4963
- code,
4964
- signal,
4965
- timedOut
4966
- });
5029
+ resolve({ stdout: stdoutRef.value, stderr: stderrRef.value, code, signal, timedOut });
4967
5030
  });
4968
5031
  });
4969
5032
  }
@@ -4972,69 +5035,11 @@ var init_runner = __esm(() => {
4972
5035
  activeChildren = new Map;
4973
5036
  });
4974
5037
 
4975
- // src/tools/cache.ts
4976
- class ToolResultCache {
4977
- cache = new Map;
4978
- maxEntries;
4979
- defaultTtlMs;
4980
- constructor(maxEntries = 50, defaultTtlMs = 60000) {
4981
- this.maxEntries = maxEntries;
4982
- this.defaultTtlMs = defaultTtlMs;
4983
- }
4984
- get(key) {
4985
- const entry = this.cache.get(key);
4986
- if (!entry)
4987
- return;
4988
- if (Date.now() > entry.expiresAt) {
4989
- this.cache.delete(key);
4990
- return;
4991
- }
4992
- this.cache.delete(key);
4993
- this.cache.set(key, entry);
4994
- return entry.value;
4995
- }
4996
- set(key, value, ttlMs) {
4997
- if (this.cache.size >= this.maxEntries) {
4998
- const firstKey = this.cache.keys().next().value;
4999
- if (firstKey !== undefined) {
5000
- this.cache.delete(firstKey);
5001
- }
5002
- }
5003
- this.cache.set(key, {
5004
- value,
5005
- expiresAt: Date.now() + (ttlMs ?? this.defaultTtlMs)
5006
- });
5007
- }
5008
- has(key) {
5009
- return this.get(key) !== undefined;
5010
- }
5011
- cleanExpired() {
5012
- const now = Date.now();
5013
- for (const [key, entry] of this.cache) {
5014
- if (now > entry.expiresAt) {
5015
- this.cache.delete(key);
5016
- }
5017
- }
5018
- }
5019
- clear() {
5020
- this.cache.clear();
5021
- }
5022
- get size() {
5023
- return this.cache.size;
5024
- }
5025
- }
5026
- function hashKey(toolName, args) {
5027
- const payload = toolName + JSON.stringify(args);
5028
- const hash = Bun.hash(payload).toString(16).slice(0, 16);
5029
- return hash;
5030
- }
5031
-
5032
5038
  // src/tools/executor.ts
5033
5039
  class ToolExecutor {
5034
5040
  registry;
5035
5041
  ctx;
5036
5042
  pluginManager;
5037
- cache = new ToolResultCache(50, CACHE_TTL_MS);
5038
5043
  constructor(registry, ctx, pluginManager) {
5039
5044
  this.registry = registry;
5040
5045
  this.ctx = ctx;
@@ -5049,18 +5054,6 @@ class ToolExecutor {
5049
5054
  toolCallId: call.id
5050
5055
  };
5051
5056
  }
5052
- if (CACHEABLE_TOOLS.has(call.name)) {
5053
- const key = hashKey(call.name, call.arguments);
5054
- const cached = this.cache.get(key);
5055
- if (cached !== undefined) {
5056
- this.ctx.logger.debug(`Tool ${call.name}: CACHE HIT`);
5057
- return {
5058
- success: true,
5059
- output: cached,
5060
- toolCallId: call.id
5061
- };
5062
- }
5063
- }
5064
5057
  for (const plugin of this.pluginManager.getAllPlugins()) {
5065
5058
  if (plugin.onBeforeTool) {
5066
5059
  try {
@@ -5131,12 +5124,6 @@ class ToolExecutor {
5131
5124
  }
5132
5125
  }
5133
5126
  }
5134
- if (result.success && CACHEABLE_TOOLS.has(call.name)) {
5135
- const key = hashKey(call.name, call.arguments);
5136
- this.cache.set(key, result.output);
5137
- this.ctx.logger.debug(`Tool ${call.name}: CACHED`);
5138
- }
5139
- this.cache.cleanExpired();
5140
5127
  this.ctx.logger.debug(`Tool ${call.name}: ${result.success ? "OK" : "FAIL"}`);
5141
5128
  return result;
5142
5129
  }
@@ -5146,24 +5133,17 @@ class ToolExecutor {
5146
5133
  getRegistry() {
5147
5134
  return this.registry;
5148
5135
  }
5149
- getContext() {
5150
- return this.ctx;
5151
- }
5152
5136
  setScope(scope) {
5153
5137
  this.ctx.scope = scope;
5154
5138
  }
5155
- setOnMeta(onMeta) {
5156
- this.ctx.onMeta = onMeta;
5157
- }
5158
5139
  updateProvider(provider) {
5159
5140
  this.ctx.llmProvider = provider;
5160
5141
  }
5161
5142
  }
5162
- var TOOL_EXECUTION_TIMEOUT_MS = 60000, CACHEABLE_TOOLS, CACHE_TTL_MS = 60000;
5143
+ var TOOL_EXECUTION_TIMEOUT_MS = 60000;
5163
5144
  var init_executor = __esm(() => {
5164
5145
  init_runner();
5165
5146
  init_i18n();
5166
- CACHEABLE_TOOLS = new Set(["web_fetch"]);
5167
5147
  });
5168
5148
 
5169
5149
  // src/modules/security/path-validator.ts
@@ -5694,7 +5674,7 @@ function safeResolvePath(baseDir, userPath) {
5694
5674
  var init_path_utils = () => {};
5695
5675
 
5696
5676
  // src/tools/preview.ts
5697
- var MAX_PREVIEW_LINES = 100;
5677
+ var MAX_PREVIEW_LINES = 15;
5698
5678
 
5699
5679
  // src/tools/read-file.ts
5700
5680
  import { readFileSync as readFileSync5, existsSync as existsSync9 } from "fs";
@@ -6268,8 +6248,7 @@ var init_edit_file = __esm(() => {
6268
6248
  output: t("file.string_not_found", { str: oldStr })
6269
6249
  };
6270
6250
  }
6271
- const occurrences = content.split(oldStr).length - 1;
6272
- const updated = occurrences > 1 ? content.replaceAll(oldStr, newStr) : content.replace(oldStr, newStr);
6251
+ const updated = content.replace(oldStr, newStr);
6273
6252
  const scanResult = scanContent(updated, path, ctx.config.security?.contentScan);
6274
6253
  if (!scanResult.allowed) {
6275
6254
  logSecurityBlock(ctx.sessionId, "file_write", scanResult.reason || "Content contains dangerous patterns", path);
@@ -6676,12 +6655,6 @@ var init_file_info = __esm(() => {
6676
6655
  });
6677
6656
 
6678
6657
  // src/modules/security/command-validator.ts
6679
- function hasShellIndirection(command) {
6680
- return /\$\{[^}]+\}/.test(command) || /\$\(/.test(command) || /`[^`]+`/.test(command) || /\$\(\(/.test(command) || /\$\{[!]/.test(command);
6681
- }
6682
- function hasEvalConstruct(command) {
6683
- return /\beval\b/.test(command) || /\bsource\b/.test(command);
6684
- }
6685
6658
  function extractBaseCommand(trimmed) {
6686
6659
  const tokens = trimmed.split(/\s+/);
6687
6660
  let i = 0;
@@ -6737,18 +6710,6 @@ function isCommandAllowed(command, securityConfig) {
6737
6710
  reason: `Shell wrapper "${baseForShellCheck}" is blocked — use the bash tool directly`
6738
6711
  };
6739
6712
  }
6740
- if (hasShellIndirection(trimmedCommand)) {
6741
- return {
6742
- allowed: false,
6743
- reason: `Shell indirection (variable expansion, command substitution, or backtick execution) is not allowed`
6744
- };
6745
- }
6746
- if (hasEvalConstruct(trimmedCommand)) {
6747
- return {
6748
- allowed: false,
6749
- reason: `eval/source constructs are not allowed`
6750
- };
6751
- }
6752
6713
  if (config.blockDangerousFlags) {
6753
6714
  for (const op of config.dangerousOperators || []) {
6754
6715
  if (containsOperator(trimmedCommand, op)) {
@@ -6759,15 +6720,7 @@ function isCommandAllowed(command, securityConfig) {
6759
6720
  }
6760
6721
  }
6761
6722
  }
6762
- const baseCommand = baseForShellCheck;
6763
- if (!baseCommand || baseCommand === trimmedCommand.trim()) {
6764
- if (baseCommand === "sudo" || baseCommand === "env" || baseCommand === "nohup" || baseCommand === "exec") {
6765
- return {
6766
- allowed: false,
6767
- reason: `Prefix "${baseCommand}" requires a target command`
6768
- };
6769
- }
6770
- }
6723
+ const baseCommand = extractBaseCommand(trimmedCommand);
6771
6724
  if (config.whitelist.length > 0) {
6772
6725
  if (!config.whitelist.includes(baseCommand)) {
6773
6726
  return {
@@ -7085,14 +7038,8 @@ var init_bash = __esm(() => {
7085
7038
  type: "object",
7086
7039
  properties: {
7087
7040
  command: { type: "string", description: "Shell command to execute" },
7088
- workdir: {
7089
- type: "string",
7090
- description: "Working directory (default: baseDir)"
7091
- },
7092
- background: {
7093
- type: "boolean",
7094
- description: "Start the command in the background and return immediately with a process id (default: auto-detect long-running commands)"
7095
- }
7041
+ workdir: { type: "string", description: "Working directory (default: baseDir)" },
7042
+ background: { type: "boolean", description: "Start the command in the background and return immediately with a process id (default: auto-detect long-running commands)" }
7096
7043
  },
7097
7044
  required: ["command"]
7098
7045
  },
@@ -7139,8 +7086,7 @@ ${t("proc.manage_hint", {
7139
7086
  const res = await runCommand(command, {
7140
7087
  cwd: workdir,
7141
7088
  callId: ctx.activeCallId,
7142
- timeoutMs: BASH_TIMEOUT_MS,
7143
- onOutput: ctx.onMeta
7089
+ timeoutMs: BASH_TIMEOUT_MS
7144
7090
  });
7145
7091
  const parts = [res.stdout.trimEnd(), res.stderr.trimEnd()].filter(Boolean);
7146
7092
  let output = parts.join(`
@@ -8443,12 +8389,7 @@ function validatePlan(plan, config) {
8443
8389
  const warnings = [];
8444
8390
  const autoFixes = [];
8445
8391
  if (!plan.subtasks || plan.subtasks.length === 0) {
8446
- return {
8447
- valid: false,
8448
- errors: ["Plan has no subtasks"],
8449
- warnings: [],
8450
- autoFixes: []
8451
- };
8392
+ return { valid: false, errors: ["Plan has no subtasks"], warnings: [], autoFixes: [] };
8452
8393
  }
8453
8394
  errors.push(...expertTagsExist(plan.subtasks, config));
8454
8395
  errors.push(...hasCycle(plan.subtasks));
@@ -8457,10 +8398,7 @@ function validatePlan(plan, config) {
8457
8398
  const readOverlaps = deleteReadOverlap(plan.subtasks);
8458
8399
  for (const overlap of readOverlaps) {
8459
8400
  if (overlap.canAutoFix) {
8460
- autoFixes.push({
8461
- subtaskId: overlap.subtaskId,
8462
- fix: `Add depends_on: ${overlap.dependsOn}`
8463
- });
8401
+ autoFixes.push({ subtaskId: overlap.subtaskId, fix: `Add depends_on: ${overlap.dependsOn}` });
8464
8402
  } else if (overlap.error) {
8465
8403
  errors.push(overlap.error);
8466
8404
  }
@@ -8506,6 +8444,7 @@ function hasCycle(subtasks) {
8506
8444
  }
8507
8445
  const errors = [];
8508
8446
  for (const s of subtasks) {
8447
+ visited.clear();
8509
8448
  inStack.clear();
8510
8449
  if (dfs(s.id)) {
8511
8450
  errors.push(`Cycle detected involving subtask "${s.id}"`);
@@ -8763,26 +8702,13 @@ class MoEExecutor {
8763
8702
  constructor(deps) {
8764
8703
  this.deps = deps;
8765
8704
  }
8766
- async executePlan(plan, signal) {
8705
+ async executePlan(plan) {
8767
8706
  const results = [];
8768
8707
  const errors = [];
8769
8708
  const warnings = [];
8770
- if (signal?.aborted) {
8771
- return {
8772
- success: false,
8773
- results: [],
8774
- errors: ["Execution aborted before start"],
8775
- warnings: []
8776
- };
8777
- }
8778
8709
  const waves = topologicalSort(plan.subtasks);
8779
8710
  if (waves.length === 0) {
8780
- return {
8781
- success: false,
8782
- results: [],
8783
- errors: ["Failed to topologically sort subtasks (possible cycle)"],
8784
- warnings: []
8785
- };
8711
+ return { success: false, results: [], errors: ["Failed to topologically sort subtasks (possible cycle)"], warnings: [] };
8786
8712
  }
8787
8713
  const sortedCount = waves.flat().length;
8788
8714
  if (sortedCount < plan.subtasks.length) {
@@ -8790,17 +8716,11 @@ class MoEExecutor {
8790
8716
  return {
8791
8717
  success: false,
8792
8718
  results: [],
8793
- errors: [
8794
- `Missing subtasks after topological sort: ${missing.join(", ")} (dangling or invalid depends_on)`
8795
- ],
8719
+ errors: [`Missing subtasks after topological sort: ${missing.join(", ")} (dangling or invalid depends_on)`],
8796
8720
  warnings: []
8797
8721
  };
8798
8722
  }
8799
8723
  for (let waveIdx = 0;waveIdx < waves.length; waveIdx++) {
8800
- if (signal?.aborted) {
8801
- warnings.push(`Execution aborted during wave ${waveIdx + 1}/${waves.length}`);
8802
- break;
8803
- }
8804
8724
  const wave = waves[waveIdx];
8805
8725
  const wavePromises = wave.map((subtask) => executeSubtask(subtask, this.deps, plan.shared_context).then((result) => {
8806
8726
  results.push(result);
@@ -9000,12 +8920,7 @@ var init_verifier = __esm(() => {
9000
8920
  // src/core/agent-moe.ts
9001
8921
  async function runWithMoE(deps, input, fallback, opts = {}) {
9002
8922
  const { config, llmProvider, logger, toolExecutor, baseDir } = deps;
9003
- const { onMeta, onPhase, signal } = opts;
9004
- const abortCheck = () => {
9005
- if (signal?.aborted)
9006
- return true;
9007
- return false;
9008
- };
8923
+ const { onMeta, onPhase } = opts;
9009
8924
  const orchestrator = new OrchestratorClient({
9010
8925
  model: config.orchestrator.model,
9011
8926
  provider: config.orchestrator.provider
@@ -9051,7 +8966,7 @@ async function runWithMoE(deps, input, fallback, opts = {}) {
9051
8966
  const executor = new MoEExecutor(moeDeps);
9052
8967
  onMeta?.(`⚙️ Executing ${plan.subtasks.length} subtasks...
9053
8968
  `);
9054
- const planResults = await executor.executePlan(plan, signal);
8969
+ const planResults = await executor.executePlan(plan);
9055
8970
  onMeta?.(`✅ Execution complete: ${planResults.results.filter((r) => r.success).length}/${planResults.results.length} succeeded
9056
8971
  `);
9057
8972
  const verifier = new StepVerifier(baseDir);
@@ -9231,16 +9146,6 @@ var init_store = __esm(() => {
9231
9146
 
9232
9147
  // src/core/agent.ts
9233
9148
  import { join as join10 } from "path";
9234
- function canRunInParallel(calls) {
9235
- if (calls.length <= 1)
9236
- return false;
9237
- for (const call of calls) {
9238
- if (SIDE_EFFECT_TOOLS.has(call.name) || WRITE_TOOLS.has(call.name)) {
9239
- return false;
9240
- }
9241
- }
9242
- return true;
9243
- }
9244
9149
 
9245
9150
  class Agent {
9246
9151
  deps;
@@ -9262,6 +9167,10 @@ class Agent {
9262
9167
  const systemBudget = Math.floor(this.deps.config.contextWindow * this.deps.config.contextBudget.systemPrompt);
9263
9168
  const builder = new PromptBuilder(systemBudget);
9264
9169
  builder.addBlocks(this.deps.promptBlocks);
9170
+ const dynamic = this.deps.getDynamicPromptBlocks?.() ?? [];
9171
+ if (dynamic.length > 0) {
9172
+ builder.addBlocks(dynamic);
9173
+ }
9265
9174
  const pluginBlocks = (this.deps.pluginManager.runOnBuildPrompt?.() ?? []).filter((s) => Boolean(s && s.trim() !== "")).map((content) => ({
9266
9175
  content,
9267
9176
  priority: "low",
@@ -9271,10 +9180,6 @@ class Agent {
9271
9180
  if (pluginBlocks.length > 0) {
9272
9181
  builder.addBlocks(pluginBlocks);
9273
9182
  }
9274
- const dynamic = this.deps.getDynamicPromptBlocks?.() ?? [];
9275
- if (dynamic.length > 0) {
9276
- builder.addBlocks(dynamic);
9277
- }
9278
9183
  return builder.build();
9279
9184
  }
9280
9185
  getSystemPromptInfo() {
@@ -9345,7 +9250,7 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
9345
9250
  toolExecutor,
9346
9251
  logger,
9347
9252
  baseDir: this.deps.baseDir
9348
- }, input, () => this.executeSingleAgentLoop(input, onChunk, onMeta, onTool, onPhase), { onMeta, onTool, onPhase, signal: this.abortController?.signal });
9253
+ }, input, () => this.executeSingleAgentLoop(input, onChunk, onMeta, onTool, onPhase), { onMeta, onTool, onPhase });
9349
9254
  }
9350
9255
  return this.executeSingleAgentLoop(input, onChunk, onMeta, onTool, onPhase);
9351
9256
  }
@@ -9363,7 +9268,6 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
9363
9268
  } = this.deps;
9364
9269
  const slog = new SessionLogger(sessionManager);
9365
9270
  this.abortController = new AbortController;
9366
- this.shutdownRequested = false;
9367
9271
  let iteration = 0;
9368
9272
  let lastText = "";
9369
9273
  let hallucinationRetries = 0;
@@ -9409,7 +9313,7 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
9409
9313
  const textChunks = [];
9410
9314
  this.emitPhase(iteration, "thinking", onPhase);
9411
9315
  try {
9412
- for await (const chunk of llmProvider.chat(history, allTools, this.abortController?.signal)) {
9316
+ for await (const chunk of llmProvider.chat(history, allTools)) {
9413
9317
  if (this.shutdownRequested)
9414
9318
  break;
9415
9319
  if (chunk.type === "text" && chunk.content) {
@@ -9504,7 +9408,7 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
9504
9408
  });
9505
9409
  const summaries = [];
9506
9410
  let anyToolFailed = false;
9507
- const executeToolCall = async (call) => {
9411
+ for (const call of toolCalls) {
9508
9412
  this.setScope();
9509
9413
  const startTime = Date.now();
9510
9414
  pluginManager.runOnToolCall({
@@ -9517,18 +9421,9 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
9517
9421
  const tokensBeforeTool = contextManager.getEstimatedTokens();
9518
9422
  const result = await toolExecutor.execute(call, this.abortController?.signal);
9519
9423
  const duration = Date.now() - startTime;
9520
- pluginManager.runOnToolEnd({ iteration, logger }, { id: call.id, name: call.name, arguments: call.arguments }, result, duration);
9521
- return { call, result, duration, tokensBefore: tokensBeforeTool };
9522
- };
9523
- const processToolResult = (entry) => {
9524
- const {
9525
- call,
9526
- result,
9527
- duration,
9528
- tokensBefore: tokensBeforeTool
9529
- } = entry;
9530
9424
  if (!result.success)
9531
9425
  anyToolFailed = true;
9426
+ pluginManager.runOnToolEnd({ iteration, logger }, { id: call.id, name: call.name, arguments: call.arguments }, result, duration);
9532
9427
  if (result.display) {
9533
9428
  onMeta?.(`
9534
9429
  ` + result.display + `
@@ -9568,30 +9463,11 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
9568
9463
  if (config.session.autoSave) {
9569
9464
  slog.logToolResult(call, result, duration, iteration);
9570
9465
  }
9571
- };
9572
- const toolExecutorForMeta = this.deps.toolExecutor;
9573
- const savedOnMeta = toolExecutorForMeta?.getContext?.()?.onMeta;
9574
- if (toolExecutorForMeta?.setOnMeta) {
9575
- toolExecutorForMeta.setOnMeta(onMeta);
9576
- }
9577
- if (canRunInParallel(toolCalls)) {
9578
- const entries = await Promise.all(toolCalls.map(executeToolCall));
9579
- for (const entry of entries) {
9580
- processToolResult(entry);
9581
- }
9582
- } else {
9583
- for (const call of toolCalls) {
9584
- const entry = await executeToolCall(call);
9585
- processToolResult(entry);
9466
+ if (contextManager.needsCompaction()) {
9467
+ contextManager.compact();
9468
+ logger.debug("Context compacted after tool result");
9586
9469
  }
9587
9470
  }
9588
- if (toolExecutorForMeta?.setOnMeta) {
9589
- toolExecutorForMeta.setOnMeta(savedOnMeta);
9590
- }
9591
- if (contextManager.needsCompaction()) {
9592
- contextManager.compact();
9593
- logger.debug("Context compacted after tool results");
9594
- }
9595
9471
  if (anyToolFailed) {
9596
9472
  consecutiveToolFailures++;
9597
9473
  } else {
@@ -9801,7 +9677,7 @@ ${taskReminder}</system-summary>`
9801
9677
  });
9802
9678
  }
9803
9679
  }
9804
- var TOOL_RESULT_MAX_TOKENS_RATIO = 0.3, TOOL_RESULT_ABSOLUTE_MAX_CHARS = 15000, WRITE_TOOLS, SIDE_EFFECT_TOOLS;
9680
+ var TOOL_RESULT_MAX_TOKENS_RATIO = 0.3, TOOL_RESULT_ABSOLUTE_MAX_CHARS = 15000;
9805
9681
  var init_agent = __esm(() => {
9806
9682
  init_i18n();
9807
9683
  init_colors();
@@ -9809,14 +9685,6 @@ var init_agent = __esm(() => {
9809
9685
  init_processes();
9810
9686
  init_agent_moe();
9811
9687
  init_store();
9812
- WRITE_TOOLS = new Set([
9813
- "write_file",
9814
- "edit_file",
9815
- "delete_file",
9816
- "move_file",
9817
- "create_dir"
9818
- ]);
9819
- SIDE_EFFECT_TOOLS = new Set(["bash", "subagent", "pipeline_run"]);
9820
9688
  });
9821
9689
 
9822
9690
  // src/modules/context/manager.ts
@@ -10520,7 +10388,8 @@ var init_subagent = __esm(() => {
10520
10388
  baseDir: ctx.baseDir,
10521
10389
  scope,
10522
10390
  toolTags,
10523
- promptBlocks: [systemPrompt]
10391
+ promptBlocks: [systemPrompt],
10392
+ recursionDepth: currentDepth + 1
10524
10393
  };
10525
10394
  const subAgent = new Agent(subDeps);
10526
10395
  const fullTask = context ? `${task}
@@ -13362,9 +13231,8 @@ var init_stuck_detector = __esm(() => {
13362
13231
  });
13363
13232
 
13364
13233
  // src/modules/execution/auditor.ts
13365
- import { execSync as execSync4 } from "child_process";
13366
13234
  import { existsSync as existsSync24 } from "fs";
13367
- import { resolve as resolve13, join as join18 } from "path";
13235
+ import { resolve as resolve13 } from "path";
13368
13236
 
13369
13237
  class Auditor {
13370
13238
  baseDir;
@@ -13387,22 +13255,16 @@ class Auditor {
13387
13255
  }
13388
13256
  const doneSteps = plan.steps.filter((s) => s.status === "done").length;
13389
13257
  const totalSteps = plan.steps.length;
13390
- const typeCheckError = await this.runProjectTypeCheck();
13391
13258
  let massEditWarning = null;
13392
13259
  if (uniqueFiles.length > MASS_EDIT_THRESHOLD) {
13393
13260
  massEditWarning = t("exec.mass_edit_warning", { count: String(uniqueFiles.length) });
13394
13261
  }
13395
- const passed = missingFiles.length === 0 && !typeCheckError;
13262
+ const passed = missingFiles.length === 0;
13396
13263
  let summary;
13397
13264
  if (passed) {
13398
13265
  summary = t("exec.audit_pass", { done: doneSteps, total: totalSteps, files: existingFiles.length });
13399
13266
  } else {
13400
- const missingCount = missingFiles.length;
13401
- if (typeCheckError) {
13402
- summary = t("exec.audit_fail_typecheck", { done: doneSteps, total: totalSteps, missing: missingCount, typeError: typeCheckError });
13403
- } else {
13404
- summary = t("exec.audit_fail", { done: doneSteps, total: totalSteps, files: missingCount });
13405
- }
13267
+ summary = t("exec.audit_fail", { done: doneSteps, total: totalSteps, files: missingFiles.length });
13406
13268
  }
13407
13269
  return {
13408
13270
  passed,
@@ -13410,31 +13272,9 @@ class Auditor {
13410
13272
  createdFiles: existingFiles,
13411
13273
  modifiedFiles: [],
13412
13274
  summary,
13413
- typeCheckError,
13414
13275
  massEditWarning
13415
13276
  };
13416
13277
  }
13417
- async runProjectTypeCheck() {
13418
- const tsconfigPath = join18(this.baseDir, "tsconfig.json");
13419
- if (!existsSync24(tsconfigPath)) {
13420
- return null;
13421
- }
13422
- try {
13423
- execSync4(`npx tsc --noEmit --skipLibCheck`, { cwd: this.baseDir, stdio: "pipe", timeout: 30000 });
13424
- return null;
13425
- } catch (err) {
13426
- if (err.status === 127 || err.message.includes("not found") || err.message.includes("ENOENT")) {
13427
- return null;
13428
- }
13429
- const stderr = err.stderr?.toString() || err.stdout?.toString() || "";
13430
- if (stderr.includes("error TS")) {
13431
- const firstError = stderr.split(`
13432
- `).find((line) => line.includes("error TS")) || "TypeScript type error";
13433
- return firstError.trim();
13434
- }
13435
- return null;
13436
- }
13437
- }
13438
13278
  }
13439
13279
  var MASS_EDIT_THRESHOLD = 10;
13440
13280
  var init_auditor = __esm(() => {
@@ -13443,16 +13283,16 @@ var init_auditor = __esm(() => {
13443
13283
 
13444
13284
  // src/modules/execution/plan-persister.ts
13445
13285
  import { readFileSync as readFileSync14, writeFileSync as writeFileSync9, mkdirSync as mkdirSync11, existsSync as existsSync25 } from "fs";
13446
- import { join as join19 } from "path";
13286
+ import { join as join18 } from "path";
13447
13287
 
13448
13288
  class PlanPersister {
13449
13289
  filePath;
13450
13290
  constructor(baseDir) {
13451
- const mmaDir = join19(baseDir, ".mma");
13291
+ const mmaDir = join18(baseDir, ".mma");
13452
13292
  if (!existsSync25(mmaDir)) {
13453
13293
  mkdirSync11(mmaDir, { recursive: true });
13454
13294
  }
13455
- this.filePath = join19(mmaDir, "plan.json");
13295
+ this.filePath = join18(mmaDir, "plan.json");
13456
13296
  }
13457
13297
  save(plan) {
13458
13298
  const file = {
@@ -14095,7 +13935,7 @@ var init_module = __esm(() => {
14095
13935
 
14096
13936
  // src/modules/security/session-encryption.ts
14097
13937
  import { readFileSync as readFileSync16, writeFileSync as writeFileSync10, existsSync as existsSync27, readdirSync as readdirSync6, unlinkSync as unlinkSync3 } from "fs";
14098
- import { join as join20 } from "path";
13938
+ import { join as join19 } from "path";
14099
13939
  import { homedir as homedir8 } from "os";
14100
13940
 
14101
13941
  class SessionFileEncryptor {
@@ -14104,7 +13944,7 @@ class SessionFileEncryptor {
14104
13944
  constructor(config) {
14105
13945
  this.config = { ...DEFAULT_SESSION_ENCRYPTION, ...config };
14106
13946
  this.encryptor = new ConfigEncryptor({
14107
- keyPath: config?.keyPath || join20(homedir8(), ".mma", ".session-encryption-key")
13947
+ keyPath: config?.keyPath || join19(homedir8(), ".mma", ".session-encryption-key")
14108
13948
  });
14109
13949
  }
14110
13950
  isEnabled() {
@@ -14176,7 +14016,7 @@ class SessionFileEncryptor {
14176
14016
  return;
14177
14017
  const files = readdirSync6(sessionDir);
14178
14018
  for (const file of files) {
14179
- const filePath = join20(sessionDir, file);
14019
+ const filePath = join19(sessionDir, file);
14180
14020
  if (existsSync27(filePath) && !file.endsWith(".enc")) {
14181
14021
  try {
14182
14022
  const content = readFileSync16(filePath, "utf8");
@@ -14193,7 +14033,7 @@ class SessionFileEncryptor {
14193
14033
  const files = readdirSync6(sessionDir);
14194
14034
  for (const file of files) {
14195
14035
  if (file.endsWith(".enc")) {
14196
- const encFilePath = join20(sessionDir, file);
14036
+ const encFilePath = join19(sessionDir, file);
14197
14037
  const decFilePath = encFilePath.slice(0, -4);
14198
14038
  try {
14199
14039
  const content = readFileSync16(encFilePath, "utf8");
@@ -14226,7 +14066,7 @@ import {
14226
14066
  writeFileSync as writeFileSync11,
14227
14067
  appendFileSync as appendFileSync5
14228
14068
  } from "fs";
14229
- import { join as join21 } from "path";
14069
+ import { join as join20 } from "path";
14230
14070
  import { gzipSync } from "zlib";
14231
14071
 
14232
14072
  class SessionStore {
@@ -14252,16 +14092,16 @@ class SessionStore {
14252
14092
  mkdirSync12(this.baseDir, { recursive: true });
14253
14093
  }
14254
14094
  sessionDir(id) {
14255
- return join21(this.baseDir, id);
14095
+ return join20(this.baseDir, id);
14256
14096
  }
14257
14097
  metaPath(id) {
14258
- return join21(this.sessionDir(id), "meta.json");
14098
+ return join20(this.sessionDir(id), "meta.json");
14259
14099
  }
14260
14100
  historyPath(id) {
14261
- return join21(this.sessionDir(id), "history.jsonl");
14101
+ return join20(this.sessionDir(id), "history.jsonl");
14262
14102
  }
14263
14103
  sessionLogPath(id) {
14264
- return join21(this.sessionDir(id), "session.jsonl");
14104
+ return join20(this.sessionDir(id), "session.jsonl");
14265
14105
  }
14266
14106
  sessionExists(id) {
14267
14107
  return existsSync28(this.metaPath(id));
@@ -14384,7 +14224,7 @@ class SessionStore {
14384
14224
  if (existsSync28(historyPath)) {
14385
14225
  const content = readFileSync17(historyPath, "utf-8");
14386
14226
  const compressed = gzipSync(content);
14387
- const gzPath = join21(this.baseDir, `${session2.id}.jsonl.gz`);
14227
+ const gzPath = join20(this.baseDir, `${session2.id}.jsonl.gz`);
14388
14228
  writeFileSync11(gzPath, compressed);
14389
14229
  rmSync(historyPath);
14390
14230
  }
@@ -14592,7 +14432,7 @@ class ProfileCompressor {
14592
14432
 
14593
14433
  // src/modules/user-profile/profile.ts
14594
14434
  import { readFileSync as readFileSync18, writeFileSync as writeFileSync12, existsSync as existsSync29, mkdirSync as mkdirSync13 } from "fs";
14595
- import { join as join22 } from "path";
14435
+ import { join as join21 } from "path";
14596
14436
  import { homedir as homedir9, hostname, platform as platform4, type } from "os";
14597
14437
  import { env } from "process";
14598
14438
 
@@ -14619,10 +14459,10 @@ class UserProfile {
14619
14459
  if (!existsSync29(this.profileDir)) {
14620
14460
  mkdirSync13(this.profileDir, { recursive: true });
14621
14461
  }
14622
- writeFileSync12(join22(this.profileDir, "profile.json"), JSON.stringify({ ...this.info, preferences: this.preferences }, null, 2), "utf-8");
14462
+ writeFileSync12(join21(this.profileDir, "profile.json"), JSON.stringify({ ...this.info, preferences: this.preferences }, null, 2), "utf-8");
14623
14463
  }
14624
14464
  load() {
14625
- const path = join22(this.profileDir, "profile.json");
14465
+ const path = join21(this.profileDir, "profile.json");
14626
14466
  if (!existsSync29(path))
14627
14467
  return null;
14628
14468
  try {
@@ -14662,7 +14502,7 @@ var init_profile = () => {};
14662
14502
 
14663
14503
  // src/modules/skills/loader.ts
14664
14504
  import { readdirSync as readdirSync8, readFileSync as readFileSync19, existsSync as existsSync30, statSync as statSync5 } from "fs";
14665
- import { join as join23 } from "path";
14505
+ import { join as join22 } from "path";
14666
14506
 
14667
14507
  class SkillsLoader {
14668
14508
  loadFromDir(dirPath) {
@@ -14675,7 +14515,7 @@ class SkillsLoader {
14675
14515
  scanDir(dirPath, skills) {
14676
14516
  const entries = readdirSync8(dirPath);
14677
14517
  for (const entry of entries) {
14678
- const fullPath = join23(dirPath, entry);
14518
+ const fullPath = join22(dirPath, entry);
14679
14519
  const stat = statSync5(fullPath);
14680
14520
  if (stat.isDirectory()) {
14681
14521
  this.scanDir(fullPath, skills);
@@ -14954,9 +14794,320 @@ var init_browser2 = __esm(() => {
14954
14794
  init_types();
14955
14795
  });
14956
14796
 
14797
+ // src/modules/lsp/client.ts
14798
+ import { spawn as spawn4, execSync as execSync4 } from "child_process";
14799
+ import { resolve as resolve15 } from "path";
14800
+
14801
+ class LspClient {
14802
+ process = null;
14803
+ requestId = 0;
14804
+ pending = new Map;
14805
+ buffer = "";
14806
+ contentLength = -1;
14807
+ diagnostics = [];
14808
+ diagnosticsResolve = null;
14809
+ diagnosticsTimer = null;
14810
+ initialized = false;
14811
+ async checkFile(filePath, baseDir, config) {
14812
+ const timeout = config.timeout ?? DEFAULT_TIMEOUT;
14813
+ try {
14814
+ await this.startServer(config, baseDir);
14815
+ const rootUri = this.pathToUri(resolve15(baseDir));
14816
+ const initResult = await this.sendRequest("initialize", {
14817
+ processId: process.pid,
14818
+ rootUri,
14819
+ workspaceFolders: [{ uri: rootUri, name: "workspace" }],
14820
+ capabilities: { textDocument: { publishDiagnostics: {} } }
14821
+ }, timeout);
14822
+ this.initialized = true;
14823
+ this.sendNotification("initialized", {});
14824
+ const uri = this.pathToUri(resolve15(filePath));
14825
+ const fs2 = await import("fs");
14826
+ const content = fs2.readFileSync(filePath, "utf-8");
14827
+ const diagPromise = new Promise((resolve16) => {
14828
+ this.diagnosticsResolve = resolve16;
14829
+ this.diagnostics = [];
14830
+ this.diagnosticsTimer = setTimeout(() => {
14831
+ if (this.diagnosticsResolve) {
14832
+ this.diagnosticsResolve([]);
14833
+ this.diagnosticsResolve = null;
14834
+ }
14835
+ }, timeout);
14836
+ });
14837
+ this.sendNotification("textDocument/didOpen", {
14838
+ textDocument: {
14839
+ uri,
14840
+ languageId: this.languageFromPath(filePath),
14841
+ version: 1,
14842
+ text: content
14843
+ }
14844
+ });
14845
+ return await diagPromise;
14846
+ } catch {
14847
+ return [];
14848
+ } finally {
14849
+ await this.shutdown();
14850
+ }
14851
+ }
14852
+ async startServer(config, baseDir) {
14853
+ if (config.autoInstall === false) {
14854
+ try {
14855
+ execSync4(`where ${config.command}`, { stdio: "pipe", timeout: 3000 });
14856
+ } catch {
14857
+ throw new Error(`${config.command} not found in PATH`);
14858
+ }
14859
+ }
14860
+ return new Promise((resolve16, reject) => {
14861
+ const args = config.args ?? [];
14862
+ const proc = spawn4(config.command, args, {
14863
+ stdio: ["pipe", "pipe", "pipe"],
14864
+ env: { ...process.env, ...config.env },
14865
+ cwd: baseDir
14866
+ });
14867
+ proc.on("error", reject);
14868
+ proc.stdout.on("data", (chunk) => {
14869
+ this.handleData(chunk);
14870
+ });
14871
+ proc.stderr.on("data", () => {});
14872
+ proc.once("spawn", () => {
14873
+ resolve16();
14874
+ });
14875
+ this.process = proc;
14876
+ setTimeout(() => {
14877
+ if (!this.initialized && this.process) {
14878
+ reject(new Error("LSP server start timeout"));
14879
+ }
14880
+ }, config.timeout ?? 1e4);
14881
+ });
14882
+ }
14883
+ handleData(chunk) {
14884
+ this.buffer += chunk.toString();
14885
+ this.parseMessages();
14886
+ }
14887
+ parseMessages() {
14888
+ while (true) {
14889
+ if (this.contentLength === -1) {
14890
+ const headerEnd = this.buffer.indexOf(`\r
14891
+ \r
14892
+ `);
14893
+ if (headerEnd === -1)
14894
+ return;
14895
+ const header = this.buffer.slice(0, headerEnd);
14896
+ const match = header.match(/Content-Length: (\d+)/i);
14897
+ if (!match) {
14898
+ this.buffer = this.buffer.slice(headerEnd + 4);
14899
+ this.contentLength = -1;
14900
+ continue;
14901
+ }
14902
+ this.contentLength = parseInt(match[1], 10);
14903
+ this.buffer = this.buffer.slice(headerEnd + 4);
14904
+ }
14905
+ if (this.buffer.length < this.contentLength)
14906
+ return;
14907
+ const body = this.buffer.slice(0, this.contentLength);
14908
+ this.buffer = this.buffer.slice(this.contentLength);
14909
+ this.contentLength = -1;
14910
+ try {
14911
+ const msg = JSON.parse(body);
14912
+ this.handleMessage(msg);
14913
+ } catch {}
14914
+ }
14915
+ }
14916
+ handleMessage(msg) {
14917
+ if (msg.method === "textDocument/publishDiagnostics") {
14918
+ const params = msg.params;
14919
+ if (params?.diagnostics) {
14920
+ this.diagnostics = params.diagnostics;
14921
+ if (this.diagnosticsTimer) {
14922
+ clearTimeout(this.diagnosticsTimer);
14923
+ this.diagnosticsTimer = null;
14924
+ }
14925
+ if (this.diagnosticsResolve) {
14926
+ this.diagnosticsResolve(this.diagnostics);
14927
+ this.diagnosticsResolve = null;
14928
+ }
14929
+ }
14930
+ return;
14931
+ }
14932
+ if (msg.id !== undefined && msg.id !== null) {
14933
+ const pending = this.pending.get(msg.id);
14934
+ if (pending) {
14935
+ this.pending.delete(msg.id);
14936
+ if (msg.error) {
14937
+ pending.reject(new Error(String(msg.error.message ?? "LSP error")));
14938
+ } else {
14939
+ pending.resolve(msg.result);
14940
+ }
14941
+ }
14942
+ }
14943
+ }
14944
+ sendRequest(method, params, timeout) {
14945
+ return new Promise((resolve16, reject) => {
14946
+ const id = ++this.requestId;
14947
+ this.pending.set(id, { resolve: resolve16, reject });
14948
+ const message = JSON.stringify({ jsonrpc: "2.0", id, method, params });
14949
+ this.write(message);
14950
+ setTimeout(() => {
14951
+ if (this.pending.has(id)) {
14952
+ this.pending.delete(id);
14953
+ reject(new Error(`LSP request timeout: ${method}`));
14954
+ }
14955
+ }, timeout);
14956
+ });
14957
+ }
14958
+ sendNotification(method, params) {
14959
+ const message = JSON.stringify({ jsonrpc: "2.0", method, params });
14960
+ this.write(message);
14961
+ }
14962
+ write(message) {
14963
+ if (!this.process?.stdin?.writable)
14964
+ return;
14965
+ const header = `Content-Length: ${Buffer.byteLength(message)}\r
14966
+ \r
14967
+ `;
14968
+ try {
14969
+ this.process.stdin.write(header + message);
14970
+ } catch {}
14971
+ }
14972
+ async shutdown() {
14973
+ try {
14974
+ if (this.process && this.initialized && this.process.stdin?.writable) {
14975
+ this.sendRequest("shutdown", null, 3000).catch(() => {});
14976
+ this.sendNotification("exit", null);
14977
+ await new Promise((r) => setTimeout(r, 200));
14978
+ }
14979
+ } catch {} finally {
14980
+ if (this.process) {
14981
+ try {
14982
+ this.process.kill();
14983
+ } catch {}
14984
+ this.process = null;
14985
+ }
14986
+ this.initialized = false;
14987
+ if (this.diagnosticsTimer) {
14988
+ clearTimeout(this.diagnosticsTimer);
14989
+ this.diagnosticsTimer = null;
14990
+ }
14991
+ }
14992
+ }
14993
+ pathToUri(filePath) {
14994
+ const normalized = filePath.replace(/\\/g, "/");
14995
+ if (/^[a-zA-Z]:/.test(normalized)) {
14996
+ return `file:///${normalized}`;
14997
+ }
14998
+ return `file://${normalized}`;
14999
+ }
15000
+ languageFromPath(filePath) {
15001
+ const ext = filePath.split(".").pop()?.toLowerCase();
15002
+ const map = {
15003
+ ts: "typescript",
15004
+ tsx: "typescriptreact",
15005
+ js: "javascript",
15006
+ jsx: "javascriptreact",
15007
+ py: "python",
15008
+ go: "go",
15009
+ rs: "rust",
15010
+ json: "json",
15011
+ html: "html",
15012
+ css: "css",
15013
+ scss: "scss",
15014
+ md: "markdown",
15015
+ yaml: "yaml",
15016
+ yml: "yaml"
15017
+ };
15018
+ return map[ext ?? ""] ?? "plaintext";
15019
+ }
15020
+ }
15021
+ var DEFAULT_TIMEOUT = 15000;
15022
+ var init_client2 = () => {};
15023
+
15024
+ // src/modules/lsp/module.ts
15025
+ import { existsSync as existsSync31 } from "fs";
15026
+ import { resolve as resolve16 } from "path";
15027
+
15028
+ class LspModule {
15029
+ name = "lsp";
15030
+ config;
15031
+ client = new LspClient;
15032
+ constructor(config) {
15033
+ this.config = { ...DEFAULT_LSP_CONFIG, ...config };
15034
+ }
15035
+ getPlugin() {
15036
+ const self = this;
15037
+ return {
15038
+ name: "lsp-check",
15039
+ priority: 15,
15040
+ onAfterTool: async (_ctx, call, result) => {
15041
+ if (!self.config.enabled)
15042
+ return;
15043
+ if (call.name !== "write_file" && call.name !== "edit_file")
15044
+ return;
15045
+ if (!result.success)
15046
+ return;
15047
+ const filePath = String(call.arguments.path ?? "");
15048
+ if (!filePath)
15049
+ return;
15050
+ const fullPath = resolve16(_ctx.baseDir, filePath);
15051
+ if (!existsSync31(fullPath))
15052
+ return;
15053
+ const serverConfig = getServerForFile(fullPath, self.config);
15054
+ if (!serverConfig)
15055
+ return;
15056
+ try {
15057
+ const diagnostics = await self.client.checkFile(fullPath, _ctx.baseDir, serverConfig);
15058
+ const errors = diagnostics.filter((d) => d.severity === 1);
15059
+ const warnings = diagnostics.filter((d) => d.severity === 2);
15060
+ if (errors.length > 0) {
15061
+ const items = formatDiagnostics(errors, fullPath);
15062
+ result.output += `
15063
+
15064
+ [LSP errors]:
15065
+ ${items}`;
15066
+ }
15067
+ if (warnings.length > 0) {
15068
+ const items = formatDiagnostics(warnings, fullPath);
15069
+ result.output += `
15070
+
15071
+ [LSP warnings]:
15072
+ ${items}`;
15073
+ }
15074
+ } catch {}
15075
+ }
15076
+ };
15077
+ }
15078
+ }
15079
+ function formatDiagnostics(diagnostics, filePath) {
15080
+ const filename = filePath.replace(/\\/g, "/").split("/").pop() ?? filePath;
15081
+ return diagnostics.slice(0, 5).map((d) => {
15082
+ const line = d.range.start.line + 1;
15083
+ const col = d.range.start.character + 1;
15084
+ const sev = severityLabels[d.severity] ?? "unknown";
15085
+ return ` ${filename}(${line},${col}): ${sev}: ${d.message}`;
15086
+ }).join(`
15087
+ `);
15088
+ }
15089
+ var severityLabels;
15090
+ var init_module5 = __esm(() => {
15091
+ init_client2();
15092
+ init_config();
15093
+ severityLabels = {
15094
+ 1: "error",
15095
+ 2: "warning",
15096
+ 3: "info",
15097
+ 4: "hint"
15098
+ };
15099
+ });
15100
+
15101
+ // src/modules/lsp/index.ts
15102
+ var init_lsp = __esm(() => {
15103
+ init_module5();
15104
+ init_client2();
15105
+ init_config();
15106
+ });
15107
+
14957
15108
  // src/modules/indexer/walker.ts
14958
- import { readdirSync as readdirSync9, readFileSync as readFileSync20, statSync as statSync6, existsSync as existsSync31, watch } from "fs";
14959
- import { join as join24, relative, extname as extname5 } from "path";
15109
+ import { readdirSync as readdirSync9, readFileSync as readFileSync20, statSync as statSync6, existsSync as existsSync32, watch } from "fs";
15110
+ import { join as join23, relative, extname as extname5 } from "path";
14960
15111
 
14961
15112
  class Indexer {
14962
15113
  baseDir;
@@ -14983,7 +15134,7 @@ class Indexer {
14983
15134
  let totalSize = 0;
14984
15135
  let count = 0;
14985
15136
  const walkDir = (dir) => {
14986
- if (!existsSync31(dir))
15137
+ if (!existsSync32(dir))
14987
15138
  return;
14988
15139
  let entries;
14989
15140
  try {
@@ -14994,7 +15145,7 @@ class Indexer {
14994
15145
  for (const entry of entries) {
14995
15146
  if (count >= this.MAX_FILES)
14996
15147
  return;
14997
- const fullPath = join24(dir, entry);
15148
+ const fullPath = join23(dir, entry);
14998
15149
  const relPath = relative(this.baseDir, fullPath);
14999
15150
  const stat = statSync6(fullPath);
15000
15151
  if (stat.isDirectory()) {
@@ -15057,19 +15208,19 @@ var init_walker = __esm(() => {
15057
15208
  });
15058
15209
 
15059
15210
  // src/modules/indexer/cache.ts
15060
- import { readFileSync as readFileSync21, writeFileSync as writeFileSync13, existsSync as existsSync32, mkdirSync as mkdirSync14, rmSync as rmSync2 } from "fs";
15061
- import { join as join25 } from "path";
15211
+ import { readFileSync as readFileSync21, writeFileSync as writeFileSync13, existsSync as existsSync33, mkdirSync as mkdirSync14, rmSync as rmSync2 } from "fs";
15212
+ import { join as join24 } from "path";
15062
15213
 
15063
15214
  class IndexCache {
15064
15215
  cachePath;
15065
15216
  cache = null;
15066
15217
  constructor(cacheDir) {
15067
- this.cachePath = join25(cacheDir, "index-cache.json");
15218
+ this.cachePath = join24(cacheDir, "index-cache.json");
15068
15219
  }
15069
15220
  load() {
15070
15221
  if (this.cache)
15071
15222
  return this.cache;
15072
- if (!existsSync32(this.cachePath))
15223
+ if (!existsSync33(this.cachePath))
15073
15224
  return null;
15074
15225
  try {
15075
15226
  this.cache = JSON.parse(readFileSync21(this.cachePath, "utf-8"));
@@ -15080,14 +15231,14 @@ class IndexCache {
15080
15231
  }
15081
15232
  save(result) {
15082
15233
  this.cache = result;
15083
- const dir = join25(this.cachePath, "..");
15084
- if (!existsSync32(dir))
15234
+ const dir = join24(this.cachePath, "..");
15235
+ if (!existsSync33(dir))
15085
15236
  mkdirSync14(dir, { recursive: true });
15086
15237
  writeFileSync13(this.cachePath, JSON.stringify(result), "utf-8");
15087
15238
  }
15088
15239
  invalidate() {
15089
15240
  this.cache = null;
15090
- if (existsSync32(this.cachePath)) {
15241
+ if (existsSync33(this.cachePath)) {
15091
15242
  try {
15092
15243
  rmSync2(this.cachePath);
15093
15244
  } catch {}
@@ -15280,7 +15431,7 @@ ${t("indexer.and_more", { count: result.files.length - 100 })}` : "";
15280
15431
  return { success: true, output, display: output };
15281
15432
  }
15282
15433
  }
15283
- var init_module5 = __esm(() => {
15434
+ var init_module6 = __esm(() => {
15284
15435
  init_walker();
15285
15436
  init_cache();
15286
15437
  init_i18n();
@@ -15290,7 +15441,7 @@ var init_module5 = __esm(() => {
15290
15441
  var init_indexer = __esm(() => {
15291
15442
  init_walker();
15292
15443
  init_cache();
15293
- init_module5();
15444
+ init_module6();
15294
15445
  });
15295
15446
 
15296
15447
  // src/modules/mcp/module.ts
@@ -15433,25 +15584,25 @@ class MCPModule {
15433
15584
  };
15434
15585
  }
15435
15586
  }
15436
- var init_module6 = __esm(() => {
15587
+ var init_module7 = __esm(() => {
15437
15588
  init_client();
15438
15589
  });
15439
15590
 
15440
15591
  // src/modules/mcp/index.ts
15441
15592
  var init_mcp = __esm(() => {
15442
15593
  init_client();
15443
- init_module6();
15594
+ init_module7();
15444
15595
  });
15445
15596
 
15446
15597
  // src/modules/memory/module.ts
15447
15598
  import { homedir as homedir10 } from "os";
15448
- import { join as join26 } from "path";
15599
+ import { join as join25 } from "path";
15449
15600
 
15450
15601
  class MemoryModule {
15451
15602
  name = "memory";
15452
15603
  store;
15453
15604
  constructor(memoryDir) {
15454
- const dir = memoryDir || join26(homedir10(), ".mma", "memory");
15605
+ const dir = memoryDir || join25(homedir10(), ".mma", "memory");
15455
15606
  this.store = new MemoryStore(dir);
15456
15607
  }
15457
15608
  getSystemPromptBlock() {
@@ -15486,7 +15637,7 @@ class MemoryModule {
15486
15637
  return this.store;
15487
15638
  }
15488
15639
  }
15489
- var init_module7 = __esm(() => {
15640
+ var init_module8 = __esm(() => {
15490
15641
  init_store();
15491
15642
  init_remember();
15492
15643
  init_recall();
@@ -15498,8 +15649,8 @@ __export(exports_bootstrap, {
15498
15649
  bootstrap: () => bootstrap
15499
15650
  });
15500
15651
  import { homedir as homedir11 } from "os";
15501
- import { join as join27, resolve as resolve15 } from "path";
15502
- import { existsSync as existsSync33, readFileSync as readFileSync22, writeFileSync as writeFileSync14 } from "fs";
15652
+ import { join as join26, resolve as resolve17 } from "path";
15653
+ import { existsSync as existsSync34, readFileSync as readFileSync22, writeFileSync as writeFileSync14 } from "fs";
15503
15654
  function buildSystemInfo(config, baseDir, profileCompressed) {
15504
15655
  const now = new Date().toISOString().replace("T", " ").slice(0, 19);
15505
15656
  const isWin = profileCompressed.toLowerCase().includes("win32");
@@ -15518,10 +15669,9 @@ function buildSystemInfo(config, baseDir, profileCompressed) {
15518
15669
  `- DRY: Do not duplicate code, logic, or configuration — reuse existing utilities and patterns.`
15519
15670
  ];
15520
15671
  if (isWin) {
15521
- lines.push(``, `Windows environment — use Windows-compatible commands:`, `- Use "dir" instead of "ls". Use "dir /b" for bare listing.`, `- Use "type" or "Get-Content" instead of "cat".`, `- Use "cd" instead of "pwd". Use "echo %cd%" to print working directory.`, `- Use "copy" instead of "cp", "move" instead of "mv", "del" instead of "rm".`, `- Do not use "mkdir -p" — Windows mkdir creates intermediate dirs by default. Use the create_dir tool instead.`, `- Use forward slashes (/) or escaped backslashes (\\\\) in file paths.`, `- Your working directory is: ${baseDir}`);
15672
+ lines.push(``, `Windows environment — use Windows-compatible commands:`, `- Use "dir" instead of "ls". Use "dir /b" for bare listing.`, `- Use "type" or "Get-Content" instead of "cat".`, `- Use "cd" instead of "pwd". Use "echo %cd%" to print working directory.`, `- Use "copy" instead of "cp", "move" instead of "mv", "del" instead of "rm".`, `- Do not use "mkdir -p" — Windows mkdir creates intermediate dirs by default. Use the create_dir tool instead.`, `- Do not use "head" or "tail" — they are Unix commands. Use "Select-Object -First N" or "Get-Content ... | Select-Object -First N" instead (PowerShell).`, `- Use forward slashes (/) or escaped backslashes (\\\\) in file paths.`, `- Your working directory is: ${baseDir}`);
15522
15673
  }
15523
15674
  lines.push(``, `Bash tool rules:`, `- Use the "workdir" parameter to run commands in a specific directory. Prefer workdir over "cd dir && cmd" chaining.`, `- Run one command per tool call. Split multi-step shell operations into separate bash calls.`, `- Background processes (dev servers, watchers, long-running npm install): use the "background: true" parameter or the tool will auto-detect and background them. Check output with process_log.`);
15524
- lines.push(``, `Parallel tool calls:`, `- When you need to read multiple files, call read_file for ALL of them in a SINGLE response (one tool_calls array with multiple read_file calls). They will execute in parallel — much faster than reading one at a time.`, `- Example: to read 3 files, return one assistant message with 3 read_file tool_calls. Do NOT read them one by one in separate iterations.`, `- This works for: read_file, glob, grep, file_info, list_dir — any read-only operations.`, `- Do NOT parallelize write operations (write_file, edit_file, delete_file, bash) — these run sequentially.`);
15525
15675
  lines.push(``, `=== DEVELOPMENT RULES — follow these strictly ===`, ``, `1. DEPENDENCIES FIRST: Before writing any source code, ALWAYS install project dependencies (e.g., "npm install", "pip install -r requirements.txt", "cargo build", "go mod tidy"). Verify the package manager's lock file or dependency directory exists. Never write code that imports/uses packages that aren't installed yet.`, `2. TOOLKIT/FWK FIRST: If the task specifies a framework or UI library, initialize and configure it BEFORE writing application code. Run its project init command first, then add components/modules. Never write your own version of what the framework already provides.`, `3. ONE STEP AT A TIME: Follow the plan sequentially. Complete step N before starting step N+1. When a step is done: verify the deliverables exist and have real content (not empty), then call "plan update step=N status=done". Do not redo completed work.`, `4. VERIFY YOUR WORK: After creating/modifying files, verify they exist on disk. After installing dependencies, verify the package manager completed successfully. After any command, check its output for errors. Don't assume operations succeeded.`, `5. NO PREMATURE WORK: Do not create files for future steps. Do not add imports/references to packages or modules that haven't been installed yet. Do not reference files or components that don't exist yet. Build incrementally — one layer at a time.`, `6. WHEN STUCK: If a command fails 2+ times, STOP and try a different approach. Write files directly instead of using commands. Ask the user for help. Never repeat the same failing command more than twice.`, ``, `=== PLAN QUALITY RULES — your plan MUST follow these ===`, ``, `- Each step must describe CONCRETE deliverables: exact filenames with paths, exact packages to install, exact CLI commands to run. Avoid vague steps — be specific.`, `- A step like "Настройка проекта" or "Setup the project" is too vague — describe what exactly needs to be configured or set up.`, `- A step like "Создать src/components/Header.tsx с навигацией и логотипом, добавить в src/App.tsx импорт <Header />" is GOOD.`, `- Include file extensions (.tsx, .css, .json) and directory paths. Every step must mention at least one file or command.`, `- The plan must cover EVERYTHING needed: init → deps → framework setup → code → verification.`, `- Number of steps: 5-8 for a typical task. Too few means you're being vague. Too many means you're over-splitting.`);
15526
15676
  if (config.autoPlan) {
15527
15677
  lines.push(``, `Plan rule (MANDATORY): For ANY task that requires creating files, installing packages, or multiple actions — you MUST create a plan using the "plan" tool BEFORE starting work. Each step must describe a concrete deliverable (specific files to create, packages to install, commands to run). Do not combine unrelated work into one step.`);
@@ -15534,8 +15684,8 @@ function buildSystemInfo(config, baseDir, profileCompressed) {
15534
15684
  `);
15535
15685
  }
15536
15686
  async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
15537
- const dir = configDir || join27(homedir11(), ".mma");
15538
- const projectConfigPath = projectDir ? join27(projectDir, ".mmrc") : join27(process.cwd(), ".mmrc");
15687
+ const dir = configDir || join26(homedir11(), ".mma");
15688
+ const projectConfigPath = projectDir ? join26(projectDir, ".mmrc") : join26(process.cwd(), ".mmrc");
15539
15689
  const config = loadConfig({ configDir: dir, projectConfigPath });
15540
15690
  setLocale(config.locale);
15541
15691
  try {
@@ -15545,7 +15695,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
15545
15695
  }
15546
15696
  } catch {}
15547
15697
  const logger = new Logger(config.logLevel);
15548
- logger.setLogDir(join27(dir, "logs"));
15698
+ logger.setLogDir(join26(dir, "logs"));
15549
15699
  logger.debug("MMA bootstrap", {
15550
15700
  version: config.version,
15551
15701
  model: config.model
@@ -15567,7 +15717,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
15567
15717
  logger.info(`Model ${config.model} loaded in ${loadResult.loadTime}s`);
15568
15718
  }
15569
15719
  }
15570
- const profile = new UserProfile(join27(dir));
15720
+ const profile = new UserProfile(join26(dir));
15571
15721
  profile.load() || profile.collect();
15572
15722
  profile.save();
15573
15723
  const llmProvider = new OpenAICompatProvider({
@@ -15578,8 +15728,8 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
15578
15728
  retry: config.retry,
15579
15729
  rateLimits: config.security?.rateLimits
15580
15730
  });
15581
- const baseDir = projectDir ? resolve15(projectDir) : process.cwd();
15582
- const projectMapCacheDir = join27(baseDir, ".mma");
15731
+ const baseDir = projectDir ? resolve17(projectDir) : process.cwd();
15732
+ const projectMapCacheDir = join26(baseDir, ".mma");
15583
15733
  const indexerModule = new IndexerModule({
15584
15734
  baseDir,
15585
15735
  cacheDir: projectMapCacheDir
@@ -15590,9 +15740,9 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
15590
15740
  logger.warn(`Project indexing failed: ${err.message}`);
15591
15741
  }
15592
15742
  const skillsLoader = new SkillsLoader;
15593
- const builtinDir = join27(import.meta.dirname, "skills", "builtin");
15594
- const globalDir = join27(homedir11(), ".agents", "skills");
15595
- const projectSkillsDir = join27(baseDir, ".mma", "skills");
15743
+ const builtinDir = join26(import.meta.dirname, "skills", "builtin");
15744
+ const globalDir = join26(homedir11(), ".agents", "skills");
15745
+ const projectSkillsDir = join26(baseDir, ".mma", "skills");
15596
15746
  const availableSkills = skillsLoader.loadFromAllSources(builtinDir, globalDir, projectSkillsDir);
15597
15747
  const skillsMatcher = new SkillsMatcher;
15598
15748
  const skillsBudget = Math.floor(config.contextWindow * 0.1);
@@ -15606,11 +15756,11 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
15606
15756
  essential: true,
15607
15757
  estimatedTokens: 250
15608
15758
  };
15609
- const agentsMdGlobal = join27(dir, "AGENTS.md");
15610
- if (!existsSync33(agentsMdGlobal)) {
15759
+ const agentsMdGlobal = join26(dir, "AGENTS.md");
15760
+ if (!existsSync34(agentsMdGlobal)) {
15611
15761
  writeFileSync14(agentsMdGlobal, "", "utf-8");
15612
15762
  }
15613
- const sessionDir = join27(dir, "sessions");
15763
+ const sessionDir = join26(dir, "sessions");
15614
15764
  const sessionStore = new SessionStore(sessionDir);
15615
15765
  sessionStore.init();
15616
15766
  const sessionManager = new SessionManager(sessionStore, {
@@ -15664,7 +15814,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
15664
15814
  const mcpModule = new MCPModule(config);
15665
15815
  await mcpModule.initialize();
15666
15816
  moduleRegistry.register(mcpModule);
15667
- const memoryModule = new MemoryModule(join27(dir, "memory"));
15817
+ const memoryModule = new MemoryModule(join26(dir, "memory"));
15668
15818
  moduleRegistry.register(memoryModule);
15669
15819
  if (config.browser.enabled) {
15670
15820
  const browserModule = new BrowserModule;
@@ -15675,6 +15825,13 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
15675
15825
  pluginManager.register(browserPlugin);
15676
15826
  }
15677
15827
  }
15828
+ const lspModule = new LspModule(config.lsp);
15829
+ moduleRegistry.register(lspModule);
15830
+ const lspPlugin = lspModule.getPlugin();
15831
+ if (lspPlugin) {
15832
+ lspPlugin.isBuiltin = true;
15833
+ pluginManager.register(lspPlugin);
15834
+ }
15678
15835
  const moduleTools = moduleRegistry.collectToolDefinitions();
15679
15836
  for (const tool of moduleTools) {
15680
15837
  toolRegistry.register(tool);
@@ -15707,8 +15864,8 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
15707
15864
  pluginManager.register(plugin);
15708
15865
  pluginManager.register(plugin2);
15709
15866
  const pluginLoader = new PluginLoader;
15710
- const globalPluginsDir = join27(homedir11(), ".mma", "plugins");
15711
- const projectPluginsDir = join27(dir, ".mma", "plugins");
15867
+ const globalPluginsDir = join26(homedir11(), ".mma", "plugins");
15868
+ const projectPluginsDir = join26(dir, ".mma", "plugins");
15712
15869
  pluginLoader.loadFromDir(globalPluginsDir, pluginManager, logger);
15713
15870
  pluginLoader.loadFromDir(projectPluginsDir, pluginManager, logger);
15714
15871
  contextManager.onCompact = (summary) => {
@@ -15726,12 +15883,12 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
15726
15883
  const skipAgentsMd = noAgentsMd === true;
15727
15884
  if (!skipAgentsMd) {
15728
15885
  const agentsMdCandidates = [
15729
- join27(baseDir, "AGENTS.md"),
15730
- join27(baseDir, ".mma", "AGENTS.md"),
15731
- join27(dir, "AGENTS.md")
15886
+ join26(baseDir, "AGENTS.md"),
15887
+ join26(baseDir, ".mma", "AGENTS.md"),
15888
+ join26(dir, "AGENTS.md")
15732
15889
  ];
15733
15890
  for (const p of agentsMdCandidates) {
15734
- if (existsSync33(p)) {
15891
+ if (existsSync34(p)) {
15735
15892
  const content = readFileSync22(p, "utf-8").trim();
15736
15893
  if (content) {
15737
15894
  agentsMdBlocks.push({
@@ -15781,7 +15938,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
15781
15938
  };
15782
15939
  }
15783
15940
  var init_bootstrap = __esm(() => {
15784
- init_config();
15941
+ init_config2();
15785
15942
  init_app_logger();
15786
15943
  init_openai_compat();
15787
15944
  init_tools();
@@ -15797,9 +15954,10 @@ var init_bootstrap = __esm(() => {
15797
15954
  init_profile();
15798
15955
  init_skills();
15799
15956
  init_browser2();
15957
+ init_lsp();
15800
15958
  init_indexer();
15801
15959
  init_mcp();
15802
- init_module7();
15960
+ init_module8();
15803
15961
  init_i18n();
15804
15962
  init_agent();
15805
15963
  });
@@ -15813,7 +15971,7 @@ function ansiRegex({ onlyFirst = false } = {}) {
15813
15971
  return new RegExp(pattern, onlyFirst ? undefined : "g");
15814
15972
  }
15815
15973
 
15816
- // node_modules/string-width/node_modules/strip-ansi/index.js
15974
+ // node_modules/strip-ansi/index.js
15817
15975
  function stripAnsi(string) {
15818
15976
  if (typeof string !== "string") {
15819
15977
  throw new TypeError(`Expected a \`string\`, got \`${typeof string}\``);
@@ -15912,65 +16070,135 @@ var init_get_east_asian_width = __esm(() => {
15912
16070
  init_lookup();
15913
16071
  });
15914
16072
 
15915
- // node_modules/emoji-regex/index.js
15916
- var require_emoji_regex = __commonJS((exports, module) => {
15917
- module.exports = () => {
15918
- return /[#*0-9]\uFE0F?\u20E3|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23ED-\u23EF\u23F1\u23F2\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB\u25FC\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692\u2694-\u2697\u2699\u269B\u269C\u26A0\u26A7\u26AA\u26B0\u26B1\u26BD\u26BE\u26C4\u26C8\u26CF\u26D1\u26E9\u26F0-\u26F5\u26F7\u26F8\u26FA\u2702\u2708\u2709\u270F\u2712\u2714\u2716\u271D\u2721\u2733\u2734\u2744\u2747\u2757\u2763\u27A1\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B55\u3030\u303D\u3297\u3299]\uFE0F?|[\u261D\u270C\u270D](?:\uD83C[\uDFFB-\uDFFF]|\uFE0F)?|[\u270A\u270B](?:\uD83C[\uDFFB-\uDFFF])?|[\u23E9-\u23EC\u23F0\u23F3\u25FD\u2693\u26A1\u26AB\u26C5\u26CE\u26D4\u26EA\u26FD\u2705\u2728\u274C\u274E\u2753-\u2755\u2795-\u2797\u27B0\u27BF\u2B50]|\u26D3\uFE0F?(?:\u200D\uD83D\uDCA5)?|\u26F9(?:\uD83C[\uDFFB-\uDFFF]|\uFE0F)?(?:\u200D[\u2640\u2642]\uFE0F?)?|\u2764\uFE0F?(?:\u200D(?:\uD83D\uDD25|\uD83E\uDE79))?|\uD83C(?:[\uDC04\uDD70\uDD71\uDD7E\uDD7F\uDE02\uDE37\uDF21\uDF24-\uDF2C\uDF36\uDF7D\uDF96\uDF97\uDF99-\uDF9B\uDF9E\uDF9F\uDFCD\uDFCE\uDFD4-\uDFDF\uDFF5\uDFF7]\uFE0F?|[\uDF85\uDFC2\uDFC7](?:\uD83C[\uDFFB-\uDFFF])?|[\uDFC4\uDFCA](?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDFCB\uDFCC](?:\uD83C[\uDFFB-\uDFFF]|\uFE0F)?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDCCF\uDD8E\uDD91-\uDD9A\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF43\uDF45-\uDF4A\uDF4C-\uDF7C\uDF7E-\uDF84\uDF86-\uDF93\uDFA0-\uDFC1\uDFC5\uDFC6\uDFC8\uDFC9\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF8-\uDFFF]|\uDDE6\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF]|\uDDE7\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF]|\uDDE8\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF7\uDDFA-\uDDFF]|\uDDE9\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF]|\uDDEA\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA]|\uDDEB\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7]|\uDDEC\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE]|\uDDED\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA]|\uDDEE\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9]|\uDDEF\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5]|\uDDF0\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF]|\uDDF1\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE]|\uDDF2\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF]|\uDDF3\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF]|\uDDF4\uD83C\uDDF2|\uDDF5\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE]|\uDDF6\uD83C\uDDE6|\uDDF7\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC]|\uDDF8\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF]|\uDDF9\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF]|\uDDFA\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF]|\uDDFB\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA]|\uDDFC\uD83C[\uDDEB\uDDF8]|\uDDFD\uD83C\uDDF0|\uDDFE\uD83C[\uDDEA\uDDF9]|\uDDFF\uD83C[\uDDE6\uDDF2\uDDFC]|\uDF44(?:\u200D\uD83D\uDFEB)?|\uDF4B(?:\u200D\uD83D\uDFE9)?|\uDFC3(?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D(?:[\u2640\u2642]\uFE0F?(?:\u200D\u27A1\uFE0F?)?|\u27A1\uFE0F?))?|\uDFF3\uFE0F?(?:\u200D(?:\u26A7\uFE0F?|\uD83C\uDF08))?|\uDFF4(?:\u200D\u2620\uFE0F?|\uDB40\uDC67\uDB40\uDC62\uDB40(?:\uDC65\uDB40\uDC6E\uDB40\uDC67|\uDC73\uDB40\uDC63\uDB40\uDC74|\uDC77\uDB40\uDC6C\uDB40\uDC73)\uDB40\uDC7F)?)|\uD83D(?:[\uDC3F\uDCFD\uDD49\uDD4A\uDD6F\uDD70\uDD73\uDD76-\uDD79\uDD87\uDD8A-\uDD8D\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA\uDECB\uDECD-\uDECF\uDEE0-\uDEE5\uDEE9\uDEF0\uDEF3]\uFE0F?|[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC](?:\uD83C[\uDFFB-\uDFFF])?|[\uDC6E-\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4\uDEB5](?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDD74\uDD90](?:\uD83C[\uDFFB-\uDFFF]|\uFE0F)?|[\uDC00-\uDC07\uDC09-\uDC14\uDC16-\uDC25\uDC27-\uDC3A\uDC3C-\uDC3E\uDC40\uDC44\uDC45\uDC51-\uDC65\uDC6A\uDC79-\uDC7B\uDC7D-\uDC80\uDC84\uDC88-\uDC8E\uDC90\uDC92-\uDCA9\uDCAB-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDDA4\uDDFB-\uDE2D\uDE2F-\uDE34\uDE37-\uDE41\uDE43\uDE44\uDE48-\uDE4A\uDE80-\uDEA2\uDEA4-\uDEB3\uDEB7-\uDEBF\uDEC1-\uDEC5\uDED0-\uDED2\uDED5-\uDED8\uDEDC-\uDEDF\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB\uDFF0]|\uDC08(?:\u200D\u2B1B)?|\uDC15(?:\u200D\uD83E\uDDBA)?|\uDC26(?:\u200D(?:\u2B1B|\uD83D\uDD25))?|\uDC3B(?:\u200D\u2744\uFE0F?)?|\uDC41\uFE0F?(?:\u200D\uD83D\uDDE8\uFE0F?)?|\uDC68(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDC68\uDC69]\u200D\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?)|[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?)|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]))|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC30\u200D\uD83D\uDC68\uD83C[\uDFFC-\uDFFF])|\uD83E(?:[\uDD1D\uDEEF]\u200D\uD83D\uDC68\uD83C[\uDFFC-\uDFFF]|[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC30\u200D\uD83D\uDC68\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83E(?:[\uDD1D\uDEEF]\u200D\uD83D\uDC68\uD83C[\uDFFB\uDFFD-\uDFFF]|[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC30\u200D\uD83D\uDC68\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83E(?:[\uDD1D\uDEEF]\u200D\uD83D\uDC68\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF]|[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC30\u200D\uD83D\uDC68\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83E(?:[\uDD1D\uDEEF]\u200D\uD83D\uDC68\uD83C[\uDFFB-\uDFFD\uDFFF]|[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?\uDC68\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC30\u200D\uD83D\uDC68\uD83C[\uDFFB-\uDFFE])|\uD83E(?:[\uDD1D\uDEEF]\u200D\uD83D\uDC68\uD83C[\uDFFB-\uDFFE]|[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3])))?))?|\uDC69(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:\uDC8B\u200D\uD83D)?[\uDC68\uDC69]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?|\uDC69\u200D\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?))|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]))|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC30\u200D\uD83D\uDC69\uD83C[\uDFFC-\uDFFF])|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFC-\uDFFF]|\uDEEF\u200D\uD83D\uDC69\uD83C[\uDFFC-\uDFFF])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC30\u200D\uD83D\uDC69\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB\uDFFD-\uDFFF]|\uDEEF\u200D\uD83D\uDC69\uD83C[\uDFFB\uDFFD-\uDFFF])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC30\u200D\uD83D\uDC69\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF]|\uDEEF\u200D\uD83D\uDC69\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC30\u200D\uD83D\uDC69\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB-\uDFFD\uDFFF]|\uDEEF\u200D\uD83D\uDC69\uD83C[\uDFFB-\uDFFD\uDFFF])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D\uD83D(?:[\uDC68\uDC69]|\uDC8B\u200D\uD83D[\uDC68\uDC69])\uD83C[\uDFFB-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC30\u200D\uD83D\uDC69\uD83C[\uDFFB-\uDFFE])|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3]|\uDD1D\u200D\uD83D[\uDC68\uDC69]\uD83C[\uDFFB-\uDFFE]|\uDEEF\u200D\uD83D\uDC69\uD83C[\uDFFB-\uDFFE])))?))?|\uDD75(?:\uD83C[\uDFFB-\uDFFF]|\uFE0F)?(?:\u200D[\u2640\u2642]\uFE0F?)?|\uDE2E(?:\u200D\uD83D\uDCA8)?|\uDE35(?:\u200D\uD83D\uDCAB)?|\uDE36(?:\u200D\uD83C\uDF2B\uFE0F?)?|\uDE42(?:\u200D[\u2194\u2195]\uFE0F?)?|\uDEB6(?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D(?:[\u2640\u2642]\uFE0F?(?:\u200D\u27A1\uFE0F?)?|\u27A1\uFE0F?))?)|\uD83E(?:[\uDD0C\uDD0F\uDD18-\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5\uDEC3-\uDEC5\uDEF0\uDEF2-\uDEF8](?:\uD83C[\uDFFB-\uDFFF])?|[\uDD26\uDD35\uDD37-\uDD39\uDD3C-\uDD3E\uDDB8\uDDB9\uDDCD\uDDCF\uDDD4\uDDD6-\uDDDD](?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDDDE\uDDDF](?:\u200D[\u2640\u2642]\uFE0F?)?|[\uDD0D\uDD0E\uDD10-\uDD17\uDD20-\uDD25\uDD27-\uDD2F\uDD3A\uDD3F-\uDD45\uDD47-\uDD76\uDD78-\uDDB4\uDDB7\uDDBA\uDDBC-\uDDCC\uDDD0\uDDE0-\uDDFF\uDE70-\uDE7C\uDE80-\uDE8A\uDE8E-\uDEC2\uDEC6\uDEC8\uDECD-\uDEDC\uDEDF-\uDEEA\uDEEF]|\uDDCE(?:\uD83C[\uDFFB-\uDFFF])?(?:\u200D(?:[\u2640\u2642]\uFE0F?(?:\u200D\u27A1\uFE0F?)?|\u27A1\uFE0F?))?|\uDDD1(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3\uDE70]|\uDD1D\u200D\uD83E\uDDD1|\uDDD1\u200D\uD83E\uDDD2(?:\u200D\uD83E\uDDD2)?|\uDDD2(?:\u200D\uD83E\uDDD2)?))|\uD83C(?:\uDFFB(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFC-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC30\u200D\uD83E\uDDD1\uD83C[\uDFFC-\uDFFF])|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3\uDE70]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF]|\uDEEF\u200D\uD83E\uDDD1\uD83C[\uDFFC-\uDFFF])))?|\uDFFC(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB\uDFFD-\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC30\u200D\uD83E\uDDD1\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3\uDE70]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF]|\uDEEF\u200D\uD83E\uDDD1\uD83C[\uDFFB\uDFFD-\uDFFF])))?|\uDFFD(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC30\u200D\uD83E\uDDD1\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3\uDE70]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF]|\uDEEF\u200D\uD83E\uDDD1\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])))?|\uDFFE(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB-\uDFFD\uDFFF]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC30\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3\uDE70]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF]|\uDEEF\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFD\uDFFF])))?|\uDFFF(?:\u200D(?:[\u2695\u2696\u2708]\uFE0F?|\u2764\uFE0F?\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1\uD83C[\uDFFB-\uDFFE]|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D(?:[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uDC30\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFE])|\uD83E(?:[\uDDAF\uDDBC\uDDBD](?:\u200D\u27A1\uFE0F?)?|[\uDDB0-\uDDB3\uDE70]|\uDD1D\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFF]|\uDEEF\u200D\uD83E\uDDD1\uD83C[\uDFFB-\uDFFE])))?))?|\uDEF1(?:\uD83C(?:\uDFFB(?:\u200D\uD83E\uDEF2\uD83C[\uDFFC-\uDFFF])?|\uDFFC(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB\uDFFD-\uDFFF])?|\uDFFD(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])?|\uDFFE(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB-\uDFFD\uDFFF])?|\uDFFF(?:\u200D\uD83E\uDEF2\uD83C[\uDFFB-\uDFFE])?))?)/g;
15919
- };
15920
- });
15921
-
15922
16073
  // node_modules/string-width/index.js
15923
- function stringWidth(string, options = {}) {
15924
- if (typeof string !== "string" || string.length === 0) {
16074
+ function isDoubleWidthNonRgiEmojiSequence(segment) {
16075
+ if (segment.length > 50) {
16076
+ return false;
16077
+ }
16078
+ if (unqualifiedKeycapRegex.test(segment)) {
16079
+ return true;
16080
+ }
16081
+ if (segment.includes("‍")) {
16082
+ const pictographics = segment.match(extendedPictographicRegex);
16083
+ return pictographics !== null && pictographics.length >= 2;
16084
+ }
16085
+ return false;
16086
+ }
16087
+ function baseVisible(segment) {
16088
+ return segment.replace(leadingNonPrintingRegex, "");
16089
+ }
16090
+ function isZeroWidthCluster(segment) {
16091
+ return zeroWidthClusterRegex.test(segment);
16092
+ }
16093
+ function isHangulLeadingJamo(codePoint) {
16094
+ return codePoint >= 4352 && codePoint <= 4447 || codePoint >= 43360 && codePoint <= 43388;
16095
+ }
16096
+ function isHangulVowelJamo(codePoint) {
16097
+ return codePoint >= 4448 && codePoint <= 4519 || codePoint >= 55216 && codePoint <= 55238;
16098
+ }
16099
+ function isHangulTrailingJamo(codePoint) {
16100
+ return codePoint >= 4520 && codePoint <= 4607 || codePoint >= 55243 && codePoint <= 55291;
16101
+ }
16102
+ function isHangulJamo(codePoint) {
16103
+ return isHangulLeadingJamo(codePoint) || isHangulVowelJamo(codePoint) || isHangulTrailingJamo(codePoint);
16104
+ }
16105
+ function hangulClusterWidth(visibleSegment, eastAsianWidthOptions) {
16106
+ const codePoints = [];
16107
+ for (const character of visibleSegment) {
16108
+ if (zeroWidthClusterRegex.test(character)) {
16109
+ continue;
16110
+ }
16111
+ codePoints.push(character.codePointAt(0));
16112
+ }
16113
+ if (codePoints.length === 0) {
16114
+ return;
16115
+ }
16116
+ let width = 0;
16117
+ for (let index = 0;index < codePoints.length; index++) {
16118
+ const codePoint = codePoints[index];
16119
+ if (!isHangulJamo(codePoint)) {
16120
+ if (width === 0) {
16121
+ return;
16122
+ }
16123
+ for (let remaining = index;remaining < codePoints.length; remaining++) {
16124
+ width += eastAsianWidth(codePoints[remaining], eastAsianWidthOptions);
16125
+ }
16126
+ return width;
16127
+ }
16128
+ if (isHangulLeadingJamo(codePoint) && isHangulVowelJamo(codePoints[index + 1])) {
16129
+ width += 2;
16130
+ index += isHangulTrailingJamo(codePoints[index + 2]) ? 2 : 1;
16131
+ continue;
16132
+ }
16133
+ width += eastAsianWidth(codePoint, eastAsianWidthOptions);
16134
+ }
16135
+ return width;
16136
+ }
16137
+ function trailingWidth(visibleSegment, eastAsianWidthOptions) {
16138
+ let extra = 0;
16139
+ let first = true;
16140
+ for (const character of visibleSegment) {
16141
+ if (first) {
16142
+ first = false;
16143
+ continue;
16144
+ }
16145
+ if (spacingMarkRegex.test(character) || character >= "＀" && character <= "￯") {
16146
+ extra += eastAsianWidth(character.codePointAt(0), eastAsianWidthOptions);
16147
+ }
16148
+ }
16149
+ return extra;
16150
+ }
16151
+ function stringWidth(input, options = {}) {
16152
+ if (typeof input !== "string" || input.length === 0) {
15925
16153
  return 0;
15926
16154
  }
15927
16155
  const {
15928
16156
  ambiguousIsNarrow = true,
15929
16157
  countAnsiEscapeCodes = false
15930
16158
  } = options;
15931
- if (!countAnsiEscapeCodes) {
16159
+ let string = input;
16160
+ if (!countAnsiEscapeCodes && (string.includes("\x1B") || string.includes("›"))) {
15932
16161
  string = stripAnsi(string);
15933
16162
  }
15934
16163
  if (string.length === 0) {
15935
16164
  return 0;
15936
16165
  }
16166
+ if (/^[\u0020-\u007E]*$/.test(string)) {
16167
+ return string.length;
16168
+ }
15937
16169
  let width = 0;
15938
16170
  const eastAsianWidthOptions = { ambiguousAsWide: !ambiguousIsNarrow };
15939
- for (const { segment: character } of segmenter.segment(string)) {
15940
- const codePoint = character.codePointAt(0);
15941
- if (codePoint <= 31 || codePoint >= 127 && codePoint <= 159) {
16171
+ for (const { segment } of segmenter.segment(string)) {
16172
+ if (isZeroWidthCluster(segment)) {
15942
16173
  continue;
15943
16174
  }
15944
- if (codePoint >= 8203 && codePoint <= 8207 || codePoint === 65279) {
15945
- continue;
15946
- }
15947
- if (codePoint >= 768 && codePoint <= 879 || codePoint >= 6832 && codePoint <= 6911 || codePoint >= 7616 && codePoint <= 7679 || codePoint >= 8400 && codePoint <= 8447 || codePoint >= 65056 && codePoint <= 65071) {
15948
- continue;
15949
- }
15950
- if (codePoint >= 55296 && codePoint <= 57343) {
15951
- continue;
15952
- }
15953
- if (codePoint >= 65024 && codePoint <= 65039) {
15954
- continue;
15955
- }
15956
- if (defaultIgnorableCodePointRegex.test(character)) {
16175
+ if (rgiEmojiRegex.test(segment) || isDoubleWidthNonRgiEmojiSequence(segment)) {
16176
+ width += 2;
15957
16177
  continue;
15958
16178
  }
15959
- if (import_emoji_regex.default().test(character)) {
15960
- width += 2;
16179
+ const visibleSegment = baseVisible(segment);
16180
+ const hangulWidth = hangulClusterWidth(visibleSegment, eastAsianWidthOptions);
16181
+ if (hangulWidth !== undefined) {
16182
+ width += hangulWidth;
15961
16183
  continue;
15962
16184
  }
16185
+ const codePoint = visibleSegment.codePointAt(0);
15963
16186
  width += eastAsianWidth(codePoint, eastAsianWidthOptions);
16187
+ width += trailingWidth(visibleSegment, eastAsianWidthOptions);
15964
16188
  }
15965
16189
  return width;
15966
16190
  }
15967
- var import_emoji_regex, segmenter, defaultIgnorableCodePointRegex;
16191
+ var segmenter, zeroWidthClusterRegex, leadingNonPrintingRegex, spacingMarkRegex, rgiEmojiRegex, unqualifiedKeycapRegex, extendedPictographicRegex;
15968
16192
  var init_string_width = __esm(() => {
15969
16193
  init_strip_ansi();
15970
16194
  init_get_east_asian_width();
15971
- import_emoji_regex = __toESM(require_emoji_regex(), 1);
15972
16195
  segmenter = new Intl.Segmenter;
15973
- defaultIgnorableCodePointRegex = /^\p{Default_Ignorable_Code_Point}$/u;
16196
+ zeroWidthClusterRegex = /^(?:\p{Default_Ignorable_Code_Point}|\p{Control}|\p{Format}|\p{Nonspacing_Mark}|\p{Enclosing_Mark}|\p{Surrogate})+$/v;
16197
+ leadingNonPrintingRegex = /^[\p{Default_Ignorable_Code_Point}\p{Control}\p{Format}\p{Nonspacing_Mark}\p{Enclosing_Mark}\p{Surrogate}]+/v;
16198
+ spacingMarkRegex = /\p{Spacing_Mark}/v;
16199
+ rgiEmojiRegex = /^\p{RGI_Emoji}$/v;
16200
+ unqualifiedKeycapRegex = /^[\d#*]\u20E3$/;
16201
+ extendedPictographicRegex = /\p{Extended_Pictographic}/gu;
15974
16202
  });
15975
16203
 
15976
16204
  // src/ui/table.ts
@@ -16278,10 +16506,10 @@ function menuList(items) {
16278
16506
  console.log(l);
16279
16507
  }
16280
16508
  function ask(rl, question, defaultValue) {
16281
- return new Promise((resolve16) => {
16509
+ return new Promise((resolve18) => {
16282
16510
  const prompt = defaultValue ? `${question} [${defaultValue}]: ` : `${question}: `;
16283
16511
  rl.question(prompt, (answer) => {
16284
- resolve16(answer.trim() || defaultValue || "");
16512
+ resolve18(answer.trim() || defaultValue || "");
16285
16513
  });
16286
16514
  });
16287
16515
  }
@@ -16500,12 +16728,12 @@ __export(exports_manifest, {
16500
16728
  getCertMark: () => getCertMark,
16501
16729
  MANIFEST_PATH: () => MANIFEST_PATH
16502
16730
  });
16503
- import { existsSync as existsSync34, readFileSync as readFileSync23, mkdirSync as mkdirSync15, writeFileSync as writeFileSync15 } from "fs";
16731
+ import { existsSync as existsSync35, readFileSync as readFileSync23, mkdirSync as mkdirSync15, writeFileSync as writeFileSync15 } from "fs";
16504
16732
  import { homedir as homedir13 } from "os";
16505
- import { join as join29 } from "path";
16733
+ import { join as join28 } from "path";
16506
16734
  function readManifest(path = MANIFEST_PATH) {
16507
16735
  try {
16508
- if (existsSync34(path)) {
16736
+ if (existsSync35(path)) {
16509
16737
  const raw = JSON.parse(readFileSync23(path, "utf-8"));
16510
16738
  return { version: 1, certifications: raw.certifications ?? [] };
16511
16739
  }
@@ -16513,7 +16741,7 @@ function readManifest(path = MANIFEST_PATH) {
16513
16741
  return { version: 1, certifications: [] };
16514
16742
  }
16515
16743
  function saveManifest(m, path = MANIFEST_PATH) {
16516
- mkdirSync15(join29(homedir13(), ".mma"), { recursive: true });
16744
+ mkdirSync15(join28(homedir13(), ".mma"), { recursive: true });
16517
16745
  writeFileSync15(path, JSON.stringify(m, null, 2), "utf-8");
16518
16746
  }
16519
16747
  function upsertCertification(entry, path = MANIFEST_PATH) {
@@ -16548,7 +16776,7 @@ function getCertMark(model, providerUrl, currentVersion, path = MANIFEST_PATH) {
16548
16776
  }
16549
16777
  var MANIFEST_PATH;
16550
16778
  var init_manifest = __esm(() => {
16551
- MANIFEST_PATH = join29(homedir13(), ".mma", "certifications.json");
16779
+ MANIFEST_PATH = join28(homedir13(), ".mma", "certifications.json");
16552
16780
  });
16553
16781
 
16554
16782
  // node_modules/yaml/dist/nodes/identity.js
@@ -23671,8 +23899,8 @@ var init_scenarios = __esm(() => {
23671
23899
  });
23672
23900
 
23673
23901
  // src/modules/certification/loader.ts
23674
- import { existsSync as existsSync35, readdirSync as readdirSync10, readFileSync as readFileSync24 } from "fs";
23675
- import { join as join30 } from "path";
23902
+ import { existsSync as existsSync36, readdirSync as readdirSync10, readFileSync as readFileSync24 } from "fs";
23903
+ import { join as join29 } from "path";
23676
23904
  function validateScenario(s) {
23677
23905
  const errors2 = [];
23678
23906
  const isSkip = s.mode === "skip";
@@ -23721,12 +23949,12 @@ function loadScenarios(userDir) {
23721
23949
  else
23722
23950
  scenarios.push(s);
23723
23951
  }
23724
- if (userDir && existsSync35(userDir)) {
23952
+ if (userDir && existsSync36(userDir)) {
23725
23953
  for (const file of readdirSync10(userDir)) {
23726
23954
  if (!file.endsWith(".yaml") && !file.endsWith(".yml"))
23727
23955
  continue;
23728
23956
  try {
23729
- const raw = readFileSync24(join30(userDir, file), "utf-8");
23957
+ const raw = readFileSync24(join29(userDir, file), "utf-8");
23730
23958
  const data = $parse(raw);
23731
23959
  const parsed = normalizeScenario(data, file);
23732
23960
  const errs = validateScenario(parsed);
@@ -23779,8 +24007,8 @@ var init_loader3 = __esm(() => {
23779
24007
  });
23780
24008
 
23781
24009
  // src/modules/certification/fact-checker.ts
23782
- import { existsSync as existsSync36, readFileSync as readFileSync25, statSync as statSync7 } from "fs";
23783
- import { join as join31 } from "path";
24010
+ import { existsSync as existsSync37, readFileSync as readFileSync25, statSync as statSync7 } from "fs";
24011
+ import { join as join30 } from "path";
23784
24012
  function checkSandbox(sandboxDir, checks, exitCode, output) {
23785
24013
  const failures = [];
23786
24014
  for (const check of checks) {
@@ -23797,13 +24025,13 @@ function runCheck(sandboxDir, check, exitCode, output) {
23797
24025
  case "outputContains":
23798
24026
  return output.includes(check.text);
23799
24027
  case "fileExists":
23800
- return isFile(join31(sandboxDir, check.path));
24028
+ return isFile(join30(sandboxDir, check.path));
23801
24029
  case "fileNotExists":
23802
- return !existsSync36(join31(sandboxDir, check.path));
24030
+ return !existsSync37(join30(sandboxDir, check.path));
23803
24031
  case "dirExists":
23804
- return isDir(join31(sandboxDir, check.path));
24032
+ return isDir(join30(sandboxDir, check.path));
23805
24033
  case "fileContent": {
23806
- const abs = join31(sandboxDir, check.path);
24034
+ const abs = join30(sandboxDir, check.path);
23807
24035
  if (!isFile(abs))
23808
24036
  return false;
23809
24037
  const content = readFileSync25(abs, "utf-8");
@@ -23814,7 +24042,7 @@ function runCheck(sandboxDir, check, exitCode, output) {
23814
24042
  return false;
23815
24043
  }
23816
24044
  case "fileRegex": {
23817
- const abs = join31(sandboxDir, check.path);
24045
+ const abs = join30(sandboxDir, check.path);
23818
24046
  if (!isFile(abs))
23819
24047
  return false;
23820
24048
  return new RegExp(check.pattern).test(readFileSync25(abs, "utf-8"));
@@ -23825,14 +24053,14 @@ function runCheck(sandboxDir, check, exitCode, output) {
23825
24053
  }
23826
24054
  function isFile(p) {
23827
24055
  try {
23828
- return existsSync36(p) && statSync7(p).isFile();
24056
+ return existsSync37(p) && statSync7(p).isFile();
23829
24057
  } catch {
23830
24058
  return false;
23831
24059
  }
23832
24060
  }
23833
24061
  function isDir(p) {
23834
24062
  try {
23835
- return existsSync36(p) && statSync7(p).isDirectory();
24063
+ return existsSync37(p) && statSync7(p).isDirectory();
23836
24064
  } catch {
23837
24065
  return false;
23838
24066
  }
@@ -23862,10 +24090,10 @@ function describe(check) {
23862
24090
  var init_fact_checker = () => {};
23863
24091
 
23864
24092
  // src/modules/certification/runner.ts
23865
- import { spawn as spawn4 } from "child_process";
23866
- import { existsSync as existsSync37, mkdirSync as mkdirSync16, rmSync as rmSync3, cpSync as cpSync2 } from "fs";
24093
+ import { spawn as spawn5 } from "child_process";
24094
+ import { existsSync as existsSync38, mkdirSync as mkdirSync16, rmSync as rmSync3, cpSync as cpSync2 } from "fs";
23867
24095
  import { platform as platform5 } from "os";
23868
- import { join as join32, resolve as resolve16, dirname as dirname9 } from "path";
24096
+ import { join as join31, resolve as resolve18, dirname as dirname9 } from "path";
23869
24097
  async function runScenario(scenario, opts) {
23870
24098
  if (scenario.mode === "skip") {
23871
24099
  return {
@@ -23884,7 +24112,7 @@ async function runScenario(scenario, opts) {
23884
24112
  let passed = 0;
23885
24113
  let firstError;
23886
24114
  for (let i = 1;i <= reps; i++) {
23887
- const sandbox = join32(opts.sandboxBase, `run-${scenario.id}-${i}`);
24115
+ const sandbox = join31(opts.sandboxBase, `run-${scenario.id}-${i}`);
23888
24116
  let failures = [];
23889
24117
  let exitCode = -1;
23890
24118
  let output = "";
@@ -23945,28 +24173,28 @@ function prepareSandbox(sandbox, scenario, mmaRoot) {
23945
24173
  rmSync3(sandbox, { recursive: true, force: true });
23946
24174
  mkdirSync16(sandbox, { recursive: true });
23947
24175
  for (const f of scenario.fixtures ?? []) {
23948
- const src = join32(mmaRoot, f.source);
23949
- if (!existsSync37(src)) {
24176
+ const src = join31(mmaRoot, f.source);
24177
+ if (!existsSync38(src)) {
23950
24178
  throw new Error(`fixture missing: ${f.source}`);
23951
24179
  }
23952
- const dest = join32(sandbox, f.dest);
24180
+ const dest = join31(sandbox, f.dest);
23953
24181
  mkdirSync16(dirname9(dest), { recursive: true });
23954
24182
  cpSync2(src, dest);
23955
24183
  }
23956
24184
  }
23957
24185
  function resolveMmaEntry(mmaRoot) {
23958
- const dev = join32(mmaRoot, "src", "cli", "main.ts");
23959
- if (existsSync37(dev))
24186
+ const dev = join31(mmaRoot, "src", "cli", "main.ts");
24187
+ if (existsSync38(dev))
23960
24188
  return dev;
23961
- return join32(mmaRoot, "dist", "main.js");
24189
+ return join31(mmaRoot, "dist", "main.js");
23962
24190
  }
23963
24191
  function findMmaRoot(fromDir) {
23964
24192
  const candidates = [
23965
- resolve16(fromDir, "..", "..", ".."),
23966
- resolve16(fromDir, "..")
24193
+ resolve18(fromDir, "..", "..", ".."),
24194
+ resolve18(fromDir, "..")
23967
24195
  ];
23968
24196
  for (const c of candidates) {
23969
- if (existsSync37(join32(c, "package.json")))
24197
+ if (existsSync38(join31(c, "package.json")))
23970
24198
  return c;
23971
24199
  }
23972
24200
  return process.cwd();
@@ -23976,7 +24204,7 @@ function killTree3(child) {
23976
24204
  if (!pid)
23977
24205
  return;
23978
24206
  if (platform5() === "win32") {
23979
- spawn4("taskkill", ["/pid", String(pid), "/T", "/F"], {
24207
+ spawn5("taskkill", ["/pid", String(pid), "/T", "/F"], {
23980
24208
  windowsHide: true,
23981
24209
  stdio: "ignore"
23982
24210
  });
@@ -23991,7 +24219,7 @@ function killTree3(child) {
23991
24219
  }
23992
24220
  }
23993
24221
  var defaultRunner = (env2, cwd, args, timeoutMs) => new Promise((resolvePromise) => {
23994
- const child = spawn4(process.execPath, args, {
24222
+ const child = spawn5(process.execPath, args, {
23995
24223
  cwd,
23996
24224
  env: env2,
23997
24225
  windowsHide: true,
@@ -24034,15 +24262,15 @@ __export(exports_cli, {
24034
24262
  });
24035
24263
  import { rmSync as rmSync4 } from "fs";
24036
24264
  import { homedir as homedir14 } from "os";
24037
- import { join as join33, dirname as dirname10 } from "path";
24265
+ import { join as join32, dirname as dirname10 } from "path";
24038
24266
  import { fileURLToPath } from "url";
24039
- import { existsSync as existsSync38, readFileSync as readFileSync26 } from "fs";
24267
+ import { existsSync as existsSync39, readFileSync as readFileSync26 } from "fs";
24040
24268
  function readVersion() {
24041
24269
  const candidates = [
24042
- join33(MMA_ROOT, "package.json")
24270
+ join32(MMA_ROOT, "package.json")
24043
24271
  ];
24044
24272
  for (const p of candidates) {
24045
- if (existsSync38(p)) {
24273
+ if (existsSync39(p)) {
24046
24274
  const raw = JSON.parse(readFileSync26(p, "utf-8"));
24047
24275
  if (raw.version)
24048
24276
  return raw.version;
@@ -24078,7 +24306,7 @@ async function certify(opts) {
24078
24306
  return;
24079
24307
  }
24080
24308
  console.log(t("cli.cert_started", { model: opts.name, provider: providerUrl }));
24081
- const sandboxBase = join33(process.cwd(), ".mma", "certification");
24309
+ const sandboxBase = join32(process.cwd(), ".mma", "certification");
24082
24310
  const results = [];
24083
24311
  const total = selected.length;
24084
24312
  let idx = 0;
@@ -24186,7 +24414,7 @@ var init_cli = __esm(() => {
24186
24414
  init_manifest();
24187
24415
  HERE = dirname10(fileURLToPath(import.meta.url));
24188
24416
  MMA_ROOT = findMmaRoot(HERE);
24189
- USER_SCENARIO_DIR = join33(homedir14(), ".mma", "certification", "scenarios");
24417
+ USER_SCENARIO_DIR = join32(homedir14(), ".mma", "certification", "scenarios");
24190
24418
  });
24191
24419
 
24192
24420
  // src/cli/repl-commands.ts
@@ -24195,18 +24423,18 @@ __export(exports_repl_commands, {
24195
24423
  registerAllCommands: () => registerAllCommands,
24196
24424
  COMMAND_GROUPS: () => COMMAND_GROUPS
24197
24425
  });
24198
- import { join as join35, dirname as dirname12 } from "path";
24426
+ import { join as join34, dirname as dirname12 } from "path";
24199
24427
  import { homedir as homedir16 } from "os";
24200
- import { existsSync as existsSync40, readFileSync as readFileSync28 } from "fs";
24428
+ import { existsSync as existsSync41, readFileSync as readFileSync28 } from "fs";
24201
24429
  import { fileURLToPath as fileURLToPath3 } from "url";
24202
24430
  function readVersion3() {
24203
24431
  const here = dirname12(fileURLToPath3(import.meta.url));
24204
24432
  const candidates = [
24205
- join35(here, "..", "..", "package.json"),
24206
- join35(here, "..", "package.json")
24433
+ join34(here, "..", "..", "package.json"),
24434
+ join34(here, "..", "package.json")
24207
24435
  ];
24208
24436
  for (const p of candidates) {
24209
- if (existsSync40(p)) {
24437
+ if (existsSync41(p)) {
24210
24438
  const raw = JSON.parse(readFileSync28(p, "utf8"));
24211
24439
  if (raw.version)
24212
24440
  return raw.version;
@@ -24270,8 +24498,8 @@ function registerMmaCommands(ctx) {
24270
24498
  }
24271
24499
  try {
24272
24500
  const { loadFileAsDataUrl: loadFileAsDataUrl2, loadUrlAsDataUrl: loadUrlAsDataUrl2, readClipboardImage: readClipboardImage2 } = await Promise.resolve().then(() => (init_image_utils(), exports_image_utils));
24273
- const { existsSync: existsSync41 } = await import("fs");
24274
- const { resolve: resolve17 } = await import("path");
24501
+ const { existsSync: existsSync42 } = await import("fs");
24502
+ const { resolve: resolve19 } = await import("path");
24275
24503
  let dataUrl;
24276
24504
  let label;
24277
24505
  if (source.toLowerCase() === "clipboard") {
@@ -24289,8 +24517,8 @@ function registerMmaCommands(ctx) {
24289
24517
  dataUrl = result.dataUrl;
24290
24518
  label = source;
24291
24519
  } else {
24292
- const absPath = resolve17(process.cwd(), source);
24293
- if (!existsSync41(absPath)) {
24520
+ const absPath = resolve19(process.cwd(), source);
24521
+ if (!existsSync42(absPath)) {
24294
24522
  console.log(pc.red(t("image.not_found", { path: source })));
24295
24523
  return;
24296
24524
  }
@@ -24369,7 +24597,7 @@ function registerMmaCommands(ctx) {
24369
24597
  console.log(pc.yellow(t("repl.wizard_running")));
24370
24598
  await ctx.withExclusiveInput(async () => {
24371
24599
  const answers = await runSetup(ctx.rl);
24372
- const configPath = join35(homedir16(), ".mma", "config.json");
24600
+ const configPath = join34(homedir16(), ".mma", "config.json");
24373
24601
  ctx.config.provider.type = answers.provider;
24374
24602
  ctx.config.provider.baseUrl = answers.apiBase;
24375
24603
  ctx.config.provider.apiKey = answers.apiKey;
@@ -24423,7 +24651,7 @@ Excluded blocks: ${info.excluded.length}`));
24423
24651
  return;
24424
24652
  }
24425
24653
  ctx.config.provider.type = name;
24426
- const configPath = join35(homedir16(), ".mma", "config.json");
24654
+ const configPath = join34(homedir16(), ".mma", "config.json");
24427
24655
  saveConfig(ctx.config, configPath);
24428
24656
  await ctx.agent.reconfigure(ctx.config);
24429
24657
  console.log(pc.green(t("repl.provider_set", { name })));
@@ -24479,7 +24707,7 @@ Excluded blocks: ${info.excluded.length}`));
24479
24707
  return;
24480
24708
  }
24481
24709
  ctx.config.model = name;
24482
- const configPath = join35(homedir16(), ".mma", "config.json");
24710
+ const configPath = join34(homedir16(), ".mma", "config.json");
24483
24711
  saveConfig(ctx.config, configPath);
24484
24712
  await ctx.agent.reconfigure(ctx.config);
24485
24713
  console.log(pc.green(t("repl.model_set", { name })));
@@ -24504,7 +24732,7 @@ Excluded blocks: ${info.excluded.length}`));
24504
24732
  return;
24505
24733
  }
24506
24734
  ctx.config.contextWindow = size;
24507
- const configPath = join35(homedir16(), ".mma", "config.json");
24735
+ const configPath = join34(homedir16(), ".mma", "config.json");
24508
24736
  saveConfig(ctx.config, configPath);
24509
24737
  await ctx.agent.reconfigure(ctx.config);
24510
24738
  console.log(pc.green(t("cli.context_set", { size })));
@@ -24521,11 +24749,11 @@ Excluded blocks: ${info.excluded.length}`));
24521
24749
  if (active) {}
24522
24750
  }
24523
24751
  ctx.agent.shutdown();
24524
- const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), exports_config));
24752
+ const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config2(), exports_config));
24525
24753
  const { homedir: homedir17 } = await import("os");
24526
- const { join: join36 } = await import("path");
24527
- const configDir = join36(homedir17(), ".mma");
24528
- const projectConfigPath = join36(process.cwd(), ".mmrc");
24754
+ const { join: join35 } = await import("path");
24755
+ const configDir = join35(homedir17(), ".mma");
24756
+ const projectConfigPath = join35(process.cwd(), ".mmrc");
24529
24757
  const freshConfig = loadConfig2({ configDir, projectConfigPath });
24530
24758
  Object.assign(ctx.config, freshConfig);
24531
24759
  const { bootstrap: bootstrap2 } = await Promise.resolve().then(() => (init_bootstrap(), exports_bootstrap));
@@ -24778,7 +25006,7 @@ var init_repl_commands = __esm(() => {
24778
25006
  init_table();
24779
25007
  init_i18n();
24780
25008
  init_setup();
24781
- init_config();
25009
+ init_config2();
24782
25010
  version2 = readVersion3();
24783
25011
  COMMAND_GROUPS = {
24784
25012
  help: "general",
@@ -24822,17 +25050,17 @@ var {
24822
25050
 
24823
25051
  // src/cli/commands.ts
24824
25052
  init_bootstrap();
24825
- init_config();
25053
+ init_config2();
24826
25054
  init_setup();
24827
25055
  init_i18n();
24828
- import { join as join34, dirname as dirname11 } from "path";
25056
+ import { join as join33, dirname as dirname11 } from "path";
24829
25057
  import { homedir as homedir15 } from "os";
24830
- import { existsSync as existsSync39, readFileSync as readFileSync27 } from "fs";
25058
+ import { existsSync as existsSync40, readFileSync as readFileSync27 } from "fs";
24831
25059
 
24832
25060
  // src/cli/security-commands.ts
24833
25061
  init_bootstrap();
24834
- init_config();
24835
- import { join as join28 } from "path";
25062
+ init_config2();
25063
+ import { join as join27 } from "path";
24836
25064
  import { homedir as homedir12 } from "os";
24837
25065
 
24838
25066
  // src/modules/security/security-policies.ts
@@ -25362,7 +25590,7 @@ function createSecurityCommand(program2) {
25362
25590
  }
25363
25591
  });
25364
25592
  securityCmd.command("set-policy").argument("<preset>", t("cli.security.preset")).description(t("cli.security.set_policy")).action(async (preset) => {
25365
- const configPath = join28(homedir12(), ".mma", "config.json");
25593
+ const configPath = join27(homedir12(), ".mma", "config.json");
25366
25594
  const { config: appConfig } = await bootstrap();
25367
25595
  const validPresets = ["strict", "balanced", "permissive"];
25368
25596
  if (!validPresets.includes(preset)) {
@@ -25377,7 +25605,7 @@ function createSecurityCommand(program2) {
25377
25605
  console.log(t("cli.security.policy_description", { description: policy.description }));
25378
25606
  });
25379
25607
  securityCmd.command("enable-encryption").description(t("cli.security.enable_encryption")).action(async () => {
25380
- const configPath = join28(homedir12(), ".mma", "config.json");
25608
+ const configPath = join27(homedir12(), ".mma", "config.json");
25381
25609
  const { config: appConfig } = await bootstrap();
25382
25610
  appConfig.security = appConfig.security || {};
25383
25611
  appConfig.security.sessionEncryption = {
@@ -25389,7 +25617,7 @@ function createSecurityCommand(program2) {
25389
25617
  console.log(t("cli.security.encryption_enabled"));
25390
25618
  });
25391
25619
  securityCmd.command("disable-encryption").description(t("cli.security.disable_encryption")).action(async () => {
25392
- const configPath = join28(homedir12(), ".mma", "config.json");
25620
+ const configPath = join27(homedir12(), ".mma", "config.json");
25393
25621
  const { config: appConfig } = await bootstrap();
25394
25622
  appConfig.security = appConfig.security || {};
25395
25623
  appConfig.security.sessionEncryption = {
@@ -25401,7 +25629,7 @@ function createSecurityCommand(program2) {
25401
25629
  console.log(t("cli.security.encryption_disabled"));
25402
25630
  });
25403
25631
  securityCmd.command("enable-audit").description(t("cli.security.enable_audit")).action(async () => {
25404
- const configPath = join28(homedir12(), ".mma", "config.json");
25632
+ const configPath = join27(homedir12(), ".mma", "config.json");
25405
25633
  const { config: appConfig } = await bootstrap();
25406
25634
  appConfig.security = appConfig.security || {};
25407
25635
  appConfig.security.auditNotifier = {
@@ -25415,7 +25643,7 @@ function createSecurityCommand(program2) {
25415
25643
  console.log(t("cli.security.audit_enabled"));
25416
25644
  });
25417
25645
  securityCmd.command("disable-audit").description(t("cli.security.disable_audit")).action(async () => {
25418
- const configPath = join28(homedir12(), ".mma", "config.json");
25646
+ const configPath = join27(homedir12(), ".mma", "config.json");
25419
25647
  const { config: appConfig } = await bootstrap();
25420
25648
  appConfig.security = appConfig.security || {};
25421
25649
  appConfig.security.auditNotifier = {
@@ -25451,11 +25679,11 @@ import { fileURLToPath as fileURLToPath2 } from "url";
25451
25679
  function readVersion2() {
25452
25680
  const here = dirname11(fileURLToPath2(import.meta.url));
25453
25681
  const candidates = [
25454
- join34(here, "..", "..", "package.json"),
25455
- join34(here, "..", "package.json")
25682
+ join33(here, "..", "..", "package.json"),
25683
+ join33(here, "..", "package.json")
25456
25684
  ];
25457
25685
  for (const p of candidates) {
25458
- if (existsSync39(p)) {
25686
+ if (existsSync40(p)) {
25459
25687
  const raw = JSON.parse(readFileSync27(p, "utf8"));
25460
25688
  if (raw.version)
25461
25689
  return raw.version;
@@ -25468,7 +25696,7 @@ function createProgram() {
25468
25696
  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"));
25469
25697
  program2.command("init").description(t("cli.init")).action(async () => {
25470
25698
  const answers = await runSetup();
25471
- const configPath = join34(homedir15(), ".mma", "config.json");
25699
+ const configPath = join33(homedir15(), ".mma", "config.json");
25472
25700
  const { config } = await bootstrap();
25473
25701
  config.provider.type = answers.provider;
25474
25702
  config.provider.baseUrl = answers.apiBase;
@@ -25513,7 +25741,7 @@ function createProgram() {
25513
25741
  });
25514
25742
  const configCmd = program2.command("config").description(t("cli.manage_config"));
25515
25743
  configCmd.command("set").argument("<key>", t("cli.config_key")).argument("<value>", "Config value").description(t("cli.set_value")).action(async (key, value) => {
25516
- const configPath = join34(homedir15(), ".mma", "config.json");
25744
+ const configPath = join33(homedir15(), ".mma", "config.json");
25517
25745
  const { config } = await bootstrap();
25518
25746
  const keys = key.split(".");
25519
25747
  let obj = config;
@@ -25576,7 +25804,7 @@ function createProgram() {
25576
25804
  console.log(t("cli.model_hint"));
25577
25805
  });
25578
25806
  model.command("use").argument("<name>", "Model name").description(t("cli.set_model")).action(async (name) => {
25579
- const configPath = join34(homedir15(), ".mma", "config.json");
25807
+ const configPath = join33(homedir15(), ".mma", "config.json");
25580
25808
  const { config } = await bootstrap();
25581
25809
  config.model = name;
25582
25810
  saveConfig(config, configPath);
@@ -25612,7 +25840,7 @@ function createProgram() {
25612
25840
  await uncertify2(name, config);
25613
25841
  });
25614
25842
  program2.command("context").description(t("cli.manage_context")).argument("<size>", "Context window size in tokens").action(async (size) => {
25615
- const configPath = join34(homedir15(), ".mma", "config.json");
25843
+ const configPath = join33(homedir15(), ".mma", "config.json");
25616
25844
  const { config } = await bootstrap();
25617
25845
  const contextWindow = parseInt(size, 10);
25618
25846
  if (isNaN(contextWindow) || contextWindow < 1024) {
@@ -25630,7 +25858,7 @@ function createProgram() {
25630
25858
  console.log(t("cli.base_url"), config.provider.baseUrl);
25631
25859
  });
25632
25860
  provider.command("use").argument("<name>", "Provider name").description(t("cli.set_provider")).action(async (name) => {
25633
- const configPath = join34(homedir15(), ".mma", "config.json");
25861
+ const configPath = join33(homedir15(), ".mma", "config.json");
25634
25862
  const { config } = await bootstrap();
25635
25863
  config.provider.type = name;
25636
25864
  saveConfig(config, configPath);
@@ -25682,8 +25910,8 @@ init_bootstrap();
25682
25910
  // src/cli/repl.ts
25683
25911
  init_colors();
25684
25912
  import * as readline2 from "readline";
25685
- import { existsSync as existsSync41, readFileSync as readFileSync29, writeFileSync as writeFileSync16 } from "fs";
25686
- import { join as join36, dirname as dirname13 } from "path";
25913
+ import { existsSync as existsSync42, readFileSync as readFileSync29, writeFileSync as writeFileSync16 } from "fs";
25914
+ import { join as join35, dirname as dirname13 } from "path";
25687
25915
  import { homedir as homedir17 } from "os";
25688
25916
  import { fileURLToPath as fileURLToPath4 } from "url";
25689
25917
 
@@ -25793,7 +26021,6 @@ init_colors();
25793
26021
  init_colors();
25794
26022
  init_i18n();
25795
26023
  init_table();
25796
- init_string_width();
25797
26024
  var KW = /\b(import|export|from|const|let|var|function|return|if|else|for|while|do|switch|case|break|continue|new|class|extends|implements|interface|type|enum|namespace|module|declare|abstract|async|await|yield|throw|try|catch|finally|typeof|instanceof|in|of|as|is|keyof|readonly|static|private|public|protected|get|set|constructor|this|super|void|never|any|unknown|boolean|string|number|symbol|object|true|false|null|undefined|default)\b/g;
25798
26025
  var STRING = /('[^']*'|"[^"]*"|`[^`]*`)/g;
25799
26026
  var COMMENT = /(\/\/[^\n]*|\/\*[\s\S]*?\*\/|#[^\n]*)/g;
@@ -25842,13 +26069,9 @@ class FormattingStream {
25842
26069
  tableBuffer = [];
25843
26070
  onWrite;
25844
26071
  width;
25845
- streaming;
25846
- partialEmitted = false;
25847
- lastPartial = "";
25848
- constructor(onWrite, width, streaming = false) {
26072
+ constructor(onWrite, width) {
25849
26073
  this.onWrite = onWrite;
25850
26074
  this.width = width ?? getTerminalWidth();
25851
- this.streaming = streaming;
25852
26075
  }
25853
26076
  write(chunk) {
25854
26077
  this.buffer += chunk;
@@ -25857,13 +26080,10 @@ class FormattingStream {
25857
26080
  `)) !== -1) {
25858
26081
  const line = this.buffer.slice(0, idx);
25859
26082
  this.buffer = this.buffer.slice(idx + 1);
25860
- this.clearPartial();
25861
26083
  this.processLine(line);
25862
26084
  }
25863
- this.emitPartial(this.buffer);
25864
26085
  }
25865
26086
  flush() {
25866
- this.clearPartial();
25867
26087
  if (this.inCodeBlock && this.codeLines.length > 0) {
25868
26088
  this.emitCodeBlock();
25869
26089
  }
@@ -25879,40 +26099,9 @@ class FormattingStream {
25879
26099
  }
25880
26100
  return;
25881
26101
  }
25882
- this.emitLine(this.formatLine(line));
26102
+ this.onWrite(this.formatLine(line));
25883
26103
  }
25884
26104
  }
25885
- emitLine(text) {
25886
- this.onWrite(text, true);
25887
- }
25888
- emitRaw(text) {
25889
- this.onWrite(text, false);
25890
- }
25891
- clearPartial() {
25892
- if (!this.streaming || !this.partialEmitted)
25893
- return;
25894
- const rows = Math.max(1, Math.ceil(stringWidth(this.lastPartial) / Math.max(1, this.width)));
25895
- for (let i = 0;i < rows; i++) {
25896
- this.emitRaw("\x1B[2K");
25897
- if (i < rows - 1)
25898
- this.emitRaw("\x1B[1A");
25899
- }
25900
- this.emitRaw("\r");
25901
- this.lastPartial = "";
25902
- this.partialEmitted = false;
25903
- }
25904
- emitPartial(text) {
25905
- if (!this.streaming || !text)
25906
- return;
25907
- if (this.inCodeBlock || this.tableBuffer.length > 0) {
25908
- this.clearPartial();
25909
- return;
25910
- }
25911
- this.clearPartial();
25912
- this.emitRaw(text);
25913
- this.lastPartial = text;
25914
- this.partialEmitted = true;
25915
- }
25916
26105
  processLine(line) {
25917
26106
  if (line.trim() === "```" || line.trim().startsWith("```")) {
25918
26107
  if (this.inCodeBlock) {
@@ -25935,7 +26124,7 @@ class FormattingStream {
25935
26124
  if (this.tableBuffer.length > 0) {
25936
26125
  this.flushTable();
25937
26126
  }
25938
- this.emitLine(this.formatLine(line));
26127
+ this.onWrite(this.formatLine(line));
25939
26128
  }
25940
26129
  flushTable() {
25941
26130
  const lines = this.tableBuffer;
@@ -25943,11 +26132,11 @@ class FormattingStream {
25943
26132
  const hasSeparator = lines.length >= 2 && /^\s*\|?[\s:|-]+\|?\s*$/.test(lines[1].trim());
25944
26133
  if (hasSeparator) {
25945
26134
  for (const l of formatTable(lines, { maxWidth: this.width })) {
25946
- this.emitLine(l);
26135
+ this.onWrite(l);
25947
26136
  }
25948
26137
  } else {
25949
26138
  for (const l of lines) {
25950
- this.emitLine(this.formatLine(l));
26139
+ this.onWrite(this.formatLine(l));
25951
26140
  }
25952
26141
  }
25953
26142
  }
@@ -25959,12 +26148,12 @@ class FormattingStream {
25959
26148
  const highlighted = highlight(code, this.codeLang);
25960
26149
  const lang = this.codeLang ? ` ${this.codeLang} ` : " ";
25961
26150
  const top = pc.dim(`┌─${lang}${"─".repeat(Math.max(0, this.width - 3 - lang.length))}┐`);
25962
- this.emitLine(top);
26151
+ this.onWrite(top);
25963
26152
  for (const l of highlighted.split(`
25964
26153
  `)) {
25965
- this.emitLine(pc.dim("│ ") + l);
26154
+ this.onWrite(pc.dim("│ ") + l);
25966
26155
  }
25967
- this.emitLine(pc.dim(`└${"─".repeat(Math.max(0, this.width - 1))}┘`));
26156
+ this.onWrite(pc.dim(`└${"─".repeat(Math.max(0, this.width - 1))}┘`));
25968
26157
  }
25969
26158
  this.codeLines = [];
25970
26159
  this.codeLang = "";
@@ -26076,8 +26265,8 @@ class Renderer {
26076
26265
  stream: this.err,
26077
26266
  width: this.width
26078
26267
  });
26079
- this.fmt = new FormattingStream((line, eol) => this.out.write(eol ? `${line}
26080
- ` : line), this.width, this.rich);
26268
+ this.fmt = new FormattingStream((line) => this.out.write(`${line}
26269
+ `), this.width);
26081
26270
  }
26082
26271
  text(chunk) {
26083
26272
  this.endCard();
@@ -26086,7 +26275,6 @@ class Renderer {
26086
26275
  }
26087
26276
  meta(chunk) {
26088
26277
  this.spinner.stop();
26089
- this.fmt.clearPartial();
26090
26278
  if (this.card) {
26091
26279
  this.card.body.push(chunk);
26092
26280
  } else {
@@ -26095,7 +26283,6 @@ class Renderer {
26095
26283
  }
26096
26284
  reasoning(chunk) {
26097
26285
  this.spinner.stop();
26098
- this.fmt.clearPartial();
26099
26286
  this.out.write(pc.dim(chunk));
26100
26287
  }
26101
26288
  thinkingStart() {
@@ -26107,7 +26294,6 @@ class Renderer {
26107
26294
  toolStart(tool, args) {
26108
26295
  this.endCard();
26109
26296
  this.spinner.stop();
26110
- this.fmt.clearPartial();
26111
26297
  const summary = summarizeArgs2(args);
26112
26298
  if (!this.rich) {
26113
26299
  this.out.write(`
@@ -26159,13 +26345,11 @@ ${pc.dim("⚙")} ${friendlyTool(tool)}${summary ? ` ${pc.dim(summary)}` : ""}
26159
26345
  raw(text) {
26160
26346
  this.endCard();
26161
26347
  this.spinner.stop();
26162
- this.fmt.clearPartial();
26163
26348
  this.out.write(text);
26164
26349
  }
26165
26350
  error(text) {
26166
26351
  this.endCard();
26167
26352
  this.spinner.stop();
26168
- this.fmt.clearPartial();
26169
26353
  this.err.write(`${pc.red(text)}
26170
26354
  `);
26171
26355
  }
@@ -26189,11 +26373,11 @@ init_repl_commands();
26189
26373
  function readVersion4() {
26190
26374
  const here = dirname13(fileURLToPath4(import.meta.url));
26191
26375
  const candidates = [
26192
- join36(here, "..", "..", "package.json"),
26193
- join36(here, "..", "package.json")
26376
+ join35(here, "..", "..", "package.json"),
26377
+ join35(here, "..", "package.json")
26194
26378
  ];
26195
26379
  for (const p of candidates) {
26196
- if (existsSync41(p)) {
26380
+ if (existsSync42(p)) {
26197
26381
  const raw = JSON.parse(readFileSync29(p, "utf8"));
26198
26382
  if (raw.version)
26199
26383
  return raw.version;
@@ -26245,10 +26429,10 @@ class Repl {
26245
26429
  this.sessionManager = sessionManager;
26246
26430
  this.skillsModule = skillsModule;
26247
26431
  this.pluginManager = pluginManager;
26248
- this.configDir = configDir || join36(homedir17(), ".mma");
26432
+ this.configDir = configDir || join35(homedir17(), ".mma");
26249
26433
  this.baseDir = baseDir || process.cwd();
26250
26434
  this.noAgentsMd = noAgentsMd === true;
26251
- this.historyPath = join36(homedir17(), ".mma", "repl-history");
26435
+ this.historyPath = join35(homedir17(), ".mma", "repl-history");
26252
26436
  this.loadHistory();
26253
26437
  this.rl = readline2.createInterface({
26254
26438
  input: process.stdin,
@@ -26269,7 +26453,7 @@ class Repl {
26269
26453
  this.setupListeners();
26270
26454
  }
26271
26455
  loadHistory() {
26272
- if (existsSync41(this.historyPath)) {
26456
+ if (existsSync42(this.historyPath)) {
26273
26457
  try {
26274
26458
  const raw = readFileSync29(this.historyPath, "utf-8");
26275
26459
  this.history = raw.split(`
@@ -26369,8 +26553,9 @@ class Repl {
26369
26553
  this.running = false;
26370
26554
  });
26371
26555
  if (process.stdin.isTTY) {
26372
- process.stdin.on("data", (chunk) => {
26373
- if (chunk.length === 1 && chunk[0] === 27) {
26556
+ readline2.emitKeypressEvents(process.stdin);
26557
+ process.stdin.on("keypress", async (str, key) => {
26558
+ if (key.name === "escape") {
26374
26559
  const now = Date.now();
26375
26560
  if (now - this.lastEscTime < this.doubleEscDelay) {
26376
26561
  if (this.agentRunning) {
@@ -26384,8 +26569,19 @@ ${t("repl.interrupt")}
26384
26569
  }
26385
26570
  this.lastEscTime = now;
26386
26571
  }
26387
- if (chunk.length === 1 && chunk[0] === 22 && !this.agentRunning) {
26388
- this.handlePasteImage();
26572
+ if (key.ctrl && key.name === "v" && !this.agentRunning) {
26573
+ try {
26574
+ const { readClipboardImage: readClipboardImage2, bufferToDataUrl: bufferToDataUrl2 } = await Promise.resolve().then(() => (init_image_utils(), exports_image_utils));
26575
+ const clipBuf = await readClipboardImage2();
26576
+ if (clipBuf) {
26577
+ const { dataUrl } = await bufferToDataUrl2(clipBuf);
26578
+ this.pendingClipboardImage = dataUrl;
26579
+ const sizeKb = Math.round(dataUrl.length * 3 / 4 / 1024);
26580
+ console.log(pc.green(`
26581
+ ${t("image.attached", { source: "clipboard", size: `${sizeKb} KB` })}`));
26582
+ this.rl.prompt();
26583
+ }
26584
+ } catch {}
26389
26585
  }
26390
26586
  });
26391
26587
  }
@@ -26401,20 +26597,6 @@ ${t("repl.interrupt")}
26401
26597
  }
26402
26598
  });
26403
26599
  }
26404
- async handlePasteImage() {
26405
- try {
26406
- const { readClipboardImage: readClipboardImage2, bufferToDataUrl: bufferToDataUrl2 } = await Promise.resolve().then(() => (init_image_utils(), exports_image_utils));
26407
- const clipBuf = await readClipboardImage2();
26408
- if (clipBuf) {
26409
- const { dataUrl } = await bufferToDataUrl2(clipBuf);
26410
- this.pendingClipboardImage = dataUrl;
26411
- const sizeKb = Math.round(dataUrl.length * 3 / 4 / 1024);
26412
- console.log(pc.green(`
26413
- ${t("image.attached", { source: "clipboard", size: `${sizeKb} KB` })}`));
26414
- this.rl.prompt();
26415
- }
26416
- } catch {}
26417
- }
26418
26600
  isMultiLineInput(line) {
26419
26601
  if (line.endsWith("\\"))
26420
26602
  return true;
@@ -26581,11 +26763,11 @@ ${t("image.attached", { source: "clipboard", size: `${sizeKb} KB` })}`));
26581
26763
  row(t("repl.agents_label"), pc.red(t("repl.disabled")));
26582
26764
  } else {
26583
26765
  const agentsMdCandidates = [
26584
- join36(this.baseDir, "AGENTS.md"),
26585
- join36(this.baseDir, ".mma", "AGENTS.md"),
26586
- join36(this.configDir, "AGENTS.md")
26766
+ join35(this.baseDir, "AGENTS.md"),
26767
+ join35(this.baseDir, ".mma", "AGENTS.md"),
26768
+ join35(this.configDir, "AGENTS.md")
26587
26769
  ];
26588
- const foundAgents = agentsMdCandidates.filter((p) => existsSync41(p));
26770
+ const foundAgents = agentsMdCandidates.filter((p) => existsSync42(p));
26589
26771
  if (foundAgents.length > 0) {
26590
26772
  for (const p of foundAgents) {
26591
26773
  row(t("repl.agents_label"), pc.dim(p));
@@ -26596,7 +26778,7 @@ ${t("image.attached", { source: "clipboard", size: `${sizeKb} KB` })}`));
26596
26778
  }
26597
26779
  const meta = this.sessionManager?.getActiveMeta();
26598
26780
  if (meta) {
26599
- const sessionPath = join36(this.configDir, "sessions", meta.id);
26781
+ const sessionPath = join35(this.configDir, "sessions", meta.id);
26600
26782
  row(t("repl.session_label"), `${pc.cyan(meta.name)} ${pc.dim(`(${meta.id.slice(0, 12)})`)} — ${meta.messageCount} msgs ${pc.dim(sessionPath)}`);
26601
26783
  }
26602
26784
  const headerWidth = Math.max(50, Math.min(96, process.stdout.columns || 96));
@@ -26619,11 +26801,11 @@ ${t("image.attached", { source: "clipboard", size: `${sizeKb} KB` })}`));
26619
26801
 
26620
26802
  // src/cli/main.ts
26621
26803
  init_setup();
26622
- init_config();
26804
+ init_config2();
26623
26805
  init_i18n();
26624
26806
  init_colors();
26625
- import { existsSync as existsSync42 } from "fs";
26626
- import { join as join37 } from "path";
26807
+ import { existsSync as existsSync43 } from "fs";
26808
+ import { join as join36 } from "path";
26627
26809
  import { homedir as homedir18 } from "os";
26628
26810
  async function main() {
26629
26811
  const program2 = createProgram();
@@ -26687,8 +26869,8 @@ async function main() {
26687
26869
  }
26688
26870
  agent.shutdown();
26689
26871
  } else {
26690
- const configPath = join37(homedir18(), ".mma", "config.json");
26691
- if (!existsSync42(configPath)) {
26872
+ const configPath = join36(homedir18(), ".mma", "config.json");
26873
+ if (!existsSync43(configPath)) {
26692
26874
  console.log(pc.yellow(`
26693
26875
  ` + t("cli.first_run") + `
26694
26876
  `));