Skip to content

Commit 53d06ec

Browse files
committed
Fix all net-new lint issues: remove explicit any, fix exhaustive-deps
Replace 46 new no-explicit-any violations with proper types (BoardTask, Session, Message, Record<string, unknown>) across API routes, queue, session-tools, task components, agent-registry, and store. Add missing loadAgents dependency in agent-chat-list useEffect. Baseline drops from 561 → 511.
1 parent 4553ea2 commit 53d06ec

File tree

13 files changed

+52
-129
lines changed

13 files changed

+52
-129
lines changed

.eslint-baseline.json

Lines changed: 5 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"version": 1,
3-
"generatedAt": "2026-02-24T19:52:36.427Z",
4-
"totalIssues": 561,
5-
"uniqueIssues": 172,
3+
"generatedAt": "2026-02-24T19:57:17.848Z",
4+
"totalIssues": 511,
5+
"uniqueIssues": 161,
66
"issues": [
77
{
88
"filePath": "bin/swarmclaw.js",
@@ -11,13 +11,6 @@
1111
"message": "A `require()` style import is forbidden.",
1212
"count": 2
1313
},
14-
{
15-
"filePath": "src/app/api/agents/[id]/thread/route.ts",
16-
"ruleId": "@typescript-eslint/no-explicit-any",
17-
"severity": 2,
18-
"message": "Unexpected any. Specify a different type.",
19-
"count": 3
20-
},
2114
{
2215
"filePath": "src/app/api/agents/generate/route.ts",
2316
"ruleId": "@typescript-eslint/no-explicit-any",
@@ -81,27 +74,13 @@
8174
"message": "Unexpected any. Specify a different type.",
8275
"count": 2
8376
},
84-
{
85-
"filePath": "src/app/api/preview-server/route.ts",
86-
"ruleId": "@typescript-eslint/no-explicit-any",
87-
"severity": 2,
88-
"message": "Unexpected any. Specify a different type.",
89-
"count": 2
90-
},
9177
{
9278
"filePath": "src/app/api/providers/ollama/route.ts",
9379
"ruleId": "@typescript-eslint/no-explicit-any",
9480
"severity": 2,
9581
"message": "Unexpected any. Specify a different type.",
9682
"count": 2
9783
},
98-
{
99-
"filePath": "src/app/api/schedules/[id]/run/route.ts",
100-
"ruleId": "@typescript-eslint/no-explicit-any",
101-
"severity": 2,
102-
"message": "Unexpected any. Specify a different type.",
103-
"count": 1
104-
},
10584
{
10685
"filePath": "src/app/api/secrets/[id]/route.ts",
10786
"ruleId": "@typescript-eslint/no-unused-vars",
@@ -151,13 +130,6 @@
151130
"message": "Unexpected any. Specify a different type.",
152131
"count": 2
153132
},
154-
{
155-
"filePath": "src/app/api/tasks/route.ts",
156-
"ruleId": "@typescript-eslint/no-explicit-any",
157-
"severity": 2,
158-
"message": "Unexpected any. Specify a different type.",
159-
"count": 2
160-
},
161133
{
162134
"filePath": "src/app/api/webhooks/[id]/route.ts",
163135
"ruleId": "@typescript-eslint/no-explicit-any",
@@ -214,13 +186,6 @@
214186
"message": "A `require()` style import is forbidden.",
215187
"count": 6
216188
},
217-
{
218-
"filePath": "src/components/agents/agent-chat-list.tsx",
219-
"ruleId": "react-hooks/exhaustive-deps",
220-
"severity": 1,
221-
"message": "React Hook useEffect has a missing dependency: 'loadAgents'. Either include it or remove the dependency array.",
222-
"count": 1
223-
},
224189
{
225190
"filePath": "src/components/agents/agent-list.tsx",
226191
"ruleId": "react-hooks/exhaustive-deps",
@@ -746,13 +711,6 @@
746711
"message": "'BoardTaskStatus' is defined but never used.",
747712
"count": 1
748713
},
749-
{
750-
"filePath": "src/components/tasks/task-card.tsx",
751-
"ruleId": "@typescript-eslint/no-explicit-any",
752-
"severity": 2,
753-
"message": "Unexpected any. Specify a different type.",
754-
"count": 7
755-
},
756714
{
757715
"filePath": "src/components/tasks/task-list.tsx",
758716
"ruleId": "@typescript-eslint/no-unused-vars",
@@ -774,13 +732,6 @@
774732
"message": "Using `<img>` could result in slower LCP and higher bandwidth. Consider using `<Image />` from `next/image` or a custom image loader to automatically optimize images. This may incur additional usage or cost from your provider. See: https://nextjs.org/docs/messages/no-img-element",
775733
"count": 1
776734
},
777-
{
778-
"filePath": "src/components/tasks/task-sheet.tsx",
779-
"ruleId": "@typescript-eslint/no-unused-vars",
780-
"severity": 1,
781-
"message": "'BoardTask' is defined but never used.",
782-
"count": 1
783-
},
784735
{
785736
"filePath": "src/components/tasks/task-sheet.tsx",
786737
"ruleId": "react-hooks/exhaustive-deps",
@@ -795,13 +746,6 @@
795746
"message": "React Hook useEffect has missing dependencies: 'editing', 'loadAgents', 'loadSettings', and 'orchestrators'. Either include them or remove the dependency array.",
796747
"count": 1
797748
},
798-
{
799-
"filePath": "src/components/tasks/task-sheet.tsx",
800-
"ruleId": "@typescript-eslint/no-explicit-any",
801-
"severity": 2,
802-
"message": "Unexpected any. Specify a different type.",
803-
"count": 14
804-
},
805749
{
806750
"filePath": "src/components/tasks/task-sheet.tsx",
807751
"ruleId": "react-hooks/set-state-in-effect",
@@ -879,13 +823,6 @@
879823
"message": "Unexpected any. Specify a different type.",
880824
"count": 1
881825
},
882-
{
883-
"filePath": "src/lib/server/agent-registry.ts",
884-
"ruleId": "@typescript-eslint/no-explicit-any",
885-
"severity": 2,
886-
"message": "Unexpected any. Specify a different type.",
887-
"count": 1
888-
},
889826
{
890827
"filePath": "src/lib/server/build-llm.ts",
891828
"ruleId": "@typescript-eslint/no-unused-vars",
@@ -1103,13 +1040,6 @@
11031040
"message": "Unexpected any. Specify a different type.",
11041041
"count": 2
11051042
},
1106-
{
1107-
"filePath": "src/lib/server/queue.ts",
1108-
"ruleId": "@typescript-eslint/no-explicit-any",
1109-
"severity": 2,
1110-
"message": "Unexpected any. Specify a different type.",
1111-
"count": 14
1112-
},
11131043
{
11141044
"filePath": "src/lib/server/scheduler.ts",
11151045
"ruleId": "@typescript-eslint/no-explicit-any",
@@ -1171,7 +1101,7 @@
11711101
"ruleId": "@typescript-eslint/no-explicit-any",
11721102
"severity": 2,
11731103
"message": "Unexpected any. Specify a different type.",
1174-
"count": 92
1104+
"count": 90
11751105
},
11761106
{
11771107
"filePath": "src/lib/server/session-tools.ts",
@@ -1185,7 +1115,7 @@
11851115
"ruleId": "@typescript-eslint/no-explicit-any",
11861116
"severity": 2,
11871117
"message": "Unexpected any. Specify a different type.",
1188-
"count": 43
1118+
"count": 42
11891119
},
11901120
{
11911121
"filePath": "src/lib/server/stream-agent-chat.ts",
@@ -1194,13 +1124,6 @@
11941124
"message": "Unexpected any. Specify a different type.",
11951125
"count": 4
11961126
},
1197-
{
1198-
"filePath": "src/stores/use-app-store.ts",
1199-
"ruleId": "@typescript-eslint/no-explicit-any",
1200-
"severity": 2,
1201-
"message": "Unexpected any. Specify a different type.",
1202-
"count": 1
1203-
},
12041127
{
12051128
"filePath": "src/types/index.ts",
12061129
"ruleId": "@typescript-eslint/no-explicit-any",

src/app/api/agents/[id]/thread/route.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ export async function POST(req: Request, { params }: { params: Promise<{ id: str
2121

2222
// Check if an existing session is already linked to this agent as a thread
2323
const existing = Object.values(sessions).find(
24-
(s: any) => s.name === `agent-thread:${agentId}` && s.user === user
24+
(s: Record<string, unknown>) => s.name === `agent-thread:${agentId}` && s.user === user
2525
)
2626
if (existing) {
27-
agent.threadSessionId = (existing as any).id
27+
agent.threadSessionId = (existing as Record<string, unknown>).id as string
2828
agent.updatedAt = Date.now()
2929
saveAgents(agents)
3030
return NextResponse.json(existing)
@@ -55,7 +55,7 @@ export async function POST(req: Request, { params }: { params: Promise<{ id: str
5555
heartbeatIntervalSec: agent.heartbeatIntervalSec || null,
5656
}
5757

58-
sessions[sessionId] = session as any
58+
sessions[sessionId] = session as Record<string, unknown>
5959
saveSessions(sessions)
6060

6161
agent.threadSessionId = sessionId

src/app/api/preview-server/route.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ interface PreviewServer {
3535
}
3636

3737
const globalKey = '__swarmclaw_preview_servers__' as const
38-
const servers: Map<string, PreviewServer> = (globalThis as any)[globalKey]
39-
?? ((globalThis as any)[globalKey] = new Map<string, PreviewServer>())
38+
const servers: Map<string, PreviewServer> = (globalThis as unknown as Record<string, unknown>)[globalKey] as Map<string, PreviewServer>
39+
?? ((globalThis as unknown as Record<string, unknown>)[globalKey] = new Map<string, PreviewServer>())
4040

4141
// ---------------------------------------------------------------------------
4242
// Helpers

src/app/api/schedules/[id]/run/route.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@ export async function POST(_req: Request, { params }: { params: Promise<{ id: st
4343

4444
if (existingTask && existingTask.status !== 'queued' && existingTask.status !== 'running') {
4545
taskId = existingTaskId
46-
const prev = existingTask as any
47-
prev.totalRuns = (prev.totalRuns || 0) + 1
48-
if (existingTask.status === 'completed') prev.totalCompleted = (prev.totalCompleted || 0) + 1
49-
if (existingTask.status === 'failed') prev.totalFailed = (prev.totalFailed || 0) + 1
46+
const prev = existingTask as Record<string, unknown>
47+
prev.totalRuns = ((prev.totalRuns as number) || 0) + 1
48+
if (existingTask.status === 'completed') prev.totalCompleted = ((prev.totalCompleted as number) || 0) + 1
49+
if (existingTask.status === 'failed') prev.totalFailed = ((prev.totalFailed as number) || 0) + 1
5050

5151
existingTask.status = 'backlog'
5252
existingTask.title = `[Sched] ${schedule.name} (run #${schedule.runNumber})`

src/app/api/tasks/route.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export async function DELETE(req: Request) {
3838
for (const [id, task] of Object.entries(tasks)) {
3939
const shouldRemove =
4040
filter === 'all' ||
41-
(filter === 'schedule' && (task as any).sourceType === 'schedule') ||
41+
(filter === 'schedule' && (task as Record<string, unknown>).sourceType === 'schedule') ||
4242
(!filter && task.status === 'archived')
4343
if (shouldRemove) {
4444
removed++
@@ -52,7 +52,7 @@ export async function DELETE(req: Request) {
5252
for (const [id, task] of Object.entries(tasks)) {
5353
const shouldRemove =
5454
filter === 'all' ||
55-
(filter === 'schedule' && (task as any).sourceType === 'schedule') ||
55+
(filter === 'schedule' && (task as Record<string, unknown>).sourceType === 'schedule') ||
5656
(!filter && task.status === 'archived')
5757
if (shouldRemove) deleteTask(id)
5858
}

src/components/agents/agent-chat-list.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export function AgentChatList({ inSidebar, onSelect }: Props) {
2222
const tasks = useAppStore((s) => s.tasks)
2323
const [search, setSearch] = useState('')
2424

25-
useEffect(() => { loadAgents() }, [])
25+
useEffect(() => { loadAgents() }, [loadAgents])
2626

2727
// Build agent list sorted by last activity in their thread session
2828
const sortedAgents = useMemo(() => {

src/components/tasks/task-card.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,19 +88,19 @@ export function TaskCard({ task }: { task: BoardTask }) {
8888
)}
8989

9090
{/* Schedule run stats */}
91-
{(task as any).sourceType === 'schedule' && (
91+
{task.sourceType === 'schedule' && (
9292
<div className="flex items-center gap-2 mb-3 text-[11px] text-text-3">
9393
<span className="px-1.5 py-0.5 rounded-[5px] bg-purple-500/10 text-purple-400 font-600">
9494
Run #{task.runNumber || 1}
9595
</span>
96-
{((task as any).totalRuns ?? 0) > 0 && (
96+
{(task.totalRuns ?? 0) > 0 && (
9797
<>
98-
<span title="Total runs">{(task as any).totalRuns} runs</span>
99-
{((task as any).totalCompleted ?? 0) > 0 && (
100-
<span className="text-green-400" title="Completed">{(task as any).totalCompleted} ok</span>
98+
<span title="Total runs">{task.totalRuns} runs</span>
99+
{(task.totalCompleted ?? 0) > 0 && (
100+
<span className="text-green-400" title="Completed">{task.totalCompleted} ok</span>
101101
)}
102-
{((task as any).totalFailed ?? 0) > 0 && (
103-
<span className="text-red-400" title="Failed">{(task as any).totalFailed} fail</span>
102+
{(task.totalFailed ?? 0) > 0 && (
103+
<span className="text-red-400" title="Failed">{task.totalFailed} fail</span>
104104
)}
105105
</>
106106
)}

src/components/tasks/task-sheet.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ export function TaskSheet() {
107107
}
108108

109109
const handleSave = async () => {
110-
const payload = { title: title.trim() || 'Untitled Task', description, agentId, images, cwd: cwd || undefined, file: file || undefined } as any
110+
const payload: Partial<BoardTask> & { title: string; description: string; agentId: string } = { title: title.trim() || 'Untitled Task', description, agentId, images, cwd: cwd || undefined, file: file || undefined }
111111
if (editing) {
112112
await updateTask(editing.id, payload)
113113
} else {
@@ -167,7 +167,7 @@ export function TaskSheet() {
167167
createdAt: Date.now(),
168168
}
169169
// Use atomic append to avoid race conditions with queue-added comments
170-
await updateTask(editing.id, { appendComment: c } as any)
170+
await updateTask(editing.id, { appendComment: c } as Partial<BoardTask> & { appendComment: TaskComment })
171171
await loadTasks()
172172
setCommentText('')
173173
}
@@ -301,29 +301,29 @@ export function TaskSheet() {
301301
</div>
302302
)}
303303

304-
{editing && ((editing as any).claudeResumeId || (editing as any).codexResumeId || (editing as any).opencodeResumeId || editing.cliResumeId) && (
304+
{editing && (editing.claudeResumeId || editing.codexResumeId || editing.opencodeResumeId || editing.cliResumeId) && (
305305
<div className="mb-8">
306306
<label className="block font-display text-[12px] font-600 text-text-2 uppercase tracking-[0.08em] mb-3">CLI Sessions</label>
307307
<div className="flex flex-wrap gap-2">
308-
{(editing as any).claudeResumeId && (
308+
{editing.claudeResumeId && (
309309
<div className="flex items-center gap-2 px-3 py-2 rounded-[10px] border border-white/[0.06] bg-surface">
310310
<span className="text-[11px] font-600 text-amber-400">Claude</span>
311-
<code className="text-[11px] text-text-3 font-mono">{(editing as any).claudeResumeId}</code>
311+
<code className="text-[11px] text-text-3 font-mono">{editing.claudeResumeId}</code>
312312
</div>
313313
)}
314-
{(editing as any).codexResumeId && (
314+
{editing.codexResumeId && (
315315
<div className="flex items-center gap-2 px-3 py-2 rounded-[10px] border border-white/[0.06] bg-surface">
316316
<span className="text-[11px] font-600 text-emerald-400">Codex</span>
317-
<code className="text-[11px] text-text-3 font-mono">{(editing as any).codexResumeId}</code>
317+
<code className="text-[11px] text-text-3 font-mono">{editing.codexResumeId}</code>
318318
</div>
319319
)}
320-
{(editing as any).opencodeResumeId && (
320+
{editing.opencodeResumeId && (
321321
<div className="flex items-center gap-2 px-3 py-2 rounded-[10px] border border-white/[0.06] bg-surface">
322322
<span className="text-[11px] font-600 text-sky-400">OpenCode</span>
323-
<code className="text-[11px] text-text-3 font-mono">{(editing as any).opencodeResumeId}</code>
323+
<code className="text-[11px] text-text-3 font-mono">{editing.opencodeResumeId}</code>
324324
</div>
325325
)}
326-
{!((editing as any).claudeResumeId || (editing as any).codexResumeId || (editing as any).opencodeResumeId) && editing.cliResumeId && (
326+
{!(editing.claudeResumeId || editing.codexResumeId || editing.opencodeResumeId) && editing.cliResumeId && (
327327
<div className="flex items-center gap-2 px-3 py-2 rounded-[10px] border border-white/[0.06] bg-surface">
328328
<span className="text-[11px] font-600 text-text-2">{editing.cliProvider || 'CLI'}</span>
329329
<code className="text-[11px] text-text-3 font-mono">{editing.cliResumeId}</code>

src/lib/server/agent-registry.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ export function getAgentDirectory(excludeId?: string): AgentDirectoryEntry[] {
2525

2626
// Find active sessions per agent
2727
const activeSessions = new Set<string>()
28-
for (const session of Object.values(sessions) as any[]) {
28+
for (const session of Object.values(sessions) as Record<string, unknown>[]) {
2929
if (session.active && session.agentId) {
30-
activeSessions.add(session.agentId)
30+
activeSessions.add(session.agentId as string)
3131
}
3232
}
3333

0 commit comments

Comments
 (0)