Feature/avatar customization (#25)

* Avatar Customization + Update Agent Brain

* Bugfixes

---------

Co-authored-by: iamlukethedev <iamlukethedev@users.noreply.github.com>
This commit is contained in:
Luke The Dev
2026-03-20 23:17:30 -05:00
committed by GitHub
parent 65c2b9cf85
commit 6b5895dcfe
3 changed files with 42 additions and 12 deletions
@@ -19,6 +19,10 @@ const PreviewFigure = ({
const groupRef = useRef<THREE.Group>(null); const groupRef = useRef<THREE.Group>(null);
const reportedReadyRef = useRef(false); const reportedReadyRef = useRef(false);
useEffect(() => {
reportedReadyRef.current = false;
}, [profile]);
useFrame((state) => { useFrame((state) => {
if (!reportedReadyRef.current) { if (!reportedReadyRef.current) {
reportedReadyRef.current = true; reportedReadyRef.current = true;
+20 -6
View File
@@ -1799,11 +1799,18 @@ export function OfficeScreen({
spokenPhoneCallKeysRef.current = new Set( spokenPhoneCallKeysRef.current = new Set(
[...spokenPhoneCallKeysRef.current].filter((key) => activeKeys.has(key)), [...spokenPhoneCallKeysRef.current].filter((key) => activeKeys.has(key)),
); );
setPreparedPhoneCallsByAgentId((previous) => setPreparedPhoneCallsByAgentId((previous) => {
Object.fromEntries( const next = Object.fromEntries(
Object.entries(previous).filter(([, entry]) => activeKeys.has(entry.requestKey)), Object.entries(previous).filter(([, entry]) => activeKeys.has(entry.requestKey)),
),
); );
if (
Object.keys(previous).length === Object.keys(next).length &&
Object.keys(previous).every((agentId) => previous[agentId] === next[agentId])
) {
return previous;
}
return next;
});
}, [phoneCallByAgentId]); }, [phoneCallByAgentId]);
useEffect(() => { useEffect(() => {
@@ -1955,11 +1962,18 @@ export function OfficeScreen({
preparedTextMessageKeysRef.current = new Set( preparedTextMessageKeysRef.current = new Set(
[...preparedTextMessageKeysRef.current].filter((key) => activeKeys.has(key)), [...preparedTextMessageKeysRef.current].filter((key) => activeKeys.has(key)),
); );
setPreparedTextMessagesByAgentId((previous) => setPreparedTextMessagesByAgentId((previous) => {
Object.fromEntries( const next = Object.fromEntries(
Object.entries(previous).filter(([, entry]) => activeKeys.has(entry.requestKey)), Object.entries(previous).filter(([, entry]) => activeKeys.has(entry.requestKey)),
),
); );
if (
Object.keys(previous).length === Object.keys(next).length &&
Object.keys(previous).every((agentId) => previous[agentId] === next[agentId])
) {
return previous;
}
return next;
});
}, [textMessageByAgentId]); }, [textMessageByAgentId]);
useEffect(() => { useEffect(() => {
+16 -4
View File
@@ -2133,6 +2133,8 @@ export function RetroOffice3D({
const phoneBoothAgentIdRef = useRef<string | null>(null); const phoneBoothAgentIdRef = useRef<string | null>(null);
const onPhoneCallSpeakRef = useRef(onPhoneCallSpeak); const onPhoneCallSpeakRef = useRef(onPhoneCallSpeak);
const onPhoneCallCompleteRef = useRef(onPhoneCallComplete); const onPhoneCallCompleteRef = useRef(onPhoneCallComplete);
const onStandupArrivalsChangeRef = useRef(onStandupArrivalsChange);
const lastStandupArrivalKeyRef = useRef<string | null>(null);
const effectiveSmsBoothAgentIdRef = useRef<string | null>(null); const effectiveSmsBoothAgentIdRef = useRef<string | null>(null);
const effectiveTextMessageScenarioRef = useRef<MockTextMessageScenario | null>(null); const effectiveTextMessageScenarioRef = useRef<MockTextMessageScenario | null>(null);
const smsBoothAgentIdRef = useRef<string | null>(null); const smsBoothAgentIdRef = useRef<string | null>(null);
@@ -2221,7 +2223,10 @@ export function RetroOffice3D({
useEffect(() => { useEffect(() => {
const intervalId = window.setInterval(() => { const intervalId = window.setInterval(() => {
const now = Date.now(); const now = Date.now();
setJanitorActors((previous) => pruneExpiredJanitorActors(previous, now)); setJanitorActors((previous) => {
const next = pruneExpiredJanitorActors(previous, now);
return next.length === previous.length ? previous : next;
});
}, 1000); }, 1000);
return () => { return () => {
window.clearInterval(intervalId); window.clearInterval(intervalId);
@@ -2590,6 +2595,7 @@ export function RetroOffice3D({
phoneBoothAgentIdRef.current = phoneBoothAgentId; phoneBoothAgentIdRef.current = phoneBoothAgentId;
onPhoneCallSpeakRef.current = onPhoneCallSpeak; onPhoneCallSpeakRef.current = onPhoneCallSpeak;
onPhoneCallCompleteRef.current = onPhoneCallComplete; onPhoneCallCompleteRef.current = onPhoneCallComplete;
onStandupArrivalsChangeRef.current = onStandupArrivalsChange;
}, [ }, [
effectiveSmsBoothAgentId, effectiveSmsBoothAgentId,
effectiveTextMessageScenario, effectiveTextMessageScenario,
@@ -2599,6 +2605,7 @@ export function RetroOffice3D({
effectivePhoneCallScenario, effectivePhoneCallScenario,
onPhoneCallComplete, onPhoneCallComplete,
onPhoneCallSpeak, onPhoneCallSpeak,
onStandupArrivalsChange,
phoneBoothAgentId, phoneBoothAgentId,
]); ]);
@@ -3008,7 +3015,10 @@ export function RetroOffice3D({
} }
if (!standupActive || !standupMeeting) { if (!standupActive || !standupMeeting) {
onStandupArrivalsChange?.([]); const nextArrivalsKey = "";
if (lastStandupArrivalKeyRef.current === nextArrivalsKey) return;
lastStandupArrivalKeyRef.current = nextArrivalsKey;
onStandupArrivalsChangeRef.current?.([]);
return; return;
} }
@@ -3017,7 +3027,10 @@ export function RetroOffice3D({
if (!agent || agent.interactionTarget !== "meeting_room") return false; if (!agent || agent.interactionTarget !== "meeting_room") return false;
return Math.hypot(agent.x - agent.targetX, agent.y - agent.targetY) < 18; return Math.hypot(agent.x - agent.targetX, agent.y - agent.targetY) < 18;
}); });
onStandupArrivalsChange?.(arrivedParticipants); const nextArrivalsKey = arrivedParticipants.join("|");
if (lastStandupArrivalKeyRef.current === nextArrivalsKey) return;
lastStandupArrivalKeyRef.current = nextArrivalsKey;
onStandupArrivalsChangeRef.current?.(arrivedParticipants);
}; };
syncArrivalState(); syncArrivalState();
@@ -3029,7 +3042,6 @@ export function RetroOffice3D({
githubReviewAgentId, githubReviewAgentId,
manualSmsBoothOpen, manualSmsBoothOpen,
manualPhoneBoothOpen, manualPhoneBoothOpen,
onStandupArrivalsChange,
phoneBoothAgentId, phoneBoothAgentId,
qaTestingAgentId, qaTestingAgentId,
renderAgentLookupRef, renderAgentLookupRef,