feat: Implement a modular skill system with hotword detection, streaming text output, and enhanced logging.
This commit is contained in:
@@ -22,4 +22,47 @@ public static class Notifications
|
||||
Console.WriteLine($"[Notifications] Failed to send notification: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public static void PlaySound(string soundPath)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(soundPath)) return;
|
||||
try
|
||||
{
|
||||
var absolutePath = soundPath;
|
||||
if (!Path.IsPathRooted(absolutePath))
|
||||
absolutePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, absolutePath);
|
||||
|
||||
if (!File.Exists(absolutePath))
|
||||
{
|
||||
var resourceName = "Toak." + soundPath.Replace("/", ".").Replace("\\", ".");
|
||||
using var stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName);
|
||||
if (stream != null)
|
||||
{
|
||||
absolutePath = Path.Combine(Path.GetTempPath(), "toak_" + Path.GetFileName(soundPath));
|
||||
if (!File.Exists(absolutePath))
|
||||
{
|
||||
using var fileStream = File.Create(absolutePath);
|
||||
stream.CopyTo(fileStream);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var pInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "paplay",
|
||||
Arguments = $"\"{absolutePath}\"",
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
Process.Start(pInfo);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"[Notifications] Failed to play sound: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
using System.Diagnostics;
|
||||
|
||||
using Toak.Core;
|
||||
|
||||
namespace Toak.IO;
|
||||
|
||||
public static class TextInjector
|
||||
{
|
||||
public static void Inject(string text, string backend)
|
||||
{
|
||||
Logger.LogDebug($"Injecting text: '{text}' with {backend}");
|
||||
if (string.IsNullOrWhiteSpace(text)) return;
|
||||
|
||||
try
|
||||
@@ -13,6 +16,7 @@ public static class TextInjector
|
||||
ProcessStartInfo pInfo;
|
||||
if (backend.ToLowerInvariant() == "wtype")
|
||||
{
|
||||
Logger.LogDebug($"Injecting text using wtype...");
|
||||
pInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "wtype",
|
||||
@@ -23,6 +27,7 @@ public static class TextInjector
|
||||
}
|
||||
else // xdotool
|
||||
{
|
||||
Logger.LogDebug($"Injecting text using xdotool...");
|
||||
pInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "xdotool",
|
||||
@@ -40,4 +45,57 @@ public static class TextInjector
|
||||
Notifications.Notify("Injection Error", "Could not type text into window.");
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task InjectStreamAsync(IAsyncEnumerable<string> tokenStream, string backend)
|
||||
{
|
||||
try
|
||||
{
|
||||
ProcessStartInfo pInfo;
|
||||
if (backend.ToLowerInvariant() == "wtype")
|
||||
{
|
||||
Logger.LogDebug($"Setting up stream injection using wtype...");
|
||||
pInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "wtype",
|
||||
Arguments = "-",
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
RedirectStandardInput = true
|
||||
};
|
||||
}
|
||||
else // xdotool
|
||||
{
|
||||
Logger.LogDebug($"Setting up stream injection using xdotool...");
|
||||
pInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "xdotool",
|
||||
Arguments = "type --clearmodifiers --delay 0 --file -",
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
RedirectStandardInput = true
|
||||
};
|
||||
}
|
||||
|
||||
using var process = Process.Start(pInfo);
|
||||
if (process == null) return;
|
||||
|
||||
Logger.LogDebug("Started stream injection process, waiting for tokens...");
|
||||
|
||||
await foreach (var token in tokenStream)
|
||||
{
|
||||
Logger.LogDebug($"Injecting token: '{token}'");
|
||||
await process.StandardInput.WriteAsync(token);
|
||||
await process.StandardInput.FlushAsync();
|
||||
}
|
||||
|
||||
Logger.LogDebug("Stream injection complete. Closing standard input.");
|
||||
process.StandardInput.Close();
|
||||
await process.WaitForExitAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"[TextInjector] Error injecting text stream: {ex.Message}");
|
||||
Notifications.Notify("Injection Error", "Could not type text stream into window.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user