Skip to content

Conversation

@connor-tyndall
Copy link
Contributor

@connor-tyndall connor-tyndall commented Jan 11, 2026

Summary

  • Auto-resume conversations: When opening the chat panel, automatically loads and resumes the most recent conversation for that project
  • New Chat button: Added UI button to start fresh conversations when desired
  • Backend resume support: Added resume WebSocket message type and skip_greeting parameter to avoid repeating the greeting on reconnect
  • Updated greeting: Now mentions feature management capabilities (create, edit, delete, reorder)
  • README updates: Documented the Project Assistant feature and conversation persistence

Changes

  • ui/src/hooks/useAssistantChat.ts: Added conversation fetching, persistence, and resume logic
  • ui/src/components/AssistantChat.tsx: Added "New Chat" button and loading states
  • server/routers/assistant_chat.py: Added resume message type handler
  • server/services/assistant_chat_session.py: Added skip_greeting parameter to start()
  • README.md: Documented Project Assistant and added feature MCP tools

Test plan

  • Open chat panel → should load previous conversation if exists
  • Navigate away and back → conversation should persist (no new greeting)
  • Click "New Chat" → should start fresh conversation with greeting
  • Send messages in resumed conversation → should work normally

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added Project Assistant: AI-powered chat interface for exploring codebases and managing features with conversation persistence.
    • Introduced conversation history: resume previous conversations or start fresh chat sessions via New Chat button.
    • Enhanced UI with loading indicators for historical conversations.
  • Documentation

    • Updated documentation to reflect Project Assistant capabilities and session structure.

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

- Auto-resume most recent conversation when opening chat panel
- Add "New Chat" button to start fresh conversations
- Add "resume" WebSocket message type for reconnecting without greeting
- Add skip_greeting parameter to session.start() for resumed conversations
- Update greeting message to reflect feature management capabilities
- Store conversations in assistant.db with full message history
- Update README with Project Assistant documentation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@coderabbitai
Copy link

coderabbitai bot commented Jan 11, 2026

📝 Walkthrough

Walkthrough

The changes introduce a new Project Assistant feature enabling conversation history management. The backend adds support for resuming conversations via a new WebSocket "resume" message type and optional skip_greeting parameter, while the frontend adds UI components for viewing conversation history, switching between conversations, and explicitly starting new chats. README documentation is updated accordingly.

Changes

Cohort / File(s) Summary
Documentation
README.md
Added "Project Assistant" feature overview, MCP server feature management tools (feature_create, feature_update, feature_delete), assistant capabilities, conversation persistence mechanism (assistant.db), and updated project structure/layout examples.
Backend: Conversation Resume & Session
server/routers/assistant_chat.py, server/services/assistant_chat_session.py
Introduced new WebSocket "resume" message type to reconnect to existing conversations; modified start() method signature to accept skip_greeting: bool parameter; greeting is now conditionally sent based on skip_greeting flag; greeting content updated to reflect expanded feature management capabilities.
Frontend: Chat UI & Conversation Management
ui/src/components/AssistantChat.tsx, ui/src/hooks/useAssistantChat.ts
Added conversation history loading and management; replaced auto-resume on mount with explicit user-triggered "New Chat" button; introduced startNewConversation(), switchConversation(), and refreshConversations() methods; exposed new public API including conversations, isLoadingHistory, and conversation switching capabilities; refactored input handling and connection-state checks.

Sequence Diagram

