Files
openhuman/scripts/tools-generator/tauri-integration.js
T
cyrusandClaude aef7df5dce feat: implement unified AI injection system with dynamic TOOLS.md generation
- Create complete modular AI configuration system following OpenClaw standards
- Add dynamic TOOLS.md generation from V8 skills runtime discovery
- Implement unified injection system with injectAll() for SOUL + TOOLS contexts
- Update all 4 integration points to use unified injection consistently

## New Features:

### Modular AI Configuration System
- loadSoul() → SoulConfig (personality, voice, behavior)
- loadTools() → ToolsConfig (available tools and capabilities)
- loadAIConfig() → AIConfig (unified SOUL + TOOLS configuration)
- Multi-layer caching: memory → localStorage → GitHub → bundled

### Dynamic TOOLS.md Generation
- yarn tools:generate command for build-time tool discovery
- Spawns Tauri runtime to call runtime_all_tools() from V8 skills
- Generates OpenClaw-compliant documentation with usage examples
- Professional formatting with environment configs and statistics
- Currently discovers 4 tools from 3 skills (telegram, notion, gmail)

### Unified Injection System
- injectAll() function combines SOUL + TOOLS injection
- injectSoul() and injectTools() for individual injection
- Consistent [PERSONA_CONTEXT] and [TOOLS_CONTEXT] formatting
- Updated all integration points: Conversations.tsx, threadSlice.ts, threadApi.ts, tauriCommands.ts

### Build System Integration
- Added tools:generate script to package.json
- Rust binary: src-tauri/src/bin/alphahuman-tools-discovery.rs
- Cross-platform discovery scripts in scripts/tools-generator/
- Fixed Cargo.toml binary configuration and main.rs imports

### Enhanced Settings UI
- AI Configuration panel shows both SOUL and TOOLS
- Individual refresh buttons for each component
- Combined "Refresh All AI Configuration" functionality
- Source indicators and statistics display

## Technical Implementation:

### File Structure:
- /ai/TOOLS.md - Auto-generated tool documentation
- src/lib/ai/tools/injector.ts - Tools injection system
- src/lib/ai/injector.ts - Unified injection orchestrator
- src/lib/ai/loader.ts - Unified configuration loader
- scripts/tools-generator/ - Build-time discovery system

### Message Format:
```
[PERSONA_CONTEXT]
I am AlphaHuman: incredibly smart, funny friend...
[/PERSONA_CONTEXT]

[TOOLS_CONTEXT]
4 tools across 3 skills
Categories: Communication (2), Productivity (1), Email (1)
[/TOOLS_CONTEXT]

User message: Hello!
```

### Performance & Reliability:
- Multi-layer caching with 30min TTL
- Graceful degradation if injection fails
- Cross-platform build support (Windows, macOS, Linux)
- Full TypeScript compliance with comprehensive error handling

🤖 Generated with Claude Code(https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-03-05 19:42:55 +05:30

224 lines
5.7 KiB
JavaScript

#!/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 { fileURLToPath } from 'url';
import { dirname } from 'path';
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',
'alphahuman-tools-discovery'
]
};
}
/**
* Validates if Tauri development environment is available
* @returns {Promise<boolean>} 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<Array>} 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<Array>} 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<void>}
*/
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<Object>} Environment information
*/
export async function getTauriEnvironmentInfo() {
const cargoAvailable = await validateTauriEnvironment();
return {
cargoAvailable,
platform: process.platform,
architecture: process.arch,
projectRoot: PROJECT_ROOT,
command: getTauriCommand()
};
}