refactor: split DevTools/Settings god files, fix async handlers, delete dead code#135
refactor: split DevTools/Settings god files, fix async handlers, delete dead code#135
Conversation
There was a problem hiding this comment.
Pull request overview
Refactors oversized DevTools/Settings UI “god files” into smaller components while cleaning up and hardening parts of the CoS backend (event wiring, socket handler error handling, and removal of dead compatibility code).
Changes:
- Split
client/src/pages/DevTools.jsxinto individual page modules and splitclient/src/pages/Settings.jsxinto tab components. - Improve backend robustness by handling async errors in CoS event listeners / socket handlers and removing dead compatibility exports.
- Normalize CoS event emitter imports (
cosEvents.js) and simplifyspawnViaRunnerinvocation via an options object.
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| server/services/taskSchedule.js | Removes backward-compat delegate exports (dead code cleanup). |
| server/services/socket.js | Adds try/catch around several async socket handlers. |
| server/services/memoryDB.js | Switches cosEvents import to cosEvents.js to avoid circular deps. |
| server/services/memory.test.js | Updates mocks/imports to match cosEvents.js usage. |
| server/services/memory.js | Switches cosEvents import to cosEvents.js. |
| server/services/cos.js | Unifies improvement task description helpers; wraps async event listeners to avoid unhandled rejections. |
| server/services/agentLifecycle.js | Converts spawnViaRunner call/signature to an options object. |
| client/src/pages/DevTools.jsx | Converts DevTools into a barrel re-export file. |
| client/src/pages/HistoryPage.jsx | New extracted DevTools History page module. |
| client/src/pages/RunsHistoryPage.jsx | New extracted AI runs history page module. |
| client/src/pages/RunnerPage.jsx | New extracted DevTools runner page module. |
| client/src/pages/ProcessesPage.jsx | New extracted PM2 processes page module. |
| client/src/pages/UsagePage.jsx | New extracted usage metrics page module. |
| client/src/pages/AgentsPage.jsx | New extracted agents/process list page module. |
| client/src/pages/Settings.jsx | Replaces monolith Settings page with a tab router that renders extracted tab components. |
| client/src/components/settings/BackupTab.jsx | Extracted Settings “Backup” tab UI/logic. |
| client/src/components/settings/DatabaseTab.jsx | Extracted Settings “Database” tab UI/logic. |
| client/src/components/settings/TelegramTab.jsx | Extracted Settings “Telegram” tab UI/logic. |
| client/src/components/settings/GeneralTab.jsx | Extracted Settings “General” tab UI/logic. |
| client/src/components/settings/ImageGenTab.jsx | Extracted Settings “Image Gen” tab UI/logic. |
Comments suppressed due to low confidence (1)
server/services/socket.js:81
- Inside the
standardize:starthandler, the code withintry { ... }is not indented consistently with the surrounding file. This makes the try/catch scope harder to visually verify and may fail linting/style checks. Please align indentation for the block.
socket.on('standardize:start', async (rawData) => {
try {
const data = validateSocketData(standardizeStartSchema, rawData, socket, 'standardize:start');
if (!data) return;
const { repoPath, providerId } = data;
console.log(`🔧 Starting PM2 standardization: ${repoPath}`);
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…ulls, wire expand buttons - socket.js: emit standardize:complete, app:update:error/complete, app:standardize:error in outer catch blocks so clients don't get stuck in loading state - socket.js: fix indentation inside standardize:start try block - UsagePage.jsx: guard formatNumber against null/undefined, use nullish coalescing for tokens/cost - RunsHistoryPage.jsx: wire onClick and aria-label on expand/collapse button - HistoryPage.jsx: wire onClick on expand/collapse button (with stopPropagation) - RunnerPage.jsx: add aria-label to dismiss context and remove screenshot buttons, add group-focus-within:opacity-100 for keyboard accessibility
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 20 out of 20 changed files in this pull request and generated 9 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- socket.js: use err?.message ?? String(err) in all catch blocks to handle non-Error rejection values; emit detect:complete on detect:start failure - cos.js: use err?.message ?? String(err) in event listener catch handlers
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 20 out of 20 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…ride on resume - UsagePage: clamp maxActivity to >= 1 to prevent NaN bar heights - UsagePage: compute maxHour once outside map loop (O(n) vs O(n^2)) - RunnerPage: use functional setState for workspace selection to avoid overriding continuation context workspace with default
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 20 out of 20 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Apply the same error handling pattern as other socket handlers: outer try/catch with safe error extraction and operation-specific error event emission.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 20 out of 20 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 20 out of 20 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…outer for state clear - socket.js: emit error:recover:error instead of generic error:server - memory.test.js: remove redundant cos.js mock (memory.js imports from cosEvents.js) - RunnerPage.jsx: use navigate() with replace instead of window.history.replaceState to preserve React Router internal state
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 20 out of 20 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- RunnerPage: store continuation workspace in ref to survive location.state clearing; remove stale location.state read from apps initializer - RunsHistoryPage: catch deleteRun failures to prevent optimistic UI update - HistoryPage: catch clearHistory/deleteHistoryEntry failures gracefully
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 20 out of 20 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
client/src/pages/RunsHistoryPage.jsx
Outdated
| const result = await api.deleteFailedRuns().catch(() => null); | ||
| if (result) { | ||
| setRuns(prev => prev.filter(r => r.success !== false)); |
There was a problem hiding this comment.
deleteFailedRuns() may also return null for HTTP 204 via request(). Because the code only updates local state when result is truthy, the list may not refresh after a successful delete that returns no content. Consider checking for result !== null (or simply awaiting the call and updating state on success).
| const result = await api.deleteFailedRuns().catch(() => null); | |
| if (result) { | |
| setRuns(prev => prev.filter(r => r.success !== false)); | |
| try { | |
| await api.deleteFailedRuns(); | |
| setRuns(prev => prev.filter(r => r.success !== false)); | |
| } catch { | |
| // Leave local state unchanged if the delete request fails. |
client/src/pages/RunnerPage.jsx
Outdated
| setSelectedProvider(active.id); | ||
| setSelectedModel(active.defaultModel || ''); |
There was a problem hiding this comment.
When navigating with continueFrom, the first effect sets selectedProvider/selectedModel from the previous run, but the initialization effect later unconditionally overwrites them with the active/default provider/model (setSelectedProvider(active.id) / setSelectedModel(active.defaultModel)). This makes “resume/continue” pick the wrong provider/model. Preserve existing selections (e.g., only set defaults when state is still empty, or gate on continueContext).
| setSelectedProvider(active.id); | |
| setSelectedModel(active.defaultModel || ''); | |
| setSelectedProvider(prev => prev || active.id); | |
| setSelectedModel(prev => prev || active.defaultModel || ''); |
- RunsHistoryPage: use then/catch boolean pattern for deleteFailedRuns to handle HTTP 204 (null result) correctly - RunnerPage: use functional setState for provider/model to avoid overwriting continuation context selections with defaults
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 20 out of 20 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Better Audit — Architecture & SOLID
Summary
7 findings addressed across 20 files (11 new files created from splits).
Changes
Files Modified
server/services/{cos,taskSchedule,socket,agentLifecycle,memory,memoryDB}.js, client/src/pages/{DevTools,Settings}.jsx + 11 new extracted files
Merge Order
Independent — can be merged in any order