Skip to content

Conversation

@RSO
Copy link
Contributor

@RSO RSO commented Jul 28, 2025

We noticed people missing that they still had free credits waiting, so added a way to tell them!

CleanShot 2025-07-29 at 14 45 40@2x

Summary by CodeRabbit

  • New Features

    • Introduced in-app notifications from the kilocode backend, visible on the welcome screen.
    • Added support for dismissing notifications and tracking dismissed notification IDs.
    • Enabled navigation through multiple notifications and action buttons for notification links.
  • Enhancements

    • Improved layout and styling of the welcome screen to accommodate notifications.
    • Updated global and extension state management to support notification tracking.
  • Storybook

    • Added a new Storybook story to showcase the notifications feature with task history.

@changeset-bot
Copy link

changeset-bot bot commented Jul 28, 2025

🦋 Changeset detected

Latest commit: a5b1323

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
kilo-code Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link

coderabbitai bot commented Jul 28, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

This change introduces a notifications system integrated with the Kilocode backend. It adds support for fetching, displaying, dismissing, and tracking notifications both in the extension state and in the webview UI. The update includes schema changes, backend handlers, UI components, and state management to support notifications, along with Storybook test coverage and a changeset entry.

Changes

Cohort / File(s) Change Summary
Storybook Notification Story
apps/storybook/stories/ChatView.stories.tsx
Added a new Storybook story (EmptyWithNotificationsAndHistory) that simulates the presence of Kilocode notifications and task history in the chat view, with mocked notification events and UI container adjustments.
Changeset Metadata
.changeset/early-lemons-guess.md
Added a changeset file documenting a patch-level update for the addition of Kilocode backend notifications.
Global Settings Schema
packages/types/src/global-settings.ts
Extended the global settings schema and default settings to include dismissedNotificationIds, commitMessageApiConfigId, systemNotificationsEnabled, and ghostServiceSettings for notification and Kilocode integration.
Kilocode Notification Handler
src/core/kilocode/webview/webviewMessageHandlerUtils.ts
Introduced a new async function to fetch notifications from the Kilocode backend, handle API token logic, and post results or errors back to the webview.
Provider State Extension
src/core/webview/ClineProvider.ts
Added dismissedNotificationIds to the provider's state, ensuring it is persisted and communicated to the webview.
Webview Message Handling
src/core/webview/webviewMessageHandler.ts
Added handlers for "fetchKilocodeNotifications" and "dismissNotificationId" messages, updating dismissed IDs and posting updated state to the webview.
Extension Message Types
src/shared/ExtensionMessage.ts
Extended message types to include kilocodeNotificationsResponse and support for notification payloads and dismissed notification IDs in the extension state.
Webview Message Types
src/shared/WebviewMessage.ts
Added new message types for dismissing and fetching notifications, plus an optional notificationId payload property.
Chat View UI
webview-ui/src/components/chat/ChatView.tsx
Incorporated the new KilocodeNotifications component into the welcome screen layout, adjusted layout and conditional rendering logic for telemetry and notifications.
Kilocode Notifications Component
webview-ui/src/components/kilocode/KilocodeNotifications.tsx
Added a new React component to display, navigate, and dismiss Kilocode notifications, integrating with VSCode messaging and extension state.
Extension State Context
webview-ui/src/context/ExtensionStateContext.tsx
Extended the context with dismissedNotificationIds and a method to mark notifications as dismissed, updating state accordingly.

Sequence Diagram(s)

sequenceDiagram
    participant UI as ChatView/KilocodeNotifications
    participant Webview as Webview JS
    participant ExtHost as Extension Host (webviewMessageHandler)
    participant Provider as ClineProvider
    participant Kilocode as Kilocode Backend

    UI->>Webview: postMessage({ type: "fetchKilocodeNotifications" })
    Webview->>ExtHost: "fetchKilocodeNotifications"
    ExtHost->>Provider: fetchKilocodeNotificationsHandler
    Provider->>Kilocode: GET /notifications (with token)
    Kilocode-->>Provider: Notifications[]
    Provider->>ExtHost: Notifications[]
    ExtHost->>Webview: postMessage({ type: "kilocodeNotificationsResponse", notifications })
    Webview->>UI: Event: kilocodeNotificationsResponse
    UI->>User: Display notifications

    User->>UI: Dismiss notification
    UI->>Webview: postMessage({ type: "dismissNotificationId", notificationId })
    Webview->>ExtHost: "dismissNotificationId"
    ExtHost->>Provider: Update dismissedNotificationIds
    ExtHost->>Webview: postMessage({ type: "state", dismissedNotificationIds })
    Webview->>UI: Update context state
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • catrielmuller