sequenceDiagram
    participant UI as UI Component
    participant Hook as useAssistantChat Hook
    participant WS as WebSocket Router
    participant Session as AssistantChatSession
    participant DB as Backend (History)

    UI->>Hook: Mount component
    Hook->>DB: Fetch conversation history
    DB-->>Hook: Return conversations (sorted by updated_at)
    Hook->>Hook: Load messages from most recent conversation
    
    alt Has Previous Messages
        Hook->>WS: Send resume message (conversation_id, skip_greeting=true)
        WS->>Session: Create session with skip_greeting=true
        Session->>Session: Start without greeting
        Session-->>WS: Stream message chunks
        WS-->>Hook: Receive streamed content
    else No Previous Messages
        Hook->>WS: Send start message
        WS->>Session: Create new session
        Session->>Session: Start with greeting (skip_greeting=false)
        Session-->>WS: Stream greeting + chunks
        WS-->>Hook: Receive greeting and content
    end
    
    Hook-->>UI: Update state (messages, conversations)
    UI-->>UI: Render chat interface with New Chat button

    alt User Clicks "New Chat"
        UI->>Hook: Call startNewConversation()
        Hook->>Hook: Reset chat state
        Hook->>WS: Send start message (new conversation)
    else User Switches Conversation
        UI->>Hook: Call switchConversation(conversationId)
        Hook->>Hook: Load selected conversation messages
        Hook->>WS: Send resume/start based on message existence
    end
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 Resuming tales from yesterday's burrow,
Where conversations need not borrow,
Skip the greeting, recall the chat—
The Assistant remembers where we sat!
New conversations hop with glee,
Yet history keeps you company! 🌙

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: adding persistence and conversation management for the assistant chat feature across multiple files and layers.

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

✨ Finishing touches
  • 📝 Generate docstrings

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

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: 5

🤖 Fix all issues with AI agents
In @README.md:
- Around line 111-123: Update the Project Assistant capabilities text in
README.md to accurately list only the supported operations (create and skip)
instead of "Create, edit, delete, and reorder features", and make the same
change to the assistant greeting text defined in the AssistantChatSession
implementation so both UX text and backend greeting match; locate the assistant
greeting string in the AssistantChatSession class (the method that composes the
initial/system prompt) and remove references to edit/delete/reorder, replacing
them with the correct "create and skip" wording.

In @server/routers/assistant_chat.py:
- Around line 291-315: The resume handler fails to validate conversation_id and
may call create_session with None; before calling create_session in the "resume"
branch, check that message.get("conversation_id") returns a non-empty
string/UUID and if missing/invalid, log a warning and send a websocket error
JSON (type:"error", content:"Missing or invalid conversation_id for resume") and
skip create_session; otherwise proceed to call
create_session(conversation_id=conversation_id) and keep the existing try/except
logic around session.start and websocket.send_json.

In @server/services/assistant_chat_session.py:
- Around line 273-285: The greeting text in the initial message (the local
variable greeting in the assistant_chat_session.py initial send block) is
inaccurate about feature management; update the string so it reflects only the
implemented operations (feature_create, feature_create_bulk, and feature_skip) —
e.g. change "manage features (create, edit, delete, reorder)" to "manage
features (create and deprioritize (skip))" or similar, and ensure the same
corrected string is what is passed to add_message(self.project_dir,
self.conversation_id, "assistant", greeting) and yielded to the client.

In @ui/src/hooks/useAssistantChat.ts:
- Around line 409-439: The retry loop in resumeConversation can leak timeouts
and touch stale wsRef.current after unmount; create a ref (e.g.,
resumeTimeoutRef via useRef<number | null>) to store the timeout id,
clearTimeout(resumeTimeoutRef.current) before scheduling a new setTimeout in
checkAndResume and when sending the resume, and ensure you clear it in a
useEffect cleanup (component unmount) so checkAndResume never runs against an
unmounted component; reference the existing symbols resumeConversation, connect,
wsRef, checkAndResume, maxRetries and retryCount when adding/clearing the
timeout ref.
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b1473cd and b6ddaff.

📒 Files selected for processing (6)
  • README.md
  • server/routers/assistant_chat.py
  • server/services/assistant_chat_session.py
  • start_ui.sh
  • ui/src/components/AssistantChat.tsx
  • ui/src/hooks/useAssistantChat.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Use SQLite with SQLAlchemy ORM for database access and feature management

Files:

  • server/services/assistant_chat_session.py
  • server/routers/assistant_chat.py
ui/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

ui/src/**/*.{ts,tsx}: Use TypeScript for React components in the UI (React 18 with TypeScript)
Use React Query (TanStack Query) for API calls and data fetching in the UI
Use Radix UI for component primitives in the React UI
Run ESLint to lint React UI code

