Compare commits
17 Commits
26c6e32c59
...
2025.06.07
| Author | SHA1 | Date | |
|---|---|---|---|
| f18c31df6c | |||
| ca0e3b5987 | |||
| 0009d90a68 | |||
| 2c2efc56f0 | |||
| 3dca3e5b23 | |||
| 27c35939b1 | |||
| 7e87ebf04b | |||
| ec6c135581 | |||
| 998c63cc71 | |||
| 1b9a9a90b1 | |||
| 4c8c8d896d | |||
| 4672592dba | |||
| 7a12992b88 | |||
| 7a87fb51bb | |||
| 2cc2fda28c | |||
| c99d0f6ee1 | |||
| 5b642cd9e2 |
@@ -6,3 +6,4 @@ dist/
|
||||
build/
|
||||
*.kate-swp
|
||||
.directory
|
||||
CLAUDE.md
|
||||
|
||||
@@ -75,9 +75,10 @@ KEY_FENRIR,KEY_F2=toggle_braille
|
||||
KEY_FENRIR,KEY_F3=toggle_sound
|
||||
KEY_FENRIR,KEY_F4=toggle_speech
|
||||
KEY_FENRIR,KEY_ENTER=temp_disable_speech
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_ENTER=silence_until_prompt
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_CTRL,KEY_P=toggle_punctuation_level
|
||||
KEY_FENRIR,KEY_RIGHTBRACE=toggle_auto_spell_check
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_ENTER=toggle_output
|
||||
KEY_FENRIR,KEY_CTRL,KEY_SHIFT,KEY_ENTER=toggle_output
|
||||
KEY_FENRIR,KEY_SHIFT,KEY_E=toggle_emoticons
|
||||
KEY_FENRIR,KEY_ENTER=toggle_auto_read
|
||||
KEY_FENRIR,KEY_CTRL,KEY_T=toggle_auto_time
|
||||
|
||||
@@ -29,7 +29,7 @@ genericPlayFileCommand=play -q -v fenrirVolume fenrirSoundFile
|
||||
genericFrequencyCommand=play -q -v fenrirVolume -n -c1 synth fenrirDuration sine fenrirFrequence
|
||||
|
||||
# Enable progress bar monitoring with ascending tones by default
|
||||
progressMonitoring=False
|
||||
progressMonitoring=True
|
||||
|
||||
[speech]
|
||||
# Turn speech on or off:
|
||||
@@ -166,7 +166,7 @@ autoPresentIndent=False
|
||||
# 1 = sound only
|
||||
# 2 = speak only
|
||||
autoPresentIndentMode=1
|
||||
# play a sound when attributes are changeing
|
||||
# play a sound when attributes change
|
||||
hasAttributes=True
|
||||
# shell for PTY emulatiun (empty = default shell)
|
||||
shell=
|
||||
@@ -220,7 +220,7 @@ quickMenu=speech#rate;speech#pitch;speech#volume
|
||||
# Each pattern should be on a separate line, format: customPatterns=pattern1,pattern2,pattern3
|
||||
# Examples:
|
||||
# For PS1='[\u@\h \W] \$ ' use: \[.*@.*\s.*\]\s*[$#>]\s*
|
||||
# For "[storm@fenrir ~] $" use: \[.*@.*\s.*\]\s*[$#>]\s*
|
||||
# For "[user@hostname ~] $" use: \[.*@.*\s.*\]\s*[$#>]\s*
|
||||
# For custom prompts ending with specific strings, use patterns like: .*your_prompt_ending$
|
||||
customPatterns=
|
||||
|
||||
@@ -231,7 +231,7 @@ customPatterns=
|
||||
exactMatches=
|
||||
|
||||
[time]
|
||||
# automatic time anouncement
|
||||
# automatic time announcement
|
||||
enabled=False
|
||||
# present time
|
||||
presentTime=True
|
||||
|
||||
@@ -60,13 +60,14 @@ class command():
|
||||
# Debug: Print what we're checking
|
||||
self.env['runtime']['debug'].writeDebugOut("Progress detector checking: '" + text + "'", debug.debugLevel.INFO)
|
||||
|
||||
# Check if progress monitoring should automatically stop
|
||||
self.checkProgressCompletion(text, currentTime)
|
||||
# Note: Auto-disable on 100% completion removed to respect user settings
|
||||
|
||||
# Pattern 1: Percentage (50%, 25.5%, etc.)
|
||||
percentMatch = re.search(r'(\d+(?:\.\d+)?)\s*%', text)
|
||||
if percentMatch:
|
||||
percentage = float(percentMatch.group(1))
|
||||
# Only trigger on realistic progress percentages (0-100%)
|
||||
if 0 <= percentage <= 100:
|
||||
self.env['runtime']['debug'].writeDebugOut("Found percentage: " + str(percentage), debug.debugLevel.INFO)
|
||||
if percentage != self.env['commandBuffer']['lastProgressValue']:
|
||||
self.env['runtime']['debug'].writeDebugOut("Playing tone for: " + str(percentage), debug.debugLevel.INFO)
|
||||
@@ -78,11 +79,15 @@ class command():
|
||||
# Pattern 1b: Time/token activity (not percentage-based, so use single beep)
|
||||
timeMatch = re.search(r'(\d+)s\s', text)
|
||||
tokenMatch = re.search(r'(\d+)\s+tokens', text)
|
||||
# Pattern 1c: dd command output (bytes copied with transfer rate)
|
||||
ddMatch = re.search(r'\d+\s+bytes.*copied.*\d+\s+s.*[kMGT]?B/s', text)
|
||||
# Pattern 1d: Curl-style transfer data (bytes, speed indicators)
|
||||
curlMatch = re.search(r'(\d+\s+\d+\s+\d+\s+\d+.*?(?:k|M|G)?.*?--:--:--|Speed)', text)
|
||||
|
||||
if timeMatch or tokenMatch:
|
||||
if timeMatch or tokenMatch or ddMatch or curlMatch:
|
||||
# For non-percentage progress, use a single activity beep every 2 seconds
|
||||
if currentTime - self.env['commandBuffer']['lastProgressTime'] >= 2.0:
|
||||
self.env['runtime']['debug'].writeDebugOut("Playing activity beep for Claude Code progress", debug.debugLevel.INFO)
|
||||
self.env['runtime']['debug'].writeDebugOut("Playing activity beep for transfer progress", debug.debugLevel.INFO)
|
||||
self.playActivityBeep()
|
||||
self.env['commandBuffer']['lastProgressTime'] = currentTime
|
||||
return
|
||||
@@ -148,21 +153,6 @@ class command():
|
||||
except Exception as e:
|
||||
self.env['runtime']['debug'].writeDebugOut("Sox tone error: " + str(e), debug.debugLevel.ERROR)
|
||||
|
||||
def checkProgressCompletion(self, text, currentTime):
|
||||
"""Check if progress is complete and should auto-disable monitoring"""
|
||||
# Progress monitor is now beep-only - user controls speech separately
|
||||
# Only auto-disable on clear 100% completion for convenience
|
||||
import re
|
||||
|
||||
if re.search(r'100\s*%', text):
|
||||
self.env['runtime']['debug'].writeDebugOut("Progress complete: 100%", debug.debugLevel.INFO)
|
||||
self.stopProgressMonitoring()
|
||||
return
|
||||
|
||||
def stopProgressMonitoring(self):
|
||||
"""Stop progress monitoring - beep-only, no speech control"""
|
||||
self.env['commandBuffer']['progressMonitoring'] = False
|
||||
# Just disable monitoring, don't touch speech settings
|
||||
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
@@ -38,7 +38,7 @@ class textManager():
|
||||
if name[0] == name[1]:
|
||||
newText += ' ' + str(numberOfChars) + ' ' + self.env['runtime']['punctuationManager'].proceedPunctuation(name[0], True) + ' '
|
||||
else:
|
||||
newText += ' ' + str(int(numberOfChars / 2)) + ' ' + self.env['runtime']['punctuationManager'].proceedPunctuation(name, True) + ' '
|
||||
newText += ' ' + self.env['runtime']['punctuationManager'].proceedPunctuation(name[0], True) + ' ' + str(int(numberOfChars / 2)) + ' ' + self.env['runtime']['punctuationManager'].proceedPunctuation(name[1], True) + ' '
|
||||
lastPos = span[1]
|
||||
if lastPos != 0:
|
||||
newText += ' '
|
||||
@@ -46,7 +46,7 @@ class textManager():
|
||||
lastPos = 0
|
||||
for match in self.regExSingle.finditer(newText):
|
||||
span = match.span()
|
||||
result += text[lastPos:span[0]]
|
||||
result += newText[lastPos:span[0]]
|
||||
numberOfChars = len(newText[span[0]:span[1]])
|
||||
name = newText[span[0]:span[1]][:2]
|
||||
if not self.env['runtime']['punctuationManager'].isPuctuation(name[0]):
|
||||
@@ -55,7 +55,7 @@ class textManager():
|
||||
if name[0] == name[1]:
|
||||
result += ' ' + str(numberOfChars) + ' ' + self.env['runtime']['punctuationManager'].proceedPunctuation(name[0], True) + ' '
|
||||
else:
|
||||
result += ' ' + str(int(numberOfChars / 2)) + ' ' + self.env['runtime']['punctuationManager'].proceedPunctuation(name, True) + ' '
|
||||
result += ' ' + self.env['runtime']['punctuationManager'].proceedPunctuation(name[0], True) + ' ' + str(int(numberOfChars / 2)) + ' ' + self.env['runtime']['punctuationManager'].proceedPunctuation(name[1], True) + ' '
|
||||
lastPos = span[1]
|
||||
if lastPos != 0:
|
||||
result += ' '
|
||||
|
||||
@@ -5,4 +5,4 @@
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
version = "2025.06.07"
|
||||
codeName = "testing"
|
||||
codeName = "master"
|
||||
|
||||
@@ -45,28 +45,17 @@ class driver(remoteDriver):
|
||||
continue
|
||||
if self.fenrirSock in r:
|
||||
client_sock, client_addr = self.fenrirSock.accept()
|
||||
response = "ERROR: Failed to process command\n"
|
||||
try:
|
||||
rawdata = client_sock.recv(8129)
|
||||
data = rawdata.decode("utf-8").rstrip().lstrip()
|
||||
if data:
|
||||
# Process the command and get response
|
||||
result = self.env['runtime']['remoteManager'].handleRemoteIncommingWithResponse(data)
|
||||
if result['success']:
|
||||
response = f"OK: {result['message']}\n"
|
||||
else:
|
||||
response = f"ERROR: {result['message']}\n"
|
||||
else:
|
||||
response = "ERROR: Empty command\n"
|
||||
except Exception as e:
|
||||
response = f"ERROR: {str(e)}\n"
|
||||
|
||||
# Send response back to client
|
||||
try:
|
||||
client_sock.send(response.encode("utf-8"))
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
data = rawdata.decode("utf-8").rstrip().lstrip()
|
||||
eventQueue.put({"Type":fenrirEventType.RemoteIncomming,
|
||||
"Data": data
|
||||
})
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
client_sock.close()
|
||||
except:
|
||||
|
||||
Reference in New Issue
Block a user