ayechat-dev 0.36.8.20260126124453__py3-none-any.whl → 0.36.9.20260201141756__py3-none-any.whl

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.
aye/controller/repl.py CHANGED
@@ -1,7 +1,7 @@
1
1
  import os
2
2
  import json
3
3
  from pathlib import Path
4
- from typing import Optional, Any
4
+ from typing import Optional, Any, List
5
5
  import shlex
6
6
  import threading
7
7
  import glob
@@ -252,6 +252,34 @@ def create_prompt_session(completer: Any, completion_style: str = "readline") ->
252
252
  )
253
253
 
254
254
 
255
+ def _execute_forced_shell_command(command: str, args: List[str], conf: Any) -> None:
256
+ """Execute a shell command with force flag (bypasses command validation).
257
+
258
+ Used when user prefixes input with '!' to force shell execution.
259
+
260
+ Args:
261
+ command: The command to execute
262
+ args: List of arguments to pass to the command
263
+ conf: Configuration object with plugin_manager
264
+ """
265
+ telemetry.record_command(command, has_args=len(args) > 0, prefix=_CMD_PREFIX)
266
+ shell_response = conf.plugin_manager.handle_command(
267
+ "execute_shell_command",
268
+ {"command": command, "args": args, "force": True}
269
+ )
270
+ if shell_response is not None:
271
+ if "stdout" in shell_response or "stderr" in shell_response:
272
+ if shell_response.get("stdout", "").strip():
273
+ rprint(shell_response["stdout"])
274
+ if shell_response.get("stderr", "").strip():
275
+ rprint(f"[yellow]{shell_response['stderr']}[/]")
276
+ if "error" in shell_response:
277
+ rprint(f"[red]Error:[/] {shell_response['error']}")
278
+ elif "message" in shell_response:
279
+ rprint(shell_response["message"])
280
+ else:
281
+ rprint(f"[red]Error:[/] Failed to execute shell command")
282
+
255
283
 
256
284
  def chat_repl(conf: Any) -> None:
257
285
  is_first_run = run_first_time_tutorial_if_needed()
@@ -327,6 +355,14 @@ def chat_repl(conf: Any) -> None:
327
355
  chat_id = new_chat_id
328
356
  continue
329
357
 
358
+ # Check for '!' prefix - force shell execution
359
+ force_shell = False
360
+ if prompt.strip().startswith('!'):
361
+ force_shell = True
362
+ prompt = prompt.strip()[1:] # Remove the '!'
363
+ if not prompt.strip():
364
+ continue # Nothing after the '!', skip
365
+
330
366
  if not prompt.strip():
331
367
  continue
332
368
  tokens = shlex.split(prompt.strip(), posix=False)
@@ -340,6 +376,11 @@ def chat_repl(conf: Any) -> None:
340
376
 
341
377
  original_first, lowered_first = tokens[0], tokens[0].lower()
342
378
 
379
+ # If force_shell is True, execute as shell command directly and skip all other checks
380
+ if force_shell:
381
+ _execute_forced_shell_command(original_first, tokens[1:], conf)
382
+ continue
383
+
343
384
  # Normalize slash-prefixed commands: /restore -> restore, /model -> model, etc.
344
385
  if lowered_first.startswith('/'):
345
386
  lowered_first = lowered_first[1:] # Remove leading slash
@@ -10,7 +10,7 @@ from rich import print as rprint
10
10
 
11
11
  class ShellExecutorPlugin(Plugin):
12
12
  name = "shell_executor"
13
- version = "1.0.2" # Fixed Windows localization bug in command detection
13
+ version = "1.0.3" # Added force parameter for ! prefix execution
14
14
  premium = "free"
15
15
 
16
16
  # Known interactive commands that require a TTY (add more as needed)
@@ -143,15 +143,17 @@ class ShellExecutorPlugin(Plugin):
143
143
  "returncode": e.returncode