Files:

  • ui/src/hooks/useAssistantChat.ts
  • ui/src/components/AssistantChat.tsx
server/routers/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Use FastAPI for REST API endpoints in the server/routers/ directory

Files:

  • server/routers/assistant_chat.py
🧠 Learnings (5)
📚 Learning: 2026-01-10T08:23:04.012Z
Learnt from: CR
Repo: leonvanzyl/autocoder PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T08:23:04.012Z
Learning: Applies to mcp_server/**/*.py : Use MCP (Model Context Protocol) servers for agent tools: feature_mcp.py for feature management, with tools: feature_get_stats, feature_get_next, feature_get_for_regression, feature_mark_passing, feature_skip, feature_create_bulk

Applied to files:

  • README.md
📚 Learning: 2026-01-10T08:23:04.012Z
Learnt from: CR
Repo: leonvanzyl/autocoder PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T08:23:04.012Z
Learning: Two-agent pattern: Initializer Agent reads app spec and creates features in first session; Coding Agent implements features one by one in subsequent sessions

Applied to files:

  • README.md
📚 Learning: 2026-01-10T08:23:04.012Z
Learnt from: CR
Repo: leonvanzyl/autocoder PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T08:23:04.012Z
Learning: Applies to server/routers/**/*.py : Use FastAPI for REST API endpoints in the server/routers/ directory

Applied to files:

  • README.md
📚 Learning: 2026-01-10T08:23:04.012Z
Learnt from: CR
Repo: leonvanzyl/autocoder PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T08:23:04.012Z
Learning: Applies to ui/src/styles/**/*.css : React UI custom animations: animate-slide-in, animate-pulse-neo, animate-shimmer

Applied to files:

  • ui/src/components/AssistantChat.tsx
📚 Learning: 2026-01-10T08:23:04.012Z
Learnt from: CR
Repo: leonvanzyl/autocoder PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-10T08:23:04.012Z
Learning: Applies to ui/src/styles/**/*.css : React UI uses neobrutalism design system with CSS variables for color tokens: --color-neo-pending (yellow), --color-neo-progress (cyan), --color-neo-done (green)

Applied to files:

  • ui/src/components/AssistantChat.tsx
🧬 Code graph analysis (4)
server/services/assistant_chat_session.py (1)
server/services/assistant_database.py (1)
  • add_message (162-196)
ui/src/hooks/useAssistantChat.ts (3)
ui/src/lib/types.ts (2)
  • AssistantConversation (238-245)
  • ChatMessage (224-232)
ui/src/lib/api.ts (2)
  • listAssistantConversations (253-257)
  • getAssistantConversation (259-266)
server/services/assistant_chat_session.py (1)
  • start (194-285)
server/routers/assistant_chat.py (1)
server/services/assistant_chat_session.py (2)
  • create_session (377-403)
  • start (194-285)
ui/src/components/AssistantChat.tsx (1)
ui/src/hooks/useAssistantChat.ts (1)
  • useAssistantChat (46-523)
🔇 Additional comments (9)
server/services/assistant_chat_session.py (1)

194-194: LGTM!

The skip_greeting parameter addition is correctly documented and defaults to False to preserve backward compatibility.

Also applies to: 201-202

ui/src/components/AssistantChat.tsx (3)

28-38: LGTM!

The hook integration correctly uses the new isLoadingHistory and startNewConversation exports from the updated useAssistantChat hook.


98-106: LGTM!

The "New Chat" button is well-implemented with proper disabled states, accessibility attributes, and clear visual feedback.


113-125: LGTM!

The loading states are well-ordered: isLoadingHistory takes precedence over isLoading, providing clear feedback when fetching conversation history versus waiting for assistant responses.

ui/src/hooks/useAssistantChat.ts (5)

89-102: LGTM!

The refreshConversations function correctly fetches and sorts conversations. Error handling logs failures without disrupting the UI, which is appropriate for a background refresh operation.


