micro-models-agent 0.42.0 → 0.43.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.js +400 -149
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -2552,6 +2552,15 @@ Command: {command}`,
|
|
|
2552
2552
|
"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.',
|
|
2553
2553
|
"plan.id_ignored": 'note: plan ids are auto-generated; use "plan switch" to activate an existing plan by id.',
|
|
2554
2554
|
"plan.existing_fresh": "note: the previous active plan had no progress and was preserved as a draft.",
|
|
2555
|
+
"plan.already_active": "Plan {id} is already active — nothing to switch.",
|
|
2556
|
+
"plan.already_archived": "Plan {id} is already archived — nothing to abort.",
|
|
2557
|
+
"plan.aborted_id": "Plan {id} aborted and archived.",
|
|
2558
|
+
"plan.delete_no_id": "Provide a plan id to delete (plan delete id=plan_xxx).",
|
|
2559
|
+
"plan.deleted": "Plan {id} deleted permanently.",
|
|
2560
|
+
"plan.purged": "Deleted {count} plan(s). Plan storage is empty.",
|
|
2561
|
+
"plan.no_deliverables": "note: step {step} names no files — its completion cannot be auto-verified; run an explicit check (e.g. build/tests) before your final answer.",
|
|
2562
|
+
"plan.list_legend": "[*] active · [ ] draft · [-] archived",
|
|
2563
|
+
"exec.plan_nudge": "You made {count} file-changing tool call(s) without a plan. For tasks that create or modify files, or span multiple steps, create a plan first (plan create) with concrete steps (exact filenames, commands, deliverables), then continue.",
|
|
2555
2564
|
"todo.added": "Added {count} todo(s): {items}",
|
|
2556
2565
|
"todo.marked_done": "Marked {count} item(s) as done",
|
|
2557
2566
|
"todo.no_active": "No active todos",
|
|
@@ -3195,6 +3204,15 @@ var init_ru = __esm(() => {
|
|
|
3195
3204
|
"plan.active_in_progress": 'Нельзя создать новый план: активный план {id} уже имеет прогресс ({done}/{total} выполнено, текущий: шаг {current}). Продолжай его — вызови "plan show", чтобы увидеть, и продолжай работу. Чтобы заменить план, сначала вызови "plan abort", затем "plan create".',
|
|
3196
3205
|
"plan.id_ignored": 'примечание: id плана генерируется автоматически; используй "plan switch", чтобы активировать существующий план по id.',
|
|
3197
3206
|
"plan.existing_fresh": "примечание: предыдущий активный план не имел прогресса и сохранён как черновик.",
|
|
3207
|
+
"plan.already_active": "План {id} уже активен — переключаться некуда.",
|
|
3208
|
+
"plan.already_archived": "План {id} уже в архиве — отменять нечего.",
|
|
3209
|
+
"plan.aborted_id": "План {id} отменён и архивирован.",
|
|
3210
|
+
"plan.delete_no_id": "Укажите id плана для удаления (plan delete id=plan_xxx).",
|
|
3211
|
+
"plan.deleted": "План {id} удалён окончательно.",
|
|
3212
|
+
"plan.purged": "Удалено планов: {count}. Хранилище планов пусто.",
|
|
3213
|
+
"plan.no_deliverables": "примечание: шаг {step} не называет файлов — его выполнение нельзя проверить автоматически; перед финальным ответом явно проверь результат (например, запусти сборку/тесты).",
|
|
3214
|
+
"plan.list_legend": "[*] активный · [ ] черновик · [-] архив",
|
|
3215
|
+
"exec.plan_nudge": "Ты сделал(а) {count} вызов(ов), изменяющих файлы, без плана. Для задач, создающих/изменяющих файлы или состоящих из нескольких шагов, сначала создай план (plan create) с конкретными шагами (точные имена файлов, команды, результаты), а потом продолжай.",
|
|
3198
3216
|
"todo.added": "Добавлено {count} задач: {items}",
|
|
3199
3217
|
"todo.marked_done": "Отмечено выполненными: {count}",
|
|
3200
3218
|
"todo.no_active": "Нет активных задач",
|
|
@@ -5679,12 +5697,17 @@ class ToolExecutor {
|
|
|
5679
5697
|
toolCallId: call.id
|
|
5680
5698
|
};
|
|
5681
5699
|
}
|
|
5682
|
-
|
|
5683
|
-
|
|
5684
|
-
|
|
5685
|
-
|
|
5686
|
-
|
|
5687
|
-
|
|
5700
|
+
if (signal?.aborted) {
|
|
5701
|
+
this.ctx.logger.debug(`Tool ${call.name}: abort, skipping onAfterTool plugins`);
|
|
5702
|
+
} else {
|
|
5703
|
+
const pluginCtx = signal ? { ...this.ctx, signal } : this.ctx;
|
|
5704
|
+
for (const plugin of this.pluginManager.getAllPlugins()) {
|
|
5705
|
+
if (plugin.onAfterTool) {
|
|
5706
|
+
try {
|
|
5707
|
+
await plugin.onAfterTool(pluginCtx, call, result);
|
|
5708
|
+
} catch (e) {
|
|
5709
|
+
this.ctx.logger.warn(`Plugin onAfterTool error: ${e.message}`);
|
|
5710
|
+
}
|
|
5688
5711
|
}
|
|
5689
5712
|
}
|
|
5690
5713
|
}
|
|
@@ -10598,8 +10621,46 @@ var init_js_identifiers = __esm(() => {
|
|
|
10598
10621
|
});
|
|
10599
10622
|
|
|
10600
10623
|
// src/modules/execution/audit-runners.ts
|
|
10601
|
-
import { existsSync as existsSync20, readdirSync as readdirSync5 } from "fs";
|
|
10624
|
+
import { existsSync as existsSync20, readdirSync as readdirSync5, readFileSync as readFileSync10 } from "fs";
|
|
10602
10625
|
import { dirname as dirname7, join as join11, resolve as resolve11 } from "path";
|
|
10626
|
+
function resolveTestCommand(dir) {
|
|
10627
|
+
const pkgPath = join11(dir, "package.json");
|
|
10628
|
+
if (existsSync20(pkgPath)) {
|
|
10629
|
+
try {
|
|
10630
|
+
const pkg = JSON.parse(readFileSync10(pkgPath, "utf-8"));
|
|
10631
|
+
const script = pkg?.scripts?.test;
|
|
10632
|
+
if (typeof script === "string" && script.trim())
|
|
10633
|
+
return script.trim();
|
|
10634
|
+
} catch {}
|
|
10635
|
+
}
|
|
10636
|
+
for (const f of [
|
|
10637
|
+
"vitest.config.ts",
|
|
10638
|
+
"vitest.config.js",
|
|
10639
|
+
"vitest.config.mjs",
|
|
10640
|
+
"jest.config.js",
|
|
10641
|
+
"jest.config.ts",
|
|
10642
|
+
"jest.config.mjs",
|
|
10643
|
+
"jest.config.cjs",
|
|
10644
|
+
"bunfig.toml"
|
|
10645
|
+
]) {
|
|
10646
|
+
if (existsSync20(join11(dir, f))) {
|
|
10647
|
+
if (f.startsWith("vitest"))
|
|
10648
|
+
return "bunx vitest run";
|
|
10649
|
+
if (f.startsWith("jest"))
|
|
10650
|
+
return "npx --no-install jest";
|
|
10651
|
+
if (f === "bunfig.toml")
|
|
10652
|
+
return "bun test";
|
|
10653
|
+
}
|
|
10654
|
+
}
|
|
10655
|
+
if (existsSync20(join11(dir, "pyproject.toml")) || existsSync20(join11(dir, "pytest.ini")) || existsSync20(join11(dir, "conftest.py"))) {
|
|
10656
|
+
return "python -m pytest -q";
|
|
10657
|
+
}
|
|
10658
|
+
if (existsSync20(join11(dir, "go.mod")))
|
|
10659
|
+
return "go test ./...";
|
|
10660
|
+
if (existsSync20(join11(dir, "Cargo.toml")))
|
|
10661
|
+
return "cargo test";
|
|
10662
|
+
return "bun test";
|
|
10663
|
+
}
|
|
10603
10664
|
function findTestFile(dir, depth = 0) {
|
|
10604
10665
|
if (depth > 5)
|
|
10605
10666
|
return null;
|
|
@@ -10617,7 +10678,7 @@ function findTestFile(dir, depth = 0) {
|
|
|
10617
10678
|
const found = findTestFile(full, depth + 1);
|
|
10618
10679
|
if (found)
|
|
10619
10680
|
return found;
|
|
10620
|
-
} else if (TEST_EXT_RE.test(e.name)) {
|
|
10681
|
+
} else if (TEST_EXT_RE.test(e.name) || PY_TEST_RE.test(e.name)) {
|
|
10621
10682
|
return full;
|
|
10622
10683
|
}
|
|
10623
10684
|
}
|
|
@@ -10638,7 +10699,8 @@ function extractFailingNames(output, limit = 5) {
|
|
|
10638
10699
|
return names;
|
|
10639
10700
|
}
|
|
10640
10701
|
async function runTests(baseDir) {
|
|
10641
|
-
const
|
|
10702
|
+
const command = resolveTestCommand(baseDir);
|
|
10703
|
+
const entry = processRegistry.start(command, baseDir);
|
|
10642
10704
|
const exited = await processRegistry.waitForExit(entry.id, 90000);
|
|
10643
10705
|
const output = entry.log.join(`
|
|
10644
10706
|
`);
|
|
@@ -10649,8 +10711,8 @@ async function runTests(baseDir) {
|
|
|
10649
10711
|
passed: true,
|
|
10650
10712
|
failed: 0,
|
|
10651
10713
|
passedCount: 0,
|
|
10652
|
-
detail:
|
|
10653
|
-
command
|
|
10714
|
+
detail: `test run timed out after 90s — result unknown`,
|
|
10715
|
+
command
|
|
10654
10716
|
};
|
|
10655
10717
|
}
|
|
10656
10718
|
const run = detectTestResults(output);
|
|
@@ -10661,7 +10723,7 @@ async function runTests(baseDir) {
|
|
|
10661
10723
|
failed: entry.exitCode === 0 ? 0 : 1,
|
|
10662
10724
|
passedCount: 0,
|
|
10663
10725
|
detail: output.slice(0, 200).trim(),
|
|
10664
|
-
command
|
|
10726
|
+
command
|
|
10665
10727
|
};
|
|
10666
10728
|
}
|
|
10667
10729
|
const names = extractFailingNames(output);
|
|
@@ -10671,7 +10733,7 @@ async function runTests(baseDir) {
|
|
|
10671
10733
|
failed: run.failed,
|
|
10672
10734
|
passedCount: run.passed,
|
|
10673
10735
|
detail: names.length ? names.join("; ") : run.summary || `${run.failed} failed / ${run.passed} passed`,
|
|
10674
|
-
command
|
|
10736
|
+
command
|
|
10675
10737
|
};
|
|
10676
10738
|
}
|
|
10677
10739
|
function parseTypecheckErrors(output) {
|
|
@@ -10708,7 +10770,7 @@ async function runTypecheck(baseDir) {
|
|
|
10708
10770
|
return null;
|
|
10709
10771
|
return parseTypecheckErrors(output);
|
|
10710
10772
|
}
|
|
10711
|
-
var SKIP_DIRS, TEST_EXT_RE, TEST_STEP_RE;
|
|
10773
|
+
var SKIP_DIRS, TEST_EXT_RE, PY_TEST_RE, TEST_STEP_RE;
|
|
10712
10774
|
var init_audit_runners = __esm(() => {
|
|
10713
10775
|
init_bash();
|
|
10714
10776
|
init_processes();
|
|
@@ -10724,6 +10786,7 @@ var init_audit_runners = __esm(() => {
|
|
|
10724
10786
|
"vendor"
|
|
10725
10787
|
]);
|
|
10726
10788
|
TEST_EXT_RE = /\.(test|spec)\.[jt]sx?$/i;
|
|
10789
|
+
PY_TEST_RE = /^test_.*\.py$|^.*_test\.py$/i;
|
|
10727
10790
|
TEST_STEP_RE = /\b(test(ing|s)?|тест(ы|ирование|ировать)?|провер\w*\s+тест|запустить\s+тест)\b|bun test|npm test|vitest|pytest|go test|jest|mocha/i;
|
|
10728
10791
|
});
|
|
10729
10792
|
|
|
@@ -11639,6 +11702,8 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
|
|
|
11639
11702
|
slog.logToolCall(call, iteration);
|
|
11640
11703
|
const tokensBeforeTool = contextManager.getEstimatedTokens();
|
|
11641
11704
|
const result = await toolExecutor.execute(call, this.abortController?.signal);
|
|
11705
|
+
if (this.shutdownRequested)
|
|
11706
|
+
break;
|
|
11642
11707
|
const duration = Date.now() - startTime;
|
|
11643
11708
|
if (!result.success)
|
|
11644
11709
|
anyToolFailed = true;
|
|
@@ -11717,6 +11782,8 @@ ${t("tool.truncated", { tokens: Math.ceil(removedChars / 2) })}`;
|
|
|
11717
11782
|
}
|
|
11718
11783
|
}
|
|
11719
11784
|
}
|
|
11785
|
+
if (this.shutdownRequested)
|
|
11786
|
+
break;
|
|
11720
11787
|
if (anyToolFailed) {
|
|
11721
11788
|
consecutiveToolFailures++;
|
|
11722
11789
|
} else {
|
|
@@ -13408,7 +13475,7 @@ ${joined}` }
|
|
|
13408
13475
|
var DEFAULT_CHUNK_SYSTEM_PROMPT = 'Answer the query using ONLY the provided text. Be concise. If the text does not contain the answer, say "NO_EVIDENCE".', DEFAULT_SYNTHESIS_SYSTEM_PROMPT = "You are given a query and per-chunk answers over a large text. Produce the final answer to the query, combining evidence from the chunks. If no chunk had evidence, say so.";
|
|
13409
13476
|
|
|
13410
13477
|
// src/tools/chunk-query.ts
|
|
13411
|
-
import { readFileSync as
|
|
13478
|
+
import { readFileSync as readFileSync11 } from "node:fs";
|
|
13412
13479
|
import { resolve as resolve16 } from "node:path";
|
|
13413
13480
|
var chunkQueryTool;
|
|
13414
13481
|
var init_chunk_query = __esm(() => {
|
|
@@ -13477,7 +13544,7 @@ var init_chunk_query = __esm(() => {
|
|
|
13477
13544
|
return { success: false, output: `[SCOPE] ${check.reason || "Path not allowed"}` };
|
|
13478
13545
|
}
|
|
13479
13546
|
try {
|
|
13480
|
-
content =
|
|
13547
|
+
content = readFileSync11(resolve16(ctx.baseDir, inputPath), "utf8");
|
|
13481
13548
|
} catch (e) {
|
|
13482
13549
|
return { success: false, output: `Cannot read ${inputPath}: ${e.message}` };
|
|
13483
13550
|
}
|
|
@@ -14849,7 +14916,7 @@ var init_search_history = __esm(() => {
|
|
|
14849
14916
|
});
|
|
14850
14917
|
|
|
14851
14918
|
// src/modules/memory/search.ts
|
|
14852
|
-
import { readFileSync as
|
|
14919
|
+
import { readFileSync as readFileSync13, existsSync as existsSync26 } from "fs";
|
|
14853
14920
|
import { join as join17 } from "path";
|
|
14854
14921
|
|
|
14855
14922
|
class MemorySearch {
|
|
@@ -14864,7 +14931,7 @@ class MemorySearch {
|
|
|
14864
14931
|
const path = join17(this.memoryDir, `${name}.md`);
|
|
14865
14932
|
if (!existsSync26(path))
|
|
14866
14933
|
continue;
|
|
14867
|
-
const content =
|
|
14934
|
+
const content = readFileSync13(path, "utf-8");
|
|
14868
14935
|
const lines = content.split(`
|
|
14869
14936
|
`);
|
|
14870
14937
|
for (const line of lines) {
|
|
@@ -14876,7 +14943,7 @@ class MemorySearch {
|
|
|
14876
14943
|
const prefsPath = join17(this.memoryDir, "preferences.json");
|
|
14877
14944
|
if (existsSync26(prefsPath)) {
|
|
14878
14945
|
try {
|
|
14879
|
-
const prefs = JSON.parse(
|
|
14946
|
+
const prefs = JSON.parse(readFileSync13(prefsPath, "utf-8"));
|
|
14880
14947
|
for (const [key, value] of Object.entries(prefs)) {
|
|
14881
14948
|
const searchStr = `${key}=${value}`;
|
|
14882
14949
|
if (searchStr.toLowerCase().includes(lowerQuery)) {
|
|
@@ -14894,7 +14961,7 @@ var init_search = __esm(() => {
|
|
|
14894
14961
|
});
|
|
14895
14962
|
|
|
14896
14963
|
// src/modules/memory/store.ts
|
|
14897
|
-
import { readFileSync as
|
|
14964
|
+
import { readFileSync as readFileSync14, writeFileSync as writeFileSync9, appendFileSync as appendFileSync5, existsSync as existsSync27, mkdirSync as mkdirSync13 } from "fs";
|
|
14898
14965
|
import { join as join18 } from "path";
|
|
14899
14966
|
|
|
14900
14967
|
class MemoryStore {
|
|
@@ -14920,7 +14987,7 @@ class MemoryStore {
|
|
|
14920
14987
|
const path = join18(this.memoryDir, `${name}.md`);
|
|
14921
14988
|
if (!existsSync27(path))
|
|
14922
14989
|
return "";
|
|
14923
|
-
return
|
|
14990
|
+
return readFileSync14(path, "utf-8");
|
|
14924
14991
|
}
|
|
14925
14992
|
append(name, entry) {
|
|
14926
14993
|
const path = join18(this.memoryDir, `${name}.md`);
|
|
@@ -14941,7 +15008,7 @@ class MemoryStore {
|
|
|
14941
15008
|
if (!existsSync27(path))
|
|
14942
15009
|
return {};
|
|
14943
15010
|
try {
|
|
14944
|
-
return JSON.parse(
|
|
15011
|
+
return JSON.parse(readFileSync14(path, "utf-8"));
|
|
14945
15012
|
} catch {
|
|
14946
15013
|
return {};
|
|
14947
15014
|
}
|
|
@@ -16230,7 +16297,7 @@ __export(exports_image_utils, {
|
|
|
16230
16297
|
detectMime: () => detectMime,
|
|
16231
16298
|
bufferToDataUrl: () => bufferToDataUrl
|
|
16232
16299
|
});
|
|
16233
|
-
import { readFileSync as
|
|
16300
|
+
import { readFileSync as readFileSync15 } from "fs";
|
|
16234
16301
|
import { extname as extname3 } from "path";
|
|
16235
16302
|
function detectMime(filePath) {
|
|
16236
16303
|
const ext = extname3(filePath).toLowerCase();
|
|
@@ -16251,7 +16318,7 @@ async function readClipboardImage() {
|
|
|
16251
16318
|
async function readClipboardFallback() {
|
|
16252
16319
|
const { platform: platform5 } = await import("os");
|
|
16253
16320
|
const { execSync } = await import("child_process");
|
|
16254
|
-
const { readFileSync:
|
|
16321
|
+
const { readFileSync: readFileSync16, unlinkSync: unlinkSync4 } = await import("fs");
|
|
16255
16322
|
const { join: join24 } = await import("path");
|
|
16256
16323
|
const tmpPath = join24(process.env.TEMP || process.env.TMP || "/tmp", `mma-clip-${Date.now()}.png`);
|
|
16257
16324
|
try {
|
|
@@ -16262,7 +16329,7 @@ async function readClipboardFallback() {
|
|
|
16262
16329
|
} else {
|
|
16263
16330
|
return null;
|
|
16264
16331
|
}
|
|
16265
|
-
const buf =
|
|
16332
|
+
const buf = readFileSync16(tmpPath);
|
|
16266
16333
|
unlinkSync4(tmpPath);
|
|
16267
16334
|
return buf.length > 0 ? buf : null;
|
|
16268
16335
|
} catch {
|
|
@@ -16273,7 +16340,7 @@ async function readClipboardFallback() {
|
|
|
16273
16340
|
}
|
|
16274
16341
|
}
|
|
16275
16342
|
async function loadFileAsDataUrl(filePath) {
|
|
16276
|
-
const buf =
|
|
16343
|
+
const buf = readFileSync15(filePath);
|
|
16277
16344
|
if (typeof Bun !== "undefined" && typeof Bun.Image !== "undefined") {
|
|
16278
16345
|
try {
|
|
16279
16346
|
const img = new Bun.Image(buf);
|
|
@@ -16700,7 +16767,7 @@ var init_loader = __esm(() => {
|
|
|
16700
16767
|
|
|
16701
16768
|
// src/modules/plugins/builtin/lint-on-write.ts
|
|
16702
16769
|
import { spawn as spawn5, execSync } from "child_process";
|
|
16703
|
-
import { existsSync as existsSync31, readFileSync as
|
|
16770
|
+
import { existsSync as existsSync31, readFileSync as readFileSync16 } from "fs";
|
|
16704
16771
|
import { resolve as resolve18, extname as extname4, join as join25 } from "path";
|
|
16705
16772
|
import { platform as platform5 } from "os";
|
|
16706
16773
|
function contentHash(content) {
|
|
@@ -16750,22 +16817,29 @@ class LintOnWritePlugin {
|
|
|
16750
16817
|
const fullPath = resolve18(ctx.baseDir, path);
|
|
16751
16818
|
if (!existsSync31(fullPath))
|
|
16752
16819
|
return;
|
|
16820
|
+
const signal = ctx.signal;
|
|
16821
|
+
if (signal?.aborted)
|
|
16822
|
+
return;
|
|
16753
16823
|
const ext = extname4(fullPath);
|
|
16754
|
-
const syntaxError = await this.checkSyntax(fullPath, ext, ctx.baseDir);
|
|
16824
|
+
const syntaxError = await this.checkSyntax(fullPath, ext, ctx.baseDir, signal);
|
|
16825
|
+
if (signal?.aborted)
|
|
16826
|
+
return;
|
|
16755
16827
|
if (syntaxError) {
|
|
16756
16828
|
result.output += `
|
|
16757
16829
|
|
|
16758
16830
|
[Syntax check failed]: ${syntaxError}`;
|
|
16759
16831
|
return;
|
|
16760
16832
|
}
|
|
16761
|
-
await this.runProjectLint(ctx, result);
|
|
16762
|
-
|
|
16833
|
+
await this.runProjectLint(ctx, result, signal);
|
|
16834
|
+
if (signal?.aborted)
|
|
16835
|
+
return;
|
|
16836
|
+
await this.runProjectTypeCheck(fullPath, ctx.baseDir, result, signal);
|
|
16763
16837
|
}
|
|
16764
|
-
async checkSyntax(filePath, ext, baseDir) {
|
|
16838
|
+
async checkSyntax(filePath, ext, baseDir, signal) {
|
|
16765
16839
|
if (ext === ".ts" || ext === ".tsx" || ext === ".cts" || ext === ".mts") {
|
|
16766
16840
|
let content = "";
|
|
16767
16841
|
try {
|
|
16768
|
-
content =
|
|
16842
|
+
content = readFileSync16(filePath, "utf-8");
|
|
16769
16843
|
} catch {
|
|
16770
16844
|
return null;
|
|
16771
16845
|
}
|
|
@@ -16775,7 +16849,9 @@ class LintOnWritePlugin {
|
|
|
16775
16849
|
return cached.error;
|
|
16776
16850
|
}
|
|
16777
16851
|
try {
|
|
16778
|
-
await runAsync(`bun build --no-bundle --target=bun "${filePath}"`, baseDir, 1e4);
|
|
16852
|
+
await runAsync(`bun build --no-bundle --target=bun "${filePath}"`, baseDir, 1e4, signal);
|
|
16853
|
+
if (signal?.aborted)
|
|
16854
|
+
return null;
|
|
16779
16855
|
syntaxCache.set(filePath, { hash, error: null });
|
|
16780
16856
|
return null;
|
|
16781
16857
|
} catch (err) {
|
|
@@ -16791,7 +16867,7 @@ class LintOnWritePlugin {
|
|
|
16791
16867
|
}
|
|
16792
16868
|
if (ext === ".js" || ext === ".jsx" || ext === ".cjs" || ext === ".mjs") {
|
|
16793
16869
|
try {
|
|
16794
|
-
await runAsync(`node --check "${filePath}"`, baseDir, 5000);
|
|
16870
|
+
await runAsync(`node --check "${filePath}"`, baseDir, 5000, signal);
|
|
16795
16871
|
return null;
|
|
16796
16872
|
} catch (err) {
|
|
16797
16873
|
const stderr = err.stderr?.toString() || "";
|
|
@@ -16802,19 +16878,19 @@ class LintOnWritePlugin {
|
|
|
16802
16878
|
}
|
|
16803
16879
|
return null;
|
|
16804
16880
|
}
|
|
16805
|
-
async runProjectLint(ctx, result) {
|
|
16881
|
+
async runProjectLint(ctx, result, signal) {
|
|
16806
16882
|
try {
|
|
16807
16883
|
const packageJsonPath = join25(ctx.baseDir, "package.json");
|
|
16808
16884
|
if (!existsSync31(packageJsonPath)) {
|
|
16809
16885
|
return;
|
|
16810
16886
|
}
|
|
16811
|
-
const packageJson = JSON.parse(
|
|
16887
|
+
const packageJson = JSON.parse(readFileSync16(packageJsonPath, "utf-8"));
|
|
16812
16888
|
const lintScript = packageJson.scripts?.lint;
|
|
16813
16889
|
if (!lintScript) {
|
|
16814
16890
|
return;
|
|
16815
16891
|
}
|
|
16816
16892
|
ctx.logger.debug(`Running lint: ${lintScript}`);
|
|
16817
|
-
await runAsync(lintScript, ctx.baseDir, 30000);
|
|
16893
|
+
await runAsync(lintScript, ctx.baseDir, 30000, signal);
|
|
16818
16894
|
ctx.logger.debug("Lint passed");
|
|
16819
16895
|
} catch (err) {
|
|
16820
16896
|
const stderr = (err.stderr?.toString?.() || "").trim();
|
|
@@ -16828,7 +16904,7 @@ class LintOnWritePlugin {
|
|
|
16828
16904
|
[Project lint failed]: ${detail}`;
|
|
16829
16905
|
}
|
|
16830
16906
|
}
|
|
16831
|
-
async runProjectTypeCheck(filePath, baseDir, result) {
|
|
16907
|
+
async runProjectTypeCheck(filePath, baseDir, result, signal) {
|
|
16832
16908
|
const projectRoot = findProjectRoot(filePath, baseDir, ["tsconfig.json", "package.json"]);
|
|
16833
16909
|
const tsconfigPath = join25(projectRoot, "tsconfig.json");
|
|
16834
16910
|
if (!existsSync31(tsconfigPath)) {
|
|
@@ -16845,7 +16921,7 @@ class LintOnWritePlugin {
|
|
|
16845
16921
|
return;
|
|
16846
16922
|
}
|
|
16847
16923
|
this._checkTimestamp = now;
|
|
16848
|
-
this._checkPromise = this.runTscCheck(projectRoot);
|
|
16924
|
+
this._checkPromise = this.runTscCheck(projectRoot, signal);
|
|
16849
16925
|
const error = await this._checkPromise;
|
|
16850
16926
|
if (error) {
|
|
16851
16927
|
result.output += `
|
|
@@ -16853,9 +16929,9 @@ class LintOnWritePlugin {
|
|
|
16853
16929
|
[Project typecheck failed]: ${error}`;
|
|
16854
16930
|
}
|
|
16855
16931
|
}
|
|
16856
|
-
async runTscCheck(baseDir) {
|
|
16932
|
+
async runTscCheck(baseDir, signal) {
|
|
16857
16933
|
try {
|
|
16858
|
-
await runAsync(`npx tsc --noEmit --skipLibCheck`, baseDir, 30000);
|
|
16934
|
+
await runAsync(`npx tsc --noEmit --skipLibCheck`, baseDir, 30000, signal);
|
|
16859
16935
|
return null;
|
|
16860
16936
|
} catch (err) {
|
|
16861
16937
|
if (err.status === 127 || err.message.includes("not found") || err.message.includes("ENOENT")) {
|
|
@@ -16871,7 +16947,7 @@ class LintOnWritePlugin {
|
|
|
16871
16947
|
}
|
|
16872
16948
|
}
|
|
16873
16949
|
}
|
|
16874
|
-
function runAsync(command, cwd, timeoutMs) {
|
|
16950
|
+
function runAsync(command, cwd, timeoutMs, signal) {
|
|
16875
16951
|
return new Promise((resolve19, reject) => {
|
|
16876
16952
|
const child = spawn5(command, {
|
|
16877
16953
|
cwd,
|
|
@@ -16892,15 +16968,27 @@ function runAsync(command, cwd, timeoutMs) {
|
|
|
16892
16968
|
child.kill();
|
|
16893
16969
|
reject(new Error(`Command timed out after ${timeoutMs}ms`));
|
|
16894
16970
|
}, timeoutMs);
|
|
16971
|
+
const onAbort = () => child.kill();
|
|
16972
|
+
if (signal?.aborted) {
|
|
16973
|
+
child.kill();
|
|
16974
|
+
} else {
|
|
16975
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
16976
|
+
}
|
|
16895
16977
|
child.on("error", (err) => {
|
|
16896
16978
|
clearTimeout(timer);
|
|
16897
|
-
|
|
16979
|
+
signal?.removeEventListener("abort", onAbort);
|
|
16980
|
+
if (signal?.aborted) {
|
|
16981
|
+
resolve19({ stdout, stderr });
|
|
16982
|
+
} else {
|
|
16983
|
+
reject(err);
|
|
16984
|
+
}
|
|
16898
16985
|
});
|
|
16899
16986
|
child.on("close", (code) => {
|
|
16900
16987
|
clearTimeout(timer);
|
|
16988
|
+
signal?.removeEventListener("abort", onAbort);
|
|
16901
16989
|
stdout += decoder.decode();
|
|
16902
16990
|
stderr += decoder.decode();
|
|
16903
|
-
if (code === 0) {
|
|
16991
|
+
if (signal?.aborted || code === 0) {
|
|
16904
16992
|
resolve19({ stdout, stderr });
|
|
16905
16993
|
} else {
|
|
16906
16994
|
const err = new Error(`Command failed with exit code ${code}`);
|
|
@@ -16944,25 +17032,6 @@ function generatePlanId() {
|
|
|
16944
17032
|
}
|
|
16945
17033
|
|
|
16946
17034
|
class PlanCreator {
|
|
16947
|
-
static isMultiStep(task) {
|
|
16948
|
-
const fileCount = (task.match(/\b[\w./-]+\.[a-z]+\b/gi) || []).length;
|
|
16949
|
-
if (fileCount > 1)
|
|
16950
|
-
return true;
|
|
16951
|
-
const actionWords = [
|
|
16952
|
-
"implement",
|
|
16953
|
-
"create",
|
|
16954
|
-
"add",
|
|
16955
|
-
"build",
|
|
16956
|
-
"setup",
|
|
16957
|
-
"configure",
|
|
16958
|
-
"write",
|
|
16959
|
-
"make",
|
|
16960
|
-
"develop"
|
|
16961
|
-
];
|
|
16962
|
-
const words = task.split(/\s+/);
|
|
16963
|
-
const hasActionWord = actionWords.some((w) => task.toLowerCase().includes(w));
|
|
16964
|
-
return hasActionWord && words.length > 8;
|
|
16965
|
-
}
|
|
16966
17035
|
static createPlan(title, stepDescriptions, baseDir, kinds) {
|
|
16967
17036
|
const stepCount = stepDescriptions.length;
|
|
16968
17037
|
return {
|
|
@@ -16983,16 +17052,17 @@ class PlanCreator {
|
|
|
16983
17052
|
const baseTitle = plan.title.replace(/^\[\d+[^]]*\]\s*/, "");
|
|
16984
17053
|
const newTitle = title || baseTitle;
|
|
16985
17054
|
const totalSteps = kept.length + newSteps.length;
|
|
16986
|
-
const added = newSteps.map((desc
|
|
16987
|
-
id:
|
|
17055
|
+
const added = newSteps.map((desc) => ({
|
|
17056
|
+
id: -1,
|
|
16988
17057
|
description: desc,
|
|
16989
17058
|
status: "pending",
|
|
16990
17059
|
kind: "create"
|
|
16991
17060
|
}));
|
|
17061
|
+
const steps = [...kept, ...added].map((s, i) => ({ ...s, id: i + 1 }));
|
|
16992
17062
|
return {
|
|
16993
17063
|
id: plan.id,
|
|
16994
17064
|
title: `[${totalSteps}] ${newTitle}`,
|
|
16995
|
-
steps
|
|
17065
|
+
steps,
|
|
16996
17066
|
createdAt: plan.createdAt,
|
|
16997
17067
|
baseDir: plan.baseDir,
|
|
16998
17068
|
name: plan.name
|
|
@@ -17000,10 +17070,13 @@ class PlanCreator {
|
|
|
17000
17070
|
}
|
|
17001
17071
|
static toPromptBlock(plan, currentStepIndex) {
|
|
17002
17072
|
const date = plan.createdAt.slice(0, 10);
|
|
17073
|
+
const doneCount = plan.steps.filter((s) => s.status === "done").length;
|
|
17074
|
+
const terminal = plan.steps.every((s) => s.status === "done" || s.status === "skipped");
|
|
17075
|
+
const progress = terminal ? `${doneCount}/${plan.steps.length} done, complete` : `${doneCount}/${plan.steps.length} done, current: step ${currentStepIndex + 1}`;
|
|
17003
17076
|
const lines = [
|
|
17004
17077
|
`[${plan.id}] ${plan.title}`,
|
|
17005
17078
|
`Dir: ${plan.baseDir}`,
|
|
17006
|
-
`Created: ${date} | Progress: ${
|
|
17079
|
+
`Created: ${date} | Progress: ${progress}`,
|
|
17007
17080
|
``
|
|
17008
17081
|
];
|
|
17009
17082
|
for (const step of plan.steps) {
|
|
@@ -17080,11 +17153,11 @@ class PlanTracker {
|
|
|
17080
17153
|
var init_tracker = () => {};
|
|
17081
17154
|
|
|
17082
17155
|
// src/modules/execution/plan-store.ts
|
|
17083
|
-
import { readFileSync as
|
|
17156
|
+
import { readFileSync as readFileSync17, writeFileSync as writeFileSync10, mkdirSync as mkdirSync14, existsSync as existsSync32, readdirSync as readdirSync10, rmSync } from "fs";
|
|
17084
17157
|
import { join as join26 } from "path";
|
|
17085
17158
|
function readPlanFile(path, fallbackBaseDir) {
|
|
17086
17159
|
try {
|
|
17087
|
-
const raw =
|
|
17160
|
+
const raw = readFileSync17(path, "utf-8");
|
|
17088
17161
|
if (!raw.trim())
|
|
17089
17162
|
return null;
|
|
17090
17163
|
const parsed = JSON.parse(raw);
|
|
@@ -17227,6 +17300,41 @@ class PlanStore {
|
|
|
17227
17300
|
return { plan: archived, status: "archived" };
|
|
17228
17301
|
return null;
|
|
17229
17302
|
}
|
|
17303
|
+
deletePlan(id) {
|
|
17304
|
+
const active = this.loadActive();
|
|
17305
|
+
if (active && active.id === id) {
|
|
17306
|
+
this.clearActive();
|
|
17307
|
+
return "active";
|
|
17308
|
+
}
|
|
17309
|
+
const draftPath = join26(this.draftsDir, `${id}.json`);
|
|
17310
|
+
if (existsSync32(draftPath)) {
|
|
17311
|
+
rmSync(draftPath, { force: true });
|
|
17312
|
+
return "draft";
|
|
17313
|
+
}
|
|
17314
|
+
const archivedPath = join26(this.archiveDir, `${id}.json`);
|
|
17315
|
+
if (existsSync32(archivedPath)) {
|
|
17316
|
+
rmSync(archivedPath, { force: true });
|
|
17317
|
+
return "archived";
|
|
17318
|
+
}
|
|
17319
|
+
return null;
|
|
17320
|
+
}
|
|
17321
|
+
purgeAll() {
|
|
17322
|
+
let n = 0;
|
|
17323
|
+
const active = this.loadActive();
|
|
17324
|
+
if (active) {
|
|
17325
|
+
this.clearActive();
|
|
17326
|
+
n++;
|
|
17327
|
+
}
|
|
17328
|
+
for (const p of this.listDrafts()) {
|
|
17329
|
+
this.removeDraft(p.id);
|
|
17330
|
+
n++;
|
|
17331
|
+
}
|
|
17332
|
+
for (const p of this.listArchived()) {
|
|
17333
|
+
this.removeArchived(p.id);
|
|
17334
|
+
n++;
|
|
17335
|
+
}
|
|
17336
|
+
return n;
|
|
17337
|
+
}
|
|
17230
17338
|
}
|
|
17231
17339
|
var LEGACY_FILE = "plan.json";
|
|
17232
17340
|
var init_plan_store = () => {};
|
|
@@ -17300,16 +17408,18 @@ function createPlanToolDefinitions(deps) {
|
|
|
17300
17408
|
{
|
|
17301
17409
|
name: "plan",
|
|
17302
17410
|
alwaysOn: true,
|
|
17303
|
-
description: `Create, update, show, abort, list, switch, or re-plan multi-step plans.
|
|
17411
|
+
description: `Create, update, show, abort, list, switch, delete, purge, or re-plan multi-step plans.
|
|
17304
17412
|
|
|
17305
17413
|
Actions:
|
|
17306
17414
|
- create: Start a new plan. Previous active plan is auto-preserved: incomplete → draft, complete → archive.
|
|
17307
17415
|
- update: Mark step status (done/failed/skipped), or rebuild plan with new steps.
|
|
17308
17416
|
- show: Print current plan checklist.
|
|
17309
|
-
- abort: Archive current plan and clear active slot.
|
|
17417
|
+
- abort: Archive the current plan (or the plan given by id) and clear the active slot.
|
|
17310
17418
|
- list: Show all plans (active, drafts, archived) with progress.
|
|
17311
17419
|
- switch: Make a different plan active (by plan id).
|
|
17312
17420
|
- re-plan: Iterative replanning: keep completed steps, replace remaining with new steps.
|
|
17421
|
+
- delete: Permanently delete a plan by id (plan delete id=plan_xxx).
|
|
17422
|
+
- purge: Delete ALL plans (active, drafts, archived).
|
|
17313
17423
|
|
|
17314
17424
|
Write CONCRETE steps with exact file paths and commands:
|
|
17315
17425
|
- Specify WHICH files to create with exact paths (e.g. "create src/components/Header.tsx with navigation and logo")
|
|
@@ -17324,7 +17434,17 @@ Write CONCRETE steps with exact file paths and commands:
|
|
|
17324
17434
|
properties: {
|
|
17325
17435
|
action: {
|
|
17326
17436
|
type: "string",
|
|
17327
|
-
enum: [
|
|
17437
|
+
enum: [
|
|
17438
|
+
"create",
|
|
17439
|
+
"update",
|
|
17440
|
+
"show",
|
|
17441
|
+
"abort",
|
|
17442
|
+
"list",
|
|
17443
|
+
"switch",
|
|
17444
|
+
"re-plan",
|
|
17445
|
+
"delete",
|
|
17446
|
+
"purge"
|
|
17447
|
+
]
|
|
17328
17448
|
},
|
|
17329
17449
|
title: { type: "string" },
|
|
17330
17450
|
steps: { type: "array", items: { type: "string" } },
|
|
@@ -17352,6 +17472,8 @@ Write CONCRETE steps with exact file paths and commands:
|
|
|
17352
17472
|
const namePart = m.name ? ` (${m.name})` : "";
|
|
17353
17473
|
return `${icon} ${m.id}${namePart} — ${m.title} ${m.doneCount}/${m.stepCount}`;
|
|
17354
17474
|
});
|
|
17475
|
+
lines.push("");
|
|
17476
|
+
lines.push(t("plan.list_legend"));
|
|
17355
17477
|
return {
|
|
17356
17478
|
success: true,
|
|
17357
17479
|
output: `${t("plan.list_header")}
|
|
@@ -17371,6 +17493,16 @@ ${lines.join(`
|
|
|
17371
17493
|
output: t("plan.not_found", { id: planId })
|
|
17372
17494
|
};
|
|
17373
17495
|
}
|
|
17496
|
+
if (found.status === "active") {
|
|
17497
|
+
return {
|
|
17498
|
+
success: true,
|
|
17499
|
+
output: t("plan.already_active", {
|
|
17500
|
+
id: found.plan.id,
|
|
17501
|
+
title: found.plan.title
|
|
17502
|
+
}),
|
|
17503
|
+
display: deps.trackerRef.current?.toPromptBlock()
|
|
17504
|
+
};
|
|
17505
|
+
}
|
|
17374
17506
|
deps.preserveActive();
|
|
17375
17507
|
if (found.status === "draft") {
|
|
17376
17508
|
deps.store.removeDraft(found.plan.id);
|
|
@@ -17378,7 +17510,7 @@ ${lines.join(`
|
|
|
17378
17510
|
deps.store.removeArchived(found.plan.id);
|
|
17379
17511
|
}
|
|
17380
17512
|
deps.setPlan(found.plan);
|
|
17381
|
-
const display =
|
|
17513
|
+
const display = deps.trackerRef.current?.toPromptBlock();
|
|
17382
17514
|
return {
|
|
17383
17515
|
success: true,
|
|
17384
17516
|
output: t("plan.switched", {
|
|
@@ -17401,7 +17533,7 @@ ${lines.join(`
|
|
|
17401
17533
|
const replanned = PlanCreator.replan(oldPlan, newSteps, args.title ? String(args.title) : undefined);
|
|
17402
17534
|
const keptCount = replanned.steps.length - newSteps.length;
|
|
17403
17535
|
deps.setPlan(replanned);
|
|
17404
|
-
const display =
|
|
17536
|
+
const display = deps.trackerRef.current?.toPromptBlock();
|
|
17405
17537
|
return {
|
|
17406
17538
|
success: true,
|
|
17407
17539
|
output: t("plan.replanned", {
|
|
@@ -17514,6 +17646,7 @@ ${display}`,
|
|
|
17514
17646
|
if (tracker.isComplete()) {
|
|
17515
17647
|
const plan = tracker.getPlan();
|
|
17516
17648
|
deps.store.archivePlan(plan);
|
|
17649
|
+
deps.recordCompleted(plan);
|
|
17517
17650
|
deps.trackerRef.current = null;
|
|
17518
17651
|
const done = plan.steps.filter((s) => s.status === "done").length;
|
|
17519
17652
|
return {
|
|
@@ -17580,9 +17713,13 @@ ${progress2}`,
|
|
|
17580
17713
|
tracker.addNote(Number(args.step), String(args.note));
|
|
17581
17714
|
tracker.syncCurrentStep();
|
|
17582
17715
|
deps.store.saveActive(tracker.getPlan());
|
|
17716
|
+
const vacuousGate = status === "done" && !deps.hasStepDeliverables(target);
|
|
17717
|
+
const vacuousNote = vacuousGate ? `
|
|
17718
|
+
${t("plan.no_deliverables", { step: String(stepId) })}` : "";
|
|
17583
17719
|
if (tracker.isComplete()) {
|
|
17584
17720
|
const plan = tracker.getPlan();
|
|
17585
17721
|
deps.store.archivePlan(plan);
|
|
17722
|
+
deps.recordCompleted(plan);
|
|
17586
17723
|
deps.trackerRef.current = null;
|
|
17587
17724
|
const done = plan.steps.filter((s) => s.status === "done").length;
|
|
17588
17725
|
return {
|
|
@@ -17592,7 +17729,7 @@ ${t("plan.completed_archived", {
|
|
|
17592
17729
|
id: plan.id,
|
|
17593
17730
|
done: String(done),
|
|
17594
17731
|
total: String(plan.steps.length)
|
|
17595
|
-
})}`
|
|
17732
|
+
})}${vacuousNote}`
|
|
17596
17733
|
};
|
|
17597
17734
|
}
|
|
17598
17735
|
const progress = tracker.getProgressString();
|
|
@@ -17601,7 +17738,7 @@ ${t("plan.completed_archived", {
|
|
|
17601
17738
|
return {
|
|
17602
17739
|
success: true,
|
|
17603
17740
|
output: `${t("plan.step_status", { step: String(args.step), status: String(args.status || "done") })}
|
|
17604
|
-
${progress}`,
|
|
17741
|
+
${progress}${vacuousNote}`,
|
|
17605
17742
|
display
|
|
17606
17743
|
};
|
|
17607
17744
|
}
|
|
@@ -17615,7 +17752,7 @@ ${progress}`,
|
|
|
17615
17752
|
}
|
|
17616
17753
|
const plan = PlanCreator.createPlan(title, steps, deps.baseDir, parsed.kinds ?? []);
|
|
17617
17754
|
deps.setPlan(plan);
|
|
17618
|
-
const display =
|
|
17755
|
+
const display = deps.trackerRef.current?.toPromptBlock();
|
|
17619
17756
|
const output = t("plan.updated", {
|
|
17620
17757
|
title,
|
|
17621
17758
|
steps: String(steps.length)
|
|
@@ -17627,14 +17764,71 @@ ${progress}`,
|
|
|
17627
17764
|
};
|
|
17628
17765
|
}
|
|
17629
17766
|
if (action === "abort") {
|
|
17767
|
+
const planId = args.id ? String(args.id) : "";
|
|
17768
|
+
if (planId) {
|
|
17769
|
+
const found = deps.store.find(planId);
|
|
17770
|
+
if (!found) {
|
|
17771
|
+
return {
|
|
17772
|
+
success: false,
|
|
17773
|
+
output: t("plan.not_found", { id: planId })
|
|
17774
|
+
};
|
|
17775
|
+
}
|
|
17776
|
+
if (found.status === "archived") {
|
|
17777
|
+
return {
|
|
17778
|
+
success: false,
|
|
17779
|
+
output: t("plan.already_archived", { id: planId })
|
|
17780
|
+
};
|
|
17781
|
+
}
|
|
17782
|
+
deps.store.archivePlan(found.plan);
|
|
17783
|
+
if (found.status === "active") {
|
|
17784
|
+
deps.trackerRef.current = null;
|
|
17785
|
+
deps.clearCompleted();
|
|
17786
|
+
}
|
|
17787
|
+
return {
|
|
17788
|
+
success: true,
|
|
17789
|
+
output: t("plan.aborted_id", { id: found.plan.id })
|
|
17790
|
+
};
|
|
17791
|
+
}
|
|
17630
17792
|
const tracker = deps.trackerRef.current;
|
|
17631
|
-
if (tracker) {
|
|
17632
|
-
|
|
17793
|
+
if (!tracker) {
|
|
17794
|
+
return { success: false, output: t("plan.no_active") };
|
|
17633
17795
|
}
|
|
17796
|
+
deps.store.archivePlan(tracker.getPlan());
|
|
17634
17797
|
deps.trackerRef.current = null;
|
|
17635
17798
|
deps.store.clearActive();
|
|
17799
|
+
deps.clearCompleted();
|
|
17636
17800
|
return { success: true, output: t("plan.aborted") };
|
|
17637
17801
|
}
|
|
17802
|
+
if (action === "delete") {
|
|
17803
|
+
const planId = String(args.id || "");
|
|
17804
|
+
if (!planId) {
|
|
17805
|
+
return { success: false, output: t("plan.delete_no_id") };
|
|
17806
|
+
}
|
|
17807
|
+
const deleted = deps.store.deletePlan(planId);
|
|
17808
|
+
if (!deleted) {
|
|
17809
|
+
return {
|
|
17810
|
+
success: false,
|
|
17811
|
+
output: t("plan.not_found", { id: planId })
|
|
17812
|
+
};
|
|
17813
|
+
}
|
|
17814
|
+
if (deleted === "active") {
|
|
17815
|
+
deps.trackerRef.current = null;
|
|
17816
|
+
deps.clearCompleted();
|
|
17817
|
+
}
|
|
17818
|
+
return {
|
|
17819
|
+
success: true,
|
|
17820
|
+
output: t("plan.deleted", { id: planId })
|
|
17821
|
+
};
|
|
17822
|
+
}
|
|
17823
|
+
if (action === "purge") {
|
|
17824
|
+
const count = deps.store.purgeAll();
|
|
17825
|
+
deps.trackerRef.current = null;
|
|
17826
|
+
deps.clearCompleted();
|
|
17827
|
+
return {
|
|
17828
|
+
success: true,
|
|
17829
|
+
output: t("plan.purged", { count: String(count) })
|
|
17830
|
+
};
|
|
17831
|
+
}
|
|
17638
17832
|
if (!deps.trackerRef.current) {
|
|
17639
17833
|
return { success: false, output: t("plan.no_active") };
|
|
17640
17834
|
}
|
|
@@ -17825,6 +18019,8 @@ function createExecutionPlugin(deps) {
|
|
|
17825
18019
|
deps.state.consecutivePlanWarnings = 0;
|
|
17826
18020
|
deps.state.lastStepId = -1;
|
|
17827
18021
|
deps.state.stuckNotified = false;
|
|
18022
|
+
deps.state.mutationsWithoutPlan = 0;
|
|
18023
|
+
deps.state.planNudgeSent = false;
|
|
17828
18024
|
} else {
|
|
17829
18025
|
const step = deps.trackerRef.current?.getCurrentStep();
|
|
17830
18026
|
if (deps.trackerRef.current && step) {
|
|
@@ -17835,22 +18031,21 @@ function createExecutionPlugin(deps) {
|
|
|
17835
18031
|
}
|
|
17836
18032
|
deps.stuckDetector.setCurrentStep(step.id, step.description);
|
|
17837
18033
|
deps.stuckDetector.recordIteration(step.id);
|
|
18034
|
+
deps.state.mutationsWithoutPlan = 0;
|
|
18035
|
+
deps.state.planNudgeSent = false;
|
|
17838
18036
|
} else {
|
|
17839
18037
|
deps.stuckDetector.reset();
|
|
17840
18038
|
deps.state.consecutivePlanWarnings = 0;
|
|
17841
18039
|
deps.state.lastStepId = -1;
|
|
17842
18040
|
deps.state.stuckNotified = false;
|
|
17843
|
-
const
|
|
17844
|
-
if (
|
|
17845
|
-
|
|
17846
|
-
role: "user",
|
|
17847
|
-
content: `<system-summary>You have made 3 tool calls without creating a plan. For any task that involves creating files, installing packages, or multiple steps — you MUST use plan create BEFORE continuing. Use the plan tool now with concrete steps (exact filenames, commands, deliverables). Do NOT make any more write/edit/bash calls until you have a plan.</system-summary>`
|
|
17848
|
-
});
|
|
17849
|
-
}
|
|
17850
|
-
if (iter >= 6 && !deps.trackerRef.current && ctx.contextManager) {
|
|
18041
|
+
const mutations = deps.state.mutationsWithoutPlan;
|
|
18042
|
+
if (mutations >= PLAN_NUDGE_THRESHOLD && !deps.state.planNudgeSent && ctx.contextManager) {
|
|
18043
|
+
deps.state.planNudgeSent = true;
|
|
17851
18044
|
ctx.contextManager.addMessage({
|
|
17852
18045
|
role: "user",
|
|
17853
|
-
content: `<system-summary
|
|
18046
|
+
content: `<system-summary>${t("exec.plan_nudge", {
|
|
18047
|
+
count: String(mutations)
|
|
18048
|
+
})}</system-summary>`
|
|
17854
18049
|
});
|
|
17855
18050
|
}
|
|
17856
18051
|
}
|
|
@@ -17943,6 +18138,9 @@ Tool "${deps.stuckDetector.getLastFailedTool()}" is failing. Try "${alternative}
|
|
|
17943
18138
|
const args = ctx?.args;
|
|
17944
18139
|
if (toolName && args) {
|
|
17945
18140
|
deps.stuckDetector.recordToolCall(toolName, args);
|
|
18141
|
+
if (!deps.trackerRef.current && (toolName === "write_file" || toolName === "edit_file" || toolName === "bash" || toolName === "download_file")) {
|
|
18142
|
+
deps.state.mutationsWithoutPlan++;
|
|
18143
|
+
}
|
|
17946
18144
|
}
|
|
17947
18145
|
},
|
|
17948
18146
|
onAfterTool: (ctx, call, result) => {
|
|
@@ -18029,7 +18227,7 @@ Tool "${deps.stuckDetector.getLastFailedTool()}" is failing. Try "${alternative}
|
|
|
18029
18227
|
}
|
|
18030
18228
|
};
|
|
18031
18229
|
}
|
|
18032
|
-
var STUCK_RECOVERY_COOLDOWN = 5, MAX_PLAN_WARNINGS_BEFORE_BLOCK = 3, FORCE_SKIP_THRESHOLD = 10;
|
|
18230
|
+
var STUCK_RECOVERY_COOLDOWN = 5, MAX_PLAN_WARNINGS_BEFORE_BLOCK = 3, FORCE_SKIP_THRESHOLD = 10, PLAN_NUDGE_THRESHOLD = 2;
|
|
18033
18231
|
var init_execution_plugin = __esm(() => {
|
|
18034
18232
|
init_i18n();
|
|
18035
18233
|
init_bash();
|
|
@@ -18037,7 +18235,7 @@ var init_execution_plugin = __esm(() => {
|
|
|
18037
18235
|
});
|
|
18038
18236
|
|
|
18039
18237
|
// src/modules/execution/module.ts
|
|
18040
|
-
import { existsSync as existsSync33, readFileSync as
|
|
18238
|
+
import { existsSync as existsSync33, readFileSync as readFileSync18 } from "fs";
|
|
18041
18239
|
import { resolve as resolve19 } from "path";
|
|
18042
18240
|
|
|
18043
18241
|
class ExecutionModule {
|
|
@@ -18049,6 +18247,7 @@ class ExecutionModule {
|
|
|
18049
18247
|
store;
|
|
18050
18248
|
baseDir;
|
|
18051
18249
|
_auditSkipsRemaining = 0;
|
|
18250
|
+
completedPlan = null;
|
|
18052
18251
|
pendingMessages = [];
|
|
18053
18252
|
forbiddenBashFailures = new Map;
|
|
18054
18253
|
searchRunner;
|
|
@@ -18062,7 +18261,9 @@ class ExecutionModule {
|
|
|
18062
18261
|
consecutivePlanWarnings: 0,
|
|
18063
18262
|
lastStepId: -1,
|
|
18064
18263
|
stuckNotified: false,
|
|
18065
|
-
depsGateHints: new Map
|
|
18264
|
+
depsGateHints: new Map,
|
|
18265
|
+
mutationsWithoutPlan: 0,
|
|
18266
|
+
planNudgeSent: false
|
|
18066
18267
|
};
|
|
18067
18268
|
trackerRef = (() => {
|
|
18068
18269
|
const self = this;
|
|
@@ -18087,9 +18288,17 @@ class ExecutionModule {
|
|
|
18087
18288
|
}
|
|
18088
18289
|
setPlan(plan) {
|
|
18089
18290
|
this.tracker = new PlanTracker(plan);
|
|
18291
|
+
this.tracker.syncCurrentStep();
|
|
18090
18292
|
this.store.saveActive(plan);
|
|
18293
|
+
this.completedPlan = null;
|
|
18091
18294
|
this._auditSkipsRemaining = 0;
|
|
18092
18295
|
}
|
|
18296
|
+
recordCompleted(plan) {
|
|
18297
|
+
this.completedPlan = plan;
|
|
18298
|
+
}
|
|
18299
|
+
clearCompleted() {
|
|
18300
|
+
this.completedPlan = null;
|
|
18301
|
+
}
|
|
18093
18302
|
restorePlan() {
|
|
18094
18303
|
const plan = this.store.loadActive();
|
|
18095
18304
|
if (!plan)
|
|
@@ -18167,8 +18376,22 @@ class ExecutionModule {
|
|
|
18167
18376
|
}).catch((e) => ctx.logger?.warn(`error web search: ${e.message}`));
|
|
18168
18377
|
}
|
|
18169
18378
|
async runFinalAudit() {
|
|
18170
|
-
if (!this.tracker)
|
|
18171
|
-
|
|
18379
|
+
if (!this.tracker) {
|
|
18380
|
+
if (!this.completedPlan)
|
|
18381
|
+
return null;
|
|
18382
|
+
const plan2 = this.completedPlan;
|
|
18383
|
+
const audit2 = await this.auditor.audit(plan2);
|
|
18384
|
+
const pendingSteps2 = plan2.steps.flatMap((s) => s.status !== "done" && s.status !== "skipped" ? [`${s.id}. ${s.description}`] : []);
|
|
18385
|
+
const done2 = plan2.steps.filter((s) => s.status === "done").length;
|
|
18386
|
+
return {
|
|
18387
|
+
passed: audit2.passed && pendingSteps2.length === 0,
|
|
18388
|
+
done: done2,
|
|
18389
|
+
total: plan2.steps.length,
|
|
18390
|
+
pendingSteps: pendingSteps2,
|
|
18391
|
+
missingFiles: audit2.missingFiles,
|
|
18392
|
+
summary: audit2.summary
|
|
18393
|
+
};
|
|
18394
|
+
}
|
|
18172
18395
|
if (this._auditSkipsRemaining > 0) {
|
|
18173
18396
|
this._auditSkipsRemaining--;
|
|
18174
18397
|
return null;
|
|
@@ -18216,6 +18439,9 @@ class ExecutionModule {
|
|
|
18216
18439
|
trackerRef: this.trackerRef,
|
|
18217
18440
|
preserveActive: () => this.preserveActive(),
|
|
18218
18441
|
setPlan: (p) => this.setPlan(p),
|
|
18442
|
+
recordCompleted: (p) => this.recordCompleted(p),
|
|
18443
|
+
clearCompleted: () => this.clearCompleted(),
|
|
18444
|
+
hasStepDeliverables: (s) => this.hasStepDeliverables(s),
|
|
18219
18445
|
missingStepDeliverables: (s) => this.missingStepDeliverables(s),
|
|
18220
18446
|
stillExistingDeliverables: (s) => this.stillExistingDeliverables(s),
|
|
18221
18447
|
parseKinds: (a, st) => this.parseKinds(a, st),
|
|
@@ -18267,7 +18493,7 @@ class ExecutionModule {
|
|
|
18267
18493
|
const stepPaths = extractFileLikeTokens(stripUrls(step.description)).map((p) => p.toLowerCase());
|
|
18268
18494
|
if (stepPaths.length === 0)
|
|
18269
18495
|
return null;
|
|
18270
|
-
const argStr =
|
|
18496
|
+
const argStr = this.pathArgStrings(call.arguments).join(" ");
|
|
18271
18497
|
const callPaths = extractFileLikeTokens(stripUrls(argStr)).map((p) => p.toLowerCase());
|
|
18272
18498
|
if (callPaths.length === 0)
|
|
18273
18499
|
return null;
|
|
@@ -18292,13 +18518,31 @@ class ExecutionModule {
|
|
|
18292
18518
|
tool: call.name
|
|
18293
18519
|
});
|
|
18294
18520
|
}
|
|
18521
|
+
pathArgStrings(args) {
|
|
18522
|
+
if (!args)
|
|
18523
|
+
return [];
|
|
18524
|
+
const out = [];
|
|
18525
|
+
for (const [key, value] of Object.entries(args)) {
|
|
18526
|
+
if (!/path|file|dir|src|dst|source|target|input|output|destination|glob|workdir|cwd|command|pattern|query/i.test(key)) {
|
|
18527
|
+
continue;
|
|
18528
|
+
}
|
|
18529
|
+
if (typeof value === "string")
|
|
18530
|
+
out.push(value);
|
|
18531
|
+
else if (Array.isArray(value)) {
|
|
18532
|
+
for (const v of value)
|
|
18533
|
+
if (typeof v === "string")
|
|
18534
|
+
out.push(v);
|
|
18535
|
+
}
|
|
18536
|
+
}
|
|
18537
|
+
return out;
|
|
18538
|
+
}
|
|
18295
18539
|
advancePlanIfStepComplete(contextManager, sessionLog) {
|
|
18296
18540
|
const step = this.tracker?.getCurrentStep();
|
|
18297
18541
|
if (!step)
|
|
18298
18542
|
return;
|
|
18299
18543
|
const stepText = step.description.toLowerCase();
|
|
18300
18544
|
const stepPaths = extractFileLikeTokens(stripUrls(step.description)) || [];
|
|
18301
|
-
const isDepsStep =
|
|
18545
|
+
const isDepsStep = /(?:npm|bun|yarn|pnpm|pip|pip3|pipenv|poetry|composer|deno|go|gem|cargo)\s+(?:install|add|init|i|get)\b|bun\s+(?:add|install)|npm\s+(?:i|install|add)|(?:install|установ\w*)\s+(?:dependencies|зависимост\w*|пакет\w*|packages?)/i.test(stepText);
|
|
18302
18546
|
if (isDepsStep) {
|
|
18303
18547
|
const lockFiles = [
|
|
18304
18548
|
"package-lock.json",
|
|
@@ -18332,18 +18576,21 @@ class ExecutionModule {
|
|
|
18332
18576
|
}
|
|
18333
18577
|
if (stepPaths.length === 0)
|
|
18334
18578
|
return;
|
|
18335
|
-
const
|
|
18336
|
-
const
|
|
18579
|
+
const resolved = stepPaths.map((p) => findExistingFile(this.baseDir, p));
|
|
18580
|
+
const allExist = resolved.every((r) => r !== null);
|
|
18581
|
+
const allGone = resolved.every((r) => r === null);
|
|
18337
18582
|
const satisfied = step.kind === "delete" ? allGone && !allExist : allExist;
|
|
18338
18583
|
if (!satisfied)
|
|
18339
18584
|
return;
|
|
18340
18585
|
if (step.kind !== "delete") {
|
|
18341
18586
|
const emptyFiles = [];
|
|
18342
|
-
for (const
|
|
18587
|
+
for (const r of resolved) {
|
|
18588
|
+
if (!r)
|
|
18589
|
+
continue;
|
|
18343
18590
|
try {
|
|
18344
|
-
const content =
|
|
18591
|
+
const content = readFileSync18(r, "utf-8");
|
|
18345
18592
|
if (content.trim().length < 10) {
|
|
18346
|
-
emptyFiles.push(
|
|
18593
|
+
emptyFiles.push(r);
|
|
18347
18594
|
}
|
|
18348
18595
|
} catch {}
|
|
18349
18596
|
}
|
|
@@ -18376,6 +18623,7 @@ class ExecutionModule {
|
|
|
18376
18623
|
if (this.tracker?.isComplete()) {
|
|
18377
18624
|
const completed = this.tracker.getPlan();
|
|
18378
18625
|
this.store.archivePlan(completed);
|
|
18626
|
+
this.recordCompleted(completed);
|
|
18379
18627
|
this.tracker = null;
|
|
18380
18628
|
sessionLog?.plan("auto-archive", `Plan ${completed.id} complete — archived`);
|
|
18381
18629
|
}
|
|
@@ -18392,6 +18640,9 @@ class ExecutionModule {
|
|
|
18392
18640
|
return [];
|
|
18393
18641
|
return tokens.filter((p) => findExistingFile(this.baseDir, p));
|
|
18394
18642
|
}
|
|
18643
|
+
hasStepDeliverables(step) {
|
|
18644
|
+
return extractFileLikeTokens(stripUrls(step.description)).length > 0;
|
|
18645
|
+
}
|
|
18395
18646
|
parseKinds(args, steps) {
|
|
18396
18647
|
if (args.kinds === undefined)
|
|
18397
18648
|
return { kinds: null, error: null };
|
|
@@ -18445,7 +18696,7 @@ var init_module = __esm(() => {
|
|
|
18445
18696
|
});
|
|
18446
18697
|
|
|
18447
18698
|
// src/modules/security/session-encryption.ts
|
|
18448
|
-
import { readFileSync as
|
|
18699
|
+
import { readFileSync as readFileSync19, writeFileSync as writeFileSync11, existsSync as existsSync34, readdirSync as readdirSync11, unlinkSync as unlinkSync4 } from "fs";
|
|
18449
18700
|
import { join as join27 } from "path";
|
|
18450
18701
|
import { homedir as homedir8 } from "os";
|
|
18451
18702
|
|
|
@@ -18500,7 +18751,7 @@ class SessionFileEncryptor {
|
|
|
18500
18751
|
return lines.map((line) => this.decryptFileContent(line));
|
|
18501
18752
|
}
|
|
18502
18753
|
readSessionFile(filePath) {
|
|
18503
|
-
const content =
|
|
18754
|
+
const content = readFileSync19(filePath, "utf8");
|
|
18504
18755
|
return this.decryptFileContent(content);
|
|
18505
18756
|
}
|
|
18506
18757
|
writeSessionFile(filePath, content) {
|
|
@@ -18508,7 +18759,7 @@ class SessionFileEncryptor {
|
|
|
18508
18759
|
writeFileSync11(filePath, encrypted, "utf8");
|
|
18509
18760
|
}
|
|
18510
18761
|
readSessionJSON(filePath) {
|
|
18511
|
-
const content =
|
|
18762
|
+
const content = readFileSync19(filePath, "utf8");
|
|
18512
18763
|
return this.decryptJSON(content);
|
|
18513
18764
|
}
|
|
18514
18765
|
writeSessionJSON(filePath, obj) {
|
|
@@ -18516,7 +18767,7 @@ class SessionFileEncryptor {
|
|
|
18516
18767
|
writeFileSync11(filePath, content, "utf8");
|
|
18517
18768
|
}
|
|
18518
18769
|
readSessionJSONL(filePath) {
|
|
18519
|
-
const content =
|
|
18770
|
+
const content = readFileSync19(filePath, "utf8");
|
|
18520
18771
|
const lines = content.split(`
|
|
18521
18772
|
`).filter((line) => line.trim());
|
|
18522
18773
|
const decryptedLines = this.decryptJSONL(lines);
|
|
@@ -18544,7 +18795,7 @@ class SessionFileEncryptor {
|
|
|
18544
18795
|
const filePath = join27(sessionDir, file);
|
|
18545
18796
|
if (existsSync34(filePath) && !file.endsWith(".enc")) {
|
|
18546
18797
|
try {
|
|
18547
|
-
const content =
|
|
18798
|
+
const content = readFileSync19(filePath, "utf8");
|
|
18548
18799
|
const encrypted = this.encryptFileContent(content);
|
|
18549
18800
|
writeFileSync11(filePath + ".enc", encrypted, "utf8");
|
|
18550
18801
|
unlinkSync4(filePath);
|
|
@@ -18561,7 +18812,7 @@ class SessionFileEncryptor {
|
|
|
18561
18812
|
const encFilePath = join27(sessionDir, file);
|
|
18562
18813
|
const decFilePath = encFilePath.slice(0, -4);
|
|
18563
18814
|
try {
|
|
18564
|
-
const content =
|
|
18815
|
+
const content = readFileSync19(encFilePath, "utf8");
|
|
18565
18816
|
const decrypted = this.decryptFileContent(content);
|
|
18566
18817
|
writeFileSync11(decFilePath, decrypted, "utf8");
|
|
18567
18818
|
unlinkSync4(encFilePath);
|
|
@@ -18586,7 +18837,7 @@ import {
|
|
|
18586
18837
|
existsSync as existsSync35,
|
|
18587
18838
|
mkdirSync as mkdirSync15,
|
|
18588
18839
|
readdirSync as readdirSync12,
|
|
18589
|
-
readFileSync as
|
|
18840
|
+
readFileSync as readFileSync20,
|
|
18590
18841
|
rmSync as rmSync2,
|
|
18591
18842
|
writeFileSync as writeFileSync12,
|
|
18592
18843
|
appendFileSync as appendFileSync6
|
|
@@ -18654,7 +18905,7 @@ class SessionStore {
|
|
|
18654
18905
|
if (!existsSync35(path))
|
|
18655
18906
|
return null;
|
|
18656
18907
|
try {
|
|
18657
|
-
const raw =
|
|
18908
|
+
const raw = readFileSync20(path, "utf-8");
|
|
18658
18909
|
const content = this.encryptor ? this.encryptor.decryptFileContent(raw) : raw;
|
|
18659
18910
|
const meta = JSON.parse(content);
|
|
18660
18911
|
this._metaCache.set(id, meta);
|
|
@@ -18686,7 +18937,7 @@ class SessionStore {
|
|
|
18686
18937
|
if (!existsSync35(path))
|
|
18687
18938
|
return [];
|
|
18688
18939
|
try {
|
|
18689
|
-
const raw =
|
|
18940
|
+
const raw = readFileSync20(path, "utf-8");
|
|
18690
18941
|
const lines = raw.split(`
|
|
18691
18942
|
`).filter(Boolean);
|
|
18692
18943
|
const parseLine = (line) => {
|
|
@@ -18727,7 +18978,7 @@ class SessionStore {
|
|
|
18727
18978
|
if (!existsSync35(path))
|
|
18728
18979
|
return [];
|
|
18729
18980
|
try {
|
|
18730
|
-
const raw =
|
|
18981
|
+
const raw = readFileSync20(path, "utf-8");
|
|
18731
18982
|
const lines = raw.split(`
|
|
18732
18983
|
`).filter(Boolean);
|
|
18733
18984
|
const parseLine = (line) => {
|
|
@@ -18782,7 +19033,7 @@ class SessionStore {
|
|
|
18782
19033
|
if (updatedAt < thirtyDaysAgo) {
|
|
18783
19034
|
const historyPath = this.historyPath(session2.id);
|
|
18784
19035
|
if (existsSync35(historyPath)) {
|
|
18785
|
-
const content =
|
|
19036
|
+
const content = readFileSync20(historyPath, "utf-8");
|
|
18786
19037
|
const compressed = gzipSync(content);
|
|
18787
19038
|
const gzPath = join28(this.baseDir, `${session2.id}.jsonl.gz`);
|
|
18788
19039
|
writeFileSync12(gzPath, compressed);
|
|
@@ -18994,7 +19245,7 @@ class ProfileCompressor {
|
|
|
18994
19245
|
}
|
|
18995
19246
|
|
|
18996
19247
|
// src/modules/user-profile/profile.ts
|
|
18997
|
-
import { readFileSync as
|
|
19248
|
+
import { readFileSync as readFileSync21, writeFileSync as writeFileSync13, existsSync as existsSync36, mkdirSync as mkdirSync16 } from "fs";
|
|
18998
19249
|
import { join as join29 } from "path";
|
|
18999
19250
|
import { homedir as homedir9, hostname, platform as platform7, type } from "os";
|
|
19000
19251
|
import { env } from "process";
|
|
@@ -19029,7 +19280,7 @@ class UserProfile {
|
|
|
19029
19280
|
if (!existsSync36(path))
|
|
19030
19281
|
return null;
|
|
19031
19282
|
try {
|
|
19032
|
-
const data = JSON.parse(
|
|
19283
|
+
const data = JSON.parse(readFileSync21(path, "utf-8"));
|
|
19033
19284
|
this.info = {
|
|
19034
19285
|
platform: data.platform,
|
|
19035
19286
|
os: data.os,
|
|
@@ -19064,7 +19315,7 @@ class UserProfile {
|
|
|
19064
19315
|
var init_profile = () => {};
|
|
19065
19316
|
|
|
19066
19317
|
// src/modules/skills/loader.ts
|
|
19067
|
-
import { readdirSync as readdirSync13, readFileSync as
|
|
19318
|
+
import { readdirSync as readdirSync13, readFileSync as readFileSync22, existsSync as existsSync37, statSync as statSync6 } from "fs";
|
|
19068
19319
|
import { join as join30 } from "path";
|
|
19069
19320
|
|
|
19070
19321
|
class SkillsLoader {
|
|
@@ -19086,7 +19337,7 @@ class SkillsLoader {
|
|
|
19086
19337
|
}
|
|
19087
19338
|
if (!entry.endsWith(".md") && !entry.endsWith(".skill.md"))
|
|
19088
19339
|
continue;
|
|
19089
|
-
const content =
|
|
19340
|
+
const content = readFileSync22(fullPath, "utf-8");
|
|
19090
19341
|
const parsed = this.parseSkillFile(content, fullPath);
|
|
19091
19342
|
if (parsed)
|
|
19092
19343
|
skills.push(parsed);
|
|
@@ -19988,7 +20239,7 @@ var init_startup_check = __esm(() => {
|
|
|
19988
20239
|
});
|
|
19989
20240
|
|
|
19990
20241
|
// src/modules/indexer/walker.ts
|
|
19991
|
-
import { readdirSync as readdirSync14, readFileSync as
|
|
20242
|
+
import { readdirSync as readdirSync14, readFileSync as readFileSync23, statSync as statSync7, existsSync as existsSync40, watch } from "fs";
|
|
19992
20243
|
import { join as join32, relative as relative4, extname as extname5 } from "path";
|
|
19993
20244
|
|
|
19994
20245
|
class Indexer {
|
|
@@ -20038,7 +20289,7 @@ class Indexer {
|
|
|
20038
20289
|
const ext = extname5(entry).toLowerCase();
|
|
20039
20290
|
const language = LANGUAGES[ext];
|
|
20040
20291
|
if (language) {
|
|
20041
|
-
const content =
|
|
20292
|
+
const content = readFileSync23(fullPath, "utf-8");
|
|
20042
20293
|
const exports = this.extractExports(content, language);
|
|
20043
20294
|
files.push({ path: relPath, language, exports, size: stat2.size });
|
|
20044
20295
|
totalSize += stat2.size;
|
|
@@ -20090,7 +20341,7 @@ var init_walker = __esm(() => {
|
|
|
20090
20341
|
});
|
|
20091
20342
|
|
|
20092
20343
|
// src/modules/indexer/cache.ts
|
|
20093
|
-
import { readFileSync as
|
|
20344
|
+
import { readFileSync as readFileSync24, writeFileSync as writeFileSync14, existsSync as existsSync41, mkdirSync as mkdirSync17, rmSync as rmSync3 } from "fs";
|
|
20094
20345
|
import { join as join33 } from "path";
|
|
20095
20346
|
|
|
20096
20347
|
class IndexCache {
|
|
@@ -20105,7 +20356,7 @@ class IndexCache {
|
|
|
20105
20356
|
if (!existsSync41(this.cachePath))
|
|
20106
20357
|
return null;
|
|
20107
20358
|
try {
|
|
20108
|
-
this.cache = JSON.parse(
|
|
20359
|
+
this.cache = JSON.parse(readFileSync24(this.cachePath, "utf-8"));
|
|
20109
20360
|
return this.cache;
|
|
20110
20361
|
} catch {
|
|
20111
20362
|
return null;
|
|
@@ -20130,7 +20381,7 @@ class IndexCache {
|
|
|
20130
20381
|
var init_cache = () => {};
|
|
20131
20382
|
|
|
20132
20383
|
// src/modules/indexer/project-profile.ts
|
|
20133
|
-
import { readFileSync as
|
|
20384
|
+
import { readFileSync as readFileSync25, existsSync as existsSync42 } from "fs";
|
|
20134
20385
|
import { join as join34 } from "path";
|
|
20135
20386
|
function detectManifest(baseDir) {
|
|
20136
20387
|
for (const manifest of MANIFEST_ORDER) {
|
|
@@ -20151,7 +20402,7 @@ function cleanDependency(entry) {
|
|
|
20151
20402
|
}
|
|
20152
20403
|
function readPackageJson(baseDir) {
|
|
20153
20404
|
try {
|
|
20154
|
-
const raw = JSON.parse(
|
|
20405
|
+
const raw = JSON.parse(readFileSync25(join34(baseDir, "package.json"), "utf-8"));
|
|
20155
20406
|
if (!raw || typeof raw !== "object")
|
|
20156
20407
|
return null;
|
|
20157
20408
|
const profile = {
|
|
@@ -20175,7 +20426,7 @@ function readPackageJson(baseDir) {
|
|
|
20175
20426
|
}
|
|
20176
20427
|
function readPyproject(baseDir) {
|
|
20177
20428
|
try {
|
|
20178
|
-
const content =
|
|
20429
|
+
const content = readFileSync25(join34(baseDir, "pyproject.toml"), "utf-8");
|
|
20179
20430
|
const profile = { runtime: "python", deps: [], devDeps: [], scripts: {} };
|
|
20180
20431
|
const nameMatch = content.match(/^\s*name\s*=\s*"([^"]+)"/m);
|
|
20181
20432
|
if (nameMatch)
|
|
@@ -20191,7 +20442,7 @@ function readPyproject(baseDir) {
|
|
|
20191
20442
|
}
|
|
20192
20443
|
function readCargo(baseDir) {
|
|
20193
20444
|
try {
|
|
20194
|
-
const content =
|
|
20445
|
+
const content = readFileSync25(join34(baseDir, "Cargo.toml"), "utf-8");
|
|
20195
20446
|
const profile = { runtime: "rust", deps: [], devDeps: [], scripts: {} };
|
|
20196
20447
|
const nameMatch = content.match(/^\s*name\s*=\s*"([^"]+)"/m);
|
|
20197
20448
|
if (nameMatch)
|
|
@@ -20215,7 +20466,7 @@ function readCargo(baseDir) {
|
|
|
20215
20466
|
}
|
|
20216
20467
|
function readGoMod(baseDir) {
|
|
20217
20468
|
try {
|
|
20218
|
-
const content =
|
|
20469
|
+
const content = readFileSync25(join34(baseDir, "go.mod"), "utf-8");
|
|
20219
20470
|
const profile = { runtime: "go", deps: [], devDeps: [], scripts: {} };
|
|
20220
20471
|
const moduleMatch = content.match(/^module\s+(\S+)/m);
|
|
20221
20472
|
if (moduleMatch)
|
|
@@ -20233,7 +20484,7 @@ function readGoMod(baseDir) {
|
|
|
20233
20484
|
}
|
|
20234
20485
|
function readRequirements(baseDir) {
|
|
20235
20486
|
try {
|
|
20236
|
-
const content =
|
|
20487
|
+
const content = readFileSync25(join34(baseDir, "requirements.txt"), "utf-8");
|
|
20237
20488
|
const profile = { runtime: "python", deps: [], devDeps: [], scripts: {} };
|
|
20238
20489
|
for (const line of content.split(`
|
|
20239
20490
|
`)) {
|
|
@@ -20786,7 +21037,7 @@ var init_module8 = __esm(() => {
|
|
|
20786
21037
|
});
|
|
20787
21038
|
|
|
20788
21039
|
// src/core/version.ts
|
|
20789
|
-
import { existsSync as existsSync43, readFileSync as
|
|
21040
|
+
import { existsSync as existsSync43, readFileSync as readFileSync26 } from "fs";
|
|
20790
21041
|
import { join as join36, dirname as dirname13 } from "path";
|
|
20791
21042
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
20792
21043
|
function readMmaVersion() {
|
|
@@ -20795,7 +21046,7 @@ function readMmaVersion() {
|
|
|
20795
21046
|
for (const p of candidates) {
|
|
20796
21047
|
if (existsSync43(p)) {
|
|
20797
21048
|
try {
|
|
20798
|
-
const raw = JSON.parse(
|
|
21049
|
+
const raw = JSON.parse(readFileSync26(p, "utf8"));
|
|
20799
21050
|
if (raw.version)
|
|
20800
21051
|
return raw.version;
|
|
20801
21052
|
} catch {}
|
|
@@ -20813,7 +21064,7 @@ __export(exports_bootstrap, {
|
|
|
20813
21064
|
});
|
|
20814
21065
|
import { homedir as homedir11 } from "os";
|
|
20815
21066
|
import { join as join37, resolve as resolve23 } from "path";
|
|
20816
|
-
import { existsSync as existsSync44, readFileSync as
|
|
21067
|
+
import { existsSync as existsSync44, readFileSync as readFileSync27, writeFileSync as writeFileSync15 } from "fs";
|
|
20817
21068
|
function buildSystemInfo(config, baseDir, profileCompressed) {
|
|
20818
21069
|
const now = new Date().toISOString().replace("T", " ").slice(0, 19);
|
|
20819
21070
|
const isWin = profileCompressed.toLowerCase().includes("win32");
|
|
@@ -21073,7 +21324,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
21073
21324
|
];
|
|
21074
21325
|
for (const p of agentsMdCandidates) {
|
|
21075
21326
|
if (existsSync44(p)) {
|
|
21076
|
-
const content =
|
|
21327
|
+
const content = readFileSync27(p, "utf-8").trim();
|
|
21077
21328
|
if (content) {
|
|
21078
21329
|
agentsMdBlocks.push({
|
|
21079
21330
|
content,
|
|
@@ -21937,13 +22188,13 @@ __export(exports_manifest, {
|
|
|
21937
22188
|
getCertMark: () => getCertMark,
|
|
21938
22189
|
MANIFEST_PATH: () => MANIFEST_PATH
|
|
21939
22190
|
});
|
|
21940
|
-
import { existsSync as existsSync45, readFileSync as
|
|
22191
|
+
import { existsSync as existsSync45, readFileSync as readFileSync28, mkdirSync as mkdirSync18, writeFileSync as writeFileSync16 } from "fs";
|
|
21941
22192
|
import { homedir as homedir13 } from "os";
|
|
21942
22193
|
import { join as join39 } from "path";
|
|
21943
22194
|
function readManifest(path = MANIFEST_PATH) {
|
|
21944
22195
|
try {
|
|
21945
22196
|
if (existsSync45(path)) {
|
|
21946
|
-
const raw = JSON.parse(
|
|
22197
|
+
const raw = JSON.parse(readFileSync28(path, "utf-8"));
|
|
21947
22198
|
return { version: 1, certifications: raw.certifications ?? [] };
|
|
21948
22199
|
}
|
|
21949
22200
|
} catch {}
|
|
@@ -29108,7 +29359,7 @@ var init_scenarios = __esm(() => {
|
|
|
29108
29359
|
});
|
|
29109
29360
|
|
|
29110
29361
|
// src/modules/certification/loader.ts
|
|
29111
|
-
import { existsSync as existsSync46, readdirSync as readdirSync15, readFileSync as
|
|
29362
|
+
import { existsSync as existsSync46, readdirSync as readdirSync15, readFileSync as readFileSync29 } from "fs";
|
|
29112
29363
|
import { join as join40 } from "path";
|
|
29113
29364
|
function validateScenario(s) {
|
|
29114
29365
|
const errors2 = [];
|
|
@@ -29163,7 +29414,7 @@ function loadScenarios(userDir) {
|
|
|
29163
29414
|
if (!file.endsWith(".yaml") && !file.endsWith(".yml"))
|
|
29164
29415
|
continue;
|
|
29165
29416
|
try {
|
|
29166
|
-
const raw =
|
|
29417
|
+
const raw = readFileSync29(join40(userDir, file), "utf-8");
|
|
29167
29418
|
const data = $parse(raw);
|
|
29168
29419
|
const parsed = normalizeScenario(data, file);
|
|
29169
29420
|
const errs = validateScenario(parsed);
|
|
@@ -29216,7 +29467,7 @@ var init_loader3 = __esm(() => {
|
|
|
29216
29467
|
});
|
|
29217
29468
|
|
|
29218
29469
|
// src/modules/certification/fact-checker.ts
|
|
29219
|
-
import { existsSync as existsSync47, readFileSync as
|
|
29470
|
+
import { existsSync as existsSync47, readFileSync as readFileSync30, statSync as statSync8 } from "fs";
|
|
29220
29471
|
import { join as join41 } from "path";
|
|
29221
29472
|
function checkSandbox(sandboxDir, checks, exitCode, output) {
|
|
29222
29473
|
const failures = [];
|
|
@@ -29243,7 +29494,7 @@ function runCheck2(sandboxDir, check, exitCode, output) {
|
|
|
29243
29494
|
const abs = join41(sandboxDir, check.path);
|
|
29244
29495
|
if (!isFile(abs))
|
|
29245
29496
|
return false;
|
|
29246
|
-
const content =
|
|
29497
|
+
const content = readFileSync30(abs, "utf-8");
|
|
29247
29498
|
if (check.contains !== undefined)
|
|
29248
29499
|
return content.includes(check.contains);
|
|
29249
29500
|
if (check.equals !== undefined)
|
|
@@ -29254,7 +29505,7 @@ function runCheck2(sandboxDir, check, exitCode, output) {
|
|
|
29254
29505
|
const abs = join41(sandboxDir, check.path);
|
|
29255
29506
|
if (!isFile(abs))
|
|
29256
29507
|
return false;
|
|
29257
|
-
return new RegExp(check.pattern).test(
|
|
29508
|
+
return new RegExp(check.pattern).test(readFileSync30(abs, "utf-8"));
|
|
29258
29509
|
}
|
|
29259
29510
|
default:
|
|
29260
29511
|
return false;
|
|
@@ -29470,13 +29721,13 @@ import { rmSync as rmSync5 } from "fs";
|
|
|
29470
29721
|
import { homedir as homedir14 } from "os";
|
|
29471
29722
|
import { join as join43, dirname as dirname15 } from "path";
|
|
29472
29723
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
29473
|
-
import { existsSync as existsSync49, readFileSync as
|
|
29724
|
+
import { existsSync as existsSync49, readFileSync as readFileSync31 } from "fs";
|
|
29474
29725
|
function readVersion() {
|
|
29475
29726
|
const candidates = [join43(MMA_ROOT, "package.json")];
|
|
29476
29727
|
for (const p of candidates) {
|
|
29477
29728
|
if (existsSync49(p)) {
|
|
29478
29729
|
try {
|
|
29479
|
-
const raw = JSON.parse(
|
|
29730
|
+
const raw = JSON.parse(readFileSync31(p, "utf-8"));
|
|
29480
29731
|
if (raw.version)
|
|
29481
29732
|
return raw.version;
|
|
29482
29733
|
} catch {}
|
|
@@ -29637,7 +29888,7 @@ __export(exports_repl_commands, {
|
|
|
29637
29888
|
});
|
|
29638
29889
|
import { join as join45, dirname as dirname17 } from "path";
|
|
29639
29890
|
import { homedir as homedir16 } from "os";
|
|
29640
|
-
import { existsSync as existsSync51, readFileSync as
|
|
29891
|
+
import { existsSync as existsSync51, readFileSync as readFileSync33 } from "fs";
|
|
29641
29892
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
29642
29893
|
function readVersion3() {
|
|
29643
29894
|
const here = dirname17(fileURLToPath5(import.meta.url));
|
|
@@ -29645,7 +29896,7 @@ function readVersion3() {
|
|
|
29645
29896
|
for (const p of candidates) {
|
|
29646
29897
|
if (existsSync51(p)) {
|
|
29647
29898
|
try {
|
|
29648
|
-
const raw = JSON.parse(
|
|
29899
|
+
const raw = JSON.parse(readFileSync33(p, "utf8"));
|
|
29649
29900
|
if (raw.version)
|
|
29650
29901
|
return raw.version;
|
|
29651
29902
|
} catch {}
|
|
@@ -30303,7 +30554,7 @@ init_setup();
|
|
|
30303
30554
|
init_i18n();
|
|
30304
30555
|
import { join as join44, dirname as dirname16 } from "path";
|
|
30305
30556
|
import { homedir as homedir15 } from "os";
|
|
30306
|
-
import { existsSync as existsSync50, readFileSync as
|
|
30557
|
+
import { existsSync as existsSync50, readFileSync as readFileSync32 } from "fs";
|
|
30307
30558
|
|
|
30308
30559
|
// src/cli/security-commands.ts
|
|
30309
30560
|
init_bootstrap();
|
|
@@ -30945,7 +31196,7 @@ function readVersion2() {
|
|
|
30945
31196
|
for (const p of candidates) {
|
|
30946
31197
|
if (existsSync50(p)) {
|
|
30947
31198
|
try {
|
|
30948
|
-
const raw = JSON.parse(
|
|
31199
|
+
const raw = JSON.parse(readFileSync32(p, "utf8"));
|
|
30949
31200
|
if (raw.version)
|
|
30950
31201
|
return raw.version;
|
|
30951
31202
|
} catch {}
|
|
@@ -31928,7 +32179,7 @@ class LineEditor {
|
|
|
31928
32179
|
}
|
|
31929
32180
|
|
|
31930
32181
|
// src/cli/repl.ts
|
|
31931
|
-
import { existsSync as existsSync53, readFileSync as
|
|
32182
|
+
import { existsSync as existsSync53, readFileSync as readFileSync35, writeFileSync as writeFileSync17 } from "fs";
|
|
31932
32183
|
import { join as join47, dirname as dirname18 } from "path";
|
|
31933
32184
|
import { homedir as homedir17 } from "os";
|
|
31934
32185
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
@@ -32517,14 +32768,14 @@ init_config();
|
|
|
32517
32768
|
init_colors();
|
|
32518
32769
|
init_js_identifiers();
|
|
32519
32770
|
init_i18n();
|
|
32520
|
-
import { existsSync as existsSync52, readFileSync as
|
|
32771
|
+
import { existsSync as existsSync52, readFileSync as readFileSync34 } from "fs";
|
|
32521
32772
|
import { join as join46 } from "path";
|
|
32522
32773
|
function readActivePlan(baseDir) {
|
|
32523
32774
|
const p = join46(baseDir, ".mma", "plans", "active.json");
|
|
32524
32775
|
if (!existsSync52(p))
|
|
32525
32776
|
return null;
|
|
32526
32777
|
try {
|
|
32527
|
-
const raw =
|
|
32778
|
+
const raw = readFileSync34(p, "utf-8");
|
|
32528
32779
|
if (!raw.trim())
|
|
32529
32780
|
return null;
|
|
32530
32781
|
const parsed = JSON.parse(raw);
|
|
@@ -32623,7 +32874,7 @@ function readVersion4() {
|
|
|
32623
32874
|
for (const p of candidates) {
|
|
32624
32875
|
if (existsSync53(p)) {
|
|
32625
32876
|
try {
|
|
32626
|
-
const raw = JSON.parse(
|
|
32877
|
+
const raw = JSON.parse(readFileSync35(p, "utf8"));
|
|
32627
32878
|
if (raw.version)
|
|
32628
32879
|
return raw.version;
|
|
32629
32880
|
} catch {}
|
|
@@ -32719,7 +32970,7 @@ class Repl {
|
|
|
32719
32970
|
loadHistory() {
|
|
32720
32971
|
if (existsSync53(this.historyPath)) {
|
|
32721
32972
|
try {
|
|
32722
|
-
const raw =
|
|
32973
|
+
const raw = readFileSync35(this.historyPath, "utf-8");
|
|
32723
32974
|
this.history = raw.split(`
|
|
32724
32975
|
`).filter(Boolean).slice(-this.maxHistory);
|
|
32725
32976
|
} catch {
|
|
@@ -33192,7 +33443,7 @@ init_setup();
|
|
|
33192
33443
|
init_config2();
|
|
33193
33444
|
init_i18n();
|
|
33194
33445
|
init_colors();
|
|
33195
|
-
import { existsSync as existsSync54, readFileSync as
|
|
33446
|
+
import { existsSync as existsSync54, readFileSync as readFileSync36 } from "fs";
|
|
33196
33447
|
import { join as join48, dirname as dirname19 } from "path";
|
|
33197
33448
|
import { homedir as homedir18 } from "os";
|
|
33198
33449
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
@@ -33301,7 +33552,7 @@ function readVersion5() {
|
|
|
33301
33552
|
for (const p of candidates) {
|
|
33302
33553
|
if (existsSync54(p)) {
|
|
33303
33554
|
try {
|
|
33304
|
-
const raw = JSON.parse(
|
|
33555
|
+
const raw = JSON.parse(readFileSync36(p, "utf8"));
|
|
33305
33556
|
if (raw.version)
|
|
33306
33557
|
return raw.version;
|
|
33307
33558
|
} catch {}
|