Skip to content

Feature/state machine challenges - #224

Merged
Vinod-V3 merged 13 commits into
ELEVATE-Project:release-1.0.5from
VishnuKrishnathu:feature/state-machine-challenges
Jan 14, 2026
Merged

Feature/state machine challenges#224
Vinod-V3 merged 13 commits into
ELEVATE-Project:release-1.0.5from
VishnuKrishnathu:feature/state-machine-challenges

Conversation

@VishnuKrishnathu

@VishnuKrishnathu VishnuKrishnathu commented Jan 13, 2026

Copy link
Copy Markdown

Summary by CodeRabbit

  • New Features

    • Added a state-machine driven chat interface for the challenge-definition workflow.
  • Refactor

    • Streamlined chat components and reduced public prop surfaces for simpler integration.
    • Added sorting utilities and accessors for strand step and state-machine length.
  • Chores

    • Styling and formatting consistency updates.
    • Adjusted WebSocket cleanup behavior.
    • Introduced a default company slug constant.

✏️ Tip: You can customize this high-level summary in your review settings.

…nent structure

- Simplified error handling and response processing in chat flow API functions.
- Refactored MainPage component to enhance readability and maintainability.
- Introduced StateMachineDefineChallenge component for better separation of concerns.
- Updated ChatWindow and ChatMessage components for improved functionality and performance.
- Added utility functions for sorting data.
- Added DEFAULT_COMPANY_SLUG constant for improved company slug management.
- Integrated useChatDataSessionStore and useSiteDataLocalStore in MainPage for better state management.
- Implemented WebSocket connection handling in StateMachineDefineChallenge for real-time chat updates.
- Refactored message handling logic to streamline user and bot interactions.
- Updated session management to ensure proper state resets and error handling.
- Reorganized imports and removed unnecessary comments for clarity.
- Streamlined state management and effect hooks in MainPage for better performance.
- Enhanced message handling and WebSocket connection logic in InitialSwitch.
- Updated loading states and conditional rendering in StateMachineDefineChallenge and ChatWindow components.
- Improved overall code readability and maintainability.
@coderabbitai

coderabbitai Bot commented Jan 13, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR adds a new StateMachineDefineChallenge React component (chat state machine with WebSocket, TTS, and session orchestration), replaces DefineChallenge with it in MainPage, tightens ChatWindow/ChatMessage props, adds sort utilities and chatData accessors, removes websocket.close() from the hook cleanup, and adds a new DEFAULT_COMPANY_SLUG constant.

Changes

Cohort / File(s) Summary
Configuration & Constants
src/configure.js, src/constants/session.js
Formatting changes in configure.js; new exported constant DEFAULT_COMPANY_SLUG = "shikshalokamstaging" in session.js
WebSocket Hook
src/hooks/useChatWebhook.js
Removed websocket.close() from effect cleanup (no automatic WebSocket close on unmount)
New State-Machine Feature
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/StateMachineDefineChallenge.jsx
New component implementing chat-based state machine: WebSocket integration, API calls (profile/session/intro), TTS/audio playback and caching, chat orchestration, store interactions, and exported createMessage helper
Main Page Integration
src/pages/ai-creation/pages/shikshalokam-mitra/MainPage.jsx
Replaced DefineChallenge import/usage with StateMachineDefineChallenge; minor formatting/store resets updated
Chat UI Components
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/ChatWindow.jsx, src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/chat-message/ChatMessage.jsx
ChatWindow signature: removed botNameToDisplay prop; ChatMessage signature: removed recording, appendixURL, isTalking, validation props and removed legacy/commented JSX
State & Utilities
src/store/slices/chatData/state.js, src/utils/sorts.js
Added getStrandStep() and getStateMachineLength() accessors to chatData state; added compareById() and quickSort() utility functions

Sequence Diagram(s)

sequenceDiagram
    participant UI as StateMachineDefineChallenge (React)
    participant API as Backend API
    participant WS as WebSocket
    participant Store as Zustand Store

    UI->>API: Fetch user profile, company bot, session, intro
    API-->>UI: Profile, bot info, session, intro
    UI->>Store: Initialize session & language state
    UI->>WS: Open WebSocket connection & authenticate
    WS-->>UI: Auth confirmed
    UI->>UI: Render intro message (optional TTS)
    Note over UI: User sends a message
    UI->>WS: Send user message
    WS-->>UI: Stream BOT response (chunks)
    UI->>UI: Append streamed BOT messages to chat history
    UI->>Store: Update strand step / should_move_forward
    UI->>API: Persist or fetch additional session data as needed
    Note over UI: Repeat until flow completion
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested reviewers

  • Vinod-V3

Poem

🐰 I hopped into code to weave a chat,
New state-machine steps and a websocket hat,
Bots now sing, audio cached and clear,
Slimmer messages, props trimmed near,
A rabbit's tiny hop — the conversation's here. 🥕

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title refers to the core feature being added but lacks specificity about what state machine challenges entails. Consider a more descriptive title such as 'Add StateMachineDefineChallenge component with WebSocket integration' to better convey the main technical change.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

🧹 Recent nitpick comments
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/StateMachineDefineChallenge.jsx (1)

30-30: Consider using const for non-reassigned variable.

access_token is never reassigned within this component, so const is more appropriate than let.

Suggested fix
-  let access_token = sessionStorage.getItem(URL_PARAMS.ACCESS_TOKEN)
+  const access_token = sessionStorage.getItem(URL_PARAMS.ACCESS_TOKEN)

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between eb2f19f and 7627940.

📒 Files selected for processing (5)
  • src/pages/ai-creation/pages/shikshalokam-mitra/MainPage.jsx
  • src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/StateMachineDefineChallenge.jsx
  • src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/ChatWindow.jsx
  • src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/chat-message/ChatMessage.jsx
  • src/store/slices/chatData/state.js
💤 Files with no reviewable changes (1)
  • src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/ChatWindow.jsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/store/slices/chatData/state.js
  • src/pages/ai-creation/pages/shikshalokam-mitra/MainPage.jsx
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-12-23T16:55:04.450Z
Learnt from: pinkman7009
Repo: ELEVATE-Project/mohini-app-frontend PR: 218
File: src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/ActionItems.jsx:318-320
Timestamp: 2025-12-23T16:55:04.450Z
Learning: In ActionItems.jsx (src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/ActionItems.jsx), the action list is intentionally refetched every time the objective changes. The commented-out guard and the useEffect dependency on `objective` are part of the expected design for handling objective regeneration flows.

