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