Skip to content

Improve group chat autorun resilience and large-session performance #1037

Open
ets wants to merge 14 commits into
RunMaestro:mainfrom
ets:ets/group-chat-enhancements
Open

Improve group chat autorun resilience and large-session performance #1037
ets wants to merge 14 commits into
RunMaestro:mainfrom
ets:ets/group-chat-enhancements

Conversation

@ets
Copy link
Copy Markdown
Contributor

@ets ets commented May 23, 2026

Summary

Improves group chat behavior for long-running conversations by virtualizing the message list and tightening state updates that previously made the chat composer sluggish as message volume grew. Also strengthens group chat Auto Run handling so participant execution, queueing, and completion reporting are more robust in large collaborative sessions.

Why

Long group chats can accumulate enough rendered message content to degrade the responsiveness of the Maestro window, including visibly slower typing in the group chat input. These changes reduce rendering pressure for large sessions and make group chat Auto Run flows safer for users coordinating multiple agents over longer conversations.

What changed

  • Virtualized group chat message rendering for large histories while preserving markdown rendering, message metadata, and scroll behavior.
  • Added support for compact persisted group chat message records to reduce storage and recovery overhead.
  • Hardened moderator and participant routing around Auto Run completion, participant state reporting, and queued message handling.
  • Debounced group chat draft persistence so typing does not force store-wide updates on every keystroke.
  • Updated related tests for compact message structures, draft persistence timing, and process error listener mocks.

Testing

  • npm run build:prompts
  • npm run format:check:all
  • npm run lint
  • npm run lint:eslint
  • npm test
  • Manual app testing - I run this build as my daily driver

Notes: npm run lint:eslint reports one existing warning in src/main/web-server/web-server-factory.ts:80 for an unused e variable. Full test suite passed with 22,512 tests and 107 skipped.

Summary by CodeRabbit

  • New Features

    • Machine-readable Auto Run references on group chat messages
    • Virtualized group chat message list with improved scroll-to-message and temporary highlight
    • Message UI: timestamps, line expand/collapse, copy/markdown toggle
    • Debounced draft saving for smoother typing
    • Extended timeouts for participant-triggered Auto Run flows
  • Bug Fixes

    • Improved agent execution error tracking
    • Better orphaned batch detection/reporting
  • Documentation

    • Reformatted changelog and updated group-chat prompts with Auto Run guidance
  • Tests

    • Updated/added tests for autorun helpers, virtualized messaging, and debounce/timers

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 23, 2026

Note

Reviews paused

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

Use the following commands to manage reviews:

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

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds canonical Auto Run parsing and propagation to group-chat messages (backend resolution and renderer hydration), virtualizes the group chat message list with memoized subcomponents and index-based scrolling, tracks agent-run errors and batch registry consumption, updates prompts and release-note formatting, and updates related tests.

Changes

Auto Run References Feature

Layer / File(s) Summary
Shared auto-run types and extraction utilities
src/shared/group-chat-types.ts, src/renderer/types/index.ts
Introduces GroupChatAutoRunRef and functions to extract AUTO_RUN_PATH/AUTO_RUN_TRIGGER lines and produce canonical refs; GroupChatMessage gains optional autoRunRefs.
Backend message enrichment and auto-run path resolution
src/main/group-chat/group-chat-router.ts
Router resolves !autorun targets against local/remote auto-run markdown, normalizes paths, matches by exact or unique basename, appends canonical AUTO_RUN_PATH / AUTO_RUN_TRIGGER blocks, and uses enriched content for emission and history; autorun timeouts use an isAutoRun flag.
IPC and preload type updates
src/main/preload/groupChat.ts, src/renderer/global.d.ts
Adds optional autoRunRefs to ChatMessage/MaestroAPI group chat message types to carry resolved refs across processes.
Renderer message hydration and draft debouncing
src/renderer/hooks/groupChat/useGroupChatHandlers.ts
Incoming and initial messages are hydrated to add missing autoRunRefs via extractCanonicalAutoRunRefs; draft persistence is debounced to 300ms.
System and participant prompt updates
src/prompts/group-chat-moderator-system.md, src/prompts/group-chat-participant-request.md
Prompts now prefer/require machine-readable AUTO_RUN_PATH and AUTO_RUN_TRIGGER lines with !autorun @<PARTICIPANT>:<relative-path> format.
Auto-run extraction and handler tests
src/__tests__/shared/group-chat-types.test.ts, src/__tests__/renderer/hooks/useGroupChatHandlers.test.ts
Rewrites types tests to autorun-helper tests; updates handler tests to use fake timers and restore real timers in afterEach, verifying debounced draft behavior and cancellation on unmount.