Applied to files:

  • src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/StateMachineDefineChallenge.jsx
📚 Learning: 2026-01-14T02:51:09.584Z
Learnt from: pinkman7009
Repo: ELEVATE-Project/mohini-app-frontend PR: 225
File: src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/InitialSwitch.jsx:79-89
Timestamp: 2026-01-14T02:51:09.584Z
Learning: In the AI creation flow React components (InitialSwitch.jsx and CommonFlow.jsx), the pattern of using a pendingMessageRef with a 100ms setTimeout after WebSocket authentication is an accepted approach to ensure the authenticate message is sent before user messages. Apply this pattern to all JSX files in src/pages/ai-creation/pages/ to maintain consistent timing-based readiness across the flow.

Applied to files:

  • src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/StateMachineDefineChallenge.jsx
  • src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/chat-message/ChatMessage.jsx
🧬 Code graph analysis (1)
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/StateMachineDefineChallenge.jsx (9)
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/chat-message/ChatMessage.jsx (1)
  • CONVERSATION_USER_TYPES (7-7)
src/pages/ai-creation/pages/shikshalokam-mitra/MainPage.jsx (1)
  • chatHistory (63-65)
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/InitialSwitch.jsx (1)
  • setSessionStore (41-46)
src/hooks/useChatWebhook.js (3)
  • useChatWebhook (3-99)
  • useChatWebhook (3-99)
  • sendMessage (72-80)
src/api/endpoints/chat.js (1)
  • data (31-31)
src/pages/shikshalokamChat.js (1)
  • setProfileId (38-38)
src/constants/session.js (2)
  • DEFAULT_COMPANY_SLUG (8-8)
  • DEFAULT_COMPANY_SLUG (8-8)
src/components/ToastMessage/TotastMessage.jsx (1)
  • Notification (6-23)
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/LoadingChat.jsx (1)
  • LoadingChat (1-8)
🔇 Additional comments (5)
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/chat-message/ChatMessage.jsx (1)

9-53: Clean prop surface reduction.

The streamlined prop interface improves maintainability. Good use of DOMPurify for sanitizing message content before rendering. The default values for isShowImages and isShowBotSpeaker are sensible defensive defaults.

src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/StateMachineDefineChallenge.jsx (4)

81-158: Good improvement using store getters for fresh values.

The use of getStateMachineLength() and getStrandStep() (lines 132-133) directly from the store inside the callback correctly addresses the stale closure concern from the previous review. This ensures the comparison uses the current values rather than captured state.


379-418: LGTM - WebSocket message handling follows established pattern.

The authenticate-then-send pattern is consistent with other components in the AI creation flow. The useChatWebhook hook's internal socketQueue handles the timing between connection establishment and message sending.


549-559: Good - proper guards and immutable updates.

The condition at line 550 now properly guards against empty chatHistory with Array.isArray(chatHistory) && chatHistory.length, and structuredClone at line 551 ensures immutable updates. Previous review concerns have been addressed.


585-602: LGTM - Clean conditional rendering.

The loading state handling with LoadingChat and the conditional layout based on isDefineChallengeSection is well structured. Props are properly passed to child components.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

…functions

- Updated all API functions in chat_flow.js to use consistent formatting and error handling.
- Improved readability by aligning try-catch blocks and ensuring uniform return statements.
- Removed unnecessary comments and streamlined the code for better maintainability.
@VishnuKrishnathu

Copy link
Copy Markdown
Author

@CodeRabbit review

@coderabbitai

coderabbitai Bot commented Jan 13, 2026

Copy link
Copy Markdown
✅ 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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/ChatWindow.jsx (1)

124-144: Passing unused props to ChatMessage.

Several props passed to ChatMessage (name, recording, hasAppendix, appendixURL, isTalking, validation, isAnyPlaying, setNotMute) are not accepted by the simplified ChatMessage component signature. These will be silently ignored.

Remove unused props for clarity, or update ChatMessage if these props are needed.

Suggested fix - remove unused props
              <ChatMessage
                userType={chat?.source}
                message={`${chat?.msg}`}
-               name={"You"}
-               recording={chat?.recording}
-               hasAppendix={chat?.recording}
-               appendixURL={chat?.appendixURL}
-               isTalking={chat.source === "bot" && !isStreamingComplete && i === chatHistory.length - 1}
                handleOnStopSpeaking={() => handleOnStopSpeaking()}
                handleOnSpeaking={() => {
                  setNotMute(false)
                  handleOnSpeaking(`${chat?.msg}`, chat?.updated_at)
                }}
-               isAnyPlaying={!!hasOverRideId || isTalking}
                isPlaying={hasOverRideId === chat?.updated_at}
                isStreamingComplete={isStreamingComplete}
-               setNotMute={setNotMute}
                chatId={chat?.updated_at}
-               validation={chat?.validation}
                userDetail={userDetail}
              />
🤖 Fix all issues with AI agents
In @src/constants/session.js:
- Line 8: StateMachineDefineChallenge.jsx currently uses the hardcoded
DEFAULT_COMPANY_SLUG when calling getCompanyBotApi; update it to use the company
slug fetched into state (the value set by setCompanyStore / profile data) and
only fall back to DEFAULT_COMPANY_SLUG if that state/profile value is missing.
Locate the getCompanyBotApi call in StateMachineDefineChallenge.jsx (around
where setCompanyStore(data?.company?.slug) is used) and pass the
profile/companyStore slug instead of DEFAULT_COMPANY_SLUG, ensuring the same
fallback semantics as in DefineChallenge.jsx.

In
@src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/ChatWindow.jsx:
- Around line 31-37: The code in ChatWindow.jsx has two identical if (errorText)
{ showLoader = false } blocks; remove the duplicate so there is only one check
that sets showLoader to false when errorText is truthy (keep the first
occurrence and delete the repeated block), ensuring no other logic around
showLoader or errorText is altered.
- Line 53: The return expression can throw when chatHistory is empty; guard
access before reading .source by checking length and using optional chaining:
ensure chatHistory?.length > 0 (or chatHistory?.[chatHistory.length -
1]?.source) before comparing to "user" so the expression becomes something like:
!hasStartedListening && chatHistory?.length > 0 &&
chatHistory[chatHistory.length - 1]?.source === "user" && indexNumber ===
chatHistory.length - 1 && showLoader.

