2026-04-06 15:42:53 -04:00
|
|
|
import { useState } from "preact/hooks";
|
|
|
|
|
import {
|
|
|
|
|
AgentWorkspace,
|
|
|
|
|
FeedWorkspace,
|
|
|
|
|
SwipeWorkspace,
|
|
|
|
|
useAppPresentation,
|
|
|
|
|
useSessionDrawerEdgeSwipe,
|
|
|
|
|
} from "./appShell/presentation";
|
|
|
|
|
import { VoiceStatus } from "./components/Controls";
|
|
|
|
|
import { SessionDrawer } from "./components/SessionDrawer";
|
|
|
|
|
import { WorkbenchOverlay } from "./components/WorkbenchOverlay";
|
2026-03-06 22:51:19 -05:00
|
|
|
import { useWebRTC } from "./hooks/useWebRTC";
|
2026-04-06 15:42:53 -04:00
|
|
|
import type { ThemeName, ThemeOption } from "./theme/themes";
|
|
|
|
|
import { useThemePreference } from "./theme/useThemePreference";
|
2026-03-12 09:25:15 -04:00
|
|
|
|
2026-04-06 15:42:53 -04:00
|
|
|
function AgentPanel({
|
|
|
|
|
app,
|
2026-03-14 20:21:44 -04:00
|
|
|
rtc,
|
2026-04-06 15:42:53 -04:00
|
|
|
sessionDrawerOpen,
|
|
|
|
|
setSessionDrawerOpen,
|
|
|
|
|
sessionDrawerEdgeGesture,
|
|
|
|
|
activeTheme,
|
|
|
|
|
themeOptions,
|
|
|
|
|
onSelectTheme,
|
2026-03-14 20:21:44 -04:00
|
|
|
}: {
|
2026-04-06 15:42:53 -04:00
|
|
|
app: ReturnType<typeof useAppPresentation>;
|
|
|
|
|
rtc: ReturnType<typeof useWebRTC>;
|
|
|
|
|
sessionDrawerOpen: boolean;
|
|
|
|
|
setSessionDrawerOpen(open: boolean): void;
|
|
|
|
|
sessionDrawerEdgeGesture: ReturnType<typeof useSessionDrawerEdgeSwipe>;
|
|
|
|
|
activeTheme: ThemeName;
|
|
|
|
|
themeOptions: ThemeOption[];
|
|
|
|
|
onSelectTheme(themeName: ThemeName): void;
|
2026-03-14 20:21:44 -04:00
|
|
|
}) {
|
|
|
|
|
return (
|
2026-04-06 15:42:53 -04:00
|
|
|
<AgentWorkspace
|
|
|
|
|
active={app.view === "agent"}
|
|
|
|
|
selectedCard={app.selectedCard}
|
|
|
|
|
selectedCardSelection={app.selectedCardSelection}
|
|
|
|
|
selectedCardContextLabel={app.selectedCardContextLabel}
|
|
|
|
|
onClearSelectedCardContext={app.clearSelectedCardContext}
|
|
|
|
|
textOnly={rtc.textOnly}
|
|
|
|
|
onToggleTextOnly={app.handleToggleTextOnly}
|
|
|
|
|
sessionDrawerEdge={
|
|
|
|
|
!sessionDrawerOpen ? (
|
|
|
|
|
<div
|
|
|
|
|
id="session-drawer-edge"
|
|
|
|
|
data-no-swipe="1"
|
|
|
|
|
onTouchStart={sessionDrawerEdgeGesture.onTouchStart}
|
|
|
|
|
onTouchMove={sessionDrawerEdgeGesture.onTouchMove}
|
|
|
|
|
onTouchEnd={sessionDrawerEdgeGesture.onTouchEnd}
|
|
|
|
|
onTouchCancel={sessionDrawerEdgeGesture.onTouchCancel}
|
|
|
|
|
/>
|
|
|
|
|
) : null
|
|
|
|
|
}
|
|
|
|
|
logLines={rtc.logLines}
|
|
|
|
|
connected={rtc.connected}
|
|
|
|
|
onSendMessage={app.handleSendMessage}
|
|
|
|
|
effectiveAgentState={app.effectiveAgentState}
|
|
|
|
|
textStreaming={rtc.textStreaming}
|
|
|
|
|
connecting={rtc.connecting}
|
|
|
|
|
audioLevel={app.audioLevel}
|
|
|
|
|
sessionDrawer={
|
|
|
|
|
<SessionDrawer
|
|
|
|
|
open={sessionDrawerOpen}
|
|
|
|
|
progress={sessionDrawerEdgeGesture.progress}
|
|
|
|
|
dragging={sessionDrawerEdgeGesture.progress > 0 && !sessionDrawerOpen}
|
|
|
|
|
sessions={rtc.sessions}
|
|
|
|
|
activeSessionId={rtc.activeSessionId}
|
|
|
|
|
busy={rtc.sessionLoading || rtc.textStreaming}
|
|
|
|
|
onClose={() => setSessionDrawerOpen(false)}
|
|
|
|
|
onCreate={async () => {
|
|
|
|
|
await rtc.createSession();
|
|
|
|
|
setSessionDrawerOpen(false);
|
|
|
|
|
}}
|
|
|
|
|
onSelect={async (chatId) => {
|
|
|
|
|
await rtc.switchSession(chatId);
|
|
|
|
|
setSessionDrawerOpen(false);
|
|
|
|
|
}}
|
|
|
|
|
onRename={async (chatId, title) => {
|
|
|
|
|
await rtc.renameSession(chatId, title);
|
|
|
|
|
}}
|
|
|
|
|
onDelete={async (chatId) => {
|
|
|
|
|
await rtc.deleteSession(chatId);
|
|
|
|
|
setSessionDrawerOpen(false);
|
|
|
|
|
}}
|
|
|
|
|
activeTheme={activeTheme}
|
|
|
|
|
themeOptions={themeOptions}
|
|
|
|
|
onSelectTheme={onSelectTheme}
|
2026-03-14 20:21:44 -04:00
|
|
|
/>
|
2026-04-06 15:42:53 -04:00
|
|
|
}
|
|
|
|
|
workbenchOverlay={
|
|
|
|
|
<WorkbenchOverlay
|
|
|
|
|
items={rtc.workbenchItems}
|
|
|
|
|
onDismiss={rtc.dismissWorkbenchItem}
|
|
|
|
|
onPromote={rtc.promoteWorkbenchItem}
|
2026-03-14 20:21:44 -04:00
|
|
|
/>
|
2026-04-06 15:42:53 -04:00
|
|
|
}
|
|
|
|
|
/>
|
2026-03-14 20:21:44 -04:00
|
|
|
);
|
|
|
|
|
}
|
2026-03-12 09:25:15 -04:00
|
|
|
|
2026-04-06 15:42:53 -04:00
|
|
|
function FeedPanel({
|
|
|
|
|
app,
|
|
|
|
|
rtc,
|
2026-03-14 20:21:44 -04:00
|
|
|
}: {
|
2026-04-06 15:42:53 -04:00
|
|
|
app: ReturnType<typeof useAppPresentation>;
|
|
|
|
|
rtc: ReturnType<typeof useWebRTC>;
|
2026-03-14 20:21:44 -04:00
|
|
|
}) {
|
|
|
|
|
return (
|
2026-04-06 15:42:53 -04:00
|
|
|
<FeedWorkspace
|
|
|
|
|
cards={rtc.cards}
|
|
|
|
|
onDismiss={rtc.dismissCard}
|
|
|
|
|
onChoice={app.handleCardChoice}
|
|
|
|
|
onAskCard={app.handleAskCard}
|
|
|
|
|
/>
|
2026-03-14 20:21:44 -04:00
|
|
|
);
|
|
|
|
|
}
|
2026-03-14 12:10:39 -04:00
|
|
|
|
2026-03-14 20:21:44 -04:00
|
|
|
export function App() {
|
|
|
|
|
const rtc = useWebRTC();
|
2026-04-06 15:42:53 -04:00
|
|
|
const app = useAppPresentation(rtc);
|
|
|
|
|
const theme = useThemePreference();
|
|
|
|
|
const [sessionDrawerOpen, setSessionDrawerOpen] = useState(false);
|
|
|
|
|
const sessionDrawerEdgeGesture = useSessionDrawerEdgeSwipe({
|
|
|
|
|
enabled: app.view === "agent" && !sessionDrawerOpen,
|
|
|
|
|
onOpen: () => setSessionDrawerOpen(true),
|
2026-03-14 20:21:44 -04:00
|
|
|
});
|
2026-03-06 22:51:19 -05:00
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<>
|
2026-04-06 15:42:53 -04:00
|
|
|
<SwipeWorkspace
|
|
|
|
|
view={app.view}
|
|
|
|
|
trackStyle={app.trackStyle}
|
|
|
|
|
onSwipeStart={app.onSwipeStart}
|
|
|
|
|
onSwipeMove={app.onSwipeMove}
|
|
|
|
|
onSwipeEnd={app.onSwipeEnd}
|
|
|
|
|
onSwipeCancel={app.onSwipeCancel}
|
|
|
|
|
onTouchStart={app.onTouchStart}
|
|
|
|
|
onTouchMove={app.onTouchMove}
|
|
|
|
|
onTouchEnd={app.onTouchEnd}
|
|
|
|
|
onTouchCancel={app.onTouchCancel}
|
|
|
|
|
agentWorkspace={
|
|
|
|
|
<AgentPanel
|
|
|
|
|
app={app}
|
|
|
|
|
rtc={rtc}
|
|
|
|
|
sessionDrawerOpen={sessionDrawerOpen}
|
|
|
|
|
setSessionDrawerOpen={setSessionDrawerOpen}
|
|
|
|
|
sessionDrawerEdgeGesture={sessionDrawerEdgeGesture}
|
|
|
|
|
activeTheme={theme.themeName}
|
|
|
|
|
themeOptions={theme.themeOptions}
|
|
|
|
|
onSelectTheme={theme.setThemeName}
|
2026-03-14 20:21:44 -04:00
|
|
|
/>
|
2026-04-06 15:42:53 -04:00
|
|
|
}
|
|
|
|
|
feedWorkspace={<FeedPanel app={app} rtc={rtc} />}
|
|
|
|
|
/>
|
2026-03-06 22:51:19 -05:00
|
|
|
<VoiceStatus text={rtc.voiceStatus} visible={rtc.statusVisible} />
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
}
|