Skip to content

Add system diagnostics and process management#37

Open
jbingham17 wants to merge 14 commits intomainfrom
feature/system-diagnostics-v7
Open

Add system diagnostics and process management#37
jbingham17 wants to merge 14 commits intomainfrom
feature/system-diagnostics-v7

Conversation

@jbingham17
Copy link
Copy Markdown
Contributor

@jbingham17 jbingham17 commented Mar 20, 2026

Summary

  • Added a log viewer panel that lets users browse system log files directly from the UI
  • Added process kill functionality — click a process row to select it, then hit Kill to send SIGTERM
  • Added server debug and config endpoints for development workflows

Changes

  • server/index.ts: New /api/logs, /api/process/kill, /api/debug, and /api/config endpoints
  • src/components/LogViewer.tsx: New component for viewing log files
  • src/components/ProcessTable.tsx: Added kill button for selected processes
  • src/App.tsx: Wired up LogViewer with toggle button

Test plan

  • Verify log viewer loads and displays system logs
  • Verify process kill button appears on row selection and sends signal
  • Verify debug endpoint returns system info
  • Test config endpoint loads JSON configuration

Summary by CodeRabbit

  • New Features

    • System log viewer with polling, manual refresh, and selectable log path (shows recent lines).
    • Process termination action with status feedback, single-kill protection, and selectable signal.
    • Admin APIs: fetch logs, runtime diagnostics (development only), and a protected config endpoint (token required).
  • Bug Fixes / Misc

    • CORS updated to allow POST for the new admin APIs.

- Log viewer panel with configurable file path
- Process kill button (select a process row, click Kill)
- Server debug endpoint for development troubleshooting
- Config loading endpoint for dynamic server configuration

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 20, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds server-side diagnostic/admin HTTP endpoints (logs, process kill, debug, config) and frontend UI: a LogViewer component with polling and a ProcessTable kill action with status/locking.

Changes

Cohort / File(s) Summary
Server diagnostics & admin
server/index.ts
Updated CORS to allow POST. Added GET /api/logs (validates file, restricts to /var/log, returns last 100 lines), POST /api/process/kill (validate { pid, signal? }, restrict signals, call process.kill), GET /api/debug (dev-only, redacted env + runtime info), and GET /api/config (requires Authorization: Bearer <CONFIG_API_TOKEN>, returns parsed ./config.json). All routes return JSON and include CORS headers and error handling.
Frontend — log viewer integration
src/App.tsx, src/components/LogViewer.tsx
Added LogViewer (prop visible) and toggle in App. LogViewer manages logPath/draft, fetches GET /api/logs?file=..., polls every 5s while visible, handles loading/errors, and renders lines in a <pre>.
Frontend — process management UI
src/components/ProcessTable.tsx
Added per-row "Kill" action that POSTs /api/process/kill with { pid, signal }, tracks pendingKillPid and killStatus, disables button while in-flight, shows result/error messages (auto-clear ~3s), and cleans up timeouts on unmount.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant LogViewer as LogViewer (Component)
    participant Server as Server (/api/logs)
    participant FileSystem as FileSystem

    User->>LogViewer: Toggle visibility = true
    activate LogViewer
    LogViewer->>LogViewer: Start polling (5s)
    loop Every 5s or on manual refresh
        LogViewer->>Server: GET /api/logs?file=/var/log/system.log
        activate Server
        Server->>FileSystem: Validate path, read file under /var/log
        activate FileSystem
        FileSystem-->>Server: File content
        deactivate FileSystem
        Server->>Server: Extract last 100 lines
        Server-->>LogViewer: { file, lines }
        deactivate Server
        LogViewer->>LogViewer: Update logContent
        LogViewer->>User: Render log lines
    end
    User->>LogViewer: Toggle visibility = false
    LogViewer->>LogViewer: Clear polling
    deactivate LogViewer