In
@src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/StateMachineDefineChallenge.jsx:
- Around line 349-360: The effect is mutating chat_history in place when setting
the last item; instead, build a new array copy and replace the last element
immutably before calling setChatHistory. In the useEffect that reads recordings
and chatHistory (and uses getChatHistory()), create a shallow copy (e.g.,
[...chat_history]) or map over chat_history, replace the last element with
{...chat_history[lastIndex], recording: recordings[recordings.length-1]} and
then call setChatHistory(newArray) so React sees a new reference; keep the same
guard (recordings?.length && chatHistory[last]?.source !== BOT).
- Around line 551-561: Guard against empty chatHistory before accessing its last
element: in the useEffect that checks appendix and chatHistory, ensure
chatHistory has at least one item (e.g., chatHistory?.length > 0) before reading
chatHistory[chatHistory.length - 1].source or use optional chaining on the last
element (e.g., chatHistory[chatHistory.length - 1]?.source === BOT). Update the
condition surrounding appendix handling in the useEffect (symbols: useEffect,
appendix, chatHistory, BOT, getChatHistory, lastMessage, setChatHistory,
setAppendix) so you only mutate lastMessage when it exists, then proceed to
setChatHistory and setAppendix as before; keep the
isDefineChallengeSection/handleScrollIntoView logic unchanged.
- Around line 243-250: The three async calls createUserProfile(),
fetchCompanyBotInfo(), and getSessionId() are fired in parallel and can cause
state updates after unmount; coordinate them and add an abort/cleanup flag in
the useEffect so no setState or navigation happens if the effect is cleaned up.
Make createUserProfile, fetchCompanyBotInfo, and getSessionId return Promises
(if they don't already), then either await them sequentially or use
Promise.allSettled to observe results, wrap their state-setting calls
(setShouldFetchIntro, setIsStreamingComplete, any navigation) behind a check of
a local cancelled/isMounted flag, and implement the effect cleanup to set that
flag to true; also add try/catch around awaits to handle errors and avoid
unguarded state updates.
- Around line 132-135: The onWebSocketMessage callback passed into
useChatWebhook can close over a stale stateMachineLength; update it to read the
latest value (e.g., create a stateMachineLengthRef via useRef, keep it in sync
by assigning stateMachineLengthRef.current = stateMachineLength in an effect or
immediately after state updates, and then inside onWebSocketMessage call
getStrandStep() and compare against stateMachineLengthRef.current before calling
setShouldMoveForward("yes")). Alternatively, instead of the ref approach, read
stateMachineLength from the store inside onWebSocketMessage to ensure the latest
value is used; ensure you update references to stateMachineLength in that
callback (and keep setShouldMoveForward usage unchanged).

In @src/utils/sorts.js:
- Around line 5-8: The quickSort function currently uses optional chaining so
when arr is null/undefined it returns undefined; change it to explicitly handle
null/undefined by adding a guard at the top of quickSort (e.g., if (arr == null)
return []) before the length check, then keep the existing behavior for arrays
(if (arr.length <= 1) return arr). Reference quickSort to locate where to add
the null/undefined guard so callers always receive an array rather than
undefined.
🧹 Nitpick comments (4)
src/utils/sorts.js (1)

5-23: Consider using the built-in Array.prototype.sort() instead.

The custom quicksort implementation works, but JavaScript's built-in sort() is typically more performant (uses optimized algorithms like Timsort in V8) and handles edge cases more robustly. The first-element pivot selection can also degrade to O(n²) on already-sorted arrays.

♻️ Simpler alternative using built-in sort
export function quickSort(arr, compare) {
  if (!arr || arr.length <= 1) {
    return arr || []
  }
  return [...arr].sort(compare)
}

This creates a shallow copy to preserve immutability (like the current implementation) and leverages the optimized native sort.

src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/StateMachineDefineChallenge.jsx (2)

30-30: Avoid using let for variables that aren't reassigned.

access_token is declared with let but never reassigned. Use const for consistency.

Suggested fix
-  let access_token = sessionStorage.getItem(URL_PARAMS.ACCESS_TOKEN)
+  const access_token = sessionStorage.getItem(URL_PARAMS.ACCESS_TOKEN)

347-347: Remove empty useEffect.

This useEffect has no side effects and serves no purpose.

Suggested fix
-  useEffect(() => {}, [])
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/ChatWindow.jsx (1)

56-68: Consider using a cleaner approach for filtering.

The current implementation uses forEach with a flag to stop pushing. A more functional approach would be clearer.

Alternative implementation
   const chatsToShow = useMemo(() => {
-    const data = []
-    let shouldPush = true
-    chatHistory?.forEach(chat => {
-      if (shouldPush) {
-        data.push(chat)
-        if (chat?.shouldMoveForward === "yes" && chat?.source === "user") {
-          shouldPush = false
-        }
-      }
-    })
-    return data
+    const stopIndex = chatHistory?.findIndex(
+      chat => chat?.shouldMoveForward === "yes" && chat?.source === "user"
+    )
+    return stopIndex === -1 
+      ? chatHistory ?? [] 
+      : chatHistory?.slice(0, stopIndex + 1) ?? []
   }, [chatHistory])
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a587823 and 05f8836.

📒 Files selected for processing (9)
  • src/configure.js
  • src/constants/session.js
  • src/hooks/useChatWebhook.js
  • src/pages/ai-creation/pages/shikshalokam-mitra/MainPage.jsx
  • src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/StateMachineDefineChallenge.jsx
  • src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/ChatWindow.jsx
  • src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/chat-message/ChatMessage.jsx
  • src/store/slices/chatData/state.js
  • src/utils/sorts.js
💤 Files with no reviewable changes (1)
  • src/hooks/useChatWebhook.js
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2026-01-11T21:04:07.741Z
Learnt from: pinkman7009
Repo: ELEVATE-Project/mohini-app-frontend PR: 223
File: src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/CommonFlow.jsx:124-140
Timestamp: 2026-01-11T21:04:07.741Z
Learning: In CommonFlow.jsx (src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/CommonFlow.jsx), the WebSocket URL intentionally uses `sessionFlowName.Creation` for all common flows (LFA, LCF, FREE_FLOW) in the `buildWebSocketUrl` call. The derived `storageFlow` (from `flowConfig.flow_name`) is used in the authentication message sent via `onWebSocketOpen`, not in the WebSocket URL construction. This is the expected design.

Applied to files:

  • src/configure.js
📚 Learning: 2025-12-23T16:55:04.450Z
Learnt from: pinkman7009
Repo: ELEVATE-Project/mohini-app-frontend PR: 218
File: src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/ActionItems.jsx:318-320
Timestamp: 2025-12-23T16:55:04.450Z
Learning: In ActionItems.jsx (src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/ActionItems.jsx), the action list is intentionally refetched every time the objective changes. The commented-out guard and the useEffect dependency on `objective` are part of the expected design for handling objective regeneration flows.

Applied to files:

  • src/pages/ai-creation/pages/shikshalokam-mitra/MainPage.jsx
📚 Learning: 2026-01-11T21:08:05.729Z
Learnt from: pinkman7009
Repo: ELEVATE-Project/mohini-app-frontend PR: 223
File: src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/SelectObjective.jsx:416-439
Timestamp: 2026-01-11T21:08:05.729Z
Learning: In the SelectObjective.jsx component (src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/SelectObjective.jsx), objectives are guaranteed to have unique text values, so text-based equality comparison is safe for determining objective selection without risk of duplicate matches.

Applied to files:

  • src/pages/ai-creation/pages/shikshalokam-mitra/MainPage.jsx
🧬 Code graph analysis (5)
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/StateMachineDefineChallenge.jsx (8)
src/configure.js (2)
  • bot_routes (22-42)
  • bot_routes (22-42)
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/chat-message/ChatMessage.jsx (1)
  • CONVERSATION_USER_TYPES (7-7)
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/InitialSwitch.jsx (1)
  • setSessionStore (41-46)
src/api/endpoints/chat.js (1)
  • data (31-31)
src/pages/shikshalokamChat.js (1)
  • setProfileId (38-38)
src/constants/session.js (2)
  • DEFAULT_COMPANY_SLUG (8-8)
  • DEFAULT_COMPANY_SLUG (8-8)
src/components/ToastMessage/TotastMessage.jsx (1)
  • Notification (6-23)
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/LoadingChat.jsx (1)
  • LoadingChat (1-8)
src/configure.js (2)
src/url.js (1)
  • ROUTES (1-26)
src/utils/index.js (2)
  • result (13-17)
  • getDomainDetail (3-22)
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/chat-message/ChatMessage.jsx (3)
src/pages/ai-creation/constants/mitra.constants.js (2)
  • CONVERSATION_USER_TYPES (7-10)
  • CONVERSATION_USER_TYPES (7-10)
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/chat-message/BotMessage.jsx (1)
  • BotMessage (7-57)
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/chat-message/UserMessage.jsx (1)
  • UserMessage (6-24)
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/ChatWindow.jsx (3)
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/DefineChallenge.jsx (1)
  • chatHistory (54-56)
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/ConversationWrapperCard.jsx (1)
  • containerRef (4-4)
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/LoadingChat.jsx (1)
  • LoadingChat (1-8)
src/pages/ai-creation/pages/shikshalokam-mitra/MainPage.jsx (5)
src/pages/ai-creation/constants/mitra.constants.js (2)
  • ACTIVE_TABS (1-5)
  • ACTIVE_TABS (1-5)
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/CommonFlow.jsx (1)
  • CommonFlow (14-219)
src/pages/ai-creation/constants/common.js (2)
  • LOADER_KEYS (1-11)
  • LOADER_KEYS (1-11)
src/configure.js (4)
  • bot_routes (22-42)
  • bot_routes (22-42)
  • FLOW_TYPES (45-50)
  • FLOW_TYPES (45-50)
src/i18n.js (2)
  • setLanguage (29-34)
  • setLanguage (29-34)
🔇 Additional comments (13)
src/configure.js (1)

1-159: LGTM!

The changes are purely stylistic (semicolon removal and quote consistency) with no functional impact on the configuration logic.

src/store/slices/chatData/state.js (1)

39-40: LGTM!

The new getStrandStep accessor follows the established pattern for state accessors in this slice and correctly exposes the existing strandStep state.

src/pages/ai-creation/pages/shikshalokam-mitra/MainPage.jsx (5)

1-28: LGTM!

The imports are well-organized, with the new StateMachineDefineChallenge component replacing the previous DefineChallenge, and the additional store imports (useChatDataSessionStore, useSiteDataLocalStore) are correctly added to support the new reset functionality.


100-114: LGTM!

The useEffect hooks correctly sync local state to the Zustand store. The store functions obtained from getState() are stable references (a standard Zustand pattern), so omitting them from dependency arrays is intentional and correct.


294-298: LGTM!

The StateMachineDefineChallenge component is correctly integrated with appropriate props for handling loader states, navigation, and scroll behavior.


453-463: LGTM!

The additional store reset calls for useChatDataSessionStore and useSiteDataLocalStore properly extend the session cleanup to include the new stores, following the established pattern.


30-98: Formatting changes look good.

State initialization and effect hooks have been reformatted for consistency without altering functionality.

src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/StateMachineDefineChallenge.jsx (4)

174-178: LGTM!

Proper cleanup of WebSocket connection on component unmount.


609-614: LGTM!

Clean utility function with sensible defaults for message creation.


494-494: The hardcoded bot_routes.mitra_create is intentional and correct. All TTS calls throughout the mitra creation flow (DefineChallenge.jsx, ai4bharat_services.js, and StateMachineDefineChallenge.jsx) consistently use bot_routes.mitra_create as the designated TTS endpoint, while state_machine_bot_route (define_challenges) is reserved for bot conversation. These routes serve different purposes and should not be interchangeable.


399-414: No changes needed. The code handles this correctly through message queuing.

When connectToWebSocket() is called, the WebSocket enters a CONNECTING state. The sendMessage() function has built-in logic (useChatWebhook.js line 76-78) that queues messages when the socket is in CONNECTING state. Once the connection opens, all queued messages are flushed in order (lines 25-29), preserving message sequence. Both the authenticate and text messages will be queued and sent in the correct order automatically.

Likely an incorrect or invalid review comment.

src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/chat-message/ChatMessage.jsx (1)

9-20: LGTM!

The component has been cleanly refactored with a reduced prop surface. The sanitization with DOMPurify is properly applied, and the conditional rendering based on user type is straightforward.

src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/ChatWindow.jsx (1)

100-109: LGTM!

Good use of the callback ref pattern to handle both internal containerRef and the forwarded scrollRef, with proper handling for both function and object ref types.

Comment thread src/constants/session.js
}; No newline at end of file
}

