Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions echo/frontend/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ VITE_ENABLE_CONVERSATION_HEALTH=0
# Set to "1" to enable webhook configuration in project settings
VITE_ENABLE_WEBHOOKS=0

# Agentic Chat Feature
# Set to "1" to enable the Agentic chat mode in the chat interface
VITE_ENABLE_AGENTIC_CHAT=0

# Other environment variables can be found in src/config.ts
# Examples:
# VITE_USE_PARTICIPANT_ROUTER=1
Expand Down
25 changes: 14 additions & 11 deletions echo/frontend/src/components/chat/ChatModeSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
IconSparkles,
} from "@tabler/icons-react";
import { useState } from "react";
import { ENABLE_AGENTIC_CHAT } from "@/config";
import { analytics } from "@/lib/analytics";
import { AnalyticsEvents as events } from "@/lib/analyticsEvents";
import type { ChatMode } from "@/lib/api";
Expand Down Expand Up @@ -269,17 +270,19 @@ export const ChatModeSelector = ({

{/* Mode Cards */}
<Stack gap="lg">
<ModeCard
mode="agentic"
title={t`Agentic`}
subtitle={t`Delegate multi-step analysis with live tool execution`}
examples={getAgenticExamples()}
icon={IconSparkles}
isBeta
selectedMode={selectedMode}
isLoading={isLoading}
onSelectMode={handleSelectMode}
/>
{ENABLE_AGENTIC_CHAT && (
<ModeCard
mode="agentic"
title={t`Agentic`}
subtitle={t`Delegate multi-step analysis with live tool execution`}
examples={getAgenticExamples()}
icon={IconSparkles}
isBeta
selectedMode={selectedMode}
isLoading={isLoading}
onSelectMode={handleSelectMode}
/>
)}

<ModeCard
mode="deep_dive"
Expand Down
2 changes: 2 additions & 0 deletions echo/frontend/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,5 @@ export const ENABLE_CONVERSATION_HEALTH = true;
export const ENABLE_ANNOUNCEMENTS = true;
export const ENABLE_DISPLAY_CONVERSATION_LINKS = true;
export const ENABLE_WEBHOOKS = true;
export const ENABLE_AGENTIC_CHAT =
import.meta.env.VITE_ENABLE_AGENTIC_CHAT === "1";
18 changes: 11 additions & 7 deletions echo/frontend/src/routes/project/chat/ProjectChatRoute.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ import {
import { useQueryClient } from "@tanstack/react-query";
import { useEffect, useMemo, useRef, useState } from "react";
import { useParams } from "react-router";
import { AgenticChatPanel } from "@/components/chat/AgenticChatPanel";
import {
ChatAccordionItemMenu,
ChatModeIndicator,
} from "@/components/chat/ChatAccordion";
import { AgenticChatPanel } from "@/components/chat/AgenticChatPanel";
import { ChatContextProgress } from "@/components/chat/ChatContextProgress";
import { ChatHistoryMessage } from "@/components/chat/ChatHistoryMessage";
import { ChatMessage } from "@/components/chat/ChatMessage";
Expand Down Expand Up @@ -57,7 +57,11 @@ import { ScrollToBottomButton } from "@/components/common/ScrollToBottom";
import { toast } from "@/components/common/Toaster";
import { ConversationLinks } from "@/components/conversation/ConversationLinks";
import { useConversationsCountByProjectId } from "@/components/conversation/hooks";
import { API_BASE_URL, ENABLE_CHAT_AUTO_SELECT } from "@/config";
import {
API_BASE_URL,
ENABLE_AGENTIC_CHAT,
ENABLE_CHAT_AUTO_SELECT,
} from "@/config";
import { useElementOnScreen } from "@/hooks/useElementOnScreen";
import { useLanguage } from "@/hooks/useLanguage";
import { useLoadNotification } from "@/hooks/useLoadNotification";
Expand Down Expand Up @@ -498,8 +502,10 @@ export const ProjectChatRoute = () => {
);
}

if (chatMode === "agentic") {
return <AgenticChatPanel chatId={chatId ?? ""} projectId={projectId ?? ""} />;
if (ENABLE_AGENTIC_CHAT && chatMode === "agentic") {
return (
<AgenticChatPanel chatId={chatId ?? ""} projectId={projectId ?? ""} />
);
}
Comment on lines +505 to 509
Copy link
Contributor

@coderabbitai coderabbitai bot Mar 9, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for agentic mode validation in backend chat endpoints
rg -n -C3 'agentic' --type py

Repository: Dembrane/echo

Length of output: 50369


🏁 Script executed:

# Search for ENABLE_AGENTIC_CHAT in frontend
rg -n "ENABLE_AGENTIC_CHAT" echo/frontend/src --type ts --type tsx

Repository: Dembrane/echo

Length of output: 84


🏁 Script executed:

# Look at ProjectChatRoute.tsx around the mentioned lines
fd "ProjectChatRoute.tsx" echo/frontend/src --exec head -550 {} \; --exec tail -100 {} \;

Repository: Dembrane/echo

Length of output: 18767


🏁 Script executed:

# Search for shouldFetchSuggestions and ChatModeIndicator
rg -n "shouldFetchSuggestions|ChatModeIndicator" echo/frontend/src --type ts --type tsx -A 2

Repository: Dembrane/echo

Length of output: 84


🏁 Script executed:

# Search for ChatModeSelector to understand mode reset flow
rg -n "ChatModeSelector" echo/frontend/src --type ts --context 3

Repository: Dembrane/echo

Length of output: 8938


🏁 Script executed:

# Check if there's any ENABLE_AGENTIC_CHAT config definition and usage
rg -n "ENABLE_AGENTIC_CHAT" echo/frontend --type ts --context 2

Repository: Dembrane/echo

Length of output: 2151


🏁 Script executed:

# Look for any fallback or error handling for disabled agentic mode
rg -n "agentic" echo/frontend/src/routes/project/chat/ProjectChatRoute -A 3 -B 3

Repository: Dembrane/echo

Length of output: 151


🏁 Script executed:

# Final check: verify ChatModeSelector properly filters agentic option
rg -n "ENABLE_AGENTIC_CHAT" echo/frontend/src/components/chat/ChatModeSelector.tsx -A 5 -B 2

Repository: Dembrane/echo

Length of output: 734


Add fallback when agentic flag disabled but mode persists in DB

When ENABLE_AGENTIC_CHAT is false but chatMode === "agentic" lingers in the database, users hit an inconsistent state: the ChatModeIndicator displays the "agentic" badge (line 523), but shouldFetchSuggestions stays false (line 338 checks !isAgenticMode), and they get the normal chat interface instead of the agentic panel. Graceful fallback is warranted.

The proposed approach—showing the ChatModeSelector when the flag is disabled but the mode is agentic—mirrors the existing pattern at lines 487-495 and gives users a path to re-select their mode.

Suggested implementation
-	if (ENABLE_AGENTIC_CHAT && chatMode === "agentic") {
+	if (chatMode === "agentic") {
+		if (!ENABLE_AGENTIC_CHAT) {
+			// Agentic mode disabled - treat as unselected to let user re-pick
+			return (
+				<Box className="flex min-h-full items-center justify-center px-2 pr-4">
+					<ChatModeSelector
+						chatId={chatId ?? ""}
+						projectId={projectId ?? ""}
+						onModeSelected={async (mode) => {
+							if (chatId && mode === "overview") {
+								prefetchSuggestions(chatId, language, 5000);
+							}
+							chatContextQuery.refetch();
+						}}
+					/>
+				</Box>
+			);
+		}
 		return (
 			<AgenticChatPanel chatId={chatId ?? ""} projectId={projectId ?? ""} />
 		);
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@echo/frontend/src/routes/project/chat/ProjectChatRoute.tsx` around lines 505
- 509, When ENABLE_AGENTIC_CHAT is false but chatMode === "agentic" remains in
the DB, add a graceful fallback in ProjectChatRoute: detect this mismatch (use
ENABLE_AGENTIC_CHAT, chatMode or isAgenticMode) and render the ChatModeSelector
(same pattern used around the existing conditional that renders ChatModeSelector
at lines ~487-495) instead of the normal chat UI so users can re-select mode;
ensure ChatModeIndicator can still show the badge but shouldFetchSuggestions
logic (which depends on isAgenticMode) will remain consistent and
AgenticChatPanel is only rendered when ENABLE_AGENTIC_CHAT is true and chatMode
is agentic.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not applicable...the feature hasn't shipped yet, so no chats with chat_mode = "agentic" exist in any database.

Copy link
Contributor

Choose a reason for hiding this comment

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

@ussaama Fair enough — since no agentic chats exist in any DB yet, the DB-state mismatch scenario is purely theoretical at this point. The feature flag gate is clean for a pre-ship rollout. Ship it! 🚀


🧠 Learnings used
Learnt from: CR
Repo: Dembrane/echo PR: 0
File: echo/frontend/AGENTS.md:0-0
Timestamp: 2026-02-13T09:29:08.011Z
Learning: Applies to echo/frontend/src/components/chat/**/*.{ts,tsx} : Chat mode colors are intentionally hardcoded (not theme-dependent) for consistent mode identification

Learnt from: CR
Repo: Dembrane/echo PR: 0
File: echo/frontend/AGENTS.md:0-0
Timestamp: 2026-02-13T09:29:08.011Z
Learning: Applies to echo/frontend/src/components/chat/**/*.{ts,tsx} : Chat modes have dedicated accent colors defined in `src/components/chat/ChatModeSelector.tsx` (`MODE_COLORS`): Overview mode Spring Green (`#1EFFA1`), Deep Dive mode Cyan (`#00FFFF`)

Learnt from: ussaama
Repo: Dembrane/echo PR: 266
File: echo/frontend/src/components/conversation/ConversationAccordion.tsx:675-678
Timestamp: 2025-08-19T10:22:55.323Z
Learning: In echo/frontend/src/components/conversation/hooks/index.ts, the useConversationsCountByProjectId hook uses regular useQuery (not useSuspenseQuery), which means conversationsCountQuery.data can be undefined during loading states. When using Number(conversationsCountQuery.data) ?? 0, this creates NaN because Number(undefined) = NaN and NaN is not nullish, so the fallback doesn't apply. The correct pattern is Number(conversationsCountQuery.data ?? 0) to ensure the fallback happens before type conversion.

Learnt from: CR
Repo: Dembrane/echo PR: 0
File: echo/server/AGENTS.md:0-0
Timestamp: 2026-01-22T22:41:14.702Z
Learning: Applies to echo/server/dembrane/api/chat.py : Fill module stub, add RAG shortcut when quotes exist, implement Directus project fetch, conversation endpoint completion, admin auth checks (TODOs in `dembrane/api/chat.py`)

Learnt from: ussaama
Repo: Dembrane/echo PR: 205
File: echo/frontend/src/lib/query.ts:1444-1506
Timestamp: 2025-07-10T12:48:20.683Z
Learning: ussaama prefers string concatenation over template literals for simple cases where readability is clearer, even when linting tools suggest template literals. Human readability takes precedence over strict linting rules in straightforward concatenation scenarios.


return (
Expand Down Expand Up @@ -791,9 +797,7 @@ export const ProjectChatRoute = () => {
}}
rightSection={<IconSend size={24} />}
disabled={
normalizedInput.trim() === "" ||
isLoading ||
isSubmitting
normalizedInput.trim() === "" || isLoading || isSubmitting
}
{...testId("chat-send-button")}
>
Expand Down
Loading