105-122: LGTM!

The loadConversationMessages function properly transforms backend messages to the UI format and handles errors gracefully with an empty array fallback.


442-460: LGTM!

The switchConversation function correctly manages the loading state and conditionally resumes or starts based on whether the conversation has existing messages.


463-506: LGTM!

The initialization effect is well-structured with proper error handling and fallback behavior. The hasInitializedRef guard prevents duplicate initialization, and the loading state is correctly managed in the finally block.


26-40: LGTM!

The UseAssistantChatReturn interface correctly reflects all new exports while maintaining the start method for backward compatibility.

README.md Outdated
Comment on lines 107 to 109
- `feature_create` - Create a single feature
- `feature_update` - Edit feature details
- `feature_delete` - Remove a feature
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Documentation inconsistent with implementation.

The README lists feature_update and feature_delete as available MCP tools, but these tools are not included in the ASSISTANT_FEATURE_TOOLS list in server/services/assistant_chat_session.py (lines 48-62). Only feature_create, feature_create_bulk, and feature_skip are actually available.

Based on the implementation in server/services/assistant_chat_session.py, the actual tools are:

  • feature_create - Create a single feature
  • feature_create_bulk - Initialize all features
  • feature_skip - Move feature to end of queue

Comment on lines 111 to 123
### Project Assistant

The Web UI includes a **Project Assistant** - an AI-powered chat interface for each project. Click the chat button in the bottom-right corner to open it.

**Capabilities:**
- **Explore the codebase** - Ask questions about files, architecture, and implementation details
- **Manage features** - Create, edit, delete, and reorder features via natural language
- **Get feature details** - Ask about specific features, their status, and test steps

**Conversation Persistence:**
- Conversations are automatically saved to `assistant.db` in each project directory
- When you navigate away and return, your conversation resumes where you left off
- Click "New Chat" to start a fresh conversation
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Capabilities documentation overstates actual features.

Line 118 claims the assistant can "Create, edit, delete, and reorder features" but the implementation only supports create and skip operations. This aligns with the same issue found in the greeting text (server/services/assistant_chat_session.py line 276).

🤖 Prompt for AI Agents
In @README.md around lines 111 - 123, Update the Project Assistant capabilities
text in README.md to accurately list only the supported operations (create and
skip) instead of "Create, edit, delete, and reorder features", and make the same
change to the assistant greeting text defined in the AssistantChatSession
implementation so both UX text and backend greeting match; locate the assistant
greeting string in the AssistantChatSession class (the method that composes the
initial/system prompt) and remove references to edit/delete/reorder, replacing
them with the correct "create and skip" wording.

Comment on lines 291 to 315
elif msg_type == "resume":
# Resume an existing conversation without sending greeting
conversation_id = message.get("conversation_id")

try:
# Create session
session = await create_session(
project_name,
project_dir,
conversation_id=conversation_id,
)
# Initialize but skip the greeting
async for chunk in session.start(skip_greeting=True):
await websocket.send_json(chunk)
# Confirm we're ready
await websocket.send_json({
"type": "conversation_created",
"conversation_id": conversation_id,
})
except Exception as e:
logger.exception(f"Error resuming assistant session for {project_name}")
await websocket.send_json({
"type": "error",
"content": f"Failed to resume session: {str(e)}"
})
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Validate conversation_id before resuming.

The resume message handler does not validate that conversation_id is provided. If a client sends {"type": "resume"} without a conversation_id, this will pass None to create_session, which could create unintended behavior (a new conversation instead of resuming).

🛡️ Proposed validation
 elif msg_type == "resume":
     # Resume an existing conversation without sending greeting
     conversation_id = message.get("conversation_id")
+
+    if conversation_id is None:
+        await websocket.send_json({
+            "type": "error",
+            "content": "conversation_id is required for resume"
+        })
+        continue

     try:
         # Create session