Message List Virtualization

Layer / File(s) Summary
Virtualized message list with subcomponents
src/renderer/components/GroupChatMessages.tsx
Replaces direct mapping with useVirtualizer-based rendering, adds memoized MessageBubble and TypingIndicator, implements scrollToMessage by virtual index and temporary highlight, and updates auto-scroll/near-bottom logic.
Integration tests: virtualizer mocking and scroll assertions
src/__tests__/integration/GroupChatMessages.integration.test.tsx
Mocks virtualizer spies, imports act for scroll interactions, and asserts scrollToIndex calls with { align: 'center', behavior: 'smooth' } instead of DOM scrollIntoView.

Agent Execution and Batch Handling

Layer / File(s) Summary
Agent error listener and success resolution
src/renderer/hooks/agent/useAgentExecution.ts
Registers onAgentError per session to record run errors so AgentSpawnResult.success reflects !didError.
Batch completion and registry consumption
src/renderer/App.tsx
Uses DEFAULT_BATCH_PROMPT for Group Chat Auto Run batches and calls consumeGroupChatAutoRun on both resolution and rejection to detect/report orphaned batches.
Agent test mock adjustments
src/__tests__/renderer/hooks/useAgentExecution.test.ts
Adds onAgentError mock and installs it in beforeEach to align test mocks with the listener API.

Tests and Release Notes

Layer / File(s) Summary
Autorun tests and handler timer adjustments
src/__tests__/shared/group-chat-types.test.ts, src/__tests__/renderer/hooks/useGroupChatHandlers.test.ts
New autorun helper tests; handler tests now use fake timers and restore real timers in afterEach, asserting debounced draft persistence.
Release notes reformatting
docs/releases.md
Reflows and normalizes Markdown/spacing across many release sections without changing content or bullet text.

Sequence Diagram

sequenceDiagram
  participant P
  participant R
  participant X
  participant F
  participant S
  participant U
  P->>R: message with !autorun directives
  R->>X: extractStructuredAutoRunPaths(content)
  X-->>R: relative paths
  R->>F: resolve local .md candidates
  R->>S: readDirRemote when SSH configured
  F-->>R: matched documents
  S-->>R: matched remote documents
  R->>X: extractCanonicalAutoRunRefs(enrichedContent)
  X-->>R: canonical AUTO_RUN_PATH/AUTO_RUN_TRIGGER blocks
  R->>U: emit message with autoRunRefs and enriched content
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • RunMaestro/Maestro#478: Touches src/renderer/App.tsx and Group Chat auto-run batch wiring related to DEFAULT_BATCH_PROMPT.

Suggested labels

ready to merge

"I’m a rabbit in the code‑filled glen,
Parsing paths and hopping again,
Virtual rows and canonical trails,
Errors watched and prompt details,
A little hop — Auto Run prevails."

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 32.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main objectives: virtualizing group chat rendering for performance and hardening Auto Run handling for resilience in large sessions.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@ets ets changed the title Ets/group chat enhancements Improve group chat autorun resilience and large-session performance May 23, 2026
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 23, 2026

Greptile Summary

