mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-28 13:32:23 +00:00
- 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>
105 lines
3.6 KiB
TypeScript
105 lines
3.6 KiB
TypeScript
import type { ApiResponse } from '../../types/api';
|
|
import type {
|
|
PurgeRequestBody,
|
|
PurgeResultData,
|
|
SendMessageResponseData,
|
|
SuggestQuestionsData,
|
|
ThreadCreateData,
|
|
ThreadDeleteData,
|
|
ThreadMessagesData,
|
|
ThreadsListData,
|
|
} from '../../types/thread';
|
|
import { apiClient } from '../apiClient';
|
|
import { injectAll } from '../../lib/ai/injector';
|
|
import type { Message } from '../../lib/ai/providers/interface';
|
|
|
|
export const threadApi = {
|
|
/** GET /threads — list all threads for the authenticated user */
|
|
getThreads: async (): Promise<ThreadsListData> => {
|
|
const response = await apiClient.get<ApiResponse<ThreadsListData>>('/threads');
|
|
return response.data;
|
|
},
|
|
|
|
/** POST /threads — create a new thread */
|
|
createThread: async (chatId?: number): Promise<ThreadCreateData> => {
|
|
const response = await apiClient.post<ApiResponse<ThreadCreateData>>(
|
|
'/threads',
|
|
chatId != null ? { chatId } : undefined
|
|
);
|
|
return response.data;
|
|
},
|
|
|
|
/** GET /threads/:threadId/messages — get messages for a thread */
|
|
getThreadMessages: async (threadId: string): Promise<ThreadMessagesData> => {
|
|
const response = await apiClient.get<ApiResponse<ThreadMessagesData>>(
|
|
`/threads/${encodeURIComponent(threadId)}/messages`
|
|
);
|
|
return response.data;
|
|
},
|
|
|
|
/** DELETE /threads/:threadId — delete a single thread */
|
|
deleteThread: async (threadId: string): Promise<ThreadDeleteData> => {
|
|
const response = await apiClient.delete<ApiResponse<ThreadDeleteData>>(
|
|
`/threads/${encodeURIComponent(threadId)}`
|
|
);
|
|
return response.data;
|
|
},
|
|
|
|
/** POST /chat/sendMessage — send a user message with SOUL + TOOLS injection */
|
|
sendMessage: async (
|
|
message: string,
|
|
conversationId: string,
|
|
options: { injectSoul?: boolean } = { injectSoul: true }
|
|
): Promise<SendMessageResponseData> => {
|
|
let processedMessage = message;
|
|
|
|
if (options.injectSoul) {
|
|
try {
|
|
const userMessage: Message = {
|
|
role: 'user',
|
|
content: [{ type: 'text', text: message }]
|
|
};
|
|
|
|
const injectedMessage = await injectAll(userMessage, {
|
|
mode: 'context-block',
|
|
includeMetadata: false
|
|
});
|
|
|
|
// Extract the processed text
|
|
const textContent = injectedMessage.content
|
|
.filter(block => block.type === 'text')
|
|
.map(block => (block as { text: string }).text)
|
|
.join('\n');
|
|
|
|
processedMessage = textContent;
|
|
console.log('✅ SOUL + TOOLS injection successful in threadApi sendMessage');
|
|
} catch (error) {
|
|
// Graceful degradation - log error but continue with original message
|
|
console.warn('⚠️ SOUL + TOOLS injection failed in threadApi sendMessage:', error);
|
|
}
|
|
}
|
|
|
|
const response = await apiClient.post<ApiResponse<SendMessageResponseData>>(
|
|
'/chat/sendMessage',
|
|
{ message: processedMessage, conversationId }
|
|
);
|
|
return response.data;
|
|
},
|
|
|
|
/** GET /chat/autocomplete — suggested starter questions (e.g. for a new/empty thread) */
|
|
getSuggestQuestions: async (conversationId?: string): Promise<SuggestQuestionsData> => {
|
|
const url =
|
|
conversationId != null
|
|
? `/chat/autocomplete?conversationId=${encodeURIComponent(conversationId)}`
|
|
: '/chat/autocomplete';
|
|
const response = await apiClient.get<ApiResponse<SuggestQuestionsData>>(url);
|
|
return response.data;
|
|
},
|
|
|
|
/** POST /purge — purge messages and/or threads */
|
|
purge: async (body: PurgeRequestBody): Promise<PurgeResultData> => {
|
|
const response = await apiClient.post<ApiResponse<PurgeResultData>>('/purge', body);
|
|
return response.data;
|
|
},
|
|
};
|