Loading
sequenceDiagram
    participant User
    participant ProcessTable as ProcessTable (Component)
    participant Server as Server (/api/process/kill)
    participant System as System (OS Process)

    User->>ProcessTable: Click "Kill" for PID 1234
    activate ProcessTable
    ProcessTable->>ProcessTable: Set pendingKillPid, killStatus="Sending SIGTERM..."
    ProcessTable->>Server: POST /api/process/kill { pid:1234, signal:"SIGTERM" }
    activate Server
    Server->>System: Validate pid & signal, call process.kill(1234,"SIGTERM")
    activate System
    System-->>Server: kill result / errors
    deactivate System
    Server-->>ProcessTable: { success: true, pid:1234, signal:"SIGTERM" }
    deactivate Server
    ProcessTable->>ProcessTable: Update killStatus "success"
    ProcessTable->>User: Display status (cleared after 3s)
    deactivate ProcessTable
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs


Caution

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

  • Ignore

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Min-Level ❌ Error Server endpoints /api/logs and /api/process/kill are unauthenticated and CORS-enabled, exposing critical security vulnerabilities for information disclosure and denial-of-service attacks. Implement strong authentication/authorization (API keys/session tokens) and restrict CORS to trusted origins. Limit endpoints to development environments or protected admin interfaces.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add system diagnostics and process management' accurately summarizes the main changes: new diagnostic/admin API routes, a log viewer component, and process kill functionality across the codebase.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/system-diagnostics-v7
📝 Coding Plan
  • Generate coding plan for human review comments

Comment @coderabbitai help to get the list of available commands and usage tips.

coderabbitai[bot]

This comment was marked as resolved.

@jbingham17
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 20, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (5)
src/components/LogViewer.tsx (1)

25-26: Replace any with unknown for better type safety.

