From 851f2308bd49737da025ab731d47a72cd9245c5e Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Thu, 26 Mar 2026 18:29:44 -0700 Subject: [PATCH] refactor: remove Tauri integration and update tools discovery mechanism - Eliminated the Tauri integration files and related functions to streamline the tools discovery process. - Updated the tools discovery logic to utilize a mock registry instead of relying on Tauri, enhancing compatibility and simplifying the workflow. - Adjusted comments in the release workflow to reflect the changes in tools discovery and removed references to the now-removed Tauri binary. --- .github/workflows/release.yml | 6 +- scripts/tools-generator/discover-tools.js | 110 +-------- scripts/tools-generator/tauri-integration.js | 223 ------------------ src-tauri/Cargo.toml | 6 - .../src/bin/openhuman-tools-discovery.rs | 150 ------------ 5 files changed, 5 insertions(+), 490 deletions(-) delete mode 100644 scripts/tools-generator/tauri-integration.js delete mode 100644 src-tauri/src/bin/openhuman-tools-discovery.rs diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0976ae70b..d272c34c2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -313,9 +313,9 @@ jobs: WITH_UPDATER: 'true' MACOSX_DEPLOYMENT_TARGET: ${{ matrix.settings.platform == 'macos-latest' && '10.15' || '' }} with: - # `openhuman-tools-discovery` is feature-gated in Cargo.toml so it - # does not get bundled into release app packages and break macOS - # codesign as an unsigned subcomponent. + # Tools discovery now uses a JS mock registry (no Rust discovery + # binary target), so there is no extra helper executable for Tauri + # to copy/sign inside release app bundles. args: -c ${{ steps.config-overrides.outputs.json }} ${{ matrix.settings.args }} includeDebug: false includeRelease: true diff --git a/scripts/tools-generator/discover-tools.js b/scripts/tools-generator/discover-tools.js index 6a72bb277..31a2c946d 100644 --- a/scripts/tools-generator/discover-tools.js +++ b/scripts/tools-generator/discover-tools.js @@ -12,12 +12,6 @@ import { dirname, join } from 'path'; import { fileURLToPath } from 'url'; import { generateOpenClawMarkdown } from './openClaw-formatter.js'; -import { - executeTauriDiscovery, - getTauriEnvironmentInfo, - prepareTauriEnvironment, - validateTauriEnvironment, -} from './tauri-integration.js'; const __dirname = dirname(fileURLToPath(import.meta.url)); const PROJECT_ROOT = join(__dirname, '../..'); @@ -42,39 +36,7 @@ const ENVIRONMENTS = { * @returns {Promise} Array of discovered tools with skill metadata */ async function discoverTools() { - console.log('🔍 Discovering tools from V8 skills runtime...'); - - // Check if Tauri environment is available - const tauriAvailable = await validateTauriEnvironment(); - - if (tauriAvailable) { - try { - console.log('🔧 Preparing Tauri environment...'); - await prepareTauriEnvironment(); - - console.log('🚀 Executing Tauri tools discovery...'); - const realTools = await executeTauriDiscovery({ - timeout: 60000, // 60 seconds - retries: 2, - verbose: process.env.VERBOSE === 'true', - }); - - if (realTools && realTools.length > 0) { - console.log( - `✅ Discovered ${realTools.length} tools from ${new Set(realTools.map(t => t.skillId)).size} skills via Tauri` - ); - return realTools; - } - } catch (error) { - console.warn('⚠️ Could not discover tools from Tauri runtime:', error.message); - console.log('📋 Using development mock data instead'); - } - } else { - console.warn('⚠️ Tauri environment not available'); - console.log('📋 Using development mock data instead'); - } - - // Fallback to mock data for development + console.log('🔍 Discovering tools from mock registry...'); const mockTools = generateMockToolsForDevelopment(); console.log( `✅ Using mock data: ${mockTools.length} tools from ${new Set(mockTools.map(t => t.skillId)).size} skills` @@ -195,77 +157,9 @@ async function main() { } } -/** - * Attempts to discover tools from a running Tauri process - * @returns {Promise} Array of tools from Tauri runtime - */ -async function discoverToolsFromTauri() { - return new Promise((resolve, reject) => { - // Try to spawn a minimal Tauri process for tool discovery - const isWindows = process.platform === 'win32'; - const tauriCommand = isWindows ? 'cargo.exe' : 'cargo'; - - const args = [ - 'run', - '--manifest-path', - join(PROJECT_ROOT, 'src-tauri', 'Cargo.toml'), - '--bin', - 'openhuman-tools-discovery', - '--features', - 'tools-discovery-bin', - ]; - - console.log('🔧 Attempting to run tools discovery via Cargo...'); - - const child = spawn(tauriCommand, args, { - stdio: ['pipe', 'pipe', 'pipe'], - cwd: PROJECT_ROOT, - env: { ...process.env, TAURI_TOOLS_DISCOVERY: 'true' }, - }); - - let output = ''; - let errorOutput = ''; - - child.stdout.on('data', data => { - output += data.toString(); - }); - - child.stderr.on('data', data => { - errorOutput += data.toString(); - }); - - child.on('close', code => { - if (code === 0 && output.trim()) { - try { - const result = JSON.parse(output.trim()); - if (result.success && result.tools) { - resolve(result.tools); - } else { - reject(new Error(result.error || 'Unknown error from Tauri')); - } - } catch (parseError) { - reject(new Error(`Failed to parse Tauri output: ${parseError.message}`)); - } - } else { - reject(new Error(`Tauri process failed (code ${code}): ${errorOutput}`)); - } - }); - - child.on('error', error => { - reject(new Error(`Failed to spawn Tauri process: ${error.message}`)); - }); - - // Timeout after 30 seconds - setTimeout(() => { - child.kill(); - reject(new Error('Tauri discovery process timed out')); - }, 30000); - }); -} - // Run if called directly if (import.meta.url === `file://${process.argv[1]}`) { main(); } -export { discoverTools, discoverToolsFromTauri, generateMockToolsForDevelopment }; +export { discoverTools, generateMockToolsForDevelopment }; diff --git a/scripts/tools-generator/tauri-integration.js b/scripts/tools-generator/tauri-integration.js deleted file mode 100644 index c1998d215..000000000 --- a/scripts/tools-generator/tauri-integration.js +++ /dev/null @@ -1,223 +0,0 @@ -#!/usr/bin/env node -/** - * Tauri Integration for Tools Discovery - * - * Provides integration utilities for discovering tools via Tauri runtime. - * Handles cross-platform execution, error handling, and fallbacks. - */ -import { spawn } from 'child_process'; -import { join } from 'path'; -import { dirname } from 'path'; -import { fileURLToPath } from 'url'; - -const __dirname = dirname(fileURLToPath(import.meta.url)); -const PROJECT_ROOT = join(__dirname, '../..'); - -/** - * Platform-specific command detection - * @returns {Object} Command and arguments for spawning Tauri process - */ -export function getTauriCommand() { - const isWindows = process.platform === 'win32'; - - return { - command: isWindows ? 'cargo.exe' : 'cargo', - args: [ - 'run', - '--manifest-path', - join(PROJECT_ROOT, 'src-tauri', 'Cargo.toml'), - '--bin', - 'openhuman-tools-discovery', - '--features', - 'tools-discovery-bin', - ], - }; -} - -/** - * Validates if Tauri development environment is available - * @returns {Promise} True if Tauri can be used - */ -export async function validateTauriEnvironment() { - return new Promise(resolve => { - const { command } = getTauriCommand(); - - const child = spawn(command, ['--version'], { stdio: ['pipe', 'pipe', 'pipe'] }); - - child.on('close', code => { - resolve(code === 0); - }); - - child.on('error', () => { - resolve(false); - }); - - // Timeout after 10 seconds - setTimeout(() => { - child.kill(); - resolve(false); - }, 10000); - }); -} - -/** - * Executes tools discovery via Tauri runtime - * @param {Object} options - Configuration options - * @returns {Promise} Discovered tools - */ -export async function executeTauriDiscovery(options = {}) { - const { - timeout = 45000, // 45 seconds - retries = 2, - verbose = false, - } = options; - - for (let attempt = 1; attempt <= retries; attempt++) { - try { - if (verbose) { - console.log(`🔄 Tauri discovery attempt ${attempt}/${retries}...`); - } - - const result = await runTauriDiscovery(timeout, verbose); - return result; - } catch (error) { - if (attempt === retries) { - throw error; - } - - if (verbose) { - console.warn(`⚠️ Attempt ${attempt} failed:`, error.message); - console.log('🔄 Retrying...'); - } - } - } -} - -/** - * Internal function to run Tauri discovery process - * @param {number} timeout - Timeout in milliseconds - * @param {boolean} verbose - Enable verbose logging - * @returns {Promise} Discovered tools - */ -async function runTauriDiscovery(timeout, verbose) { - return new Promise((resolve, reject) => { - const { command, args } = getTauriCommand(); - - if (verbose) { - console.log(`🔧 Executing: ${command} ${args.join(' ')}`); - } - - const child = spawn(command, args, { - stdio: ['pipe', 'pipe', 'pipe'], - cwd: PROJECT_ROOT, - env: { - ...process.env, - TAURI_TOOLS_DISCOVERY: 'true', - RUST_LOG: verbose ? 'debug' : 'warn', - RUST_BACKTRACE: '1', - }, - }); - - let output = ''; - let errorOutput = ''; - - child.stdout.on('data', data => { - const text = data.toString(); - output += text; - - if (verbose && text.trim()) { - console.log('📤 Tauri output:', text.trim()); - } - }); - - child.stderr.on('data', data => { - const text = data.toString(); - errorOutput += text; - - if (verbose && text.trim()) { - console.log('📤 Tauri stderr:', text.trim()); - } - }); - - child.on('close', code => { - if (code === 0) { - try { - // Extract JSON from output (may have other log lines) - const jsonMatch = output.match(/\{.*"success".*\}/s); - if (!jsonMatch) { - reject(new Error('No valid JSON found in Tauri output')); - return; - } - - const result = JSON.parse(jsonMatch[0]); - - if (result.success) { - resolve(result.tools || []); - } else { - reject(new Error(result.error || 'Unknown error from Tauri discovery')); - } - } catch (parseError) { - reject(new Error(`Failed to parse Tauri output: ${parseError.message}`)); - } - } else { - const errorMsg = errorOutput.trim() || `Process exited with code ${code}`; - reject(new Error(`Tauri discovery failed: ${errorMsg}`)); - } - }); - - child.on('error', error => { - reject(new Error(`Failed to spawn Tauri process: ${error.message}`)); - }); - - // Timeout handling - const timeoutId = setTimeout(() => { - child.kill('SIGTERM'); - - // Force kill after 5 more seconds - setTimeout(() => { - if (!child.killed) { - child.kill('SIGKILL'); - } - }, 5000); - - reject(new Error(`Tauri discovery timed out after ${timeout}ms`)); - }, timeout); - - child.on('close', () => { - clearTimeout(timeoutId); - }); - }); -} - -/** - * Prepares the environment for tools discovery - * Ensures build dependencies and environment are ready - * @returns {Promise} - */ -export async function prepareTauriEnvironment() { - console.log('🔧 Preparing Tauri environment for tools discovery...'); - - // Check if Cargo is available - const cargoAvailable = await validateTauriEnvironment(); - if (!cargoAvailable) { - throw new Error('Cargo/Rust toolchain not found. Please install Rust and Cargo.'); - } - - console.log('✅ Tauri environment ready'); -} - -/** - * Gets information about the current Tauri setup - * @returns {Promise} Environment information - */ -export async function getTauriEnvironmentInfo() { - const cargoAvailable = await validateTauriEnvironment(); - - return { - cargoAvailable, - platform: process.platform, - architecture: process.arch, - projectRoot: PROJECT_ROOT, - command: getTauriCommand(), - }; -} diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index cd90c0594..7e5fa845d 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -19,11 +19,6 @@ crate-type = ["staticlib", "cdylib", "rlib"] name = "OpenHuman" path = "src/main.rs" -[[bin]] -name = "openhuman-tools-discovery" -path = "src/bin/openhuman-tools-discovery.rs" -required-features = ["tools-discovery-bin"] - [[bin]] name = "openhuman-core" path = "src/bin/openhuman-core.rs" @@ -185,7 +180,6 @@ tempfile = "3" custom-protocol = ["tauri/custom-protocol"] sandbox-landlock = ["dep:landlock"] sandbox-bubblewrap = [] -tools-discovery-bin = [] # OpenHuman feature flags hardware = ["dep:nusb", "dep:tokio-serial"] diff --git a/src-tauri/src/bin/openhuman-tools-discovery.rs b/src-tauri/src/bin/openhuman-tools-discovery.rs deleted file mode 100644 index 19d392601..000000000 --- a/src-tauri/src/bin/openhuman-tools-discovery.rs +++ /dev/null @@ -1,150 +0,0 @@ -//! OpenHuman Tools Discovery Binary -//! -//! A standalone Rust binary that discovers all available tools from the V8 skills runtime -//! and outputs them as JSON for consumption by the build system. -//! -//! This binary is invoked during the build process to generate TOOLS.md automatically. - -use std::env; -use std::path::PathBuf; -use tokio; - -#[tokio::main] -async fn main() -> Result<(), Box> { - // Check if we're in tools discovery mode - if env::var("TAURI_TOOLS_DISCOVERY").is_err() { - eprintln!("This binary should only be run for tools discovery"); - std::process::exit(1); - } - - // Initialize minimal logging for discovery - env_logger::init(); - - // Platform check - V8 runtime only available on desktop - #[cfg(any(target_os = "android", target_os = "ios"))] - { - // Mobile platforms don't support V8 runtime - let result = serde_json::json!({ - "success": true, - "tools": [], - "message": "V8 runtime not available on mobile platforms" - }); - println!("{}", serde_json::to_string(&result)?); - return Ok(()); - } - - #[cfg(not(any(target_os = "android", target_os = "ios")))] - { - // Desktop platforms with V8 runtime - match discover_tools_desktop().await { - Ok(tools) => { - let result = serde_json::json!({ - "success": true, - "tools": tools - }); - println!("{}", serde_json::to_string(&result)?); - } - Err(error) => { - let result = serde_json::json!({ - "success": false, - "error": error.to_string(), - "tools": [] - }); - println!("{}", serde_json::to_string(&result)?); - std::process::exit(1); - } - } - } - - Ok(()) -} - -#[cfg(not(any(target_os = "android", target_os = "ios")))] -async fn discover_tools_desktop() -> Result, Box> { - // For now, return mock data until we can properly access the runtime engine - // The runtime module is private and the engine initialization is complex - log::info!("Using mock tools data for build-time discovery"); - - let mock_tools = vec![ - serde_json::json!({ - "skillId": "telegram", - "name": "send_message", - "description": "Send a message to a Telegram chat or user", - "inputSchema": { - "type": "object", - "properties": { - "chat_id": { "type": "string", "description": "Telegram chat ID or username" }, - "message": { "type": "string", "description": "Message text to send" }, - "parse_mode": { "type": "string", "description": "Message formatting mode" } - }, - "required": ["chat_id", "message"] - } - }), - serde_json::json!({ - "skillId": "telegram", - "name": "get_chat_history", - "description": "Retrieve message history from a Telegram chat", - "inputSchema": { - "type": "object", - "properties": { - "chat_id": { "type": "string", "description": "Telegram chat ID or username" }, - "limit": { "type": "number", "description": "Number of messages to retrieve" } - }, - "required": ["chat_id"] - } - }), - serde_json::json!({ - "skillId": "notion", - "name": "create_page", - "description": "Create a new page in Notion workspace", - "inputSchema": { - "type": "object", - "properties": { - "parent_id": { "type": "string", "description": "Parent database or page ID" }, - "title": { "type": "string", "description": "Page title" }, - "content": { "type": "array", "description": "Page content blocks" } - }, - "required": ["parent_id", "title"] - } - }), - serde_json::json!({ - "skillId": "gmail", - "name": "send_email", - "description": "Send an email via Gmail", - "inputSchema": { - "type": "object", - "properties": { - "to": { "type": "string", "description": "Recipient email address" }, - "subject": { "type": "string", "description": "Email subject line" }, - "body": { "type": "string", "description": "Email body content" } - }, - "required": ["to", "subject", "body"] - } - }) - ]; - - log::info!("Using {} mock tools for build-time generation", mock_tools.len()); - Ok(mock_tools) -} - -/// Determines the skills directory based on the current environment -fn determine_skills_directory() -> Result> { - // Try to find skills directory relative to project root - let current_dir = env::current_dir()?; - - // Check if we're in src-tauri directory - let potential_paths = vec![ - current_dir.join("skills"), - current_dir.parent().map(|p| p.join("skills")).unwrap_or_default(), - current_dir.join("../skills").canonicalize().unwrap_or_default(), - ]; - - for path in potential_paths { - if path.exists() && path.is_dir() { - log::info!("Found skills directory at: {:?}", path); - return Ok(path); - } - } - - Err("Could not find skills directory".into()) -}