export const DEFAULT_COMPANY_SLUG = "shikshalokamstaging"

@coderabbitai coderabbitai Bot Jan 13, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

rg -n "DEFAULT_COMPANY_SLUG" --type=js --type=jsx -A 3 -B 1

Repository: ELEVATE-Project/mohini-app-frontend

Length of output: 106


🏁 Script executed:

rg -n "DEFAULT_COMPANY_SLUG" -A 3 -B 1

Repository: ELEVATE-Project/mohini-app-frontend

Length of output: 1722


🏁 Script executed:

rg -n "company.*slug|COMPANY.*SLUG" --type js -i

Repository: ELEVATE-Project/mohini-app-frontend

Length of output: 1615


🏁 Script executed:

sed -n '185,210p' src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/StateMachineDefineChallenge.jsx

Repository: ELEVATE-Project/mohini-app-frontend

Length of output: 877


🏁 Script executed:

rg -n "companyStore" src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/StateMachineDefineChallenge.jsx

Repository: ELEVATE-Project/mohini-app-frontend

Length of output: 61


🏁 Script executed:

sed -n '150,160p' src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/DefineChallenge.jsx

Repository: ELEVATE-Project/mohini-app-frontend

Length of output: 547


🏁 Script executed:

sed -n '395,435p' src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/DefineChallenge.jsx

