Phase 1: Browser bundle + TTS/Tentone solver scaffolding

- Content/Browser: package.json, vite.config.ts, src/index.ts for JS bundling
- Content/Browser/build-browser.bat for Windows npm build
- Solvers/piper/piper_tts_wrapper.py for TTS sidecar (1C)
- Solvers/tentone/build.bat for OpenCV-aware standalone build (1G)
- Supports 1H (pmndrs spatial), 1I (echarts analytics), 1J (model-viewer)
This commit is contained in:
axiomlogicnexus 2026-06-10 17:45:42 +00:00
parent 91c15ad366
commit 0fbae2f3bc
6 changed files with 260 additions and 0 deletions

View file

@ -0,0 +1,25 @@
@echo off
setlocal
REM Build HyperTwist browser runtime bundle
REM Phase 1H, 1I, 1J: bundles all JS spatial/analytics/model-viewer repos
cd /d "%~dp0"
echo Installing browser runtime dependencies...
call npm install
if errorlevel 1 (
echo npm install failed
exit /b 1
)
echo Building browser runtime bundle...
call npm run build
if errorlevel 1 (
echo Build failed
exit /b 1
)
echo Browser runtime built successfully.
echo Output: dist\hypertwist-browser-runtime.umd.js
echo Copy to Content\Browser\ for UE embedded WebBrowser widget loading.

View file

@ -0,0 +1,34 @@
{
"name": "hypertwist-browser-runtime",
"version": "1.0.0",
"description": "Bundled browser runtime for HyperTwist embedded WebBrowser widget",
"type": "module",
"scripts": {
"build": "vite build",
"build-deps": "node scripts/build-dependencies.js",
"dev": "vite"
},
"dependencies": {
"three": "^0.160.0",
"@pmndrs/postprocessing": "file:../../.external/postprocessing",
"@react-three/drei": "file:../../.external/drei",
"@react-three/fiber": "^8.15.0",
"leva": "file:../../.external/leva",
"maath": "file:../../.external/maath",
"three-stdlib": "file:../../.external/three-stdlib",
"zustand": "file:../../.external/zustand",
"@use-gesture/react": "file:../../.external/use-gesture",
"@react-spring/three": "file:../../.external/react-spring",
"@react-spring/web": "file:../../.external/react-spring",
"echarts": "^5.4.0",
"zrender": "file:../../.external/zrender",
"echarts-gl": "file:../../.external/echarts-gl",
"@google/model-viewer": "file:../../.external/model-viewer/packages/model-viewer",
"claygl": "file:../../.external/claygl",
"rubix-solver": "file:../../.external/rubix-solver"
},
"devDependencies": {
"vite": "^5.0.0",
"typescript": "^5.3.0"
}
}

View file

@ -0,0 +1,71 @@
/**
* HyperTwist Browser Runtime Entry Point
*
* Exports all bundled browser-capable libraries for use in the embedded
* WebBrowser widget or external browser runtime.
*
* Phase 1 wiring targets:
* - 1G: tentone/rubix-solver (vision + solver UI)
* - 1H: pmndrs spatial stack (postprocessing, drei, fiber, etc.)
* - 1I: ecomfe analytics stack (zrender, echarts-gl)
* - 1J: google/model-viewer sub-packages
*/
// Three.js core (peer dependency for most spatial packages)
import * as THREE from 'three';
// pmndrs spatial stack (1H)
export { THREE };
export { default as postprocessing } from '@pmndrs/postprocessing';
export { default as drei } from '@react-three/drei';
export { Canvas, useFrame, useThree } from '@react-three/fiber';
export { default as leva } from 'leva';
export { default as maath } from 'maath';
export { default as threeStdlib } from 'three-stdlib';
export { create as createZustandStore } from 'zustand';
export { useGesture } from '@use-gesture/react';
export { useSpring, animated } from '@react-spring/three';
// Analytics stack (1I)
export { default as zrender } from 'zrender';
export { default as echarts } from 'echarts';
export { default as echartsGl } from 'echarts-gl';
// Model viewer (1J)
export { default as ModelViewerElement } from '@google/model-viewer';
// claygl / clay-viewer (1H)
export { default as claygl } from 'claygl';
// rubix-solver (1G)
// Note: tentone solver is primarily a C++/OpenCV desktop app.
// The JS bundle exports a placeholder for future WASM or web port.
export const RubixSolver = {
version: '1.0.0',
note: 'C++ solver compiled as standalone executable. Web port TBD.'
};
// UE Bridge: postMessage API for state synchronization
interface UEStateBridge {
sendState(state: object): void;
onCommand(callback: (cmd: object) => void): void;
}
export const UEBridge: UEStateBridge = {
sendState(state: object) {
if ((window as any).ue && (window as any).ue.hypertwist) {
(window as any).ue.hypertwist.sendState(JSON.stringify(state));
} else {
window.parent.postMessage({ type: 'hypertwist-state', payload: state }, '*');
}
},
onCommand(callback: (cmd: object) => void) {
window.addEventListener('message', (event) => {
if (event.data && event.data.type === 'hypertwist-command') {
callback(event.data.payload);
}
});
}
};
console.log('[HyperTwist Browser Runtime] Loaded');