This PR improves group chat reliability and performance through two main tracks: (1) virtualizing the message list with @tanstack/react-virtual and adding per-message memoization to reduce rendering pressure for large histories, and (2) hardening the Auto Run flow by fixing a cross-chat session ID collision in the onAutoRunBatchComplete handler, adding a 2-hour participant timeout for autorun batches, and enriching participant messages with machine-readable AUTO_RUN_PATH / AUTO_RUN_TRIGGER refs resolved against the filesystem.

  • Virtualized group chat message rendering with ESTIMATED_MESSAGE_HEIGHT = 180 and overscan: 8; virtualizer.measureElement is correctly used so actual heights are measured and the virtualizer converges quickly.
  • Registry-level fix scopes getAutoRunSessionForGroupChatParticipant and consumeCompletedGroupChatAutoRun by groupChatId so same-named participants across different group chats no longer cross-dispatch COMPLETE_BATCH.
  • Draft persistence debounced at 300 ms with a cleanup effect on unmount, addressing the previous review finding.

Confidence Score: 5/5

Safe to merge. The cross-chat session collision in onAutoRunBatchComplete is properly fixed and all three completion paths (normal, orphan, timeout) are covered by targeted tests.

All three paths through the Auto Run completion flow (normal batch finish, orphaned batch, and participant timeout) are now scoped by groupChatId. The previous unscoped name-only fallback is removed. Both the registry lookup and the pendingCompletions map enforce groupChatId isolation, and the new test suite explicitly verifies that same-named participants across different group chats produce independent COMPLETE_BATCH dispatches without interference.

No files require special attention. The new filesystem-traversal code in group-chat-router.ts handles error paths gracefully and the error test coverage in group-chat-router.test.ts is thorough.

Important Files Changed

Filename Overview
src/renderer/utils/groupChatAutoRunRegistry.ts Adds pendingCompletions map and four new functions to scope batch-complete lookups by groupChatId+participantName, directly fixing the cross-chat collision that was the prior P1.
src/renderer/hooks/groupChat/useGroupChatHandlers.ts onAutoRunBatchComplete handler now uses scoped registry lookups; draft-persistence is debounced with cleanup on unmount, addressing the previously flagged issue.
src/renderer/App.tsx Auto Run orchestration now wraps startBatchRun in a promise chain with orphan detection; replaces empty-string prompt with DEFAULT_BATCH_PROMPT so batches run with the correct context.
src/main/group-chat/group-chat-router.ts Adds 2-hour autorun timeout, filesystem-based Auto Run ref resolution (local + SSH remote), and message enrichment with canonical AUTO_RUN_PATH / AUTO_RUN_TRIGGER lines; new code paths are well error-guarded.
src/renderer/components/GroupChatMessages.tsx Full rewrite using @tanstack/react-virtual with measureElement for dynamic heights, memoized MessageBubble, correct auto-scroll and scroll-to-message support.
src/renderer/hooks/agent/useAgentExecution.ts Adds onAgentError listener with 25 ms grace window so IPC-ordered errors arriving after exit still flip success=false and are reported to Sentry.
src/shared/group-chat-types.ts Adds GroupChatAutoRunRef, extractStructuredAutoRunPaths, and extractCanonicalAutoRunRefs; Maestro-section regex correctly prefers server-enriched block over raw model-authored lines.
src/renderer/hooks/batch/useBatchHandlers.ts Single-line change swaps consumeGroupChatAutoRun for consumeGroupChatAutoRunForCompletion so the pendingCompletions entry is populated before emitAutoRunBatchComplete arrives.

Sequence Diagram

