diff --git a/src/main/agent/runtime.ts b/src/main/agent/runtime.ts index a9b6d0c..68806aa 100644 --- a/src/main/agent/runtime.ts +++ b/src/main/agent/runtime.ts @@ -23,7 +23,7 @@ let globalWorkspacePath: string | null = null * Set the workspace path for filesystem synchronization. * When set, files created by the agent will be synced to this directory. */ -export function setWorkspacePath(path: string | null) { +export function setWorkspacePath(path: string | null): void { globalWorkspacePath = path console.log('[Runtime] Workspace path set to:', path) } @@ -98,7 +98,7 @@ export async function createAgentRuntime(options: CreateAgentRuntimeOptions = {} const model = getModelInstance(modelId) console.log('[Runtime] Model instance created:', typeof model) - const saver = await getCheckpointer() + const checkpointer = await getCheckpointer() console.log('[Runtime] Checkpointer ready') // Use provided workspace path, fall back to global, or null for no sync @@ -107,18 +107,19 @@ export async function createAgentRuntime(options: CreateAgentRuntimeOptions = {} // Using type assertion to work around version compatibility issues // between @langchain packages and deepagentsjs types - // eslint-disable-next-line @typescript-eslint/no-explicit-any const agent = createDeepAgent({ - model: model as any, - checkpointer: saver as any, + model, + checkpointer, // Use SyncedStateBackend to enable bidirectional disk sync - backend: createSyncedBackendFactory(syncPath) as any + backend: createSyncedBackendFactory(syncPath) }) console.log('[Runtime] Deep agent created with', syncPath ? 'disk sync' : 'state-only storage') return agent } +export type DeepAgent = ReturnType + // Clean up resources export async function closeRuntime(): Promise { if (checkpointer) { diff --git a/src/main/agent/types.ts b/src/main/agent/types.ts new file mode 100644 index 0000000..fab6771 --- /dev/null +++ b/src/main/agent/types.ts @@ -0,0 +1,4 @@ +// @ts-ignore this is a workaround to avoid type errors in the main process +import type { createAgentRuntime } from './runtime' + +export type DeepAgent = Awaited> diff --git a/src/preload/index.d.ts b/src/preload/index.d.ts index 99b86c2..601eabe 100644 --- a/src/preload/index.d.ts +++ b/src/preload/index.d.ts @@ -36,7 +36,9 @@ interface CustomAPI { } models: { list: () => Promise + listProviders: () => Promise getDefault: () => Promise + deleteApiKey: (provider: string) => Promise setDefault: (modelId: string) => Promise setApiKey: (provider: string, apiKey: string) => Promise getApiKey: (provider: string) => Promise diff --git a/src/preload/index.ts b/src/preload/index.ts index c8dfb3b..aa62d82 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -152,7 +152,9 @@ const api = { select: (threadId?: string): Promise => { return ipcRenderer.invoke('workspace:select', threadId) }, - syncToDisk: (threadId: string): Promise<{ + syncToDisk: ( + threadId: string + ): Promise<{ success: boolean synced?: string[] errors?: string[] diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx index edd1d5f..0c9016e 100644 --- a/src/renderer/src/App.tsx +++ b/src/renderer/src/App.tsx @@ -18,29 +18,35 @@ function App(): React.JSX.Element { const [isLoading, setIsLoading] = useState(true) const [leftWidth, setLeftWidth] = useState(LEFT_DEFAULT) const [rightWidth, setRightWidth] = useState(RIGHT_DEFAULT) - + // Track drag start widths const dragStartWidths = useRef<{ left: number; right: number } | null>(null) - const handleLeftResize = useCallback((totalDelta: number) => { - if (!dragStartWidths.current) { - dragStartWidths.current = { left: leftWidth, right: rightWidth } - } - const newWidth = dragStartWidths.current.left + totalDelta - setLeftWidth(Math.min(LEFT_MAX, Math.max(LEFT_MIN, newWidth))) - }, [leftWidth, rightWidth]) + const handleLeftResize = useCallback( + (totalDelta: number) => { + if (!dragStartWidths.current) { + dragStartWidths.current = { left: leftWidth, right: rightWidth } + } + const newWidth = dragStartWidths.current.left + totalDelta + setLeftWidth(Math.min(LEFT_MAX, Math.max(LEFT_MIN, newWidth))) + }, + [leftWidth, rightWidth] + ) - const handleRightResize = useCallback((totalDelta: number) => { - if (!dragStartWidths.current) { - dragStartWidths.current = { left: leftWidth, right: rightWidth } - } - const newWidth = dragStartWidths.current.right - totalDelta - setRightWidth(Math.min(RIGHT_MAX, Math.max(RIGHT_MIN, newWidth))) - }, [leftWidth, rightWidth]) + const handleRightResize = useCallback( + (totalDelta: number) => { + if (!dragStartWidths.current) { + dragStartWidths.current = { left: leftWidth, right: rightWidth } + } + const newWidth = dragStartWidths.current.right - totalDelta + setRightWidth(Math.min(RIGHT_MAX, Math.max(RIGHT_MIN, newWidth))) + }, + [leftWidth, rightWidth] + ) // Reset drag start on mouse up useEffect(() => { - const handleMouseUp = () => { + const handleMouseUp = (): void => { dragStartWidths.current = null } document.addEventListener('mouseup', handleMouseUp) @@ -78,11 +84,15 @@ function App(): React.JSX.Element { {/* Draggable titlebar region with app badge */}
- OPENWORK - {__APP_VERSION__} + + OPENWORK + + + {__APP_VERSION__} +
- + {/* Main content area */}
{/* Left Sidebar - Thread List */} diff --git a/src/renderer/src/components/chat/ChatContainer.tsx b/src/renderer/src/components/chat/ChatContainer.tsx index 4cc00da..37bfcb8 100644 --- a/src/renderer/src/components/chat/ChatContainer.tsx +++ b/src/renderer/src/components/chat/ChatContainer.tsx @@ -10,6 +10,7 @@ import { WorkspacePicker } from './WorkspacePicker' import { ApprovalDialog } from '@/components/hitl/ApprovalDialog' import { ElectronIPCTransport } from '@/lib/electron-transport' import type { Message } from '@/types' +import type { DeepAgent } from '../../../../main/agent/types' interface ChatContainerProps { threadId: string @@ -158,7 +159,7 @@ export function ChatContainer({ threadId }: ChatContainerProps): React.JSX.Eleme ) // Use the useStream hook with our custom transport - const stream = useStream({ + const stream = useStream({ transport, threadId, messagesKey: 'messages', @@ -169,7 +170,6 @@ export function ChatContainer({ threadId }: ChatContainerProps): React.JSX.Eleme console.error('[ChatContainer] Stream error:', error) } }) - console.log('[ChatContainer] Stream:', stream.messages) // Refresh threads when loading state changes from true to false (stream completed) const prevLoadingRef = useRef(false) diff --git a/src/renderer/src/components/panels/TodoPanel.tsx b/src/renderer/src/components/panels/TodoPanel.tsx index 7b1500d..107eda3 100644 --- a/src/renderer/src/components/panels/TodoPanel.tsx +++ b/src/renderer/src/components/panels/TodoPanel.tsx @@ -33,15 +33,15 @@ const STATUS_CONFIG = { } } -export function TodoPanel() { +export function TodoPanel(): React.JSX.Element { const { todos } = useAppStore() const [completedExpanded, setCompletedExpanded] = useState(false) // Group todos by status - const inProgress = todos.filter(t => t.status === 'in_progress') - const pending = todos.filter(t => t.status === 'pending') - const completed = todos.filter(t => t.status === 'completed') - const cancelled = todos.filter(t => t.status === 'cancelled') + const inProgress = todos.filter((t) => t.status === 'in_progress') + const pending = todos.filter((t) => t.status === 'pending') + const completed = todos.filter((t) => t.status === 'completed') + const cancelled = todos.filter((t) => t.status === 'cancelled') // Completed section includes both completed and cancelled const doneItems = [...completed, ...cancelled] @@ -59,10 +59,12 @@ export function TodoPanel() {
PROGRESS - {done}/{total} + + {done}/{total} +
-
@@ -73,9 +75,7 @@ export function TodoPanel() {
{!hasAnyTodos ? ( -
- No tasks yet -
+
No tasks yet
) : ( <> {/* Completed/Cancelled Section (Collapsible) */} @@ -129,22 +129,26 @@ export function TodoPanel() { ) } -function TodoItem({ todo }: { todo: Todo }) { +function TodoItem({ todo }: { todo: Todo }): React.JSX.Element { const config = STATUS_CONFIG[todo.status] const Icon = config.icon return ( -
- +
+
-
+
{todo.content}
diff --git a/src/renderer/src/lib/store.ts b/src/renderer/src/lib/store.ts index c4c0f66..de41492 100644 --- a/src/renderer/src/lib/store.ts +++ b/src/renderer/src/lib/store.ts @@ -1,5 +1,14 @@ import { create } from 'zustand' -import type { Thread, Message, Todo, ModelConfig, Provider, HITLRequest, FileInfo, Subagent } from '@/types' +import type { + Thread, + Message, + Todo, + ModelConfig, + Provider, + HITLRequest, + FileInfo, + Subagent +} from '@/types' interface AppState { // Threads diff --git a/tsconfig.web.json b/tsconfig.web.json index c9941d0..0a7cb26 100644 --- a/tsconfig.web.json +++ b/tsconfig.web.json @@ -5,7 +5,8 @@ "src/renderer/src/**/*", "src/renderer/src/**/*.tsx", "src/preload/*.d.ts", - "src/types.ts" + "src/types.ts", + "src/main/agent/types.ts" ], "compilerOptions": { "composite": true,