From 2537fbb3428e929d6082a35806144a5f8f2744c5 Mon Sep 17 00:00:00 2001 From: Will Chen Date: Thu, 8 May 2025 17:21:35 -0700 Subject: [PATCH] lint using oxlint (#106) --- .oxlintrc.json | 5 + forge.config.ts | 2 - package-lock.json | 140 ++++++++++++++++++ package.json | 5 +- scaffold/dyad-shim.js | 3 +- scaffold/src/hooks/use-toast.ts | 4 +- scaffold/vite.config.ts | 2 +- src/__tests__/chat_stream_handlers.test.ts | 8 +- src/atoms/proposalAtoms.ts | 2 +- src/components/ChatList.tsx | 4 +- src/components/ChatPanel.tsx | 22 +-- src/components/ErrorBoundary.tsx | 8 +- src/components/HelpDialog.tsx | 2 +- src/components/ProviderSettings.tsx | 11 +- src/components/SupabaseConnector.tsx | 10 +- src/components/TelemetryBanner.tsx | 2 +- src/components/TelemetrySwitch.tsx | 1 - src/components/chat/AttachmentsList.tsx | 1 - src/components/chat/ChatHeader.tsx | 3 +- src/components/chat/ChatInput.tsx | 12 +- src/components/chat/ChatMessage.tsx | 1 - src/components/chat/DyadAddDependency.tsx | 26 +--- src/components/chat/DyadMarkdownParser.tsx | 16 +- src/components/chat/DyadOutput.tsx | 6 +- src/components/chat/HomeChatInput.tsx | 6 +- src/components/chat/MessagesList.tsx | 8 +- src/components/preview_panel/CodeView.tsx | 1 - src/components/preview_panel/FileEditor.tsx | 2 +- .../preview_panel/PreviewIframe.tsx | 7 +- src/components/preview_panel/PreviewPanel.tsx | 5 +- .../settings/ProviderSettingsPage.tsx | 4 +- src/components/ui/sidebar.tsx | 3 +- src/hooks/useAppVersion.ts | 2 +- src/hooks/useLoadApp.ts | 4 +- src/hooks/useLoadApps.ts | 2 +- src/hooks/useProposal.ts | 2 +- src/hooks/useRunApp.ts | 1 - src/hooks/useSettings.ts | 5 +- src/hooks/useStreamChat.ts | 6 +- src/hooks/useVersions.ts | 2 +- src/ipc/handlers/app_handlers.ts | 19 +-- src/ipc/handlers/chat_handlers.ts | 2 +- src/ipc/handlers/chat_stream_handlers.ts | 15 +- src/ipc/handlers/debug_handlers.ts | 4 +- src/ipc/handlers/github_handlers.ts | 9 +- .../handlers/local_model_lmstudio_handler.ts | 2 +- src/ipc/handlers/node_handlers.ts | 4 +- src/ipc/handlers/proposal_handlers.ts | 23 +-- src/ipc/handlers/settings_handlers.ts | 23 +-- src/ipc/handlers/token_count_handlers.ts | 5 +- src/ipc/handlers/version_handlers.ts | 7 +- src/ipc/ipc_client.ts | 4 +- src/ipc/processors/response_processor.ts | 4 +- src/ipc/utils/get_model_client.ts | 2 +- src/ipc/utils/lock_utils.ts | 2 +- src/lib/chat.ts | 1 - src/lib/toast.ts | 2 +- src/main.ts | 2 +- src/pages/app-details.tsx | 7 +- src/pages/settings.tsx | 4 +- src/paths/paths.ts | 2 +- .../supabase_management_client.ts | 2 +- src/utils/codebase.ts | 42 +----- 63 files changed, 251 insertions(+), 292 deletions(-) create mode 100644 .oxlintrc.json diff --git a/.oxlintrc.json b/.oxlintrc.json new file mode 100644 index 0000000..0325337 --- /dev/null +++ b/.oxlintrc.json @@ -0,0 +1,5 @@ +{ + "rules": { + "eslint/no-unused-vars": "error" + } +} diff --git a/forge.config.ts b/forge.config.ts index b100452..eebd778 100644 --- a/forge.config.ts +++ b/forge.config.ts @@ -7,8 +7,6 @@ import { VitePlugin } from "@electron-forge/plugin-vite"; import { FusesPlugin } from "@electron-forge/plugin-fuses"; import { FuseV1Options, FuseVersion } from "@electron/fuses"; import { AutoUnpackNativesPlugin } from "@electron-forge/plugin-auto-unpack-natives"; -import path from "path"; -import fs from "fs"; // Based on https://github.com/electron/forge/blob/6b2d547a7216c30fde1e1fddd1118eee5d872945/packages/plugin/vite/src/VitePlugin.ts#L124 const ignore = (file: string) => { diff --git a/package-lock.json b/package-lock.json index 5b43250..f701d96 100644 --- a/package-lock.json +++ b/package-lock.json @@ -99,6 +99,7 @@ "happy-dom": "^17.4.4", "husky": "^9.1.7", "lint-staged": "^15.5.2", + "oxlint": "^0.16.9", "prettier": "3.5.3", "typescript": "^5.8.3", "vite": "^5.4.17", @@ -3604,6 +3605,118 @@ "node": ">=8.0.0" } }, + "node_modules/@oxlint/darwin-arm64": { + "version": "0.16.9", + "resolved": "https://registry.npmjs.org/@oxlint/darwin-arm64/-/darwin-arm64-0.16.9.tgz", + "integrity": "sha512-s8gPacumFNuDQcl0dCRLI0+efbiQrOF984brGrW1i2buJtaMzjYiunaU5TSrbHgnb/omvpFnG4l9g+YHOK/s0A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@oxlint/darwin-x64": { + "version": "0.16.9", + "resolved": "https://registry.npmjs.org/@oxlint/darwin-x64/-/darwin-x64-0.16.9.tgz", + "integrity": "sha512-QFue9yhfRU+fkbsOmDzCCwDafPR6fnaP/M+Rocp/MMDQ7qvjbB2sj0/xxp/CcvL7aLtFklMeXPR0hCfW3LyrSw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@oxlint/linux-arm64-gnu": { + "version": "0.16.9", + "resolved": "https://registry.npmjs.org/@oxlint/linux-arm64-gnu/-/linux-arm64-gnu-0.16.9.tgz", + "integrity": "sha512-qP/wdlgqLuiW9WDkAsyMN85wQ3nqAQynjRD+1II1QO0yI9N1ZHD6LF9P5fXAqY0eJwcf3emluQMoaeveewtiCg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxlint/linux-arm64-musl": { + "version": "0.16.9", + "resolved": "https://registry.npmjs.org/@oxlint/linux-arm64-musl/-/linux-arm64-musl-0.16.9.tgz", + "integrity": "sha512-486wn1MIqP4hkHTnuWedTb16X6Zs3ImmmMxqzfYlcemf9kODM6yNlxal6wGvkm7SGRPYrsB/P9S5wgpzmLzKrw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxlint/linux-x64-gnu": { + "version": "0.16.9", + "resolved": "https://registry.npmjs.org/@oxlint/linux-x64-gnu/-/linux-x64-gnu-0.16.9.tgz", + "integrity": "sha512-d20zqy4Mimz9CxjIEJdGd6jtyyhpSryff95gNJSTvh/EA4NqvjjlbjxuHt3clNjglRwJWE3kgmUCw9U9oWFcWA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxlint/linux-x64-musl": { + "version": "0.16.9", + "resolved": "https://registry.npmjs.org/@oxlint/linux-x64-musl/-/linux-x64-musl-0.16.9.tgz", + "integrity": "sha512-mZLshz99773RMa77YhtsgWbqE7JY4xnYSDecDy+ZkafRb0acqz1Ujiq2l4cE+HnJOGVOMaOpzG0UoQ3ZNkXNAA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@oxlint/win32-arm64": { + "version": "0.16.9", + "resolved": "https://registry.npmjs.org/@oxlint/win32-arm64/-/win32-arm64-0.16.9.tgz", + "integrity": "sha512-Zp9+0CfTb7ebgvRwDO2F6NVgRtRmxWMdBnrbMRdVbKY6CCT2vjLAIILwBf5AsNLdLQC7FbXAEivSKbRX0UPyJA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@oxlint/win32-x64": { + "version": "0.16.9", + "resolved": "https://registry.npmjs.org/@oxlint/win32-x64/-/win32-x64-0.16.9.tgz", + "integrity": "sha512-6a507bALmDNFdvEbJzu9ybajryBHo+6nMWPNyu/mBguCqmconoBbQXftELd2VG/0ecxBmBcMKAQW6aONGUVc3w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@petamoriken/float16": { "version": "3.9.2", "resolved": "https://registry.npmjs.org/@petamoriken/float16/-/float16-3.9.2.tgz", @@ -15062,6 +15175,33 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/oxlint": { + "version": "0.16.9", + "resolved": "https://registry.npmjs.org/oxlint/-/oxlint-0.16.9.tgz", + "integrity": "sha512-YMGu177AURJxdCq45/Yw6Q+uDh9ZfU++GuLYhUz+DfIGdHpAqVlBI9lCqm2HkLc6qO8ySYZ+8ljsWHLQA8F+EQ==", + "dev": true, + "license": "MIT", + "bin": { + "oxc_language_server": "bin/oxc_language_server", + "oxlint": "bin/oxlint" + }, + "engines": { + "node": ">=8.*" + }, + "funding": { + "url": "https://github.com/sponsors/Boshen" + }, + "optionalDependencies": { + "@oxlint/darwin-arm64": "0.16.9", + "@oxlint/darwin-x64": "0.16.9", + "@oxlint/linux-arm64-gnu": "0.16.9", + "@oxlint/linux-arm64-musl": "0.16.9", + "@oxlint/linux-x64-gnu": "0.16.9", + "@oxlint/linux-x64-musl": "0.16.9", + "@oxlint/win32-arm64": "0.16.9", + "@oxlint/win32-x64": "0.16.9" + } + }, "node_modules/p-cancelable": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", diff --git a/package.json b/package.json index a28fe67..a98b070 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,8 @@ "make": "npm run clean && electron-forge make", "publish": "npm run clean && electron-forge publish", "ts": "npx tsc -p tsconfig.app.json --noEmit", - "lint": "npx biome lint src --fix --unsafe", + "lint": "npx oxlint --fix", + "lint:fix": "npx oxlint --fix --fix-suggestions --fix-dangerously", "db:generate": "drizzle-kit generate", "db:push": "drizzle-kit push", "db:studio": "drizzle-kit studio", @@ -61,6 +62,7 @@ "happy-dom": "^17.4.4", "husky": "^9.1.7", "lint-staged": "^15.5.2", + "oxlint": "^0.16.9", "prettier": "3.5.3", "typescript": "^5.8.3", "vite": "^5.4.17", @@ -131,6 +133,7 @@ "uuid": "^11.1.0" }, "lint-staged": { + "**/*.{js,mjs,cjs,jsx,ts,mts,cts,tsx,vue,astro,svelte}": "oxlint", "*.{js,css,md,ts,tsx,jsx,json}": "prettier --write" } } diff --git a/scaffold/dyad-shim.js b/scaffold/dyad-shim.js index bf204d9..89d1ce6 100644 --- a/scaffold/dyad-shim.js +++ b/scaffold/dyad-shim.js @@ -17,6 +17,7 @@ ? new URL(url, window.location.href).href : window.location.href; } catch (e) { + console.error("Could not parse URL", e); newUrl = window.location.href; } @@ -64,7 +65,7 @@ }; // --- Listener for Back/Forward Navigation (popstate event) --- - window.addEventListener("popstate", (event) => { + window.addEventListener("popstate", () => { const currentUrl = window.location.href; previousUrl = currentUrl; }); diff --git a/scaffold/src/hooks/use-toast.ts b/scaffold/src/hooks/use-toast.ts index 01f0976..9070a0f 100644 --- a/scaffold/src/hooks/use-toast.ts +++ b/scaffold/src/hooks/use-toast.ts @@ -12,7 +12,7 @@ type ToasterToast = ToastProps & { action?: ToastActionElement; }; -const actionTypes = { +const _actionTypes = { ADD_TOAST: "ADD_TOAST", UPDATE_TOAST: "UPDATE_TOAST", DISMISS_TOAST: "DISMISS_TOAST", @@ -26,7 +26,7 @@ function genId() { return count.toString(); } -type ActionType = typeof actionTypes; +type ActionType = typeof _actionTypes; type Action = | { diff --git a/scaffold/vite.config.ts b/scaffold/vite.config.ts index c553812..fec7dae 100644 --- a/scaffold/vite.config.ts +++ b/scaffold/vite.config.ts @@ -87,7 +87,7 @@ export function devErrorAndNavigationPlugin(): Plugin { }; } -export default defineConfig(({ mode }) => ({ +export default defineConfig(() => ({ server: { host: "::", port: 8080, diff --git a/src/__tests__/chat_stream_handlers.test.ts b/src/__tests__/chat_stream_handlers.test.ts index 0af7b99..aacea50 100644 --- a/src/__tests__/chat_stream_handlers.test.ts +++ b/src/__tests__/chat_stream_handlers.test.ts @@ -99,8 +99,8 @@ console.log("TodoItem"); expect(result).toEqual([ { path: "src/components/TodoItem.tsx", - content: `import React from \"react\"; -console.log(\"TodoItem\");`, + content: `import React from "react"; +console.log("TodoItem");`, }, ]); }); @@ -117,8 +117,8 @@ console.log("TodoItem"); expect(result).toEqual([ { path: "src/components/TodoItem.tsx", - content: `import React from \"react\"; -console.log(\"TodoItem\");`, + content: `import React from "react"; +console.log("TodoItem");`, }, ]); }); diff --git a/src/atoms/proposalAtoms.ts b/src/atoms/proposalAtoms.ts index 203a649..12083be 100644 --- a/src/atoms/proposalAtoms.ts +++ b/src/atoms/proposalAtoms.ts @@ -1,4 +1,4 @@ import { atom } from "jotai"; -import type { CodeProposal, ProposalResult } from "@/lib/schemas"; +import type { ProposalResult } from "@/lib/schemas"; export const proposalResultAtom = atom(null); diff --git a/src/components/ChatList.tsx b/src/components/ChatList.tsx index ccc1e4a..703d39f 100644 --- a/src/components/ChatList.tsx +++ b/src/components/ChatList.tsx @@ -1,6 +1,6 @@ import { useEffect } from "react"; import { useNavigate, useRouterState } from "@tanstack/react-router"; -import type { ChatSummary } from "@/lib/schemas"; + import { formatDistanceToNow } from "date-fns"; import { PlusCircle, MoreVertical, Trash2 } from "lucide-react"; import { useAtom } from "jotai"; @@ -29,7 +29,7 @@ export function ChatList({ show }: { show?: boolean }) { const navigate = useNavigate(); const [selectedChatId, setSelectedChatId] = useAtom(selectedChatIdAtom); const [selectedAppId, setSelectedAppId] = useAtom(selectedAppIdAtom); - const [isDropdownOpen, setIsDropdownOpen] = useAtom(dropdownOpenAtom); + const [, setIsDropdownOpen] = useAtom(dropdownOpenAtom); const { chats, loading, refreshChats } = useChats(selectedAppId); const routerState = useRouterState(); const isChatRoute = routerState.location.pathname === "/chat"; diff --git a/src/components/ChatPanel.tsx b/src/components/ChatPanel.tsx index 212c8ca..8f65c24 100644 --- a/src/components/ChatPanel.tsx +++ b/src/components/ChatPanel.tsx @@ -2,7 +2,7 @@ import { useState, useRef, useEffect, useCallback } from "react"; import { useAtom, useAtomValue } from "jotai"; import { chatMessagesAtom, chatStreamCountAtom } from "../atoms/chatAtoms"; import { IpcClient } from "@/ipc/ipc_client"; -import { selectedAppIdAtom } from "@/atoms/appAtoms"; + import { ChatHeader } from "./chat/ChatHeader"; import { MessagesList } from "./chat/MessagesList"; import { ChatInput } from "./chat/ChatInput"; @@ -20,14 +20,11 @@ export function ChatPanel({ isPreviewOpen, onTogglePreview, }: ChatPanelProps) { - const appId = useAtomValue(selectedAppIdAtom); const [messages, setMessages] = useAtom(chatMessagesAtom); - const [appName, setAppName] = useState("Chat"); const [isVersionPaneOpen, setIsVersionPaneOpen] = useState(false); const [error, setError] = useState(null); const streamCount = useAtomValue(chatStreamCountAtom); // Reference to store the processed prompt so we don't submit it twice - const processedPromptRef = useRef(null); const messagesEndRef = useRef(null); const messagesContainerRef = useRef(null); @@ -83,23 +80,6 @@ export function ChatPanel({ }; }, []); - useEffect(() => { - const fetchAppName = async () => { - if (!appId) return; - - try { - const app = await IpcClient.getInstance().getApp(appId); - if (app?.name) { - setAppName(app.name); - } - } catch (error) { - console.error("Failed to fetch app name:", error); - } - }; - - fetchAppName(); - }, [appId]); - const fetchChatMessages = useCallback(async () => { if (!chatId) { setMessages([]); diff --git a/src/components/ErrorBoundary.tsx b/src/components/ErrorBoundary.tsx index 56250b3..527f7ad 100644 --- a/src/components/ErrorBoundary.tsx +++ b/src/components/ErrorBoundary.tsx @@ -1,10 +1,4 @@ -import React, { - Component, - ErrorInfo, - ReactNode, - useState, - useEffect, -} from "react"; +import React, { useState, useEffect } from "react"; import { Button } from "@/components/ui/button"; import { LightbulbIcon } from "lucide-react"; import { ErrorComponentProps } from "@tanstack/react-router"; diff --git a/src/components/HelpDialog.tsx b/src/components/HelpDialog.tsx index c2d64d3..7848eed 100644 --- a/src/components/HelpDialog.tsx +++ b/src/components/HelpDialog.tsx @@ -292,7 +292,7 @@ Session ID: ${sessionId}

Chat Messages

- {chatLogsData.chat.messages.map((msg, index) => ( + {chatLogsData.chat.messages.map((msg) => (
{msg.role === "user" ? "You" : "Assistant"}:{" "} diff --git a/src/components/ProviderSettings.tsx b/src/components/ProviderSettings.tsx index b7a10d0..9a32e59 100644 --- a/src/components/ProviderSettings.tsx +++ b/src/components/ProviderSettings.tsx @@ -10,13 +10,8 @@ import { providerSettingsRoute } from "@/routes/settings/providers/$provider"; import type { ModelProvider } from "@/lib/schemas"; import { useSettings } from "@/hooks/useSettings"; import { GiftIcon } from "lucide-react"; -interface ProviderSettingsProps { - configuredProviders?: ModelProvider[]; -} -export function ProviderSettingsGrid({ - configuredProviders = [], -}: ProviderSettingsProps) { +export function ProviderSettingsGrid() { const navigate = useNavigate(); const handleProviderClick = (provider: ModelProvider) => { @@ -33,10 +28,6 @@ export function ProviderSettingsGrid({

AI Providers

{Object.entries(PROVIDERS).map(([key, provider]) => { - const isConfigured = configuredProviders.includes( - key as ModelProvider, - ); - return ( (null); - const { settings, updateSettings, isAnyProviderSetup } = useSettings(); + const { settings, updateSettings } = useSettings(); const appId = useAtomValue(selectedAppIdAtom); const { refreshVersions } = useVersions(appId); const { streamMessage, isStreaming, setIsStreaming, error, setError } = @@ -76,7 +73,7 @@ export function ChatInput({ chatId }: { chatId?: number }) { const [showError, setShowError] = useState(true); const [isApproving, setIsApproving] = useState(false); // State for approving const [isRejecting, setIsRejecting] = useState(false); // State for rejecting - const [messages, setMessages] = useAtom(chatMessagesAtom); + const [, setMessages] = useAtom(chatMessagesAtom); const setIsPreviewOpen = useSetAtom(isPreviewOpenAtom); const [showTokenBar, setShowTokenBar] = useAtom(showTokenBarAtom); @@ -101,7 +98,7 @@ export function ChatInput({ chatId }: { chatId?: number }) { error: proposalError, refreshProposal, } = useProposal(chatId); - const { proposal, chatId: proposalChatId, messageId } = proposalResult ?? {}; + const { proposal, messageId } = proposalResult ?? {}; const adjustHeight = () => { const textarea = textareaRef.current; @@ -620,7 +617,6 @@ function ChatInputActions({ isApproving, isRejecting, }: ChatInputActionsProps) { - const [autoApprove, setAutoApprove] = useState(false); const [isDetailsVisible, setIsDetailsVisible] = useState(false); if (proposal.type === "tip-proposal") { diff --git a/src/components/chat/ChatMessage.tsx b/src/components/chat/ChatMessage.tsx index 3b363e8..1210f35 100644 --- a/src/components/chat/ChatMessage.tsx +++ b/src/components/chat/ChatMessage.tsx @@ -1,4 +1,3 @@ -import { memo } from "react"; import type { Message } from "@/ipc/ipc_types"; import { DyadMarkdownParser, diff --git a/src/components/chat/DyadAddDependency.tsx b/src/components/chat/DyadAddDependency.tsx index 94a96ca..3350c09 100644 --- a/src/components/chat/DyadAddDependency.tsx +++ b/src/components/chat/DyadAddDependency.tsx @@ -1,19 +1,10 @@ import type React from "react"; import type { ReactNode } from "react"; import { useState } from "react"; -import { Button } from "../ui/button"; + import { IpcClient } from "../../ipc/ipc_client"; -import { useAtom, useAtomValue } from "jotai"; -import { chatMessagesAtom, selectedChatIdAtom } from "../../atoms/chatAtoms"; -import { useStreamChat } from "@/hooks/useStreamChat"; -import { - Package, - ChevronsUpDown, - ChevronsDownUp, - Loader, - ExternalLink, - Download, -} from "lucide-react"; + +import { Package, ChevronsUpDown, ChevronsDownUp } from "lucide-react"; import { CodeHighlight } from "./CodeHighlight"; interface DyadAddDependencyProps { @@ -28,15 +19,14 @@ export const DyadAddDependency: React.FC = ({ }) => { // Extract package attribute from the node if available const packages = node?.properties?.packages?.split(" ") || ""; - const [isInstalling, setIsInstalling] = useState(false); const [isContentVisible, setIsContentVisible] = useState(false); const hasChildren = !!children; return (
setIsContentVisible(!isContentVisible) : undefined } @@ -66,12 +56,6 @@ export const DyadAddDependency: React.FC = ({
)} - {isInstalling && ( -
- - Installing... -
- )}
{hasChildren && (
diff --git a/src/components/chat/DyadMarkdownParser.tsx b/src/components/chat/DyadMarkdownParser.tsx index bbab8b7..bc04845 100644 --- a/src/components/chat/DyadMarkdownParser.tsx +++ b/src/components/chat/DyadMarkdownParser.tsx @@ -30,7 +30,13 @@ type ContentPiece = | { type: "markdown"; content: string } | { type: "custom-tag"; tagInfo: CustomTagInfo }; -const customLink = ({ node, ...props }: { node?: any; [key: string]: any }) => ( +const customLink = ({ + node: _node, + ...props +}: { + node?: any; + [key: string]: any; +}) => ( { @@ -358,11 +364,3 @@ function renderCustomTag( return null; } } - -/** - * Extract attribute values from className string - */ -function extractAttribute(className: string, attrName: string): string { - const match = new RegExp(`${attrName}="([^"]*)"`, "g").exec(className); - return match ? match[1] : ""; -} diff --git a/src/components/chat/DyadOutput.tsx b/src/components/chat/DyadOutput.tsx index fef825b..792cb49 100644 --- a/src/components/chat/DyadOutput.tsx +++ b/src/components/chat/DyadOutput.tsx @@ -6,8 +6,8 @@ import { XCircle, Sparkles, } from "lucide-react"; -import { useAtom, useSetAtom } from "jotai"; -import { chatInputValueAtom, selectedChatIdAtom } from "@/atoms/chatAtoms"; +import { useAtomValue } from "jotai"; +import { selectedChatIdAtom } from "@/atoms/chatAtoms"; import { useStreamChat } from "@/hooks/useStreamChat"; interface DyadOutputProps { type: "error" | "warning"; @@ -21,7 +21,7 @@ export const DyadOutput: React.FC = ({ children, }) => { const [isContentVisible, setIsContentVisible] = useState(false); - const [selectedChatId, setSelectedChatId] = useAtom(selectedChatIdAtom); + const selectedChatId = useAtomValue(selectedChatIdAtom); const { streamMessage } = useStreamChat(); // If the type is not warning, it is an error (in case LLM gives a weird "type") diff --git a/src/components/chat/HomeChatInput.tsx b/src/components/chat/HomeChatInput.tsx index 49a007a..d38129e 100644 --- a/src/components/chat/HomeChatInput.tsx +++ b/src/components/chat/HomeChatInput.tsx @@ -1,6 +1,6 @@ -import { SendIcon, StopCircleIcon, X, Paperclip, Loader2 } from "lucide-react"; +import { SendIcon, StopCircleIcon, Paperclip } from "lucide-react"; import type React from "react"; -import { useEffect, useRef, useState } from "react"; +import { useEffect, useRef } from "react"; import { ModelPicker } from "@/components/ModelPicker"; import { useSettings } from "@/hooks/useSettings"; import { homeChatInputValueAtom } from "@/atoms/chatAtoms"; // Use a different atom for home input @@ -21,7 +21,7 @@ export function HomeChatInput({ const [inputValue, setInputValue] = useAtom(homeChatInputValueAtom); const textareaRef = useRef(null); const { settings, updateSettings, isAnyProviderSetup } = useSettings(); - const { streamMessage, isStreaming, setIsStreaming } = useStreamChat({ + const { isStreaming } = useStreamChat({ hasChatId: false, }); // eslint-disable-line @typescript-eslint/no-unused-vars diff --git a/src/components/chat/MessagesList.tsx b/src/components/chat/MessagesList.tsx index d8814a5..a34eed7 100644 --- a/src/components/chat/MessagesList.tsx +++ b/src/components/chat/MessagesList.tsx @@ -6,12 +6,12 @@ import { SetupBanner } from "../SetupBanner"; import { useSettings } from "@/hooks/useSettings"; import { useStreamChat } from "@/hooks/useStreamChat"; import { selectedChatIdAtom } from "@/atoms/chatAtoms"; -import { useAtom, useAtomValue, useSetAtom } from "jotai"; +import { useAtomValue, useSetAtom } from "jotai"; import { Loader2, RefreshCw, Undo } from "lucide-react"; import { Button } from "@/components/ui/button"; import { useVersions } from "@/hooks/useVersions"; import { selectedAppIdAtom } from "@/atoms/appAtoms"; -import { showError, showSuccess, showWarning } from "@/lib/toast"; +import { showError, showWarning } from "@/lib/toast"; import { IpcClient } from "@/ipc/ipc_client"; import { chatMessagesAtom } from "@/atoms/chatAtoms"; @@ -24,13 +24,13 @@ export const MessagesList = forwardRef( function MessagesList({ messages, messagesEndRef }, ref) { const appId = useAtomValue(selectedAppIdAtom); const { versions, revertVersion } = useVersions(appId); - const { streamMessage, isStreaming, error, setError } = useStreamChat(); + const { streamMessage, isStreaming } = useStreamChat(); const { isAnyProviderSetup } = useSettings(); const setMessages = useSetAtom(chatMessagesAtom); const [isUndoLoading, setIsUndoLoading] = useState(false); const [isRetryLoading, setIsRetryLoading] = useState(false); - const [selectedChatId, setSelectedChatId] = useAtom(selectedChatIdAtom); + const selectedChatId = useAtomValue(selectedChatIdAtom); return (
diff --git a/src/components/preview_panel/CodeView.tsx b/src/components/preview_panel/CodeView.tsx index 5e49b6c..b5f4c4a 100644 --- a/src/components/preview_panel/CodeView.tsx +++ b/src/components/preview_panel/CodeView.tsx @@ -1,4 +1,3 @@ -import { useState } from "react"; import { FileEditor } from "./FileEditor"; import { FileTree } from "./FileTree"; import { RefreshCw } from "lucide-react"; diff --git a/src/components/preview_panel/FileEditor.tsx b/src/components/preview_panel/FileEditor.tsx index b81fc13..a48c2ae 100644 --- a/src/components/preview_panel/FileEditor.tsx +++ b/src/components/preview_panel/FileEditor.tsx @@ -90,7 +90,7 @@ export const FileEditor = ({ appId, filePath }: FileEditorProps) => { const editorTheme = isDarkMode ? "dyad-dark" : "dyad-light"; // Handle editor mount - const handleEditorDidMount: OnMount = (editor, monaco) => { + const handleEditorDidMount: OnMount = (editor) => { editorRef.current = editor; // Listen for model content change events diff --git a/src/components/preview_panel/PreviewIframe.tsx b/src/components/preview_panel/PreviewIframe.tsx index 53553bd..01ca2bb 100644 --- a/src/components/preview_panel/PreviewIframe.tsx +++ b/src/components/preview_panel/PreviewIframe.tsx @@ -20,7 +20,7 @@ import { } from "lucide-react"; import { selectedChatIdAtom } from "@/atoms/chatAtoms"; import { IpcClient } from "@/ipc/ipc_client"; -import { useLoadApp } from "@/hooks/useLoadApp"; + import { useLoadAppFile } from "@/hooks/useLoadAppFile"; import { DropdownMenu, @@ -28,8 +28,6 @@ import { DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; -import { useSettings } from "@/hooks/useSettings"; -import { useRunApp } from "@/hooks/useRunApp"; import { useStreamChat } from "@/hooks/useStreamChat"; interface ErrorBannerProps { @@ -113,7 +111,7 @@ export const PreviewIframe = ({ loading }: { loading: boolean }) => { // State to trigger iframe reload const [reloadKey, setReloadKey] = useState(0); const [errorMessage, setErrorMessage] = useAtom(previewErrorMessageAtom); - const [selectedChatId, setSelectedChatId] = useAtom(selectedChatIdAtom); + const selectedChatId = useAtomValue(selectedChatIdAtom); const { streamMessage } = useStreamChat(); const [availableRoutes, setAvailableRoutes] = useState< Array<{ path: string; label: string }> @@ -168,7 +166,6 @@ export const PreviewIframe = ({ loading }: { loading: boolean }) => { const [navigationHistory, setNavigationHistory] = useState([]); const [currentHistoryPosition, setCurrentHistoryPosition] = useState(0); const iframeRef = useRef(null); - const { settings } = useSettings(); // Add message listener for iframe errors and navigation events useEffect(() => { diff --git a/src/components/preview_panel/PreviewPanel.tsx b/src/components/preview_panel/PreviewPanel.tsx index b89fb08..ee65537 100644 --- a/src/components/preview_panel/PreviewPanel.tsx +++ b/src/components/preview_panel/PreviewPanel.tsx @@ -5,7 +5,7 @@ import { previewPanelKeyAtom, selectedAppIdAtom, } from "../../atoms/appAtoms"; -import { useLoadApp } from "@/hooks/useLoadApp"; + import { CodeView } from "./CodeView"; import { PreviewIframe } from "./PreviewIframe"; import { @@ -14,11 +14,8 @@ import { ChevronDown, ChevronUp, Logs, - RefreshCw, MoreVertical, - Trash2, Cog, - CirclePower, Power, } from "lucide-react"; import { motion } from "framer-motion"; diff --git a/src/components/settings/ProviderSettingsPage.tsx b/src/components/settings/ProviderSettingsPage.tsx index bf37e8a..a0e8815 100644 --- a/src/components/settings/ProviderSettingsPage.tsx +++ b/src/components/settings/ProviderSettingsPage.tsx @@ -104,7 +104,7 @@ export function ProviderSettingsPage({ provider }: ProviderSettingsPageProps) { providerSettings: { ...settings?.providerSettings, [provider]: { - ...(settings?.providerSettings?.[provider] || {}), + ...settings?.providerSettings?.[provider], apiKey: { value: apiKeyInput, }, @@ -134,7 +134,7 @@ export function ProviderSettingsPage({ provider }: ProviderSettingsPageProps) { providerSettings: { ...settings?.providerSettings, [provider]: { - ...(settings?.providerSettings?.[provider] || {}), + ...settings?.providerSettings?.[provider], apiKey: undefined, }, }, diff --git a/src/components/ui/sidebar.tsx b/src/components/ui/sidebar.tsx index 9a3a23f..df66ce1 100644 --- a/src/components/ui/sidebar.tsx +++ b/src/components/ui/sidebar.tsx @@ -1,7 +1,7 @@ import * as React from "react"; import { Slot } from "@radix-ui/react-slot"; import { type VariantProps, cva } from "class-variance-authority"; -import { Menu, PanelLeftIcon } from "lucide-react"; +import { Menu } from "lucide-react"; import { cn } from "@/lib/utils"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; @@ -224,7 +224,6 @@ function Sidebar({ } function SidebarTrigger({ - className, onClick, ...props }: React.ComponentProps) { diff --git a/src/hooks/useAppVersion.ts b/src/hooks/useAppVersion.ts index ede62b2..65163e2 100644 --- a/src/hooks/useAppVersion.ts +++ b/src/hooks/useAppVersion.ts @@ -9,7 +9,7 @@ export function useAppVersion() { try { const version = await IpcClient.getInstance().getAppVersion(); setAppVersion(version); - } catch (error) { + } catch { setAppVersion(null); } }; diff --git a/src/hooks/useLoadApp.ts b/src/hooks/useLoadApp.ts index 9533c82..506fc75 100644 --- a/src/hooks/useLoadApp.ts +++ b/src/hooks/useLoadApp.ts @@ -1,7 +1,7 @@ import { useState, useEffect } from "react"; import { IpcClient } from "@/ipc/ipc_client"; -import type { App } from "@/ipc/ipc_types"; -import { atom, useAtom } from "jotai"; + +import { useAtom } from "jotai"; import { currentAppAtom } from "@/atoms/appAtoms"; export function useLoadApp(appId: number | null) { diff --git a/src/hooks/useLoadApps.ts b/src/hooks/useLoadApps.ts index 8b7f8e8..5061efe 100644 --- a/src/hooks/useLoadApps.ts +++ b/src/hooks/useLoadApps.ts @@ -5,7 +5,7 @@ import { IpcClient } from "@/ipc/ipc_client"; export function useLoadApps() { const [apps, setApps] = useAtom(appsListAtom); - const [appBasePath, setAppBasePath] = useAtom(appBasePathAtom); + const [, setAppBasePath] = useAtom(appBasePathAtom); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); diff --git a/src/hooks/useProposal.ts b/src/hooks/useProposal.ts index 698e159..d0df7c9 100644 --- a/src/hooks/useProposal.ts +++ b/src/hooks/useProposal.ts @@ -1,6 +1,6 @@ import { useState, useEffect, useCallback } from "react"; import { IpcClient } from "@/ipc/ipc_client"; -import type { CodeProposal, ProposalResult } from "@/lib/schemas"; // Import Proposal type +import type { ProposalResult } from "@/lib/schemas"; // Import Proposal type import { proposalResultAtom } from "@/atoms/proposalAtoms"; import { useAtom } from "jotai"; export function useProposal(chatId?: number | undefined) { diff --git a/src/hooks/useRunApp.ts b/src/hooks/useRunApp.ts index 7954a30..30a8a83 100644 --- a/src/hooks/useRunApp.ts +++ b/src/hooks/useRunApp.ts @@ -9,7 +9,6 @@ import { selectedAppIdAtom, } from "@/atoms/appAtoms"; import { useAtom, useAtomValue, useSetAtom } from "jotai"; -import { App } from "@/ipc/ipc_types"; export function useRunApp() { const [loading, setLoading] = useState(false); diff --git a/src/hooks/useSettings.ts b/src/hooks/useSettings.ts index 23f86bf..53e2167 100644 --- a/src/hooks/useSettings.ts +++ b/src/hooks/useSettings.ts @@ -1,5 +1,5 @@ import { useState, useEffect, useCallback } from "react"; -import { atom, useAtom } from "jotai"; +import { useAtom } from "jotai"; import { userSettingsAtom, envVarsAtom } from "@/atoms/appAtoms"; import { IpcClient } from "@/ipc/ipc_client"; import { cloudProviders, type UserSettings } from "@/lib/schemas"; @@ -11,9 +11,6 @@ const PROVIDER_TO_ENV_VAR: Record = { google: "GEMINI_API_KEY", }; -// Define a type for the environment variables we expect -type EnvVars = Record; - const TELEMETRY_CONSENT_KEY = "dyadTelemetryConsent"; const TELEMETRY_USER_ID_KEY = "dyadTelemetryUserId"; diff --git a/src/hooks/useStreamChat.ts b/src/hooks/useStreamChat.ts index c71afee..f3193fa 100644 --- a/src/hooks/useStreamChat.ts +++ b/src/hooks/useStreamChat.ts @@ -1,4 +1,4 @@ -import { useCallback, useState } from "react"; +import { useCallback } from "react"; import type { Message } from "@/ipc/ipc_types"; import { useAtom, useSetAtom } from "jotai"; import { @@ -14,7 +14,7 @@ import { useChats } from "./useChats"; import { useLoadApp } from "./useLoadApp"; import { selectedAppIdAtom } from "@/atoms/appAtoms"; import { useVersions } from "./useVersions"; -import { showError, showUncommittedFilesWarning } from "@/lib/toast"; +import { showUncommittedFilesWarning } from "@/lib/toast"; import { useProposal } from "./useProposal"; import { useSearch } from "@tanstack/react-router"; import { useRunApp } from "./useRunApp"; @@ -27,7 +27,7 @@ export function getRandomNumberId() { export function useStreamChat({ hasChatId = true, }: { hasChatId?: boolean } = {}) { - const [messages, setMessages] = useAtom(chatMessagesAtom); + const [, setMessages] = useAtom(chatMessagesAtom); const [isStreaming, setIsStreaming] = useAtom(isStreamingAtom); const [error, setError] = useAtom(chatErrorAtom); const setIsPreviewOpen = useSetAtom(isPreviewOpenAtom); diff --git a/src/hooks/useVersions.ts b/src/hooks/useVersions.ts index a44d9d7..43d50c5 100644 --- a/src/hooks/useVersions.ts +++ b/src/hooks/useVersions.ts @@ -10,7 +10,7 @@ export function useVersions(appId: number | null) { const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const selectedChatId = useAtomValue(selectedChatIdAtom); - const [messages, setMessages] = useAtom(chatMessagesAtom); + const [, setMessages] = useAtom(chatMessagesAtom); useEffect(() => { const loadVersions = async () => { // If no app is selected, clear versions and return diff --git a/src/ipc/handlers/app_handlers.ts b/src/ipc/handlers/app_handlers.ts index 678c655..91ed247 100644 --- a/src/ipc/handlers/app_handlers.ts +++ b/src/ipc/handlers/app_handlers.ts @@ -1,20 +1,15 @@ import { ipcMain } from "electron"; import { db, getDatabasePath } from "../../db"; -import { apps, chats, messages } from "../../db/schema"; -import { desc, eq, and, gte, sql, gt } from "drizzle-orm"; -import type { - App, - CreateAppParams, - SandboxConfig, - Version, -} from "../ipc_types"; +import { apps, chats } from "../../db/schema"; +import { desc, eq } from "drizzle-orm"; +import type { App, CreateAppParams } from "../ipc_types"; import fs from "node:fs"; import path from "node:path"; import { getDyadAppPath, getUserDataPath } from "../../paths/paths"; import { spawn } from "node:child_process"; import git from "isomorphic-git"; import { promises as fsPromises } from "node:fs"; -import { extractCodebase } from "../../utils/codebase"; + // Import our utility modules import { withLock } from "../utils/lock_utils"; import { @@ -26,19 +21,17 @@ import { processCounter, killProcess, removeAppIfCurrentProcess, - RunningAppInfo, } from "../utils/process_manager"; import { ALLOWED_ENV_VARS } from "../../constants/models"; import { getEnvVar } from "../utils/read_env"; import { readSettings } from "../../main/settings"; -import { Worker } from "worker_threads"; + import fixPath from "fix-path"; import { getGitAuthor } from "../utils/git_author"; import killPort from "kill-port"; import util from "util"; import log from "electron-log"; import { getSupabaseProjectName } from "../../supabase_admin/supabase_management_client"; -import { settings } from "happy-dom/lib/PropertySymbol.js"; const logger = log.scope("app_handlers"); @@ -138,7 +131,7 @@ async function executeAppLocalNode({ async function killProcessOnPort(port: number): Promise { try { await killPort(port, "tcp"); - } catch (err) { + } catch { // Ignore if nothing was running on that port } } diff --git a/src/ipc/handlers/chat_handlers.ts b/src/ipc/handlers/chat_handlers.ts index f7d344e..f4ed7b8 100644 --- a/src/ipc/handlers/chat_handlers.ts +++ b/src/ipc/handlers/chat_handlers.ts @@ -5,7 +5,7 @@ import { desc, eq } from "drizzle-orm"; import type { ChatSummary } from "../../lib/schemas"; import * as git from "isomorphic-git"; import * as fs from "fs"; -import * as path from "path"; + import log from "electron-log"; import { getDyadAppPath } from "../../paths/paths"; diff --git a/src/ipc/handlers/chat_stream_handlers.ts b/src/ipc/handlers/chat_stream_handlers.ts index ba68e14..d777903 100644 --- a/src/ipc/handlers/chat_stream_handlers.ts +++ b/src/ipc/handlers/chat_stream_handlers.ts @@ -26,7 +26,7 @@ import * as fs from "fs"; import * as path from "path"; import * as os from "os"; import * as crypto from "crypto"; -import { stat, readFile, writeFile, mkdir, unlink } from "fs/promises"; +import { readFile, writeFile, unlink } from "fs/promises"; const logger = log.scope("chat_stream_handlers"); @@ -61,19 +61,6 @@ if (!fs.existsSync(TEMP_DIR)) { fs.mkdirSync(TEMP_DIR, { recursive: true }); } -// First, define the proper content types to match ai SDK -type TextContent = { - type: "text"; - text: string; -}; - -type ImageContent = { - type: "image"; - image: Buffer; -}; - -type MessageContent = TextContent | ImageContent; - export function registerChatStreamHandlers() { ipcMain.handle("chat:stream", async (event, req: ChatStreamParams) => { try { diff --git a/src/ipc/handlers/debug_handlers.ts b/src/ipc/handlers/debug_handlers.ts index 7d1cd4a..26d37cb 100644 --- a/src/ipc/handlers/debug_handlers.ts +++ b/src/ipc/handlers/debug_handlers.ts @@ -1,8 +1,8 @@ -import { ipcMain, app } from "electron"; +import { ipcMain } from "electron"; import { platform, arch } from "os"; import { SystemDebugInfo, ChatLogsData } from "../ipc_types"; import { readSettings } from "../../main/settings"; -import { execSync } from "child_process"; + import log from "electron-log"; import path from "path"; import fs from "fs"; diff --git a/src/ipc/handlers/github_handlers.ts b/src/ipc/handlers/github_handlers.ts index 7cf457c..8e30f2f 100644 --- a/src/ipc/handlers/github_handlers.ts +++ b/src/ipc/handlers/github_handlers.ts @@ -1,15 +1,10 @@ -import { - ipcMain, - IpcMainEvent, - BrowserWindow, - IpcMainInvokeEvent, -} from "electron"; +import { ipcMain, BrowserWindow, IpcMainInvokeEvent } from "electron"; import fetch from "node-fetch"; // Use node-fetch for making HTTP requests in main process import { writeSettings, readSettings } from "../../main/settings"; import { updateAppGithubRepo } from "../../db/index"; import git from "isomorphic-git"; import http from "isomorphic-git/http/node"; -import path from "node:path"; + import fs from "node:fs"; import { getDyadAppPath } from "../../paths/paths"; import { db } from "../../db"; diff --git a/src/ipc/handlers/local_model_lmstudio_handler.ts b/src/ipc/handlers/local_model_lmstudio_handler.ts index c445c3d..056c876 100644 --- a/src/ipc/handlers/local_model_lmstudio_handler.ts +++ b/src/ipc/handlers/local_model_lmstudio_handler.ts @@ -37,7 +37,7 @@ export async function fetchLMStudioModels(): Promise { logger.info(`Successfully fetched ${models.length} models from LM Studio`); return { models, error: null }; - } catch (error) { + } catch { return { models: [], error: "Failed to fetch models from LM Studio" }; } } diff --git a/src/ipc/handlers/node_handlers.ts b/src/ipc/handlers/node_handlers.ts index 4a93530..d19aa41 100644 --- a/src/ipc/handlers/node_handlers.ts +++ b/src/ipc/handlers/node_handlers.ts @@ -1,5 +1,5 @@ -import { ipcMain, app } from "electron"; -import { exec, execSync } from "child_process"; +import { ipcMain } from "electron"; +import { execSync } from "child_process"; import { platform, arch } from "os"; import { NodeSystemInfo } from "../ipc_types"; import fixPath from "fix-path"; diff --git a/src/ipc/handlers/proposal_handlers.ts b/src/ipc/handlers/proposal_handlers.ts index 645dbce..25e1e94 100644 --- a/src/ipc/handlers/proposal_handlers.ts +++ b/src/ipc/handlers/proposal_handlers.ts @@ -1,14 +1,12 @@ import { ipcMain, type IpcMainInvokeEvent } from "electron"; import type { CodeProposal, - FileChange, ProposalResult, - SqlQuery, ActionProposal, } from "../../lib/schemas"; import { db } from "../../db"; import { messages, chats } from "../../db/schema"; -import { desc, eq, and, Update } from "drizzle-orm"; +import { desc, eq, and } from "drizzle-orm"; import path from "node:path"; // Import path for basename // Import tag parsers import { @@ -31,26 +29,9 @@ import { import { extractCodebase } from "../../utils/codebase"; import { getDyadAppPath } from "../../paths/paths"; import { withLock } from "../utils/lock_utils"; + const logger = log.scope("proposal_handlers"); -// Placeholder Proposal data (can be removed or kept for reference) -// const placeholderProposal: Proposal = { ... }; - -// Type guard for the parsed proposal structure -interface ParsedProposal { - title: string; - files: string[]; -} -function isParsedProposal(obj: any): obj is ParsedProposal { - return ( - obj && - typeof obj === "object" && - typeof obj.title === "string" && - Array.isArray(obj.files) && - obj.files.every((file: any) => typeof file === "string") - ); -} - // Cache for codebase token counts interface CodebaseTokenCache { chatId: number; diff --git a/src/ipc/handlers/settings_handlers.ts b/src/ipc/handlers/settings_handlers.ts index 485460a..cbf88a0 100644 --- a/src/ipc/handlers/settings_handlers.ts +++ b/src/ipc/handlers/settings_handlers.ts @@ -5,28 +5,7 @@ import { readSettings } from "../../main/settings"; export function registerSettingsHandlers() { ipcMain.handle("get-user-settings", async () => { - const settings = await readSettings(); - - // Mask API keys before sending to renderer - if (settings?.providerSettings) { - // Use optional chaining - for (const providerKey in settings.providerSettings) { - // Ensure the key is own property and providerSetting exists - if ( - Object.prototype.hasOwnProperty.call( - settings.providerSettings, - providerKey, - ) - ) { - const providerSetting = settings.providerSettings[providerKey]; - // Check if apiKey exists and is a non-empty string before masking - if (providerSetting?.apiKey?.value) { - providerSetting.apiKey = providerSetting.apiKey; - } - } - } - } - + const settings = readSettings(); return settings; }); diff --git a/src/ipc/handlers/token_count_handlers.ts b/src/ipc/handlers/token_count_handlers.ts index 48d6fdb..18ef1db 100644 --- a/src/ipc/handlers/token_count_handlers.ts +++ b/src/ipc/handlers/token_count_handlers.ts @@ -1,6 +1,6 @@ import { ipcMain } from "electron"; import { db } from "../../db"; -import { chats, messages } from "../../db/schema"; +import { chats } from "../../db/schema"; import { eq } from "drizzle-orm"; import { SYSTEM_PROMPT } from "../../prompts/system_prompt"; import { @@ -11,8 +11,7 @@ import { getDyadAppPath } from "../../paths/paths"; import log from "electron-log"; import { extractCodebase } from "../../utils/codebase"; import { getSupabaseContext } from "../../supabase_admin/supabase_context"; -import { readSettings } from "../../main/settings"; -import { MODEL_OPTIONS } from "../../constants/models"; + import { TokenCountParams } from "../ipc_types"; import { TokenCountResult } from "../ipc_types"; import { estimateTokens, getContextWindow } from "../utils/token_utils"; diff --git a/src/ipc/handlers/version_handlers.ts b/src/ipc/handlers/version_handlers.ts index 9d45ea2..b48112a 100644 --- a/src/ipc/handlers/version_handlers.ts +++ b/src/ipc/handlers/version_handlers.ts @@ -133,12 +133,7 @@ export function registerVersionHandlers() { }); // Process each file to revert to the state in previousVersionId - for (const [ - filepath, - headStatus, - workdirStatus, - stageStatus, - ] of matrix) { + for (const [filepath, headStatus, workdirStatus] of matrix) { const fullPath = path.join(appPath, filepath); // If file exists in HEAD (previous version) diff --git a/src/ipc/ipc_client.ts b/src/ipc/ipc_client.ts index 6d3e6ec..e7f8a4b 100644 --- a/src/ipc/ipc_client.ts +++ b/src/ipc/ipc_client.ts @@ -9,7 +9,6 @@ import type { AppOutput, Chat, ChatResponseEnd, - ChatStreamParams, CreateAppParams, CreateAppResult, ListAppsResponse, @@ -18,13 +17,12 @@ import type { Version, SystemDebugInfo, LocalModel, - LocalModelListResponse, TokenCountParams, TokenCountResult, ChatLogsData, BranchResult, } from "./ipc_types"; -import type { CodeProposal, ProposalResult } from "@/lib/schemas"; +import type { ProposalResult } from "@/lib/schemas"; import { showError } from "@/lib/toast"; export interface ChatStreamCallbacks { diff --git a/src/ipc/processors/response_processor.ts b/src/ipc/processors/response_processor.ts index 8b569a8..f64d52c 100644 --- a/src/ipc/processors/response_processor.ts +++ b/src/ipc/processors/response_processor.ts @@ -5,7 +5,7 @@ import fs from "node:fs"; import { getDyadAppPath } from "../../paths/paths"; import path from "node:path"; import git from "isomorphic-git"; -import { getGithubUser } from "../handlers/github_handlers"; + import { getGitAuthor } from "../utils/git_author"; import log from "electron-log"; import { executeAddDependency } from "./executeAddDependency"; @@ -229,7 +229,7 @@ export async function processFullResponseActions( if (dyadExecuteSqlQueries.length > 0) { for (const query of dyadExecuteSqlQueries) { try { - const result = await executeSupabaseSql({ + await executeSupabaseSql({ supabaseProjectId: chatWithApp.app.supabaseProjectId!, query: query.content, }); diff --git a/src/ipc/utils/get_model_client.ts b/src/ipc/utils/get_model_client.ts index 2916e7a..df36abf 100644 --- a/src/ipc/utils/get_model_client.ts +++ b/src/ipc/utils/get_model_client.ts @@ -1,4 +1,4 @@ -import { createOpenAI, OpenAIProvider } from "@ai-sdk/openai"; +import { createOpenAI } from "@ai-sdk/openai"; import { createGoogleGenerativeAI as createGoogle } from "@ai-sdk/google"; import { createAnthropic } from "@ai-sdk/anthropic"; import { createOpenRouter } from "@openrouter/ai-sdk-provider"; diff --git a/src/ipc/utils/lock_utils.ts b/src/ipc/utils/lock_utils.ts index 77c5725..fa46ee3 100644 --- a/src/ipc/utils/lock_utils.ts +++ b/src/ipc/utils/lock_utils.ts @@ -39,7 +39,7 @@ export async function withLock( } // Acquire a new lock - const { release, promise } = acquireLock(lockId); + const { release } = acquireLock(lockId); try { const result = await fn(); diff --git a/src/lib/chat.ts b/src/lib/chat.ts index b8de4b2..9c670bc 100644 --- a/src/lib/chat.ts +++ b/src/lib/chat.ts @@ -1,4 +1,3 @@ -import type { Message } from "ai"; import { IpcClient } from "../ipc/ipc_client"; import type { ChatSummary } from "./schemas"; import type { CreateAppParams, CreateAppResult } from "../ipc/ipc_types"; diff --git a/src/lib/toast.ts b/src/lib/toast.ts index f0f5dc9..b20aba9 100644 --- a/src/lib/toast.ts +++ b/src/lib/toast.ts @@ -53,7 +53,7 @@ export const showLoading = ( ) => { return toast.promise(promise, { loading: loadingMessage, - success: (data) => successMessage || "Operation completed successfully", + success: () => successMessage || "Operation completed successfully", error: (err) => errorMessage || `Error: ${err.message || "Unknown error"}`, }); }; diff --git a/src/main.ts b/src/main.ts index 646e006..e5da056 100644 --- a/src/main.ts +++ b/src/main.ts @@ -129,7 +129,7 @@ const gotTheLock = app.requestSingleInstanceLock(); if (!gotTheLock) { app.quit(); } else { - app.on("second-instance", (event, commandLine, workingDirectory) => { + app.on("second-instance", (_event, commandLine, _workingDirectory) => { // Someone tried to run a second instance, we should focus our window. if (mainWindow) { if (mainWindow.isMinimized()) mainWindow.restore(); diff --git a/src/pages/app-details.tsx b/src/pages/app-details.tsx index a6f950f..418dcd3 100644 --- a/src/pages/app-details.tsx +++ b/src/pages/app-details.tsx @@ -3,15 +3,13 @@ import { useAtom, useAtomValue } from "jotai"; import { appBasePathAtom, appsListAtom } from "@/atoms/appAtoms"; import { IpcClient } from "@/ipc/ipc_client"; import { useLoadApps } from "@/hooks/useLoadApps"; -import { useState, useEffect } from "react"; +import { useState } from "react"; import { Button } from "@/components/ui/button"; import { ArrowLeft, MoreVertical, - ArrowRight, MessageCircle, Pencil, - Github, Folder, } from "lucide-react"; import { @@ -30,7 +28,6 @@ import { } from "@/components/ui/dialog"; import { GitHubConnector } from "@/components/GitHubConnector"; import { SupabaseConnector } from "@/components/SupabaseConnector"; -import { useSettings } from "@/hooks/useSettings"; export default function AppDetailsPage() { const navigate = useNavigate(); @@ -50,7 +47,7 @@ export default function AppDetailsPage() { const [newFolderName, setNewFolderName] = useState(""); const [isRenamingFolder, setIsRenamingFolder] = useState(false); const appBasePath = useAtomValue(appBasePathAtom); - const { settings } = useSettings(); + // Get the appId from search params and find the corresponding app const appId = search.appId ? Number(search.appId) : null; const selectedApp = appId ? appsList.find((app) => app.id === appId) : null; diff --git a/src/pages/settings.tsx b/src/pages/settings.tsx index 06f34ca..29336e0 100644 --- a/src/pages/settings.tsx +++ b/src/pages/settings.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from "react"; +import { useState } from "react"; import { useTheme } from "../contexts/ThemeContext"; import { ProviderSettingsGrid } from "@/components/ProviderSettings"; import ConfirmationDialog from "@/components/ConfirmationDialog"; @@ -113,7 +113,7 @@ export default function SettingsPage() {
- +
diff --git a/src/paths/paths.ts b/src/paths/paths.ts index 6f71cc4..8e03883 100644 --- a/src/paths/paths.ts +++ b/src/paths/paths.ts @@ -33,7 +33,7 @@ export function getElectron(): typeof import("electron") | undefined { if (process.versions.electron) { electron = require("electron"); } - } catch (e) { + } catch { // Not in Electron environment } return electron; diff --git a/src/supabase_admin/supabase_management_client.ts b/src/supabase_admin/supabase_management_client.ts index 523725a..995739b 100644 --- a/src/supabase_admin/supabase_management_client.ts +++ b/src/supabase_admin/supabase_management_client.ts @@ -226,7 +226,7 @@ async function safeParseErrorResponseBody( ) { return { message: body.message }; } - } catch (error) { + } catch { return; } } diff --git a/src/utils/codebase.ts b/src/utils/codebase.ts index cab2d5f..e7bf1e0 100644 --- a/src/utils/codebase.ts +++ b/src/utils/codebase.ts @@ -70,7 +70,7 @@ async function isGitIgnored( gitIgnoreMtimes.set(rootGitIgnorePath, stats.mtimeMs); shouldClearCache = true; } - } catch (error) { + } catch { // Root .gitignore might not exist, which is fine } @@ -86,7 +86,7 @@ async function isGitIgnored( gitIgnoreMtimes.set(gitIgnorePath, stats.mtimeMs); shouldClearCache = true; } - } catch (error) { + } catch { // This directory might not have a .gitignore, which is fine } } @@ -324,41 +324,3 @@ async function sortFilesByModificationTime(files: string[]): Promise { // Sort by modification time (oldest first) return fileStats.sort((a, b) => a.mtime - b.mtime).map((item) => item.file); } - -/** - * Sort files by their importance for context - */ -function sortFilesByImportance(files: string[], baseDir: string): string[] { - // Define patterns for important files - const highPriorityPatterns = [ - new RegExp(`(^|/)${ALWAYS_INCLUDE_FILES[0]}$`), - /tsconfig\.json$/, - /README\.md$/, - /index\.(ts|js)x?$/, - /main\.(ts|js)x?$/, - /app\.(ts|js)x?$/, - ]; - - // Custom sorting function - return [...files].sort((a, b) => { - const relativeA = path.relative(baseDir, a); - const relativeB = path.relative(baseDir, b); - - // Check if file A matches any high priority pattern - const aIsHighPriority = highPriorityPatterns.some((pattern) => - pattern.test(relativeA), - ); - - // Check if file B matches any high priority pattern - const bIsHighPriority = highPriorityPatterns.some((pattern) => - pattern.test(relativeB), - ); - - // Sort by priority first - if (aIsHighPriority && !bIsHighPriority) return -1; - if (!aIsHighPriority && bIsHighPriority) return 1; - - // If both are same priority, sort alphabetically - return relativeA.localeCompare(relativeB); - }); -}