Repository: ELEVATE-Project/mohini-app-frontend

Length of output: 1368


🏁 Script executed:

# Check if there are environment config files that might explain this
fd -e ".env" -e "*.config" | head -20

Repository: ELEVATE-Project/mohini-app-frontend

Length of output: 89


🏁 Script executed:

cat sample.env

Repository: ELEVATE-Project/mohini-app-frontend

Length of output: 164


🏁 Script executed:

# Check for any production or environment-specific config
find . -name ".env*" -o -name "*production*" -o -name "*staging*" | grep -v node_modules | head -20

Repository: ELEVATE-Project/mohini-app-frontend

Length of output: 61


🏁 Script executed:

# Check README and package.json for context about the project
head -50 README.md 2>/dev/null || echo "No README"
cat package.json | head -30

Repository: ELEVATE-Project/mohini-app-frontend

Length of output: 3263


Use the user's company slug instead of hardcoded staging value.

DEFAULT_COMPANY_SLUG is hardcoded to "shikshalokamstaging" and used unconditionally in StateMachineDefineChallenge.jsx (line 200) via getCompanyBotApi, even though the user's actual company slug is already fetched and available from the profile (line 187: setCompanyStore(data?.company?.slug)). This differs from similar code in DefineChallenge.jsx, which properly uses the staging slug only as a fallback when no profile exists. Update StateMachineDefineChallenge.jsx to use the company slug from the user profile instead of the hardcoded constant.

🤖 Prompt for AI Agents
In @src/constants/session.js at line 8, StateMachineDefineChallenge.jsx
currently uses the hardcoded DEFAULT_COMPANY_SLUG when calling getCompanyBotApi;
update it to use the company slug fetched into state (the value set by
setCompanyStore / profile data) and only fall back to DEFAULT_COMPANY_SLUG if
that state/profile value is missing. Locate the getCompanyBotApi call in
StateMachineDefineChallenge.jsx (around where
setCompanyStore(data?.company?.slug) is used) and pass the profile/companyStore
slug instead of DEFAULT_COMPANY_SLUG, ensuring the same fallback semantics as in
DefineChallenge.jsx.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

For SGCommon we have hardcoded the Company SLUG

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for SGCommon references in the codebase
rg -n "SGCommon" -C 3

# Also search for variations
rg -n -i "sg.common|sg_common" -C 2

Length of output: 4044


@VishnuKrishnathu, thank you for clarifying! I understand now that for the SG-Commons product, the company slug is intentionally hardcoded to "shikshalokamstaging" as part of the architectural design. I'll note this for future reference.

Comment on lines +243 to +250
if (!profileId && access_token) {
createUserProfile()
setShouldFetchIntro(true)
setIsStreamingComplete(true)
}
fetchCompanyBotInfo()
getSessionId()
}, [access_token, profileId])

@coderabbitai coderabbitai Bot Jan 13, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Uncoordinated async operations may cause race conditions.

createUserProfile, fetchCompanyBotInfo, and getSessionId run in parallel without coordination. If one fails and navigates away while others are still running, they may attempt state updates on an unmounted component.

Consider using an abort pattern or coordinating these calls.

Suggested fix with cleanup flag
   useEffect(() => {
+    let isMounted = true
+
     async function createUserProfile() {
       try {
         setIsLocalLoading(true)
         const data = await createUserProfileApi({ access_token }).then(resp => resp.profile_details)
+        if (!isMounted) return
         setProfileId(data?.id)
         setFirstName(data?.first_name)
         setCompanyStore(data?.company?.slug)
       } catch (error) {
         console.error(error?.response?.data || error)
+        if (!isMounted) return
         navigate(-1)
         clearMitraSessionStorage()
       } finally {
+        if (isMounted) setIsLocalLoading(false)
-        setIsLocalLoading(false)
       }
     }
     // ... similar changes for other async functions
+
+    return () => { isMounted = false }
   }, [access_token, profileId])