sequenceDiagram
    participant Router as group-chat-router.ts
    participant Registry as groupChatAutoRunRegistry
    participant BatchHandlers as useBatchHandlers
    participant AppTsx as App.tsx
    participant GCHandlers as useGroupChatHandlers
    participant BatchStore as batchStore

    Router->>Router: "setParticipantResponseTimeout(isAutoRun=true, 2h)"
    Router->>AppTsx: emitAutoRunRequest(groupChatId, participantName, files)
    AppTsx->>Registry: registerGroupChatAutoRun(sessionId, groupChatId, participantName)
    AppTsx->>AppTsx: startBatchRun(sessionId, config)

    alt Batch completes normally
        BatchHandlers->>Registry: consumeGroupChatAutoRunForCompletion(sessionId)
        Note over Registry: moves to pendingCompletions[groupChatId:participant]
        BatchHandlers->>Router: reportAutoRunComplete(groupChatId, participantName, summary)
        Router->>Router: clearParticipantTimeout
        Router->>GCHandlers: emitAutoRunBatchComplete(groupChatId, participantName)
        GCHandlers->>Registry: consumeCompletedGroupChatAutoRun(groupChatId, participantName)
        GCHandlers->>BatchStore: COMPLETE_BATCH(sessionId)
    else Orphaned batch (0 tasks)
        AppTsx->>Registry: consumeGroupChatAutoRunForCompletion(sessionId)
        Note over Registry: moves to pendingCompletions[groupChatId:participant]
        AppTsx->>Router: reportAutoRunComplete(groupChatId, participantName, failureMsg)
        Router->>Router: clearParticipantTimeout
        Router->>GCHandlers: emitAutoRunBatchComplete(groupChatId, participantName)
        GCHandlers->>Registry: consumeCompletedGroupChatAutoRun(groupChatId, participantName)
        GCHandlers->>BatchStore: COMPLETE_BATCH(sessionId)
    else Participant timeout (2h)
        Router->>GCHandlers: emitAutoRunBatchComplete(groupChatId, participantName)
        GCHandlers->>Registry: getAutoRunSessionForGroupChatParticipant(groupChatId, participantName)
        Note over Registry: live registry still has entry
        GCHandlers->>BatchStore: COMPLETE_BATCH(sessionId)
    end
Loading

Reviews (3): Last reviewed commit: "MAESTRO: Fix agent execution error order..." | Re-trigger Greptile

Comment on lines +666 to 679
// Debounce draft persistence to avoid triggering store updates (and full re-renders)
// on every keystroke. The input component keeps its own local state for immediate
// responsiveness; this only persists for cross-session draft recovery.
const draftTimerRef = useRef<ReturnType<typeof setTimeout>>();
const handleGroupChatDraftChange = useCallback((draft: string) => {
const { activeGroupChatId, setGroupChats } = useGroupChatStore.getState();
if (!activeGroupChatId) return;
setGroupChats((prev) =>
prev.map((c) => (c.id === activeGroupChatId ? { ...c, draftMessage: draft } : c))
);
if (draftTimerRef.current) clearTimeout(draftTimerRef.current);
draftTimerRef.current = setTimeout(() => {
const { activeGroupChatId, setGroupChats } = useGroupChatStore.getState();
if (!activeGroupChatId) return;
setGroupChats((prev) =>
prev.map((c) => (c.id === activeGroupChatId ? { ...c, draftMessage: draft } : c))
);
}, 300);
}, []);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 The draft debounce timer is never cleared on unmount. Although this hook is currently mounted at the app level and rarely unmounts, a pending 300 ms timer that fires after the component is gone will still call setGroupChats on the Zustand store with a stale chat ID. Adding an unmount cleanup keeps this consistent with React best practices and safe if the hook's lifecycle ever changes.