Poem

🐇
Hopping in with news to share,
Notifications now fill the air!
Dismiss, explore, and click away—
Kilocode keeps you in the fray.
With messages tracked and UI bright,
This rabbit’s code feels just right!
🥕✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8b894c0 and a5b1323.

📒 Files selected for processing (1)
  • webview-ui/src/components/kilocode/KilocodeNotifications.tsx (1 hunks)
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch remon-mark/notifications

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@markijbema markijbema changed the title Remon mark/notifications Add notifications from the kilocode backend Jul 29, 2025
"kilo-code": patch
"@roo-code/vscode-webview": patch
"@roo-code/storybook": patch
"@roo-code/types": patch
Copy link
Collaborator

Choose a reason for hiding this comment

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

Atm we should not update versions for the roo code dependencies because this breaks the release process currently and clashes a bit with future merge.

setEnhancementApiConfigId: (value: string) => void
commitMessageApiConfigId?: string // kilocode_change
setCommitMessageApiConfigId: (value: string) => void // kilocode_change
markNotificationAsDismissed: (notificationId: string) => void // kilocode_change
Copy link
Collaborator

Choose a reason for hiding this comment

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

suggestion: something like setNotificationDismissed or anything with set since this is a bit the convention here. No blocker if you disagree.

Copy link
Contributor

Choose a reason for hiding this comment

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

the reason we choose for another name is that set also implies you can pass in a value, whereas this will always add it to the dismissed set

markijbema and others added 2 commits July 29, 2025 15:38
Co-authored-by: Christiaan Arnoldus <christiaan.arnoldus@outlook.com>
@markijbema markijbema marked this pull request as ready for review July 29, 2025 13:46
Copy link

@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: 4

♻️ Duplicate comments (1)
src/core/webview/webviewMessageHandler.ts (1)

2567-2581: Code organization follows established patterns.

The implementation correctly handles both new message types within the kilocode_change markers as discussed in past reviews. The dismissNotificationId handler appropriately uses getGlobalState as noted in previous comments, and the overall approach aligns with the file's existing structure.

🧹 Nitpick comments (1)
webview-ui/src/components/kilocode/KilocodeNotifications.tsx (1)

18-24: Consider optimizing notification filtering.

The filtered notifications are recalculated on every render. Consider memoizing this computation for better performance.

Apply this diff to add memoization:

+import React, { useEffect, useState, useMemo } from "react"

 export const KilocodeNotifications: React.FC = () => {
   const { dismissedNotificationIds } = useExtensionState()
   const [notifications, setNotifications] = useState<Notification[]>([])
-  const filteredNotifications = notifications.filter(
-    (notification) => !dismissedNotificationIds.includes(notification.id),
-  )
+  const filteredNotifications = useMemo(
+    () => notifications.filter(
+      (notification) => !dismissedNotificationIds.includes(notification.id),
+    ),
+    [notifications, dismissedNotificationIds]
+  )
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between abf9898 and 0fbf0e8.

📒 Files selected for processing (11)
  • .changeset/early-lemons-guess.md (1 hunks)
  • apps/storybook/stories/ChatView.stories.tsx (2 hunks)
  • packages/types/src/global-settings.ts (2 hunks)
  • src/core/kilocode/webview/webviewMessageHandlerUtils.ts (2 hunks)
  • src/core/webview/ClineProvider.ts (3 hunks)
  • src/core/webview/webviewMessageHandler.ts (2 hunks)
  • src/shared/ExtensionMessage.ts (3 hunks)
  • src/shared/WebviewMessage.ts (3 hunks)
  • webview-ui/src/components/chat/ChatView.tsx (3 hunks)
  • webview-ui/src/components/kilocode/KilocodeNotifications.tsx (1 hunks)
  • webview-ui/src/context/ExtensionStateContext.tsx (5 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/!(*kilocode*)/**/*.{ts,tsx,js,jsx,html,css,scss}

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

**/!(*kilocode*)/**/*.{ts,tsx,js,jsx,html,css,scss}: For single line changes, add the comment '// kilocode_change' at the end of the line.
For multiple consecutive lines changed, wrap them with '// kilocode_change start' and '// kilocode_change end' comments.

Files:

  • apps/storybook/stories/ChatView.stories.tsx
  • src/shared/ExtensionMessage.ts
  • webview-ui/src/components/kilocode/KilocodeNotifications.tsx
  • webview-ui/src/context/ExtensionStateContext.tsx
  • packages/types/src/global-settings.ts
  • webview-ui/src/components/chat/ChatView.tsx
  • src/core/webview/webviewMessageHandler.ts
  • src/shared/WebviewMessage.ts
  • src/core/kilocode/webview/webviewMessageHandlerUtils.ts
  • src/core/webview/ClineProvider.ts
**/!(*kilocode*)/**/*.{html,jsx,tsx}

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

In HTML/JSX/TSX files, use '{/* kilocode_change start /}' and '{/ kilocode_change end */}' to wrap multi-line changes.

Files:

  • apps/storybook/stories/ChatView.stories.tsx
  • webview-ui/src/components/kilocode/KilocodeNotifications.tsx
  • webview-ui/src/context/ExtensionStateContext.tsx
  • webview-ui/src/components/chat/ChatView.tsx
**/*kilocode*/**

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

If the filename or directory name contains 'kilocode', no marking with comments is required.

Files:

  • webview-ui/src/components/kilocode/KilocodeNotifications.tsx
  • src/core/kilocode/webview/webviewMessageHandlerUtils.ts
🧬 Code Graph Analysis (4)
webview-ui/src/components/kilocode/KilocodeNotifications.tsx (2)
webview-ui/src/context/ExtensionStateContext.tsx (1)
  • useExtensionState (564-572)
webview-ui/src/utils/vscode.ts (1)
  • vscode (80-80)
webview-ui/src/context/ExtensionStateContext.tsx (1)
webview-ui/src/utils/vscode.ts (1)
  • setState (69-76)
webview-ui/src/components/chat/ChatView.tsx (2)
webview-ui/src/components/kilocode/KilocodeNotifications.tsx (1)
  • KilocodeNotifications (18-121)
webview-ui/src/components/kilocode/chat/IdeaSuggestionsBox.tsx (1)
  • IdeaSuggestionsBox (4-37)
src/core/kilocode/webview/webviewMessageHandlerUtils.ts (1)
src/core/webview/ClineProvider.ts (1)
  • ClineProvider (95-2224)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: storybook-playwright-snapshot
  • GitHub Check: test-extension (windows-latest)
  • GitHub Check: test-webview (windows-latest)
  • GitHub Check: compile
🔇 Additional comments (27)
.changeset/early-lemons-guess.md (1)

1-5: No release process conflict detected for kilo-code update.

  • All reviewed changesets in .changeset/ reference only kilo-code, with no roo-code version bumps.
  • Although many package.json files list roo-code dependencies, there are no changesets updating them.
  • Therefore, this kilo-code patch should not clash with past release process constraints concerning roo-code.
src/core/webview/webviewMessageHandler.ts (3)

57-57: LGTM!

The import statement correctly follows the established pattern and includes the required kilocode_change comment.


2567-2570: LGTM!

The handler correctly delegates to the imported handler function and follows the established pattern in the file. The kilocode_change comments are properly applied.


2571-2581: LGTM!

The handler properly validates the notification ID, safely updates the global state by appending to the existing dismissed notification IDs array, and keeps the webview in sync. The implementation follows established patterns and coding guidelines.

src/shared/WebviewMessage.ts (3)

234-234: LGTM!

The new message type "dismissNotificationId" is appropriately named and follows the established pattern. The kilocode_change comment is correctly applied.


244-244: LGTM!

The new message type "fetchKilocodeNotifications" is appropriately named and follows the established pattern.


273-273: LGTM!

The optional notificationId property is correctly typed and appropriately placed. It supports the notification dismissal functionality and follows the established naming convention.

src/core/kilocode/webview/webviewMessageHandlerUtils.ts (1)

7-7: LGTM!

The axios import is correctly added and needed for the HTTP request functionality.

apps/storybook/stories/ChatView.stories.tsx (2)

107-223: Well-implemented Storybook story with proper mocking.

The story implementation is excellent:

  1. Proper event simulation: Uses MessageEvent to simulate the webview message system
  2. Realistic mock data: Provides comprehensive notification examples
  3. Cleanup handling: Properly clears the timeout to prevent memory leaks
  4. Appropriate configuration: Sets API provider to "kilocode" and enables telemetry to trigger notification display

The story serves as a good demonstration of the notification system integration.


1-1: Incorrect coding guideline compliance.

According to the coding guidelines, files that don't contain 'kilocode' in their path should mark changes with comments. However, since this appears to be a new file, each line should be marked individually rather than using a single comment for the entire file.

-// kilocode_change - new file
+// Since this is a new file, each line should be marked individually according to the coding guidelines

Likely an incorrect or invalid review comment.

webview-ui/src/context/ExtensionStateContext.tsx (5)

37-37: LGTM!

The property declaration is correctly typed and follows the established pattern in the interface.


130-130: Function naming is appropriate.

Based on the past review discussion, the current naming markNotificationAsDismissed is well-chosen as it clearly indicates the action being performed without implying a generic setter behavior.


220-220: LGTM!

The property is correctly initialized as an empty array, which is the appropriate default state.


497-504: Implementation is correct and follows immutability patterns.

The method correctly:

  1. Uses functional state update pattern
  2. Prepends the new notification ID to maintain order
  3. Handles the case where dismissedNotificationIds might be undefined with fallback to empty array
  4. Returns a new state object maintaining immutability

553-553: LGTM!

The property is correctly included in the context value with proper fallback to empty array.

src/core/webview/ClineProvider.ts (3)

1507-1507: LGTM! Consistent state management for dismissed notifications.

The addition of dismissedNotificationIds follows the established pattern in the codebase for state management, with appropriate default values.


1636-1636: LGTM! Proper state propagation to webview.

The dismissedNotificationIds is correctly included in the state object sent to the webview with a sensible default value.


1786-1786: LGTM! Complete state management implementation.

The dismissedNotificationIds property is properly included in the main state getter with consistent defaulting behavior.

src/shared/ExtensionMessage.ts (3)

123-123: LGTM! Well-structured message type addition.

The new kilocodeNotificationsResponse message type follows the established naming convention and integrates cleanly with existing message types.


194-204: LGTM! Well-defined notification structure.

The notification interface is properly typed with all necessary fields:

  • Required: id, title, message for core notification data
  • Optional: action object with actionText and actionURL for interactive notifications

This provides a flexible structure that supports both informational and actionable notifications.


280-280: LGTM! Consistent ExtensionState type extension.

The addition of dismissedNotificationIds to the ExtensionState type maintains consistency with the existing type structure and naming conventions.

webview-ui/src/components/kilocode/KilocodeNotifications.tsx (1)

74-99: LGTM! Well-structured notification UI.

The notification display logic is well implemented with:

  • Proper conditional rendering
  • Clean CSS classes using VSCode theme variables
  • Accessible buttons with titles
  • Good user experience with dismiss functionality
webview-ui/src/components/chat/ChatView.tsx (2)

60-60: LGTM!

The import statement is correctly added with proper kilocode_change comment as required by the coding guidelines.


1788-1827: Layout restructuring looks good with proper conditional rendering.

The changes successfully:

  • Update container classes to support notifications with better flex layout
  • Correctly invert the telemetry conditional logic (show notifications when telemetry is NOT "unset")
  • Maintain existing functionality while adding notification support
  • Follow coding guidelines with proper kilocode_change comments

The conditional rendering logic change is logical: when telemetry is unset, show the telemetry banner; otherwise, show notifications.

packages/types/src/global-settings.ts (3)

17-17: LGTM!

The import statement is correctly added with proper kilocode_change comment.


139-141: Schema additions support the notification system well.

The new properties are properly defined:

  • dismissedNotificationIds as optional array to track dismissed notifications
  • commitMessageApiConfigId as optional string for API configuration
  • ghostServiceSettings as required schema for ghost service settings

Note that ghostServiceSettings is required while others are optional - verify this is intentional.


252-254: Default settings properly initialize the new notification properties.

The defaults are well-chosen:

  • dismissedNotificationIds: [] - empty array for fresh start
  • systemNotificationsEnabled: true - reasonable default to enable notifications
  • ghostServiceSettings: {} - empty object matching the required schema

These align perfectly with the schema definitions above.

Comment on lines +71 to +103
export const fetchKilocodeNotificationsHandler = async (provider: ClineProvider) => {
try {
const { apiConfiguration } = await provider.getState()
const kilocodeToken = apiConfiguration?.kilocodeToken

if (!kilocodeToken || apiConfiguration?.apiProvider !== "kilocode") {
provider.postMessageToWebview({
type: "kilocodeNotificationsResponse",
notifications: [],
})
return
}

const response = await axios.get("https://kilocode.ai/api/users/notifications", {
headers: {
Authorization: `Bearer ${kilocodeToken}`,
"Content-Type": "application/json",
},
timeout: 5000,
})

provider.postMessageToWebview({
type: "kilocodeNotificationsResponse",
notifications: response.data?.notifications || [],
})
} catch (error: any) {
provider.log(`Error fetching Kilocode notifications: ${error.message}`)
provider.postMessageToWebview({
type: "kilocodeNotificationsResponse",
notifications: [],
})
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider security and maintainability improvements.

The function implementation is functionally correct but has several areas for improvement:

  1. Hardcoded API endpoint: The URL https://kilocode.ai/api/users/notifications should be configurable
  2. Token exposure in logs: If the request fails, the token might be exposed in error messages
  3. Generic error handling: All errors result in empty notifications array, losing specific error information
+// Consider moving to a config file
+const KILOCODE_API_BASE_URL = process.env.KILOCODE_API_URL || "https://kilocode.ai/api"

 export const fetchKilocodeNotificationsHandler = async (provider: ClineProvider) => {
 	try {
 		const { apiConfiguration } = await provider.getState()
 		const kilocodeToken = apiConfiguration?.kilocodeToken

 		if (!kilocodeToken || apiConfiguration?.apiProvider !== "kilocode") {
 			provider.postMessageToWebview({
 				type: "kilocodeNotificationsResponse",
 				notifications: [],
 			})
 			return
 		}

-		const response = await axios.get("https://kilocode.ai/api/users/notifications", {
+		const response = await axios.get(`${KILOCODE_API_BASE_URL}/users/notifications`, {
 			headers: {
 				Authorization: `Bearer ${kilocodeToken}`,
 				"Content-Type": "application/json",
 			},
 			timeout: 5000,
 		})

 		provider.postMessageToWebview({
 			type: "kilocodeNotificationsResponse",
 			notifications: response.data?.notifications || [],
 		})
 	} catch (error: any) {
-		provider.log(`Error fetching Kilocode notifications: ${error.message}`)
+		// Log error without potentially exposing sensitive information
+		provider.log(`Error fetching Kilocode notifications: ${error.response?.status || 'Network error'}`)
 		provider.postMessageToWebview({
 			type: "kilocodeNotificationsResponse",
 			notifications: [],
 		})
 	}
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const fetchKilocodeNotificationsHandler = async (provider: ClineProvider) => {
try {
const { apiConfiguration } = await provider.getState()
const kilocodeToken = apiConfiguration?.kilocodeToken
if (!kilocodeToken || apiConfiguration?.apiProvider !== "kilocode") {
provider.postMessageToWebview({
type: "kilocodeNotificationsResponse",
notifications: [],
})
return
}
const response = await axios.get("https://kilocode.ai/api/users/notifications", {
headers: {
Authorization: `Bearer ${kilocodeToken}`,
"Content-Type": "application/json",
},
timeout: 5000,
})
provider.postMessageToWebview({
type: "kilocodeNotificationsResponse",
notifications: response.data?.notifications || [],
})
} catch (error: any) {
provider.log(`Error fetching Kilocode notifications: ${error.message}`)
provider.postMessageToWebview({
type: "kilocodeNotificationsResponse",
notifications: [],
})
}
}
// Consider moving to a config file
const KILOCODE_API_BASE_URL = process.env.KILOCODE_API_URL || "https://kilocode.ai/api"
export const fetchKilocodeNotificationsHandler = async (provider: ClineProvider) => {
try {
const { apiConfiguration } = await provider.getState()
const kilocodeToken = apiConfiguration?.kilocodeToken
if (!kilocodeToken || apiConfiguration?.apiProvider !== "kilocode") {
provider.postMessageToWebview({
type: "kilocodeNotificationsResponse",
notifications: [],
})
return
}
const response = await axios.get(`${KILOCODE_API_BASE_URL}/users/notifications`, {
headers: {
Authorization: `Bearer ${kilocodeToken}`,
"Content-Type": "application/json",
},
timeout: 5000,
})
provider.postMessageToWebview({
type: "kilocodeNotificationsResponse",
notifications: response.data?.notifications || [],
})
} catch (error: any) {
// Log error without potentially exposing sensitive information
provider.log(`Error fetching Kilocode notifications: ${error.response?.status || 'Network error'}`)
provider.postMessageToWebview({
type: "kilocodeNotificationsResponse",
notifications: [],
})
}
}
🤖 Prompt for AI Agents
In src/core/kilocode/webview/webviewMessageHandlerUtils.ts lines 71 to 103,
improve security and maintainability by making the API endpoint configurable via
environment variables or configuration files instead of hardcoding it. Avoid
exposing the kilocodeToken in any logs or error messages by ensuring error
logging does not include sensitive data. Enhance error handling by
distinguishing different error types or statuses and providing more informative
messages or fallback behaviors rather than always returning an empty
notifications array.

Comment on lines +26 to +41
useEffect(() => {
const handleMessage = (event: MessageEvent) => {
const message = event.data
if (message.type === "kilocodeNotificationsResponse") {
setNotifications(message.notifications || [])
}
}

window.addEventListener("message", handleMessage)

setCurrentIndex(Math.max(0, Math.min(currentIndex, filteredNotifications.length - 1)))

return () => {
window.removeEventListener("message", handleMessage)
}
}, [currentIndex, filteredNotifications.length, dismissedNotificationIds])
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix useEffect dependency and index bounds logic.

The useEffect has a problematic dependency on dismissedNotificationIds and the index adjustment logic could cause issues.

Apply this diff to fix the dependency and bounds checking:

 useEffect(() => {
   const handleMessage = (event: MessageEvent) => {
     const message = event.data
     if (message.type === "kilocodeNotificationsResponse") {
       setNotifications(message.notifications || [])
     }
   }

   window.addEventListener("message", handleMessage)
-  setCurrentIndex(Math.max(0, Math.min(currentIndex, filteredNotifications.length - 1)))

   return () => {
     window.removeEventListener("message", handleMessage)
   }
-}, [currentIndex, filteredNotifications.length, dismissedNotificationIds])
+}, [])

And add a separate useEffect for index bounds checking:

+useEffect(() => {
+  if (filteredNotifications.length > 0) {
+    setCurrentIndex(prev => Math.max(0, Math.min(prev, filteredNotifications.length - 1)))
+  } else {
+    setCurrentIndex(0)
+  }
+}, [filteredNotifications.length])
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
useEffect(() => {
const handleMessage = (event: MessageEvent) => {
const message = event.data
if (message.type === "kilocodeNotificationsResponse") {
setNotifications(message.notifications || [])
}
}
window.addEventListener("message", handleMessage)
setCurrentIndex(Math.max(0, Math.min(currentIndex, filteredNotifications.length - 1)))
return () => {
window.removeEventListener("message", handleMessage)
}
}, [currentIndex, filteredNotifications.length, dismissedNotificationIds])
useEffect(() => {
const handleMessage = (event: MessageEvent) => {
const message = event.data
if (message.type === "kilocodeNotificationsResponse") {
setNotifications(message.notifications || [])
}
}
window.addEventListener("message", handleMessage)
return () => {
window.removeEventListener("message", handleMessage)
}
}, [])
useEffect(() => {
if (filteredNotifications.length > 0) {
setCurrentIndex(prev =>
Math.max(0, Math.min(prev, filteredNotifications.length - 1))
)
} else {
setCurrentIndex(0)
}
}, [filteredNotifications.length])
🤖 Prompt for AI Agents
In webview-ui/src/components/kilocode/KilocodeNotifications.tsx around lines 26
to 41, the useEffect incorrectly includes dismissedNotificationIds in its
dependency array and combines message handling with index bounds adjustment,
which can cause unnecessary re-renders and logic errors. To fix this, remove
dismissedNotificationIds from the dependencies of the message event listener
useEffect and isolate the index bounds checking into a separate useEffect that
only depends on currentIndex and filteredNotifications.length. This separation
ensures proper event handling and correct index adjustment without unintended
side effects.

@RSO RSO requested a review from kevinvandijk July 29, 2025 14:04
@RSO RSO merged commit b3b024f into main Jul 29, 2025
7 of 8 checks passed
@RSO RSO deleted the remon-mark/notifications branch July 29, 2025 14:18
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.

5 participants