🤖 Prompt for AI Agents
In
@src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/StateMachineDefineChallenge.jsx
around lines 243 - 250, The three async calls createUserProfile(),
fetchCompanyBotInfo(), and getSessionId() are fired in parallel and can cause
state updates after unmount; coordinate them and add an abort/cleanup flag in
the useEffect so no setState or navigation happens if the effect is cleaned up.
Make createUserProfile, fetchCompanyBotInfo, and getSessionId return Promises
(if they don't already), then either await them sequentially or use
Promise.allSettled to observe results, wrap their state-setting calls
(setShouldFetchIntro, setIsStreamingComplete, any navigation) behind a check of
a local cancelled/isMounted flag, and implement the effect cleanup to set that
flag to true; also add try/catch around awaits to handle errors and avoid
unguarded state updates.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

This is existing code that already works. We'll note the issue and try once from our side, if valid we'll change the code in the next PR.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@VishnuKrishnathu, understood! I appreciate you noting the feedback. If you'd like, I can create a GitHub issue to track this for the future PR—just let me know. Otherwise, feel free to revisit it when convenient.


🧠 Learnings used
Learnt from: pinkman7009
Repo: ELEVATE-Project/mohini-app-frontend PR: 225
File: src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/InitialSwitch.jsx:79-89
Timestamp: 2026-01-14T02:51:09.584Z
Learning: In the AI creation flow components (InitialSwitch.jsx, CommonFlow.jsx), the pattern of using `pendingMessageRef` with a 100ms `setTimeout` after WebSocket authentication is intentionally used to ensure the authenticate message is sent before any user messages. This is an accepted implementation pattern for these flows.

Learnt from: pinkman7009
Repo: ELEVATE-Project/mohini-app-frontend PR: 218
File: src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/ActionItems.jsx:318-320
Timestamp: 2025-12-23T16:55:04.450Z
Learning: In ActionItems.jsx (src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/ActionItems.jsx), the action list is intentionally refetched every time the objective changes. The commented-out guard and the useEffect dependency on `objective` are part of the expected design for handling objective regeneration flows.

Comment thread src/utils/sorts.js
- Updated StateMachineDefineChallenge to ensure chat history is always an array before accessing its properties.
- Improved ChatWindow component to handle chat history checks more robustly.
- Added a safeguard in quickSort utility to return an empty array if the input is not an array, enhancing error handling.
@VishnuKrishnathu

Copy link
Copy Markdown
Author

@CodeRabbit review

@coderabbitai

coderabbitai Bot commented Jan 13, 2026

Copy link
Copy Markdown
✅ 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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🤖 Fix all issues with AI agents
In
@src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/ChatWindow.jsx:
- Around line 7-14: Several selectors use useAICreationSessionStore.getState()
which reads once and won't subscribe to updates, causing stale UI (e.g.,
objectiveList, allObjectiveChatHistory, selectedWeek, selectedFlowType,
errorText); change these to use the reactive selector form
useAICreationSessionStore(state => state.<property>) so the component subscribes
and re-renders on changes, and ensure derived getters return stable references
or use shallow equality if needed to avoid unnecessary re-renders (apply this to
objectiveList, allObjectiveChatHistory, selectedWeek, selectedFlowType,
errorText to match selectedObjective/selectedAction).

In
@src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/StateMachineDefineChallenge.jsx:
- Line 347: Remove the dead empty useEffect call by deleting the line containing
useEffect(() => {}, []) in StateMachineDefineChallenge (remove the no-op import
usage if it leaves useEffect unused); ensure no other logic depends on that hook
and run linter/tests to confirm no unused-import warnings.
- Around line 93-108: The code mutates an object from state by shallow-copying
the array via getChatHistory() then directly updating
chat_history[chat_history.length - 1].msg; instead, create a new array and
replace the last element with a new object to avoid mutating the original
reference: when the last item source === BOT and message?.msg exists, build a
newLast = { ...oldLast, msg: (oldLast.msg || "") + (message?.msg || ""),
updated_at: Date.now() } and produce newChatHistory = [...oldArray.slice(0, -1),
newLast] (or use map to return a new object for the last index), then call
setChatHistory(newChatHistory); keep the existing fields problemStatement,
shouldMoveForward, validation unchanged when constructing newLast.
- Around line 349-360: The useEffect in StateMachineDefineChallenge risks a
render loop because it depends on chatHistory and calls setChatHistory; modify
it to only call setChatHistory when the latest recording actually differs from
the existing recording on the last chat entry: compute const latestRecording =
recordings?.[recordings.length-1] and const currentLast =
getChatHistory()?.[getChatHistory().length-1], then if recordings?.length &&
currentLast?.source !== BOT && currentLast?.recording !== latestRecording,
create the updated array and call setChatHistory; remove the empty cleanup
return and narrow the dependency array to [recordings] (or [recordings,
getChatHistory] if getChatHistory is not stable) to avoid unnecessary triggers.
- Around line 551-559: The current useEffect mutates the last message object
directly after shallow-copying the array (chat_history) which risks shared-state
bugs; instead, locate the last index (e.g., const i = chat_history.length - 1),
create a new object for lastMessage via shallow copy and updated fields
(appendixURL and hasAppendix), assign that new object into chat_history[i], then
call setChatHistory(chat_history) and setAppendix([]); update references in the
useEffect block (appendix, chatHistory, getChatHistory, lastMessage,
setChatHistory, setAppendix) to follow this immutable update pattern.
- Around line 132-135: The callback uses the render-time stateMachineLength
value which can be stale; instead create a ref (e.g., stateMachineLengthRef)
that you update whenever stateMachineLength changes (via useEffect or inside the
setter) and read stateMachineLengthRef.current inside onWebSocketMessage when
calling getStrandStep and comparing to it; alternatively read the latest value
directly from the store inside the callback; then keep the same Number.isInteger
and setShouldMoveForward("yes") logic but use the fresh ref/store value instead
of the captured stateMachineLength.
- Around line 444-455: The code mutates the last message object via
lastMessage.msg += " " + sentence; instead, create immutable copies: build a new
message object (copying properties and updating msg) and replace the last
element in a new chat array before calling setChatHistory; reference the
variables/functions chat_history, getChatHistory(), chatHistory, BOT,
lastMessage, setChatHistory and mirror the non-mutating approach used in
onWebSocketMessage to avoid shallow-copy mutation.
🧹 Nitpick comments (7)
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/ChatWindow.jsx (2)

118-118: Consider using a stable unique identifier as the list key.

Using array index i as a key can cause issues with component state and reconciliation if chat messages are ever reordered, inserted, or removed from the middle of the list. Since each chat has an updated_at property used elsewhere as an identifier, consider using it as the key.

Suggested change
-          <li key={i} className={`div35 ${chat?.source === "user" ? "label1" : "label1"}`}>
+          <li key={chat?.updated_at ?? i} className={`div35 ${chat?.source === "user" ? "label1" : "label1"}`}>

127-127: Add optional chaining for chatHistory.length access.

chatHistory is accessed without optional chaining here. While chatsToShow guards its own iteration, if chatHistory becomes undefined between renders, this line would throw. For consistency with the defensive patterns used elsewhere in this component:

Suggested fix
-                isTalking={chat.source === "bot" && !isStreamingComplete && i === chatHistory.length - 1}
+                isTalking={chat.source === "bot" && !isStreamingComplete && i === chatHistory?.length - 1}
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/StateMachineDefineChallenge.jsx (5)

30-30: Move access_token retrieval into a useMemo or store it in state.

Reading from sessionStorage on every render is inefficient. Additionally, let should be const since the variable is never reassigned.

Suggested improvement
-  let access_token = sessionStorage.getItem(URL_PARAMS.ACCESS_TOKEN)
+  const access_token = useMemo(() => sessionStorage.getItem(URL_PARAMS.ACCESS_TOKEN), [])

Or store it in state if it needs to be reactive to changes.


