micro-models-agent 0.41.2 → 0.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/mma.mjs +41 -41
- package/dist/cli/commands.js +19 -9
- package/dist/cli/completer.js +37 -36
- package/dist/cli/index.js +2 -2
- package/dist/cli/main.js +23 -48
- package/dist/cli/repl-commands.js +12 -40
- package/dist/cli/repl.js +87 -217
- package/dist/cli/security-commands.js +7 -5
- package/dist/cli/setup.js +26 -8
- package/dist/config/config.js +5 -52
- package/dist/config/defaults.js +5 -29
- package/dist/config/experts.js +1 -1
- package/dist/config/index.js +3 -3
- package/dist/config/security.js +10 -3
- package/dist/core/agent-moe.js +10 -2
- package/dist/core/agent.js +82 -273
- package/dist/core/bootstrap.js +13 -80
- package/dist/core/index.js +2 -2
- package/dist/core/prompt-builder.js +2 -23
- package/dist/core/session-logger.js +4 -46
- package/dist/i18n/en.json +2 -75
- package/dist/i18n/ru.json +1 -74
- package/dist/index.js +1 -1
- package/dist/llm/image-utils.js +5 -4
- package/dist/llm/index.js +4 -4
- package/dist/llm/model-loader.js +6 -6
- package/dist/llm/openai-compat.js +34 -40
- package/dist/llm/orchestrator.js +29 -33
- package/dist/llm/response.js +9 -9
- package/dist/logger/app-logger.js +1 -1
- package/dist/logger/index.js +1 -1
- package/dist/main.js +299 -55
- package/dist/migration/backup.js +13 -13
- package/dist/migration/detect.js +11 -11
- package/dist/migration/index.js +2 -2
- package/dist/modules/browser/actions.js +4 -34
- package/dist/modules/browser/bridge-server.mjs +202 -202
- package/dist/modules/browser/cookie-store.js +6 -6
- package/dist/modules/browser/index.js +5 -7
- package/dist/modules/browser/module.js +7 -8
- package/dist/modules/browser/session.js +84 -87
- package/dist/modules/browser/snapshot.js +58 -92
- package/dist/modules/browser/types.js +1 -4
- package/dist/modules/certification/cli.js +4 -2
- package/dist/modules/certification/fact-checker.js +3 -1
- package/dist/modules/certification/loader.js +9 -3
- package/dist/modules/certification/runner.js +4 -1
- package/dist/modules/context/index.js +1 -1
- package/dist/modules/context/manager.js +86 -160
- package/dist/modules/execution/auditor.js +25 -177
- package/dist/modules/execution/module.js +544 -201
- package/dist/modules/execution/moe-executor.js +0 -25
- package/dist/modules/execution/plan-store.js +3 -1
- package/dist/modules/execution/plan-validator.js +10 -10
- package/dist/modules/execution/planner.js +1 -6
- package/dist/modules/execution/stuck-detector.js +10 -173
- package/dist/modules/execution/verifier.js +42 -86
- package/dist/modules/hallucination/confidence.js +1 -8
- package/dist/modules/hallucination/detector.js +5 -2
- package/dist/modules/hallucination/factual.js +64 -3
- package/dist/modules/hallucination/index.js +1 -1
- package/dist/modules/hallucination/js-identifiers.js +0 -190
- package/dist/modules/hallucination/llm-judge.js +3 -1
- package/dist/modules/indexer/cache.js +7 -9
- package/dist/modules/indexer/index.js +3 -3
- package/dist/modules/indexer/module.js +42 -95
- package/dist/modules/indexer/walker.js +17 -17
- package/dist/modules/lsp/client.js +31 -74
- package/dist/modules/lsp/config.js +33 -87
- package/dist/modules/lsp/index.js +3 -3
- package/dist/modules/lsp/module.js +21 -185
- package/dist/modules/mcp/module.js +6 -2
- package/dist/modules/memory/index.js +1 -1
- package/dist/modules/memory/module.js +23 -71
- package/dist/modules/memory/search.js +9 -11
- package/dist/modules/memory/store.js +13 -13
- package/dist/modules/pipelines/engine.js +10 -10
- package/dist/modules/pipelines/index.js +3 -3
- package/dist/modules/pipelines/parser.js +14 -17
- package/dist/modules/pipelines/template.js +1 -1
- package/dist/modules/plugins/builtin/lint-on-write.js +16 -21
- package/dist/modules/plugins/builtin/notify.js +2 -3
- package/dist/modules/plugins/index.js +1 -1
- package/dist/modules/plugins/loader.js +17 -59
- package/dist/modules/plugins/manager.js +17 -73
- package/dist/modules/processes/index.js +1 -1
- package/dist/modules/processes/registry.js +46 -135
- package/dist/modules/registry.js +2 -4
- package/dist/modules/security/audit-notifier.js +39 -39
- package/dist/modules/security/command-validator.js +8 -2
- package/dist/modules/security/data-sanitizer.js +9 -1
- package/dist/modules/security/encryption.js +56 -58
- package/dist/modules/security/network-validator.js +9 -1
- package/dist/modules/security/path-validator.js +3 -1
- package/dist/modules/security/security-policies.js +19 -3
- package/dist/modules/security/session-encryption.js +1 -1
- package/dist/modules/security/session-isolation.js +8 -8
- package/dist/modules/session/index.js +3 -3
- package/dist/modules/session/module.js +5 -5
- package/dist/modules/session/store.js +9 -3
- package/dist/modules/skills/module.js +2 -1
- package/dist/modules/updater/checker.js +6 -70
- package/dist/modules/updater/index.js +1 -2
- package/dist/modules/user-profile/compressor.js +2 -2
- package/dist/modules/user-profile/index.js +1 -1
- package/dist/modules/user-profile/profile.js +9 -9
- package/dist/tools/attach-image.js +1 -1
- package/dist/tools/bash.js +19 -178
- package/dist/tools/browser.js +29 -46
- package/dist/tools/executor.js +5 -4
- package/dist/tools/file-info.js +12 -13
- package/dist/tools/filter-tools.js +2 -9
- package/dist/tools/glob-tool.js +11 -11
- package/dist/tools/grep-tool.js +3 -1
- package/dist/tools/index.js +2 -13
- package/dist/tools/list-dir.js +17 -18
- package/dist/tools/load-skill.js +3 -1
- package/dist/tools/path-utils.js +4 -4
- package/dist/tools/pipeline-run.js +25 -25
- package/dist/tools/process-kill.js +11 -11
- package/dist/tools/process-list.js +22 -20
- package/dist/tools/process-log.js +18 -22
- package/dist/tools/question.js +3 -1
- package/dist/tools/read-file.js +2 -10
- package/dist/tools/recall.js +37 -44
- package/dist/tools/registry.js +4 -15
- package/dist/tools/remember.js +29 -29
- package/dist/tools/scope-check.js +9 -9
- package/dist/tools/subagent.js +9 -54
- package/dist/tools/user-input.js +1 -1
- package/dist/tools/web-browse.js +3 -3
- package/dist/tools/web-fetch.js +3 -3
- package/dist/tools/web-search.js +3 -3
- package/dist/tools/write-file.js +3 -1
- package/dist/ui/box.js +5 -1
- package/dist/ui/index.js +6 -6
- package/dist/ui/md-formatter.js +33 -33
- package/dist/ui/output.js +5 -5
- package/dist/ui/renderer.js +10 -15
- package/dist/ui/table.js +1 -1
- package/package.json +48 -48
- package/dist/cli/plugin-commands.js +0 -36
- package/dist/cli/run-result.js +0 -22
- package/dist/core/version.js +0 -24
- package/dist/modules/artifacts/store.js +0 -61
- package/dist/modules/browser/bridge-client.js +0 -199
- package/dist/modules/browser/bridge-path.js +0 -10
- package/dist/modules/browser/driver.js +0 -136
- package/dist/modules/context/chunk-query.js +0 -100
- package/dist/modules/context/fact-extractor.js +0 -162
- package/dist/modules/context/history.js +0 -15
- package/dist/modules/execution/audit-runners.js +0 -152
- package/dist/modules/execution/execution-plugin.js +0 -272
- package/dist/modules/execution/plan-tool.js +0 -508
- package/dist/modules/execution/windows-commands.js +0 -41
- package/dist/modules/indexer/project-profile.js +0 -183
- package/dist/modules/lsp/check-tool.js +0 -58
- package/dist/modules/lsp/command.js +0 -60
- package/dist/modules/lsp/probe.js +0 -76
- package/dist/modules/lsp/project-root.js +0 -32
- package/dist/modules/lsp/startup-check.js +0 -141
- package/dist/modules/processes/detect.js +0 -34
- package/dist/modules/skills/matcher.js +0 -27
- package/dist/modules/updater/module.js +0 -116
- package/dist/tools/chunk-query.js +0 -99
- package/dist/tools/download-file.js +0 -116
- package/dist/tools/enable-tools.js +0 -58
- package/dist/tools/hidden-tools-block.js +0 -37
- package/dist/ui/line-editor.js +0 -703
- package/dist/ui/line-math.js +0 -69
- package/dist/ui/plan-view.js +0 -103
package/dist/main.js
CHANGED
|
@@ -2287,6 +2287,17 @@ var init_defaults = __esm(() => {
|
|
|
2287
2287
|
viewportHeight: 720,
|
|
2288
2288
|
navigationTimeout: 15000
|
|
2289
2289
|
},
|
|
2290
|
+
webSearch: {
|
|
2291
|
+
enabled: true
|
|
2292
|
+
},
|
|
2293
|
+
errorWebSearch: {
|
|
2294
|
+
enabled: true,
|
|
2295
|
+
threshold: 5,
|
|
2296
|
+
maxResults: 5,
|
|
2297
|
+
maxQueryChars: 200,
|
|
2298
|
+
maxSearchesPerSession: 3,
|
|
2299
|
+
requestTimeoutMs: 1e4
|
|
2300
|
+
},
|
|
2290
2301
|
ui: {
|
|
2291
2302
|
spinner: true,
|
|
2292
2303
|
toolStyle: "inline",
|
|
@@ -2476,6 +2487,7 @@ Summary:
|
|
|
2476
2487
|
"tool.no_results": 'No results found for "{query}"',
|
|
2477
2488
|
"tool.search_results": `Search results for "{query}":
|
|
2478
2489
|
{results}`,
|
|
2490
|
+
"tool.web_search_disabled": "Web search is disabled (webSearch.enabled: false). Use file/system tools only.",
|
|
2479
2491
|
"tool.history_results": `History results for "{query}":
|
|
2480
2492
|
{results}`,
|
|
2481
2493
|
"tool.no_history": 'No history entries matching "{query}"',
|
|
@@ -2561,6 +2573,7 @@ Command: {command}`,
|
|
|
2561
2573
|
"lsp.check_notfound": "Path not found: {path}",
|
|
2562
2574
|
"lsp.check_unsupported": "No LSP server configured for: {path}",
|
|
2563
2575
|
"lsp.check_clean": "No errors or warnings detected ({count} file(s) checked).",
|
|
2576
|
+
"lsp.checked_files": "Checked {count} file(s):",
|
|
2564
2577
|
"lsp.startup_header": "[Existing project errors (checked at session start) — fix these before continuing]:",
|
|
2565
2578
|
"cli.description": "Micro Models Agent — AI coding agent for small models",
|
|
2566
2579
|
"cli.init": "Run interactive setup wizard",
|
|
@@ -2860,6 +2873,11 @@ Use this knowledge to answer the user's question.`,
|
|
|
2860
2873
|
{hints}`,
|
|
2861
2874
|
"exec.file_rewrite_warning": "⚠️ File {file} has been rewritten {count} times. Consider a different approach — the current fix strategy is not working.",
|
|
2862
2875
|
"exec.forbidden_cmd": 'STOP using "{cmd}" via the bash tool — it is not a native Windows cmd.exe command and has failed repeatedly this session. Use the dedicated tool instead: grep → the grep tool, ls/dir → list_dir, find → glob, rm → delete_file, sed → edit_file, touch → write_file, which → `where`, cp/mv → move_file, diff → read_file. Do NOT call bash for this purpose again.',
|
|
2876
|
+
"exec.error_search_results": `The error "{sig}" has occurred {count} times. Web search found:
|
|
2877
|
+
{results}
|
|
2878
|
+
Apply a matching solution from these results. If none is relevant — do NOT repeat the same approach; change strategy or honestly report being stuck.`,
|
|
2879
|
+
"exec.error_search_failed": 'Web search returned nothing for "{query}".',
|
|
2880
|
+
"exec.error_search_no_query": "Error output is not meaningful — skipping the web search.",
|
|
2863
2881
|
"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.',
|
|
2864
2882
|
"hall.max_retries_exhausted": "Model returned empty or insufficient responses after multiple retries",
|
|
2865
2883
|
"hall.short_response": "Response too short or empty",
|
|
@@ -2909,6 +2927,7 @@ Use this knowledge to answer the user's question.`,
|
|
|
2909
2927
|
"ui.success_prefix": "✓ ",
|
|
2910
2928
|
"ui.warning_prefix": "⚠ ",
|
|
2911
2929
|
"ui.thinking": "Thinking…",
|
|
2930
|
+
"ui.tool_running": "{tool}…",
|
|
2912
2931
|
"ui.step_context": "step {id}: {desc}",
|
|
2913
2932
|
"indexer.map_header": "Project map",
|
|
2914
2933
|
"indexer.top_directories": "Top directories",
|
|
@@ -3111,6 +3130,7 @@ var init_ru = __esm(() => {
|
|
|
3111
3130
|
"tool.no_results": 'Нет результатов по "{query}"',
|
|
3112
3131
|
"tool.search_results": `Результаты поиска "{query}":
|
|
3113
3132
|
{results}`,
|
|
3133
|
+
"tool.web_search_disabled": "Веб-поиск отключён (webSearch.enabled: false). Используй только файловые и системные инструменты.",
|
|
3114
3134
|
"tool.history_results": `Результаты истории "{query}":
|
|
3115
3135
|
{results}`,
|
|
3116
3136
|
"tool.no_history": 'Нет записей истории по "{query}"',
|
|
@@ -3196,6 +3216,7 @@ var init_ru = __esm(() => {
|
|
|
3196
3216
|
"lsp.check_notfound": "Путь не найден: {path}",
|
|
3197
3217
|
"lsp.check_unsupported": "Для файла не настроен LSP-сервер: {path}",
|
|
3198
3218
|
"lsp.check_clean": "Ошибок и предупреждений не обнаружено (проверено файлов: {count}).",
|
|
3219
|
+
"lsp.checked_files": "Проверено файлов: {count}:",
|
|
3199
3220
|
"lsp.startup_header": "[Существующие ошибки проекта (проверено при старте сессии) — исправьте их перед продолжением]:",
|
|
3200
3221
|
"cli.description": "Micro Models Agent — ИИ-агент для кодинга на малых моделях",
|
|
3201
3222
|
"cli.init": "Запустить мастер настройки",
|
|
@@ -3495,6 +3516,11 @@ var init_ru = __esm(() => {
|
|
|
3495
3516
|
{hints}`,
|
|
3496
3517
|
"exec.file_rewrite_warning": "⚠️ Файл {file} был перезаписан {count} раз. Попробуйте другой подход — текущая стратегия исправлений не работает.",
|
|
3497
3518
|
"exec.forbidden_cmd": 'ПРЕКРАТИ использовать "{cmd}" через bash — это не команда Windows cmd.exe, и она уже неоднократно падала в этой сессии. Используй предназначенный тул: grep → тул grep, ls/dir → list_dir, find → glob, rm → delete_file, sed → edit_file, touch → write_file, which → `where`, cp/mv → move_file, diff → read_file. Больше не вызывай bash для этого.',
|
|
3519
|
+
"exec.error_search_results": `Ошибка "{sig}" повторилась {count} раз. Поиск в интернете нашёл:
|
|
3520
|
+
{results}
|
|
3521
|
+
Примени подходящее решение из результатов. Если ни один результат не релевантен — НЕ повторяй тот же подход, смени стратегию или честно сообщи о застревании.`,
|
|
3522
|
+
"exec.error_search_failed": 'Поиск в интернете для "{query}" ничего не дал.',
|
|
3523
|
+
"exec.error_search_no_query": "Текст ошибки незначимый — поиск в интернете пропущен.",
|
|
3498
3524
|
"exec.npm_exec_hint": '"could not determine executable to run" — у пакета/скрипта нет "bin". Используй "npm run <script>" (скрипт должен быть в package.json) или "bunx <pkg>" для пакета с объявленным bin.',
|
|
3499
3525
|
"hall.max_retries_exhausted": "Модель вернула пустой или недостаточный ответ после нескольких попыток",
|
|
3500
3526
|
"hall.short_response": "Слишком короткий или пустой ответ",
|
|
@@ -3544,6 +3570,7 @@ var init_ru = __esm(() => {
|
|
|
3544
3570
|
"ui.success_prefix": "✓ ",
|
|
3545
3571
|
"ui.warning_prefix": "⚠ ",
|
|
3546
3572
|
"ui.thinking": "Думаю…",
|
|
3573
|
+
"ui.tool_running": "{tool}…",
|
|
3547
3574
|
"ui.step_context": "шаг {id}: {desc}",
|
|
3548
3575
|
"indexer.map_header": "Карта проекта",
|
|
3549
3576
|
"indexer.top_directories": "Основные директории",
|
|
@@ -9464,6 +9491,41 @@ function filterToolsByTags(tools, toolTags) {
|
|
|
9464
9491
|
}
|
|
9465
9492
|
|
|
9466
9493
|
// src/modules/execution/stuck-detector.ts
|
|
9494
|
+
function normalizeErrorSignature(toolName, output) {
|
|
9495
|
+
if (!output)
|
|
9496
|
+
return null;
|
|
9497
|
+
const cleaned = output.replace(ANSI_RE, "").replace(ERROR_LOC_RE, " <path>").split(`
|
|
9498
|
+
`).map((l) => l.trim()).filter(Boolean).join(" ").replace(/\s+/g, " ").trim();
|
|
9499
|
+
if (!cleaned)
|
|
9500
|
+
return null;
|
|
9501
|
+
return `${toolName}::${cleaned.slice(0, SIGNATURE_MAX_CHARS)}`;
|
|
9502
|
+
}
|
|
9503
|
+
function isSearchableError(output) {
|
|
9504
|
+
if (!output || !output.trim())
|
|
9505
|
+
return false;
|
|
9506
|
+
const text = output.trim();
|
|
9507
|
+
return SEARCHABLE_PATTERNS.some((p) => p.test(text));
|
|
9508
|
+
}
|
|
9509
|
+
function buildSearchQuery(stepDescription, lastBashCommand, lastErrorOutput, toolName, maxQueryChars) {
|
|
9510
|
+
const errorText = (lastErrorOutput || "").replace(ANSI_RE, "").replace(ERROR_LOC_RE, " <path>").split(`
|
|
9511
|
+
`).map((l) => l.trim()).filter(Boolean).slice(0, 3).join(" ").replace(/\s+/g, " ").trim();
|
|
9512
|
+
const context = `${stepDescription} ${lastBashCommand}`.toLowerCase();
|
|
9513
|
+
const runtime = RUNTIME_WORDS.find((w) => context.includes(w)) || "";
|
|
9514
|
+
const framework = FRAMEWORK_WORDS.find((w) => context.includes(w)) || "";
|
|
9515
|
+
let query;
|
|
9516
|
+
if (errorText) {
|
|
9517
|
+
query = runtime && !errorText.toLowerCase().includes(runtime) ? `${runtime} ${errorText}` : errorText;
|
|
9518
|
+
if (framework && !query.toLowerCase().includes(framework))
|
|
9519
|
+
query = `${query} ${framework}`;
|
|
9520
|
+
query = `${query} how to fix`;
|
|
9521
|
+
} else if (runtime || framework) {
|
|
9522
|
+
query = `${[runtime, framework, "error", "how to fix"].filter(Boolean).join(" ")}`;
|
|
9523
|
+
} else {
|
|
9524
|
+
query = `${toolName} ${stepDescription} how to fix`;
|
|
9525
|
+
}
|
|
9526
|
+
return query.slice(0, maxQueryChars);
|
|
9527
|
+
}
|
|
9528
|
+
|
|
9467
9529
|
class StuckDetector {
|
|
9468
9530
|
threshold;
|
|
9469
9531
|
errorThreshold;
|
|
@@ -9485,9 +9547,13 @@ class StuckDetector {
|
|
|
9485
9547
|
lastBashOutput = "";
|
|
9486
9548
|
emptyBashRunCount = 0;
|
|
9487
9549
|
readOnlyStreak = 0;
|
|
9488
|
-
|
|
9550
|
+
errorSignatureCounts = new Map;
|
|
9551
|
+
searchedErrorSignatures = new Set;
|
|
9552
|
+
webSearchThreshold;
|
|
9553
|
+
constructor(threshold = 6, errorThreshold = 3, webSearchThreshold = 5) {
|
|
9489
9554
|
this.threshold = threshold;
|
|
9490
9555
|
this.errorThreshold = errorThreshold;
|
|
9556
|
+
this.webSearchThreshold = webSearchThreshold;
|
|
9491
9557
|
}
|
|
9492
9558
|
recordIteration(stepId) {
|
|
9493
9559
|
if (stepId === this.currentStepId) {
|
|
@@ -9517,6 +9583,10 @@ class StuckDetector {
|
|
|
9517
9583
|
this.lastFailedTool = toolName;
|
|
9518
9584
|
if (output)
|
|
9519
9585
|
this.lastErrorOutput = output;
|
|
9586
|
+
const sig = normalizeErrorSignature(toolName, output);
|
|
9587
|
+
if (sig) {
|
|
9588
|
+
this.errorSignatureCounts.set(sig, (this.errorSignatureCounts.get(sig) || 0) + 1);
|
|
9589
|
+
}
|
|
9520
9590
|
}
|
|
9521
9591
|
getLastErrorOutput() {
|
|
9522
9592
|
return this.lastErrorOutput;
|
|
@@ -9540,6 +9610,26 @@ class StuckDetector {
|
|
|
9540
9610
|
getLastFailedTool() {
|
|
9541
9611
|
return this.lastFailedTool;
|
|
9542
9612
|
}
|
|
9613
|
+
getRepeatedErrorSignature() {
|
|
9614
|
+
for (const [sig, count] of this.errorSignatureCounts) {
|
|
9615
|
+
if (count >= this.webSearchThreshold && !this.searchedErrorSignatures.has(sig)) {
|
|
9616
|
+
return sig;
|
|
9617
|
+
}
|
|
9618
|
+
}
|
|
9619
|
+
return null;
|
|
9620
|
+
}
|
|
9621
|
+
getErrorSignatureCount(sig) {
|
|
9622
|
+
return this.errorSignatureCounts.get(sig) || 0;
|
|
9623
|
+
}
|
|
9624
|
+
markErrorSearched(sig) {
|
|
9625
|
+
this.searchedErrorSignatures.add(sig);
|
|
9626
|
+
}
|
|
9627
|
+
unmarkErrorSearched(sig) {
|
|
9628
|
+
this.searchedErrorSignatures.delete(sig);
|
|
9629
|
+
}
|
|
9630
|
+
hasErrorSearched(sig) {
|
|
9631
|
+
return this.searchedErrorSignatures.has(sig);
|
|
9632
|
+
}
|
|
9543
9633
|
getIterationsOnCurrentStep() {
|
|
9544
9634
|
return this.iterationsOnCurrentStep;
|
|
9545
9635
|
}
|
|
@@ -9812,6 +9902,8 @@ class StuckDetector {
|
|
|
9812
9902
|
this.lastBashOutput = "";
|
|
9813
9903
|
this.emptyBashRunCount = 0;
|
|
9814
9904
|
this.readOnlyStreak = 0;
|
|
9905
|
+
this.errorSignatureCounts.clear();
|
|
9906
|
+
this.searchedErrorSignatures.clear();
|
|
9815
9907
|
}
|
|
9816
9908
|
resetStepProgress() {
|
|
9817
9909
|
this.currentStepId = null;
|
|
@@ -9825,6 +9917,8 @@ class StuckDetector {
|
|
|
9825
9917
|
this.lastBashCommand = "";
|
|
9826
9918
|
this.lastBashOutput = "";
|
|
9827
9919
|
this.emptyBashRunCount = 0;
|
|
9920
|
+
this.errorSignatureCounts.clear();
|
|
9921
|
+
this.searchedErrorSignatures.clear();
|
|
9828
9922
|
}
|
|
9829
9923
|
resetStepState(stepId) {
|
|
9830
9924
|
this.currentStepId = stepId;
|
|
@@ -9839,9 +9933,11 @@ class StuckDetector {
|
|
|
9839
9933
|
this.lastBashOutput = "";
|
|
9840
9934
|
this.emptyBashRunCount = 0;
|
|
9841
9935
|
this.readOnlyStreak = 0;
|
|
9936
|
+
this.errorSignatureCounts.clear();
|
|
9937
|
+
this.searchedErrorSignatures.clear();
|
|
9842
9938
|
}
|
|
9843
9939
|
}
|
|
9844
|
-
var READ_ONLY_TOOLS, READ_ONLY_LOOP_THRESHOLD = 10;
|
|
9940
|
+
var READ_ONLY_TOOLS, READ_ONLY_LOOP_THRESHOLD = 10, ANSI_RE, ERROR_LOC_RE, SIGNATURE_MAX_CHARS = 120, SEARCHABLE_PATTERNS, RUNTIME_WORDS, FRAMEWORK_WORDS;
|
|
9845
9941
|
var init_stuck_detector = __esm(() => {
|
|
9846
9942
|
init_i18n();
|
|
9847
9943
|
READ_ONLY_TOOLS = new Set([
|
|
@@ -9865,6 +9961,55 @@ var init_stuck_detector = __esm(() => {
|
|
|
9865
9961
|
"verify",
|
|
9866
9962
|
"load_skill"
|
|
9867
9963
|
]);
|
|
9964
|
+
ANSI_RE = /\x1b\[[0-9;]*m/g;
|
|
9965
|
+
ERROR_LOC_RE = /(?:[A-Za-z]:[\\/])?(?:[\w.@+-]+[\\/])+[\w.@+-]+\.[a-zA-Z0-9]{1,6}(?::\d+(?::\d+)?)?/g;
|
|
9966
|
+
SEARCHABLE_PATTERNS = [
|
|
9967
|
+
/error TS\d+/i,
|
|
9968
|
+
/ERR_[A-Z_]+/,
|
|
9969
|
+
/ENOENT|EACCES|EPERM|ECONNREFUSED|ETIMEDOUT|ECONNRESET|ENOTFOUND|EADDRINUSE/i,
|
|
9970
|
+
/Cannot find module|Module not found|ERR_MODULE_NOT_FOUND/i,
|
|
9971
|
+
/TypeError|ReferenceError|SyntaxError|RangeError/i,
|
|
9972
|
+
/is not a function|is not defined|is not a constructor/i,
|
|
9973
|
+
/Cannot read properties of/i,
|
|
9974
|
+
/failed to (compile|build|resolve|parse)/i,
|
|
9975
|
+
/fatal error|panic/i
|
|
9976
|
+
];
|
|
9977
|
+
RUNTIME_WORDS = [
|
|
9978
|
+
"bun",
|
|
9979
|
+
"node",
|
|
9980
|
+
"deno",
|
|
9981
|
+
"npm",
|
|
9982
|
+
"yarn",
|
|
9983
|
+
"pnpm",
|
|
9984
|
+
"pip",
|
|
9985
|
+
"pip3",
|
|
9986
|
+
"python",
|
|
9987
|
+
"python3",
|
|
9988
|
+
"tsc",
|
|
9989
|
+
"tsx",
|
|
9990
|
+
"npx",
|
|
9991
|
+
"go",
|
|
9992
|
+
"cargo",
|
|
9993
|
+
"gradle",
|
|
9994
|
+
"maven",
|
|
9995
|
+
"make"
|
|
9996
|
+
];
|
|
9997
|
+
FRAMEWORK_WORDS = [
|
|
9998
|
+
"react",
|
|
9999
|
+
"vue",
|
|
10000
|
+
"angular",
|
|
10001
|
+
"svelte",
|
|
10002
|
+
"vite",
|
|
10003
|
+
"next",
|
|
10004
|
+
"nest",
|
|
10005
|
+
"express",
|
|
10006
|
+
"fastify",
|
|
10007
|
+
"flask",
|
|
10008
|
+
"django",
|
|
10009
|
+
"spring",
|
|
10010
|
+
"webpack",
|
|
10011
|
+
"tailwind"
|
|
10012
|
+
];
|
|
9868
10013
|
});
|
|
9869
10014
|
|
|
9870
10015
|
// src/modules/artifacts/store.ts
|
|
@@ -13425,6 +13570,43 @@ var init_network_validator = __esm(() => {
|
|
|
13425
13570
|
});
|
|
13426
13571
|
|
|
13427
13572
|
// src/tools/web-search.ts
|
|
13573
|
+
async function performWebSearch(query, numResults, networkConfig, requestTimeoutMs) {
|
|
13574
|
+
const url = `https://html.duckduckgo.com/html/?q=${encodeURIComponent(query)}`;
|
|
13575
|
+
const validation = isUrlAllowed(url, networkConfig);
|
|
13576
|
+
if (!validation.allowed) {
|
|
13577
|
+
return {
|
|
13578
|
+
success: false,
|
|
13579
|
+
blocked: true,
|
|
13580
|
+
results: [],
|
|
13581
|
+
error: validation.reason || "URL blocked by security policy"
|
|
13582
|
+
};
|
|
13583
|
+
}
|
|
13584
|
+
try {
|
|
13585
|
+
const response = await fetch(url, {
|
|
13586
|
+
signal: AbortSignal.timeout(requestTimeoutMs ?? networkConfig?.requestTimeout ?? 1e4)
|
|
13587
|
+
});
|
|
13588
|
+
const html = await response.text();
|
|
13589
|
+
const results = [];
|
|
13590
|
+
const snippetRegex = /<a[^>]+class="result__a"[^>]*href="([^"]*)"[^>]*>([\s\S]*?)<\/a>[\s\S]*?<a[^>]+class="result__snippet"[^>]*>([\s\S]*?)<\/a>/gi;
|
|
13591
|
+
let match;
|
|
13592
|
+
while ((match = snippetRegex.exec(html)) !== null && results.length < numResults) {
|
|
13593
|
+
results.push({
|
|
13594
|
+
url: match[1].trim(),
|
|
13595
|
+
title: match[2].replace(/<[^>]+>/g, "").trim(),
|
|
13596
|
+
snippet: match[3].replace(/<[^>]+>/g, "").trim()
|
|
13597
|
+
});
|
|
13598
|
+
}
|
|
13599
|
+
return { success: true, results };
|
|
13600
|
+
} catch (err) {
|
|
13601
|
+
return { success: false, results: [], error: err.message };
|
|
13602
|
+
}
|
|
13603
|
+
}
|
|
13604
|
+
function formatResults(results) {
|
|
13605
|
+
return results.map((r, i) => `${i + 1}. ${r.title}
|
|
13606
|
+
URL: ${r.url}
|
|
13607
|
+
${r.snippet}`).join(`
|
|
13608
|
+
`);
|
|
13609
|
+
}
|
|
13428
13610
|
var webSearchTool;
|
|
13429
13611
|
var init_web_search = __esm(() => {
|
|
13430
13612
|
init_i18n();
|
|
@@ -13447,59 +13629,42 @@ var init_web_search = __esm(() => {
|
|
|
13447
13629
|
required: ["query"]
|
|
13448
13630
|
},
|
|
13449
13631
|
handler: async (ctx, args) => {
|
|
13632
|
+
if (ctx.config?.webSearch?.enabled === false) {
|
|
13633
|
+
return { success: false, output: t("tool.web_search_disabled") };
|
|
13634
|
+
}
|
|
13450
13635
|
const query = String(args.query || "");
|
|
13451
13636
|
const numResults = Number(args.numResults) || 5;
|
|
13452
|
-
const url = `https://html.duckduckgo.com/html/?q=${encodeURIComponent(query)}`;
|
|
13453
13637
|
const securityConfig = ctx.sessionContext ? getSessionSecurityConfig(ctx.config, ctx.sessionContext).network : ctx.config.security?.network;
|
|
13454
|
-
const
|
|
13455
|
-
|
|
13456
|
-
|
|
13638
|
+
const outcome = await performWebSearch(query, numResults, securityConfig);
|
|
13639
|
+
const url = `https://html.duckduckgo.com/html/?q=${encodeURIComponent(query)}`;
|
|
13640
|
+
if (outcome.blocked) {
|
|
13641
|
+
logSecurityBlock(ctx.sessionId, "network_request", outcome.error || "URL blocked by security policy", sanitizeUrl(url));
|
|
13457
13642
|
return {
|
|
13458
13643
|
success: false,
|
|
13459
|
-
output:
|
|
13644
|
+
output: t("error.search_failed", { message: String(outcome.error) })
|
|
13460
13645
|
};
|
|
13461
13646
|
}
|
|
13462
|
-
|
|
13463
|
-
|
|
13464
|
-
signal: AbortSignal.timeout(securityConfig?.requestTimeout || 1e4)
|
|
13465
|
-
});
|
|
13466
|
-
const html = await response.text();
|
|
13467
|
-
const results = [];
|
|
13468
|
-
const snippetRegex = /<a[^>]+class="result__a"[^>]*href="([^"]*)"[^>]*>([\s\S]*?)<\/a>[\s\S]*?<a[^>]+class="result__snippet"[^>]*>([\s\S]*?)<\/a>/gi;
|
|
13469
|
-
let match;
|
|
13470
|
-
let count = 0;
|
|
13471
|
-
while ((match = snippetRegex.exec(html)) !== null && count < numResults) {
|
|
13472
|
-
const href = match[1].trim();
|
|
13473
|
-
const title = match[2].replace(/<[^>]+>/g, "").trim();
|
|
13474
|
-
const snippet = match[3].replace(/<[^>]+>/g, "").trim();
|
|
13475
|
-
results.push(`${count + 1}. ${title}
|
|
13476
|
-
URL: ${href}
|
|
13477
|
-
${snippet}`);
|
|
13478
|
-
count++;
|
|
13479
|
-
}
|
|
13480
|
-
logNetworkRequest(ctx.sessionId, sanitizeUrl(url), true, `Results: ${results.length}`);
|
|
13481
|
-
if (results.length === 0) {
|
|
13482
|
-
return { success: true, output: t("tool.no_results", { query }) };
|
|
13483
|
-
}
|
|
13484
|
-
return {
|
|
13485
|
-
success: true,
|
|
13486
|
-
output: t("tool.search_results", {
|
|
13487
|
-
query,
|
|
13488
|
-
results: results.join(`
|
|
13489
|
-
`)
|
|
13490
|
-
}),
|
|
13491
|
-
display: t("tool.web_search_result", {
|
|
13492
|
-
query,
|
|
13493
|
-
count: String(results.length)
|
|
13494
|
-
})
|
|
13495
|
-
};
|
|
13496
|
-
} catch (err) {
|
|
13497
|
-
logNetworkRequest(ctx.sessionId, sanitizeUrl(url), false, `Error: ${err.message}`);
|
|
13647
|
+
logNetworkRequest(ctx.sessionId, sanitizeUrl(url), outcome.success, `Results: ${outcome.results.length}`);
|
|
13648
|
+
if (!outcome.success) {
|
|
13498
13649
|
return {
|
|
13499
13650
|
success: false,
|
|
13500
|
-
output: t("error.search_failed", { message:
|
|
13651
|
+
output: t("error.search_failed", { message: String(outcome.error) })
|
|
13501
13652
|
};
|
|
13502
13653
|
}
|
|
13654
|
+
if (outcome.results.length === 0) {
|
|
13655
|
+
return { success: true, output: t("tool.no_results", { query }) };
|
|
13656
|
+
}
|
|
13657
|
+
return {
|
|
13658
|
+
success: true,
|
|
13659
|
+
output: t("tool.search_results", {
|
|
13660
|
+
query,
|
|
13661
|
+
results: formatResults(outcome.results)
|
|
13662
|
+
}),
|
|
13663
|
+
display: t("tool.web_search_result", {
|
|
13664
|
+
query,
|
|
13665
|
+
count: String(outcome.results.length)
|
|
13666
|
+
})
|
|
13667
|
+
};
|
|
13503
13668
|
}
|
|
13504
13669
|
};
|
|
13505
13670
|
});
|
|
@@ -17785,7 +17950,8 @@ Tool "${deps.stuckDetector.getLastFailedTool()}" is failing. Try "${alternative}
|
|
|
17785
17950
|
deps.stuckDetector.recordBashOutput(String(call.arguments?.command ?? ""), String(result.output ?? ""));
|
|
17786
17951
|
}
|
|
17787
17952
|
const toolText = String(result.output ?? "");
|
|
17788
|
-
|
|
17953
|
+
const hasTypeError = /error TS\d+|\[Project typecheck failed\]|\[Syntax check failed\]/.test(toolText);
|
|
17954
|
+
if (hasTypeError) {
|
|
17789
17955
|
deps.stuckDetector.recordToolError(call.name, toolText.slice(0, 300));
|
|
17790
17956
|
}
|
|
17791
17957
|
if (!result.success) {
|
|
@@ -17803,7 +17969,9 @@ Tool "${deps.stuckDetector.getLastFailedTool()}" is failing. Try "${alternative}
|
|
|
17803
17969
|
}
|
|
17804
17970
|
}
|
|
17805
17971
|
}
|
|
17806
|
-
|
|
17972
|
+
if (!hasTypeError) {
|
|
17973
|
+
deps.stuckDetector.recordToolError(call.name, result.output);
|
|
17974
|
+
}
|
|
17807
17975
|
const actionableHints = deps.stuckDetector.getActionableHints();
|
|
17808
17976
|
const alternative = deps.stuckDetector.getToolAlternative();
|
|
17809
17977
|
if (actionableHints.length > 0 || alternative) {
|
|
@@ -17857,6 +18025,7 @@ Tool "${deps.stuckDetector.getLastFailedTool()}" is failing. Try "${alternative}
|
|
|
17857
18025
|
}
|
|
17858
18026
|
deps.advancePlanIfStepComplete(ctx.contextManager, ctx.sessionLog);
|
|
17859
18027
|
}
|
|
18028
|
+
deps.maybeSearchError(ctx, call);
|
|
17860
18029
|
}
|
|
17861
18030
|
};
|
|
17862
18031
|
}
|
|
@@ -17882,6 +18051,12 @@ class ExecutionModule {
|
|
|
17882
18051
|
_auditSkipsRemaining = 0;
|
|
17883
18052
|
pendingMessages = [];
|
|
17884
18053
|
forbiddenBashFailures = new Map;
|
|
18054
|
+
searchRunner;
|
|
18055
|
+
webSearchThreshold;
|
|
18056
|
+
searchesThisSession = 0;
|
|
18057
|
+
retryWebSearchSignatures = new Set;
|
|
18058
|
+
lastErrorSearchAt = 0;
|
|
18059
|
+
errorSearchCooldownMs;
|
|
17885
18060
|
state = {
|
|
17886
18061
|
lastRecoveryIteration: -STUCK_RECOVERY_COOLDOWN,
|
|
17887
18062
|
consecutivePlanWarnings: 0,
|
|
@@ -17900,12 +18075,15 @@ class ExecutionModule {
|
|
|
17900
18075
|
}
|
|
17901
18076
|
};
|
|
17902
18077
|
})();
|
|
17903
|
-
constructor(baseDir, stuckThreshold = 6) {
|
|
18078
|
+
constructor(baseDir, stuckThreshold = 6, webSearchThreshold = 5, searchRunner = performWebSearch, errorSearchCooldownMs = ERROR_SEARCH_MIN_INTERVAL_MS) {
|
|
17904
18079
|
this.baseDir = baseDir;
|
|
17905
18080
|
this.verifier = new StepVerifier(baseDir);
|
|
17906
|
-
this.stuckDetector = new StuckDetector(stuckThreshold);
|
|
18081
|
+
this.stuckDetector = new StuckDetector(stuckThreshold, 3, webSearchThreshold);
|
|
17907
18082
|
this.auditor = new Auditor(baseDir);
|
|
17908
18083
|
this.store = new PlanStore(baseDir);
|
|
18084
|
+
this.webSearchThreshold = webSearchThreshold;
|
|
18085
|
+
this.searchRunner = searchRunner;
|
|
18086
|
+
this.errorSearchCooldownMs = errorSearchCooldownMs;
|
|
17909
18087
|
}
|
|
17910
18088
|
setPlan(plan) {
|
|
17911
18089
|
this.tracker = new PlanTracker(plan);
|
|
@@ -17936,6 +18114,58 @@ class ExecutionModule {
|
|
|
17936
18114
|
getStuckDetector() {
|
|
17937
18115
|
return this.stuckDetector;
|
|
17938
18116
|
}
|
|
18117
|
+
maybeSearchError(ctx, call) {
|
|
18118
|
+
if (ctx.config?.webSearch?.enabled === false)
|
|
18119
|
+
return;
|
|
18120
|
+
const cfg = ctx.config?.errorWebSearch;
|
|
18121
|
+
if (!cfg?.enabled)
|
|
18122
|
+
return;
|
|
18123
|
+
const sig = this.stuckDetector.getRepeatedErrorSignature();
|
|
18124
|
+
if (!sig)
|
|
18125
|
+
return;
|
|
18126
|
+
if (this.stuckDetector.hasErrorSearched(sig) && !this.retryWebSearchSignatures.has(sig))
|
|
18127
|
+
return;
|
|
18128
|
+
if (this.searchesThisSession >= (cfg.maxSearchesPerSession ?? 3))
|
|
18129
|
+
return;
|
|
18130
|
+
const lastError = this.stuckDetector.getLastErrorOutput();
|
|
18131
|
+
if (!isSearchableError(lastError)) {
|
|
18132
|
+
ctx.logger?.debug(t("exec.error_search_no_query"));
|
|
18133
|
+
return;
|
|
18134
|
+
}
|
|
18135
|
+
const now = Date.now();
|
|
18136
|
+
if (now - this.lastErrorSearchAt < this.errorSearchCooldownMs)
|
|
18137
|
+
return;
|
|
18138
|
+
const stepDesc = this.tracker?.getCurrentStep()?.description ?? "";
|
|
18139
|
+
const query = buildSearchQuery(stepDesc, this.stuckDetector.getLastBashCommand(), lastError, call.name, cfg.maxQueryChars ?? 200);
|
|
18140
|
+
const count = this.stuckDetector.getErrorSignatureCount(sig);
|
|
18141
|
+
this.stuckDetector.markErrorSearched(sig);
|
|
18142
|
+
this.searchesThisSession++;
|
|
18143
|
+
this.lastErrorSearchAt = now;
|
|
18144
|
+
const networkConfig = getSessionSecurityConfig(ctx.config, ctx.sessionContext).network;
|
|
18145
|
+
this.searchRunner(query, cfg.maxResults ?? 5, networkConfig, cfg.requestTimeoutMs ?? 1e4).then((res) => {
|
|
18146
|
+
if (!res.success || res.results.length === 0) {
|
|
18147
|
+
if (!this.retryWebSearchSignatures.has(sig)) {
|
|
18148
|
+
this.retryWebSearchSignatures.add(sig);
|
|
18149
|
+
this.stuckDetector.unmarkErrorSearched(sig);
|
|
18150
|
+
}
|
|
18151
|
+
ctx.logger?.warn(t("exec.error_search_failed", { query }));
|
|
18152
|
+
ctx.sessionLog?.plan("web-search", `empty/failed: ${query}`);
|
|
18153
|
+
return;
|
|
18154
|
+
}
|
|
18155
|
+
const resultsText = res.results.map((r, i) => `${i + 1}. ${r.title} — ${r.url}
|
|
18156
|
+
${r.snippet}`).join(`
|
|
18157
|
+
`);
|
|
18158
|
+
this.pendingMessages.push({
|
|
18159
|
+
role: "user",
|
|
18160
|
+
content: `<system-summary>${t("exec.error_search_results", {
|
|
18161
|
+
sig,
|
|
18162
|
+
count: String(count),
|
|
18163
|
+
query,
|
|
18164
|
+
results: resultsText
|
|
18165
|
+
})}</system-summary>`
|
|
18166
|
+
});
|
|
18167
|
+
}).catch((e) => ctx.logger?.warn(`error web search: ${e.message}`));
|
|
18168
|
+
}
|
|
17939
18169
|
async runFinalAudit() {
|
|
17940
18170
|
if (!this.tracker)
|
|
17941
18171
|
return null;
|
|
@@ -18001,7 +18231,8 @@ class ExecutionModule {
|
|
|
18001
18231
|
forbiddenBashFailures: this.forbiddenBashFailures,
|
|
18002
18232
|
state: this.state,
|
|
18003
18233
|
checkPlanAlignment: (call) => this.checkPlanAlignment(call),
|
|
18004
|
-
advancePlanIfStepComplete: (cm, sl) => this.advancePlanIfStepComplete(cm, sl)
|
|
18234
|
+
advancePlanIfStepComplete: (cm, sl) => this.advancePlanIfStepComplete(cm, sl),
|
|
18235
|
+
maybeSearchError: (ctx, call) => this.maybeSearchError(ctx, call)
|
|
18005
18236
|
});
|
|
18006
18237
|
}
|
|
18007
18238
|
preserveActive() {
|
|
@@ -18198,6 +18429,7 @@ class ExecutionModule {
|
|
|
18198
18429
|
return getMessageText(firstUser.content).trim();
|
|
18199
18430
|
}
|
|
18200
18431
|
}
|
|
18432
|
+
var ERROR_SEARCH_MIN_INTERVAL_MS = 30000;
|
|
18201
18433
|
var init_module = __esm(() => {
|
|
18202
18434
|
init_i18n();
|
|
18203
18435
|
init_tracker();
|
|
@@ -18206,6 +18438,8 @@ var init_module = __esm(() => {
|
|
|
18206
18438
|
init_auditor();
|
|
18207
18439
|
init_plan_store();
|
|
18208
18440
|
init_js_identifiers();
|
|
18441
|
+
init_web_search();
|
|
18442
|
+
init_session_isolation();
|
|
18209
18443
|
init_plan_tool();
|
|
18210
18444
|
init_execution_plugin();
|
|
18211
18445
|
});
|
|
@@ -19402,7 +19636,7 @@ var init_check_tool = __esm(() => {
|
|
|
19402
19636
|
|
|
19403
19637
|
// src/modules/lsp/module.ts
|
|
19404
19638
|
import { existsSync as existsSync38 } from "fs";
|
|
19405
|
-
import { resolve as resolve22 } from "path";
|
|
19639
|
+
import { relative as relative3, resolve as resolve22 } from "path";
|
|
19406
19640
|
|
|
19407
19641
|
class LspModule {
|
|
19408
19642
|
name = "lsp";
|
|
@@ -19537,6 +19771,7 @@ ${items}`;
|
|
|
19537
19771
|
const errors = [];
|
|
19538
19772
|
const warnings = [];
|
|
19539
19773
|
const notes = [];
|
|
19774
|
+
const checkedFiles = [];
|
|
19540
19775
|
let checked = 0;
|
|
19541
19776
|
for (const file of files) {
|
|
19542
19777
|
const serverConfig = getServerForFile(file, this.config);
|
|
@@ -19550,6 +19785,7 @@ ${items}`;
|
|
|
19550
19785
|
const diags = await this.client.checkFile(file, ctx.baseDir, serverConfig, projectRoot);
|
|
19551
19786
|
this.failuresByServer.set(key, 0);
|
|
19552
19787
|
checked++;
|
|
19788
|
+
checkedFiles.push(relative3(ctx.baseDir, file).replace(/\\/g, "/"));
|
|
19553
19789
|
for (const d of diags) {
|
|
19554
19790
|
if (d.severity === 1)
|
|
19555
19791
|
errors.push({ file, diag: d });
|
|
@@ -19572,6 +19808,10 @@ ${items}`;
|
|
|
19572
19808
|
}
|
|
19573
19809
|
}
|
|
19574
19810
|
const lines = [];
|
|
19811
|
+
if (checked > 0) {
|
|
19812
|
+
lines.push(t("lsp.checked_files", { count: String(checked) }));
|
|
19813
|
+
lines.push(...checkedFiles.map((f) => ` ${f}`));
|
|
19814
|
+
}
|
|
19575
19815
|
if (errors.length > 0) {
|
|
19576
19816
|
lines.push(`[LSP errors] (${errors.length}):`);
|
|
19577
19817
|
lines.push(formatCheckDiagnostics(errors, ctx.baseDir));
|
|
@@ -19749,7 +19989,7 @@ var init_startup_check = __esm(() => {
|
|
|
19749
19989
|
|
|
19750
19990
|
// src/modules/indexer/walker.ts
|
|
19751
19991
|
import { readdirSync as readdirSync14, readFileSync as readFileSync22, statSync as statSync7, existsSync as existsSync40, watch } from "fs";
|
|
19752
|
-
import { join as join32, relative as
|
|
19992
|
+
import { join as join32, relative as relative4, extname as extname5 } from "path";
|
|
19753
19993
|
|
|
19754
19994
|
class Indexer {
|
|
19755
19995
|
baseDir;
|
|
@@ -19788,7 +20028,7 @@ class Indexer {
|
|
|
19788
20028
|
if (count >= this.MAX_FILES)
|
|
19789
20029
|
return;
|
|
19790
20030
|
const fullPath = join32(dir, entry);
|
|
19791
|
-
const relPath =
|
|
20031
|
+
const relPath = relative4(this.baseDir, fullPath);
|
|
19792
20032
|
const stat2 = statSync7(fullPath);
|
|
19793
20033
|
if (stat2.isDirectory()) {
|
|
19794
20034
|
if (!IGNORE_DIRS.has(entry)) {
|
|
@@ -20735,7 +20975,7 @@ async function bootstrap(configDir, projectDir, noAgentsMd, exitOnComplete) {
|
|
|
20735
20975
|
toolCtx.toolExecutor = toolExecutor;
|
|
20736
20976
|
const hallucinationDetector = new HallucinationDetector(baseDir, llmProvider);
|
|
20737
20977
|
const moduleRegistry = new ModuleRegistry;
|
|
20738
|
-
const execModule = new ExecutionModule(baseDir, config.stuckThreshold);
|
|
20978
|
+
const execModule = new ExecutionModule(baseDir, config.stuckThreshold, config.errorWebSearch?.threshold ?? 5);
|
|
20739
20979
|
const activeMeta = sessionManager.getActiveMeta();
|
|
20740
20980
|
if (activeMeta && activeMeta.messageCount > 0) {
|
|
20741
20981
|
execModule.restorePlan();
|
|
@@ -30940,9 +31180,9 @@ import * as readline2 from "readline";
|
|
|
30940
31180
|
|
|
30941
31181
|
// src/ui/line-math.ts
|
|
30942
31182
|
init_string_width();
|
|
30943
|
-
var
|
|
31183
|
+
var ANSI_RE2 = /\x1b\[[0-9;?]*[ -/]*[@-~]/g;
|
|
30944
31184
|
function stripAnsi2(s) {
|
|
30945
|
-
return s.replace(
|
|
31185
|
+
return s.replace(ANSI_RE2, "");
|
|
30946
31186
|
}
|
|
30947
31187
|
function charLen(s) {
|
|
30948
31188
|
return Array.from(s).length;
|
|
@@ -31996,6 +32236,7 @@ init_box();
|
|
|
31996
32236
|
init_table();
|
|
31997
32237
|
init_i18n();
|
|
31998
32238
|
var GUTTER = " ";
|
|
32239
|
+
var BUSY_TOOLS = new Set(["lsp_check"]);
|
|
31999
32240
|
function toolMarker(tool) {
|
|
32000
32241
|
switch (tool) {
|
|
32001
32242
|
case "write_file":
|
|
@@ -32115,6 +32356,9 @@ ${pc2.dim("⚙")} ${friendlyTool(tool)}${summary ? ` ${pc2.dim(summary)}` : ""}$
|
|
|
32115
32356
|
this.out.write(`
|
|
32116
32357
|
${pc2.dim(marker)} ${friendlyTool(tool)}${summary ? ` ${pc2.dim(summary)}` : ""}${step}
|
|
32117
32358
|
`);
|
|
32359
|
+
if (BUSY_TOOLS.has(tool)) {
|
|
32360
|
+
this.spinner.start(t("ui.tool_running", { tool: friendlyTool(tool) }));
|
|
32361
|
+
}
|
|
32118
32362
|
return;
|
|
32119
32363
|
}
|
|
32120
32364
|
this.spinner.start(`${pc2.dim("⚙")} ${friendlyTool(tool)}${summary ? ` ${pc2.dim(summary)}` : ""}${step}`);
|