micro-models-agent 0.37.0 → 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 +371 -122
- 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,12 +15786,12 @@ class ModuleRegistry {
|
|
|
15725
15786
|
}
|
|
15726
15787
|
|
|
15727
15788
|
// src/modules/plugins/loader.ts
|
|
15728
|
-
import { readdirSync as readdirSync7, existsSync as
|
|
15789
|
+
import { readdirSync as readdirSync7, existsSync as existsSync27, statSync as statSync5 } from "fs";
|
|
15729
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
15796
|
const entries = readdirSync7(dirPath).sort();
|
|
15736
15797
|
for (const entry of entries) {
|
|
@@ -15751,7 +15812,7 @@ class PluginLoader {
|
|
|
15751
15812
|
findEntryFile(dir) {
|
|
15752
15813
|
for (const name of FOLDER_ENTRY_NAMES) {
|
|
15753
15814
|
const candidate = join21(dir, name);
|
|
15754
|
-
if (
|
|
15815
|
+
if (existsSync27(candidate))
|
|
15755
15816
|
return candidate;
|
|
15756
15817
|
}
|
|
15757
15818
|
return null;
|
|
@@ -15777,7 +15838,7 @@ var init_loader = __esm(() => {
|
|
|
15777
15838
|
|
|
15778
15839
|
// src/modules/plugins/builtin/lint-on-write.ts
|
|
15779
15840
|
import { spawn as spawn5, execSync } from "child_process";
|
|
15780
|
-
import { existsSync as
|
|
15841
|
+
import { existsSync as existsSync28, readFileSync as readFileSync15 } from "fs";
|
|
15781
15842
|
import { resolve as resolve16, extname as extname4, join as join22 } from "path";
|
|
15782
15843
|
import { platform as platform3 } from "os";
|
|
15783
15844
|
function contentHash(content) {
|
|
@@ -15824,7 +15885,7 @@ class LintOnWritePlugin {
|
|
|
15824
15885
|
if (!path)
|
|
15825
15886
|
return;
|
|
15826
15887
|
const fullPath = resolve16(ctx.baseDir, path);
|
|
15827
|
-
if (!
|
|
15888
|
+
if (!existsSync28(fullPath))
|
|
15828
15889
|
return;
|
|
15829
15890
|
const ext = extname4(fullPath);
|
|
15830
15891
|
const syntaxError = await this.checkSyntax(fullPath, ext, ctx.baseDir);
|
|
@@ -15881,7 +15942,7 @@ class LintOnWritePlugin {
|
|
|
15881
15942
|
async runProjectLint(ctx, result) {
|
|
15882
15943
|
try {
|
|
15883
15944
|
const packageJsonPath = join22(ctx.baseDir, "package.json");
|
|
15884
|
-
if (!
|
|
15945
|
+
if (!existsSync28(packageJsonPath)) {
|
|
15885
15946
|
return;
|
|
15886
15947
|
}
|
|
15887
15948
|
const packageJson = JSON.parse(readFileSync15(packageJsonPath, "utf-8"));
|
|
@@ -15905,7 +15966,7 @@ class LintOnWritePlugin {
|
|
|
15905
15966
|
"package.json"
|
|
15906
15967
|
]);
|
|
15907
15968
|
const tsconfigPath = join22(projectRoot, "tsconfig.json");
|
|
15908
|
-
if (!
|
|
15969
|
+
if (!existsSync28(tsconfigPath)) {
|
|
15909
15970
|
return;
|
|
15910
15971
|
}
|
|
15911
15972
|
const now = Date.now();
|
|
@@ -16153,7 +16214,7 @@ class PlanTracker {
|
|
|
16153
16214
|
var init_tracker = () => {};
|
|
16154
16215
|
|
|
16155
16216
|
// src/modules/execution/audit-runners.ts
|
|
16156
|
-
import { existsSync as
|
|
16217
|
+
import { existsSync as existsSync29, readdirSync as readdirSync8 } from "fs";
|
|
16157
16218
|
import { dirname as dirname10, join as join23, resolve as resolve17 } from "path";
|
|
16158
16219
|
function findTestFile(dir, depth = 0) {
|
|
16159
16220
|
if (depth > 5)
|
|
@@ -16240,7 +16301,7 @@ function findTypecheckRoot(baseDir, existingFiles = []) {
|
|
|
16240
16301
|
for (const start of candidates) {
|
|
16241
16302
|
let dir = resolve17(start);
|
|
16242
16303
|
for (let depth = 0;depth <= 10; depth++) {
|
|
16243
|
-
if (
|
|
16304
|
+
if (existsSync29(join23(dir, "tsconfig.json"))) {
|
|
16244
16305
|
if (!best || depth < best.depth)
|
|
16245
16306
|
best = { depth, root: dir };
|
|
16246
16307
|
break;
|
|
@@ -16283,11 +16344,11 @@ var init_audit_runners = __esm(() => {
|
|
|
16283
16344
|
});
|
|
16284
16345
|
|
|
16285
16346
|
// src/modules/execution/auditor.ts
|
|
16286
|
-
import { existsSync as
|
|
16347
|
+
import { existsSync as existsSync30, readdirSync as readdirSync9 } from "fs";
|
|
16287
16348
|
import { resolve as resolve18, join as join24, basename as basename3 } from "path";
|
|
16288
16349
|
function findExistingFile(baseDir, filePath) {
|
|
16289
16350
|
const direct = resolve18(baseDir, filePath);
|
|
16290
|
-
if (
|
|
16351
|
+
if (existsSync30(direct))
|
|
16291
16352
|
return direct;
|
|
16292
16353
|
const name = basename3(filePath).toLowerCase();
|
|
16293
16354
|
const suffix = filePath.replace(/\\/g, "/").toLowerCase();
|
|
@@ -16442,7 +16503,7 @@ var init_auditor = __esm(() => {
|
|
|
16442
16503
|
});
|
|
16443
16504
|
|
|
16444
16505
|
// src/modules/execution/plan-store.ts
|
|
16445
|
-
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";
|
|
16446
16507
|
import { join as join25 } from "path";
|
|
16447
16508
|
function readPlanFile(path, fallbackBaseDir) {
|
|
16448
16509
|
try {
|
|
@@ -16468,7 +16529,7 @@ function writePlanFile(path, plan) {
|
|
|
16468
16529
|
writeFileSync10(path, JSON.stringify(plan, null, 2), "utf-8");
|
|
16469
16530
|
}
|
|
16470
16531
|
function listDir(dir, baseDir) {
|
|
16471
|
-
if (!
|
|
16532
|
+
if (!existsSync31(dir))
|
|
16472
16533
|
return [];
|
|
16473
16534
|
const files = readdirSync10(dir).filter((f) => f.endsWith(".json"));
|
|
16474
16535
|
return files.map((f) => readPlanFile(join25(dir, f), baseDir)).filter((p) => p !== null);
|
|
@@ -16493,7 +16554,7 @@ class PlanStore {
|
|
|
16493
16554
|
legacyPath;
|
|
16494
16555
|
constructor(baseDir) {
|
|
16495
16556
|
const mmaDir = join25(baseDir, ".mma");
|
|
16496
|
-
if (!
|
|
16557
|
+
if (!existsSync31(mmaDir))
|
|
16497
16558
|
mkdirSync14(mmaDir, { recursive: true });
|
|
16498
16559
|
this.baseDir = baseDir;
|
|
16499
16560
|
this.plansDir = join25(mmaDir, "plans");
|
|
@@ -16501,7 +16562,7 @@ class PlanStore {
|
|
|
16501
16562
|
this.archiveDir = join25(this.plansDir, "archive");
|
|
16502
16563
|
this.legacyPath = join25(mmaDir, LEGACY_FILE);
|
|
16503
16564
|
for (const dir of [this.plansDir, this.draftsDir, this.archiveDir]) {
|
|
16504
|
-
if (!
|
|
16565
|
+
if (!existsSync31(dir))
|
|
16505
16566
|
mkdirSync14(dir, { recursive: true });
|
|
16506
16567
|
}
|
|
16507
16568
|
}
|
|
@@ -16513,12 +16574,12 @@ class PlanStore {
|
|
|
16513
16574
|
}
|
|
16514
16575
|
loadActive() {
|
|
16515
16576
|
const activePath = this.activePath();
|
|
16516
|
-
if (
|
|
16577
|
+
if (existsSync31(activePath)) {
|
|
16517
16578
|
const plan = readPlanFile(activePath, this.baseDir);
|
|
16518
16579
|
if (plan)
|
|
16519
16580
|
return plan;
|
|
16520
16581
|
}
|
|
16521
|
-
if (
|
|
16582
|
+
if (existsSync31(this.legacyPath)) {
|
|
16522
16583
|
const legacy = readPlanFile(this.legacyPath, this.baseDir);
|
|
16523
16584
|
if (legacy) {
|
|
16524
16585
|
this.saveActive(legacy);
|
|
@@ -16532,7 +16593,7 @@ class PlanStore {
|
|
|
16532
16593
|
}
|
|
16533
16594
|
clearActive() {
|
|
16534
16595
|
const p = this.activePath();
|
|
16535
|
-
if (
|
|
16596
|
+
if (existsSync31(p))
|
|
16536
16597
|
rmSync(p, { force: true });
|
|
16537
16598
|
}
|
|
16538
16599
|
saveDraft(plan) {
|
|
@@ -16540,11 +16601,11 @@ class PlanStore {
|
|
|
16540
16601
|
}
|
|
16541
16602
|
loadDraft(id) {
|
|
16542
16603
|
const p = join25(this.draftsDir, `${id}.json`);
|
|
16543
|
-
return
|
|
16604
|
+
return existsSync31(p) ? readPlanFile(p, this.baseDir) : null;
|
|
16544
16605
|
}
|
|
16545
16606
|
removeDraft(id) {
|
|
16546
16607
|
const p = join25(this.draftsDir, `${id}.json`);
|
|
16547
|
-
if (
|
|
16608
|
+
if (existsSync31(p))
|
|
16548
16609
|
rmSync(p, { force: true });
|
|
16549
16610
|
}
|
|
16550
16611
|
listDrafts() {
|
|
@@ -16563,7 +16624,7 @@ class PlanStore {
|
|
|
16563
16624
|
}
|
|
16564
16625
|
removeArchived(id) {
|
|
16565
16626
|
const p = join25(this.archiveDir, `${id}.json`);
|
|
16566
|
-
if (
|
|
16627
|
+
if (existsSync31(p))
|
|
16567
16628
|
rmSync(p, { force: true });
|
|
16568
16629
|
}
|
|
16569
16630
|
listAll() {
|
|
@@ -16790,6 +16851,23 @@ ${lines.join(`
|
|
|
16790
16851
|
if (parsed.error) {
|
|
16791
16852
|
return { success: false, output: parsed.error };
|
|
16792
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
|
+
}
|
|
16793
16871
|
deps.preserveActive();
|
|
16794
16872
|
const plan = PlanCreator.createPlan(title, steps, deps.baseDir, parsed.kinds ?? []);
|
|
16795
16873
|
deps.setPlan(plan);
|
|
@@ -16798,6 +16876,14 @@ ${lines.join(`
|
|
|
16798
16876
|
title,
|
|
16799
16877
|
steps: String(steps.length)
|
|
16800
16878
|
});
|
|
16879
|
+
if (args.id) {
|
|
16880
|
+
output += `
|
|
16881
|
+
${t("plan.id_ignored")}`;
|
|
16882
|
+
}
|
|
16883
|
+
if (existing) {
|
|
16884
|
+
output += `
|
|
16885
|
+
${t("plan.existing_fresh")}`;
|
|
16886
|
+
}
|
|
16801
16887
|
let displayOut = display;
|
|
16802
16888
|
const taskText = deps.getTaskText(_ctx);
|
|
16803
16889
|
if (taskText) {
|
|
@@ -17340,7 +17426,7 @@ var init_execution_plugin = __esm(() => {
|
|
|
17340
17426
|
});
|
|
17341
17427
|
|
|
17342
17428
|
// src/modules/execution/module.ts
|
|
17343
|
-
import { existsSync as
|
|
17429
|
+
import { existsSync as existsSync32, readFileSync as readFileSync17 } from "fs";
|
|
17344
17430
|
import { resolve as resolve19 } from "path";
|
|
17345
17431
|
|
|
17346
17432
|
class ExecutionModule {
|
|
@@ -17433,6 +17519,14 @@ class ExecutionModule {
|
|
|
17433
17519
|
estimatedTokens: 200
|
|
17434
17520
|
};
|
|
17435
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
|
+
}
|
|
17436
17530
|
getToolDefinitions() {
|
|
17437
17531
|
return createPlanToolDefinitions({
|
|
17438
17532
|
store: this.store,
|
|
@@ -17535,7 +17629,7 @@ class ExecutionModule {
|
|
|
17535
17629
|
"poetry.lock",
|
|
17536
17630
|
"requirements.txt"
|
|
17537
17631
|
];
|
|
17538
|
-
const hasLockFile = lockFiles.some((f) =>
|
|
17632
|
+
const hasLockFile = lockFiles.some((f) => existsSync32(resolve19(this.baseDir, f)));
|
|
17539
17633
|
if (!hasLockFile) {
|
|
17540
17634
|
if (contextManager) {
|
|
17541
17635
|
const hints = this.state.depsGateHints.get(step.id) || 0;
|
|
@@ -17555,8 +17649,8 @@ class ExecutionModule {
|
|
|
17555
17649
|
}
|
|
17556
17650
|
if (stepPaths.length === 0)
|
|
17557
17651
|
return;
|
|
17558
|
-
const allExist = stepPaths.every((p) =>
|
|
17559
|
-
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)));
|
|
17560
17654
|
const satisfied = step.kind === "delete" ? allGone && !allExist : allExist;
|
|
17561
17655
|
if (!satisfied)
|
|
17562
17656
|
return;
|
|
@@ -17662,7 +17756,7 @@ var init_module = __esm(() => {
|
|
|
17662
17756
|
import {
|
|
17663
17757
|
readFileSync as readFileSync18,
|
|
17664
17758
|
writeFileSync as writeFileSync11,
|
|
17665
|
-
existsSync as
|
|
17759
|
+
existsSync as existsSync33,
|
|
17666
17760
|
readdirSync as readdirSync11,
|
|
17667
17761
|
unlinkSync as unlinkSync4
|
|
17668
17762
|
} from "fs";
|
|
@@ -17762,7 +17856,7 @@ class SessionFileEncryptor {
|
|
|
17762
17856
|
const files = readdirSync11(sessionDir);
|
|
17763
17857
|
for (const file of files) {
|
|
17764
17858
|
const filePath = join26(sessionDir, file);
|
|
17765
|
-
if (
|
|
17859
|
+
if (existsSync33(filePath) && !file.endsWith(".enc")) {
|
|
17766
17860
|
try {
|
|
17767
17861
|
const content = readFileSync18(filePath, "utf8");
|
|
17768
17862
|
const encrypted = this.encryptFileContent(content);
|
|
@@ -17803,7 +17897,7 @@ var init_session_encryption = __esm(() => {
|
|
|
17803
17897
|
|
|
17804
17898
|
// src/modules/session/store.ts
|
|
17805
17899
|
import {
|
|
17806
|
-
existsSync as
|
|
17900
|
+
existsSync as existsSync34,
|
|
17807
17901
|
mkdirSync as mkdirSync15,
|
|
17808
17902
|
readdirSync as readdirSync12,
|
|
17809
17903
|
readFileSync as readFileSync19,
|
|
@@ -17853,7 +17947,7 @@ class SessionStore {
|
|
|
17853
17947
|
return join27(this.sessionDir(id), "session.jsonl");
|
|
17854
17948
|
}
|
|
17855
17949
|
sessionExists(id) {
|
|
17856
|
-
return
|
|
17950
|
+
return existsSync34(this.metaPath(id));
|
|
17857
17951
|
}
|
|
17858
17952
|
saveMeta(id, meta) {
|
|
17859
17953
|
this._metaCache.set(id, meta);
|
|
@@ -17871,7 +17965,7 @@ class SessionStore {
|
|
|
17871
17965
|
if (cached)
|
|
17872
17966
|
return cached;
|
|
17873
17967
|
const path = this.metaPath(id);
|
|
17874
|
-
if (!
|
|
17968
|
+
if (!existsSync34(path))
|
|
17875
17969
|
return null;
|
|
17876
17970
|
try {
|
|
17877
17971
|
const raw = readFileSync19(path, "utf-8");
|
|
@@ -17903,7 +17997,7 @@ class SessionStore {
|
|
|
17903
17997
|
}
|
|
17904
17998
|
loadHistory(id) {
|
|
17905
17999
|
const path = this.historyPath(id);
|
|
17906
|
-
if (!
|
|
18000
|
+
if (!existsSync34(path))
|
|
17907
18001
|
return [];
|
|
17908
18002
|
try {
|
|
17909
18003
|
const raw = readFileSync19(path, "utf-8");
|
|
@@ -17944,7 +18038,7 @@ class SessionStore {
|
|
|
17944
18038
|
}
|
|
17945
18039
|
loadSessionLog(id) {
|
|
17946
18040
|
const path = this.sessionLogPath(id);
|
|
17947
|
-
if (!
|
|
18041
|
+
if (!existsSync34(path))
|
|
17948
18042
|
return [];
|
|
17949
18043
|
try {
|
|
17950
18044
|
const raw = readFileSync19(path, "utf-8");
|
|
@@ -17972,7 +18066,7 @@ class SessionStore {
|
|
|
17972
18066
|
}
|
|
17973
18067
|
}
|
|
17974
18068
|
listSessions() {
|
|
17975
|
-
if (!
|
|
18069
|
+
if (!existsSync34(this.baseDir))
|
|
17976
18070
|
return [];
|
|
17977
18071
|
const entries = readdirSync12(this.baseDir, { withFileTypes: true });
|
|
17978
18072
|
const sessions = [];
|
|
@@ -17989,7 +18083,7 @@ class SessionStore {
|
|
|
17989
18083
|
deleteSession(id) {
|
|
17990
18084
|
this._metaCache.delete(id);
|
|
17991
18085
|
const dir = this.sessionDir(id);
|
|
17992
|
-
if (
|
|
18086
|
+
if (existsSync34(dir)) {
|
|
17993
18087
|
rmSync2(dir, { recursive: true, force: true });
|
|
17994
18088
|
}
|
|
17995
18089
|
}
|
|
@@ -18001,7 +18095,7 @@ class SessionStore {
|
|
|
18001
18095
|
const updatedAt = new Date(session2.updatedAt);
|
|
18002
18096
|
if (updatedAt < thirtyDaysAgo) {
|
|
18003
18097
|
const historyPath = this.historyPath(session2.id);
|
|
18004
|
-
if (
|
|
18098
|
+
if (existsSync34(historyPath)) {
|
|
18005
18099
|
const content = readFileSync19(historyPath, "utf-8");
|
|
18006
18100
|
const compressed = gzipSync(content);
|
|
18007
18101
|
const gzPath = join27(this.baseDir, `${session2.id}.jsonl.gz`);
|
|
@@ -18214,7 +18308,7 @@ class ProfileCompressor {
|
|
|
18214
18308
|
}
|
|
18215
18309
|
|
|
18216
18310
|
// src/modules/user-profile/profile.ts
|
|
18217
|
-
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";
|
|
18218
18312
|
import { join as join28 } from "path";
|
|
18219
18313
|
import { homedir as homedir9, hostname, platform as platform5, type } from "os";
|
|
18220
18314
|
import { env } from "process";
|
|
@@ -18239,14 +18333,14 @@ class UserProfile {
|
|
|
18239
18333
|
return this.info;
|
|
18240
18334
|
}
|
|
18241
18335
|
save() {
|
|
18242
|
-
if (!
|
|
18336
|
+
if (!existsSync35(this.profileDir)) {
|
|
18243
18337
|
mkdirSync16(this.profileDir, { recursive: true });
|
|
18244
18338
|
}
|
|
18245
18339
|
writeFileSync13(join28(this.profileDir, "profile.json"), JSON.stringify({ ...this.info, preferences: this.preferences }, null, 2), "utf-8");
|
|
18246
18340
|
}
|
|
18247
18341
|
load() {
|
|
18248
18342
|
const path = join28(this.profileDir, "profile.json");
|
|
18249
|
-
if (!
|
|
18343
|
+
if (!existsSync35(path))
|
|
18250
18344
|
return null;
|
|
18251
18345
|
try {
|
|
18252
18346
|
const data = JSON.parse(readFileSync20(path, "utf-8"));
|
|
@@ -18284,12 +18378,12 @@ class UserProfile {
|
|
|
18284
18378
|
var init_profile = () => {};
|
|
18285
18379
|
|
|
18286
18380
|
// src/modules/skills/loader.ts
|
|
18287
|
-
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";
|
|
18288
18382
|
import { join as join29 } from "path";
|
|
18289
18383
|
|
|
18290
18384
|
class SkillsLoader {
|
|
18291
18385
|
loadFromDir(dirPath) {
|
|
18292
|
-
if (!
|
|
18386
|
+
if (!existsSync36(dirPath))
|
|
18293
18387
|
return [];
|
|
18294
18388
|
const skills = [];
|
|
18295
18389
|
this.scanDir(dirPath, skills);
|
|
@@ -18543,7 +18637,7 @@ var init_browser2 = __esm(() => {
|
|
|
18543
18637
|
|
|
18544
18638
|
// src/modules/lsp/command.ts
|
|
18545
18639
|
import { delimiter, join as join30 } from "path";
|
|
18546
|
-
import { existsSync as
|
|
18640
|
+
import { existsSync as existsSync37 } from "fs";
|
|
18547
18641
|
import { platform as platform6 } from "os";
|
|
18548
18642
|
function resolveSpawnCommand(command, platformName = platform6(), pathEnv = process.env.PATH ?? "") {
|
|
18549
18643
|
if (platformName !== "win32")
|
|
@@ -18555,7 +18649,7 @@ function resolveSpawnCommand(command, platformName = platform6(), pathEnv = proc
|
|
|
18555
18649
|
for (const dir of dirs) {
|
|
18556
18650
|
for (const ext of WIN_EXTS) {
|
|
18557
18651
|
const candidate = join30(dir, `${command}${ext}`);
|
|
18558
|
-
if (
|
|
18652
|
+
if (existsSync37(candidate))
|
|
18559
18653
|
return `${command}${ext}`;
|
|
18560
18654
|
}
|
|
18561
18655
|
}
|
|
@@ -18823,18 +18917,70 @@ var init_client2 = __esm(() => {
|
|
|
18823
18917
|
init_command();
|
|
18824
18918
|
});
|
|
18825
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
|
+
|
|
18826
18971
|
// src/modules/lsp/module.ts
|
|
18827
|
-
import { existsSync as
|
|
18828
|
-
import { resolve as
|
|
18972
|
+
import { existsSync as existsSync38 } from "fs";
|
|
18973
|
+
import { resolve as resolve22 } from "path";
|
|
18829
18974
|
|
|
18830
18975
|
class LspModule {
|
|
18831
18976
|
name = "lsp";
|
|
18832
18977
|
config;
|
|
18833
|
-
client
|
|
18978
|
+
client;
|
|
18834
18979
|
failuresByServer = new Map;
|
|
18835
18980
|
disabledServers = new Set;
|
|
18836
|
-
constructor(config) {
|
|
18981
|
+
constructor(config, client) {
|
|
18837
18982
|
this.config = { ...DEFAULT_LSP_CONFIG, ...config };
|
|
18983
|
+
this.client = client ?? new LspClient;
|
|
18838
18984
|
}
|
|
18839
18985
|
isLspDisabled() {
|
|
18840
18986
|
return this.disabledServers.size > 0;
|
|
@@ -18860,8 +19006,8 @@ class LspModule {
|
|
|
18860
19006
|
const filePath = String(call.arguments.path ?? "");
|
|
18861
19007
|
if (!filePath)
|
|
18862
19008
|
return;
|
|
18863
|
-
const fullPath =
|
|
18864
|
-
if (!
|
|
19009
|
+
const fullPath = resolve22(_ctx.baseDir, filePath);
|
|
19010
|
+
if (!existsSync38(fullPath))
|
|
18865
19011
|
return;
|
|
18866
19012
|
const serverConfig = getServerForFile(fullPath, self.config);
|
|
18867
19013
|
if (!serverConfig)
|
|
@@ -18910,6 +19056,110 @@ ${items}`;
|
|
|
18910
19056
|
}
|
|
18911
19057
|
};
|
|
18912
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
|
+
}
|
|
18913
19163
|
}
|
|
18914
19164
|
function formatDiagnostics(diagnostics, filePath) {
|
|
18915
19165
|
const filename = filePath.replace(/\\/g, "/").split("/").pop() ?? filePath;
|
|
@@ -18921,18 +19171,16 @@ function formatDiagnostics(diagnostics, filePath) {
|
|
|
18921
19171
|
}).join(`
|
|
18922
19172
|
`);
|
|
18923
19173
|
}
|
|
18924
|
-
var
|
|
19174
|
+
var MAX_CONSECUTIVE_LSP_FAILURES = 3;
|
|
18925
19175
|
var init_module5 = __esm(() => {
|
|
18926
19176
|
init_client2();
|
|
18927
19177
|
init_config();
|
|
18928
19178
|
init_project_root();
|
|
19179
|
+
init_path_validator();
|
|
19180
|
+
init_security();
|
|
19181
|
+
init_path_utils();
|
|
18929
19182
|
init_i18n();
|
|
18930
|
-
|
|
18931
|
-
1: "error",
|
|
18932
|
-
2: "warning",
|
|
18933
|
-
3: "info",
|
|
18934
|
-
4: "hint"
|
|
18935
|
-
};
|
|
19183
|
+
init_check_tool();
|
|
18936
19184
|
});
|
|
18937
19185
|
|
|
18938
19186
|
// src/modules/lsp/index.ts
|
|
@@ -18943,8 +19191,8 @@ var init_lsp = __esm(() => {
|
|
|
18943
19191
|
});
|
|
18944
19192
|
|
|
18945
19193
|
// src/modules/indexer/walker.ts
|
|
18946
|
-
import { readdirSync as readdirSync14, readFileSync as readFileSync22, statSync as statSync7, existsSync as
|
|
18947
|
-
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";
|
|
18948
19196
|
|
|
18949
19197
|
class Indexer {
|
|
18950
19198
|
baseDir;
|
|
@@ -18970,8 +19218,8 @@ class Indexer {
|
|
|
18970
19218
|
const files = [];
|
|
18971
19219
|
let totalSize = 0;
|
|
18972
19220
|
let count = 0;
|
|
18973
|
-
const
|
|
18974
|
-
if (!
|
|
19221
|
+
const walkDir2 = (dir) => {
|
|
19222
|
+
if (!existsSync39(dir))
|
|
18975
19223
|
return;
|
|
18976
19224
|
let entries;
|
|
18977
19225
|
try {
|
|
@@ -18983,26 +19231,26 @@ class Indexer {
|
|
|
18983
19231
|
if (count >= this.MAX_FILES)
|
|
18984
19232
|
return;
|
|
18985
19233
|
const fullPath = join31(dir, entry);
|
|
18986
|
-
const relPath =
|
|
18987
|
-
const
|
|
18988
|
-
if (
|
|
19234
|
+
const relPath = relative3(this.baseDir, fullPath);
|
|
19235
|
+
const stat2 = statSync7(fullPath);
|
|
19236
|
+
if (stat2.isDirectory()) {
|
|
18989
19237
|
if (!IGNORE_DIRS.has(entry)) {
|
|
18990
|
-
|
|
19238
|
+
walkDir2(fullPath);
|
|
18991
19239
|
}
|
|
18992
|
-
} else if (
|
|
19240
|
+
} else if (stat2.isFile()) {
|
|
18993
19241
|
const ext = extname5(entry).toLowerCase();
|
|
18994
19242
|
const language = LANGUAGES[ext];
|
|
18995
19243
|
if (language) {
|
|
18996
19244
|
const content = readFileSync22(fullPath, "utf-8");
|
|
18997
19245
|
const exports = this.extractExports(content, language);
|
|
18998
|
-
files.push({ path: relPath, language, exports, size:
|
|
18999
|
-
totalSize +=
|
|
19246
|
+
files.push({ path: relPath, language, exports, size: stat2.size });
|
|
19247
|
+
totalSize += stat2.size;
|
|
19000
19248
|
count++;
|
|
19001
19249
|
}
|
|
19002
19250
|
}
|
|
19003
19251
|
}
|
|
19004
19252
|
};
|
|
19005
|
-
|
|
19253
|
+
walkDir2(this.baseDir);
|
|
19006
19254
|
return { files, totalSize };
|
|
19007
19255
|
}
|
|
19008
19256
|
extractExports(content, language) {
|
|
@@ -19045,7 +19293,7 @@ var init_walker = __esm(() => {
|
|
|
19045
19293
|
});
|
|
19046
19294
|
|
|
19047
19295
|
// src/modules/indexer/cache.ts
|
|
19048
|
-
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";
|
|
19049
19297
|
import { join as join32 } from "path";
|
|
19050
19298
|
|
|
19051
19299
|
class IndexCache {
|
|
@@ -19057,7 +19305,7 @@ class IndexCache {
|
|
|
19057
19305
|
load() {
|
|
19058
19306
|
if (this.cache)
|
|
19059
19307
|
return this.cache;
|
|
19060
|
-
if (!
|
|
19308
|
+
if (!existsSync40(this.cachePath))
|
|
19061
19309
|
return null;
|
|
19062
19310
|
try {
|
|
19063
19311
|
this.cache = JSON.parse(readFileSync23(this.cachePath, "utf-8"));
|
|
@@ -19069,13 +19317,13 @@ class IndexCache {
|
|
|
19069
19317
|
save(result) {
|
|
19070
19318
|
this.cache = result;
|
|
19071
19319
|
const dir = join32(this.cachePath, "..");
|
|
19072
|
-
if (!
|
|
19320
|
+
if (!existsSync40(dir))
|
|
19073
19321
|
mkdirSync17(dir, { recursive: true });
|
|
19074
19322
|
writeFileSync14(this.cachePath, JSON.stringify(result), "utf-8");
|
|
19075
19323
|
}
|
|
19076
19324
|
invalidate() {
|
|
19077
19325
|
this.cache = null;
|
|
19078
|
-
if (
|
|
19326
|
+
if (existsSync40(this.cachePath)) {
|
|
19079
19327
|
try {
|
|
19080
19328
|
rmSync3(this.cachePath);
|
|
19081
19329
|
} catch {}
|
|
@@ -19085,11 +19333,11 @@ class IndexCache {
|
|
|
19085
19333
|
var init_cache = () => {};
|
|
19086
19334
|
|
|
19087
19335
|
// src/modules/indexer/project-profile.ts
|
|
19088
|
-
import { readFileSync as readFileSync24, existsSync as
|
|
19336
|
+
import { readFileSync as readFileSync24, existsSync as existsSync41 } from "fs";
|
|
19089
19337
|
import { join as join33 } from "path";
|
|
19090
19338
|
function detectManifest(baseDir) {
|
|
19091
19339
|
for (const manifest of MANIFEST_ORDER) {
|
|
19092
|
-
if (
|
|
19340
|
+
if (existsSync41(join33(baseDir, manifest)))
|
|
19093
19341
|
return manifest;
|
|
19094
19342
|
}
|
|
19095
19343
|
return null;
|
|
@@ -19743,8 +19991,8 @@ __export(exports_bootstrap, {
|
|
|
19743
19991
|
bootstrap: () => bootstrap
|
|
19744
19992
|
});
|
|
19745
19993
|
import { homedir as homedir11 } from "os";
|
|
19746
|
-
import { join as join35, resolve as
|
|
19747
|
-
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";
|
|
19748
19996
|
function buildSystemInfo(config, baseDir, profileCompressed) {
|
|
19749
19997
|
const now = new Date().toISOString().replace("T", " ").slice(0, 19);
|
|
19750
19998
|
const isWin = profileCompressed.toLowerCase().includes("win32");
|
|
@@ -19757,7 +20005,7 @@ function buildSystemInfo(config, baseDir, profileCompressed) {
|
|
|
19757
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}`);
|
|
19758
20006
|
}
|
|
19759
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).`);
|
|
19760
|
-
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.`);
|
|
19761
20009
|
if (config.autoPlan) {
|
|
19762
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.`);
|
|
19763
20011
|
}
|
|
@@ -19814,7 +20062,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
19814
20062
|
retry: config.retry,
|
|
19815
20063
|
rateLimits: config.security?.rateLimits
|
|
19816
20064
|
});
|
|
19817
|
-
const baseDir = projectDir ?
|
|
20065
|
+
const baseDir = projectDir ? resolve23(projectDir) : process.cwd();
|
|
19818
20066
|
const projectMapCacheDir = join35(baseDir, ".mma");
|
|
19819
20067
|
const indexerModule = new IndexerModule({
|
|
19820
20068
|
baseDir,
|
|
@@ -19843,7 +20091,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
19843
20091
|
estimatedTokens: Math.ceil(systemInfoContent.length / 4)
|
|
19844
20092
|
};
|
|
19845
20093
|
const agentsMdGlobal = join35(dir, "AGENTS.md");
|
|
19846
|
-
if (!
|
|
20094
|
+
if (!existsSync42(agentsMdGlobal)) {
|
|
19847
20095
|
writeFileSync15(agentsMdGlobal, "", "utf-8");
|
|
19848
20096
|
}
|
|
19849
20097
|
const sessionDir = join35(dir, "sessions");
|
|
@@ -19979,6 +20227,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
19979
20227
|
timestamp: new Date().toISOString()
|
|
19980
20228
|
});
|
|
19981
20229
|
};
|
|
20230
|
+
contextManager.setPlanSummaryProvider(() => execModule.getPlanSummary());
|
|
19982
20231
|
const agentsMdBlocks = [];
|
|
19983
20232
|
const skipAgentsMd = noAgentsMd === true;
|
|
19984
20233
|
if (!skipAgentsMd) {
|
|
@@ -19988,7 +20237,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
19988
20237
|
join35(dir, "AGENTS.md")
|
|
19989
20238
|
];
|
|
19990
20239
|
for (const p of agentsMdCandidates) {
|
|
19991
|
-
if (
|
|
20240
|
+
if (existsSync42(p)) {
|
|
19992
20241
|
const content = readFileSync25(p, "utf-8").trim();
|
|
19993
20242
|
if (content) {
|
|
19994
20243
|
agentsMdBlocks.push({
|
|
@@ -20621,10 +20870,10 @@ function menuList(items) {
|
|
|
20621
20870
|
console.log(l);
|
|
20622
20871
|
}
|
|
20623
20872
|
function ask(rl, question, defaultValue) {
|
|
20624
|
-
return new Promise((
|
|
20873
|
+
return new Promise((resolve24) => {
|
|
20625
20874
|
const prompt = defaultValue ? `${question} [${defaultValue}]: ` : `${question}: `;
|
|
20626
20875
|
rl.question(prompt, (answer) => {
|
|
20627
|
-
|
|
20876
|
+
resolve24(answer.trim() || defaultValue || "");
|
|
20628
20877
|
});
|
|
20629
20878
|
});
|
|
20630
20879
|
}
|
|
@@ -20843,12 +21092,12 @@ __export(exports_manifest, {
|
|
|
20843
21092
|
getCertMark: () => getCertMark,
|
|
20844
21093
|
MANIFEST_PATH: () => MANIFEST_PATH
|
|
20845
21094
|
});
|
|
20846
|
-
import { existsSync as
|
|
21095
|
+
import { existsSync as existsSync43, readFileSync as readFileSync26, mkdirSync as mkdirSync18, writeFileSync as writeFileSync16 } from "fs";
|
|
20847
21096
|
import { homedir as homedir13 } from "os";
|
|
20848
21097
|
import { join as join37 } from "path";
|
|
20849
21098
|
function readManifest(path = MANIFEST_PATH) {
|
|
20850
21099
|
try {
|
|
20851
|
-
if (
|
|
21100
|
+
if (existsSync43(path)) {
|
|
20852
21101
|
const raw = JSON.parse(readFileSync26(path, "utf-8"));
|
|
20853
21102
|
return { version: 1, certifications: raw.certifications ?? [] };
|
|
20854
21103
|
}
|
|
@@ -28014,7 +28263,7 @@ var init_scenarios = __esm(() => {
|
|
|
28014
28263
|
});
|
|
28015
28264
|
|
|
28016
28265
|
// src/modules/certification/loader.ts
|
|
28017
|
-
import { existsSync as
|
|
28266
|
+
import { existsSync as existsSync44, readdirSync as readdirSync15, readFileSync as readFileSync27 } from "fs";
|
|
28018
28267
|
import { join as join38 } from "path";
|
|
28019
28268
|
function validateScenario(s) {
|
|
28020
28269
|
const errors2 = [];
|
|
@@ -28064,7 +28313,7 @@ function loadScenarios(userDir) {
|
|
|
28064
28313
|
else
|
|
28065
28314
|
scenarios.push(s);
|
|
28066
28315
|
}
|
|
28067
|
-
if (userDir &&
|
|
28316
|
+
if (userDir && existsSync44(userDir)) {
|
|
28068
28317
|
for (const file of readdirSync15(userDir)) {
|
|
28069
28318
|
if (!file.endsWith(".yaml") && !file.endsWith(".yml"))
|
|
28070
28319
|
continue;
|
|
@@ -28122,7 +28371,7 @@ var init_loader3 = __esm(() => {
|
|
|
28122
28371
|
});
|
|
28123
28372
|
|
|
28124
28373
|
// src/modules/certification/fact-checker.ts
|
|
28125
|
-
import { existsSync as
|
|
28374
|
+
import { existsSync as existsSync45, readFileSync as readFileSync28, statSync as statSync8 } from "fs";
|
|
28126
28375
|
import { join as join39 } from "path";
|
|
28127
28376
|
function checkSandbox(sandboxDir, checks, exitCode, output) {
|
|
28128
28377
|
const failures = [];
|
|
@@ -28142,7 +28391,7 @@ function runCheck(sandboxDir, check, exitCode, output) {
|
|
|
28142
28391
|
case "fileExists":
|
|
28143
28392
|
return isFile(join39(sandboxDir, check.path));
|
|
28144
28393
|
case "fileNotExists":
|
|
28145
|
-
return !
|
|
28394
|
+
return !existsSync45(join39(sandboxDir, check.path));
|
|
28146
28395
|
case "dirExists":
|
|
28147
28396
|
return isDir(join39(sandboxDir, check.path));
|
|
28148
28397
|
case "fileContent": {
|
|
@@ -28168,14 +28417,14 @@ function runCheck(sandboxDir, check, exitCode, output) {
|
|
|
28168
28417
|
}
|
|
28169
28418
|
function isFile(p) {
|
|
28170
28419
|
try {
|
|
28171
|
-
return
|
|
28420
|
+
return existsSync45(p) && statSync8(p).isFile();
|
|
28172
28421
|
} catch {
|
|
28173
28422
|
return false;
|
|
28174
28423
|
}
|
|
28175
28424
|
}
|
|
28176
28425
|
function isDir(p) {
|
|
28177
28426
|
try {
|
|
28178
|
-
return
|
|
28427
|
+
return existsSync45(p) && statSync8(p).isDirectory();
|
|
28179
28428
|
} catch {
|
|
28180
28429
|
return false;
|
|
28181
28430
|
}
|
|
@@ -28206,9 +28455,9 @@ var init_fact_checker = () => {};
|
|
|
28206
28455
|
|
|
28207
28456
|
// src/modules/certification/runner.ts
|
|
28208
28457
|
import { spawn as spawn7 } from "child_process";
|
|
28209
|
-
import { existsSync as
|
|
28458
|
+
import { existsSync as existsSync46, mkdirSync as mkdirSync19, rmSync as rmSync4, cpSync as cpSync2 } from "fs";
|
|
28210
28459
|
import { platform as platform8 } from "os";
|
|
28211
|
-
import { join as join40, resolve as
|
|
28460
|
+
import { join as join40, resolve as resolve24, dirname as dirname13 } from "path";
|
|
28212
28461
|
async function runScenario(scenario, opts) {
|
|
28213
28462
|
if (scenario.mode === "skip") {
|
|
28214
28463
|
return {
|
|
@@ -28289,7 +28538,7 @@ function prepareSandbox(sandbox, scenario, mmaRoot) {
|
|
|
28289
28538
|
mkdirSync19(sandbox, { recursive: true });
|
|
28290
28539
|
for (const f of scenario.fixtures ?? []) {
|
|
28291
28540
|
const src = join40(mmaRoot, f.source);
|
|
28292
|
-
if (!
|
|
28541
|
+
if (!existsSync46(src)) {
|
|
28293
28542
|
throw new Error(`fixture missing: ${f.source}`);
|
|
28294
28543
|
}
|
|
28295
28544
|
const dest = join40(sandbox, f.dest);
|
|
@@ -28299,17 +28548,17 @@ function prepareSandbox(sandbox, scenario, mmaRoot) {
|
|
|
28299
28548
|
}
|
|
28300
28549
|
function resolveMmaEntry(mmaRoot) {
|
|
28301
28550
|
const dev = join40(mmaRoot, "src", "cli", "main.ts");
|
|
28302
|
-
if (
|
|
28551
|
+
if (existsSync46(dev))
|
|
28303
28552
|
return dev;
|
|
28304
28553
|
return join40(mmaRoot, "dist", "main.js");
|
|
28305
28554
|
}
|
|
28306
28555
|
function findMmaRoot(fromDir) {
|
|
28307
28556
|
const candidates = [
|
|
28308
|
-
|
|
28309
|
-
|
|
28557
|
+
resolve24(fromDir, "..", "..", ".."),
|
|
28558
|
+
resolve24(fromDir, "..")
|
|
28310
28559
|
];
|
|
28311
28560
|
for (const c of candidates) {
|
|
28312
|
-
if (
|
|
28561
|
+
if (existsSync46(join40(c, "package.json")))
|
|
28313
28562
|
return c;
|
|
28314
28563
|
}
|
|
28315
28564
|
return process.cwd();
|
|
@@ -28379,11 +28628,11 @@ import { rmSync as rmSync5 } from "fs";
|
|
|
28379
28628
|
import { homedir as homedir14 } from "os";
|
|
28380
28629
|
import { join as join41, dirname as dirname14 } from "path";
|
|
28381
28630
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
28382
|
-
import { existsSync as
|
|
28631
|
+
import { existsSync as existsSync47, readFileSync as readFileSync29 } from "fs";
|
|
28383
28632
|
function readVersion() {
|
|
28384
28633
|
const candidates = [join41(MMA_ROOT, "package.json")];
|
|
28385
28634
|
for (const p of candidates) {
|
|
28386
|
-
if (
|
|
28635
|
+
if (existsSync47(p)) {
|
|
28387
28636
|
try {
|
|
28388
28637
|
const raw = JSON.parse(readFileSync29(p, "utf-8"));
|
|
28389
28638
|
if (raw.version)
|
|
@@ -28546,7 +28795,7 @@ __export(exports_repl_commands, {
|
|
|
28546
28795
|
});
|
|
28547
28796
|
import { join as join43, dirname as dirname16 } from "path";
|
|
28548
28797
|
import { homedir as homedir16 } from "os";
|
|
28549
|
-
import { existsSync as
|
|
28798
|
+
import { existsSync as existsSync49, readFileSync as readFileSync31 } from "fs";
|
|
28550
28799
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
28551
28800
|
function readVersion3() {
|
|
28552
28801
|
const here = dirname16(fileURLToPath4(import.meta.url));
|
|
@@ -28555,7 +28804,7 @@ function readVersion3() {
|
|
|
28555
28804
|
join43(here, "..", "package.json")
|
|
28556
28805
|
];
|
|
28557
28806
|
for (const p of candidates) {
|
|
28558
|
-
if (
|
|
28807
|
+
if (existsSync49(p)) {
|
|
28559
28808
|
try {
|
|
28560
28809
|
const raw = JSON.parse(readFileSync31(p, "utf8"));
|
|
28561
28810
|
if (raw.version)
|
|
@@ -28621,8 +28870,8 @@ function registerMmaCommands(ctx) {
|
|
|
28621
28870
|
}
|
|
28622
28871
|
try {
|
|
28623
28872
|
const { loadFileAsDataUrl: loadFileAsDataUrl2, loadUrlAsDataUrl: loadUrlAsDataUrl2, readClipboardImage: readClipboardImage2 } = await Promise.resolve().then(() => (init_image_utils(), exports_image_utils));
|
|
28624
|
-
const { existsSync:
|
|
28625
|
-
const { resolve:
|
|
28873
|
+
const { existsSync: existsSync50 } = await import("fs");
|
|
28874
|
+
const { resolve: resolve25 } = await import("path");
|
|
28626
28875
|
let dataUrl;
|
|
28627
28876
|
let label;
|
|
28628
28877
|
if (source.toLowerCase() === "clipboard") {
|
|
@@ -28640,8 +28889,8 @@ function registerMmaCommands(ctx) {
|
|
|
28640
28889
|
dataUrl = result.dataUrl;
|
|
28641
28890
|
label = source;
|
|
28642
28891
|
} else {
|
|
28643
|
-
const absPath =
|
|
28644
|
-
if (!
|
|
28892
|
+
const absPath = resolve25(process.cwd(), source);
|
|
28893
|
+
if (!existsSync50(absPath)) {
|
|
28645
28894
|
console.log(pc2.red(t("image.not_found", { path: source })));
|
|
28646
28895
|
return;
|
|
28647
28896
|
}
|
|
@@ -29179,7 +29428,7 @@ init_setup();
|
|
|
29179
29428
|
init_i18n();
|
|
29180
29429
|
import { join as join42, dirname as dirname15 } from "path";
|
|
29181
29430
|
import { homedir as homedir15 } from "os";
|
|
29182
|
-
import { existsSync as
|
|
29431
|
+
import { existsSync as existsSync48, readFileSync as readFileSync30 } from "fs";
|
|
29183
29432
|
|
|
29184
29433
|
// src/cli/security-commands.ts
|
|
29185
29434
|
init_bootstrap();
|
|
@@ -29807,7 +30056,7 @@ function readVersion2() {
|
|
|
29807
30056
|
join42(here, "..", "package.json")
|
|
29808
30057
|
];
|
|
29809
30058
|
for (const p of candidates) {
|
|
29810
|
-
if (
|
|
30059
|
+
if (existsSync48(p)) {
|
|
29811
30060
|
try {
|
|
29812
30061
|
const raw = JSON.parse(readFileSync30(p, "utf8"));
|
|
29813
30062
|
if (raw.version)
|
|
@@ -30791,7 +31040,7 @@ class LineEditor {
|
|
|
30791
31040
|
}
|
|
30792
31041
|
|
|
30793
31042
|
// src/cli/repl.ts
|
|
30794
|
-
import { existsSync as
|
|
31043
|
+
import { existsSync as existsSync50, readFileSync as readFileSync32, writeFileSync as writeFileSync17 } from "fs";
|
|
30795
31044
|
import { join as join44, dirname as dirname17 } from "path";
|
|
30796
31045
|
import { homedir as homedir17 } from "os";
|
|
30797
31046
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
@@ -31302,7 +31551,7 @@ function readVersion4() {
|
|
|
31302
31551
|
join44(here, "..", "package.json")
|
|
31303
31552
|
];
|
|
31304
31553
|
for (const p of candidates) {
|
|
31305
|
-
if (
|
|
31554
|
+
if (existsSync50(p)) {
|
|
31306
31555
|
try {
|
|
31307
31556
|
const raw = JSON.parse(readFileSync32(p, "utf8"));
|
|
31308
31557
|
if (raw.version)
|
|
@@ -31396,7 +31645,7 @@ class Repl {
|
|
|
31396
31645
|
this.setupListeners();
|
|
31397
31646
|
}
|
|
31398
31647
|
loadHistory() {
|
|
31399
|
-
if (
|
|
31648
|
+
if (existsSync50(this.historyPath)) {
|
|
31400
31649
|
try {
|
|
31401
31650
|
const raw = readFileSync32(this.historyPath, "utf-8");
|
|
31402
31651
|
this.history = raw.split(`
|
|
@@ -31759,7 +32008,7 @@ ${t("image.clipboard_empty")}`));
|
|
|
31759
32008
|
join44(this.baseDir, ".mma", "AGENTS.md"),
|
|
31760
32009
|
join44(this.configDir, "AGENTS.md")
|
|
31761
32010
|
];
|
|
31762
|
-
const foundAgents = agentsMdCandidates.filter((p) =>
|
|
32011
|
+
const foundAgents = agentsMdCandidates.filter((p) => existsSync50(p));
|
|
31763
32012
|
if (foundAgents.length > 0) {
|
|
31764
32013
|
for (const p of foundAgents) {
|
|
31765
32014
|
row(t("repl.agents_label"), pc2.dim(p));
|
|
@@ -31811,7 +32060,7 @@ init_setup();
|
|
|
31811
32060
|
init_config2();
|
|
31812
32061
|
init_i18n();
|
|
31813
32062
|
init_colors();
|
|
31814
|
-
import { existsSync as
|
|
32063
|
+
import { existsSync as existsSync51, readFileSync as readFileSync33 } from "fs";
|
|
31815
32064
|
import { join as join45, dirname as dirname18 } from "path";
|
|
31816
32065
|
import { homedir as homedir18 } from "os";
|
|
31817
32066
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
@@ -31832,8 +32081,8 @@ function semverGt(a, b) {
|
|
|
31832
32081
|
}
|
|
31833
32082
|
var defaultRunner2 = async (command, args, options) => {
|
|
31834
32083
|
const { execFile } = await import("child_process");
|
|
31835
|
-
return new Promise((
|
|
31836
|
-
execFile(command, args, options, (err) =>
|
|
32084
|
+
return new Promise((resolve25) => {
|
|
32085
|
+
execFile(command, args, options, (err) => resolve25({ error: err?.message }));
|
|
31837
32086
|
});
|
|
31838
32087
|
};
|
|
31839
32088
|
|
|
@@ -31998,7 +32247,7 @@ function readVersion5() {
|
|
|
31998
32247
|
join45(here, "..", "package.json")
|
|
31999
32248
|
];
|
|
32000
32249
|
for (const p of candidates) {
|
|
32001
|
-
if (
|
|
32250
|
+
if (existsSync51(p)) {
|
|
32002
32251
|
try {
|
|
32003
32252
|
const raw = JSON.parse(readFileSync33(p, "utf8"));
|
|
32004
32253
|
if (raw.version)
|
|
@@ -32084,7 +32333,7 @@ async function main() {
|
|
|
32084
32333
|
process.exit(exitCode);
|
|
32085
32334
|
} else {
|
|
32086
32335
|
const configPath = join45(homedir18(), ".mma", "config.json");
|
|
32087
|
-
if (!
|
|
32336
|
+
if (!existsSync51(configPath)) {
|
|
32088
32337
|
console.log(pc2.yellow(`
|
|
32089
32338
|
` + t("cli.first_run") + `
|
|
32090
32339
|
`));
|