-
- {provider === 'claude' && onArchive && (
-
- )}
- {onDelete && (
-
- )}
+function DetailBar({ sessionTitle, isConnected, isGenerating, onDelete }: DetailBarProps) {
+ return (
+
+
+ {onDelete && (
+
+ )}
+
+
+ {sessionTitle ?? 'New chat'}
+
+
+ {!isConnected ? (
+
+ ) : isGenerating ? (
+
+ ) : (
+
+ )}
+ {!isConnected ? 'Disconnected' : isGenerating ? 'Working...' : ''}
+
-
- {sessionTitle ?? 'New chat'}
-
-
- {!isConnected ? (
-
- ) : isGenerating ? (
-
- ) : (
-
- )}
- {!isConnected ? 'Disconnected' : isGenerating ? 'Working...' : ''}
-
-
-);
+ );
+}
-type InnerProps = {
+type SessionChatProps = {
sessionId: string;
model?: string | null;
};
-const ClaudeInner = ({ sessionId, model }: InnerProps) => {
- const chat = useClaude(sessionId, model, { replaceUrl: false });
- const models = useVisibleClaudeModels();
- const { sessions, archiveSession, deleteSession } = useChatSessions();
- const [, setSelected] = usePanelChannel
(CHANNEL, null);
- const sessionTitle = sessions.find((s) => s.id === sessionId)?.title;
-
- return (
-
- {
- await archiveSession('claude', sessionId);
- setSelected(null);
- window.history.replaceState(null, '', '/chat');
- }}
- onDelete={async () => {
- await deleteSession('claude', sessionId);
- setSelected(null);
- window.history.replaceState(null, '', '/chat');
- }}
- />
-
-
- );
-};
-
-const OpenCodeInner = ({ sessionId, model }: InnerProps) => {
- const chat = useOpenCode(sessionId, model, { replaceUrl: false });
- const models = useVisibleOpenCodeModels();
+function SessionChat({ sessionId, model }: SessionChatProps) {
+ const chat = usePi(sessionId, model, { replaceUrl: false });
+ const models = useVisiblePiModels();
const { sessions, deleteSession } = useChatSessions();
const [, setSelected] = usePanelChannel(CHANNEL, null);
const sessionTitle = sessions.find((s) => s.id === sessionId)?.title;
@@ -123,13 +75,11 @@ const OpenCodeInner = ({ sessionId, model }: InnerProps) => {
return (
{
- await deleteSession('opencode', sessionId);
+ await deleteSession(sessionId);
setSelected(null);
window.history.replaceState(null, '', '/chat');
}}
@@ -137,45 +87,19 @@ const OpenCodeInner = ({ sessionId, model }: InnerProps) => {
);
-};
+}
-const PiMonoInner = ({ sessionId, model }: InnerProps) => {
- const chat = usePiMono(sessionId, model, { replaceUrl: false });
- const models = useVisiblePiMonoModels();
- const { sessions, deleteSession } = useChatSessions();
- const [, setSelected] = usePanelChannel(CHANNEL, null);
- const sessionTitle = sessions.find((s) => s.id === sessionId)?.title;
-
- return (
-
- {
- await deleteSession('pi-mono', sessionId);
- setSelected(null);
- window.history.replaceState(null, '', '/chat');
- }}
- />
-
-
- );
-};
-
-const NewClaudeInner = () => {
+function NewChat() {
const location = useLocation();
const locationState = location.state as ChatLocationState;
const initialSentRef = useRef(false);
- const chat = useClaude();
- const models = useVisibleClaudeModels();
+ const chat = usePi();
+ const models = useVisiblePiModels();
const [, setSelected] = usePanelChannel(CHANNEL, null);
useEffect(() => {
if (chat.sessionId) {
- setSelected({ id: chat.sessionId, provider: 'claude', model: chat.model });
+ setSelected({ id: chat.sessionId, model: chat.model });
}
}, [chat.sessionId]);
@@ -196,11 +120,9 @@ const NewClaudeInner = () => {
return (
{
/>
);
-};
+}
-const NewOpenCodeInner = () => {
- const location = useLocation();
- const locationState = location.state as ChatLocationState;
- const initialSentRef = useRef(false);
- const chat = useOpenCode();
- const models = useVisibleOpenCodeModels();
- const [, setSelected] = usePanelChannel(CHANNEL, null);
-
- useEffect(() => {
- if (chat.sessionId) {
- setSelected({ id: chat.sessionId, provider: 'opencode', model: chat.model });
- }
- }, [chat.sessionId]);
-
- useEffect(() => {
- if (!locationState || initialSentRef.current || !chat.isConnected) return;
- if (locationState.prefillInput) {
- initialSentRef.current = true;
- window.history.replaceState({}, '', location.pathname);
- return;
- }
- if (!locationState.initialMessage) return;
- initialSentRef.current = true;
- if (locationState.model) chat.setSelectedModel(locationState.model);
- chat.sendPrompt(locationState.initialMessage, locationState.attachmentIds, locationState.images);
- window.history.replaceState({}, '', location.pathname);
- }, [chat.isConnected, location.state]);
-
- return (
-
-
-
-
- );
-};
-
-const NewPiMonoInner = () => {
- const location = useLocation();
- const locationState = location.state as ChatLocationState;
- const initialSentRef = useRef(false);
- const chat = usePiMono();
- const models = useVisiblePiMonoModels();
- const [, setSelected] = usePanelChannel(CHANNEL, null);
-
- useEffect(() => {
- if (chat.sessionId) {
- setSelected({ id: chat.sessionId, provider: 'pi-mono', model: chat.model });
- }
- }, [chat.sessionId]);
-
- useEffect(() => {
- if (!locationState || initialSentRef.current || !chat.isConnected) return;
- if (locationState.prefillInput) {
- initialSentRef.current = true;
- window.history.replaceState({}, '', location.pathname);
- return;
- }
- if (!locationState.initialMessage) return;
- initialSentRef.current = true;
- if (locationState.model) chat.setSelectedModel(locationState.model);
- chat.sendPrompt(locationState.initialMessage, locationState.attachmentIds, locationState.images);
- window.history.replaceState({}, '', location.pathname);
- }, [chat.isConnected, location.state]);
-
- return (
-
-
-
-
- );
-};
-
-type NewChatPanelProps = {
- initialProvider?: 'claude' | 'opencode' | 'pi-mono';
-};
-
-const NewChatPanel = ({ initialProvider = 'pi-mono' }: NewChatPanelProps) => {
+function NewChatPanel() {
const [selected] = usePanelChannel(CHANNEL, null);
- // Once a session is created, the inner component updates selected via the channel
if (selected && selected.id !== 'new') {
- return ;
+ return ;
}
- return ;
-};
+ return ;
+}
-export const ChatDetailPanel = () => {
+export function ChatDetailPanel() {
const [selected] = usePanelChannel(CHANNEL, null);
if (!selected) {
@@ -337,8 +158,8 @@ export const ChatDetailPanel = () => {
}
if (selected.id === 'new') {
- return ;
+ return ;
}
- return ;
-};
+ return ;
+}
diff --git a/src/apps/officer-web/Screens/Dashboard/ChatHistory/Screen.tsx b/src/apps/officer-web/Screens/Dashboard/ChatHistory/Screen.tsx
index b1e0cf5b..a05e10b4 100644
--- a/src/apps/officer-web/Screens/Dashboard/ChatHistory/Screen.tsx
+++ b/src/apps/officer-web/Screens/Dashboard/ChatHistory/Screen.tsx
@@ -20,19 +20,19 @@ export const SessionList = () => {
useEffect(() => {
scrolledRef.current = false;
- }, [selected?.id, selected?.provider]);
+ }, [selected?.id]);
const handleSelect = (session: (typeof sessions)[number]) => {
- setSelected({ id: session.id, provider: session.provider, model: session.model ?? null });
+ setSelected({ id: session.id, model: session.model ?? null });
window.history.replaceState(null, '', `/chat/${session.id}`);
};
- const handleDelete = async (provider: 'claude' | 'opencode' | 'pi-mono', id: string) => {
- if (selected?.id === id && selected?.provider === provider) {
+ const handleDelete = async (id: string) => {
+ if (selected?.id === id) {
setSelected(null);
window.history.replaceState(null, '', '/chat');
}
- await deleteSession(provider, id);
+ await deleteSession(id);
};
return (
@@ -42,7 +42,7 @@ export const SessionList = () => {
Sessions