diff --git a/Solvers/freestyle/freestyle_sidecar.bat b/Solvers/freestyle/freestyle_sidecar.bat new file mode 100644 index 0000000..e44edb3 --- /dev/null +++ b/Solvers/freestyle/freestyle_sidecar.bat @@ -0,0 +1,38 @@ +@echo off +setlocal + +REM HyperTwist Freestyle STT Sidecar Launcher +REM Phase 1B: Runs freestyle server as external HTTP sidecar process + +cd /d "%~dp0\..\..\.external\freestyle" + +REM Check if pnpm is available +where pnpm >nul 2>nul +if errorlevel 1 ( + echo ERROR: pnpm not found. Install pnpm first: + echo npm install -g pnpm + exit /b 1 +) + +REM Install dependencies if node_modules is missing +if not exist "node_modules" ( + echo Installing freestyle dependencies... + call pnpm install + if errorlevel 1 ( + echo ERROR: pnpm install failed + exit /b 1 + ) +) + +REM Build the server package +cd apps\server +echo Building freestyle server... +call pnpm build +if errorlevel 1 ( + echo ERROR: Server build failed + exit /b 1 +) + +REM Start the server +echo Starting freestyle server on port 8787... +node dist\index.js diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistIPC/HyperTwistIPCProcessManager.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistIPC/HyperTwistIPCProcessManager.cpp index 0c514bc..0148e42 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistIPC/HyperTwistIPCProcessManager.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistIPC/HyperTwistIPCProcessManager.cpp @@ -38,11 +38,6 @@ FHyperTwistIPCResult UHyperTwistIPCProcessManager::RunProcess(const FHyperTwistI if (Options.bCaptureOutput) { FPlatformProcess::CreatePipe(ReadPipe, WritePipe); - if (Options.bRedirectInput) - { - FPlatformProcess::CreatePipe(StdErrPipe, nullptr); - } - ProcessHandle = FPlatformProcess::CreateProc( *Options.ExecutablePath, *Params, @@ -213,7 +208,7 @@ bool UHyperTwistIPCProcessManager::TerminateProcess(int32 ProcessId) bool UHyperTwistIPCProcessManager::IsProcessRunning(int32 ProcessId) const { - const FActiveProcess* Proc = ActiveProcesses.Find(ProcessId); + FActiveProcess* Proc = ActiveProcesses.Find(ProcessId); if (!Proc) { return false; diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistIPC/HyperTwistSolverOracleLibrary.cpp b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistIPC/HyperTwistSolverOracleLibrary.cpp index fbc8c27..d12f7c4 100644 --- a/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistIPC/HyperTwistSolverOracleLibrary.cpp +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Private/HyperTwistIPC/HyperTwistSolverOracleLibrary.cpp @@ -88,11 +88,9 @@ bool UHyperTwistSolverOracleLibrary::CompareSolvers(const FString& FaceletString { // rob-twophase result TArray RobTwophaseMoves = UHyperTwistSolverLibrary::SolveClassicState(FaceletString, 5000, 25, 1); - TArray RobMoves; - RobTwophaseSolution.ParseIntoArrayWS(RobMoves); // cahidenes result TArray CahidenesMoves = SolveWithCahidenesOracle(FaceletString); - return RobMoves.Num() == CahidenesMoves.Num(); + return RobTwophaseMoves.Num() == CahidenesMoves.Num(); } diff --git a/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistIPC/HyperTwistHttpSpeechClient.h b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistIPC/HyperTwistHttpSpeechClient.h new file mode 100644 index 0000000..a4dfabc --- /dev/null +++ b/UnrealHyperTwist/Source/UnrealHyperTwist/Public/HyperTwistIPC/HyperTwistHttpSpeechClient.h @@ -0,0 +1,51 @@ +#pragma once + +#include "CoreMinimal.h" +#include "Kismet/BlueprintFunctionLibrary.h" +#include "Http.h" +#include "HyperTwistHttpSpeechClient.generated.h" + +USTRUCT(BlueprintType) +struct FHyperTwistSpeechTranscriptResult +{ + GENERATED_BODY() + + UPROPERTY(BlueprintReadOnly, Category = "HyperTwist|Speech") + bool bSuccess = false; + + UPROPERTY(BlueprintReadOnly, Category = "HyperTwist|Speech") + FString Transcript; + + UPROPERTY(BlueprintReadOnly, Category = "HyperTwist|Speech") + FString ErrorMessage; + + UPROPERTY(BlueprintReadOnly, Category = "HyperTwist|Speech") + float Confidence = 0.0f; +}; + +/** + * HTTP client for freestyle-voice sidecar integration. + * Communicates with the freestyle Node.js server running on localhost:8787. + */ +UCLASS() +class UNREALHYPERTWIST_API UHyperTwistHttpSpeechClient : public UBlueprintFunctionLibrary +{ + GENERATED_BODY() + +public: + UFUNCTION(BlueprintCallable, Category = "HyperTwist|Speech", meta = (WorldContext = "WorldContextObject")) + static void SendDictationAudio(UObject* WorldContextObject, const TArray& PCM16Data, + const FOnSpeechTranscriptReceived& OnComplete); + + UFUNCTION(BlueprintCallable, Category = "HyperTwist|Speech") + static bool IsFreestyleSidecarReachable(); + + UFUNCTION(BlueprintPure, Category = "HyperTwist|Speech") + static FString GetFreestyleSidecarUrl(); + + /** Parse move notation from transcript. e.g. "R prime" -> R counter-clockwise */ + UFUNCTION(BlueprintCallable, Category = "HyperTwist|Speech") + static TArray ParseMoveNotation(const FString& Transcript); +}; + +DECLARE_DYNAMIC_DELEGATE_OneParam(FOnSpeechTranscriptReceived, const FHyperTwistSpeechTranscriptResult&, Result);