From efdeff7a31eb936775495f309507d671ba55e6c9 Mon Sep 17 00:00:00 2001 From: Mufeed VH Date: Mon, 28 Jul 2025 15:28:07 +0530 Subject: [PATCH] fix(build): resolve TypeScript errors and add missing dependencies - Add missing zustand dependency to package.json - Fix unused variable errors in ToolWidgets.tsx - Remove invalid 'white' theme comparison in claudeSyntaxTheme.ts - Add proper TypeScript types to stores using StateCreator pattern - Add null checks and type casting in Settings.tsx filter operations - Add onChange handler to Switch component to suppress React warning - Add 'check' script for TypeScript validation These changes ensure the TypeScript build passes without errors. --- bun.lock | 3 +++ package.json | 3 ++- src/components/Settings.tsx | 8 +++---- src/components/ToolWidgets.tsx | 3 --- src/components/ui/switch.tsx | 1 + src/lib/claudeSyntaxTheme.ts | 2 +- src/stores/agentStore.ts | 40 ++++++++++++++++++++-------------- src/stores/sessionStore.ts | 28 +++++++++++++++--------- 8 files changed, 53 insertions(+), 35 deletions(-) diff --git a/bun.lock b/bun.lock index c6b28bf..41ccfd2 100644 --- a/bun.lock +++ b/bun.lock @@ -44,6 +44,7 @@ "tailwind-merge": "^2.6.0", "tailwindcss": "^4.1.8", "zod": "^3.24.1", + "zustand": "^5.0.6", }, "devDependencies": { "@tauri-apps/cli": "^2", @@ -1021,6 +1022,8 @@ "zod": ["zod@3.25.67", "", {}, "sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw=="], + "zustand": ["zustand@5.0.6", "", { "peerDependencies": { "@types/react": ">=18.0.0", "immer": ">=9.0.6", "react": ">=18.0.0", "use-sync-external-store": ">=1.2.0" }, "optionalPeers": ["@types/react", "immer", "react", "use-sync-external-store"] }, "sha512-ihAqNeUVhe0MAD+X8M5UzqyZ9k3FFZLBTtqo6JLPwV53cbRB/mJwBI0PxcIgqhBBHlEs8G45OTDTMq3gNcLq3A=="], + "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="], "@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], diff --git a/package.json b/package.json index d35ddc8..32fde47 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,8 @@ "dev": "vite", "build": "tsc && vite build", "preview": "vite preview", - "tauri": "tauri" + "tauri": "tauri", + "check": "tsc --noEmit && cd src-tauri && cargo check" }, "dependencies": { "@hookform/resolvers": "^3.9.1", diff --git a/src/components/Settings.tsx b/src/components/Settings.tsx index 5e0c162..79fa791 100644 --- a/src/components/Settings.tsx +++ b/src/components/Settings.tsx @@ -170,12 +170,12 @@ export const Settings: React.FC = ({ const updatedSettings: ClaudeSettings = { ...settings, permissions: { - allow: allowRules.map(rule => rule.value).filter(v => v.trim()), - deny: denyRules.map(rule => rule.value).filter(v => v.trim()), + allow: allowRules.map(rule => rule.value).filter(v => v && String(v).trim()), + deny: denyRules.map(rule => rule.value).filter(v => v && String(v).trim()), }, env: envVars.reduce((acc, { key, value }) => { - if (key.trim() && value.trim()) { - acc[key] = value; + if (key && String(key).trim() && value && String(value).trim()) { + acc[key] = String(value); } return acc; }, {} as Record), diff --git a/src/components/ToolWidgets.tsx b/src/components/ToolWidgets.tsx index 285c635..fdb00e8 100644 --- a/src/components/ToolWidgets.tsx +++ b/src/components/ToolWidgets.tsx @@ -632,9 +632,6 @@ export const BashWidget: React.FC<{ description?: string; result?: any; }> = ({ command, description, result }) => { - const { theme } = useTheme(); - const syntaxTheme = getClaudeSyntaxTheme(theme); - // Extract result content if available let resultContent = ''; let isError = false; diff --git a/src/components/ui/switch.tsx b/src/components/ui/switch.tsx index 17e7a66..a687d9a 100644 --- a/src/components/ui/switch.tsx +++ b/src/components/ui/switch.tsx @@ -52,6 +52,7 @@ const Switch = React.forwardRef( checked={checked} disabled={disabled} className="sr-only" + onChange={() => {}} {...props} /> diff --git a/src/lib/claudeSyntaxTheme.ts b/src/lib/claudeSyntaxTheme.ts index a4aa9ed..31cc8b8 100644 --- a/src/lib/claudeSyntaxTheme.ts +++ b/src/lib/claudeSyntaxTheme.ts @@ -124,7 +124,7 @@ export const getClaudeSyntaxTheme = (theme: ThemeMode): any => { overflow: 'auto', }, ':not(pre) > code[class*="language-"]': { - background: theme === 'light' || theme === 'white' + background: theme === 'light' ? 'rgba(139, 92, 246, 0.1)' : 'rgba(139, 92, 246, 0.1)', padding: '0.1em 0.3em', diff --git a/src/stores/agentStore.ts b/src/stores/agentStore.ts index f91a531..93c2b9d 100644 --- a/src/stores/agentStore.ts +++ b/src/stores/agentStore.ts @@ -1,5 +1,6 @@ import { create } from 'zustand'; import { subscribeWithSelector } from 'zustand/middleware'; +import type { StateCreator } from 'zustand'; import { api } from '@/lib/api'; import type { AgentRunWithMetrics } from '@/lib/api'; @@ -32,8 +33,12 @@ interface AgentState { pollingInterval: NodeJS.Timeout | null; } -export const useAgentStore = create()( - subscribeWithSelector((set, get) => ({ +const agentStore: StateCreator< + AgentState, + [], + [['zustand/subscribeWithSelector', never]], + AgentState +> = (set, get) => ({ // Initial state agentRuns: [], runningAgents: new Set(), @@ -59,8 +64,8 @@ export const useAgentStore = create()( try { const runs = await api.listAgentRuns(); const runningIds = runs - .filter(r => r.status === 'running' || r.status === 'pending') - .map(r => r.id?.toString() || '') + .filter((r) => r.status === 'running' || r.status === 'pending') + .map((r) => r.id?.toString() || '') .filter(Boolean); set({ @@ -83,7 +88,7 @@ export const useAgentStore = create()( try { const output = await api.getAgentRunWithRealTimeMetrics(runId).then(run => run.output || ''); - set(state => ({ + set((state) => ({ sessionOutputs: { ...state.sessionOutputs, [runId]: output @@ -107,7 +112,7 @@ export const useAgentStore = create()( const run = await api.getAgentRun(runId); // Update local state immediately - set(state => ({ + set((state) => ({ agentRuns: [run, ...state.agentRuns], runningAgents: new Set([...state.runningAgents, runId.toString()]) })); @@ -127,8 +132,8 @@ export const useAgentStore = create()( await api.killAgentSession(runId); // Update local state - set(state => ({ - agentRuns: state.agentRuns.map(r => + set((state) => ({ + agentRuns: state.agentRuns.map((r) => r.id === runId ? { ...r, status: 'cancelled' } : r ), runningAgents: new Set( @@ -147,7 +152,7 @@ export const useAgentStore = create()( deleteAgentRun: async (runId: number) => { try { // First ensure the run is cancelled if it's still running - const run = get().agentRuns.find(r => r.id === runId); + const run = get().agentRuns.find((r) => r.id === runId); if (run && (run.status === 'running' || run.status === 'pending')) { await api.killAgentSession(runId); } @@ -156,8 +161,8 @@ export const useAgentStore = create()( // The run will remain in the database but won't be shown in the UI // Update local state - set(state => ({ - agentRuns: state.agentRuns.filter(r => r.id !== runId), + set((state) => ({ + agentRuns: state.agentRuns.filter((r) => r.id !== runId), runningAgents: new Set( [...state.runningAgents].filter(id => id !== runId.toString()) ), @@ -178,8 +183,8 @@ export const useAgentStore = create()( // Handle real-time agent run updates handleAgentRunUpdate: (run: AgentRunWithMetrics) => { - set(state => { - const existingIndex = state.agentRuns.findIndex(r => r.id === run.id); + set((state) => { + const existingIndex = state.agentRuns.findIndex((r) => r.id === run.id); const updatedRuns = [...state.agentRuns]; if (existingIndex >= 0) { @@ -189,8 +194,8 @@ export const useAgentStore = create()( } const runningIds = updatedRuns - .filter(r => r.status === 'running' || r.status === 'pending') - .map(r => r.id?.toString() || '') + .filter((r) => r.status === 'running' || r.status === 'pending') + .map((r) => r.id?.toString() || '') .filter(Boolean); return { @@ -228,5 +233,8 @@ export const useAgentStore = create()( set({ pollingInterval: null }); } } - })) + }); + +export const useAgentStore = create()( + subscribeWithSelector(agentStore) ); \ No newline at end of file diff --git a/src/stores/sessionStore.ts b/src/stores/sessionStore.ts index 4d9fa68..d30d4fa 100644 --- a/src/stores/sessionStore.ts +++ b/src/stores/sessionStore.ts @@ -1,5 +1,6 @@ import { create } from 'zustand'; import { subscribeWithSelector } from 'zustand/middleware'; +import type { StateCreator } from 'zustand'; import { api } from '@/lib/api'; import type { Session, Project } from '@/lib/api'; @@ -30,8 +31,12 @@ interface SessionState { handleOutputUpdate: (sessionId: string, output: string) => void; } -export const useSessionStore = create()( - subscribeWithSelector((set, get) => ({ +const sessionStore: StateCreator< + SessionState, + [], + [['zustand/subscribeWithSelector', never]], + SessionState +> = (set, get) => ({ // Initial state projects: [], sessions: {}, @@ -62,7 +67,7 @@ export const useSessionStore = create()( set({ isLoadingSessions: true, error: null }); try { const projectSessions = await api.getProjectSessions(projectId); - set(state => ({ + set((state) => ({ sessions: { ...state.sessions, [projectId]: projectSessions @@ -85,7 +90,7 @@ export const useSessionStore = create()( if (sessionId) { // Find session across all projects for (const projectSessions of Object.values(sessions)) { - const found = projectSessions.find(s => s.id === sessionId); + const found = projectSessions.find((s) => s.id === sessionId); if (found) { currentSession = found; break; @@ -101,7 +106,7 @@ export const useSessionStore = create()( set({ isLoadingOutputs: true, error: null }); try { const output = await api.getClaudeSessionOutput(sessionId); - set(state => ({ + set((state) => ({ sessionOutputs: { ...state.sessionOutputs, [sessionId]: output @@ -123,10 +128,10 @@ export const useSessionStore = create()( console.warn('deleteSession not implemented in API'); // Update local state - set(state => ({ + set((state) => ({ sessions: { ...state.sessions, - [projectId]: state.sessions[projectId]?.filter(s => s.id !== sessionId) || [] + [projectId]: state.sessions[projectId]?.filter((s) => s.id !== sessionId) || [] }, currentSessionId: state.currentSessionId === sessionId ? null : state.currentSessionId, currentSession: state.currentSession?.id === sessionId ? null : state.currentSession, @@ -150,7 +155,7 @@ export const useSessionStore = create()( set(state => { const projectId = session.project_id; const projectSessions = state.sessions[projectId] || []; - const existingIndex = projectSessions.findIndex(s => s.id === session.id); + const existingIndex = projectSessions.findIndex((s) => s.id === session.id); let updatedSessions; if (existingIndex >= 0) { @@ -172,12 +177,15 @@ export const useSessionStore = create()( // Handle output update handleOutputUpdate: (sessionId: string, output: string) => { - set(state => ({ + set((state) => ({ sessionOutputs: { ...state.sessionOutputs, [sessionId]: output } })); } - })) + }); + +export const useSessionStore = create()( + subscribeWithSelector(sessionStore) ); \ No newline at end of file