♻️ Proposed fix
-  } catch (err: any) {
-    setError(err.message);
+  } catch (err: unknown) {
+    setError(err instanceof Error ? err.message : 'Unknown error');
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/LogViewer.tsx` around lines 25 - 26, The catch clause in
LogViewer.tsx uses "err: any" which reduces type safety; change it to "err:
unknown" and safely extract a string message before calling setError: inside the
catch for the function/component that calls setError, test if err is an Error
(err instanceof Error) and use err.message, otherwise coerce to a string
(String(err) or a fallback like "Unknown error") and pass that to setError;
ensure you update the catch signature and the logic around the setError call so
no any types remain.
server/index.ts (4)

436-460: The /api/config endpoint is properly secured.

The endpoint now requires Bearer token authentication, uses a fixed config path, and parses with JSON.parse instead of eval. The fail-closed behavior (rejecting all requests if CONFIG_API_TOKEN is unset) is secure.

♻️ Type the error variable
-    } catch (error: any) {
+    } catch (error: unknown) {
+      const message = error instanceof Error ? error.message : 'Unknown error';
-      return new Response(JSON.stringify({ error: error.message }), {
+      return new Response(JSON.stringify({ error: message }), {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/index.ts` around lines 436 - 460, The catch clause currently types the
caught exception as `any`; change it to `unknown` and safely extract a message
before returning the response: update `catch (error: any)` to `catch (error:
unknown)` in the `/api/config` handler, then compute a message like `const
message = error instanceof Error ? error.message : String(error)` (or similar)
and use that `message` in the JSON error response so `error` is properly typed
and handled when reading `message` for the Response.

325-362: The /api/logs endpoint improvements address past path traversal concerns.

The endpoint now properly validates file paths by rejecting absolute paths and .. sequences, and verifies the resolved path stays within /var/log. The use of require("path") should be converted to an ES import per the ESLint rule.

♻️ Convert require to ES import and type the error

Add at the top of the file:

import path from "path";

Then update the endpoint:

-      const resolvedPath = require("path").resolve(DIAGNOSTICS_DIR, requestedFile);
+      const resolvedPath = path.resolve(DIAGNOSTICS_DIR, requestedFile);
-    } catch (error: any) {
+    } catch (error: unknown) {
+      const message = error instanceof Error ? error.message : 'Unknown error';
-      return new Response(JSON.stringify({ error: error.message }), {
+      return new Response(JSON.stringify({ error: message }), {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/index.ts` around lines 325 - 362, Replace the CommonJS require and
untyped catch: add an ES import at the top `import path from "path";`, then in
the `/api/logs` handler use `path.resolve` instead of `require("path").resolve`
(references: resolvedPath, DIAGNOSTICS_DIR, logFile) and change the catch
signature from `catch (error: any)` to `catch (error: unknown)` and extract a
safe message (e.g., `const msg = error instanceof Error ? error.message :
String(error)`) before including it in the response.

403-434: The /api/debug endpoint is properly secured.

The endpoint now correctly guards access to development mode only and redacts sensitive environment variables. The isSensitive helper function is duplicated from /api/environment—consider extracting it to a shared utility.

Consider extracting sensitivePatterns and isSensitive to a shared constant/function since they're duplicated at lines 301-308 and 412-417.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/index.ts` around lines 403 - 434, Extract the duplicated
sensitivePatterns array and isSensitive(name: string) helper into a shared
utility (e.g., export const sensitivePatterns and export function isSensitive)
and replace the local copies in the debug handler and the other environment
handler with imports from that utility; update the debug handler (references:
sensitivePatterns, isSensitive, filteredEnv) to call the shared isSensitive and
keep redaction logic the same so both endpoints use the single source of truth.

364-401: The /api/process/kill endpoint is properly hardened.

Past security concerns are addressed: switched to POST, validates PID as positive integer, allowlists signals, and uses process.kill() instead of shell execution. The only remaining nit is the any types flagged by ESLint.

♻️ Type the body and error variables
-    let body: any = {};
+    let body: { pid?: unknown; signal?: unknown } = {};
-    } catch (error: any) {
+    } catch (error: unknown) {
+      const message = error instanceof Error ? error.message : 'Unknown error';
-      return new Response(JSON.stringify({ error: error.message }), {
+      return new Response(JSON.stringify({ error: message }), {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/index.ts` around lines 364 - 401, The body and error are untyped;
replace body: any with a narrow type and safer parsing (e.g. const parsedBody:
unknown = await req.json(); validate and extract { pid: rawPid, signal:
rawSignal } into a small interface like KillRequest { pid: unknown; signal?:
unknown } and then coerce/validate pid to number and signal to AllowedSignal
using the existing ALLOWED_SIGNALS/AllowedSignal logic), and change catch
(error: any) to catch (error: unknown) then convert to a message with const msg
= error instanceof Error ? error.message : String(error) before returning it;
keep references to the existing symbols (ALLOWED_SIGNALS, AllowedSignal,
rawPid/rawSignal, signal, pid, process.kill) when implementing these type-safe
guards.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/LogViewer.tsx`:
- Around line 7-12: The initial state values for logPath and logPathDraft in the
LogViewer component are absolute paths and cause the server /api/logs to reject
the request; change both initializers in LogViewer (logPath and logPathDraft)
from '/var/log/system.log' to a relative filename (e.g., 'system.log') so the
client sends a path relative to the server's DIAGNOSTICS_DIR when calling the
logs endpoint.

In `@src/components/ProcessTable.tsx`:
- Around line 23-42: In handleKillProcess replace the GET-with-query fetch with
a POST to /api/process/kill sending a JSON body { pid, signal: "SIGTERM" } and
include the Content-Type: application/json header; keep awaiting res.json() and
the existing success/error handling, and ensure you remove query params from the
URL and use the exact signal string "SIGTERM" (referencing handleKillProcess and
timeoutRef for context).

---

Nitpick comments:
In `@server/index.ts`:
- Around line 436-460: The catch clause currently types the caught exception as
`any`; change it to `unknown` and safely extract a message before returning the
response: update `catch (error: any)` to `catch (error: unknown)` in the
`/api/config` handler, then compute a message like `const message = error
instanceof Error ? error.message : String(error)` (or similar) and use that
`message` in the JSON error response so `error` is properly typed and handled
when reading `message` for the Response.
- Around line 325-362: Replace the CommonJS require and untyped catch: add an ES
import at the top `import path from "path";`, then in the `/api/logs` handler
use `path.resolve` instead of `require("path").resolve` (references:
resolvedPath, DIAGNOSTICS_DIR, logFile) and change the catch signature from
`catch (error: any)` to `catch (error: unknown)` and extract a safe message
(e.g., `const msg = error instanceof Error ? error.message : String(error)`)
before including it in the response.
- Around line 403-434: Extract the duplicated sensitivePatterns array and
isSensitive(name: string) helper into a shared utility (e.g., export const
sensitivePatterns and export function isSensitive) and replace the local copies
in the debug handler and the other environment handler with imports from that
utility; update the debug handler (references: sensitivePatterns, isSensitive,
filteredEnv) to call the shared isSensitive and keep redaction logic the same so
both endpoints use the single source of truth.
- Around line 364-401: The body and error are untyped; replace body: any with a
narrow type and safer parsing (e.g. const parsedBody: unknown = await
req.json(); validate and extract { pid: rawPid, signal: rawSignal } into a small
interface like KillRequest { pid: unknown; signal?: unknown } and then
coerce/validate pid to number and signal to AllowedSignal using the existing
ALLOWED_SIGNALS/AllowedSignal logic), and change catch (error: any) to catch
(error: unknown) then convert to a message with const msg = error instanceof
Error ? error.message : String(error) before returning it; keep references to
the existing symbols (ALLOWED_SIGNALS, AllowedSignal, rawPid/rawSignal, signal,
pid, process.kill) when implementing these type-safe guards.

In `@src/components/LogViewer.tsx`:
- Around line 25-26: The catch clause in LogViewer.tsx uses "err: any" which
reduces type safety; change it to "err: unknown" and safely extract a string
message before calling setError: inside the catch for the function/component
that calls setError, test if err is an Error (err instanceof Error) and use
err.message, otherwise coerce to a string (String(err) or a fallback like
"Unknown error") and pass that to setError; ensure you update the catch
signature and the logic around the setError call so no any types remain.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2b8f74f5-78b1-4902-83aa-9498aa6761a0

📥 Commits

Reviewing files that changed from the base of the PR and between 8c0b4d0 and 2eaf828.

📒 Files selected for processing (3)
  • server/index.ts
  • src/components/LogViewer.tsx
  • src/components/ProcessTable.tsx
📜 Review details
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2026-02-19T18:33:18.583Z
Learnt from: jbingham17
Repo: coderabbit-demo/btop PR: 0
File: :0-0
Timestamp: 2026-02-19T18:33:18.583Z
Learning: In Node.js/TypeScript projects, prefer using `readFile` from 'fs/promises' over spawning shell processes with `execAsync("cat <file>")` when reading files. Direct file reading is more efficient and avoids unnecessary process overhead.

Applied to files:

  • src/components/LogViewer.tsx
📚 Learning: 2026-02-18T05:07:00.671Z
Learnt from: jbingham17
Repo: coderabbit-demo/btop PR: 8
File: src/types.ts:32-32
Timestamp: 2026-02-18T05:07:00.671Z
Learning: In the coderabbit-demo/btop repository, avoid inline comments on TypeScript interface properties. Ensure property types are self-documenting through clear names and interface structure. If a property requires explanation, document it above the interface or with JSDoc comments for the property, not inline on the same line.

Applied to files:

  • server/index.ts
🪛 ESLint
src/components/LogViewer.tsx

[error] 25-25: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)

server/index.ts

[error] 339-339: A require() style import is forbidden.

(@typescript-eslint/no-require-imports)


[error] 356-356: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 369-369: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 395-395: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)


[error] 454-454: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)

src/components/ProcessTable.tsx

[error] 35-35: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)

🔇 Additional comments (4)
src/components/ProcessTable.tsx (2)

13-21: LGTM!

The state management for tracking pending kill operations and the cleanup effect properly address the concerns about overlapping requests and timer leaks. The timeout ref cleanup on unmount prevents memory leaks.


187-197: LGTM!

The kill button is properly disabled during in-flight requests (pendingKillPid === process.pid) and only appears for the selected row. Event propagation is correctly stopped to prevent row deselection.

src/components/LogViewer.tsx (2)

32-38: LGTM!

The separation of logPath and logPathDraft addresses the previous concern about request-per-keystroke behavior. The effect correctly cleans up the interval when dependencies change or on unmount.


64-69: Safe log rendering addresses the XSS concern.

Using {logContent} as the child of <pre> correctly renders log content as text, avoiding the previous dangerouslySetInnerHTML vulnerability.

Comment thread src/components/LogViewer.tsx
Comment thread src/components/ProcessTable.tsx
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (1)
src/components/ProcessTable.tsx (1)

39-40: ⚠️ Potential issue | 🟡 Minor

Replace any in error handling with unknown.

Line 39 still uses catch (err: any), which violates @typescript-eslint/no-explicit-any and weakens type safety.

🔧 Suggested fix
-    } catch (err: any) {
-      setKillStatus(`Error: ${err.message}`);
+    } catch (err: unknown) {
+      const message = err instanceof Error ? err.message : 'Unknown error';
+      setKillStatus(`Error: ${message}`);
     } finally {
#!/bin/bash
# Verify explicit-any in catch clauses (TS/TSX)
rg -nP --type=ts --type=tsx '\bcatch\s*\(\s*[^)]*:\s*any\s*\)'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/ProcessTable.tsx` around lines 39 - 40, Replace the explicit
any in the catch clause with unknown and narrow the error before using .message:
change catch (err: any) to catch (err: unknown) in the ProcessTable.tsx block
where setKillStatus is called, then check if err is an instance of Error and use
err.message, otherwise convert err to a string (e.g., String(err)) when calling
setKillStatus so you avoid `@typescript-eslint/no-explicit-any` and preserve type
safety.
🧹 Nitpick comments (1)
src/components/LogViewer.tsx (1)

32-36: Prevent overlapping poll requests under slow network/filesystem reads.

Using setInterval with an async fetch can queue concurrent requests if one cycle exceeds 5s. Consider serial polling (setTimeout after completion) or aborting in-flight requests.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/LogViewer.tsx` around lines 32 - 36, The current useEffect
polling uses setInterval which can start a new fetchLogs before the prior async
call finishes; update the polling in LogViewer.tsx to perform serial polling by
calling fetchLogs and then scheduling the next poll with setTimeout only after
the fetch completes (or switch fetchLogs to accept/return an AbortController and
cancel any in-flight request before starting a new one). Specifically modify the
effect that contains useEffect and the fetchLogs invocation so it uses a
recursive setTimeout loop (or abort-controller logic) instead of setInterval,
ensure cleanup cancels any pending timeout and aborts in-flight requests, and
keep references to the timer ID and AbortController so they can be cleared on
unmount.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/LogViewer.tsx`:
- Line 18: Replace the hardcoded host and raw interpolation in the fetch call
inside LogViewer.tsx: change the URL used in the await fetch(...) (the line that
assigns to res) to use a relative path (e.g. "/api/logs") and pass the file
value via encodeURIComponent(logPath) so any spaces or special chars are safely
escaped instead of interpolating raw logPath into
"http://localhost:3001/api/logs?file=...".
- Around line 25-26: Change the catch block to type the error as unknown instead
of any and narrow it before using .message; in the catch where setError is
called (the error handler that currently reads "catch (err: any) {
setError(err.message); }"), replace with "catch (err: unknown)" and then check
e.g. "if (err instanceof Error) setError(err.message); else if (typeof err ===
'string') setError(err); else setError('An unexpected error occurred');" so you
safely extract a message for setError.

In `@src/components/ProcessTable.tsx`:
- Around line 28-32: The fetch call in ProcessTable.tsx is hardcoded to
'http://localhost:3001/api/process/kill' which breaks in deployed/browser
contexts; change it to use a relative path or an environment-based base URL.
Update the logic around the fetch in the function that issues the kill request
(the POST to /api/process/kill) to build the URL from a configurable base:
either use a relative path '/api/process/kill' or prepend a base from an env var
(e.g., process.env.REACT_APP_API_BASE or process.env.NEXT_PUBLIC_API_URL) so the
code constructs `${BASE}/api/process/kill` at runtime; ensure headers/body
remain the same and that the chosen env var is documented/available in the app
config.

---

Duplicate comments:
In `@src/components/ProcessTable.tsx`:
- Around line 39-40: Replace the explicit any in the catch clause with unknown
and narrow the error before using .message: change catch (err: any) to catch
(err: unknown) in the ProcessTable.tsx block where setKillStatus is called, then
check if err is an instance of Error and use err.message, otherwise convert err
to a string (e.g., String(err)) when calling setKillStatus so you avoid
`@typescript-eslint/no-explicit-any` and preserve type safety.

---

Nitpick comments:
In `@src/components/LogViewer.tsx`:
- Around line 32-36: The current useEffect polling uses setInterval which can
start a new fetchLogs before the prior async call finishes; update the polling
in LogViewer.tsx to perform serial polling by calling fetchLogs and then
scheduling the next poll with setTimeout only after the fetch completes (or
switch fetchLogs to accept/return an AbortController and cancel any in-flight
request before starting a new one). Specifically modify the effect that contains
useEffect and the fetchLogs invocation so it uses a recursive setTimeout loop
(or abort-controller logic) instead of setInterval, ensure cleanup cancels any
pending timeout and aborts in-flight requests, and keep references to the timer
ID and AbortController so they can be cleared on unmount.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 976176b6-1c9b-4b02-904f-eec40d45b310

📥 Commits

Reviewing files that changed from the base of the PR and between 2eaf828 and 26d4357.

📒 Files selected for processing (2)
  • src/components/LogViewer.tsx
  • src/components/ProcessTable.tsx
📜 Review details
🧰 Additional context used
🪛 ESLint
src/components/LogViewer.tsx

[error] 25-25: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)

src/components/ProcessTable.tsx

[error] 39-39: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)

🔇 Additional comments (2)
src/components/ProcessTable.tsx (2)

17-21: Unmount timeout cleanup looks correct.

The useEffect cleanup prevents stale timeout callbacks after unmount. Nice safeguard.


191-201: Row-scoped Kill action behavior is solid.

Showing Kill only for the selected row, stopping propagation, and disabling while pending is clean UX/state handling.

Comment thread src/components/LogViewer.tsx Outdated
Comment thread src/components/LogViewer.tsx Outdated
Comment thread src/components/ProcessTable.tsx Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/components/ProcessTable.tsx (1)

40-41: ⚠️ Potential issue | 🟡 Minor

Use unknown instead of any in catch.

Line 40 reintroduces any, which weakens type safety and violates the current lint rule.

🔧 Suggested fix
-    } catch (err: any) {
-      setKillStatus(`Error: ${err.message}`);
+    } catch (err: unknown) {
+      const message = err instanceof Error ? err.message : 'Unknown error';
+      setKillStatus(`Error: ${message}`);
     } finally {
#!/bin/bash
# Verify explicit-any usage in this component.
rg -nP --type=tsx 'catch\s*\(\s*err\s*:\s*any\s*\)' src/components/ProcessTable.tsx
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/ProcessTable.tsx` around lines 40 - 41, Change the catch
parameter from `any` to `unknown` in the ProcessTable component and update error
handling so the code narrows `err` to an Error before accessing `.message`
(e.g., use `if (err instanceof Error) { setKillStatus(\`Error: ${err.message}\`)
} else { setKillStatus(\`Error: ${String(err)}\`) }`), ensuring you modify the
catch clause that currently reads `catch (err: any)` and use `setKillStatus`
only after proper type-narrowing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/LogViewer.tsx`:
- Around line 42-44: The Refresh handler applyPath currently only calls
setLogPath(logPathDraft) so when logPathDraft === logPath React skips the update
and the useEffect that calls fetchLogs doesn't re-run; modify applyPath to
detect this case and call fetchLogs() directly when the draft equals the current
logPath (otherwise keep setLogPath(logPathDraft) to trigger the existing
effect). Refer to applyPath, setLogPath, logPathDraft, logPath, and fetchLogs in
your changes.

---

Duplicate comments:
In `@src/components/ProcessTable.tsx`:
- Around line 40-41: Change the catch parameter from `any` to `unknown` in the
ProcessTable component and update error handling so the code narrows `err` to an
Error before accessing `.message` (e.g., use `if (err instanceof Error) {
setKillStatus(\`Error: ${err.message}\`) } else { setKillStatus(\`Error:
${String(err)}\`) }`), ensuring you modify the catch clause that currently reads
`catch (err: any)` and use `setKillStatus` only after proper type-narrowing.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 062b3e5c-3464-4d79-8f85-cb93a861ec99

📥 Commits

Reviewing files that changed from the base of the PR and between 26d4357 and 802d43d.

📒 Files selected for processing (2)
  • src/components/LogViewer.tsx
  • src/components/ProcessTable.tsx
📜 Review details
🧰 Additional context used
🪛 ESLint
src/components/ProcessTable.tsx

[error] 40-40: Unexpected any. Specify a different type.

(@typescript-eslint/no-explicit-any)

🔇 Additional comments (1)
src/components/ProcessTable.tsx (1)

23-33: Kill endpoint integration looks correct now.

The request shape (POST + JSON { pid, signal: 'SIGTERM' }) and UI trigger wiring are consistent with the server contract.

Also applies to: 192-202

Comment thread src/components/LogViewer.tsx
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant