Files
openhuman/src/services/api/threadApi.ts
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

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;
},
};