Updates to the ai app. Should get better responses that read automatically when they arrive.
This commit is contained in:
+21
-8
@@ -6,7 +6,8 @@ Provides accessibility-focused AI interaction with multiple providers
|
|||||||
|
|
||||||
import gi
|
import gi
|
||||||
gi.require_version('Gtk', '3.0')
|
gi.require_version('Gtk', '3.0')
|
||||||
from gi.repository import Gtk, GLib, Gdk
|
gi.require_version('Atk', '1.0')
|
||||||
|
from gi.repository import Gtk, GLib, Gdk, Atk
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
@@ -17,7 +18,6 @@ import i3ipc
|
|||||||
import threading
|
import threading
|
||||||
import requests
|
import requests
|
||||||
import time
|
import time
|
||||||
import pyaudio
|
|
||||||
import wave
|
import wave
|
||||||
|
|
||||||
class SystemCommands:
|
class SystemCommands:
|
||||||
@@ -73,11 +73,13 @@ class VoiceRecognition:
|
|||||||
# Audio settings
|
# Audio settings
|
||||||
self.sample_rate = 16000
|
self.sample_rate = 16000
|
||||||
self.chunk_size = 1024
|
self.chunk_size = 1024
|
||||||
self.audio_format = pyaudio.paInt16
|
|
||||||
self.channels = 1
|
self.channels = 1
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
import pyaudio
|
||||||
import speech_recognition as sr
|
import speech_recognition as sr
|
||||||
|
self.pyaudio = pyaudio
|
||||||
|
self.audio_format = pyaudio.paInt16
|
||||||
self.recognizer = sr.Recognizer()
|
self.recognizer = sr.Recognizer()
|
||||||
self.microphone = sr.Microphone()
|
self.microphone = sr.Microphone()
|
||||||
self.sr_available = True
|
self.sr_available = True
|
||||||
@@ -86,6 +88,8 @@ class VoiceRecognition:
|
|||||||
with self.microphone as source:
|
with self.microphone as source:
|
||||||
self.recognizer.adjust_for_ambient_noise(source)
|
self.recognizer.adjust_for_ambient_noise(source)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
self.pyaudio = None
|
||||||
|
self.audio_format = None
|
||||||
self.sr_available = False
|
self.sr_available = False
|
||||||
self.recognizer = None
|
self.recognizer = None
|
||||||
self.microphone = None
|
self.microphone = None
|
||||||
@@ -96,11 +100,11 @@ class VoiceRecognition:
|
|||||||
|
|
||||||
def start_recording(self):
|
def start_recording(self):
|
||||||
"""Start recording audio"""
|
"""Start recording audio"""
|
||||||
if not self.sr_available:
|
if not self.sr_available or not self.pyaudio:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.audio = pyaudio.PyAudio()
|
self.audio = self.pyaudio.PyAudio()
|
||||||
self.is_recording = True
|
self.is_recording = True
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -288,7 +292,8 @@ class OllamaInterface:
|
|||||||
'stream': False
|
'stream': False
|
||||||
}
|
}
|
||||||
|
|
||||||
if context and not context.startswith("You are a helpful AI assistant"):
|
# Add system context if provided
|
||||||
|
if context:
|
||||||
data['system'] = context
|
data['system'] = context
|
||||||
|
|
||||||
# Handle image if provided
|
# Handle image if provided
|
||||||
@@ -334,7 +339,7 @@ class ClaudeCodeInterface:
|
|||||||
cmd = ['claude']
|
cmd = ['claude']
|
||||||
|
|
||||||
# Add context if provided
|
# Add context if provided
|
||||||
if context and not context.startswith("You are a helpful AI assistant"):
|
if context:
|
||||||
message = f"Context: {context}\n\n{message}"
|
message = f"Context: {context}\n\n{message}"
|
||||||
|
|
||||||
# Add image if provided
|
# Add image if provided
|
||||||
@@ -372,7 +377,7 @@ class CodexCliInterface:
|
|||||||
"""Send message to Codex CLI using non-interactive exec mode"""
|
"""Send message to Codex CLI using non-interactive exec mode"""
|
||||||
try:
|
try:
|
||||||
full_message = message
|
full_message = message
|
||||||
if context and not context.startswith("You are a helpful AI assistant"):
|
if context:
|
||||||
full_message = f"Context: {context}\n\n{message}"
|
full_message = f"Context: {context}\n\n{message}"
|
||||||
|
|
||||||
cmd = ['codex', 'exec', '--skip-git-repo-check', '--sandbox', 'read-only']
|
cmd = ['codex', 'exec', '--skip-git-repo-check', '--sandbox', 'read-only']
|
||||||
@@ -703,6 +708,10 @@ class AiAssistant(Gtk.Window):
|
|||||||
response_atk.set_name("AI Response")
|
response_atk.set_name("AI Response")
|
||||||
response_atk.set_description("AI assistant's response to your question")
|
response_atk.set_description("AI assistant's response to your question")
|
||||||
|
|
||||||
|
# Make this a live region so screen readers automatically announce new content
|
||||||
|
# Note: ATK live region support in GTK3 is limited, so we rely primarily on focus management
|
||||||
|
# in set_response_text() to ensure Orca reads new responses
|
||||||
|
|
||||||
# Link response label to text view
|
# Link response label to text view
|
||||||
self.responseLabel.set_mnemonic_widget(self.responseText)
|
self.responseLabel.set_mnemonic_widget(self.responseText)
|
||||||
|
|
||||||
@@ -1299,6 +1308,10 @@ class AiAssistant(Gtk.Window):
|
|||||||
buffer = self.responseText.get_buffer()
|
buffer = self.responseText.get_buffer()
|
||||||
buffer.set_text(text)
|
buffer.set_text(text)
|
||||||
|
|
||||||
|
# Move focus to the response so Orca reads it immediately
|
||||||
|
# This is the most reliable way to ensure screen readers announce new content
|
||||||
|
GLib.idle_add(self.responseText.grab_focus)
|
||||||
|
|
||||||
def append_response_text(self, text):
|
def append_response_text(self, text):
|
||||||
"""Append text to response text view"""
|
"""Append text to response text view"""
|
||||||
buffer = self.responseText.get_buffer()
|
buffer = self.responseText.get_buffer()
|
||||||
|
|||||||
Reference in New Issue
Block a user