Skip to content

Commit acafd08

Browse files
committed
wtf fix, new methods to get terminal history
1 parent 76e87ec commit acafd08

File tree

2 files changed

+165
-21
lines changed

2 files changed

+165
-21
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ packages = [
44
{include = "interpreter"},
55
{include = "scripts"},
66
]
7-
version = "0.3.5" # Use "-rc1", "-rc2", etc. for pre-release versions
7+
version = "0.3.6" # Use "-rc1", "-rc2", etc. for pre-release versions
88
description = "Let language models run code"
99
authors = ["Killian Lucas <[email protected]>"]
1010
readme = "README.md"

scripts/wtf.py

Lines changed: 164 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import os
77
import platform
88
import re
9+
import subprocess
910
import time
1011

1112
import platformdirs
@@ -49,33 +50,176 @@
4950

5051
def main():
5152
keyboard = Controller()
53+
history = None
5254

53-
# Save clipboard
54-
clipboard = pyperclip.paste()
55+
## SELECT ALL AND COPY METHOD
5556

56-
# Select all text
57-
shortcut_key = Key.cmd if platform.system() == "Darwin" else Key.ctrl
58-
with keyboard.pressed(shortcut_key):
59-
keyboard.press("a")
60-
keyboard.release("a")
57+
if True:
58+
# Save clipboard
59+
clipboard = pyperclip.paste()
6160

62-
# Copy selected text
63-
with keyboard.pressed(shortcut_key):
64-
keyboard.press("c")
65-
keyboard.release("c")
61+
# Select all text
62+
shortcut_key = Key.cmd if platform.system() == "Darwin" else Key.ctrl
63+
with keyboard.pressed(shortcut_key):
64+
keyboard.press("a")
65+
keyboard.release("a")
6666

67-
# Deselect
68-
keyboard.press(Key.backspace)
69-
keyboard.release(Key.backspace)
67+
# Copy selected text
68+
with keyboard.pressed(shortcut_key):
69+
keyboard.press("c")
70+
keyboard.release("c")
7071

71-
# Wait for the clipboard to update
72-
time.sleep(0.1)
72+
# Deselect
73+
keyboard.press(Key.backspace)
74+
keyboard.release(Key.backspace)
7375

74-
# Get terminal history from clipboard
75-
history = pyperclip.paste()
76+
# Wait for the clipboard to update
77+
time.sleep(0.1)
7678

77-
# Reset clipboard to stored one
78-
pyperclip.copy(clipboard)
79+
# Get terminal history from clipboard
80+
history = pyperclip.paste()
81+
82+
# Reset clipboard to stored one
83+
pyperclip.copy(clipboard)
84+
85+
## OCR SCREENSHOT METHOD
86+
87+
if not history:
88+
try:
89+
import pytesseract
90+
from PIL import ImageGrab
91+
92+
# Get active window coordinates using platform-specific methods
93+
platform_name = platform.system()
94+
if platform_name == "Windows":
95+
import win32gui
96+
97+
window = win32gui.GetForegroundWindow()
98+
left, top, right, bottom = win32gui.GetWindowRect(window)
99+
elif platform_name == "Darwin":
100+
from Quartz import (
101+
CGWindowListCopyWindowInfo,
102+
kCGNullWindowID,
103+
kCGWindowListOptionOnScreenOnly,
104+
)
105+
106+
window_info = CGWindowListCopyWindowInfo(
107+
kCGWindowListOptionOnScreenOnly, kCGNullWindowID
108+
)
109+
for window in window_info:
110+
if window["kCGWindowLayer"] == 0:
111+
window_geometry = window["kCGWindowBounds"]
112+
left = window_geometry["X"]
113+
top = window_geometry["Y"]
114+
right = int(left + window_geometry["Width"])
115+
bottom = int(top + window_geometry["Height"])
116+
break
117+
else: # Assume it's a Linux-based system
118+
root = subprocess.Popen(
119+
["xprop", "-root", "_NET_ACTIVE_WINDOW"], stdout=subprocess.PIPE
120+
)
121+
stdout, stderr = root.communicate()
122+
m = re.search(b"^_NET_ACTIVE_WINDOW.* ([\\w]+)$", stdout)
123+
if m is not None:
124+
window_id = m.group(1)
125+
window = subprocess.Popen(
126+
["xwininfo", "-id", window_id], stdout=subprocess.PIPE
127+
)
128+
stdout, stderr = window.communicate()
129+
match = re.search(
130+
rb"Absolute upper-left X:\s*(\d+).*Absolute upper-left Y:\s*(\d+).*Width:\s*(\d+).*Height:\s*(\d+)",
131+
stdout,
132+
re.DOTALL,
133+
)
134+
if match is not None:
135+
left, top, width, height = map(int, match.groups())
136+
right = left + width
137+
bottom = top + height
138+
139+
# spinner.stop()
140+
# print("\nPermission to capture terminal commands via screenshot -> OCR?")
141+
# permission = input("(y/n) > ")
142+
# print("")
143+
# if permission.lower() != 'y':
144+
# print("Exiting...")
145+
# exit()
146+
# spinner.start()
147+
148+
# Take screenshot of the active window
149+
screenshot = ImageGrab.grab(
150+
bbox=(int(left), int(top), int(right), int(bottom))
151+
)
152+
153+
# OCR the screenshot to get the text
154+
text = pytesseract.image_to_string(screenshot)
155+
156+
history = text
157+
158+
if "wtf" in history:
159+
last_wtf_index = history.rindex("wtf")
160+
history = history[:last_wtf_index]
161+
except ImportError:
162+
spinner.stop()
163+
print(
164+
"To use OCR to capture terminal output (recommended) run `pip install pytesseract` or `pip3 install pytesseract`."
165+
)
166+
spinner.start()
167+
168+
## TERMINAL HISTORY METHOD
169+
170+
if not history:
171+
try:
172+
shell = os.environ.get("SHELL", "/bin/bash")
173+
command = [shell, "-ic", "fc -ln -10"] # Get just the last command
174+
175+
output = subprocess.check_output(command, stderr=subprocess.STDOUT).decode(
176+
"utf-8"
177+
)
178+
179+
# Split the output into lines
180+
lines = output.strip().split("\n")
181+
182+
# Filter out lines that look like the "saving session" message
183+
history = [
184+
line
185+
for line in lines
186+
if not line.startswith("...")
187+
and "saving" not in line
188+
and "Saving session..." not in line
189+
]
190+
history = [l.strip() for l in history if l.strip()][-10:]
191+
192+
# Split the history into individual commands
193+
194+
# Get the last command
195+
last_command = history[-1]
196+
spinner.start()
197+
print(
198+
f"\nRunning the last command again to collect its output: {last_command}\n"
199+
)
200+
spinner.stop()
201+
# Run the last command and collect its output
202+
try:
203+
last_command_output = subprocess.check_output(
204+
last_command, shell=True, stderr=subprocess.STDOUT
205+
).decode("utf-8")
206+
except subprocess.CalledProcessError as e:
207+
last_command_output = e.output.decode("utf-8")
208+
except Exception as e:
209+
last_command_output = str(e)
210+
211+
# Format the history
212+
history = "The user tried to run the following commands:\n" + "\n".join(
213+
history
214+
)
215+
history += f"\nThe last command, {last_command}, resulted in this output:\n{last_command_output}"
216+
217+
except Exception as e:
218+
raise
219+
print(
220+
"Failed to retrieve and run the last command from terminal history. Exiting."
221+
)
222+
return
79223

80224
# Trim history
81225
history = history[-9000:].strip()

0 commit comments

Comments
 (0)