📝 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
elif msg_type == "resume":
# Resume an existing conversation without sending greeting
conversation_id = message.get("conversation_id")
try:
# Create session
session = await create_session(
project_name,
project_dir,
conversation_id=conversation_id,
)
# Initialize but skip the greeting
async for chunk in session.start(skip_greeting=True):
await websocket.send_json(chunk)
# Confirm we're ready
await websocket.send_json({
"type": "conversation_created",
"conversation_id": conversation_id,
})
except Exception as e:
logger.exception(f"Error resuming assistant session for {project_name}")
await websocket.send_json({
"type": "error",
"content": f"Failed to resume session: {str(e)}"
})
elif msg_type == "resume":
# Resume an existing conversation without sending greeting
conversation_id = message.get("conversation_id")
if conversation_id is None:
await websocket.send_json({
"type": "error",
"content": "conversation_id is required for resume"
})
continue
try:
# Create session
session = await create_session(
project_name,
project_dir,
conversation_id=conversation_id,
)
# Initialize but skip the greeting
async for chunk in session.start(skip_greeting=True):
await websocket.send_json(chunk)
# Confirm we're ready
await websocket.send_json({
"type": "conversation_created",
"conversation_id": conversation_id,
})
except Exception as e:
logger.exception(f"Error resuming assistant session for {project_name}")
await websocket.send_json({
"type": "error",
"content": f"Failed to resume session: {str(e)}"
})
🤖 Prompt for AI Agents
In @server/routers/assistant_chat.py around lines 291 - 315, The resume handler
fails to validate conversation_id and may call create_session with None; before
calling create_session in the "resume" branch, check that
message.get("conversation_id") returns a non-empty string/UUID and if
missing/invalid, log a warning and send a websocket error JSON (type:"error",
content:"Missing or invalid conversation_id for resume") and skip
create_session; otherwise proceed to call
create_session(conversation_id=conversation_id) and keep the existing try/except
logic around session.start and websocket.send_json.

Comment on lines 273 to 285
# Send initial greeting (unless resuming)
if not skip_greeting:
try:
greeting = f"Hello! I'm your project assistant for **{self.project_name}**. I can help you understand the codebase, manage features (create, edit, delete, reorder), and answer questions about the project. What would you like to do?"

# Store the greeting in the database
add_message(self.project_dir, self.conversation_id, "assistant", greeting)
# Store the greeting in the database
add_message(self.project_dir, self.conversation_id, "assistant", greeting)

yield {"type": "text", "content": greeting}
yield {"type": "response_done"}
except Exception as e:
logger.exception("Failed to send greeting")
yield {"type": "error", "content": f"Failed to start conversation: {str(e)}"}
yield {"type": "text", "content": greeting}
yield {"type": "response_done"}
except Exception as e:
logger.exception("Failed to send greeting")
yield {"type": "error", "content": f"Failed to start conversation: {str(e)}"}
Copy link

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:

# First, let's look at the ASSISTANT_FEATURE_TOOLS definition in the file
cat -n server/services/assistant_chat_session.py | sed -n '48,62p'

Repository: leonvanzyl/autocoder

Length of output: 648


🏁 Script executed:

# Search for all feature-related tools in the codebase
rg "feature_(create|delete|edit|update|reorder|skip)" --type py -A 2 | head -100

Repository: leonvanzyl/autocoder

Length of output: 2589


🏁 Script executed:

# Look for any tool definitions that might handle feature management
rg "def feature_" --type py

Repository: leonvanzyl/autocoder

Length of output: 616


🏁 Script executed:

# Check the system prompt to understand capabilities mentioned there
cat -n server/services/assistant_chat_session.py | sed -n '88,156p'

Repository: leonvanzyl/autocoder

Length of output: 3330


Update greeting text to accurately reflect available feature management capabilities.

The greeting claims "manage features (create, edit, delete, reorder)" but the assistant's actual feature management capabilities are limited to:

  • feature_create and feature_create_bulk for creating features
  • feature_skip for moving features to the end of the queue (deprioritization)

The system prompt (lines 100-103) correctly describes these constraints. The greeting should be updated to match, such as: "manage features (create and deprioritize)" or "manage features (create and skip)" to avoid misleading users about the assistant's capabilities.