View file

@ -0,0 +1,28 @@
import { defineConfig } from 'vite';
import { resolve } from 'path';
export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, 'src/index.ts'),
name: 'HyperTwistBrowserRuntime',
fileName: (format) => `hypertwist-browser-runtime.${format}.js`,
formats: ['umd', 'es']
},
rollupOptions: {
external: [],
output: {
globals: {},
inlineDynamicImports: true
}
},
outDir: 'dist',
emptyOutDir: true,
sourcemap: true
},
resolve: {
alias: {
'@': resolve(__dirname, 'src')
}
}
});

View file

@ -0,0 +1,49 @@
#!/usr/bin/env python3
"""
HyperTwist IPC wrapper for rhasspy/piper TTS engine.
Usage:
python piper_tts_wrapper.py --text "Hello world" --model path/to/model.onnx --output output.wav
Returns:
Path to generated WAV file on success
"""
import argparse
import sys
import json
import subprocess
import os
def synthesize(text: str, model_path: str, config_path: str, output_path: str) -> str:
"""Synthesize speech using piper."""
if not os.path.exists(model_path):
return f"ERROR: Model not found: {model_path}"
# Try using piper directly if available in PATH
try:
cmd = [
"piper",
"--model", model_path,
"--config", config_path,
"--output_file", output_path
]
result = subprocess.run(cmd, input=text, text=True, capture_output=True, timeout=60)
if result.returncode == 0:
return output_path
return f"ERROR: {result.stderr}"
except FileNotFoundError:
return "ERROR: piper executable not found in PATH. Install piper or compile from .external/piper"
except Exception as e:
return f"ERROR: {e}"
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="HyperTwist Piper TTS Wrapper")
parser.add_argument("--text", required=True, help="Text to synthesize")
parser.add_argument("--model", required=True, help="Path to .onnx voice model")
parser.add_argument("--config", help="Path to model config JSON")
parser.add_argument("--output", default="output.wav", help="Output WAV path")
args = parser.parse_args()
config_path = args.config or args.model.replace(".onnx", ".onnx.json")
result = synthesize(args.text, args.model, config_path, args.output)
print(result)

53
Solvers/tentone/build.bat Normal file
View file

@ -0,0 +1,53 @@
@echo off
setlocal
REM Build tentone/rubix-solver as standalone executable
REM Requires OpenCV. If OpenCV is not installed, only the solver logic
REM (cube.cpp, solver.cpp, solution.cpp) can be compiled without vision.
set SRCDIR=..\..\.external\rubix-solver
set OUTDIR=..\..\UnrealHyperTwist\Binaries\Win64\Solvers
if not exist %OUTDIR% mkdir %OUTDIR%
REM Try to find OpenCV
set OPENCV_DIR=
if exist "C:\opencv\build" set OPENCV_DIR=C:\opencv\build
if exist "C:\tools\opencv\build" set OPENCV_DIR=C:\tools\opencv\build
if "%OPENCV_DIR%"=="" (
echo WARNING: OpenCV not found. Building solver-only executable without vision.
echo Install OpenCV and set OPENCV_DIR to enable computer vision features.
call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" x64
if errorlevel 1 exit /b 1
cl /nologo /W4 /O2 /Fe%OUTDIR%\tentone-solver.exe ^
%SRCDIR%\cube.cpp ^
%SRCDIR%\solver.cpp ^
%SRCDIR%\solution.cpp ^
%SRCDIR%\utils.cpp ^
%SRCDIR%\config.cpp ^
%SRCDIR%\main.cpp
) else (
echo Found OpenCV at %OPENCV_DIR%
call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" x64
if errorlevel 1 exit /b 1
cl /nologo /W4 /O2 /I%OPENCV_DIR%\include /Fe%OUTDIR%\tentone-solver.exe ^
%SRCDIR%\cube.cpp ^
%SRCDIR%\solver.cpp ^
%SRCDIR%\solution.cpp ^
%SRCDIR%\utils.cpp ^
%SRCDIR%\config.cpp ^
%SRCDIR%\vision.cpp ^
%SRCDIR%\main.cpp ^
/link /LIBPATH:%OPENCV_DIR%\x64\vc16\lib opencv_world490.lib
)
if errorlevel 1 (
echo Build failed
exit /b 1
)
echo tentone-solver built successfully at %OUTDIR%\tentone-solver.exe