micro-models-agent 0.50.0 → 0.50.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 +132 -40
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -1991,7 +1991,6 @@ var init_security = __esm(() => {
|
|
|
1991
1991
|
"python",
|
|
1992
1992
|
"python3",
|
|
1993
1993
|
"node",
|
|
1994
|
-
"bun",
|
|
1995
1994
|
"perl",
|
|
1996
1995
|
"ruby",
|
|
1997
1996
|
"del",
|
|
@@ -2013,8 +2012,6 @@ var init_security = __esm(() => {
|
|
|
2013
2012
|
"--delete",
|
|
2014
2013
|
"--remove",
|
|
2015
2014
|
"--dangerous",
|
|
2016
|
-
"--yes",
|
|
2017
|
-
"-y",
|
|
2018
2015
|
"--no-confirm"
|
|
2019
2016
|
],
|
|
2020
2017
|
dangerousOperators: [">", ">>", "2>", "2>>", ";", "&&", "||", "|", "`", "$("]
|
|
@@ -2539,6 +2536,8 @@ Command: {command}`,
|
|
|
2539
2536
|
{lines}`,
|
|
2540
2537
|
"proc.none": "No background processes running.",
|
|
2541
2538
|
"proc.not_found": "Process not found: {id}",
|
|
2539
|
+
"proc.missing_id": "Provide the process id: process_kill id=proc_xxx (the id is returned by bash when a command goes to the background, or by process_list).",
|
|
2540
|
+
"proc.missing_id_list": "No background processes are currently running.",
|
|
2542
2541
|
"proc.killed": "Process {id} (PID {pid}) killed.",
|
|
2543
2542
|
"proc.kill_failed": "Failed to kill process {id}",
|
|
2544
2543
|
"proc.list_header": "Background processes",
|
|
@@ -2595,6 +2594,8 @@ Fix the error and re-edit the file (a clean write clears the failure), or mark t
|
|
|
2595
2594
|
"plan.deleted": "Plan {id} deleted permanently.",
|
|
2596
2595
|
"plan.purged": "Deleted {count} plan(s). Plan storage is empty.",
|
|
2597
2596
|
"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.",
|
|
2597
|
+
"plan.bulk_update_rejected": 'Bulk steps[] rewrite via action=update is not supported: it would discard all step statuses. Use "re-plan" (keeps completed steps, replaces the rest) or mark steps individually: plan update step=N status=done|failed|skipped.',
|
|
2598
|
+
"plan.readonly": 'Plan {id} is {status} (read-only) — it cannot be updated. Use "plan switch" to activate it, or create a new plan for new work.',
|
|
2598
2599
|
"plan.list_legend": "[*] active · [ ] draft · [-] archived",
|
|
2599
2600
|
"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.",
|
|
2600
2601
|
"todo.added": "Added {count} todo(s): {items}",
|
|
@@ -2941,6 +2942,7 @@ Apply a matching solution from these results. If none is relevant — do NOT rep
|
|
|
2941
2942
|
"exec.error_search_failed": 'Web search returned nothing for "{query}".',
|
|
2942
2943
|
"exec.error_search_no_query": "Error output is not meaningful — skipping the web search.",
|
|
2943
2944
|
"exec.npm_exec_hint": '"could not determine executable to run" — no "bin" for that package/script. Use "npm run <script>" (script must exist in package.json) or "bunx <pkg>" for a package that declares a bin.',
|
|
2945
|
+
"exec.hidden_tool_hint": '"{tool}" is not a shell command — it is an MMA tool that is currently hidden. Call the enable_tools tool with tags ["shell"] to unlock it; it becomes available on the next iteration.',
|
|
2944
2946
|
"exec.task_reminder": "Task: {task}. Continue making progress — do not repeat failed actions.",
|
|
2945
2947
|
"hall.max_retries_exhausted": "Model returned empty or insufficient responses after multiple retries",
|
|
2946
2948
|
"hall.short_response": "Response too short or empty",
|
|
@@ -3248,6 +3250,8 @@ var init_ru = __esm(() => {
|
|
|
3248
3250
|
{lines}`,
|
|
3249
3251
|
"proc.none": "Фоновых процессов нет.",
|
|
3250
3252
|
"proc.not_found": "Процесс не найден: {id}",
|
|
3253
|
+
"proc.missing_id": "Укажите id процесса: process_kill id=proc_xxx (id возвращается bash при уходе команды в фон или выводится через process_list).",
|
|
3254
|
+
"proc.missing_id_list": "Сейчас фоновых процессов нет.",
|
|
3251
3255
|
"proc.killed": "Процесс {id} (PID {pid}) остановлен.",
|
|
3252
3256
|
"proc.kill_failed": "Не удалось остановить процесс {id}",
|
|
3253
3257
|
"proc.list_header": "Фоновые процессы",
|
|
@@ -3304,6 +3308,8 @@ var init_ru = __esm(() => {
|
|
|
3304
3308
|
"plan.deleted": "План {id} удалён окончательно.",
|
|
3305
3309
|
"plan.purged": "Удалено планов: {count}. Хранилище планов пусто.",
|
|
3306
3310
|
"plan.no_deliverables": "примечание: шаг {step} не называет файлов — его выполнение нельзя проверить автоматически; перед финальным ответом явно проверь результат (например, запусти сборку/тесты).",
|
|
3311
|
+
"plan.bulk_update_rejected": 'Массовая перезапись steps[] через action=update не поддерживается: она бы стёрла статусы всех шагов. Используй "re-plan" (сохраняет завершённые шаги, заменяет остальные) или отмечай шаги по одному: plan update step=N status=done|failed|skipped.',
|
|
3312
|
+
"plan.readonly": 'План {id} имеет статус {status} (только чтение) — обновить его нельзя. Используй "plan switch", чтобы активировать его, или создай новый план для новой задачи.',
|
|
3307
3313
|
"plan.list_legend": "[*] активный · [ ] черновик · [-] архив",
|
|
3308
3314
|
"exec.plan_nudge": "Ты сделал(а) {count} вызов(ов), изменяющих файлы, без плана. Для задач, создающих/изменяющих файлы или состоящих из нескольких шагов, сначала создай план (plan create) с конкретными шагами (точные имена файлов, команды, результаты), а потом продолжай.",
|
|
3309
3315
|
"todo.added": "Добавлено {count} задач: {items}",
|
|
@@ -3650,6 +3656,7 @@ var init_ru = __esm(() => {
|
|
|
3650
3656
|
"exec.error_search_failed": 'Поиск в интернете для "{query}" ничего не дал.',
|
|
3651
3657
|
"exec.error_search_no_query": "Текст ошибки незначимый — поиск в интернете пропущен.",
|
|
3652
3658
|
"exec.npm_exec_hint": '"could not determine executable to run" — у пакета/скрипта нет "bin". Используй "npm run <script>" (скрипт должен быть в package.json) или "bunx <pkg>" для пакета с объявленным bin.',
|
|
3659
|
+
"exec.hidden_tool_hint": '"{tool}" — не команда оболочки, это инструмент MMA, который сейчас скрыт. Вызови тул enable_tools с tags ["shell"], чтобы включить его; он станет доступен на следующей итерации.',
|
|
3653
3660
|
"exec.task_reminder": "Задача: {task}. Продолжай работу — не повторяй неудачные действия.",
|
|
3654
3661
|
"hall.max_retries_exhausted": "Модель вернула пустой или недостаточный ответ после нескольких попыток",
|
|
3655
3662
|
"hall.short_response": "Слишком короткий или пустой ответ",
|
|
@@ -4200,22 +4207,6 @@ function normalizeLspServerArgs(config) {
|
|
|
4200
4207
|
}
|
|
4201
4208
|
}
|
|
4202
4209
|
}
|
|
4203
|
-
function normalizeStaleSecurityConfig(config) {
|
|
4204
|
-
const sec = config.security;
|
|
4205
|
-
if (!sec || sec.enabled !== false)
|
|
4206
|
-
return;
|
|
4207
|
-
const bash = sec.bash;
|
|
4208
|
-
if (!bash || bash.enabled !== false || bash.blockDangerousFlags !== false)
|
|
4209
|
-
return;
|
|
4210
|
-
const LEGACY_OPERATORS = [">", ">>", "2>", "2>>", "`"];
|
|
4211
|
-
if (JSON.stringify(bash.dangerousOperators ?? []) !== JSON.stringify(LEGACY_OPERATORS))
|
|
4212
|
-
return;
|
|
4213
|
-
const defaultCmds = new Set(DEFAULT_SECURITY_CONFIG.bash.blacklist);
|
|
4214
|
-
const blacklist = Array.isArray(bash.blacklist) ? bash.blacklist : [];
|
|
4215
|
-
if (blacklist.some((cmd) => !defaultCmds.has(cmd)))
|
|
4216
|
-
return;
|
|
4217
|
-
config.security = JSON.parse(JSON.stringify(DEFAULT_SECURITY_CONFIG));
|
|
4218
|
-
}
|
|
4219
4210
|
function loadJSON(path) {
|
|
4220
4211
|
try {
|
|
4221
4212
|
if (existsSync4(path)) {
|
|
@@ -4289,7 +4280,6 @@ function loadConfig(options) {
|
|
|
4289
4280
|
config.security.contentScan.dangerousPatterns = restoreDangerousPatterns(config.security.contentScan.dangerousPatterns, DEFAULT_SECURITY_CONFIG.contentScan.dangerousPatterns);
|
|
4290
4281
|
}
|
|
4291
4282
|
normalizeLspServerArgs(config);
|
|
4292
|
-
normalizeStaleSecurityConfig(config);
|
|
4293
4283
|
config = applyEnvVars(config);
|
|
4294
4284
|
try {
|
|
4295
4285
|
const encryptor = new ConfigEncryptor;
|
|
@@ -8628,7 +8618,7 @@ Hint: ${t("exec.npm_exec_hint")}`;
|
|
|
8628
8618
|
}
|
|
8629
8619
|
return output;
|
|
8630
8620
|
}
|
|
8631
|
-
var BASH_GRACE_MS = 5000, SPAWN_SETTLE_MS = 100, BG_OUTPUT_PREVIEW_LINES = 15, bashGraceMs, FAILING_FIRST_WORDS, HARD_BLOCK_THRESHOLD = 3, UNIX_TO_WIN_HINTS, UNIX_TO_WIN_TRANSLATE, NEVER_TOOL_CALLS, CLI_FILE_RUN_RE, NPM_EXEC_RE, bashTool;
|
|
8621
|
+
var BASH_GRACE_MS = 5000, SPAWN_SETTLE_MS = 100, BG_OUTPUT_PREVIEW_LINES = 15, bashGraceMs, FAILING_FIRST_WORDS, HARD_BLOCK_THRESHOLD = 3, UNIX_TO_WIN_HINTS, UNIX_TO_WIN_TRANSLATE, NEVER_TOOL_CALLS, CLI_FILE_RUN_RE, NPM_EXEC_RE, HIDDEN_PROCESS_TOOLS, bashTool;
|
|
8632
8622
|
var init_bash = __esm(() => {
|
|
8633
8623
|
init_command_validator();
|
|
8634
8624
|
init_audit_log();
|
|
@@ -8694,6 +8684,7 @@ var init_bash = __esm(() => {
|
|
|
8694
8684
|
]);
|
|
8695
8685
|
CLI_FILE_RUN_RE = /\b(bun|node|deno|python|python3|tsx|ts-node|php|ruby|go\s+run)\S*\s+(run\s+)?["']?[\w./\\-]+\.(ts|js|tsx|jsx|mjs|cjs|py)\b/;
|
|
8696
8686
|
NPM_EXEC_RE = /could not determine executable to run/i;
|
|
8687
|
+
HIDDEN_PROCESS_TOOLS = ["process_list", "process_log", "process_kill"];
|
|
8697
8688
|
bashTool = {
|
|
8698
8689
|
name: "bash",
|
|
8699
8690
|
icon: "\uD83D\uDCBB",
|
|
@@ -8728,6 +8719,13 @@ ${redirected.output}`
|
|
|
8728
8719
|
};
|
|
8729
8720
|
}
|
|
8730
8721
|
const command = adaptCommandForWindows(originalCommand);
|
|
8722
|
+
const baseCmd = originalCommand.trim().split(/\s+/)[0];
|
|
8723
|
+
if (HIDDEN_PROCESS_TOOLS.includes(baseCmd) && ctx.toolExecutor?.hasTool?.(baseCmd)) {
|
|
8724
|
+
return {
|
|
8725
|
+
success: false,
|
|
8726
|
+
output: t("exec.hidden_tool_hint", { tool: baseCmd })
|
|
8727
|
+
};
|
|
8728
|
+
}
|
|
8731
8729
|
if (platform2() === "win32") {
|
|
8732
8730
|
const echoWrite = extractEchoFileWrite(originalCommand);
|
|
8733
8731
|
if (echoWrite) {
|
|
@@ -8930,6 +8928,14 @@ var init_process_log = __esm(() => {
|
|
|
8930
8928
|
required: ["id"]
|
|
8931
8929
|
},
|
|
8932
8930
|
handler: async (ctx, args) => {
|
|
8931
|
+
if (args.id === undefined || String(args.id).trim() === "") {
|
|
8932
|
+
const known = processRegistry.list();
|
|
8933
|
+
const ids = known.map((p) => p.id);
|
|
8934
|
+
const listPart = ids.length ? `
|
|
8935
|
+
${t("proc.list_header")}: ${ids.join(", ")}` : `
|
|
8936
|
+
${t("proc.missing_id_list")}`;
|
|
8937
|
+
return { success: false, output: `${t("proc.missing_id")}${listPart}` };
|
|
8938
|
+
}
|
|
8933
8939
|
const id = String(args.id);
|
|
8934
8940
|
const entry = processRegistry.get(id);
|
|
8935
8941
|
if (!entry) {
|
|
@@ -8971,6 +8977,14 @@ var init_process_kill = __esm(() => {
|
|
|
8971
8977
|
required: ["id"]
|
|
8972
8978
|
},
|
|
8973
8979
|
handler: async (ctx, args) => {
|
|
8980
|
+
if (args.id === undefined || String(args.id).trim() === "") {
|
|
8981
|
+
const known = processRegistry.list();
|
|
8982
|
+
const ids = known.map((p) => p.id);
|
|
8983
|
+
const listPart = ids.length ? `
|
|
8984
|
+
${t("proc.list_header")}: ${ids.join(", ")}` : `
|
|
8985
|
+
${t("proc.missing_id_list")}`;
|
|
8986
|
+
return { success: false, output: `${t("proc.missing_id")}${listPart}` };
|
|
8987
|
+
}
|
|
8974
8988
|
const id = String(args.id);
|
|
8975
8989
|
const entry = processRegistry.get(id);
|
|
8976
8990
|
if (!entry) {
|
|
@@ -10580,6 +10594,12 @@ class StuckDetector {
|
|
|
10580
10594
|
this.consecutiveFailures = 0;
|
|
10581
10595
|
this.lastFailedTool = "";
|
|
10582
10596
|
this.escalationCount = 0;
|
|
10597
|
+
for (const [tool, count] of this.toolErrors) {
|
|
10598
|
+
if (count <= 1)
|
|
10599
|
+
this.toolErrors.delete(tool);
|
|
10600
|
+
else
|
|
10601
|
+
this.toolErrors.set(tool, count - 1);
|
|
10602
|
+
}
|
|
10583
10603
|
if (this.iterationsOnCurrentStep > 0) {
|
|
10584
10604
|
this.iterationsOnCurrentStep = Math.max(0, this.iterationsOnCurrentStep - 1);
|
|
10585
10605
|
}
|
|
@@ -10770,6 +10790,20 @@ class StuckDetector {
|
|
|
10770
10790
|
count: this.repetitionThreshold
|
|
10771
10791
|
});
|
|
10772
10792
|
}
|
|
10793
|
+
getWarningKey() {
|
|
10794
|
+
if (this.isStuck())
|
|
10795
|
+
return "stuck";
|
|
10796
|
+
const errorTool = Array.from(this.toolErrors.entries()).find(([_, c]) => c >= this.errorThreshold);
|
|
10797
|
+
if (errorTool)
|
|
10798
|
+
return `tool-errors:${errorTool[0]}`;
|
|
10799
|
+
if (this.hasConsecutiveFailures())
|
|
10800
|
+
return "consecutive";
|
|
10801
|
+
if (this.hasRepetitiveToolCalls())
|
|
10802
|
+
return "repetitive";
|
|
10803
|
+
if (this.hasReadOnlyLoop())
|
|
10804
|
+
return "read-only";
|
|
10805
|
+
return "";
|
|
10806
|
+
}
|
|
10773
10807
|
getStuckReason() {
|
|
10774
10808
|
if (this.isStuck()) {
|
|
10775
10809
|
return t("exec.stuck", {
|
|
@@ -18034,6 +18068,16 @@ import { spawn as spawn6, execSync } from "child_process";
|
|
|
18034
18068
|
import { existsSync as existsSync32, readFileSync as readFileSync17 } from "fs";
|
|
18035
18069
|
import { resolve as resolve18, extname as extname4, join as join26 } from "path";
|
|
18036
18070
|
import { platform as platform5 } from "os";
|
|
18071
|
+
function lintCacheKey(baseDir, lintScript) {
|
|
18072
|
+
return `${baseDir}::${lintScript}`;
|
|
18073
|
+
}
|
|
18074
|
+
function isMissingBinaryError(err, combinedOutput) {
|
|
18075
|
+
if (err.status === 127)
|
|
18076
|
+
return true;
|
|
18077
|
+
if (err.code === "ENOENT")
|
|
18078
|
+
return true;
|
|
18079
|
+
return MISSING_BINARY_RE.test(combinedOutput);
|
|
18080
|
+
}
|
|
18037
18081
|
function contentHash(content) {
|
|
18038
18082
|
let h = 5381;
|
|
18039
18083
|
for (let i = 0;i < content.length; i++) {
|
|
@@ -18143,23 +18187,35 @@ class LintOnWritePlugin {
|
|
|
18143
18187
|
return null;
|
|
18144
18188
|
}
|
|
18145
18189
|
async runProjectLint(ctx, result, signal) {
|
|
18190
|
+
let lintScript;
|
|
18146
18191
|
try {
|
|
18147
18192
|
const packageJsonPath = join26(ctx.baseDir, "package.json");
|
|
18148
18193
|
if (!existsSync32(packageJsonPath)) {
|
|
18149
18194
|
return;
|
|
18150
18195
|
}
|
|
18151
18196
|
const packageJson = JSON.parse(readFileSync17(packageJsonPath, "utf-8"));
|
|
18152
|
-
|
|
18197
|
+
lintScript = packageJson.scripts?.lint;
|
|
18153
18198
|
if (!lintScript) {
|
|
18154
18199
|
return;
|
|
18155
18200
|
}
|
|
18201
|
+
if (missingLintBinaries.has(lintCacheKey(ctx.baseDir, lintScript))) {
|
|
18202
|
+
ctx.logger.debug(`Lint skipped (linter for "${lintScript}" not installed)`);
|
|
18203
|
+
return;
|
|
18204
|
+
}
|
|
18156
18205
|
ctx.logger.debug(`Running lint: ${lintScript}`);
|
|
18157
18206
|
await runAsync(lintScript, ctx.baseDir, 30000, signal);
|
|
18158
18207
|
ctx.logger.debug("Lint passed");
|
|
18159
18208
|
} catch (err) {
|
|
18160
18209
|
const stderr = (err.stderr?.toString?.() || "").trim();
|
|
18161
18210
|
const stdout = (err.stdout?.toString?.() || "").trim();
|
|
18162
|
-
const
|
|
18211
|
+
const combined = `${stderr}
|
|
18212
|
+
${stdout}`;
|
|
18213
|
+
if (lintScript && isMissingBinaryError(err, combined)) {
|
|
18214
|
+
missingLintBinaries.add(lintCacheKey(ctx.baseDir, lintScript));
|
|
18215
|
+
ctx.logger.debug(`Lint binary missing — skipping project lint for this session`);
|
|
18216
|
+
return;
|
|
18217
|
+
}
|
|
18218
|
+
const detail = combined.trim().split(`
|
|
18163
18219
|
`).filter(Boolean).slice(-5).join(`
|
|
18164
18220
|
`);
|
|
18165
18221
|
ctx.logger.warn(`Lint failed: ${err.message}`);
|
|
@@ -18264,9 +18320,11 @@ function runAsync(command, cwd, timeoutMs, signal) {
|
|
|
18264
18320
|
});
|
|
18265
18321
|
});
|
|
18266
18322
|
}
|
|
18267
|
-
var TYPE_CHECK_DEBOUNCE_MS = 2000, syntaxCache, _winDecoder, plugin;
|
|
18323
|
+
var TYPE_CHECK_DEBOUNCE_MS = 2000, missingLintBinaries, MISSING_BINARY_RE, syntaxCache, _winDecoder, plugin;
|
|
18268
18324
|
var init_lint_on_write = __esm(() => {
|
|
18269
18325
|
init_project_root();
|
|
18326
|
+
missingLintBinaries = new Set;
|
|
18327
|
+
MISSING_BINARY_RE = /command not found|not recognized|не является внутренней|не распознан|не є внутрішньою|".+?" не является/i;
|
|
18270
18328
|
syntaxCache = new Map;
|
|
18271
18329
|
plugin = new LintOnWritePlugin;
|
|
18272
18330
|
});
|
|
@@ -18294,6 +18352,13 @@ function generatePlanId() {
|
|
|
18294
18352
|
}
|
|
18295
18353
|
return `plan_${id}`;
|
|
18296
18354
|
}
|
|
18355
|
+
function getPlanProgress(plan) {
|
|
18356
|
+
const done = plan.steps.filter((s) => s.status === "done").length;
|
|
18357
|
+
const skipped = plan.steps.filter((s) => s.status === "skipped").length;
|
|
18358
|
+
const total = plan.steps.length;
|
|
18359
|
+
const settled = done + skipped;
|
|
18360
|
+
return { done, skipped, total, settled, terminal: total > 0 && settled === total };
|
|
18361
|
+
}
|
|
18297
18362
|
|
|
18298
18363
|
class PlanCreator {
|
|
18299
18364
|
static createPlan(title, stepDescriptions, baseDir, kinds) {
|
|
@@ -18334,9 +18399,9 @@ class PlanCreator {
|
|
|
18334
18399
|
}
|
|
18335
18400
|
static toPromptBlock(plan, currentStepIndex) {
|
|
18336
18401
|
const date = plan.createdAt.slice(0, 10);
|
|
18337
|
-
const
|
|
18338
|
-
const
|
|
18339
|
-
const progress = terminal ? `${
|
|
18402
|
+
const p = getPlanProgress(plan);
|
|
18403
|
+
const skippedPart = p.skipped > 0 ? `, ${p.skipped} skipped` : "";
|
|
18404
|
+
const progress = p.terminal ? `${p.settled}/${p.total} done${skippedPart}, complete` : `${p.settled}/${p.total} done${skippedPart}, current: step ${currentStepIndex + 1}`;
|
|
18340
18405
|
const lines = [
|
|
18341
18406
|
`[${plan.id}] ${plan.title}`,
|
|
18342
18407
|
`Dir: ${plan.baseDir}`,
|
|
@@ -18402,13 +18467,15 @@ class PlanTracker {
|
|
|
18402
18467
|
return this.plan.steps.every((s) => s.status === "done" || s.status === "skipped");
|
|
18403
18468
|
}
|
|
18404
18469
|
getProgressString() {
|
|
18405
|
-
const
|
|
18406
|
-
const total =
|
|
18407
|
-
const
|
|
18470
|
+
const p = getPlanProgress(this.plan);
|
|
18471
|
+
const total = p.total;
|
|
18472
|
+
const settled = p.settled;
|
|
18473
|
+
const pct = total > 0 ? Math.round(settled / total * 100) : 0;
|
|
18408
18474
|
const barWidth = 10;
|
|
18409
|
-
const filled = Math.round(
|
|
18475
|
+
const filled = Math.round(settled / total * barWidth);
|
|
18410
18476
|
const bar = "█".repeat(filled) + "░".repeat(barWidth - filled);
|
|
18411
|
-
|
|
18477
|
+
const skippedPart = p.skipped > 0 ? ` (${p.skipped} skipped)` : "";
|
|
18478
|
+
return `[${this.plan.id}] ${this.plan.title} ${settled}/${total}${skippedPart} ${bar} ${pct}%`;
|
|
18412
18479
|
}
|
|
18413
18480
|
toPromptBlock() {
|
|
18414
18481
|
return PlanCreator.toPromptBlock(this.plan, this.currentStepIndex);
|
|
@@ -18786,13 +18853,20 @@ function createExecutionPlugin(deps) {
|
|
|
18786
18853
|
}
|
|
18787
18854
|
const stuckReason = deps.stuckDetector.getStuckReason();
|
|
18788
18855
|
if (stuckReason) {
|
|
18789
|
-
const
|
|
18856
|
+
const isStuck = deps.stuckDetector.isStuck();
|
|
18857
|
+
const warnKey = deps.stuckDetector.getWarningKey();
|
|
18858
|
+
const iter = typeof ctx.iteration === "number" ? ctx.iteration : 0;
|
|
18859
|
+
const logIt = isStuck ? !deps.state.stuckNotified : warnKey !== deps.state.lastStuckWarnKey || iter - deps.state.lastStuckWarnIter >= STUCK_WARN_REPEAT_EVERY;
|
|
18790
18860
|
if (logIt) {
|
|
18791
18861
|
ctx.logger?.warn(stuckReason);
|
|
18792
18862
|
ctx.sessionLog?.plan("stuck-warning", stuckReason, typeof ctx.iteration === "number" ? ctx.iteration : undefined);
|
|
18793
|
-
|
|
18863
|
+
deps.state.lastStuckWarnKey = warnKey;
|
|
18864
|
+
deps.state.lastStuckWarnIter = iter;
|
|
18865
|
+
if (isStuck)
|
|
18794
18866
|
deps.state.stuckNotified = true;
|
|
18795
18867
|
}
|
|
18868
|
+
} else {
|
|
18869
|
+
deps.state.lastStuckWarnKey = "";
|
|
18796
18870
|
}
|
|
18797
18871
|
if (deps.stuckDetector.isStuck() || deps.stuckDetector.hasRepetitiveToolCalls() || deps.stuckDetector.hasReadOnlyLoop()) {
|
|
18798
18872
|
const currentIter = typeof ctx.iteration === "number" ? ctx.iteration : 0;
|
|
@@ -18973,7 +19047,7 @@ Last compile error: ${first[1]}`;
|
|
|
18973
19047
|
}
|
|
18974
19048
|
};
|
|
18975
19049
|
}
|
|
18976
|
-
var STUCK_RECOVERY_COOLDOWN = 5, MAX_PLAN_WARNINGS_BEFORE_BLOCK = 3, FORCE_SKIP_THRESHOLD = 10, PLAN_NUDGE_THRESHOLD = 2;
|
|
19050
|
+
var STUCK_RECOVERY_COOLDOWN = 5, MAX_PLAN_WARNINGS_BEFORE_BLOCK = 3, FORCE_SKIP_THRESHOLD = 10, STUCK_WARN_REPEAT_EVERY = 5, PLAN_NUDGE_THRESHOLD = 2;
|
|
18977
19051
|
var init_execution_plugin = __esm(() => {
|
|
18978
19052
|
init_i18n();
|
|
18979
19053
|
init_bash();
|
|
@@ -19228,12 +19302,12 @@ ${display}`,
|
|
|
19228
19302
|
deps.store.archivePlan(plan);
|
|
19229
19303
|
deps.recordCompleted(plan);
|
|
19230
19304
|
deps.trackerRef.current = null;
|
|
19231
|
-
const
|
|
19305
|
+
const p = getPlanProgress(plan);
|
|
19232
19306
|
return {
|
|
19233
19307
|
success: true,
|
|
19234
19308
|
output: t("plan.completed_archived", {
|
|
19235
19309
|
id: plan.id,
|
|
19236
|
-
done: String(
|
|
19310
|
+
done: String(p.settled),
|
|
19237
19311
|
total: String(plan.steps.length)
|
|
19238
19312
|
})
|
|
19239
19313
|
};
|
|
@@ -19327,13 +19401,13 @@ ${t("plan.no_deliverables", { step: String(stepId) })}` : "";
|
|
|
19327
19401
|
deps.store.archivePlan(plan);
|
|
19328
19402
|
deps.recordCompleted(plan);
|
|
19329
19403
|
deps.trackerRef.current = null;
|
|
19330
|
-
const
|
|
19404
|
+
const p = getPlanProgress(plan);
|
|
19331
19405
|
return {
|
|
19332
19406
|
success: true,
|
|
19333
19407
|
output: `${t("plan.step_status", { step: String(args.step), status: String(args.status || "done") })}
|
|
19334
19408
|
${t("plan.completed_archived", {
|
|
19335
19409
|
id: plan.id,
|
|
19336
|
-
done: String(
|
|
19410
|
+
done: String(p.settled),
|
|
19337
19411
|
total: String(plan.steps.length)
|
|
19338
19412
|
})}${vacuousNote}`
|
|
19339
19413
|
};
|
|
@@ -19348,8 +19422,15 @@ ${progress}${vacuousNote}`,
|
|
|
19348
19422
|
display
|
|
19349
19423
|
};
|
|
19350
19424
|
}
|
|
19351
|
-
if (action === "update" && Array.isArray(args.steps) && args.steps.length > 0 &&
|
|
19425
|
+
if (action === "update" && Array.isArray(args.steps) && args.steps.length > 0 && !args.step) {
|
|
19352
19426
|
const tracker = deps.trackerRef.current;
|
|
19427
|
+
if (!tracker) {
|
|
19428
|
+
return { success: false, output: t("plan.no_active") };
|
|
19429
|
+
}
|
|
19430
|
+
const progressed = tracker.getPlan().steps.some((s) => s.status !== "pending");
|
|
19431
|
+
if (progressed) {
|
|
19432
|
+
return { success: false, output: t("plan.bulk_update_rejected") };
|
|
19433
|
+
}
|
|
19353
19434
|
const title = String(args.title || tracker.getPlan().title);
|
|
19354
19435
|
const steps = args.steps.map(String);
|
|
19355
19436
|
const parsed = deps.parseKinds(args, steps);
|
|
@@ -19436,6 +19517,15 @@ ${progress}${vacuousNote}`,
|
|
|
19436
19517
|
};
|
|
19437
19518
|
}
|
|
19438
19519
|
if (!deps.trackerRef.current) {
|
|
19520
|
+
if (args.id) {
|
|
19521
|
+
const found = deps.store.find(String(args.id));
|
|
19522
|
+
if (found && found.status !== "active") {
|
|
19523
|
+
return {
|
|
19524
|
+
success: false,
|
|
19525
|
+
output: t("plan.readonly", { id: found.plan.id, status: found.status })
|
|
19526
|
+
};
|
|
19527
|
+
}
|
|
19528
|
+
}
|
|
19439
19529
|
return { success: false, output: t("plan.no_active") };
|
|
19440
19530
|
}
|
|
19441
19531
|
return {
|
|
@@ -19610,6 +19700,8 @@ class ExecutionModule {
|
|
|
19610
19700
|
consecutivePlanWarnings: 0,
|
|
19611
19701
|
lastStepId: -1,
|
|
19612
19702
|
stuckNotified: false,
|
|
19703
|
+
lastStuckWarnKey: "",
|
|
19704
|
+
lastStuckWarnIter: -STUCK_WARN_REPEAT_EVERY,
|
|
19613
19705
|
depsGateHints: new Map,
|
|
19614
19706
|
mutationsWithoutPlan: 0,
|
|
19615
19707
|
planNudgeSent: false,
|