49-49: Confusing state setter name.

The state variable is isMute but the setter is setNotMute, which inverts the expected naming convention. Consider renaming for clarity.

Suggested fix
-  const [isMute, setNotMute] = useState(true)
+  const [isMute, setIsMute] = useState(true)

Then update all usages of setNotMute to setIsMute.


159-172: Redundant nested try-catch.

The inner try-catch block at lines 161-165 is redundant since the outer catch block at lines 169-171 will handle any errors. This can be simplified.

Suggested simplification
 const handleOnStopSpeaking = async () => {
   try {
-    try {
-      if (audioRef.current) await audioRef.current.pause()
-    } catch (error) {
-      console.error({ error })
-    }
+    if (audioRef.current) await audioRef.current.pause()
     setHasOverRideId(null)
     setSentences([])
     setIsNextAllowed(true)
   } catch (error) {
     console.error({ error })
   }
 }

563-585: Same redundant nested try-catch pattern.

Apply the same simplification suggested for handleOnStopSpeaking.


399-414: WebSocket message ordering relies on implicit queueing behavior.

The code calls connectToWebSocket() followed by sendMessage() calls. When the socket is in CONNECTING state, messages are automatically queued in socketQueue (see useChatWebhook.js lines 76-78) and flushed in order when the connection opens (lines 25-29). This works correctly but the behavior is not obvious from the code. Consider adding a comment explaining that messages are queued during connection establishment.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 05f8836 and eb2f19f.

📒 Files selected for processing (3)
  • src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/StateMachineDefineChallenge.jsx
  • src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/ChatWindow.jsx
  • src/utils/sorts.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/utils/sorts.js
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-12-23T16:55:04.450Z
Learnt from: pinkman7009
Repo: ELEVATE-Project/mohini-app-frontend PR: 218
File: src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/ActionItems.jsx:318-320
Timestamp: 2025-12-23T16:55:04.450Z
Learning: In ActionItems.jsx (src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/ActionItems.jsx), the action list is intentionally refetched every time the objective changes. The commented-out guard and the useEffect dependency on `objective` are part of the expected design for handling objective regeneration flows.

Applied to files:

  • src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/StateMachineDefineChallenge.jsx
  • src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/ChatWindow.jsx
📚 Learning: 2026-01-11T21:08:05.729Z
Learnt from: pinkman7009
Repo: ELEVATE-Project/mohini-app-frontend PR: 223
File: src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/SelectObjective.jsx:416-439
Timestamp: 2026-01-11T21:08:05.729Z
Learning: In the SelectObjective.jsx component (src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/SelectObjective.jsx), objectives are guaranteed to have unique text values, so text-based equality comparison is safe for determining objective selection without risk of duplicate matches.

Applied to files:

  • src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/ChatWindow.jsx
🧬 Code graph analysis (2)
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/StateMachineDefineChallenge.jsx (10)
src/configure.js (2)
  • bot_routes (22-42)
  • bot_routes (22-42)
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/chat-message/ChatMessage.jsx (1)
  • CONVERSATION_USER_TYPES (7-7)
src/pages/ai-creation/pages/shikshalokam-mitra/MainPage.jsx (2)
  • chatHistory (56-56)
  • audioRef (87-87)
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/InitialSwitch.jsx (1)
  • setSessionStore (41-46)
src/hooks/useChatWebhook.js (3)
  • useChatWebhook (3-99)
  • useChatWebhook (3-99)
  • sendMessage (72-80)
src/api/endpoints/chat.js (1)
  • data (31-31)
src/pages/shikshalokamChat.js (1)
  • setProfileId (38-38)
src/constants/session.js (2)
  • DEFAULT_COMPANY_SLUG (8-8)
  • DEFAULT_COMPANY_SLUG (8-8)
src/components/ToastMessage/TotastMessage.jsx (1)
  • Notification (6-23)
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/LoadingChat.jsx (1)
  • LoadingChat (1-8)
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/ChatWindow.jsx (4)
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/StateMachineDefineChallenge.jsx (3)
  • chatHistory (32-32)
  • hasStartedListening (46-46)
  • isStreamingComplete (44-44)
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/DefineChallenge.jsx (3)
  • chatHistory (54-56)
  • hasStartedListening (62-62)
  • isStreamingComplete (60-60)
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/ConversationWrapperCard.jsx (1)
  • containerRef (4-4)
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/LoadingChat.jsx (1)
  • LoadingChat (1-8)
🔇 Additional comments (2)
src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/ChatWindow.jsx (1)

16-50: LGTM on the defensive array check.

The Array.isArray(chatHistory) guard at line 49 properly handles cases where chatHistory might not be an array, aligning with the PR's robustness improvements. The optional chaining throughout the function provides good defensive coding.

src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/StateMachineDefineChallenge.jsx (1)

587-614: LGTM - Clean render logic and well-designed helper.

The conditional rendering with loading states is appropriate. The createMessage helper with sensible defaults is a good pattern for consistent message creation.

Comment on lines +7 to +14
const objectiveList = useAICreationSessionStore.getState().getObjective()
const allObjectiveChatHistory = useAICreationSessionStore.getState().getObjectiveChatHistory()
const allActionListChatHistory = useAICreationSessionStore.getState().getActionListChatHistory()
const selectedObjective = useAICreationSessionStore(state => state.selectedObjective)
const selectedAction = useAICreationSessionStore(state => state.selectedAction)
const selectedWeek = useAICreationSessionStore.getState().getSelectedWeek()
const selectedFlowType = useAICreationSessionStore.getState().getSelectedFlowType()
const errorText = useAICreationSessionStore.getState().getErrorText()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Inconsistent store subscriptions may cause stale UI.

Lines 7-9 and 12-14 use getState() which reads state once without subscribing to changes. If objectiveList, allObjectiveChatHistory, selectedWeek, selectedFlowType, or errorText change in the store, this component won't re-render, causing the loading indicator logic in getShowLoadingChat to use stale values.

Lines 10-11 correctly use the subscription pattern. Apply the same pattern to the other selectors:

Suggested fix
-  const objectiveList = useAICreationSessionStore.getState().getObjective()
-  const allObjectiveChatHistory = useAICreationSessionStore.getState().getObjectiveChatHistory()
-  const allActionListChatHistory = useAICreationSessionStore.getState().getActionListChatHistory()
+  const objectiveList = useAICreationSessionStore(state => state.getObjective())
+  const allObjectiveChatHistory = useAICreationSessionStore(state => state.getObjectiveChatHistory())
+  const allActionListChatHistory = useAICreationSessionStore(state => state.getActionListChatHistory())
   const selectedObjective = useAICreationSessionStore(state => state.selectedObjective)
   const selectedAction = useAICreationSessionStore(state => state.selectedAction)