Suggested change
// Debounce draft persistence to avoid triggering store updates (and full re-renders)
// on every keystroke. The input component keeps its own local state for immediate
// responsiveness; this only persists for cross-session draft recovery.
const draftTimerRef = useRef<ReturnType<typeof setTimeout>>();
const handleGroupChatDraftChange = useCallback((draft: string) => {
const { activeGroupChatId, setGroupChats } = useGroupChatStore.getState();
if (!activeGroupChatId) return;
setGroupChats((prev) =>
prev.map((c) => (c.id === activeGroupChatId ? { ...c, draftMessage: draft } : c))
);
if (draftTimerRef.current) clearTimeout(draftTimerRef.current);
draftTimerRef.current = setTimeout(() => {
const { activeGroupChatId, setGroupChats } = useGroupChatStore.getState();
if (!activeGroupChatId) return;
setGroupChats((prev) =>
prev.map((c) => (c.id === activeGroupChatId ? { ...c, draftMessage: draft } : c))
);
}, 300);
}, []);
// Debounce draft persistence to avoid triggering store updates (and full re-renders)
// on every keystroke. The input component keeps its own local state for immediate
// responsiveness; this only persists for cross-session draft recovery.
const draftTimerRef = useRef<ReturnType<typeof setTimeout>>();
useEffect(() => {
return () => {
if (draftTimerRef.current) clearTimeout(draftTimerRef.current);
};
}, []);
const handleGroupChatDraftChange = useCallback((draft: string) => {
if (draftTimerRef.current) clearTimeout(draftTimerRef.current);
draftTimerRef.current = setTimeout(() => {
const { activeGroupChatId, setGroupChats } = useGroupChatStore.getState();
if (!activeGroupChatId) return;
setGroupChats((prev) =>
prev.map((c) => (c.id === activeGroupChatId ? { ...c, draftMessage: draft } : c))
);
}, 300);
}, []);

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 10

🧹 Nitpick comments (1)
src/__tests__/renderer/hooks/useAgentExecution.test.ts (1)

71-71: ⚡ Quick win

Expose and assert the onAgentError path in the test harness.

At Line [103]-Line [105], the mock registers onAgentError but does not retain the callback, so the new failure path can’t be exercised. Please store the handler and add one assertion that spawnAgentForSession resolves with success: false when that handler fires.

Suggested patch
 let onUsageHandler: ((sid: string, usage: UsageStats) => void) | undefined;
+let onAgentErrorHandler: ((sid: string) => void) | undefined;
 let onExitHandler: ((sid: string) => void) | undefined;
 ...
