From 3733e99ba8c5d3c8dc18a2c86e55afe6ef253fdc Mon Sep 17 00:00:00 2001 From: Andre Padez Date: Tue, 17 Feb 2026 20:37:40 +0000 Subject: [PATCH] harness uniformization --- .../Screens/Dashboard/Chat/ChatPanel.tsx | 18 +- .../Screens/Dashboard/Chat/useClaude.ts | 8 +- .../Screens/Dashboard/Chat/useOpenCode.ts | 6 +- .../Screens/Dashboard/ChatHistory/Screen.tsx | 21 +- .../Screens/Dashboard/ChatHistory/Widget.tsx | 19 +- .../officer-web/state/useChatSessions.ts} | 31 +- src/apps/officer-web/state/useInitialData.ts | 4 +- .../officer-web/state}/useSlashCommands.ts | 6 +- src/server.tsx | 3 +- src/servers/api/claude/sessions.ts | 96 +------ src/servers/api/opencode/sessions.ts | 122 +------- src/servers/api/opencode/websocket.ts | 10 +- src/servers/api/sessions/sessions.ts | 268 ++++++++++++++++++ src/servers/data-path.ts | 5 + src/servers/hono.ts | 36 +-- src/workspaces/widgets/ChatHistory/index.ts | 3 - .../ChatHistory/useOpenCodeSessions.ts | 38 --- 17 files changed, 338 insertions(+), 356 deletions(-) rename src/{workspaces/widgets/ChatHistory/useSessions.ts => apps/officer-web/state/useChatSessions.ts} (56%) rename src/{workspaces/widgets/ChatHistory => apps/officer-web/state}/useSlashCommands.ts (82%) create mode 100644 src/servers/api/sessions/sessions.ts delete mode 100644 src/workspaces/widgets/ChatHistory/useOpenCodeSessions.ts diff --git a/src/apps/officer-web/Screens/Dashboard/Chat/ChatPanel.tsx b/src/apps/officer-web/Screens/Dashboard/Chat/ChatPanel.tsx index f5368a94..cebaeac7 100644 --- a/src/apps/officer-web/Screens/Dashboard/Chat/ChatPanel.tsx +++ b/src/apps/officer-web/Screens/Dashboard/Chat/ChatPanel.tsx @@ -1,6 +1,8 @@ import { useRef, useEffect, useState } from 'react'; import { useNavigate, useLocation } from 'react-router'; -import { useSessions, useOpenCodeSessions, useSlashCommands, SessionBar } from 'widgets/ChatHistory'; +import { useChatSessions } from '@/state/useChatSessions'; +import { useSlashCommands } from '@/state/useSlashCommands'; +import { SessionBar } from 'widgets/ChatHistory'; import type { ModelOption } from '@/state/useModels'; import type { useClaude } from './useClaude'; import { EmbeddableChat, type Attachment } from './EmbeddableChat'; @@ -24,13 +26,7 @@ export const ChatPanel = ({ chat, provider = 'claude', availableModels = [], onP const [fullscreen, setFullscreen] = useState(false); const initialSentRef = useRef(false); - const claudeSessions = useSessions(); - const opencodeSessions = useOpenCodeSessions(); - const { archiveSession, deleteSession } = - provider === 'claude' - ? claudeSessions - : { archiveSession: undefined, deleteSession: opencodeSessions.deleteSession }; - const sessions = provider === 'claude' ? claudeSessions.sessions : opencodeSessions.sessions; + const { sessions, archiveSession, deleteSession } = useChatSessions(); const slashCommands = useSlashCommands({ sessionId }); const sessionTitle = sessionId ? sessions.find((s) => s.id === sessionId)?.title : undefined; const listPath = '/chat'; @@ -89,16 +85,16 @@ export const ChatPanel = ({ chat, provider = 'claude', availableModels = [], onP isGenerating={isGenerating} fullscreen={fullscreen} onArchive={ - archiveSession && sessionId + provider === 'claude' && sessionId ? async () => { - await archiveSession(sessionId); + await archiveSession(provider, sessionId); navigate(listPath); } : undefined } onDelete={async () => { if (!sessionId) return; - await deleteSession(sessionId); + await deleteSession(provider, sessionId); navigate(listPath); }} onToggleFullscreen={() => setFullscreen((f) => !f)} diff --git a/src/apps/officer-web/Screens/Dashboard/Chat/useClaude.ts b/src/apps/officer-web/Screens/Dashboard/Chat/useClaude.ts index 6f5fd439..1744d671 100644 --- a/src/apps/officer-web/Screens/Dashboard/Chat/useClaude.ts +++ b/src/apps/officer-web/Screens/Dashboard/Chat/useClaude.ts @@ -1,6 +1,6 @@ import { useState, useEffect, useRef } from 'react'; import { useChatWebSocket } from 'hooks/useChatWebSocket'; -import { useSessions } from 'widgets/ChatHistory'; +import { useChatSessions } from '@/state/useChatSessions'; import type { ChatMessage, ServerMessage, TaskInfo } from 'widgets/Chat'; const SAVE_DEBOUNCE_MS = 1000; @@ -31,7 +31,7 @@ export const useClaude = (initialSessionId?: string, initialModel?: string | nul const sessionIdRef = useRef(initialSessionId ?? null); const saveTimerRef = useRef(null); - const { getMessages, saveMessages } = useSessions(); + const { getMessages, saveMessages } = useChatSessions(); const token = localStorage.getItem('BEARER_TOKEN'); const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; @@ -137,7 +137,7 @@ export const useClaude = (initialSessionId?: string, initialModel?: string | nul return; } if (!initialSessionId) return; - getMessages(initialSessionId) + getMessages('claude', initialSessionId) .then((data) => { if (Array.isArray(data) && data.length > 0) setMessages(data); }) @@ -156,7 +156,7 @@ export const useClaude = (initialSessionId?: string, initialModel?: string | nul if (storage) { storage.save(sid, snapshot).catch(() => {}); } else { - saveMessages(sid, snapshot).catch(() => {}); + saveMessages('claude', sid, snapshot).catch(() => {}); } saveTimerRef.current = null; }, SAVE_DEBOUNCE_MS); diff --git a/src/apps/officer-web/Screens/Dashboard/Chat/useOpenCode.ts b/src/apps/officer-web/Screens/Dashboard/Chat/useOpenCode.ts index 22d3d607..8b398912 100644 --- a/src/apps/officer-web/Screens/Dashboard/Chat/useOpenCode.ts +++ b/src/apps/officer-web/Screens/Dashboard/Chat/useOpenCode.ts @@ -2,7 +2,7 @@ import { useState, useEffect, useRef } from 'react'; import { useChatWebSocket } from 'hooks/useChatWebSocket'; import { useSettings } from '@/state/useSettings'; import { useVisibleOpenCodeModels } from '@/state/useModels'; -import { useOpenCodeSessions } from 'widgets/ChatHistory'; +import { useChatSessions } from '@/state/useChatSessions'; import type { ChatMessage, ServerMessage, TaskInfo } from 'widgets/Chat'; type UseOpenCodeOptions = { @@ -29,7 +29,7 @@ export const useOpenCode = (initialSessionId?: string, initialModel?: string | n setSelectedModel(value); }; - const { getMessages } = useOpenCodeSessions(); + const { getMessages } = useChatSessions(); const { settings } = useSettings(); const openCodeModels = useVisibleOpenCodeModels(); @@ -144,7 +144,7 @@ export const useOpenCode = (initialSessionId?: string, initialModel?: string | n // Load messages from OpenCode on mount when resuming a session useEffect(() => { if (!initialSessionId) return; - getMessages(initialSessionId) + getMessages('opencode', initialSessionId) .then((data) => { if (Array.isArray(data) && data.length > 0) setMessages(data); }) diff --git a/src/apps/officer-web/Screens/Dashboard/ChatHistory/Screen.tsx b/src/apps/officer-web/Screens/Dashboard/ChatHistory/Screen.tsx index 2f40e34a..9a54d2c7 100644 --- a/src/apps/officer-web/Screens/Dashboard/ChatHistory/Screen.tsx +++ b/src/apps/officer-web/Screens/Dashboard/ChatHistory/Screen.tsx @@ -1,28 +1,17 @@ -import { useMemo, useState } from 'react'; +import { useState } from 'react'; import { Link } from 'react-router'; import { Plus, MessageSquare, Trash2 } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Card } from '@/components/Card'; -import { useSessions, useOpenCodeSessions } from 'widgets/ChatHistory'; +import { useChatSessions } from '@/state/useChatSessions'; type Filter = 'all' | 'claude' | 'opencode'; export const SessionList = () => { const [filter, setFilter] = useState('all'); - const claude = useSessions(); - const opencode = useOpenCodeSessions(); + const { sessions, deleteSession } = useChatSessions(); - const merged = useMemo( - () => [...claude.sessions, ...opencode.sessions].sort((a, b) => b.createdAt - a.createdAt), - [claude.sessions, opencode.sessions], - ); - - const filtered = filter === 'all' ? merged : merged.filter((s) => s.provider === filter); - - const handleDelete = (id: string, provider: 'claude' | 'opencode') => { - if (provider === 'claude') claude.deleteSession(id); - else opencode.deleteSession(id); - }; + const filtered = filter === 'all' ? sessions : sessions.filter((s) => s.provider === filter); return (
@@ -90,7 +79,7 @@ export const SessionList = () => {