micro-models-agent 0.21.0 → 0.22.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.
Files changed (2) hide show
  1. package/dist/main.js +176 -70
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -1888,6 +1888,7 @@ var require_commander = __commonJS((exports) => {
1888
1888
  // src/config/security.ts
1889
1889
  function mergeSecurityConfig(userConfig) {
1890
1890
  return {
1891
+ enabled: userConfig?.enabled ?? DEFAULT_SECURITY_CONFIG.enabled,
1891
1892
  bash: {
1892
1893
  ...DEFAULT_SECURITY_CONFIG.bash,
1893
1894
  ...userConfig?.bash
@@ -1923,7 +1924,9 @@ function mergeSecurityConfig(userConfig) {
1923
1924
  var DEFAULT_SECURITY_CONFIG;
1924
1925
  var init_security = __esm(() => {
1925
1926
  DEFAULT_SECURITY_CONFIG = {
1927
+ enabled: false,
1926
1928
  bash: {
1929
+ enabled: false,
1927
1930
  blacklist: [
1928
1931
  "rm",
1929
1932
  "dd",
@@ -1985,6 +1988,7 @@ var init_security = __esm(() => {
1985
1988
  dangerousOperators: [">", ">>", "2>", "2>>", "`"]
1986
1989
  },
1987
1990
  paths: {
1991
+ enabled: false,
1988
1992
  denied: [
1989
1993
  ".git/",
1990
1994
  "node_modules/",
@@ -2004,6 +2008,7 @@ var init_security = __esm(() => {
2004
2008
  allowed: []
2005
2009
  },
2006
2010
  network: {
2011
+ enabled: false,
2007
2012
  deniedDomains: ["localhost", "127.0.0.1", "::1"],
2008
2013
  allowedDomains: [],
2009
2014
  requestTimeout: 15000,
@@ -2304,7 +2309,6 @@ Command: {command}`,
2304
2309
  "tool.friendly.process_log": "Process output",
2305
2310
  "tool.friendly.process_kill": "Stopping process",
2306
2311
  "plan.no_steps": "No plan steps specified. Provide concrete steps with files and commands.",
2307
- "plan.bad_steps": "Plan step quality unacceptable. Each step must describe concrete deliverables (files, packages, commands). Minimum 20 chars per step. Errors: {errors}",
2308
2312
  "plan.created": "Plan created: {title} ({steps} steps)",
2309
2313
  "plan.step_done": "Step {n}/{total}: {description} ✓",
2310
2314
  "plan.complete": "Task complete: {summary}",
@@ -2549,16 +2553,15 @@ Available commands:`,
2549
2553
  {content}
2550
2554
 
2551
2555
  Use this knowledge to answer the user's question.`,
2552
- "exec.stuck": "Stuck on step {stepId}. Current: {description}. No progress for {iterations} iterations.",
2553
- "exec.stuck_recovery": '[STUCK: {iterations} iterations on step {stepId} — "{description}". You MUST change approach NOW. Concrete actions: (1) Check what this step needs are dependencies installed? (2) Use plan show to see the plan. (3) If commands fail — create files directly via write_file. (4) After completing the step, call plan update step={stepId} status=done. Do NOT work on other steps until this one is finished.]',
2554
- "exec.tool_errors": "Tool {tool} failed {count} times. Suggest alternative approach.",
2555
- "exec.tool_errors_recovery": "[Tool {tool} failed {count} consecutive times. DO NOT use it again. Try a different approach: (1) create files directly via write_file, (2) use a different tool for the same task, (3) if nothing works — explain the problem and skip this step via plan update step=N status=skipped with a note why.]",
2556
- "exec.repetitive_tool": "[REPETITION: you called {tool} {count} times with identical arguments and result. This is pointless. IMMEDIATELY change approach: create files directly, change arguments, or if it's a process — check its status via process_log.]",
2557
- "exec.consecutive_failures_recovery": "[{count} CONSECUTIVE TOOLS FAILED. Stop running commands. Here is what to do: (1) Create files directly via write_file instead of terminal commands. (2) Check if dependencies are installed (npm install). (3) Use list_dir to see what's in the project. (4) Do not attempt build/tests until all files are created.]",
2558
- "exec.task_reminder": "[ORIGINAL TASK: {task}. You MUST work on this task only. Do not create files for other tasks. If you cannot complete it explain why and request help.]",
2559
- "exec.plan_warning": '[⚠ PLAN: you are on step {step} — "{description}", but calling {tool} with files outside this step. This is FORBIDDEN — work STRICTLY on the current step. First complete it and call plan update step={step} status=done, only then move to the next.]',
2560
- "exec.plan_blocked": "[⛔ BLOCKED: {max} consecutive calls outside the current step. You are violating the plan. Return to step {step} and complete it. Other steps are blocked until this one is done.]",
2561
- "exec.off_track": `[⚠ OFF PLAN: step {stepId} is "{description}", but you're using {tool} on a different path. Return to the current step immediately.]`,
2556
+ "exec.stuck": "No progress on step {stepId} ({description}) for {iterations} iterations.",
2557
+ "exec.stuck_recovery": 'Step {stepId} — "{description}" has had no progress for {iterations} iterations. Try a different approach: review what this step needs, check if dependencies are installed, or create files directly via write_file instead of shell commands. After completing the step call plan update step={stepId} status=done.',
2558
+ "exec.tool_errors": "Tool {tool} failed {count} times. Consider using a different tool.",
2559
+ "exec.tool_errors_recovery": "Tool {tool} has failed {count} times in a row. Try an alternative: create files directly via write_file, use a different command, or if nothing works — skip this step via plan update step=N status=skipped with a note explaining why.",
2560
+ "exec.repetitive_tool": "Called {tool} {count} times with identical arguments and result. Try a different approach create files directly, change arguments, or check process status via process_log.",
2561
+ "exec.consecutive_failures_recovery": "{count} consecutive tool failures. Create files directly via write_file instead of terminal commands. Check that dependencies are installed (npm install). Do not run build/tests until all files are created.",
2562
+ "exec.plan_warning": 'Current plan step {step} is "{description}", but {tool} is being called for files outside this step. Complete the current step first, then call plan update step={step} status=done before moving to the next step.',
2563
+ "exec.plan_blocked": "{max} consecutive calls outside the current step. Finish step {step} before proceeding other steps should wait until this one is complete.",
2564
+ "exec.off_track": 'Step {stepId} "{description}" but you are using {tool} on a different path. Return to the current step.',
2562
2565
  "exec.step_gate_deps": '[⚠ Step {step} "{description}": dependencies are not installed. First run the install command (npm install, pip install, etc.). Verify the lock file or dependency directory exists.]',
2563
2566
  "exec.step_gate_empty": "[⚠ Step {step}: files exist but appear empty: {files}. Add real code to these files before advancing to the next step.]",
2564
2567
  "exec.step_gate_ok": '[✓] Step {step} completed and verified. MOVING to step {nextStep}: "{nextDesc}". Work ONLY on this step.',
@@ -2803,7 +2806,6 @@ var init_ru = __esm(() => {
2803
2806
  "tool.friendly.process_log": "Вывод процесса",
2804
2807
  "tool.friendly.process_kill": "Остановка процесса",
2805
2808
  "plan.no_steps": "Не указаны шаги плана. Укажите конкретные шаги с файлами и командами.",
2806
- "plan.bad_steps": "Качество шагов плана неприемлемо. Каждый шаг должен описывать конкретные deliverables (файлы, пакеты, команды). Минимум 20 символов на шаг. Ошибки: {errors}",
2807
2809
  "plan.created": "План создан: {title} ({steps} шагов)",
2808
2810
  "plan.step_done": "Шаг {n}/{total}: {description} ✓",
2809
2811
  "plan.complete": "Задача выполнена: {summary}",
@@ -3048,16 +3050,15 @@ var init_ru = __esm(() => {
3048
3050
  {content}
3049
3051
 
3050
3052
  Используйте эти знания для ответа на вопрос пользователя.`,
3051
- "exec.stuck": "Застряли на шаге {stepId}. Текущий: {description}. Нет прогресса {iterations} итераций.",
3052
- "exec.stuck_recovery": '[ЗАСТРЕВАНИЕ: {iterations} итераций на шаге {stepId} — "{description}". ВЫ ДОЛЖНЫ сменить подход прямо сейчас. Конкретные действия: (1) Проверьте что нужно для этого шага установлены ли зависимости? (2) Используйте plan show чтобы увидеть план. (3) Если команды не работают — создайте файлы напрямую через write_file. (4) После завершения шага вызовите plan update step={stepId} status=done. НЕ переходите к другим шагам пока этот не завершён.]',
3053
- "exec.tool_errors": "Инструмент {tool} сбоил {count} раз. Предложите другой подход.",
3054
- "exec.tool_errors_recovery": "[Инструмент {tool} сбоил {count} раз подряд. НЕ ИСПОЛЬЗУЙТЕ его снова. Используйте другой подход: (1) создайте нужные файлы напрямую через write_file, (2) используйте другой инструмент для той же задачи, (3) если ничего не работает — объясните проблему и переходите к следующему шагу плана через plan update step=N status=skipped с пометкой почему.]",
3055
- "exec.repetitive_tool": "[ПОВТОРЕНИЕ: вы вызвали {tool} {count} раз с одинаковыми аргументами и результатом. Это бессмысленно. НЕМЕДЛЕННО смените подход: создайте файлы напрямую, измените аргументы или, если это процесс — проверьте его статус через process_log.]",
3056
- "exec.consecutive_failures_recovery": "[{count} ИНСТРУМЕНТОВ ПОДРЯД УПАЛИ. Хватит пытаться запускать команды. Вот что делать: (1) Создавайте файлы напрямую через write_file вместо команд терминала. (2) Проверьте, установлены ли зависимости (npm install). (3) Используйте list_dir чтобы увидеть что есть в проекте. (4) Не пытайтесь запустить сборку/тесты пока не созданы все файлы.]",
3057
- "exec.task_reminder": "[ИСХОДНАЯ ЗАДАЧА: {task}. ВЫ ДОЛЖНЫ работать только над этой задачей. Не создавайте файлы для других задач. Если не можете выполнить объясните почему и запросите помощь.]",
3058
- "exec.plan_warning": '[⚠ ПЛАН: вы на шаге {step} — "{description}", но вызываете {tool} для файлов вне этого шага. Это ЗАПРЕЩЕНОработайте СТРОГО над текущим шагом. Сначала завершите его и вызовите plan update step={step} status=done, только потом переходите к следующему.]',
3059
- "exec.plan_blocked": "[⛔ ЗАБЛОКИРОВАНО: {max} вызова подряд вне текущего шага. Вы нарушаете план. Вернитесь к шагу {step} и завершите его. Другие шаги будут заблокированы пока текущий не выполнен.]",
3060
- "exec.off_track": '[⚠ ВНЕ ПЛАНА: шаг {stepId} — "{description}", но вы используете {tool} для другого пути. Вернитесь к текущему шагу немедленно.]',
3053
+ "exec.stuck": "Нет прогресса на шаге {stepId} ({description}) {iterations} итераций.",
3054
+ "exec.stuck_recovery": 'Шаг {stepId} — "{description}" без прогресса уже {iterations} итераций. Попробуйте другой подход: проверьте что нужно для этого шага, установлены ли зависимости, или создайте файлы напрямую через write_file вместо команд терминала. После завершения шага вызовите plan update step={stepId} status=done.',
3055
+ "exec.tool_errors": "Инструмент {tool} упал {count} раз. Попробуйте другой инструмент.",
3056
+ "exec.tool_errors_recovery": "Инструмент {tool} упал {count} раз подряд. Попробуйте альтернативу: создайте файлы напрямую через write_file, используйте другую команду, или пропустите этот шаг через plan update step=N status=skipped с пометкой почему.",
3057
+ "exec.repetitive_tool": "Инструмент {tool} вызван {count} раз с одинаковыми аргументами и результатом. Попробуйте другой подход создайте файлы напрямую, измените аргументы или проверьте статус процесса через process_log.",
3058
+ "exec.consecutive_failures_recovery": "{count} инструментов подряд упали. Создавайте файлы напрямую через write_file вместо команд терминала. Проверьте что зависимости установлены (npm install). Не запускайте сборку/тесты пока не созданы все файлы.",
3059
+ "exec.plan_warning": 'Текущий шаг плана {step} "{description}", но вызывается {tool} для файлов вне этого шага. Завершите текущий шаг, вызовите plan update step={step} status=done, затем переходите к следующему.',
3060
+ "exec.plan_blocked": "{max} вызовов подряд вне текущего шага. Завершите шаг {step} остальные шаги ждут пока этот не будет выполнен.",
3061
+ "exec.off_track": 'Шаг {stepId} "{description}", но используется {tool} для другого пути. Вернитесь к текущему шагу.',
3061
3062
  "exec.step_gate_deps": '[⚠ Шаг {step} "{description}": зависимости не установлены. Сначала выполните команду установки (npm install, pip install и т.д.). Проверьте что lock-файл или директория зависимостей существует.]',
3062
3063
  "exec.step_gate_empty": "[⚠ Шаг {step}: файлы существуют, но выглядят пустыми: {files}. Добавьте реальный код в эти файлы перед тем как переходить к следующему шагу.]",
3063
3064
  "exec.step_gate_ok": '[✓] Шаг {step} завершён и проверен. ПЕРЕХОДИМ к шагу {nextStep}: "{nextDesc}". Работайте ТОЛЬКО над этим шагом.',
@@ -4938,12 +4939,33 @@ function isPathInScope(baseDir, targetPath, scope, securityConfig) {
4938
4939
  const baseResolved = resolve(baseDir);
4939
4940
  const targetResolved = resolve(baseDir, normalize(targetPath));
4940
4941
  if (!targetResolved.startsWith(baseResolved)) {
4941
- return { allowed: false, reason: "Path is outside the base working directory" };
4942
+ return {
4943
+ allowed: false,
4944
+ reason: "Path is outside the base working directory"
4945
+ };
4946
+ }
4947
+ if (!securityConfig?.enabled) {
4948
+ if (scope) {
4949
+ const isReadScope = scope.read_only_files.some((f) => targetResolved.startsWith(resolve(baseDir, f)));
4950
+ const isWriteScope = scope.allowed_files.some((f) => targetResolved.startsWith(resolve(baseDir, f)));
4951
+ if (isWriteScope)
4952
+ return { allowed: true };
4953
+ if (isReadScope)
4954
+ return { allowed: true, reason: "Read-only file" };
4955
+ return {
4956
+ allowed: false,
4957
+ reason: "Path is not within the allowed scope for this sub-agent"
4958
+ };
4959
+ }
4960
+ return { allowed: true };
4942
4961
  }
4943
4962
  if (securityConfig?.denied?.length) {
4944
4963
  for (const pattern of securityConfig.denied) {
4945
4964
  if (matchesGlobPattern(targetResolved, baseDir, pattern)) {
4946
- return { allowed: false, reason: `Path matches denied pattern: ${pattern}` };
4965
+ return {
4966
+ allowed: false,
4967
+ reason: `Path matches denied pattern: ${pattern}`
4968
+ };
4947
4969
  }
4948
4970
  }
4949
4971
  }
@@ -4956,7 +4978,10 @@ function isPathInScope(baseDir, targetPath, scope, securityConfig) {
4956
4978
  }
4957
4979
  }
4958
4980
  if (!isAllowed) {
4959
- return { allowed: false, reason: "Path does not match any allowed pattern" };
4981
+ return {
4982
+ allowed: false,
4983
+ reason: "Path does not match any allowed pattern"
4984
+ };
4960
4985
  }
4961
4986
  }
4962
4987
  if (!scope) {
@@ -4977,12 +5002,30 @@ function isPathWritable(baseDir, targetPath, scope, securityConfig) {
4977
5002
  const baseResolved = resolve(baseDir);
4978
5003
  const targetResolved = resolve(baseDir, normalize(targetPath));
4979
5004
  if (!targetResolved.startsWith(baseResolved)) {
4980
- return { allowed: false, reason: "Path is outside the base working directory" };
5005
+ return {
5006
+ allowed: false,
5007
+ reason: "Path is outside the base working directory"
5008
+ };
5009
+ }
5010
+ if (!securityConfig?.enabled) {
5011
+ if (scope) {
5012
+ const isWriteScope = scope.allowed_files.some((f) => targetResolved.startsWith(resolve(baseDir, f)));
5013
+ if (isWriteScope)
5014
+ return { allowed: true };
5015
+ return {
5016
+ allowed: false,
5017
+ reason: "Path is not within the allowed scope for this sub-agent"
5018
+ };
5019
+ }
5020
+ return { allowed: true };
4981
5021
  }
4982
5022
  if (securityConfig?.denied?.length) {
4983
5023
  for (const pattern of securityConfig.denied) {
4984
5024
  if (matchesGlobPattern(targetResolved, baseDir, pattern)) {
4985
- return { allowed: false, reason: `Path matches denied pattern: ${pattern}` };
5025
+ return {
5026
+ allowed: false,
5027
+ reason: `Path matches denied pattern: ${pattern}`
5028
+ };
4986
5029
  }
4987
5030
  }
4988
5031
  }
@@ -4995,7 +5038,10 @@ function isPathWritable(baseDir, targetPath, scope, securityConfig) {
4995
5038
  }
4996
5039
  }
4997
5040
  if (!isAllowed) {
4998
- return { allowed: false, reason: "Path does not match any allowed pattern" };
5041
+ return {
5042
+ allowed: false,
5043
+ reason: "Path does not match any allowed pattern"
5044
+ };
4999
5045
  }
5000
5046
  }
5001
5047
  if (!scope) {
@@ -6419,9 +6465,15 @@ function containsOperator(command, op) {
6419
6465
  return new RegExp(escaped).test(command);
6420
6466
  }
6421
6467
  function isCommandAllowed(command, securityConfig) {
6422
- let config = securityConfig || DEFAULT_BASH_CONFIG;
6468
+ if (!securityConfig?.enabled) {
6469
+ return { allowed: true, sanitizedCommand: command };
6470
+ }
6471
+ let config = securityConfig;
6423
6472
  if (!config.blacklist || !Array.isArray(config.blacklist)) {
6424
- config = FALLBACK_BASH_CONFIG;
6473
+ config = {
6474
+ ...FALLBACK_BASH_CONFIG,
6475
+ enabled: config.enabled ?? FALLBACK_BASH_CONFIG.enabled
6476
+ };
6425
6477
  }
6426
6478
  const trimmedCommand = command.trim();
6427
6479
  if (!trimmedCommand) {
@@ -6510,7 +6562,21 @@ var FALLBACK_BASH_CONFIG, DEFAULT_BASH_CONFIG;
6510
6562
  var init_command_validator = __esm(() => {
6511
6563
  init_security();
6512
6564
  FALLBACK_BASH_CONFIG = {
6513
- blacklist: ["rm", "dd", "chmod", "wget", "curl", "scp", "ssh", "nc", "netcat", "powershell", "pwsh", "cmd"],
6565
+ enabled: false,
6566
+ blacklist: [
6567
+ "rm",
6568
+ "dd",
6569
+ "chmod",
6570
+ "wget",
6571
+ "curl",
6572
+ "scp",
6573
+ "ssh",
6574
+ "nc",
6575
+ "netcat",
6576
+ "powershell",
6577
+ "pwsh",
6578
+ "cmd"
6579
+ ],
6514
6580
  whitelist: [],
6515
6581
  blockDangerousFlags: false,
6516
6582
  dangerousFlags: ["--force", "-rf", "--no-preserve-root"],
@@ -9870,7 +9936,7 @@ Partial output: ${result.text}`
9870
9936
 
9871
9937
  // src/modules/security/network-validator.ts
9872
9938
  function isUrlAllowed(url, securityConfig) {
9873
- if (!securityConfig) {
9939
+ if (!securityConfig?.enabled) {
9874
9940
  return { allowed: true };
9875
9941
  }
9876
9942
  try {
@@ -12428,16 +12494,6 @@ class PlanCreator {
12428
12494
  baseDir
12429
12495
  };
12430
12496
  }
12431
- static validateSteps(steps) {
12432
- const errors = [];
12433
- for (let i = 0;i < steps.length; i++) {
12434
- const s = steps[i].trim();
12435
- if (s.length < MIN_STEP_DESC_LENGTH) {
12436
- errors.push(`Step ${i + 1} too short (${s.length} chars). Describe WHAT files to create, WHICH packages to install, WHICH commands to run. Minimum ${MIN_STEP_DESC_LENGTH} chars.`);
12437
- }
12438
- }
12439
- return { valid: errors.length === 0, errors };
12440
- }
12441
12497
  static toPromptBlock(plan, currentStepIndex) {
12442
12498
  const date = plan.createdAt.slice(0, 10);
12443
12499
  const lines = [
@@ -12455,7 +12511,6 @@ class PlanCreator {
12455
12511
  `);
12456
12512
  }
12457
12513
  }
12458
- var MIN_STEP_DESC_LENGTH = 20;
12459
12514
 
12460
12515
  // src/modules/execution/tracker.ts
12461
12516
  class PlanTracker {
@@ -12863,13 +12918,13 @@ class ExecutionModule {
12863
12918
  name: "plan",
12864
12919
  description: `Create, update, show, or abort a multi-step plan. Use "create" at the start of complex tasks. Use "update" after completing each step to track progress. Use "show" to re-print the current plan checklist.
12865
12920
 
12866
- IMPORTANT each step MUST be detailed and concrete:
12867
- - Specify WHICH files to create (filenames with paths, e.g. "create src/components/Header.tsx...")
12921
+ Write CONCRETE steps with exact file paths and commands:
12922
+ - Specify WHICH files to create with exact paths (e.g. "create src/components/Header.tsx with navigation and logo")
12868
12923
  - Specify WHICH packages to install (e.g. "run npm install react react-dom")
12869
- - Specify WHICH commands to run with exact arguments
12870
- - Minimum 20 characters per step description
12871
- - BAD: "Настройка проекта"
12872
- - GOOD: "Создать package.json с зависимостями react@18, vite@5, установить их через npm install"`,
12924
+ - Specify WHICH CLI commands to run with exact arguments
12925
+ - Each step should include at least one file extension (.ts, .tsx, .json, etc.) or a command verb (install, create, build, run, add, init)
12926
+ - Good: "Создать src/components/Header.tsx с навигацией и логотипом"
12927
+ - Bad: "Настройка проекта" (too vague what exactly needs to be configured?)`,
12873
12928
  parameters: {
12874
12929
  type: "object",
12875
12930
  properties: {
@@ -12893,15 +12948,6 @@ IMPORTANT — each step MUST be detailed and concrete:
12893
12948
  if (steps.length === 0) {
12894
12949
  return { success: false, output: t("plan.no_steps") };
12895
12950
  }
12896
- const validation = PlanCreator.validateSteps(steps);
12897
- if (!validation.valid) {
12898
- return {
12899
- success: false,
12900
- output: t("plan.bad_steps", {
12901
- errors: validation.errors.join("; ")
12902
- })
12903
- };
12904
- }
12905
12951
  const plan = PlanCreator.createPlan(title, steps, this.baseDir);
12906
12952
  this.setPlan(plan);
12907
12953
  const display = PlanCreator.toPromptBlock(plan, 0);
@@ -14633,21 +14679,20 @@ function buildSystemInfo(config, baseDir, profileCompressed) {
14633
14679
  `Date: ${now}`,
14634
14680
  `Workspace: ${baseDir}`,
14635
14681
  `${profileCompressed}`,
14636
- `Reply in the user's language. Use tools for filesystem, bash, web access.`,
14637
- `Use tools when needed. Explain briefly what you're doing if it's not obvious.`,
14638
- `Answer the user's question directly. Only take action when the user explicitly asks you to change, create, or fix something.`,
14639
- `If a tool call fails, report the error and ask the user how to proceed.`,
14682
+ `Reply in the user's language. Use tools for: read/write/edit/delete files, search (glob/grep), shell commands (bash), web access (web_search, web_fetch), subagents, browser, MCP.`,
14683
+ `Use tools when needed explain briefly what you're doing if it's not obvious.`,
14684
+ `If a tool call fails, analyze the error and correct the call try up to 2 times with different approaches before asking the user for help.`,
14640
14685
  ``,
14641
- `Design principles — apply them automatically without naming them:`,
14642
- `- Do not add code, files, or abstractions that are not needed right now (YAGNI — You Ain't Gonna Need It). If something is not required by the current task, omit it.`,
14643
- `- Prefer simple, straightforward solutions over clever or complex ones (KISS — Keep It Simple, Stupid). Flat code beats nested, minimal config beats flexible, explicit beats generic.`,
14644
- `- Do not duplicate code, logic, or configuration (DRY Don't Repeat Yourself). Extract shared logic into a single place, reuse existing utilities and patterns before writing new ones.`
14686
+ `Design principles:`,
14687
+ `- YAGNI: Do not add code, files, or abstractions not needed right now.`,
14688
+ `- KISS: Prefer simple, straightforward solutions over clever or complex ones.`,
14689
+ `- DRY: Do not duplicate code, logic, or configuration — reuse existing utilities and patterns.`
14645
14690
  ];
14646
14691
  if (isWin) {
14647
14692
  lines.push(``, `Windows environment — use Windows-compatible commands:`, `- Use "dir" instead of "ls". Use "dir /b" for bare listing.`, `- Use "type" or "Get-Content" instead of "cat".`, `- Use "cd" instead of "pwd". Use "echo %cd%" to print working directory.`, `- Use "copy" instead of "cp", "move" instead of "mv", "del" instead of "rm".`, `- Do not use "mkdir -p" — Windows mkdir creates intermediate dirs by default. Use the create_dir tool instead.`, `- Use forward slashes (/) or escaped backslashes (\\\\) in file paths.`, `- Your working directory is: ${baseDir}`);
14648
14693
  }
14649
- lines.push(``, `Bash tool rules:`, `- Use the "workdir" parameter to run commands in a specific directory. Do NOT chain "cd dir && cmd" — the security module blocks the "&&" operator.`, `- Run one command per tool call. Split multi-step shell operations into separate bash calls.`, `- Background processes (dev servers, watchers, long-running npm install): use the "background: true" parameter or the tool will auto-detect and background them. Check output with process_log.`);
14650
- lines.push(``, `=== DEVELOPMENT RULES — follow these strictly ===`, ``, `1. DEPENDENCIES FIRST: Before writing any source code, ALWAYS install project dependencies (e.g., "npm install", "pip install -r requirements.txt", "cargo build", "go mod tidy"). Verify the package manager's lock file or dependency directory exists. Never write code that imports/uses packages that aren't installed yet.`, `2. TOOLKIT/FWK FIRST: If the task specifies a framework or UI library, initialize and configure it BEFORE writing application code. Run its project init command first, then add components/modules. Never write your own version of what the framework already provides.`, `3. ONE STEP AT A TIME: Follow the plan sequentially. Complete step N before starting step N+1. When a step is done: verify the deliverables exist and have real content (not empty), then call "plan update step=N status=done". Do not redo completed work.`, `4. VERIFY YOUR WORK: After creating/modifying files, verify they exist on disk. After installing dependencies, verify the package manager completed successfully. After any command, check its output for errors. Don't assume operations succeeded.`, `5. NO PREMATURE WORK: Do not create files for future steps. Do not add imports/references to packages or modules that haven't been installed yet. Do not reference files or components that don't exist yet. Build incrementally — one layer at a time.`, `6. WHEN STUCK: If a command fails 2+ times, STOP and try a different approach. Write files directly instead of using commands. Ask the user for help. Never repeat the same failing command more than twice.`, ``, `=== PLAN QUALITY RULES — your plan MUST follow these ===`, ``, `- Each step must describe CONCRETE deliverables: exact filenames with paths, exact packages to install, exact CLI commands to run.`, `- A step like "Настройка проекта" or "Setup the project" is USELESS and will be REJECTED.`, `- A step like "Создать src/components/Header.tsx с хедером навигации, подключить в App.tsx" is GOOD.`, `- Include file extensions (.tsx, .css, .json) and directory paths. Never write vague steps.`, `- The plan must cover EVERYTHING needed: init → deps → framework setup → code → verification.`, `- Number of steps: 5-8 for a typical task. Too few means you're being vague. Too many means you're over-splitting.`);
14694
+ lines.push(``, `Bash tool rules:`, `- Use the "workdir" parameter to run commands in a specific directory. Prefer workdir over "cd dir && cmd" chaining.`, `- Run one command per tool call. Split multi-step shell operations into separate bash calls.`, `- Background processes (dev servers, watchers, long-running npm install): use the "background: true" parameter or the tool will auto-detect and background them. Check output with process_log.`);
14695
+ lines.push(``, `=== DEVELOPMENT RULES — follow these strictly ===`, ``, `1. DEPENDENCIES FIRST: Before writing any source code, ALWAYS install project dependencies (e.g., "npm install", "pip install -r requirements.txt", "cargo build", "go mod tidy"). Verify the package manager's lock file or dependency directory exists. Never write code that imports/uses packages that aren't installed yet.`, `2. TOOLKIT/FWK FIRST: If the task specifies a framework or UI library, initialize and configure it BEFORE writing application code. Run its project init command first, then add components/modules. Never write your own version of what the framework already provides.`, `3. ONE STEP AT A TIME: Follow the plan sequentially. Complete step N before starting step N+1. When a step is done: verify the deliverables exist and have real content (not empty), then call "plan update step=N status=done". Do not redo completed work.`, `4. VERIFY YOUR WORK: After creating/modifying files, verify they exist on disk. After installing dependencies, verify the package manager completed successfully. After any command, check its output for errors. Don't assume operations succeeded.`, `5. NO PREMATURE WORK: Do not create files for future steps. Do not add imports/references to packages or modules that haven't been installed yet. Do not reference files or components that don't exist yet. Build incrementally — one layer at a time.`, `6. WHEN STUCK: If a command fails 2+ times, STOP and try a different approach. Write files directly instead of using commands. Ask the user for help. Never repeat the same failing command more than twice.`, ``, `=== PLAN QUALITY RULES — your plan MUST follow these ===`, ``, `- Each step must describe CONCRETE deliverables: exact filenames with paths, exact packages to install, exact CLI commands to run. Avoid vague steps — be specific.`, `- A step like "Настройка проекта" or "Setup the project" is too vague describe what exactly needs to be configured or set up.`, `- A step like "Создать src/components/Header.tsx с навигацией и логотипом, добавить в src/App.tsx импорт <Header />" is GOOD.`, `- Include file extensions (.tsx, .css, .json) and directory paths. Every step must mention at least one file or command.`, `- The plan must cover EVERYTHING needed: init → deps → framework setup → code → verification.`, `- Number of steps: 5-8 for a typical task. Too few means you're being vague. Too many means you're over-splitting.`);
14651
14696
  if (config.autoPlan) {
14652
14697
  lines.push(``, `Plan rule (MANDATORY): For ANY task that requires creating files, installing packages, or multiple actions — you MUST create a plan using the "plan" tool BEFORE starting work. Each step must describe a concrete deliverable (specific files to create, packages to install, commands to run). Do not combine unrelated work into one step.`);
14653
14698
  }
@@ -15708,7 +15753,9 @@ var STRICT_POLICY = {
15708
15753
  preset: "strict",
15709
15754
  recommendedFor: ["production", "sensitive-data", "multi-user", "enterprise"],
15710
15755
  config: {
15756
+ enabled: true,
15711
15757
  bash: {
15758
+ enabled: true,
15712
15759
  blacklist: [
15713
15760
  "rm",
15714
15761
  "dd",
@@ -15767,10 +15814,22 @@ var STRICT_POLICY = {
15767
15814
  "-R",
15768
15815
  "--no-clobber"
15769
15816
  ],
15770
- dangerousOperators: [">", ">>", "2>", "2>>", "|", "&&", "||", ";", "&", "`"],
15817
+ dangerousOperators: [
15818
+ ">",
15819
+ ">>",
15820
+ "2>",
15821
+ "2>>",
15822
+ "|",
15823
+ "&&",
15824
+ "||",
15825
+ ";",
15826
+ "&",
15827
+ "`"
15828
+ ],
15771
15829
  logCommands: true
15772
15830
  },
15773
15831
  paths: {
15832
+ enabled: true,
15774
15833
  denied: [
15775
15834
  ".git/",
15776
15835
  "node_modules/",
@@ -15803,6 +15862,7 @@ var STRICT_POLICY = {
15803
15862
  allowed: []
15804
15863
  },
15805
15864
  network: {
15865
+ enabled: true,
15806
15866
  deniedDomains: [
15807
15867
  "localhost",
15808
15868
  "127.0.0.1",
@@ -15874,7 +15934,9 @@ var BALANCED_POLICY = {
15874
15934
  preset: "balanced",
15875
15935
  recommendedFor: ["development", "single-user", "general-use", "testing"],
15876
15936
  config: {
15937
+ enabled: true,
15877
15938
  bash: {
15939
+ enabled: true,
15878
15940
  blacklist: [
15879
15941
  "rm",
15880
15942
  "dd",
@@ -15920,6 +15982,7 @@ var BALANCED_POLICY = {
15920
15982
  logCommands: true
15921
15983
  },
15922
15984
  paths: {
15985
+ enabled: true,
15923
15986
  denied: [
15924
15987
  ".git/",
15925
15988
  "node_modules/",
@@ -15940,6 +16003,7 @@ var BALANCED_POLICY = {
15940
16003
  allowed: []
15941
16004
  },
15942
16005
  network: {
16006
+ enabled: true,
15943
16007
  deniedDomains: [],
15944
16008
  allowedDomains: [],
15945
16009
  requestTimeout: 15000,
@@ -15975,7 +16039,12 @@ var BALANCED_POLICY = {
15975
16039
  auditNotifier: {
15976
16040
  enabled: false,
15977
16041
  minSeverity: "medium",
15978
- eventTypes: ["security_block", "bash_command", "file_operation", "network_request"],
16042
+ eventTypes: [
16043
+ "security_block",
16044
+ "bash_command",
16045
+ "file_operation",
16046
+ "network_request"
16047
+ ],
15979
16048
  maxRetries: 3
15980
16049
  }
15981
16050
  }
@@ -15986,7 +16055,9 @@ var PERMISSIVE_POLICY = {
15986
16055
  preset: "permissive",
15987
16056
  recommendedFor: ["trusted-environment", "local-dev", "testing", "sandbox"],
15988
16057
  config: {
16058
+ enabled: true,
15989
16059
  bash: {
16060
+ enabled: true,
15990
16061
  blacklist: [
15991
16062
  "rm",
15992
16063
  "dd",
@@ -16006,10 +16077,12 @@ var PERMISSIVE_POLICY = {
16006
16077
  logCommands: true
16007
16078
  },
16008
16079
  paths: {
16080
+ enabled: true,
16009
16081
  denied: [".env", "*.key", "*.pem", "*.crt", "*.p12", "*.pfx"],
16010
16082
  allowed: []
16011
16083
  },
16012
16084
  network: {
16085
+ enabled: true,
16013
16086
  deniedDomains: [],
16014
16087
  allowedDomains: [],
16015
16088
  requestTimeout: 30000,
@@ -16314,6 +16387,37 @@ function createProgram() {
16314
16387
  config.contextWindow = answers.contextWindow;
16315
16388
  config.maxToolIterations = answers.maxToolIterations;
16316
16389
  config.locale = answers.locale;
16390
+ if (config.security) {
16391
+ config.security.enabled = answers.securityBashBlock || answers.securityFlagsBlock || !answers.securityPathsDeny;
16392
+ config.security.bash.enabled = config.security.enabled;
16393
+ config.security.bash.blockDangerousFlags = answers.securityFlagsBlock;
16394
+ if (answers.securityBashBlock) {
16395
+ config.security.bash.blacklist = [
16396
+ ...new Set([
16397
+ ...config.security.bash.blacklist,
16398
+ "rm",
16399
+ "dd",
16400
+ "chmod",
16401
+ "wget",
16402
+ "curl",
16403
+ "scp",
16404
+ "ssh",
16405
+ "nc",
16406
+ "netcat",
16407
+ "sudo",
16408
+ "su",
16409
+ "kill",
16410
+ "pkill",
16411
+ "killall",
16412
+ "shutdown",
16413
+ "reboot"
16414
+ ])
16415
+ ];
16416
+ }
16417
+ if (!answers.securityPathsDeny) {
16418
+ config.security.paths.denied = [];
16419
+ }
16420
+ }
16317
16421
  saveConfig(config, configPath);
16318
16422
  console.log(t("cli.config_saved"));
16319
16423
  });
@@ -17945,6 +18049,8 @@ async function main() {
17945
18049
  config2.maxToolIterations = answers.maxToolIterations;
17946
18050
  config2.locale = answers.locale;
17947
18051
  if (config2.security) {
18052
+ config2.security.enabled = answers.securityBashBlock || answers.securityFlagsBlock || !answers.securityPathsDeny;
18053
+ config2.security.bash.enabled = config2.security.enabled;
17948
18054
  config2.security.bash.blockDangerousFlags = answers.securityFlagsBlock;
17949
18055
  if (answers.securityBashBlock) {
17950
18056
  config2.security.bash.blacklist = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "micro-models-agent",
3
- "version": "0.21.0",
3
+ "version": "0.22.0",
4
4
  "description": "Micro Models Agent (MMA) — LLM agent harness for small models (Qwen3.5-9B, 32K-64K context)",
5
5
  "type": "module",
6
6
  "bin": {