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.
This commit is contained in:
Mufeed VH
2025-07-28 15:28:07 +05:30
parent c87d36e118
commit efdeff7a31
8 changed files with 53 additions and 35 deletions

View File

@@ -44,6 +44,7 @@
"tailwind-merge": "^2.6.0", "tailwind-merge": "^2.6.0",
"tailwindcss": "^4.1.8", "tailwindcss": "^4.1.8",
"zod": "^3.24.1", "zod": "^3.24.1",
"zustand": "^5.0.6",
}, },
"devDependencies": { "devDependencies": {
"@tauri-apps/cli": "^2", "@tauri-apps/cli": "^2",
@@ -1021,6 +1022,8 @@
"zod": ["zod@3.25.67", "", {}, "sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw=="], "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=="], "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=="], "@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],

View File

@@ -8,7 +8,8 @@
"dev": "vite", "dev": "vite",
"build": "tsc && vite build", "build": "tsc && vite build",
"preview": "vite preview", "preview": "vite preview",
"tauri": "tauri" "tauri": "tauri",
"check": "tsc --noEmit && cd src-tauri && cargo check"
}, },
"dependencies": { "dependencies": {
"@hookform/resolvers": "^3.9.1", "@hookform/resolvers": "^3.9.1",

View File

@@ -170,12 +170,12 @@ export const Settings: React.FC<SettingsProps> = ({
const updatedSettings: ClaudeSettings = { const updatedSettings: ClaudeSettings = {
...settings, ...settings,
permissions: { permissions: {
allow: allowRules.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.trim()), deny: denyRules.map(rule => rule.value).filter(v => v && String(v).trim()),
}, },
env: envVars.reduce((acc, { key, value }) => { env: envVars.reduce((acc, { key, value }) => {
if (key.trim() && value.trim()) { if (key && String(key).trim() && value && String(value).trim()) {
acc[key] = value; acc[key] = String(value);
} }
return acc; return acc;
}, {} as Record<string, string>), }, {} as Record<string, string>),

View File

@@ -632,9 +632,6 @@ export const BashWidget: React.FC<{
description?: string; description?: string;
result?: any; result?: any;
}> = ({ command, description, result }) => { }> = ({ command, description, result }) => {
const { theme } = useTheme();
const syntaxTheme = getClaudeSyntaxTheme(theme);
// Extract result content if available // Extract result content if available
let resultContent = ''; let resultContent = '';
let isError = false; let isError = false;

View File

@@ -52,6 +52,7 @@ const Switch = React.forwardRef<HTMLInputElement, SwitchProps>(
checked={checked} checked={checked}
disabled={disabled} disabled={disabled}
className="sr-only" className="sr-only"
onChange={() => {}}
{...props} {...props}
/> />
</button> </button>

View File

@@ -124,7 +124,7 @@ export const getClaudeSyntaxTheme = (theme: ThemeMode): any => {
overflow: 'auto', overflow: 'auto',
}, },
':not(pre) > code[class*="language-"]': { ':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)'
: 'rgba(139, 92, 246, 0.1)', : 'rgba(139, 92, 246, 0.1)',
padding: '0.1em 0.3em', padding: '0.1em 0.3em',

View File

@@ -1,5 +1,6 @@
import { create } from 'zustand'; import { create } from 'zustand';
import { subscribeWithSelector } from 'zustand/middleware'; import { subscribeWithSelector } from 'zustand/middleware';
import type { StateCreator } from 'zustand';
import { api } from '@/lib/api'; import { api } from '@/lib/api';
import type { AgentRunWithMetrics } from '@/lib/api'; import type { AgentRunWithMetrics } from '@/lib/api';
@@ -32,8 +33,12 @@ interface AgentState {
pollingInterval: NodeJS.Timeout | null; pollingInterval: NodeJS.Timeout | null;
} }
export const useAgentStore = create<AgentState>()( const agentStore: StateCreator<
subscribeWithSelector((set, get) => ({ AgentState,
[],
[['zustand/subscribeWithSelector', never]],
AgentState
> = (set, get) => ({
// Initial state // Initial state
agentRuns: [], agentRuns: [],
runningAgents: new Set(), runningAgents: new Set(),
@@ -59,8 +64,8 @@ export const useAgentStore = create<AgentState>()(
try { try {
const runs = await api.listAgentRuns(); const runs = await api.listAgentRuns();
const runningIds = runs const runningIds = runs
.filter(r => r.status === 'running' || r.status === 'pending') .filter((r) => r.status === 'running' || r.status === 'pending')
.map(r => r.id?.toString() || '') .map((r) => r.id?.toString() || '')
.filter(Boolean); .filter(Boolean);
set({ set({
@@ -83,7 +88,7 @@ export const useAgentStore = create<AgentState>()(
try { try {
const output = await api.getAgentRunWithRealTimeMetrics(runId).then(run => run.output || ''); const output = await api.getAgentRunWithRealTimeMetrics(runId).then(run => run.output || '');
set(state => ({ set((state) => ({
sessionOutputs: { sessionOutputs: {
...state.sessionOutputs, ...state.sessionOutputs,
[runId]: output [runId]: output
@@ -107,7 +112,7 @@ export const useAgentStore = create<AgentState>()(
const run = await api.getAgentRun(runId); const run = await api.getAgentRun(runId);
// Update local state immediately // Update local state immediately
set(state => ({ set((state) => ({
agentRuns: [run, ...state.agentRuns], agentRuns: [run, ...state.agentRuns],
runningAgents: new Set([...state.runningAgents, runId.toString()]) runningAgents: new Set([...state.runningAgents, runId.toString()])
})); }));
@@ -127,8 +132,8 @@ export const useAgentStore = create<AgentState>()(
await api.killAgentSession(runId); await api.killAgentSession(runId);
// Update local state // Update local state
set(state => ({ set((state) => ({
agentRuns: state.agentRuns.map(r => agentRuns: state.agentRuns.map((r) =>
r.id === runId ? { ...r, status: 'cancelled' } : r r.id === runId ? { ...r, status: 'cancelled' } : r
), ),
runningAgents: new Set( runningAgents: new Set(
@@ -147,7 +152,7 @@ export const useAgentStore = create<AgentState>()(
deleteAgentRun: async (runId: number) => { deleteAgentRun: async (runId: number) => {
try { try {
// First ensure the run is cancelled if it's still running // 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')) { if (run && (run.status === 'running' || run.status === 'pending')) {
await api.killAgentSession(runId); await api.killAgentSession(runId);
} }
@@ -156,8 +161,8 @@ export const useAgentStore = create<AgentState>()(
// The run will remain in the database but won't be shown in the UI // The run will remain in the database but won't be shown in the UI
// Update local state // Update local state
set(state => ({ set((state) => ({
agentRuns: state.agentRuns.filter(r => r.id !== runId), agentRuns: state.agentRuns.filter((r) => r.id !== runId),
runningAgents: new Set( runningAgents: new Set(
[...state.runningAgents].filter(id => id !== runId.toString()) [...state.runningAgents].filter(id => id !== runId.toString())
), ),
@@ -178,8 +183,8 @@ export const useAgentStore = create<AgentState>()(
// Handle real-time agent run updates // Handle real-time agent run updates
handleAgentRunUpdate: (run: AgentRunWithMetrics) => { handleAgentRunUpdate: (run: AgentRunWithMetrics) => {
set(state => { set((state) => {
const existingIndex = state.agentRuns.findIndex(r => r.id === run.id); const existingIndex = state.agentRuns.findIndex((r) => r.id === run.id);
const updatedRuns = [...state.agentRuns]; const updatedRuns = [...state.agentRuns];
if (existingIndex >= 0) { if (existingIndex >= 0) {
@@ -189,8 +194,8 @@ export const useAgentStore = create<AgentState>()(
} }
const runningIds = updatedRuns const runningIds = updatedRuns
.filter(r => r.status === 'running' || r.status === 'pending') .filter((r) => r.status === 'running' || r.status === 'pending')
.map(r => r.id?.toString() || '') .map((r) => r.id?.toString() || '')
.filter(Boolean); .filter(Boolean);
return { return {
@@ -228,5 +233,8 @@ export const useAgentStore = create<AgentState>()(
set({ pollingInterval: null }); set({ pollingInterval: null });
} }
} }
})) });
export const useAgentStore = create<AgentState>()(
subscribeWithSelector(agentStore)
); );

View File

@@ -1,5 +1,6 @@
import { create } from 'zustand'; import { create } from 'zustand';
import { subscribeWithSelector } from 'zustand/middleware'; import { subscribeWithSelector } from 'zustand/middleware';
import type { StateCreator } from 'zustand';
import { api } from '@/lib/api'; import { api } from '@/lib/api';
import type { Session, Project } from '@/lib/api'; import type { Session, Project } from '@/lib/api';
@@ -30,8 +31,12 @@ interface SessionState {
handleOutputUpdate: (sessionId: string, output: string) => void; handleOutputUpdate: (sessionId: string, output: string) => void;
} }
export const useSessionStore = create<SessionState>()( const sessionStore: StateCreator<
subscribeWithSelector((set, get) => ({ SessionState,
[],
[['zustand/subscribeWithSelector', never]],
SessionState
> = (set, get) => ({
// Initial state // Initial state
projects: [], projects: [],
sessions: {}, sessions: {},
@@ -62,7 +67,7 @@ export const useSessionStore = create<SessionState>()(
set({ isLoadingSessions: true, error: null }); set({ isLoadingSessions: true, error: null });
try { try {
const projectSessions = await api.getProjectSessions(projectId); const projectSessions = await api.getProjectSessions(projectId);
set(state => ({ set((state) => ({
sessions: { sessions: {
...state.sessions, ...state.sessions,
[projectId]: projectSessions [projectId]: projectSessions
@@ -85,7 +90,7 @@ export const useSessionStore = create<SessionState>()(
if (sessionId) { if (sessionId) {
// Find session across all projects // Find session across all projects
for (const projectSessions of Object.values(sessions)) { 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) { if (found) {
currentSession = found; currentSession = found;
break; break;
@@ -101,7 +106,7 @@ export const useSessionStore = create<SessionState>()(
set({ isLoadingOutputs: true, error: null }); set({ isLoadingOutputs: true, error: null });
try { try {
const output = await api.getClaudeSessionOutput(sessionId); const output = await api.getClaudeSessionOutput(sessionId);
set(state => ({ set((state) => ({
sessionOutputs: { sessionOutputs: {
...state.sessionOutputs, ...state.sessionOutputs,
[sessionId]: output [sessionId]: output
@@ -123,10 +128,10 @@ export const useSessionStore = create<SessionState>()(
console.warn('deleteSession not implemented in API'); console.warn('deleteSession not implemented in API');
// Update local state // Update local state
set(state => ({ set((state) => ({
sessions: { sessions: {
...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, currentSessionId: state.currentSessionId === sessionId ? null : state.currentSessionId,
currentSession: state.currentSession?.id === sessionId ? null : state.currentSession, currentSession: state.currentSession?.id === sessionId ? null : state.currentSession,
@@ -150,7 +155,7 @@ export const useSessionStore = create<SessionState>()(
set(state => { set(state => {
const projectId = session.project_id; const projectId = session.project_id;
const projectSessions = state.sessions[projectId] || []; 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; let updatedSessions;
if (existingIndex >= 0) { if (existingIndex >= 0) {
@@ -172,12 +177,15 @@ export const useSessionStore = create<SessionState>()(
// Handle output update // Handle output update
handleOutputUpdate: (sessionId: string, output: string) => { handleOutputUpdate: (sessionId: string, output: string) => {
set(state => ({ set((state) => ({
sessionOutputs: { sessionOutputs: {
...state.sessionOutputs, ...state.sessionOutputs,
[sessionId]: output [sessionId]: output
} }
})); }));
} }
})) });
export const useSessionStore = create<SessionState>()(
subscribeWithSelector(sessionStore)
); );