🤖 Prompt for AI Agents
In @server/services/assistant_chat_session.py around lines 273 - 285, The
greeting text in the initial message (the local variable greeting in the
assistant_chat_session.py initial send block) is inaccurate about feature
management; update the string so it reflects only the implemented operations
(feature_create, feature_create_bulk, and feature_skip) — e.g. change "manage
features (create, edit, delete, reorder)" to "manage features (create and
deprioritize (skip))" or similar, and ensure the same corrected string is what
is passed to add_message(self.project_dir, self.conversation_id, "assistant",
greeting) and yielded to the client.

Comment on lines 409 to 439
const resumeConversation = useCallback(
(convId: number) => {
connect();
setConversationId(convId);

// Wait for connection then send resume message (no greeting)
const maxRetries = 50;
let retryCount = 0;

const checkAndResume = () => {
if (wsRef.current?.readyState === WebSocket.OPEN) {
// Send start with conversation_id but backend won't send greeting
// for resumed conversations with messages
wsRef.current.send(
JSON.stringify({
type: "resume",
conversation_id: convId,
}),
);
} else if (wsRef.current?.readyState === WebSocket.CONNECTING) {
retryCount++;
if (retryCount < maxRetries) {
setTimeout(checkAndResume, 100);
}
}
};

setTimeout(checkAndResume, 100);
},
[connect],
);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Potential memory leak in retry loop.

The resumeConversation function uses setTimeout for retry logic (line 431), but these timeouts are not tracked or cleaned up if the component unmounts. This could lead to:

  1. Callbacks firing after unmount
  2. Attempts to use stale wsRef.current
  3. State updates on unmounted component
🔧 Proposed fix to track and clean up timeout

Add a ref to track the resume timeout and clean it up:

 const reconnectTimeoutRef = useRef<number | null>(null);
 const checkAndSendTimeoutRef = useRef<number | null>(null);
+const resumeTimeoutRef = useRef<number | null>(null);
 const hasInitializedRef = useRef(false);

 // Clean up on unmount
 useEffect(() => {
   return () => {
     if (pingIntervalRef.current) {
       clearInterval(pingIntervalRef.current);
     }
     if (reconnectTimeoutRef.current) {
       clearTimeout(reconnectTimeoutRef.current);
     }
     if (checkAndSendTimeoutRef.current) {
       clearTimeout(checkAndSendTimeoutRef.current);
     }
+    if (resumeTimeoutRef.current) {
+      clearTimeout(resumeTimeoutRef.current);
+    }
     if (wsRef.current) {
       wsRef.current.close();
     }
     currentAssistantMessageRef.current = null;
   };
 }, []);

Then in resumeConversation:

       } else if (wsRef.current?.readyState === WebSocket.CONNECTING) {
         retryCount++;
         if (retryCount < maxRetries) {
-          setTimeout(checkAndResume, 100);
+          resumeTimeoutRef.current = window.setTimeout(checkAndResume, 100);
         }
       }
     };

-    setTimeout(checkAndResume, 100);
+    resumeTimeoutRef.current = window.setTimeout(checkAndResume, 100);
🤖 Prompt for AI Agents
In @ui/src/hooks/useAssistantChat.ts around lines 409 - 439, The retry loop in
resumeConversation can leak timeouts and touch stale wsRef.current after
unmount; create a ref (e.g., resumeTimeoutRef via useRef<number | null>) to
store the timeout id, clearTimeout(resumeTimeoutRef.current) before scheduling a
new setTimeout in checkAndResume and when sending the resume, and ensure you
clear it in a useEffect cleanup (component unmount) so checkAndResume never runs
against an unmounted component; reference the existing symbols
resumeConversation, connect, wsRef, checkAndResume, maxRetries and retryCount
when adding/clearing the timeout ref.

- Update README and greeting to reflect actual capabilities (create and skip)
- Remove inaccurate references to edit/delete/reorder features
- Add conversation_id validation in resume handler with error message
- Fix timeout leak in resumeConversation with resumeTimeoutRef

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant