mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-08-30 19:59:38 +02:00
[eric] onboarding: fire persona generation the moment a persona is picked (runs in background through name/consent/connect) so the payoff is instant + magical, not a wait
This commit is contained in:
@@ -39,9 +39,10 @@ export const OnboardingFlow: React.FC<{ onExit: () => void }> = ({ onExit }) =>
|
||||
|
||||
const onPayoff = step === 'discovering' || step === 'greet' || step === 'task' || step === 'more';
|
||||
const floor = useMemo(() => demoPayoff(persona), [persona]);
|
||||
// Personalized payoff from the persona (cheap LLM); status drives the thinking -> stream feel.
|
||||
const { result: suggest, status: suggestStatus } = useOnboardingSuggest(useCase, name, onPayoff);
|
||||
// Deeper: background read-only profiling (only if they consented); trumps the persona suggestion.
|
||||
// Persona generation fires the MOMENT a persona is picked, so it runs in the background through
|
||||
// name/consent/connect and is already there (instant, no wait) by the time they hit the payoff.
|
||||
const { result: suggest, status: suggestStatus } = useOnboardingSuggest(useCase);
|
||||
// Deeper read-only profiling needs connected data, so it can only start after connect (onPayoff).
|
||||
const profile = useOnboardingProfile(name, consent, onPayoff);
|
||||
const profileReady = !!(profile && profile.observation.trim() && profile.options.length > 0);
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// Generates the payoff content (insight + task + 4 options) from the user's persona via the cheap
|
||||
// LLM. Exposes status so the payoff can show a brief "thinking" state, then stream the result in.
|
||||
// Fail-open: on any miss the status goes 'failed' and the caller shows its static floor.
|
||||
// LLM. Fires as soon as the persona is known (not at the payoff), so it runs in the BACKGROUND while
|
||||
// the user goes through name/consent/connect and is ready by the time they land. Fail-open: on any
|
||||
// miss the status goes 'failed' and the caller shows its static floor. Name isn't used here (the task
|
||||
// content doesn't need it; the greeting adds the name separately), so it never re-fires mid-flow.
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import { API_BASE } from '@/shared/config';
|
||||
@@ -13,18 +15,18 @@ export interface SuggestDto {
|
||||
|
||||
export type SuggestStatus = 'idle' | 'loading' | 'ready' | 'failed';
|
||||
|
||||
export function useOnboardingSuggest(persona: string, name: string, active: boolean): { result: SuggestDto | null; status: SuggestStatus } {
|
||||
export function useOnboardingSuggest(persona: string): { result: SuggestDto | null; status: SuggestStatus } {
|
||||
const [result, setResult] = useState<SuggestDto | null>(null);
|
||||
const [status, setStatus] = useState<SuggestStatus>('idle');
|
||||
|
||||
useEffect(() => {
|
||||
if (!active || !persona) return;
|
||||
if (!persona) return;
|
||||
let cancelled = false;
|
||||
setStatus('loading');
|
||||
fetch(`${API_BASE}/agents/onboarding-suggest`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ persona, name }),
|
||||
body: JSON.stringify({ persona }),
|
||||
})
|
||||
.then((r) => (r.ok ? r.json() : null))
|
||||
.then((data: SuggestDto | null) => {
|
||||
@@ -38,7 +40,7 @@ export function useOnboardingSuggest(persona: string, name: string, active: bool
|
||||
})
|
||||
.catch(() => { if (!cancelled) setStatus('failed'); });
|
||||
return () => { cancelled = true; };
|
||||
}, [active, persona, name]);
|
||||
}, [persona]);
|
||||
|
||||
return { result, status };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user