144
144
  }
145
145
  except FileNotFoundError:
146
- return None # Command not found
146
+ return {"error": f"Command not found: {command}", "stdout": "", "stderr": "", "returncode": 127}
147
147
 
148
148
  def on_command(self, command_name: str, params: Dict[str, Any]) -> Optional[Dict[str, Any]]:
149
149
  """Handle shell command execution through plugin system."""
150
150
  if command_name == "execute_shell_command":
151
151
  command = params.get("command", "")
152
152
  args = params.get("args", [])
153
+ force = params.get("force", False)
153
154
 
154
- if not self._is_valid_command(command):
155
+ # If force is False, validate the command exists first
156
+ if not force and not self._is_valid_command(command):
155
157
  return None # Command not found or not executable
156
158
 
157
159
  full_cmd_str = self._build_full_cmd(command, args)
aye/presenter/repl_ui.py CHANGED
@@ -87,7 +87,7 @@ def print_help_message():
87
87
  commands = [
88
88
  # Some commands are intentionally undocumented: keep them as such.
89
89
  ("@filename", "Include a file in your prompt inline (e.g., \"explain @main.py\"). Supports wildcards (e.g., @*.py, @src/*.js)."),
90
- ("blog <intent>", "Generate a technical deep-dive blog post derived from the current chat session and write it to blog.md."),
90
+ ("!command", "Force shell execution (e.g., \"!echo hello\")."),
91
91
  ("model", "Select a different model. Selection will persist between sessions."),
92
92
  (r"verbose \[on|off]", "Toggle verbose mode to increase or decrease chattiness (on/off, persists between sessions)"),
93
93
  (r"completion \[readline|multi]", "Switch auto-completion style (readline or multi, persists between sessions)"),
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ayechat-dev
3
- Version: 0.36.8.20260126124453
3
+ Version: 0.36.9.20260201141756
4
4
  Summary: Aye Chat: Terminal-first AI Code Generator
5
5
  Author-email: "Acrotron, Inc." <info@acrotron.com>
6
6
  License: MIT
@@ -8,7 +8,7 @@ aye/controller/commands.py,sha256=sXmK_sgNBrw9Fs7mKcr93-wsu740ZlvWSisQfS-1EUE,12
8
8
  aye/controller/llm_handler.py,sha256=BSBab6onF9BYiFndYW1647eEy377Vt52trzu0Qjm4bQ,5075
9
9
  aye/controller/llm_invoker.py,sha256=p_Vk2a3YrWKwDupLfSVRinR5llDfq1Fb_f7WrYozK6M,14127
10
10
  aye/controller/plugin_manager.py,sha256=9ZuITyA5sQJJJU-IntLQ1SsxXsDnbgZKPOF4e9VmsEU,3018
11
- aye/controller/repl.py,sha256=FOw8jH2gJp8DcNrSiUZkwrqB-qtDZ4b_9HwwpK4jiHY,24697
11
+ aye/controller/repl.py,sha256=UCgH4bdL3AUYjgD6KPtIOeysCNaYbs0TvEwS3Zql8kY,26552
12
12
  aye/controller/tutorial.py,sha256=lc92jOcJOYCVrrjTEF0Suk4-8jn-ku98kTJEIL8taUA,7254
13
13
  aye/controller/util.py,sha256=gBmktDEaY63OKhgzZHA2IFrgcWUN_Iphn3e1daEeUBI,2828
14
14
  aye/model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -45,17 +45,17 @@ aye/plugins/completer.py,sha256=qhxke5Q76P2u0LojSIL3V48RTNG5tWL-5-TK5tNutrE,1389
45
45
  aye/plugins/local_model.py,sha256=Jj4bHiPYaLMx6zTrKamBPrkiGQQ787jWz0F4ojRCjlQ,14394
46
46
  aye/plugins/offline_llm.py,sha256=qFmd1e8Lbl7yiMgXpXjOQkQTNxOk0_WXU7km2DTKXGY,13357
47
47
  aye/plugins/plugin_base.py,sha256=t5hTOnA0dZC237BnseAgdXbOqErlSCNLUo_Uul09TSw,1673
48
- aye/plugins/shell_executor.py,sha256=B4R04pJsjS6uy7z4MP_WcbxMPB6ct8V3BNFp9JMldrE,7317
48
+ aye/plugins/shell_executor.py,sha256=a0mlZnQeURONdtPM7iageTcQ8PiNLQbjxoY54EsS32o,7502
49
49
  aye/plugins/slash_completer.py,sha256=MyrDTC_KwVWhtD_kpHbu0WjSjmSAWp36PwOBQczSuXA,2252
50
50
  aye/presenter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
51
51
  aye/presenter/cli_ui.py,sha256=8oHqQiMHO8hHXCTdqWoquMkJBshl2_3-YWN6SQnlbKg,8449
52
52
  aye/presenter/diff_presenter.py,sha256=cbxfOEqGomPTDvQpKdybfYeNUD2DYVAl85j1uy5--Ww,12512
53
- aye/presenter/repl_ui.py,sha256=OTJlcqNdNoaAwfEUqallig45rIzMoKa0dUSxk6Io4jU,7979
53
+ aye/presenter/repl_ui.py,sha256=J6QlcFa_qvV00NP1OS5xyhDuJcfNcCrADZq9ZFY2GKQ,7917
54
54
  aye/presenter/streaming_ui.py,sha256=_3tBEuNH9UQ9Gyq2yuvRfX4SWVkcGMYirEUGj-MXVJ0,12768
55
55
  aye/presenter/ui_utils.py,sha256=6KXR4_ZZZUdF5pCHrPqO8yywlQk7AOzWe-2B4Wj_-ZQ,5441
56
- ayechat_dev-0.36.8.20260126124453.dist-info/licenses/LICENSE,sha256=U1ou6lkMKmPo16-E9YowIu3goU7sOWKUprGo0AOA72s,1065
57
- ayechat_dev-0.36.8.20260126124453.dist-info/METADATA,sha256=8yGbe7K_dhHm0RDKT9q7aPPrmBPKbU0oel9e4Igp4ws,7718
58
- ayechat_dev-0.36.8.20260126124453.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
59
- ayechat_dev-0.36.8.20260126124453.dist-info/entry_points.txt,sha256=KGsOma6szoefNN6vHozg3Pbf1fjZ7ZbmwrOiVwBd0Ik,41
60
- ayechat_dev-0.36.8.20260126124453.dist-info/top_level.txt,sha256=7WZL0LOx4-GKKvgU1mtI5s4Dhk2OdieVZZvVnxFJHr8,4
61
- ayechat_dev-0.36.8.20260126124453.dist-info/RECORD,,
56
+ ayechat_dev-0.36.9.20260201141756.dist-info/licenses/LICENSE,sha256=U1ou6lkMKmPo16-E9YowIu3goU7sOWKUprGo0AOA72s,1065
57
+ ayechat_dev-0.36.9.20260201141756.dist-info/METADATA,sha256=1whf_VoyU8Vt49wLxnbCTCtt6vLGS1NtXCsJDaRqFQI,7718
58
+ ayechat_dev-0.36.9.20260201141756.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
59
+ ayechat_dev-0.36.9.20260201141756.dist-info/entry_points.txt,sha256=KGsOma6szoefNN6vHozg3Pbf1fjZ7ZbmwrOiVwBd0Ik,41
60
+ ayechat_dev-0.36.9.20260201141756.dist-info/top_level.txt,sha256=7WZL0LOx4-GKKvgU1mtI5s4Dhk2OdieVZZvVnxFJHr8,4
61
+ ayechat_dev-0.36.9.20260201141756.dist-info/RECORD,,