-  const selectedWeek = useAICreationSessionStore.getState().getSelectedWeek()
-  const selectedFlowType = useAICreationSessionStore.getState().getSelectedFlowType()
-  const errorText = useAICreationSessionStore.getState().getErrorText()
+  const selectedWeek = useAICreationSessionStore(state => state.getSelectedWeek())
+  const selectedFlowType = useAICreationSessionStore(state => state.getSelectedFlowType())
+  const errorText = useAICreationSessionStore(state => state.getErrorText())

Note: If the getter functions derive state from other store properties, ensure the selector returns a stable reference or use a shallow equality check to avoid unnecessary re-renders.

📝 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
const objectiveList = useAICreationSessionStore.getState().getObjective()
const allObjectiveChatHistory = useAICreationSessionStore.getState().getObjectiveChatHistory()
const allActionListChatHistory = useAICreationSessionStore.getState().getActionListChatHistory()
const selectedObjective = useAICreationSessionStore(state => state.selectedObjective)
const selectedAction = useAICreationSessionStore(state => state.selectedAction)
const selectedWeek = useAICreationSessionStore.getState().getSelectedWeek()
const selectedFlowType = useAICreationSessionStore.getState().getSelectedFlowType()
const errorText = useAICreationSessionStore.getState().getErrorText()
const objectiveList = useAICreationSessionStore(state => state.getObjective())
const allObjectiveChatHistory = useAICreationSessionStore(state => state.getObjectiveChatHistory())
const allActionListChatHistory = useAICreationSessionStore(state => state.getActionListChatHistory())
const selectedObjective = useAICreationSessionStore(state => state.selectedObjective)
const selectedAction = useAICreationSessionStore(state => state.selectedAction)
const selectedWeek = useAICreationSessionStore(state => state.getSelectedWeek())
const selectedFlowType = useAICreationSessionStore(state => state.getSelectedFlowType())
const errorText = useAICreationSessionStore(state => state.getErrorText())
🤖 Prompt for AI Agents
In
@src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/components/ChatWindow.jsx
around lines 7 - 14, Several selectors use useAICreationSessionStore.getState()
which reads once and won't subscribe to updates, causing stale UI (e.g.,
objectiveList, allObjectiveChatHistory, selectedWeek, selectedFlowType,
errorText); change these to use the reactive selector form
useAICreationSessionStore(state => state.<property>) so the component subscribes
and re-renders on changes, and ensure derived getters return stable references
or use shallow equality if needed to avoid unnecessary re-renders (apply this to
objectiveList, allObjectiveChatHistory, selectedWeek, selectedFlowType,
errorText to match selectedObjective/selectedAction).

Comment on lines +444 to +455
const chat_history = [...getChatHistory()]
if (chatHistory[chatHistory?.length - 1]?.source === BOT) {
const lastMessage = chat_history[chat_history?.length - 1]
lastMessage.msg += " " + sentence
setChatHistory(chat_history)
} else {
chat_history.push({
msg: sentence,
source: BOT,
})
setChatHistory(chat_history)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Object mutation through shallow copy (same issue as earlier).

lastMessage.msg += " " + sentence mutates the original object. Apply the same fix as suggested for onWebSocketMessage.

Suggested fix
     const chat_history = [...getChatHistory()]
     if (chatHistory[chatHistory?.length - 1]?.source === BOT) {
-      const lastMessage = chat_history[chat_history?.length - 1]
-      lastMessage.msg += " " + sentence
+      chat_history[chat_history.length - 1] = {
+        ...chat_history[chat_history.length - 1],
+        msg: chat_history[chat_history.length - 1].msg + " " + sentence,
+      }
       setChatHistory(chat_history)
     } else {
📝 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
const chat_history = [...getChatHistory()]
if (chatHistory[chatHistory?.length - 1]?.source === BOT) {
const lastMessage = chat_history[chat_history?.length - 1]
lastMessage.msg += " " + sentence
setChatHistory(chat_history)
} else {
chat_history.push({
msg: sentence,
source: BOT,
})
setChatHistory(chat_history)
}
const chat_history = [...getChatHistory()]
if (chatHistory[chatHistory?.length - 1]?.source === BOT) {
chat_history[chat_history.length - 1] = {
...chat_history[chat_history.length - 1],
msg: chat_history[chat_history.length - 1].msg + " " + sentence,
}
setChatHistory(chat_history)
} else {
chat_history.push({
msg: sentence,
source: BOT,
})
setChatHistory(chat_history)
}
🤖 Prompt for AI Agents
In
@src/pages/ai-creation/pages/shikshalokam-mitra/mitra-pages/StateMachineDefineChallenge.jsx
around lines 444 - 455, The code mutates the last message object via
lastMessage.msg += " " + sentence; instead, create immutable copies: build a new
message object (copying properties and updating msg) and replace the last
element in a new chat array before calling setChatHistory; reference the
variables/functions chat_history, getChatHistory(), chatHistory, BOT,
lastMessage, setChatHistory and mirror the non-mutating approach used in
onWebSocketMessage to avoid shallow-copy mutation.

- Enhanced readability by reorganizing imports and formatting code.
- Updated loading chat logic to ensure proper handling of chat history and loading states.
- Streamlined the use of hooks and conditional rendering for better performance and maintainability.
- Reorganized imports for improved readability and consistency.
- Streamlined state initialization and effect hooks for better performance.
- Enhanced loading state handling and conditional rendering logic.
- Improved overall code clarity and maintainability.
- Reorganized imports for better clarity and consistency.
- Enhanced formatting of the ChatMessage function for improved readability.
- Streamlined conditional rendering for BotMessage and UserMessage components.
- Ensured consistent use of semicolons and code style throughout the file.
…ement

- Added a getter for stateMachineLength in the chat data store for better state access.
- Updated StateMachineDefineChallenge to utilize the new getter, enhancing clarity and maintainability.
- Improved conditional logic by using the retrieved stateMachineLength value directly.
@VishnuKrishnathu

Copy link
Copy Markdown
Author

@CodeRabbit review

@coderabbitai

coderabbitai Bot commented Jan 14, 2026

Copy link
Copy Markdown
✅ 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.

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.

2 participants