micro-models-agent 0.16.4 → 0.16.5

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/cli/repl.js CHANGED
@@ -753,6 +753,19 @@ export class Repl {
753
753
  }
754
754
  });
755
755
  }
756
+ // SIGINT: first Ctrl+C sends graceful shutdown, second forces exit
757
+ process.on("SIGINT", () => {
758
+ if (this.agentRunning) {
759
+ console.log(pc.yellow("\n[Ctrl+C] Остановка агента... (ещё раз — принудительно)"));
760
+ this.agent.shutdown();
761
+ this.agentRunning = false;
762
+ // Force exit after 2s if graceful shutdown hangs
763
+ setTimeout(() => process.exit(1), 2000).unref();
764
+ }
765
+ else {
766
+ process.exit(0);
767
+ }
768
+ });
756
769
  }
757
770
  isMultiLineInput(line) {
758
771
  if (line.endsWith("\\"))
@@ -9,6 +9,7 @@ const TOOL_RESULT_ABSOLUTE_MAX_CHARS = 15000;
9
9
  export class Agent {
10
10
  deps;
11
11
  systemPromptAdded = false;
12
+ shutdownRequested = false;
12
13
  constructor(deps) {
13
14
  this.deps = deps;
14
15
  }
@@ -115,7 +116,7 @@ export class Agent {
115
116
  const MAX_HALLUCINATION_RETRIES = 3;
116
117
  let consecutiveToolFailures = 0;
117
118
  const MAX_CONSECUTIVE_TOOL_FAILURES = 5;
118
- while (iteration < config.maxToolIterations) {
119
+ while (iteration < config.maxToolIterations && !this.shutdownRequested) {
119
120
  iteration++;
120
121
  pluginManager.runOnBeforeThink({
121
122
  iteration,
@@ -445,6 +446,7 @@ export class Agent {
445
446
  }
446
447
  }
447
448
  shutdown() {
449
+ this.shutdownRequested = true;
448
450
  const { pluginManager, logger, sessionManager, contextManager } = this.deps;
449
451
  contextManager.onCompact = null;
450
452
  const killed = processRegistry.killAll();
@@ -43,7 +43,9 @@ function extractBaseCommand(trimmed) {
43
43
  // Extract basename from path (e.g. /usr/bin/rm → rm)
44
44
  const raw = tokens[i];
45
45
  const parts = raw.split(/[\\/]/);
46
- return parts[parts.length - 1] || raw;
46
+ const basename = parts[parts.length - 1] || raw;
47
+ // Strip .exe/.cmd/.bat extensions for blacklist matching (e.g. powershell.exe → powershell)
48
+ return basename.replace(/\.(exe|cmd|bat)$/i, '') || basename;
47
49
  }
48
50
  /**
49
51
  * Check if a shell operator appears as a standalone token in the command.
@@ -114,7 +116,7 @@ export function isCommandAllowed(command, securityConfig) {
114
116
  };
115
117
  }
116
118
  // Also check the raw first token in case it's a simple name
117
- const rawFirst = trimmedCommand.split(/\s+/)[0];
119
+ const rawFirst = trimmedCommand.split(/\s+/)[0].replace(/\.(exe|cmd|bat)$/i, '');
118
120
  if (rawFirst !== baseCommand && config.blacklist.includes(rawFirst)) {
119
121
  return {
120
122
  allowed: false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "micro-models-agent",
3
- "version": "0.16.4",
3
+ "version": "0.16.5",
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": {