mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-27 21:08:00 +00:00
feat: implement Gmail metadata synchronization to backend
- Added a new utility function `syncGmailMetadataToBackend` to emit Gmail profile and email summaries to the backend via the `integration:metadata-sync` socket event. - Updated `SkillProvider` to call the new synchronization function, ensuring Gmail skill state is sent to the backend when updated.
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Send Gmail profile (and optionally emails) to the backend via the
|
||||
* `integration:metadata-sync` socket event so the server can merge them
|
||||
* into the user's Google OAuth integration metadata.
|
||||
*/
|
||||
import { emitViaRustSocket } from '../../utils/tauriSocket';
|
||||
|
||||
const INTEGRATION_METADATA_SYNC_EVENT = 'integration:metadata-sync';
|
||||
const PROVIDER_GOOGLE = 'google';
|
||||
|
||||
/** Gmail profile shape from skill state (snake_case). */
|
||||
interface GmailProfileLike {
|
||||
email_address: string;
|
||||
messages_total: number;
|
||||
threads_total: number;
|
||||
history_id: string;
|
||||
}
|
||||
|
||||
/** Single email summary from skill state. */
|
||||
interface GmailEmailSummaryLike {
|
||||
id: string;
|
||||
threadId: string;
|
||||
snippet?: string;
|
||||
subject?: string;
|
||||
from?: string;
|
||||
date?: string;
|
||||
}
|
||||
|
||||
/** Gmail skill state slice we care about for metadata sync. */
|
||||
export interface GmailStateForSync {
|
||||
profile?: GmailProfileLike | null;
|
||||
emails?: GmailEmailSummaryLike[] | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit `integration:metadata-sync` with Gmail profile and emails so the
|
||||
* backend can merge them into the user's Google OAuth integration.
|
||||
* No-op when profile is missing or not in Tauri.
|
||||
*/
|
||||
export function syncGmailMetadataToBackend(gmailState: GmailStateForSync | undefined): void {
|
||||
if (!gmailState?.profile || typeof gmailState.profile !== 'object') return;
|
||||
|
||||
const profile = gmailState.profile as GmailProfileLike;
|
||||
const metadata: Record<string, unknown> = {
|
||||
email_address: profile.email_address,
|
||||
messages_total: profile.messages_total,
|
||||
threads_total: profile.threads_total,
|
||||
history_id: profile.history_id,
|
||||
};
|
||||
|
||||
if (Array.isArray(gmailState.emails) && gmailState.emails.length > 0) {
|
||||
metadata.emails = gmailState.emails as GmailEmailSummaryLike[];
|
||||
}
|
||||
|
||||
const payload = {
|
||||
requestId: crypto.randomUUID(),
|
||||
provider: PROVIDER_GOOGLE,
|
||||
metadata,
|
||||
};
|
||||
|
||||
void emitViaRustSocket(INTEGRATION_METADATA_SYNC_EVENT, payload);
|
||||
}
|
||||
@@ -19,6 +19,10 @@ import {
|
||||
type GmailProfile,
|
||||
} from '../store/gmailSlice';
|
||||
import { setSkillError, setSkillState, setSkillStatus } from '../store/skillsSlice';
|
||||
import {
|
||||
syncGmailMetadataToBackend,
|
||||
type GmailStateForSync,
|
||||
} from '../lib/skills/gmailMetadataSync';
|
||||
import { DEV_AUTO_LOAD_SKILL, IS_DEV } from '../utils/config';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -71,7 +75,7 @@ function parseSkillStatePayload(
|
||||
return { skillId, state };
|
||||
}
|
||||
|
||||
/** Sync profile and emails from gmail skill state into gmailSlice. */
|
||||
/** Sync profile and emails from gmail skill state into gmailSlice and send to backend via socket. */
|
||||
function syncGmailStateToSlice(
|
||||
gmailState: Record<string, unknown> | undefined,
|
||||
dispatch: ReturnType<typeof useAppDispatch>
|
||||
@@ -89,6 +93,7 @@ function syncGmailStateToSlice(
|
||||
Array.isArray(gmailState.emails) ? (gmailState.emails as GmailEmailSummary[]) : []
|
||||
)
|
||||
);
|
||||
syncGmailMetadataToBackend(gmailState as GmailStateForSync);
|
||||
}
|
||||
|
||||
export default function SkillProvider({ children }: { children: ReactNode }) {
|
||||
|
||||
Reference in New Issue
Block a user