feat: integrate TinyHumans memory client for skill data synchronization

- Added `syncMemoryClientToken` utility to synchronize JWT token with the TinyHumans memory client after user login and Redux rehydration.
- Updated `PersistGate` in `App.tsx` to call `syncMemoryClientToken` on lift.
- Modified `SkillManagementPanel` to use `triggerSync` for skill management instead of stopping and starting skills.
- Implemented memory commands in Tauri for initializing and querying the TinyHumans memory client.
- Enhanced skill instance handling to persist sync data and clear memory on OAuth revocation.
- Introduced a new memory module to manage skill data synchronization effectively.
This commit is contained in:
M3gA-Mind
2026-03-18 17:05:16 +05:30
parent 5fb37c326a
commit 232767c19a
11 changed files with 426 additions and 6 deletions
+9 -1
View File
@@ -12,6 +12,7 @@ import SocketProvider from './providers/SocketProvider';
import UserProvider from './providers/UserProvider';
import { tagErrorSource } from './services/errorReportQueue';
import { persistor, store } from './store';
import { syncMemoryClientToken } from './utils/tauriCommands';
function App() {
return (
@@ -23,7 +24,14 @@ function App() {
tagErrorSource(eventId, 'react', componentStack);
}}>
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<PersistGate
loading={null}
persistor={persistor}
onBeforeLift={() => {
const token = store.getState().auth.token;
console.info('[memory] PersistGate onBeforeLift: token_present=%s', !!token);
if (token) void syncMemoryClientToken(token);
}}>
<UserProvider>
<SocketProvider>
<AIProvider>
@@ -107,8 +107,9 @@ export default function SkillManagementPanel({
if (!skill?.manifest) return;
setRestarting(true);
try {
await skillManager.stopSkill(skillId);
await skillManager.startSkill(skill.manifest);
// await skillManager.stopSkill(skillId);
// await skillManager.startSkill(skill.manifest);
await skillManager.triggerSync(skillId);
} catch (err) {
console.error("[SkillManagementPanel] Restart failed:", err);
} finally {
+3
View File
@@ -4,6 +4,7 @@ import { useNavigate, useSearchParams } from 'react-router-dom';
import { consumeLoginToken } from '../services/api/authApi';
import { setToken } from '../store/authSlice';
import { useAppDispatch } from '../store/hooks';
import { syncMemoryClientToken } from '../utils/tauriCommands';
const Login = () => {
const navigate = useNavigate();
@@ -26,6 +27,8 @@ const Login = () => {
if (cancelled) return;
dispatch(setToken(jwtToken));
console.info('[memory] Login: dispatching syncMemoryClientToken after setToken');
void syncMemoryClientToken(jwtToken);
navigate('/onboarding/', { replace: true });
} catch (err) {
if (!cancelled) {
+22
View File
@@ -161,6 +161,28 @@ export async function setWindowTitle(title: string): Promise<void> {
await invoke('set_window_title', { title });
}
// --- Memory Commands ---
/**
* Initialise the TinyHumans memory client in Rust with the user's JWT token
* (sourced from `authSlice.token` in Redux). Call this after login and after
* Redux Persist rehydration.
*/
export async function syncMemoryClientToken(token: string): Promise<void> {
console.debug('[memory] syncMemoryClientToken: entry (token_present=%s, is_tauri=%s)', !!token, isTauri());
if (!isTauri() || !token) {
console.debug('[memory] syncMemoryClientToken: exit — skipped (not Tauri or empty token)');
return;
}
try {
console.debug('[memory] syncMemoryClientToken: payload → init_memory_client { jwtToken: <redacted, len=%d> }', token.length);
await invoke('init_memory_client', { jwtToken: token });
console.info('[memory] syncMemoryClientToken: exit — ok');
} catch (err) {
console.warn('[memory] syncMemoryClientToken: exit — error:', err);
}
}
// --- Alphahuman Commands ---
export type DoctorSeverity = 'Ok' | 'Warn' | 'Error';