micro-models-agent 0.36.3 → 0.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.js +407 -139
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -2393,6 +2393,7 @@ var init_en = __esm(() => {
|
|
|
2393
2393
|
"tool.friendly.search_history": "Searching history",
|
|
2394
2394
|
"tool.friendly.pipeline_run": "Running pipeline",
|
|
2395
2395
|
"tool.friendly.mcp_call": "MCP call",
|
|
2396
|
+
"tool.friendly.lsp_check": "Checking code",
|
|
2396
2397
|
"tool.truncated": "[Truncated: {tokens} tokens removed]",
|
|
2397
2398
|
"tool.subagent_queued": "Sub-agent task queued: {task}",
|
|
2398
2399
|
"tool.subagent_artifact": `Sub-agent completed. Full result saved to artifact: {path}
|
|
@@ -2485,6 +2486,9 @@ Command: {command}`,
|
|
|
2485
2486
|
"plan.switched": "Switched to plan {id}: {title}",
|
|
2486
2487
|
"plan.replanned": "Plan re-planned: {kept} completed steps kept, {steps} new steps added",
|
|
2487
2488
|
"plan.replan_no_steps": "Provide new steps for re-planning",
|
|
2489
|
+
"plan.active_in_progress": 'Cannot create a new plan: active plan {id} already has progress ({done}/{total} done, current: step {current}). Resume it — use "plan show" to view, then continue working. To replace it, call "plan abort" first, then "plan create" again.',
|
|
2490
|
+
"plan.id_ignored": 'note: plan ids are auto-generated; use "plan switch" to activate an existing plan by id.',
|
|
2491
|
+
"plan.existing_fresh": "note: the previous active plan had no progress and was preserved as a draft.",
|
|
2488
2492
|
"todo.added": "Added {count} todo(s): {items}",
|
|
2489
2493
|
"todo.marked_done": "Marked {count} item(s) as done",
|
|
2490
2494
|
"todo.no_active": "No active todos",
|
|
@@ -2500,6 +2504,11 @@ Command: {command}`,
|
|
|
2500
2504
|
"verify.script_failed": "Script '{script}' failed: {message}",
|
|
2501
2505
|
"verify.syntax_error": "Syntax error in: {path}",
|
|
2502
2506
|
"lsp.unavailable": "static checks are unavailable (server not found). Verify via the project's own build/test instead.",
|
|
2507
|
+
"lsp.check_disabled": "LSP checks are disabled in the config.",
|
|
2508
|
+
"lsp.check_no_path": "Provide a path (file or directory) to check.",
|
|
2509
|
+
"lsp.check_notfound": "Path not found: {path}",
|
|
2510
|
+
"lsp.check_unsupported": "No LSP server configured for: {path}",
|
|
2511
|
+
"lsp.check_clean": "No errors or warnings detected ({count} file(s) checked).",
|
|
2503
2512
|
"cli.description": "Micro Models Agent — AI coding agent for small models",
|
|
2504
2513
|
"cli.init": "Run interactive setup wizard",
|
|
2505
2514
|
"cli.config_saved": "Configuration saved to ~/.mma/config.json",
|
|
@@ -2992,6 +3001,7 @@ var init_ru = __esm(() => {
|
|
|
2992
3001
|
"tool.friendly.search_history": "Поиск в истории",
|
|
2993
3002
|
"tool.friendly.pipeline_run": "Запуск пайплайна",
|
|
2994
3003
|
"tool.friendly.mcp_call": "MCP вызов",
|
|
3004
|
+
"tool.friendly.lsp_check": "Проверка кода",
|
|
2995
3005
|
"tool.truncated": "[Обрезано: удалено {tokens} токенов]",
|
|
2996
3006
|
"tool.subagent_queued": "Задача подагенту добавлена: {task}",
|
|
2997
3007
|
"tool.subagent_artifact": `Суб-агент завершён. Полный результат сохранён в артефакт: {path}
|
|
@@ -3084,6 +3094,9 @@ var init_ru = __esm(() => {
|
|
|
3084
3094
|
"plan.switched": "Переключено на план {id}: {title}",
|
|
3085
3095
|
"plan.replanned": "План перепланирован: {kept} выполненных шагов сохранено, {steps} новых шагов добавлено",
|
|
3086
3096
|
"plan.replan_no_steps": "Укажите новые шаги для перепланирования",
|
|
3097
|
+
"plan.active_in_progress": 'Нельзя создать новый план: активный план {id} уже имеет прогресс ({done}/{total} выполнено, текущий: шаг {current}). Продолжай его — вызови "plan show", чтобы увидеть, и продолжай работу. Чтобы заменить план, сначала вызови "plan abort", затем "plan create".',
|
|
3098
|
+
"plan.id_ignored": 'примечание: id плана генерируется автоматически; используй "plan switch", чтобы активировать существующий план по id.',
|
|
3099
|
+
"plan.existing_fresh": "примечание: предыдущий активный план не имел прогресса и сохранён как черновик.",
|
|
3087
3100
|
"todo.added": "Добавлено {count} задач: {items}",
|
|
3088
3101
|
"todo.marked_done": "Отмечено выполненными: {count}",
|
|
3089
3102
|
"todo.no_active": "Нет активных задач",
|
|
@@ -3099,6 +3112,11 @@ var init_ru = __esm(() => {
|
|
|
3099
3112
|
"verify.script_failed": "Скрипт '{script}' не пройден: {message}",
|
|
3100
3113
|
"verify.syntax_error": "Синтаксическая ошибка в: {path}",
|
|
3101
3114
|
"lsp.unavailable": "статические проверки недоступны (сервер не найден). Проверяйте через собственный build/test проекта.",
|
|
3115
|
+
"lsp.check_disabled": "LSP-проверки отключены в конфигурации.",
|
|
3116
|
+
"lsp.check_no_path": "Укажите путь (файл или каталог) для проверки.",
|
|
3117
|
+
"lsp.check_notfound": "Путь не найден: {path}",
|
|
3118
|
+
"lsp.check_unsupported": "Для файла не настроен LSP-сервер: {path}",
|
|
3119
|
+
"lsp.check_clean": "Ошибок и предупреждений не обнаружено (проверено файлов: {count}).",
|
|
3102
3120
|
"cli.description": "Micro Models Agent — ИИ-агент для кодинга на малых моделях",
|
|
3103
3121
|
"cli.init": "Запустить мастер настройки",
|
|
3104
3122
|
"cli.config_saved": "Конфигурация сохранена в ~/.mma/config.json",
|
|
@@ -11196,6 +11214,7 @@ class FactExtractor {
|
|
|
11196
11214
|
deletedFacts = [];
|
|
11197
11215
|
decisionFacts = [];
|
|
11198
11216
|
errorFacts = [];
|
|
11217
|
+
readFacts = [];
|
|
11199
11218
|
static MAX_FACTS = 20;
|
|
11200
11219
|
get errorCount() {
|
|
11201
11220
|
return this.errorFacts.length;
|
|
@@ -11211,13 +11230,19 @@ class FactExtractor {
|
|
|
11211
11230
|
new RegExp(`Deleted ${DRIVE}([\\w./\\\\-]+\\.[a-z]+)`, "gi"),
|
|
11212
11231
|
new RegExp(`(?:Удалён|Файл удалён):? ${DRIVE}([\\w./\\\\-]+\\.[a-z]+)`, "gi")
|
|
11213
11232
|
];
|
|
11233
|
+
const readPatterns = [
|
|
11234
|
+
new RegExp(`── (${DRIVE}[\\w./\\\\-]+\\.[a-z]+) \\(`, "gi")
|
|
11235
|
+
];
|
|
11214
11236
|
const newFiles = [];
|
|
11215
11237
|
const newDeleted = [];
|
|
11216
11238
|
const newDecisions = [];
|
|
11217
11239
|
const newErrors = [];
|
|
11240
|
+
const newReads = [];
|
|
11218
11241
|
const lastEvent = new Map;
|
|
11219
11242
|
for (const msg of turns) {
|
|
11220
11243
|
const content = getMessageText(msg.content);
|
|
11244
|
+
if (msg.role === "system")
|
|
11245
|
+
continue;
|
|
11221
11246
|
if (msg.role === "user" && (content.startsWith("<system-summary>") || content.includes("[Compressed:"))) {
|
|
11222
11247
|
continue;
|
|
11223
11248
|
}
|
|
@@ -11234,6 +11259,11 @@ class FactExtractor {
|
|
|
11234
11259
|
lastEvent.set(match[1], "deleted");
|
|
11235
11260
|
}
|
|
11236
11261
|
}
|
|
11262
|
+
for (const pattern of readPatterns) {
|
|
11263
|
+
for (const match of content.matchAll(pattern)) {
|
|
11264
|
+
newReads.push(match[1]);
|
|
11265
|
+
}
|
|
11266
|
+
}
|
|
11237
11267
|
if (content.includes("Plan:") && content.includes("[")) {
|
|
11238
11268
|
const planLine = content.split(`
|
|
11239
11269
|
`).find((line) => line.includes("Plan:"));
|
|
@@ -11249,11 +11279,13 @@ class FactExtractor {
|
|
|
11249
11279
|
newDecisions.push(line.trim().slice(0, 200));
|
|
11250
11280
|
}
|
|
11251
11281
|
}
|
|
11252
|
-
if (
|
|
11253
|
-
|
|
11282
|
+
if (msg.role === "tool" || msg.role === "assistant") {
|
|
11283
|
+
if (content.includes("Error:") || content.includes("failed") || content.includes("Ошибка:") || content.includes("не удалось")) {
|
|
11284
|
+
const line = content.split(`
|
|
11254
11285
|
`).find((l) => l.includes("Error:") || l.includes("failed") || l.includes("Ошибка:") || l.includes("не удалось"));
|
|
11255
|
-
|
|
11256
|
-
|
|
11286
|
+
if (line)
|
|
11287
|
+
newErrors.push(line.trim().slice(0, 250));
|
|
11288
|
+
}
|
|
11257
11289
|
}
|
|
11258
11290
|
}
|
|
11259
11291
|
const dedup = (arr) => [...new Set(arr)];
|
|
@@ -11263,6 +11295,7 @@ class FactExtractor {
|
|
|
11263
11295
|
this.deletedFacts = dedup([...this.deletedFacts, ...finalDeleted].filter((p) => !finalFiles.includes(p))).slice(-FactExtractor.MAX_FACTS);
|
|
11264
11296
|
this.decisionFacts = dedup([...this.decisionFacts, ...newDecisions]).slice(-FactExtractor.MAX_FACTS);
|
|
11265
11297
|
this.errorFacts = dedup([...this.errorFacts, ...newErrors]).slice(-FactExtractor.MAX_FACTS);
|
|
11298
|
+
this.readFacts = dedup([...this.readFacts, ...newReads]).slice(-FactExtractor.MAX_FACTS);
|
|
11266
11299
|
}
|
|
11267
11300
|
filesLine() {
|
|
11268
11301
|
const deletedSet = new Set(this.deletedFacts);
|
|
@@ -11286,6 +11319,11 @@ class FactExtractor {
|
|
|
11286
11319
|
return null;
|
|
11287
11320
|
return `[Errors: ${this.errorFacts.slice(-3).join("; ")}]`;
|
|
11288
11321
|
}
|
|
11322
|
+
readLine() {
|
|
11323
|
+
if (this.readFacts.length === 0)
|
|
11324
|
+
return null;
|
|
11325
|
+
return `[Read: ${this.readFacts.slice(-12).join("; ")}]`;
|
|
11326
|
+
}
|
|
11289
11327
|
}
|
|
11290
11328
|
var init_fact_extractor = () => {};
|
|
11291
11329
|
|
|
@@ -11358,12 +11396,16 @@ class ContextManager {
|
|
|
11358
11396
|
pendingImageParts = [];
|
|
11359
11397
|
toolTokens = 0;
|
|
11360
11398
|
onCompact = null;
|
|
11399
|
+
planSummaryProvider = null;
|
|
11361
11400
|
constructor(contextWindow, contextBudget, tokenCounter) {
|
|
11362
11401
|
this.contextWindow = contextWindow;
|
|
11363
11402
|
this.compactionThreshold = contextBudget?.compactionThreshold ?? 0.75;
|
|
11364
11403
|
this.budget = this.calculateBudget(contextWindow, contextBudget);
|
|
11365
11404
|
this.tokenCounter = tokenCounter ?? null;
|
|
11366
11405
|
}
|
|
11406
|
+
setPlanSummaryProvider(fn) {
|
|
11407
|
+
this.planSummaryProvider = fn;
|
|
11408
|
+
}
|
|
11367
11409
|
calculateBudget(window, contextBudget) {
|
|
11368
11410
|
if (contextBudget) {
|
|
11369
11411
|
const systemPrompt = Math.floor(window * contextBudget.systemPrompt);
|
|
@@ -11516,12 +11558,18 @@ class ContextManager {
|
|
|
11516
11558
|
if (this.lastUserFeedback && !task.startsWith(this.lastUserFeedback)) {
|
|
11517
11559
|
parts.push(`[User feedback: ${this.lastUserFeedback}]`);
|
|
11518
11560
|
}
|
|
11561
|
+
const planLine = this.planSummaryProvider?.();
|
|
11562
|
+
if (planLine)
|
|
11563
|
+
parts.push(`[Plan: ${planLine}]`);
|
|
11519
11564
|
const filesLine = this.facts.filesLine();
|
|
11520
11565
|
if (filesLine)
|
|
11521
11566
|
parts.push(filesLine);
|
|
11522
11567
|
const deletedLine = this.facts.deletedLine();
|
|
11523
11568
|
if (deletedLine)
|
|
11524
11569
|
parts.push(deletedLine);
|
|
11570
|
+
const readLine = this.facts.readLine();
|
|
11571
|
+
if (readLine)
|
|
11572
|
+
parts.push(readLine);
|
|
11525
11573
|
const decisionsLine = this.facts.decisionsLine();
|
|
11526
11574
|
if (decisionsLine)
|
|
11527
11575
|
parts.push(decisionsLine);
|
|
@@ -14372,6 +14420,13 @@ var init_recall = __esm(() => {
|
|
|
14372
14420
|
};
|
|
14373
14421
|
});
|
|
14374
14422
|
|
|
14423
|
+
// src/modules/browser/bridge-path.ts
|
|
14424
|
+
import { existsSync as existsSync25 } from "fs";
|
|
14425
|
+
function pickExistingPath(candidates, fallback = candidates[0]) {
|
|
14426
|
+
return candidates.find((p) => existsSync25(p)) ?? fallback;
|
|
14427
|
+
}
|
|
14428
|
+
var init_bridge_path = () => {};
|
|
14429
|
+
|
|
14375
14430
|
// src/modules/browser/bridge-client.ts
|
|
14376
14431
|
var exports_bridge_client = {};
|
|
14377
14432
|
__export(exports_bridge_client, {
|
|
@@ -14382,7 +14437,12 @@ import { createInterface } from "readline";
|
|
|
14382
14437
|
import { dirname as dirname9, join as join18 } from "path";
|
|
14383
14438
|
import { fileURLToPath } from "url";
|
|
14384
14439
|
function bridgeScriptPath() {
|
|
14385
|
-
|
|
14440
|
+
const dir = dirname9(fileURLToPath(import.meta.url));
|
|
14441
|
+
const candidates = [
|
|
14442
|
+
join18(dir, "bridge-server.mjs"),
|
|
14443
|
+
join18(dir, "modules", "browser", "bridge-server.mjs")
|
|
14444
|
+
];
|
|
14445
|
+
return pickExistingPath(candidates);
|
|
14386
14446
|
}
|
|
14387
14447
|
|
|
14388
14448
|
class BridgeDriver {
|
|
@@ -14560,6 +14620,7 @@ class BridgeDriver {
|
|
|
14560
14620
|
var BRIDGE_REQUEST_TIMEOUT_MS = 30000;
|
|
14561
14621
|
var init_bridge_client = __esm(() => {
|
|
14562
14622
|
init_session();
|
|
14623
|
+
init_bridge_path();
|
|
14563
14624
|
});
|
|
14564
14625
|
|
|
14565
14626
|
// src/modules/browser/driver.ts
|
|
@@ -15520,7 +15581,7 @@ var init_image_utils = __esm(() => {
|
|
|
15520
15581
|
});
|
|
15521
15582
|
|
|
15522
15583
|
// src/tools/attach-image.ts
|
|
15523
|
-
import { existsSync as
|
|
15584
|
+
import { existsSync as existsSync26 } from "fs";
|
|
15524
15585
|
import { resolve as resolve15 } from "path";
|
|
15525
15586
|
var attachImageTool;
|
|
15526
15587
|
var init_attach_image = __esm(() => {
|
|
@@ -15563,7 +15624,7 @@ var init_attach_image = __esm(() => {
|
|
|
15563
15624
|
dataUrl = result.dataUrl;
|
|
15564
15625
|
} else {
|
|
15565
15626
|
const absPath = resolve15(ctx.baseDir, source);
|
|
15566
|
-
if (!
|
|
15627
|
+
if (!existsSync26(absPath)) {
|
|
15567
15628
|
return {
|
|
15568
15629
|
success: false,
|
|
15569
15630
|
output: t("image.not_found", { path: source })
|
|
@@ -15725,40 +15786,59 @@ class ModuleRegistry {
|
|
|
15725
15786
|
}
|
|
15726
15787
|
|
|
15727
15788
|
// src/modules/plugins/loader.ts
|
|
15728
|
-
import { readdirSync as readdirSync7, existsSync as
|
|
15729
|
-
import { join as join21 } from "path";
|
|
15789
|
+
import { readdirSync as readdirSync7, existsSync as existsSync27, statSync as statSync5 } from "fs";
|
|
15790
|
+
import { join as join21, basename as basename2 } from "path";
|
|
15730
15791
|
|
|
15731
15792
|
class PluginLoader {
|
|
15732
15793
|
loadFromDir(dirPath, pluginManager, logger) {
|
|
15733
|
-
if (!
|
|
15794
|
+
if (!existsSync27(dirPath))
|
|
15734
15795
|
return;
|
|
15735
|
-
const entries = readdirSync7(dirPath);
|
|
15796
|
+
const entries = readdirSync7(dirPath).sort();
|
|
15736
15797
|
for (const entry of entries) {
|
|
15737
15798
|
const fullPath = join21(dirPath, entry);
|
|
15738
|
-
|
|
15739
|
-
|
|
15740
|
-
|
|
15741
|
-
|
|
15742
|
-
|
|
15743
|
-
|
|
15744
|
-
const
|
|
15745
|
-
if (
|
|
15746
|
-
|
|
15747
|
-
logger?.warn(t("plugin.loaded", { name: plugin.name }));
|
|
15799
|
+
const stat = statSync5(fullPath);
|
|
15800
|
+
if (stat.isFile()) {
|
|
15801
|
+
if (!entry.endsWith(".ts") && !entry.endsWith(".js"))
|
|
15802
|
+
continue;
|
|
15803
|
+
this.tryLoad(fullPath, entry, pluginManager, logger);
|
|
15804
|
+
} else if (stat.isDirectory()) {
|
|
15805
|
+
const entryFile = this.findEntryFile(fullPath);
|
|
15806
|
+
if (entryFile) {
|
|
15807
|
+
this.tryLoad(entryFile, `${entry}/${basename2(entryFile)}`, pluginManager, logger);
|
|
15748
15808
|
}
|
|
15749
|
-
} catch (e) {
|
|
15750
|
-
logger?.warn(t("plugin.skipped", { entry, message: e.message }));
|
|
15751
15809
|
}
|
|
15752
15810
|
}
|
|
15753
15811
|
}
|
|
15812
|
+
findEntryFile(dir) {
|
|
15813
|
+
for (const name of FOLDER_ENTRY_NAMES) {
|
|
15814
|
+
const candidate = join21(dir, name);
|
|
15815
|
+
if (existsSync27(candidate))
|
|
15816
|
+
return candidate;
|
|
15817
|
+
}
|
|
15818
|
+
return null;
|
|
15819
|
+
}
|
|
15820
|
+
tryLoad(fullPath, label, pluginManager, logger) {
|
|
15821
|
+
try {
|
|
15822
|
+
const mod = __require(fullPath);
|
|
15823
|
+
const plugin = mod.default || mod.plugin;
|
|
15824
|
+
if (plugin && plugin.name) {
|
|
15825
|
+
pluginManager.register(plugin);
|
|
15826
|
+
logger?.warn(t("plugin.loaded", { name: plugin.name }));
|
|
15827
|
+
}
|
|
15828
|
+
} catch (e) {
|
|
15829
|
+
logger?.warn(t("plugin.skipped", { entry: label, message: e.message }));
|
|
15830
|
+
}
|
|
15831
|
+
}
|
|
15754
15832
|
}
|
|
15833
|
+
var FOLDER_ENTRY_NAMES;
|
|
15755
15834
|
var init_loader = __esm(() => {
|
|
15756
15835
|
init_i18n();
|
|
15836
|
+
FOLDER_ENTRY_NAMES = ["plugin.ts", "plugin.js", "index.ts", "index.js"];
|
|
15757
15837
|
});
|
|
15758
15838
|
|
|
15759
15839
|
// src/modules/plugins/builtin/lint-on-write.ts
|
|
15760
15840
|
import { spawn as spawn5, execSync } from "child_process";
|
|
15761
|
-
import { existsSync as
|
|
15841
|
+
import { existsSync as existsSync28, readFileSync as readFileSync15 } from "fs";
|
|
15762
15842
|
import { resolve as resolve16, extname as extname4, join as join22 } from "path";
|
|
15763
15843
|
import { platform as platform3 } from "os";
|
|
15764
15844
|
function contentHash(content) {
|
|
@@ -15805,7 +15885,7 @@ class LintOnWritePlugin {
|
|
|
15805
15885
|
if (!path)
|
|
15806
15886
|
return;
|
|
15807
15887
|
const fullPath = resolve16(ctx.baseDir, path);
|
|
15808
|
-
if (!
|
|
15888
|
+
if (!existsSync28(fullPath))
|
|
15809
15889
|
return;
|
|
15810
15890
|
const ext = extname4(fullPath);
|
|
15811
15891
|
const syntaxError = await this.checkSyntax(fullPath, ext, ctx.baseDir);
|
|
@@ -15862,7 +15942,7 @@ class LintOnWritePlugin {
|
|
|
15862
15942
|
async runProjectLint(ctx, result) {
|
|
15863
15943
|
try {
|
|
15864
15944
|
const packageJsonPath = join22(ctx.baseDir, "package.json");
|
|
15865
|
-
if (!
|
|
15945
|
+
if (!existsSync28(packageJsonPath)) {
|
|
15866
15946
|
return;
|
|
15867
15947
|
}
|
|
15868
15948
|
const packageJson = JSON.parse(readFileSync15(packageJsonPath, "utf-8"));
|
|
@@ -15886,7 +15966,7 @@ class LintOnWritePlugin {
|
|
|
15886
15966
|
"package.json"
|
|
15887
15967
|
]);
|
|
15888
15968
|
const tsconfigPath = join22(projectRoot, "tsconfig.json");
|
|
15889
|
-
if (!
|
|
15969
|
+
if (!existsSync28(tsconfigPath)) {
|
|
15890
15970
|
return;
|
|
15891
15971
|
}
|
|
15892
15972
|
const now = Date.now();
|
|
@@ -16134,7 +16214,7 @@ class PlanTracker {
|
|
|
16134
16214
|
var init_tracker = () => {};
|
|
16135
16215
|
|
|
16136
16216
|
// src/modules/execution/audit-runners.ts
|
|
16137
|
-
import { existsSync as
|
|
16217
|
+
import { existsSync as existsSync29, readdirSync as readdirSync8 } from "fs";
|
|
16138
16218
|
import { dirname as dirname10, join as join23, resolve as resolve17 } from "path";
|
|
16139
16219
|
function findTestFile(dir, depth = 0) {
|
|
16140
16220
|
if (depth > 5)
|
|
@@ -16221,7 +16301,7 @@ function findTypecheckRoot(baseDir, existingFiles = []) {
|
|
|
16221
16301
|
for (const start of candidates) {
|
|
16222
16302
|
let dir = resolve17(start);
|
|
16223
16303
|
for (let depth = 0;depth <= 10; depth++) {
|
|
16224
|
-
if (
|
|
16304
|
+
if (existsSync29(join23(dir, "tsconfig.json"))) {
|
|
16225
16305
|
if (!best || depth < best.depth)
|
|
16226
16306
|
best = { depth, root: dir };
|
|
16227
16307
|
break;
|
|
@@ -16264,13 +16344,13 @@ var init_audit_runners = __esm(() => {
|
|
|
16264
16344
|
});
|
|
16265
16345
|
|
|
16266
16346
|
// src/modules/execution/auditor.ts
|
|
16267
|
-
import { existsSync as
|
|
16268
|
-
import { resolve as resolve18, join as join24, basename as
|
|
16347
|
+
import { existsSync as existsSync30, readdirSync as readdirSync9 } from "fs";
|
|
16348
|
+
import { resolve as resolve18, join as join24, basename as basename3 } from "path";
|
|
16269
16349
|
function findExistingFile(baseDir, filePath) {
|
|
16270
16350
|
const direct = resolve18(baseDir, filePath);
|
|
16271
|
-
if (
|
|
16351
|
+
if (existsSync30(direct))
|
|
16272
16352
|
return direct;
|
|
16273
|
-
const name =
|
|
16353
|
+
const name = basename3(filePath).toLowerCase();
|
|
16274
16354
|
const suffix = filePath.replace(/\\/g, "/").toLowerCase();
|
|
16275
16355
|
let found = null;
|
|
16276
16356
|
const walk = (dir, depth) => {
|
|
@@ -16423,7 +16503,7 @@ var init_auditor = __esm(() => {
|
|
|
16423
16503
|
});
|
|
16424
16504
|
|
|
16425
16505
|
// src/modules/execution/plan-store.ts
|
|
16426
|
-
import { readFileSync as readFileSync16, writeFileSync as writeFileSync10, mkdirSync as mkdirSync14, existsSync as
|
|
16506
|
+
import { readFileSync as readFileSync16, writeFileSync as writeFileSync10, mkdirSync as mkdirSync14, existsSync as existsSync31, readdirSync as readdirSync10, rmSync } from "fs";
|
|
16427
16507
|
import { join as join25 } from "path";
|
|
16428
16508
|
function readPlanFile(path, fallbackBaseDir) {
|
|
16429
16509
|
try {
|
|
@@ -16449,7 +16529,7 @@ function writePlanFile(path, plan) {
|
|
|
16449
16529
|
writeFileSync10(path, JSON.stringify(plan, null, 2), "utf-8");
|
|
16450
16530
|
}
|
|
16451
16531
|
function listDir(dir, baseDir) {
|
|
16452
|
-
if (!
|
|
16532
|
+
if (!existsSync31(dir))
|
|
16453
16533
|
return [];
|
|
16454
16534
|
const files = readdirSync10(dir).filter((f) => f.endsWith(".json"));
|
|
16455
16535
|
return files.map((f) => readPlanFile(join25(dir, f), baseDir)).filter((p) => p !== null);
|
|
@@ -16474,7 +16554,7 @@ class PlanStore {
|
|
|
16474
16554
|
legacyPath;
|
|
16475
16555
|
constructor(baseDir) {
|
|
16476
16556
|
const mmaDir = join25(baseDir, ".mma");
|
|
16477
|
-
if (!
|
|
16557
|
+
if (!existsSync31(mmaDir))
|
|
16478
16558
|
mkdirSync14(mmaDir, { recursive: true });
|
|
16479
16559
|
this.baseDir = baseDir;
|
|
16480
16560
|
this.plansDir = join25(mmaDir, "plans");
|
|
@@ -16482,7 +16562,7 @@ class PlanStore {
|
|
|
16482
16562
|
this.archiveDir = join25(this.plansDir, "archive");
|
|
16483
16563
|
this.legacyPath = join25(mmaDir, LEGACY_FILE);
|
|
16484
16564
|
for (const dir of [this.plansDir, this.draftsDir, this.archiveDir]) {
|
|
16485
|
-
if (!
|
|
16565
|
+
if (!existsSync31(dir))
|
|
16486
16566
|
mkdirSync14(dir, { recursive: true });
|
|
16487
16567
|
}
|
|
16488
16568
|
}
|
|
@@ -16494,12 +16574,12 @@ class PlanStore {
|
|
|
16494
16574
|
}
|
|
16495
16575
|
loadActive() {
|
|
16496
16576
|
const activePath = this.activePath();
|
|
16497
|
-
if (
|
|
16577
|
+
if (existsSync31(activePath)) {
|
|
16498
16578
|
const plan = readPlanFile(activePath, this.baseDir);
|
|
16499
16579
|
if (plan)
|
|
16500
16580
|
return plan;
|
|
16501
16581
|
}
|
|
16502
|
-
if (
|
|
16582
|
+
if (existsSync31(this.legacyPath)) {
|
|
16503
16583
|
const legacy = readPlanFile(this.legacyPath, this.baseDir);
|
|
16504
16584
|
if (legacy) {
|
|
16505
16585
|
this.saveActive(legacy);
|
|
@@ -16513,7 +16593,7 @@ class PlanStore {
|
|
|
16513
16593
|
}
|
|
16514
16594
|
clearActive() {
|
|
16515
16595
|
const p = this.activePath();
|
|
16516
|
-
if (
|
|
16596
|
+
if (existsSync31(p))
|
|
16517
16597
|
rmSync(p, { force: true });
|
|
16518
16598
|
}
|
|
16519
16599
|
saveDraft(plan) {
|
|
@@ -16521,11 +16601,11 @@ class PlanStore {
|
|
|
16521
16601
|
}
|
|
16522
16602
|
loadDraft(id) {
|
|
16523
16603
|
const p = join25(this.draftsDir, `${id}.json`);
|
|
16524
|
-
return
|
|
16604
|
+
return existsSync31(p) ? readPlanFile(p, this.baseDir) : null;
|
|
16525
16605
|
}
|
|
16526
16606
|
removeDraft(id) {
|
|
16527
16607
|
const p = join25(this.draftsDir, `${id}.json`);
|
|
16528
|
-
if (
|
|
16608
|
+
if (existsSync31(p))
|
|
16529
16609
|
rmSync(p, { force: true });
|
|
16530
16610
|
}
|
|
16531
16611
|
listDrafts() {
|
|
@@ -16544,7 +16624,7 @@ class PlanStore {
|
|
|
16544
16624
|
}
|
|
16545
16625
|
removeArchived(id) {
|
|
16546
16626
|
const p = join25(this.archiveDir, `${id}.json`);
|
|
16547
|
-
if (
|
|
16627
|
+
if (existsSync31(p))
|
|
16548
16628
|
rmSync(p, { force: true });
|
|
16549
16629
|
}
|
|
16550
16630
|
listAll() {
|
|
@@ -16594,7 +16674,7 @@ function extractFilePaths(text) {
|
|
|
16594
16674
|
}
|
|
16595
16675
|
return result;
|
|
16596
16676
|
}
|
|
16597
|
-
function
|
|
16677
|
+
function basename4(p) {
|
|
16598
16678
|
const parts = p.split(/[/\\]/);
|
|
16599
16679
|
return parts[parts.length - 1] ?? p;
|
|
16600
16680
|
}
|
|
@@ -16606,7 +16686,7 @@ function checkPlanCoverage(taskText, stepDescriptions) {
|
|
|
16606
16686
|
`);
|
|
16607
16687
|
const missing = taskPaths.filter((p) => {
|
|
16608
16688
|
const lower = p.toLowerCase();
|
|
16609
|
-
const base =
|
|
16689
|
+
const base = basename4(lower);
|
|
16610
16690
|
return !stepText.includes(lower) && !stepText.includes(base);
|
|
16611
16691
|
});
|
|
16612
16692
|
return { missing };
|
|
@@ -16771,6 +16851,23 @@ ${lines.join(`
|
|
|
16771
16851
|
if (parsed.error) {
|
|
16772
16852
|
return { success: false, output: parsed.error };
|
|
16773
16853
|
}
|
|
16854
|
+
const existing = deps.trackerRef.current;
|
|
16855
|
+
if (existing) {
|
|
16856
|
+
const activePlan = existing.getPlan();
|
|
16857
|
+
const progressed = activePlan.steps.some((s) => s.status === "done" || s.status === "failed" || s.status === "skipped");
|
|
16858
|
+
if (progressed) {
|
|
16859
|
+
const done = activePlan.steps.filter((s) => s.status === "done").length;
|
|
16860
|
+
return {
|
|
16861
|
+
success: false,
|
|
16862
|
+
output: t("plan.active_in_progress", {
|
|
16863
|
+
id: activePlan.id,
|
|
16864
|
+
done: String(done),
|
|
16865
|
+
total: String(activePlan.steps.length),
|
|
16866
|
+
current: String(existing.getCurrentStepIndex() + 1)
|
|
16867
|
+
})
|
|
16868
|
+
};
|
|
16869
|
+
}
|
|
16870
|
+
}
|
|
16774
16871
|
deps.preserveActive();
|
|
16775
16872
|
const plan = PlanCreator.createPlan(title, steps, deps.baseDir, parsed.kinds ?? []);
|
|
16776
16873
|
deps.setPlan(plan);
|
|
@@ -16779,6 +16876,14 @@ ${lines.join(`
|
|
|
16779
16876
|
title,
|
|
16780
16877
|
steps: String(steps.length)
|
|
16781
16878
|
});
|
|
16879
|
+
if (args.id) {
|
|
16880
|
+
output += `
|
|
16881
|
+
${t("plan.id_ignored")}`;
|
|
16882
|
+
}
|
|
16883
|
+
if (existing) {
|
|
16884
|
+
output += `
|
|
16885
|
+
${t("plan.existing_fresh")}`;
|
|
16886
|
+
}
|
|
16782
16887
|
let displayOut = display;
|
|
16783
16888
|
const taskText = deps.getTaskText(_ctx);
|
|
16784
16889
|
if (taskText) {
|
|
@@ -17321,7 +17426,7 @@ var init_execution_plugin = __esm(() => {
|
|
|
17321
17426
|
});
|
|
17322
17427
|
|
|
17323
17428
|
// src/modules/execution/module.ts
|
|
17324
|
-
import { existsSync as
|
|
17429
|
+
import { existsSync as existsSync32, readFileSync as readFileSync17 } from "fs";
|
|
17325
17430
|
import { resolve as resolve19 } from "path";
|
|
17326
17431
|
|
|
17327
17432
|
class ExecutionModule {
|
|
@@ -17414,6 +17519,14 @@ class ExecutionModule {
|
|
|
17414
17519
|
estimatedTokens: 200
|
|
17415
17520
|
};
|
|
17416
17521
|
}
|
|
17522
|
+
getPlanSummary() {
|
|
17523
|
+
if (!this.tracker)
|
|
17524
|
+
return null;
|
|
17525
|
+
const plan = this.tracker.getPlan();
|
|
17526
|
+
const done = plan.steps.filter((s) => s.status === "done").length;
|
|
17527
|
+
const current = this.tracker.getCurrentStepIndex() + 1;
|
|
17528
|
+
return `[${plan.id}] "${plan.title}" ${done}/${plan.steps.length} done, current: step ${current} — continue it (plan show / re-plan), do NOT create a new plan`;
|
|
17529
|
+
}
|
|
17417
17530
|
getToolDefinitions() {
|
|
17418
17531
|
return createPlanToolDefinitions({
|
|
17419
17532
|
store: this.store,
|
|
@@ -17516,7 +17629,7 @@ class ExecutionModule {
|
|
|
17516
17629
|
"poetry.lock",
|
|
17517
17630
|
"requirements.txt"
|
|
17518
17631
|
];
|
|
17519
|
-
const hasLockFile = lockFiles.some((f) =>
|
|
17632
|
+
const hasLockFile = lockFiles.some((f) => existsSync32(resolve19(this.baseDir, f)));
|
|
17520
17633
|
if (!hasLockFile) {
|
|
17521
17634
|
if (contextManager) {
|
|
17522
17635
|
const hints = this.state.depsGateHints.get(step.id) || 0;
|
|
@@ -17536,8 +17649,8 @@ class ExecutionModule {
|
|
|
17536
17649
|
}
|
|
17537
17650
|
if (stepPaths.length === 0)
|
|
17538
17651
|
return;
|
|
17539
|
-
const allExist = stepPaths.every((p) =>
|
|
17540
|
-
const allGone = stepPaths.every((p) => !
|
|
17652
|
+
const allExist = stepPaths.every((p) => existsSync32(resolve19(this.baseDir, p)));
|
|
17653
|
+
const allGone = stepPaths.every((p) => !existsSync32(resolve19(this.baseDir, p)));
|
|
17541
17654
|
const satisfied = step.kind === "delete" ? allGone && !allExist : allExist;
|
|
17542
17655
|
if (!satisfied)
|
|
17543
17656
|
return;
|
|
@@ -17643,7 +17756,7 @@ var init_module = __esm(() => {
|
|
|
17643
17756
|
import {
|
|
17644
17757
|
readFileSync as readFileSync18,
|
|
17645
17758
|
writeFileSync as writeFileSync11,
|
|
17646
|
-
existsSync as
|
|
17759
|
+
existsSync as existsSync33,
|
|
17647
17760
|
readdirSync as readdirSync11,
|
|
17648
17761
|
unlinkSync as unlinkSync4
|
|
17649
17762
|
} from "fs";
|
|
@@ -17743,7 +17856,7 @@ class SessionFileEncryptor {
|
|
|
17743
17856
|
const files = readdirSync11(sessionDir);
|
|
17744
17857
|
for (const file of files) {
|
|
17745
17858
|
const filePath = join26(sessionDir, file);
|
|
17746
|
-
if (
|
|
17859
|
+
if (existsSync33(filePath) && !file.endsWith(".enc")) {
|
|
17747
17860
|
try {
|
|
17748
17861
|
const content = readFileSync18(filePath, "utf8");
|
|
17749
17862
|
const encrypted = this.encryptFileContent(content);
|
|
@@ -17784,7 +17897,7 @@ var init_session_encryption = __esm(() => {
|
|
|
17784
17897
|
|
|
17785
17898
|
// src/modules/session/store.ts
|
|
17786
17899
|
import {
|
|
17787
|
-
existsSync as
|
|
17900
|
+
existsSync as existsSync34,
|
|
17788
17901
|
mkdirSync as mkdirSync15,
|
|
17789
17902
|
readdirSync as readdirSync12,
|
|
17790
17903
|
readFileSync as readFileSync19,
|
|
@@ -17834,7 +17947,7 @@ class SessionStore {
|
|
|
17834
17947
|
return join27(this.sessionDir(id), "session.jsonl");
|
|
17835
17948
|
}
|
|
17836
17949
|
sessionExists(id) {
|
|
17837
|
-
return
|
|
17950
|
+
return existsSync34(this.metaPath(id));
|
|
17838
17951
|
}
|
|
17839
17952
|
saveMeta(id, meta) {
|
|
17840
17953
|
this._metaCache.set(id, meta);
|
|
@@ -17852,7 +17965,7 @@ class SessionStore {
|
|
|
17852
17965
|
if (cached)
|
|
17853
17966
|
return cached;
|
|
17854
17967
|
const path = this.metaPath(id);
|
|
17855
|
-
if (!
|
|
17968
|
+
if (!existsSync34(path))
|
|
17856
17969
|
return null;
|
|
17857
17970
|
try {
|
|
17858
17971
|
const raw = readFileSync19(path, "utf-8");
|
|
@@ -17884,7 +17997,7 @@ class SessionStore {
|
|
|
17884
17997
|
}
|
|
17885
17998
|
loadHistory(id) {
|
|
17886
17999
|
const path = this.historyPath(id);
|
|
17887
|
-
if (!
|
|
18000
|
+
if (!existsSync34(path))
|
|
17888
18001
|
return [];
|
|
17889
18002
|
try {
|
|
17890
18003
|
const raw = readFileSync19(path, "utf-8");
|
|
@@ -17925,7 +18038,7 @@ class SessionStore {
|
|
|
17925
18038
|
}
|
|
17926
18039
|
loadSessionLog(id) {
|
|
17927
18040
|
const path = this.sessionLogPath(id);
|
|
17928
|
-
if (!
|
|
18041
|
+
if (!existsSync34(path))
|
|
17929
18042
|
return [];
|
|
17930
18043
|
try {
|
|
17931
18044
|
const raw = readFileSync19(path, "utf-8");
|
|
@@ -17953,7 +18066,7 @@ class SessionStore {
|
|
|
17953
18066
|
}
|
|
17954
18067
|
}
|
|
17955
18068
|
listSessions() {
|
|
17956
|
-
if (!
|
|
18069
|
+
if (!existsSync34(this.baseDir))
|
|
17957
18070
|
return [];
|
|
17958
18071
|
const entries = readdirSync12(this.baseDir, { withFileTypes: true });
|
|
17959
18072
|
const sessions = [];
|
|
@@ -17970,7 +18083,7 @@ class SessionStore {
|
|
|
17970
18083
|
deleteSession(id) {
|
|
17971
18084
|
this._metaCache.delete(id);
|
|
17972
18085
|
const dir = this.sessionDir(id);
|
|
17973
|
-
if (
|
|
18086
|
+
if (existsSync34(dir)) {
|
|
17974
18087
|
rmSync2(dir, { recursive: true, force: true });
|
|
17975
18088
|
}
|
|
17976
18089
|
}
|
|
@@ -17982,7 +18095,7 @@ class SessionStore {
|
|
|
17982
18095
|
const updatedAt = new Date(session2.updatedAt);
|
|
17983
18096
|
if (updatedAt < thirtyDaysAgo) {
|
|
17984
18097
|
const historyPath = this.historyPath(session2.id);
|
|
17985
|
-
if (
|
|
18098
|
+
if (existsSync34(historyPath)) {
|
|
17986
18099
|
const content = readFileSync19(historyPath, "utf-8");
|
|
17987
18100
|
const compressed = gzipSync(content);
|
|
17988
18101
|
const gzPath = join27(this.baseDir, `${session2.id}.jsonl.gz`);
|
|
@@ -18195,7 +18308,7 @@ class ProfileCompressor {
|
|
|
18195
18308
|
}
|
|
18196
18309
|
|
|
18197
18310
|
// src/modules/user-profile/profile.ts
|
|
18198
|
-
import { readFileSync as readFileSync20, writeFileSync as writeFileSync13, existsSync as
|
|
18311
|
+
import { readFileSync as readFileSync20, writeFileSync as writeFileSync13, existsSync as existsSync35, mkdirSync as mkdirSync16 } from "fs";
|
|
18199
18312
|
import { join as join28 } from "path";
|
|
18200
18313
|
import { homedir as homedir9, hostname, platform as platform5, type } from "os";
|
|
18201
18314
|
import { env } from "process";
|
|
@@ -18220,14 +18333,14 @@ class UserProfile {
|
|
|
18220
18333
|
return this.info;
|
|
18221
18334
|
}
|
|
18222
18335
|
save() {
|
|
18223
|
-
if (!
|
|
18336
|
+
if (!existsSync35(this.profileDir)) {
|
|
18224
18337
|
mkdirSync16(this.profileDir, { recursive: true });
|
|
18225
18338
|
}
|
|
18226
18339
|
writeFileSync13(join28(this.profileDir, "profile.json"), JSON.stringify({ ...this.info, preferences: this.preferences }, null, 2), "utf-8");
|
|
18227
18340
|
}
|
|
18228
18341
|
load() {
|
|
18229
18342
|
const path = join28(this.profileDir, "profile.json");
|
|
18230
|
-
if (!
|
|
18343
|
+
if (!existsSync35(path))
|
|
18231
18344
|
return null;
|
|
18232
18345
|
try {
|
|
18233
18346
|
const data = JSON.parse(readFileSync20(path, "utf-8"));
|
|
@@ -18265,12 +18378,12 @@ class UserProfile {
|
|
|
18265
18378
|
var init_profile = () => {};
|
|
18266
18379
|
|
|
18267
18380
|
// src/modules/skills/loader.ts
|
|
18268
|
-
import { readdirSync as readdirSync13, readFileSync as readFileSync21, existsSync as
|
|
18381
|
+
import { readdirSync as readdirSync13, readFileSync as readFileSync21, existsSync as existsSync36, statSync as statSync6 } from "fs";
|
|
18269
18382
|
import { join as join29 } from "path";
|
|
18270
18383
|
|
|
18271
18384
|
class SkillsLoader {
|
|
18272
18385
|
loadFromDir(dirPath) {
|
|
18273
|
-
if (!
|
|
18386
|
+
if (!existsSync36(dirPath))
|
|
18274
18387
|
return [];
|
|
18275
18388
|
const skills = [];
|
|
18276
18389
|
this.scanDir(dirPath, skills);
|
|
@@ -18524,7 +18637,7 @@ var init_browser2 = __esm(() => {
|
|
|
18524
18637
|
|
|
18525
18638
|
// src/modules/lsp/command.ts
|
|
18526
18639
|
import { delimiter, join as join30 } from "path";
|
|
18527
|
-
import { existsSync as
|
|
18640
|
+
import { existsSync as existsSync37 } from "fs";
|
|
18528
18641
|
import { platform as platform6 } from "os";
|
|
18529
18642
|
function resolveSpawnCommand(command, platformName = platform6(), pathEnv = process.env.PATH ?? "") {
|
|
18530
18643
|
if (platformName !== "win32")
|
|
@@ -18536,7 +18649,7 @@ function resolveSpawnCommand(command, platformName = platform6(), pathEnv = proc
|
|
|
18536
18649
|
for (const dir of dirs) {
|
|
18537
18650
|
for (const ext of WIN_EXTS) {
|
|
18538
18651
|
const candidate = join30(dir, `${command}${ext}`);
|
|
18539
|
-
if (
|
|
18652
|
+
if (existsSync37(candidate))
|
|
18540
18653
|
return `${command}${ext}`;
|
|
18541
18654
|
}
|
|
18542
18655
|
}
|
|
@@ -18804,18 +18917,70 @@ var init_client2 = __esm(() => {
|
|
|
18804
18917
|
init_command();
|
|
18805
18918
|
});
|
|
18806
18919
|
|
|
18920
|
+
// src/modules/lsp/check-tool.ts
|
|
18921
|
+
import { readdir, stat } from "fs/promises";
|
|
18922
|
+
import { resolve as resolve21, relative as relative2 } from "path";
|
|
18923
|
+
async function collectCheckFiles(resolved, config) {
|
|
18924
|
+
const info = await stat(resolved).catch(() => null);
|
|
18925
|
+
if (!info)
|
|
18926
|
+
return [];
|
|
18927
|
+
if (info.isFile())
|
|
18928
|
+
return [resolved];
|
|
18929
|
+
const out = [];
|
|
18930
|
+
await walkDir(resolved, 0, out, config);
|
|
18931
|
+
return out;
|
|
18932
|
+
}
|
|
18933
|
+
async function walkDir(dir, depth, out, config) {
|
|
18934
|
+
if (depth > MAX_LSP_WALK_DEPTH || out.length >= MAX_LSP_CHECK_FILES)
|
|
18935
|
+
return;
|
|
18936
|
+
const entries = await readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
18937
|
+
for (const entry of entries) {
|
|
18938
|
+
if (out.length >= MAX_LSP_CHECK_FILES)
|
|
18939
|
+
break;
|
|
18940
|
+
if (entry.isDirectory()) {
|
|
18941
|
+
if (SKIP_DIRS2.has(entry.name))
|
|
18942
|
+
continue;
|
|
18943
|
+
await walkDir(resolve21(dir, entry.name), depth + 1, out, config);
|
|
18944
|
+
} else if (entry.isFile() && getServerForFile(resolve21(dir, entry.name), config)) {
|
|
18945
|
+
out.push(resolve21(dir, entry.name));
|
|
18946
|
+
}
|
|
18947
|
+
}
|
|
18948
|
+
}
|
|
18949
|
+
function formatCheckDiagnostics(items, baseDir) {
|
|
18950
|
+
return items.slice(0, 40).map(({ file, diag }) => {
|
|
18951
|
+
const rel = relative2(baseDir, file).replace(/\\/g, "/");
|
|
18952
|
+
const line = diag.range.start.line + 1;
|
|
18953
|
+
const col = diag.range.start.character + 1;
|
|
18954
|
+
const sev = severityLabels[diag.severity] ?? "unknown";
|
|
18955
|
+
return ` ${rel}(${line},${col}): ${sev}: ${diag.message}`;
|
|
18956
|
+
}).join(`
|
|
18957
|
+
`);
|
|
18958
|
+
}
|
|
18959
|
+
var MAX_LSP_CHECK_FILES = 15, MAX_LSP_WALK_DEPTH = 4, SKIP_DIRS2, severityLabels;
|
|
18960
|
+
var init_check_tool = __esm(() => {
|
|
18961
|
+
init_config();
|
|
18962
|
+
SKIP_DIRS2 = new Set(["node_modules", ".git", ".mma", "dist"]);
|
|
18963
|
+
severityLabels = {
|
|
18964
|
+
1: "error",
|
|
18965
|
+
2: "warning",
|
|
18966
|
+
3: "info",
|
|
18967
|
+
4: "hint"
|
|
18968
|
+
};
|
|
18969
|
+
});
|
|
18970
|
+
|
|
18807
18971
|
// src/modules/lsp/module.ts
|
|
18808
|
-
import { existsSync as
|
|
18809
|
-
import { resolve as
|
|
18972
|
+
import { existsSync as existsSync38 } from "fs";
|
|
18973
|
+
import { resolve as resolve22 } from "path";
|
|
18810
18974
|
|
|
18811
18975
|
class LspModule {
|
|
18812
18976
|
name = "lsp";
|
|
18813
18977
|
config;
|
|
18814
|
-
client
|
|
18978
|
+
client;
|
|
18815
18979
|
failuresByServer = new Map;
|
|
18816
18980
|
disabledServers = new Set;
|
|
18817
|
-
constructor(config) {
|
|
18981
|
+
constructor(config, client) {
|
|
18818
18982
|
this.config = { ...DEFAULT_LSP_CONFIG, ...config };
|
|
18983
|
+
this.client = client ?? new LspClient;
|
|
18819
18984
|
}
|
|
18820
18985
|
isLspDisabled() {
|
|
18821
18986
|
return this.disabledServers.size > 0;
|
|
@@ -18841,8 +19006,8 @@ class LspModule {
|
|
|
18841
19006
|
const filePath = String(call.arguments.path ?? "");
|
|
18842
19007
|
if (!filePath)
|
|
18843
19008
|
return;
|
|
18844
|
-
const fullPath =
|
|
18845
|
-
if (!
|
|
19009
|
+
const fullPath = resolve22(_ctx.baseDir, filePath);
|
|
19010
|
+
if (!existsSync38(fullPath))
|
|
18846
19011
|
return;
|
|
18847
19012
|
const serverConfig = getServerForFile(fullPath, self.config);
|
|
18848
19013
|
if (!serverConfig)
|
|
@@ -18891,6 +19056,110 @@ ${items}`;
|
|
|
18891
19056
|
}
|
|
18892
19057
|
};
|
|
18893
19058
|
}
|
|
19059
|
+
getToolDefinitions() {
|
|
19060
|
+
const self = this;
|
|
19061
|
+
return [
|
|
19062
|
+
{
|
|
19063
|
+
name: "lsp_check",
|
|
19064
|
+
description: 'Run static checks (LSP diagnostics) on a file or directory. For "check for errors" tasks: pass a file to check it, or a directory to check its source files (capped at 15). Returns [LSP errors] / [LSP warnings] for files with a configured LSP server.',
|
|
19065
|
+
tags: ["code", "check"],
|
|
19066
|
+
boundedOutput: true,
|
|
19067
|
+
timeoutMs: 90000,
|
|
19068
|
+
parameters: {
|
|
19069
|
+
type: "object",
|
|
19070
|
+
properties: {
|
|
19071
|
+
path: {
|
|
19072
|
+
type: "string",
|
|
19073
|
+
description: "File or directory to check"
|
|
19074
|
+
}
|
|
19075
|
+
},
|
|
19076
|
+
required: ["path"]
|
|
19077
|
+
},
|
|
19078
|
+
handler: async (ctx, args) => self.runCheck(ctx, args)
|
|
19079
|
+
}
|
|
19080
|
+
];
|
|
19081
|
+
}
|
|
19082
|
+
async runCheck(ctx, args) {
|
|
19083
|
+
if (!this.config.enabled) {
|
|
19084
|
+
return { success: false, output: t("lsp.check_disabled") };
|
|
19085
|
+
}
|
|
19086
|
+
const path = String(args.path ?? "");
|
|
19087
|
+
if (!path)
|
|
19088
|
+
return { success: false, output: t("lsp.check_no_path") };
|
|
19089
|
+
const resolved = safeResolvePath(ctx.baseDir, path);
|
|
19090
|
+
const securityPaths = ctx.config?.security?.paths || DEFAULT_SECURITY_CONFIG.paths;
|
|
19091
|
+
const scopeCheck = isPathInScope(ctx.baseDir, resolved, ctx.scope, securityPaths);
|
|
19092
|
+
if (!scopeCheck.allowed) {
|
|
19093
|
+
return {
|
|
19094
|
+
success: false,
|
|
19095
|
+
output: t("file.path_not_allowed", {
|
|
19096
|
+
path: `${path} — ${scopeCheck.reason}`
|
|
19097
|
+
})
|
|
19098
|
+
};
|
|
19099
|
+
}
|
|
19100
|
+
if (!existsSync38(resolved)) {
|
|
19101
|
+
return { success: false, output: t("lsp.check_notfound", { path }) };
|
|
19102
|
+
}
|
|
19103
|
+
const files = await collectCheckFiles(resolved, this.config);
|
|
19104
|
+
const errors = [];
|
|
19105
|
+
const warnings = [];
|
|
19106
|
+
const notes = [];
|
|
19107
|
+
let checked = 0;
|
|
19108
|
+
for (const file of files) {
|
|
19109
|
+
const serverConfig = getServerForFile(file, this.config);
|
|
19110
|
+
if (!serverConfig)
|
|
19111
|
+
continue;
|
|
19112
|
+
const key = this.serverKey(serverConfig);
|
|
19113
|
+
if (this.disabledServers.has(key))
|
|
19114
|
+
continue;
|
|
19115
|
+
const projectRoot = findProjectRoot(file, ctx.baseDir, serverConfig.workspaceMarkers ?? []);
|
|
19116
|
+
try {
|
|
19117
|
+
const diags = await this.client.checkFile(file, ctx.baseDir, serverConfig, projectRoot);
|
|
19118
|
+
this.failuresByServer.set(key, 0);
|
|
19119
|
+
checked++;
|
|
19120
|
+
for (const d of diags) {
|
|
19121
|
+
if (d.severity === 1)
|
|
19122
|
+
errors.push({ file, diag: d });
|
|
19123
|
+
else if (d.severity === 2)
|
|
19124
|
+
warnings.push({ file, diag: d });
|
|
19125
|
+
}
|
|
19126
|
+
} catch (e) {
|
|
19127
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
19128
|
+
const failures = (this.failuresByServer.get(key) ?? 0) + 1;
|
|
19129
|
+
this.failuresByServer.set(key, failures);
|
|
19130
|
+
try {
|
|
19131
|
+
ctx.logger?.warn(`LSP check failed for ${file}: ${msg}`);
|
|
19132
|
+
} catch {}
|
|
19133
|
+
if (failures >= MAX_CONSECUTIVE_LSP_FAILURES) {
|
|
19134
|
+
this.disabledServers.add(key);
|
|
19135
|
+
notes.push(`[LSP disabled: ${t("lsp.unavailable")}]`);
|
|
19136
|
+
} else {
|
|
19137
|
+
notes.push(`[LSP check failed for ${file}: ${msg}]`);
|
|
19138
|
+
}
|
|
19139
|
+
}
|
|
19140
|
+
}
|
|
19141
|
+
const lines = [];
|
|
19142
|
+
if (errors.length > 0) {
|
|
19143
|
+
lines.push(`[LSP errors] (${errors.length}):`);
|
|
19144
|
+
lines.push(formatCheckDiagnostics(errors, ctx.baseDir));
|
|
19145
|
+
}
|
|
19146
|
+
if (warnings.length > 0) {
|
|
19147
|
+
lines.push(`[LSP warnings] (${warnings.length}):`);
|
|
19148
|
+
lines.push(formatCheckDiagnostics(warnings, ctx.baseDir));
|
|
19149
|
+
}
|
|
19150
|
+
if (checked > 0 && errors.length === 0 && warnings.length === 0) {
|
|
19151
|
+
lines.push(t("lsp.check_clean", { count: String(checked) }));
|
|
19152
|
+
}
|
|
19153
|
+
lines.push(...notes);
|
|
19154
|
+
if (lines.length === 0) {
|
|
19155
|
+
return {
|
|
19156
|
+
success: true,
|
|
19157
|
+
output: t("lsp.check_clean", { count: String(checked) })
|
|
19158
|
+
};
|
|
19159
|
+
}
|
|
19160
|
+
return { success: errors.length === 0, output: lines.join(`
|
|
19161
|
+
`) };
|
|
19162
|
+
}
|
|
18894
19163
|
}
|
|
18895
19164
|
function formatDiagnostics(diagnostics, filePath) {
|
|
18896
19165
|
const filename = filePath.replace(/\\/g, "/").split("/").pop() ?? filePath;
|
|
@@ -18902,18 +19171,16 @@ function formatDiagnostics(diagnostics, filePath) {
|
|
|
18902
19171
|
}).join(`
|
|
18903
19172
|
`);
|
|
18904
19173
|
}
|
|
18905
|
-
var
|
|
19174
|
+
var MAX_CONSECUTIVE_LSP_FAILURES = 3;
|
|
18906
19175
|
var init_module5 = __esm(() => {
|
|
18907
19176
|
init_client2();
|
|
18908
19177
|
init_config();
|
|
18909
19178
|
init_project_root();
|
|
19179
|
+
init_path_validator();
|
|
19180
|
+
init_security();
|
|
19181
|
+
init_path_utils();
|
|
18910
19182
|
init_i18n();
|
|
18911
|
-
|
|
18912
|
-
1: "error",
|
|
18913
|
-
2: "warning",
|
|
18914
|
-
3: "info",
|
|
18915
|
-
4: "hint"
|
|
18916
|
-
};
|
|
19183
|
+
init_check_tool();
|
|
18917
19184
|
});
|
|
18918
19185
|
|
|
18919
19186
|
// src/modules/lsp/index.ts
|
|
@@ -18924,8 +19191,8 @@ var init_lsp = __esm(() => {
|
|
|
18924
19191
|
});
|
|
18925
19192
|
|
|
18926
19193
|
// src/modules/indexer/walker.ts
|
|
18927
|
-
import { readdirSync as readdirSync14, readFileSync as readFileSync22, statSync as statSync7, existsSync as
|
|
18928
|
-
import { join as join31, relative as
|
|
19194
|
+
import { readdirSync as readdirSync14, readFileSync as readFileSync22, statSync as statSync7, existsSync as existsSync39, watch } from "fs";
|
|
19195
|
+
import { join as join31, relative as relative3, extname as extname5 } from "path";
|
|
18929
19196
|
|
|
18930
19197
|
class Indexer {
|
|
18931
19198
|
baseDir;
|
|
@@ -18951,8 +19218,8 @@ class Indexer {
|
|
|
18951
19218
|
const files = [];
|
|
18952
19219
|
let totalSize = 0;
|
|
18953
19220
|
let count = 0;
|
|
18954
|
-
const
|
|
18955
|
-
if (!
|
|
19221
|
+
const walkDir2 = (dir) => {
|
|
19222
|
+
if (!existsSync39(dir))
|
|
18956
19223
|
return;
|
|
18957
19224
|
let entries;
|
|
18958
19225
|
try {
|
|
@@ -18964,26 +19231,26 @@ class Indexer {
|
|
|
18964
19231
|
if (count >= this.MAX_FILES)
|
|
18965
19232
|
return;
|
|
18966
19233
|
const fullPath = join31(dir, entry);
|
|
18967
|
-
const relPath =
|
|
18968
|
-
const
|
|
18969
|
-
if (
|
|
19234
|
+
const relPath = relative3(this.baseDir, fullPath);
|
|
19235
|
+
const stat2 = statSync7(fullPath);
|
|
19236
|
+
if (stat2.isDirectory()) {
|
|
18970
19237
|
if (!IGNORE_DIRS.has(entry)) {
|
|
18971
|
-
|
|
19238
|
+
walkDir2(fullPath);
|
|
18972
19239
|
}
|
|
18973
|
-
} else if (
|
|
19240
|
+
} else if (stat2.isFile()) {
|
|
18974
19241
|
const ext = extname5(entry).toLowerCase();
|
|
18975
19242
|
const language = LANGUAGES[ext];
|
|
18976
19243
|
if (language) {
|
|
18977
19244
|
const content = readFileSync22(fullPath, "utf-8");
|
|
18978
19245
|
const exports = this.extractExports(content, language);
|
|
18979
|
-
files.push({ path: relPath, language, exports, size:
|
|
18980
|
-
totalSize +=
|
|
19246
|
+
files.push({ path: relPath, language, exports, size: stat2.size });
|
|
19247
|
+
totalSize += stat2.size;
|
|
18981
19248
|
count++;
|
|
18982
19249
|
}
|
|
18983
19250
|
}
|
|
18984
19251
|
}
|
|
18985
19252
|
};
|
|
18986
|
-
|
|
19253
|
+
walkDir2(this.baseDir);
|
|
18987
19254
|
return { files, totalSize };
|
|
18988
19255
|
}
|
|
18989
19256
|
extractExports(content, language) {
|
|
@@ -19026,7 +19293,7 @@ var init_walker = __esm(() => {
|
|
|
19026
19293
|
});
|
|
19027
19294
|
|
|
19028
19295
|
// src/modules/indexer/cache.ts
|
|
19029
|
-
import { readFileSync as readFileSync23, writeFileSync as writeFileSync14, existsSync as
|
|
19296
|
+
import { readFileSync as readFileSync23, writeFileSync as writeFileSync14, existsSync as existsSync40, mkdirSync as mkdirSync17, rmSync as rmSync3 } from "fs";
|
|
19030
19297
|
import { join as join32 } from "path";
|
|
19031
19298
|
|
|
19032
19299
|
class IndexCache {
|
|
@@ -19038,7 +19305,7 @@ class IndexCache {
|
|
|
19038
19305
|
load() {
|
|
19039
19306
|
if (this.cache)
|
|
19040
19307
|
return this.cache;
|
|
19041
|
-
if (!
|
|
19308
|
+
if (!existsSync40(this.cachePath))
|
|
19042
19309
|
return null;
|
|
19043
19310
|
try {
|
|
19044
19311
|
this.cache = JSON.parse(readFileSync23(this.cachePath, "utf-8"));
|
|
@@ -19050,13 +19317,13 @@ class IndexCache {
|
|
|
19050
19317
|
save(result) {
|
|
19051
19318
|
this.cache = result;
|
|
19052
19319
|
const dir = join32(this.cachePath, "..");
|
|
19053
|
-
if (!
|
|
19320
|
+
if (!existsSync40(dir))
|
|
19054
19321
|
mkdirSync17(dir, { recursive: true });
|
|
19055
19322
|
writeFileSync14(this.cachePath, JSON.stringify(result), "utf-8");
|
|
19056
19323
|
}
|
|
19057
19324
|
invalidate() {
|
|
19058
19325
|
this.cache = null;
|
|
19059
|
-
if (
|
|
19326
|
+
if (existsSync40(this.cachePath)) {
|
|
19060
19327
|
try {
|
|
19061
19328
|
rmSync3(this.cachePath);
|
|
19062
19329
|
} catch {}
|
|
@@ -19066,11 +19333,11 @@ class IndexCache {
|
|
|
19066
19333
|
var init_cache = () => {};
|
|
19067
19334
|
|
|
19068
19335
|
// src/modules/indexer/project-profile.ts
|
|
19069
|
-
import { readFileSync as readFileSync24, existsSync as
|
|
19336
|
+
import { readFileSync as readFileSync24, existsSync as existsSync41 } from "fs";
|
|
19070
19337
|
import { join as join33 } from "path";
|
|
19071
19338
|
function detectManifest(baseDir) {
|
|
19072
19339
|
for (const manifest of MANIFEST_ORDER) {
|
|
19073
|
-
if (
|
|
19340
|
+
if (existsSync41(join33(baseDir, manifest)))
|
|
19074
19341
|
return manifest;
|
|
19075
19342
|
}
|
|
19076
19343
|
return null;
|
|
@@ -19724,8 +19991,8 @@ __export(exports_bootstrap, {
|
|
|
19724
19991
|
bootstrap: () => bootstrap
|
|
19725
19992
|
});
|
|
19726
19993
|
import { homedir as homedir11 } from "os";
|
|
19727
|
-
import { join as join35, resolve as
|
|
19728
|
-
import { existsSync as
|
|
19994
|
+
import { join as join35, resolve as resolve23 } from "path";
|
|
19995
|
+
import { existsSync as existsSync42, readFileSync as readFileSync25, writeFileSync as writeFileSync15 } from "fs";
|
|
19729
19996
|
function buildSystemInfo(config, baseDir, profileCompressed) {
|
|
19730
19997
|
const now = new Date().toISOString().replace("T", " ").slice(0, 19);
|
|
19731
19998
|
const isWin = profileCompressed.toLowerCase().includes("win32");
|
|
@@ -19738,7 +20005,7 @@ function buildSystemInfo(config, baseDir, profileCompressed) {
|
|
|
19738
20005
|
lines.push(`Windows (PowerShell): use list_dir/read_file/delete_file/create_dir tools instead of dir/type/del/mkdir. No PowerShell cmdlets (Get-Content, Select-Object, Write-Output), no head/tail/grep/cat. Use forward slashes in paths. CWD: ${baseDir}`);
|
|
19739
20006
|
}
|
|
19740
20007
|
lines.push(`Runtime: Bun is available — run TypeScript directly with "bun <file.ts>" and tests with "bun test" (no tsx/ts-node/npm install needed for that).`);
|
|
19741
|
-
lines.push(`Bash: use "workdir" param instead of "cd dir && cmd". One command per call. Long-running processes: pass "background: true" (id immediately), otherwise auto-backgrounded after a few seconds — check with process_log.`, `DEVELOPMENT RULES (strict): 1) install deps BEFORE writing source (npm/pip/cargo, verify lockfile exists; never import uninstalled packages); 2) framework/toolkit init BEFORE app code; 3) follow plan sequentially, after each step verify deliverables exist with real content, then "plan update step=N status=done"; 4) verify work on disk + command output — don't assume success; 5) no premature work (no files/imports for future steps); 6) stuck after 2+ failures: STOP, try a different approach, write files directly, ask the user.`, `PLAN QUALITY: each step = CONCRETE deliverables (exact file paths with extensions, exact packages, exact commands). Vague steps ("Setup the project") forbidden. Cover init → deps → framework → code → verification. 5-8 steps.`);
|
|
20008
|
+
lines.push(`Bash: use "workdir" param instead of "cd dir && cmd". One command per call. Long-running processes: pass "background: true" (id immediately), otherwise auto-backgrounded after a few seconds — check with process_log.`, `DEVELOPMENT RULES (strict): 1) install deps BEFORE writing source (npm/pip/cargo, verify lockfile exists; never import uninstalled packages); 2) framework/toolkit init BEFORE app code; 3) follow plan sequentially, after each step verify deliverables exist with real content, then "plan update step=N status=done"; 4) verify work on disk + command output — don't assume success; 5) no premature work (no files/imports for future steps); 6) stuck after 2+ failures: STOP, try a different approach, write files directly, ask the user.`, `PLAN QUALITY: each step = CONCRETE deliverables (exact file paths with extensions, exact packages, exact commands). Vague steps ("Setup the project") forbidden. Cover init → deps → framework → code → verification. 5-8 steps.`, `For "check/fix errors" tasks, each verification step must name the exact command that proves the errors are gone — "bun run build", "bun test", or the "lsp_check" tool — and the step is done only after that check reports clean.`);
|
|
19742
20009
|
if (config.autoPlan) {
|
|
19743
20010
|
lines.push(`Plan rule (MANDATORY): any task creating files, installing packages, or requiring multiple actions MUST create a plan with the "plan" tool BEFORE starting. Each step = a concrete deliverable.`);
|
|
19744
20011
|
}
|
|
@@ -19795,7 +20062,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
19795
20062
|
retry: config.retry,
|
|
19796
20063
|
rateLimits: config.security?.rateLimits
|
|
19797
20064
|
});
|
|
19798
|
-
const baseDir = projectDir ?
|
|
20065
|
+
const baseDir = projectDir ? resolve23(projectDir) : process.cwd();
|
|
19799
20066
|
const projectMapCacheDir = join35(baseDir, ".mma");
|
|
19800
20067
|
const indexerModule = new IndexerModule({
|
|
19801
20068
|
baseDir,
|
|
@@ -19824,7 +20091,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
19824
20091
|
estimatedTokens: Math.ceil(systemInfoContent.length / 4)
|
|
19825
20092
|
};
|
|
19826
20093
|
const agentsMdGlobal = join35(dir, "AGENTS.md");
|
|
19827
|
-
if (!
|
|
20094
|
+
if (!existsSync42(agentsMdGlobal)) {
|
|
19828
20095
|
writeFileSync15(agentsMdGlobal, "", "utf-8");
|
|
19829
20096
|
}
|
|
19830
20097
|
const sessionDir = join35(dir, "sessions");
|
|
@@ -19960,6 +20227,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
19960
20227
|
timestamp: new Date().toISOString()
|
|
19961
20228
|
});
|
|
19962
20229
|
};
|
|
20230
|
+
contextManager.setPlanSummaryProvider(() => execModule.getPlanSummary());
|
|
19963
20231
|
const agentsMdBlocks = [];
|
|
19964
20232
|
const skipAgentsMd = noAgentsMd === true;
|
|
19965
20233
|
if (!skipAgentsMd) {
|
|
@@ -19969,7 +20237,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
19969
20237
|
join35(dir, "AGENTS.md")
|
|
19970
20238
|
];
|
|
19971
20239
|
for (const p of agentsMdCandidates) {
|
|
19972
|
-
if (
|
|
20240
|
+
if (existsSync42(p)) {
|
|
19973
20241
|
const content = readFileSync25(p, "utf-8").trim();
|
|
19974
20242
|
if (content) {
|
|
19975
20243
|
agentsMdBlocks.push({
|
|
@@ -20602,10 +20870,10 @@ function menuList(items) {
|
|
|
20602
20870
|
console.log(l);
|
|
20603
20871
|
}
|
|
20604
20872
|
function ask(rl, question, defaultValue) {
|
|
20605
|
-
return new Promise((
|
|
20873
|
+
return new Promise((resolve24) => {
|
|
20606
20874
|
const prompt = defaultValue ? `${question} [${defaultValue}]: ` : `${question}: `;
|
|
20607
20875
|
rl.question(prompt, (answer) => {
|
|
20608
|
-
|
|
20876
|
+
resolve24(answer.trim() || defaultValue || "");
|
|
20609
20877
|
});
|
|
20610
20878
|
});
|
|
20611
20879
|
}
|
|
@@ -20824,12 +21092,12 @@ __export(exports_manifest, {
|
|
|
20824
21092
|
getCertMark: () => getCertMark,
|
|
20825
21093
|
MANIFEST_PATH: () => MANIFEST_PATH
|
|
20826
21094
|
});
|
|
20827
|
-
import { existsSync as
|
|
21095
|
+
import { existsSync as existsSync43, readFileSync as readFileSync26, mkdirSync as mkdirSync18, writeFileSync as writeFileSync16 } from "fs";
|
|
20828
21096
|
import { homedir as homedir13 } from "os";
|
|
20829
21097
|
import { join as join37 } from "path";
|
|
20830
21098
|
function readManifest(path = MANIFEST_PATH) {
|
|
20831
21099
|
try {
|
|
20832
|
-
if (
|
|
21100
|
+
if (existsSync43(path)) {
|
|
20833
21101
|
const raw = JSON.parse(readFileSync26(path, "utf-8"));
|
|
20834
21102
|
return { version: 1, certifications: raw.certifications ?? [] };
|
|
20835
21103
|
}
|
|
@@ -27995,7 +28263,7 @@ var init_scenarios = __esm(() => {
|
|
|
27995
28263
|
});
|
|
27996
28264
|
|
|
27997
28265
|
// src/modules/certification/loader.ts
|
|
27998
|
-
import { existsSync as
|
|
28266
|
+
import { existsSync as existsSync44, readdirSync as readdirSync15, readFileSync as readFileSync27 } from "fs";
|
|
27999
28267
|
import { join as join38 } from "path";
|
|
28000
28268
|
function validateScenario(s) {
|
|
28001
28269
|
const errors2 = [];
|
|
@@ -28045,7 +28313,7 @@ function loadScenarios(userDir) {
|
|
|
28045
28313
|
else
|
|
28046
28314
|
scenarios.push(s);
|
|
28047
28315
|
}
|
|
28048
|
-
if (userDir &&
|
|
28316
|
+
if (userDir && existsSync44(userDir)) {
|
|
28049
28317
|
for (const file of readdirSync15(userDir)) {
|
|
28050
28318
|
if (!file.endsWith(".yaml") && !file.endsWith(".yml"))
|
|
28051
28319
|
continue;
|
|
@@ -28103,7 +28371,7 @@ var init_loader3 = __esm(() => {
|
|
|
28103
28371
|
});
|
|
28104
28372
|
|
|
28105
28373
|
// src/modules/certification/fact-checker.ts
|
|
28106
|
-
import { existsSync as
|
|
28374
|
+
import { existsSync as existsSync45, readFileSync as readFileSync28, statSync as statSync8 } from "fs";
|
|
28107
28375
|
import { join as join39 } from "path";
|
|
28108
28376
|
function checkSandbox(sandboxDir, checks, exitCode, output) {
|
|
28109
28377
|
const failures = [];
|
|
@@ -28123,7 +28391,7 @@ function runCheck(sandboxDir, check, exitCode, output) {
|
|
|
28123
28391
|
case "fileExists":
|
|
28124
28392
|
return isFile(join39(sandboxDir, check.path));
|
|
28125
28393
|
case "fileNotExists":
|
|
28126
|
-
return !
|
|
28394
|
+
return !existsSync45(join39(sandboxDir, check.path));
|
|
28127
28395
|
case "dirExists":
|
|
28128
28396
|
return isDir(join39(sandboxDir, check.path));
|
|
28129
28397
|
case "fileContent": {
|
|
@@ -28149,14 +28417,14 @@ function runCheck(sandboxDir, check, exitCode, output) {
|
|
|
28149
28417
|
}
|
|
28150
28418
|
function isFile(p) {
|
|
28151
28419
|
try {
|
|
28152
|
-
return
|
|
28420
|
+
return existsSync45(p) && statSync8(p).isFile();
|
|
28153
28421
|
} catch {
|
|
28154
28422
|
return false;
|
|
28155
28423
|
}
|
|
28156
28424
|
}
|
|
28157
28425
|
function isDir(p) {
|
|
28158
28426
|
try {
|
|
28159
|
-
return
|
|
28427
|
+
return existsSync45(p) && statSync8(p).isDirectory();
|
|
28160
28428
|
} catch {
|
|
28161
28429
|
return false;
|
|
28162
28430
|
}
|
|
@@ -28187,9 +28455,9 @@ var init_fact_checker = () => {};
|
|
|
28187
28455
|
|
|
28188
28456
|
// src/modules/certification/runner.ts
|
|
28189
28457
|
import { spawn as spawn7 } from "child_process";
|
|
28190
|
-
import { existsSync as
|
|
28458
|
+
import { existsSync as existsSync46, mkdirSync as mkdirSync19, rmSync as rmSync4, cpSync as cpSync2 } from "fs";
|
|
28191
28459
|
import { platform as platform8 } from "os";
|
|
28192
|
-
import { join as join40, resolve as
|
|
28460
|
+
import { join as join40, resolve as resolve24, dirname as dirname13 } from "path";
|
|
28193
28461
|
async function runScenario(scenario, opts) {
|
|
28194
28462
|
if (scenario.mode === "skip") {
|
|
28195
28463
|
return {
|
|
@@ -28270,7 +28538,7 @@ function prepareSandbox(sandbox, scenario, mmaRoot) {
|
|
|
28270
28538
|
mkdirSync19(sandbox, { recursive: true });
|
|
28271
28539
|
for (const f of scenario.fixtures ?? []) {
|
|
28272
28540
|
const src = join40(mmaRoot, f.source);
|
|
28273
|
-
if (!
|
|
28541
|
+
if (!existsSync46(src)) {
|
|
28274
28542
|
throw new Error(`fixture missing: ${f.source}`);
|
|
28275
28543
|
}
|
|
28276
28544
|
const dest = join40(sandbox, f.dest);
|
|
@@ -28280,17 +28548,17 @@ function prepareSandbox(sandbox, scenario, mmaRoot) {
|
|
|
28280
28548
|
}
|
|
28281
28549
|
function resolveMmaEntry(mmaRoot) {
|
|
28282
28550
|
const dev = join40(mmaRoot, "src", "cli", "main.ts");
|
|
28283
|
-
if (
|
|
28551
|
+
if (existsSync46(dev))
|
|
28284
28552
|
return dev;
|
|
28285
28553
|
return join40(mmaRoot, "dist", "main.js");
|
|
28286
28554
|
}
|
|
28287
28555
|
function findMmaRoot(fromDir) {
|
|
28288
28556
|
const candidates = [
|
|
28289
|
-
|
|
28290
|
-
|
|
28557
|
+
resolve24(fromDir, "..", "..", ".."),
|
|
28558
|
+
resolve24(fromDir, "..")
|
|
28291
28559
|
];
|
|
28292
28560
|
for (const c of candidates) {
|
|
28293
|
-
if (
|
|
28561
|
+
if (existsSync46(join40(c, "package.json")))
|
|
28294
28562
|
return c;
|
|
28295
28563
|
}
|
|
28296
28564
|
return process.cwd();
|
|
@@ -28360,11 +28628,11 @@ import { rmSync as rmSync5 } from "fs";
|
|
|
28360
28628
|
import { homedir as homedir14 } from "os";
|
|
28361
28629
|
import { join as join41, dirname as dirname14 } from "path";
|
|
28362
28630
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
28363
|
-
import { existsSync as
|
|
28631
|
+
import { existsSync as existsSync47, readFileSync as readFileSync29 } from "fs";
|
|
28364
28632
|
function readVersion() {
|
|
28365
28633
|
const candidates = [join41(MMA_ROOT, "package.json")];
|
|
28366
28634
|
for (const p of candidates) {
|
|
28367
|
-
if (
|
|
28635
|
+
if (existsSync47(p)) {
|
|
28368
28636
|
try {
|
|
28369
28637
|
const raw = JSON.parse(readFileSync29(p, "utf-8"));
|
|
28370
28638
|
if (raw.version)
|
|
@@ -28527,7 +28795,7 @@ __export(exports_repl_commands, {
|
|
|
28527
28795
|
});
|
|
28528
28796
|
import { join as join43, dirname as dirname16 } from "path";
|
|
28529
28797
|
import { homedir as homedir16 } from "os";
|
|
28530
|
-
import { existsSync as
|
|
28798
|
+
import { existsSync as existsSync49, readFileSync as readFileSync31 } from "fs";
|
|
28531
28799
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
28532
28800
|
function readVersion3() {
|
|
28533
28801
|
const here = dirname16(fileURLToPath4(import.meta.url));
|
|
@@ -28536,7 +28804,7 @@ function readVersion3() {
|
|
|
28536
28804
|
join43(here, "..", "package.json")
|
|
28537
28805
|
];
|
|
28538
28806
|
for (const p of candidates) {
|
|
28539
|
-
if (
|
|
28807
|
+
if (existsSync49(p)) {
|
|
28540
28808
|
try {
|
|
28541
28809
|
const raw = JSON.parse(readFileSync31(p, "utf8"));
|
|
28542
28810
|
if (raw.version)
|
|
@@ -28602,8 +28870,8 @@ function registerMmaCommands(ctx) {
|
|
|
28602
28870
|
}
|
|
28603
28871
|
try {
|
|
28604
28872
|
const { loadFileAsDataUrl: loadFileAsDataUrl2, loadUrlAsDataUrl: loadUrlAsDataUrl2, readClipboardImage: readClipboardImage2 } = await Promise.resolve().then(() => (init_image_utils(), exports_image_utils));
|
|
28605
|
-
const { existsSync:
|
|
28606
|
-
const { resolve:
|
|
28873
|
+
const { existsSync: existsSync50 } = await import("fs");
|
|
28874
|
+
const { resolve: resolve25 } = await import("path");
|
|
28607
28875
|
let dataUrl;
|
|
28608
28876
|
let label;
|
|
28609
28877
|
if (source.toLowerCase() === "clipboard") {
|
|
@@ -28621,8 +28889,8 @@ function registerMmaCommands(ctx) {
|
|
|
28621
28889
|
dataUrl = result.dataUrl;
|
|
28622
28890
|
label = source;
|
|
28623
28891
|
} else {
|
|
28624
|
-
const absPath =
|
|
28625
|
-
if (!
|
|
28892
|
+
const absPath = resolve25(process.cwd(), source);
|
|
28893
|
+
if (!existsSync50(absPath)) {
|
|
28626
28894
|
console.log(pc2.red(t("image.not_found", { path: source })));
|
|
28627
28895
|
return;
|
|
28628
28896
|
}
|
|
@@ -29160,7 +29428,7 @@ init_setup();
|
|
|
29160
29428
|
init_i18n();
|
|
29161
29429
|
import { join as join42, dirname as dirname15 } from "path";
|
|
29162
29430
|
import { homedir as homedir15 } from "os";
|
|
29163
|
-
import { existsSync as
|
|
29431
|
+
import { existsSync as existsSync48, readFileSync as readFileSync30 } from "fs";
|
|
29164
29432
|
|
|
29165
29433
|
// src/cli/security-commands.ts
|
|
29166
29434
|
init_bootstrap();
|
|
@@ -29788,7 +30056,7 @@ function readVersion2() {
|
|
|
29788
30056
|
join42(here, "..", "package.json")
|
|
29789
30057
|
];
|
|
29790
30058
|
for (const p of candidates) {
|
|
29791
|
-
if (
|
|
30059
|
+
if (existsSync48(p)) {
|
|
29792
30060
|
try {
|
|
29793
30061
|
const raw = JSON.parse(readFileSync30(p, "utf8"));
|
|
29794
30062
|
if (raw.version)
|
|
@@ -30772,7 +31040,7 @@ class LineEditor {
|
|
|
30772
31040
|
}
|
|
30773
31041
|
|
|
30774
31042
|
// src/cli/repl.ts
|
|
30775
|
-
import { existsSync as
|
|
31043
|
+
import { existsSync as existsSync50, readFileSync as readFileSync32, writeFileSync as writeFileSync17 } from "fs";
|
|
30776
31044
|
import { join as join44, dirname as dirname17 } from "path";
|
|
30777
31045
|
import { homedir as homedir17 } from "os";
|
|
30778
31046
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
@@ -31283,7 +31551,7 @@ function readVersion4() {
|
|
|
31283
31551
|
join44(here, "..", "package.json")
|
|
31284
31552
|
];
|
|
31285
31553
|
for (const p of candidates) {
|
|
31286
|
-
if (
|
|
31554
|
+
if (existsSync50(p)) {
|
|
31287
31555
|
try {
|
|
31288
31556
|
const raw = JSON.parse(readFileSync32(p, "utf8"));
|
|
31289
31557
|
if (raw.version)
|
|
@@ -31377,7 +31645,7 @@ class Repl {
|
|
|
31377
31645
|
this.setupListeners();
|
|
31378
31646
|
}
|
|
31379
31647
|
loadHistory() {
|
|
31380
|
-
if (
|
|
31648
|
+
if (existsSync50(this.historyPath)) {
|
|
31381
31649
|
try {
|
|
31382
31650
|
const raw = readFileSync32(this.historyPath, "utf-8");
|
|
31383
31651
|
this.history = raw.split(`
|
|
@@ -31740,7 +32008,7 @@ ${t("image.clipboard_empty")}`));
|
|
|
31740
32008
|
join44(this.baseDir, ".mma", "AGENTS.md"),
|
|
31741
32009
|
join44(this.configDir, "AGENTS.md")
|
|
31742
32010
|
];
|
|
31743
|
-
const foundAgents = agentsMdCandidates.filter((p) =>
|
|
32011
|
+
const foundAgents = agentsMdCandidates.filter((p) => existsSync50(p));
|
|
31744
32012
|
if (foundAgents.length > 0) {
|
|
31745
32013
|
for (const p of foundAgents) {
|
|
31746
32014
|
row(t("repl.agents_label"), pc2.dim(p));
|
|
@@ -31792,7 +32060,7 @@ init_setup();
|
|
|
31792
32060
|
init_config2();
|
|
31793
32061
|
init_i18n();
|
|
31794
32062
|
init_colors();
|
|
31795
|
-
import { existsSync as
|
|
32063
|
+
import { existsSync as existsSync51, readFileSync as readFileSync33 } from "fs";
|
|
31796
32064
|
import { join as join45, dirname as dirname18 } from "path";
|
|
31797
32065
|
import { homedir as homedir18 } from "os";
|
|
31798
32066
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
@@ -31813,8 +32081,8 @@ function semverGt(a, b) {
|
|
|
31813
32081
|
}
|
|
31814
32082
|
var defaultRunner2 = async (command, args, options) => {
|
|
31815
32083
|
const { execFile } = await import("child_process");
|
|
31816
|
-
return new Promise((
|
|
31817
|
-
execFile(command, args, options, (err) =>
|
|
32084
|
+
return new Promise((resolve25) => {
|
|
32085
|
+
execFile(command, args, options, (err) => resolve25({ error: err?.message }));
|
|
31818
32086
|
});
|
|
31819
32087
|
};
|
|
31820
32088
|
|
|
@@ -31979,7 +32247,7 @@ function readVersion5() {
|
|
|
31979
32247
|
join45(here, "..", "package.json")
|
|
31980
32248
|
];
|
|
31981
32249
|
for (const p of candidates) {
|
|
31982
|
-
if (
|
|
32250
|
+
if (existsSync51(p)) {
|
|
31983
32251
|
try {
|
|
31984
32252
|
const raw = JSON.parse(readFileSync33(p, "utf8"));
|
|
31985
32253
|
if (raw.version)
|
|
@@ -32065,7 +32333,7 @@ async function main() {
|
|
|
32065
32333
|
process.exit(exitCode);
|
|
32066
32334
|
} else {
|
|
32067
32335
|
const configPath = join45(homedir18(), ".mma", "config.json");
|
|
32068
|
-
if (!
|
|
32336
|
+
if (!existsSync51(configPath)) {
|
|
32069
32337
|
console.log(pc2.yellow(`
|
|
32070
32338
|
` + t("cli.first_run") + `
|
|
32071
32339
|
`));
|