- mockProcess.onAgentError.mockImplementation(() => {
+ mockProcess.onAgentError.mockImplementation((handler: (sid: string) => void) => {
+   onAgentErrorHandler = handler;
   return () => {};
 });
it('returns success=false when agent error is emitted for the batch session', async () => {
	const session = createMockSession();
	const sessionsRef = { current: [session] };

	const { result } = renderHook(() =>
		useAgentExecution({
			activeSession: session,
			sessionsRef,
			setSessions: vi.fn(),
			processQueuedItemRef: { current: null },
			setFlashNotification: vi.fn(),
			setSuccessFlashNotification: vi.fn(),
		})
	);

	const spawnPromise = result.current.spawnAgentForSession(session.id, 'Test prompt');

	await waitFor(() => expect(mockProcess.spawn).toHaveBeenCalledTimes(1));
	const targetSessionId = mockProcess.spawn.mock.calls[0][0].sessionId as string;

	act(() => {
		onAgentErrorHandler?.(targetSessionId);
		onExitHandler?.(targetSessionId);
	});

	await expect(spawnPromise).resolves.toMatchObject({ success: false });
});

Also applies to: 103-105

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/__tests__/renderer/hooks/useAgentExecution.test.ts` at line 71, The test
currently registers onAgentError as vi.fn() without saving the callback, so the
error path in useAgentExecution.spawnAgentForSession can't be exercised; update
the mock registration of onAgentError to capture and store the handler (e.g.,
onAgentErrorHandler) when mockProcess.on or similar is called, then in the new
test invoke that stored onAgentErrorHandler with the target sessionId after
spawn is triggered (alongside onExitHandler if required) and add an assertion
that awaiting result.current.spawnAgentForSession(session.id, 'Test prompt')
resolves to an object with success: false; reference mockProcess.spawn to obtain
the targetSessionId and the spawnAgentForSession function in useAgentExecution
to locate where to trigger and assert this behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/releases.md`:
- Line 20: Several release-section headings (for example the heading "Major
0.15.x Additions" and other similar section titles) use top-level/incorrect
heading depth and should be demoted to maintain consistent nesting under their
version sections; update those headings to use "###" (or "####" where deeper
nesting is intended) so they are properly nested under the surrounding "##
vX.Y.x" version headings and restore a consistent TOC/hierarchy across the
document.
- Line 174: Replace the incorrect branding "Github" with the official casing
"GitHub" in the release note string that currently reads "Github Worktree
support was added." (search for the exact phrase "Github Worktree support" in
the doc and update it to "GitHub Worktree support").
- Line 80: Update the release notes header text that currently reads "# Smaller
Changes in 014.x" to the correct semantic version series "# Smaller Changes in
0.14.x" in docs/releases.md so the heading accurately reflects the 0.14.x
release series.
- Line 74: Update the typo in the release note sentence that currently reads
“Launch from file preview or from the FIle tree panel” by changing “FIle” to
“File” so it reads “File tree panel”; edit the string in docs/releases.md (the
sentence containing “Launch from file preview or from the FIle tree panel”) to
correct the capitalization.

In `@src/main/group-chat/group-chat-router.ts`:
- Around line 295-298: The current code silently returns [] when
readDirRemote(folderPath, sshRemoteConfig) fails or returns no data; update the
handling around readDirRemote so you inspect result.error and
result.success/result.data, classify expected vs unexpected failures, and do not
swallow unexpected errors: for expected/recoverable cases return an explicit
empty array or a clear error object (with context including folderPath and
sshRemoteConfig host), but for unexpected failures rethrow the original error
(or wrap it with context) so Sentry can capture it; ensure you reference the
readDirRemote call and use result.success, result.data, and result.error when
implementing this change in group-chat-router.ts.
- Around line 1704-1706: Wrap the call to
resolveParticipantAutoRunRefs(participantName, message) inside a try/catch in
routeAgentResponse so any I/O/remote error does not abort the flow; on success
use appendCanonicalAutoRunRefs(message, autoRunRefs), on failure log/report the
error with Sentry utilities (include context like participantName and message
metadata) and continue using the original message so append/emit/history still
run. Ensure the catch only treats this as recoverable (do not rethrow), and add
a brief error-level log via processLogger or Sentry captureException with
contextual tags to aid debugging.

In `@src/renderer/App.tsx`:
- Around line 1341-1360: startBatchRunRef.current(...) can throw synchronously
and its rejection path isn’t reporting to Sentry; wrap the call so synchronous
throws are caught and reported with Sentry utilities and keep the existing chat
failure/reporting behavior. Specifically, call startBatchRunRef.current(...)
inside a try/catch (or use Promise.resolve(...) to normalize sync throws), and
in the catch call captureException(err) and/or captureMessage with a contextual
message before rethrowing or reporting to chat; also add captureException calls
in the existing promise rejection handler (the (err) => { ... }) so both sync
throws and async rejections send errors to Sentry while still invoking
consumeGroupChatAutoRun(session.id) and reportFailure.

In `@src/renderer/global.d.ts`:
- Around line 1742-1747: The groupChat message type is inconsistent: getMessages
advertises autoRunRefs but onMessage's callback type omits it; update the
onMessage callback signature to include the same optional autoRunRefs property
(Array<{ participantName: string; relativePath: string; triggerCommand: string;
}> ) so the groupChat message shape matches getMessages. Locate the
groupChat-related types and the onMessage callback declaration (symbols:
groupChat, getMessages, onMessage, autoRunRefs) and add autoRunRefs?: Array<{
participantName: string; relativePath: string; triggerCommand: string }>; to the
callback parameter type.

In `@src/renderer/hooks/agent/useAgentExecution.ts`:
- Around line 237-245: The code may report success=true if onExit cleanup
removes listeners before a late onAgentError flips didError and also fails to
report agent errors to Sentry; modify the onExit handler (and cleanup flow
around cleanupFns) to delay finalizing/resolving success until a short grace
window or until you deterministically know no further onAgentError can arrive
(e.g., wait for a few milliseconds or an "confirmedExit" flag), ensure the
onAgentError listener (window.maestro.process.onAgentError) sets didError=true
and calls Sentry.captureException/captureMessage with context about
targetSessionId and the error, and only remove the onAgentError listener from
cleanupFns after this window/confirmation so that lines resolving success (the
resolution logic that reads didError) always sees a correct error state.

In `@src/renderer/hooks/groupChat/useGroupChatHandlers.ts`:
- Around line 670-678: The debounce currently reads
useGroupChatStore.getState().activeGroupChatId inside the setTimeout, which can
change before the timer fires and cause the draft to be saved to the wrong chat;
modify handleGroupChatDraftChange to capture the current activeGroupChatId (and
setGroupChats getter if you prefer) immediately when the callback runs and then
use that captured id inside draftTimerRef's setTimeout closure so the draft is
applied to the chat that was active at keystroke time (reference symbols:
handleGroupChatDraftChange, draftTimerRef, activeGroupChatId, setGroupChats).

---

Nitpick comments:
In `@src/__tests__/renderer/hooks/useAgentExecution.test.ts`:
- Line 71: The test currently registers onAgentError as vi.fn() without saving
the callback, so the error path in useAgentExecution.spawnAgentForSession can't
be exercised; update the mock registration of onAgentError to capture and store
the handler (e.g., onAgentErrorHandler) when mockProcess.on or similar is
called, then in the new test invoke that stored onAgentErrorHandler with the
target sessionId after spawn is triggered (alongside onExitHandler if required)
and add an assertion that awaiting
result.current.spawnAgentForSession(session.id, 'Test prompt') resolves to an
object with success: false; reference mockProcess.spawn to obtain the
targetSessionId and the spawnAgentForSession function in useAgentExecution to
locate where to trigger and assert this behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c2284ee6-7036-4298-b9b4-46d484e1ddfd

📥 Commits

Reviewing files that changed from the base of the PR and between 1006e3b and 279b995.

📒 Files selected for processing (15)
  • docs/releases.md
  • src/__tests__/renderer/hooks/useAgentExecution.test.ts
  • src/__tests__/renderer/hooks/useGroupChatHandlers.test.ts
  • src/__tests__/shared/group-chat-types.test.ts
  • src/main/group-chat/group-chat-router.ts
  • src/main/preload/groupChat.ts
  • src/prompts/group-chat-moderator-system.md
  • src/prompts/group-chat-participant-request.md
  • src/renderer/App.tsx
  • src/renderer/components/GroupChatMessages.tsx
  • src/renderer/global.d.ts
  • src/renderer/hooks/agent/useAgentExecution.ts
  • src/renderer/hooks/groupChat/useGroupChatHandlers.ts
  • src/renderer/types/index.ts
  • src/shared/group-chat-types.ts

Comment thread docs/releases.md Outdated
Comment thread docs/releases.md Outdated
Comment thread docs/releases.md Outdated
Comment thread docs/releases.md Outdated
Comment thread src/main/group-chat/group-chat-router.ts
Comment thread src/main/group-chat/group-chat-router.ts Outdated
Comment thread src/renderer/App.tsx Outdated
Comment thread src/renderer/global.d.ts Outdated
Comment thread src/renderer/hooks/agent/useAgentExecution.ts
Comment thread src/renderer/hooks/groupChat/useGroupChatHandlers.ts
@ets ets closed this May 30, 2026
@ets ets force-pushed the ets/group-chat-enhancements branch from 279b995 to 575efd0 Compare May 30, 2026 16:24
…ncements

# Conflicts:
#	src/__tests__/renderer/hooks/useGroupChatHandlers.test.ts
#	src/renderer/components/GroupChatMessages.tsx
@ets ets reopened this May 30, 2026
@ets
Copy link
Copy Markdown
Contributor Author

ets commented May 30, 2026

@greptile review

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