Skip to content

fix(backend/frontend): error handling, stream reconnection, and chat switching - #12205

Merged
majdyz merged 52 commits into
devfrom
fix/copilot-subtask-concurrency-limit
Feb 26, 2026
Merged

fix(backend/frontend): error handling, stream reconnection, and chat switching#12205
majdyz merged 52 commits into
devfrom
fix/copilot-subtask-concurrency-limit

Conversation

@majdyz

@majdyz majdyz commented Feb 25, 2026

Copy link
Copy Markdown
Contributor

Problem

CoPilot executions were experiencing:

  1. Duplicate error markers - Both execute() and _execute_async() called mark_session_completed, sending duplicate completion markers
  2. RuntimeError bypass - RuntimeErrors that weren't SDK cleanup issues bypassed error persistence logic
  3. Generic error messages - StreamError showed "An error occurred" instead of actual error text
  4. Empty chat on reconnect - Messages cleared immediately when reconnecting, before new messages arrived
  5. Stream not resuming - Switching chats (A → B → A) didn't resume active streams due to stale hasResumedRef
  6. Excessive diagnostic logging - 60+ lines of STREAM_DIAG console logs not needed in production

Changes 🏗️

1. Consolidated Exception Handling

Files: backend/copilot/executor/processor.py, backend/copilot/sdk/service.py

processor.py:

  • Removed all error handling from execute() method
  • Kept error handling only in _execute_async() where work happens
  • Merged CancelledError and BaseException handlers into single catch
  • Uses isinstance() to determine error message

service.py:

  • Merged CancelledError and Exception handlers into single catch
  • Moved RuntimeError check inside main Exception handler
  • Prevents non-cancel-scope RuntimeErrors from bypassing error persistence

Impact: Eliminates duplicate mark_session_completed calls, ~70 lines of code removed


2. Fixed StreamError Message

File: backend/copilot/sdk/service.py

  • Changed from generic "An error occurred. Please try again."
  • Now shows actual error: errorText=error_msg
  • Provides real error details to frontend during active stream

3. Deferred Message Clearing on Reconnect

File: frontend/src/app/(platform)/copilot/useCopilotPage.ts

  • Added shouldClearOnNextMessageRef flag
  • Set flag when reconnect starts
  • Clear old assistant messages only AFTER first new message arrives
  • Prevents empty chat flicker during reconnection

4. Fixed Chat Switching Stream Resume

File: frontend/src/app/(platform)/copilot/useCopilotPage.ts

Problem: When switching Chat A → B → A, the stream didn't resume because hasResumedRef.current.get(sessionId) was still true

Fix: Clear hasResumedRef entry when navigating away from session

Flow now:

  1. In Chat A with active stream
  2. Switch to Chat B → clears hasResumedRef for Chat A
  3. Switch back to Chat A → hasResumedRef is false → resumes stream ✅

5. Removed Diagnostic Logging

Files: frontend/useCopilotPage.ts, frontend/useChatSession.ts, backend/stream_registry.py, backend/processor.py, backend/routes.py

  • Removed all [STREAM_DIAG] console logs (60+ lines)
  • Logs were useful for debugging but not needed in production
  • Cleaner codebase, reduced noise in logs

6. Exception Handling Order Consistency

File: backend/copilot/executor/processor.py

  • Made both CancelledError and regular exception branches follow same pattern
  • Set error_msg before logging in both cases
  • Consistent code structure

Architecture Quality: 9/10

Strengths:

  • Eliminated duplicate completion markers
  • All RuntimeErrors now get proper error persistence
  • Real error messages shown to users
  • Stream resume works reliably when switching chats
  • Cleaner codebase with diagnostic logs removed
  • Consistent exception handling patterns

Trade-offs:

  • Message clearing deferred means brief period with stale + new messages (acceptable, prevents empty chat)

Test Plan

  • Verify no duplicate completion markers sent
  • Trigger RuntimeError, verify error persists
  • Check StreamError shows actual error message
  • Reconnect, verify chat doesn't go empty
  • Switch Chat A → B → A with active stream, verify resume works
  • Verify no STREAM_DIAG logs in console
  • Run pnpm format && pnpm lint && pnpm types - all passed
  • Run poetry run format - all passed
  • Test in production

Checklist 📋

  • I have clearly listed my changes in the PR description
  • I have made a test plan
  • I have tested my changes according to the test plan
  • .env.default is updated or compatible (no config changes)
  • docker-compose.yml is updated or compatible (no config changes)

…limit

Previously, task_spawn_count only incremented and never decremented,
making it a per-session lifetime cap. Once 10 subtasks were spawned
(even if all had completed), no more could be created — forcing
the agent to work without sub-agents for the rest of the session.

Now the counter decrements in PostToolUse when a Task completes,
making it a true concurrency limit. Finished subtasks free their
slots for reuse.
@majdyz
majdyz requested a review from a team as a code owner February 25, 2026 10:48
@majdyz
majdyz requested review from Bentlybro and Pwuts and removed request for a team February 25, 2026 10:48
@github-project-automation github-project-automation Bot moved this to 🆕 Needs initial review in AutoGPT development kanban Feb 25, 2026

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@github-actions github-actions Bot added platform/frontend AutoGPT Platform - Front end platform/backend AutoGPT Platform - Back end labels Feb 25, 2026
@github-actions

github-actions Bot commented Feb 25, 2026

Copy link
Copy Markdown
Contributor

🔍 PR Overlap Detection

This check compares your PR against all other open PRs targeting the same branch to detect potential merge conflicts early.

🔴 Merge Conflicts Detected

The following PRs have been tested and will have merge conflicts if merged after this PR. Consider coordinating with the authors.

🟢 Low Risk — File Overlap Only

These PRs touch the same files but different sections (click to expand)

Summary: 6 conflict(s), 0 medium risk, 2 low risk (out of 8 PRs with file overlap)


Auto-generated on push. Ignores: openapi.json, lock files.

Comment thread autogpt_platform/backend/backend/copilot/sdk/security_hooks.py
When the SSE stream drops unexpectedly (status transitions to "error"
while backend is still running), the frontend now automatically:
1. Refetches the session to check for active_stream
2. Resets the resume guard so the existing resume effect fires
3. Calls resumeStream() to reconnect to the Redis-backed stream

Capped at 3 reconnect attempts per session to avoid infinite loops.
On clean finish (status "ready"), the counter resets.
@majdyz
majdyz force-pushed the fix/copilot-subtask-concurrency-limit branch from 352a793 to db3d10f Compare February 25, 2026 10:52
Failed Tasks were not decrementing task_spawn_count, permanently
consuming a concurrency slot. Add the same release logic to
post_tool_failure_hook so slots are freed regardless of outcome.
@majdyz

majdyz commented Feb 25, 2026

Copy link
Copy Markdown
Contributor Author

Addressed Sentry's review comment in 142198d: post_tool_failure_hook now also decrements task_spawn_count so failed Tasks release their concurrency slot. Added test_task_slot_released_on_failure to cover this.

@majdyz
majdyz requested a review from 0ubbe February 25, 2026 11:01
@coderabbitai

coderabbitai Bot commented Feb 25, 2026

Copy link
Copy Markdown
Contributor

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

Clarified a config field to indicate a concurrent subtask limit; replaced a per-session scalar counter with per-session concurrency tracking and added slot release on task completion/failure in backend hooks; exposed refetchSession from useChatSession; added per-session reconnect/backoff and cleanup in useCopilotPage.

Changes

Cohort / File(s) Summary
Backend config
autogpt_platform/backend/backend/copilot/config.py
Updated claude_agent_max_subtasks description to indicate a concurrent limit rather than total spawned.
Backend hooks
autogpt_platform/backend/backend/copilot/sdk/security_hooks.py
Replaced scalar per-session counter with a task_tool_use_ids set for concurrency tracking; enforce concurrent-subtask limit in PreToolUse; add slot release in PostToolUse and PostToolFailure; updated denial message and logging.
Backend tests
autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py
Fixture _hooks now returns (pre, post, post_failure); tests updated/unpacked accordingly; added tests confirming slot release on completion and on failure; updated deny-message assertions.
Frontend session hook
autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
Return value now includes refetchSession mapped to sessionQuery.refetch.
Frontend page logic
autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
Added per-session reconnect/backoff (base/max delays), per-session reconnectAttempts and timer refs, guarded invalidation on stream end, exponential backoff retry using refetchSession, and timer cleanup on effect/unmount.

Sequence Diagram(s)

sequenceDiagram
  participant UI as UI
  participant Page as useCopilotPage
  participant Session as useChatSession
  participant Server as Server

  UI->>Page: observe stream / mount
  Page->>Session: subscribe + get sessionQuery + refetchSession
  Session->>Server: open stream / fetch session
  Server-->>Session: stream events (active / ready / error / idle)
  Session-->>Page: emit status updates

  alt stream ends (idle or error) and prior activity & valid sessionId
    Page->>Page: compute backoff delay, increment attempts
    Page->>Session: schedule refetchSession (after delay)
    Session->>Server: refetch session
  else stream ready
    Page->>Page: clear per-session reconnect state
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • ntindle
  • Swiftyos
  • Pwuts

Poem

🐰 I count the slots where subtasks play,
When one hops back, I clear the way.
Streams nap, then try once more—
Backoff waits, then knocks the door.
Refetch, reconnect, we hop galore! 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 85.71% which is sufficient. The required threshold is 80.00%.
Title check ✅ Passed The title accurately summarizes the main changes: error handling improvements (consolidated exception handling, fixed StreamError messages), stream reconnection (auto-reconnect on SSE disconnect), and chat switching (fixed stream resume when navigating between sessions).
Description check ✅ Passed The description is comprehensive and directly related to the changeset, detailing the problems addressed, changes made with specific files and impacts, architecture quality assessment, test plan, and checklist.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/copilot-subtask-concurrency-limit

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

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

⚠️ Outside diff range comments (1)
autogpt_platform/backend/backend/copilot/sdk/security_hooks.py (1)

236-289: ⚠️ Potential issue | 🟠 Major

Change return type from SyncHookJSONOutput to dict[str, Any] for async hook functions.

Per the Claude Agent SDK v0.1.39 documentation, async hooks must have return type dict[str, Any], not SyncHookJSONOutput. The word "Sync" in the type name contradicts these async functions. Remove the cast() calls on lines 254, 258, and 265 and update the return type annotation for post_tool_use_hook, pre_tool_use_hook, and post_tool_failure_hook to dict[str, Any].

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@autogpt_platform/backend/backend/copilot/sdk/security_hooks.py` around lines
236 - 289, Update the async hook functions post_tool_use_hook,
pre_tool_use_hook, and post_tool_failure_hook to use the async-compatible return
annotation dict[str, Any] instead of SyncHookJSONOutput, and return plain dicts
(e.g., {}) directly; remove the cast(...) wrappers around returned values (the
cast calls used around SyncHookJSONOutput) so the functions return a native
dict[str, Any] without casting.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@autogpt_platform/backend/backend/copilot/sdk/security_hooks.py`:
- Around line 253-260: The post-hook currently decrements task_spawn_count
blindly (only guarded by task_spawn_count > 0) so a PostToolUse fired for a
pre-denied Task could release a slot that was never taken; introduce a
closure-scoped Set[str] (e.g., task_tool_use_ids) to record tool_use_id values
when you actually increment task_spawn_count (in the PreToolUse/where Task
increments), then in post_tool_use_hook and post_tool_failure_hook only
decrement task_spawn_count if the incoming tool_use_id is present in
task_tool_use_ids and remove it after decrementing; update logging (the
logger.info call using task_spawn_count/max_subtasks/user_id) to remain the same
but ensure the decrement only runs when the id was tracked.

In `@autogpt_platform/frontend/src/app/`(platform)/copilot/useCopilotPage.ts:
- Around line 245-280: The reconnectAttemptsRef map is never cleared when the
user navigates away, so stale counters block future retries for that session;
update the effect to detect sessionId changes and delete the old session's
counter from reconnectAttemptsRef (and clear any related state like
hasResumedRef and pending reconnectTimerRef) when sessionId changes — e.g., keep
a prevSessionIdRef, on change call reconnectAttemptsRef.current.delete(prevId)
(and clearTimeout(reconnectTimerRef.current) /
hasResumedRef.current.delete(prevId) as needed) before setting up the new
reconnect logic in the existing useEffect that references sessionId,
reconnectTimerRef, reconnectAttemptsRef, prevStatusRef, hasResumedRef, and
refetchSession.
- Around line 252-280: The bug is cross-session bleeding of prevStatusRef when
sessionId changes; to fix it, detect session switches at the start of the
useEffect that watches status/sessionId and reset prevStatusRef for the new
session. Concretely, add a ref like prevSessionIdRef (or reuse an existing one),
and inside the useEffect check if prevSessionIdRef.current !== sessionId; if so
set prevStatusRef.current = undefined (or null) and update
prevSessionIdRef.current = sessionId before using prevStatusRef.current, so the
logic around wasActive/isIdle, queryClient.invalidateQueries,
reconnectAttemptsRef, hasResumedRef, and reconnectTimerRef uses a clean
previous-status for each session.

---

Outside diff comments:
In `@autogpt_platform/backend/backend/copilot/sdk/security_hooks.py`:
- Around line 236-289: Update the async hook functions post_tool_use_hook,
pre_tool_use_hook, and post_tool_failure_hook to use the async-compatible return
annotation dict[str, Any] instead of SyncHookJSONOutput, and return plain dicts
(e.g., {}) directly; remove the cast(...) wrappers around returned values (the
cast calls used around SyncHookJSONOutput) so the functions return a native
dict[str, Any] without casting.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 2136def and 142198d.

📒 Files selected for processing (5)
  • autogpt_platform/backend/backend/copilot/config.py
  • autogpt_platform/backend/backend/copilot/sdk/security_hooks.py
  • autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py
  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: end-to-end tests
  • GitHub Check: test (3.12)
  • GitHub Check: test (3.11)
  • GitHub Check: test (3.13)
  • GitHub Check: Check PR Status
🧰 Additional context used
📓 Path-based instructions (15)
autogpt_platform/frontend/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

autogpt_platform/frontend/**/*.{ts,tsx,js,jsx}: Use Node.js 21+ with pnpm package manager for frontend development
Always run 'pnpm format' for formatting and linting code in frontend development

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
autogpt_platform/frontend/**/*.{tsx,ts}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

autogpt_platform/frontend/**/*.{tsx,ts}: Use function declarations for components and handlers (not arrow functions) in React components
Only use arrow functions for small inline lambdas (map, filter, etc.) in React components
Use PascalCase for component names and camelCase with 'use' prefix for hook names in React
Use Tailwind CSS utilities only for styling in frontend components
Use design system components from 'src/components/' (atoms, molecules, organisms) in frontend development
Never use 'src/components/legacy/' in frontend code
Only use Phosphor Icons (@phosphor-icons/react) for icons in frontend components
Use generated API hooks from '@/app/api/generated/endpoints/' instead of deprecated 'BackendAPI' or 'src/lib/autogpt-server-api/
'
Use React Query for server state (via generated hooks) in frontend development
Default to client components ('use client') in Next.js; only use server components for SEO or extreme TTFB needs
Use '' component for rendering errors in frontend UI; use toast notifications for mutation errors; use 'Sentry.captureException()' for manual exceptions
Separate render logic from data/behavior in React components; keep comments minimal (code should be self-documenting)

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
autogpt_platform/frontend/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

autogpt_platform/frontend/**/*.{ts,tsx}: No barrel files or 'index.ts' re-exports in frontend code
Regenerate API hooks with 'pnpm generate:api' after backend OpenAPI spec changes in frontend development

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
autogpt_platform/frontend/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (autogpt_platform/frontend/CLAUDE.md)

autogpt_platform/frontend/src/**/*.{ts,tsx}: Fully capitalize acronyms in symbols, e.g. graphID, useBackendAPI
Use function declarations (not arrow functions) for components and handlers
Separate render logic (.tsx) from business logic (use*.ts hooks)
Use shadcn/ui (Radix UI primitives) with Tailwind CSS styling for UI components
Use Phosphor Icons only for icons
Use ErrorCard for render errors, toast for mutations, and Sentry for exceptions
Use design system components from src/components/ (atoms, molecules, organisms)
Never use src/components/__legacy__/* components
Use generated API hooks from @/app/api/__generated__/endpoints/ with pattern use{Method}{Version}{OperationName}
Use Tailwind CSS only for styling, with design tokens
Do not use useCallback or useMemo unless asked to optimize a given function
Never type with any unless a variable/attribute can ACTUALLY be of any type

autogpt_platform/frontend/src/**/*.{ts,tsx}: Structure components as ComponentName/ComponentName.tsx + useComponentName.ts + helpers.ts and use design system components from src/components/ (atoms, molecules, organisms)
Use generated API hooks from @/app/api/__generated__/endpoints/ with pattern use{Method}{Version}{OperationName} and regenerate with pnpm generate:api
Use function declarations (not arrow functions) for components and handlers
Separate render logic from business logic with component.tsx + useComponent.ts + helpers.ts structure
Colocate state when possible, avoid creating large components, use sub-components in local /components folder
Avoid large hooks, abstract logic into helpers.ts files when sensible
Use arrow functions only for callbacks, not for component declarations
Avoid comments at all times unless the code is very complex
Do not use useCallback or useMemo unless asked to optimize a given function

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
autogpt_platform/frontend/src/**/*use*.ts

📄 CodeRabbit inference engine (autogpt_platform/frontend/CLAUDE.md)

Do not type hook returns, let TypeScript infer as much as possible

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
autogpt_platform/frontend/**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

autogpt_platform/frontend/**/*.{js,jsx,ts,tsx}: Format frontend code using pnpm format
Never use components from src/components/__legacy__/*

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
autogpt_platform/frontend/**/*.{js,jsx,ts,tsx,css}

📄 CodeRabbit inference engine (AGENTS.md)

Use Tailwind CSS only for styling, use design tokens, and use Phosphor Icons only

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
autogpt_platform/frontend/src/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Do not type hook returns, let Typescript infer as much as possible

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
autogpt_platform/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Never type with any, if no types available use unknown

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
autogpt_platform/backend/**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

autogpt_platform/backend/**/*.py: Use Python 3.11 (required; managed by Poetry via pyproject.toml) for backend development
Always run 'poetry run format' (Black + isort) before linting in backend development
Always run 'poetry run lint' (ruff) after formatting in backend development

Files:

  • autogpt_platform/backend/backend/copilot/config.py
  • autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py
  • autogpt_platform/backend/backend/copilot/sdk/security_hooks.py
autogpt_platform/backend/**/*.{py,txt}

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

Use poetry run prefix for all Python commands, including testing, linting, formatting, and migrations

Files:

  • autogpt_platform/backend/backend/copilot/config.py
  • autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py
  • autogpt_platform/backend/backend/copilot/sdk/security_hooks.py
autogpt_platform/backend/backend/**/*.py

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

Use Prisma ORM for database operations in PostgreSQL with pgvector for embeddings

Files:

  • autogpt_platform/backend/backend/copilot/config.py
  • autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py
  • autogpt_platform/backend/backend/copilot/sdk/security_hooks.py
autogpt_platform/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Format Python code with poetry run format

Files:

  • autogpt_platform/backend/backend/copilot/config.py
  • autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py
  • autogpt_platform/backend/backend/copilot/sdk/security_hooks.py
autogpt_platform/backend/**/*_test.py

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

autogpt_platform/backend/**/*_test.py: Always review snapshot changes with git diff before committing when updating snapshots with poetry run pytest --snapshot-update
Use pytest with snapshot testing for API responses in test files
Colocate test files with source files using the *_test.py naming convention

Files:

  • autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py
autogpt_platform/backend/**/*test*.py

📄 CodeRabbit inference engine (AGENTS.md)

Run poetry run test for backend testing (runs pytest with docker based postgres + prisma)

Files:

  • autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py
🧠 Learnings (1)
📚 Learning: 2026-02-04T16:49:42.490Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-04T16:49:42.490Z
Learning: Applies to autogpt_platform/frontend/**/*.{tsx,ts} : Use generated API hooks from '@/app/api/__generated__/endpoints/' instead of deprecated 'BackendAPI' or 'src/lib/autogpt-server-api/*'

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
🔇 Additional comments (5)
autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py (2)

209-218: LGTM — fixture correctly exposes triple of hooks.

The updated _hooks fixture properly returns (pre, post, post_failure) and each test unpacks only the handle it needs. Default function-scope ensures each test gets a fresh task_spawn_count=0 closure.


272-345: LGTM — new slot-release tests are thorough and symmetric.

Both test_task_slot_released_on_completion and test_task_slot_released_on_failure follow the same fill-to-capacity → verify-denial → release-one → verify-allowed pattern, giving clear coverage of both happy and failure paths.

autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts (1)

113-123: LGTM — minimal, correct exposure of refetchSession.

Forwarding sessionQuery.refetch directly keeps the return type inferred and is the idiomatic pattern for exposing React Query refetch handles.

autogpt_platform/backend/backend/copilot/config.py (1)

86-89: LGTM — description correctly reflects the new concurrency semantics.

autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts (1)

19-20: LGTM — reconnect constants are appropriately conservative.

3 attempts with 1s base delay (1s / 2s / 4s) gives a reasonable 7-second retry window without hammering the backend.

Comment thread autogpt_platform/backend/backend/copilot/sdk/security_hooks.py Outdated
Comment thread autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts Outdated
Comment thread autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts (1)

244-246: Memory consideration: reconnectAttemptsRef Map is never pruned.

Entries are only deleted on successful reconnect (status === "ready"). If a user visits many sessions that all error out without recovering, entries accumulate. This is unlikely to matter in practice (session IDs are small strings), but you could add a cleanup when sessionId changes, similar to how hasResumedRef is used.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@autogpt_platform/frontend/src/app/`(platform)/copilot/useCopilotPage.ts
around lines 244 - 246, reconnectAttemptsRef is never pruned which can
accumulate entries for visited sessions; add a cleanup effect that runs when
sessionId changes (similar to hasResumedRef handling) to remove stale entries
from reconnectAttemptsRef (e.g., delete all keys !== sessionId or reset the map
if null) so only the current session's retry count is kept; reference
reconnectAttemptsRef and sessionId inside that useEffect to perform the pruning.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@autogpt_platform/frontend/src/app/`(platform)/copilot/useCopilotPage.ts:
- Around line 252-280: When reconnect attempts are exhausted the effect silently
returns and the user gets no feedback, and the global reconnectTimerRef.current
is overwritten which can drop the first timeout ID; modify the effect so that
when attempts >= RECONNECT_MAX_ATTEMPTS you set an explicit error/notification
(e.g., trigger a toast or set an error state via your existing UI/error handler)
referencing reconnectAttemptsRef and RECONNECT_MAX_ATTEMPTS so the UI shows a
final failure, and change the timer handling to use a local const (e.g., const
timer = setTimeout(...)) and clear that local timer in the cleanup instead of
directly mutating reconnectTimerRef.current (you can still keep
reconnectTimerRef for other usages but avoid assigning it unconditionally here),
keeping the existing logic that calls refetchSession() and deletes hasResumedRef
on retry and using
queryClient.invalidateQueries(getGetV2GetSessionQueryKey(sessionId)) as before.

---

Nitpick comments:
In `@autogpt_platform/frontend/src/app/`(platform)/copilot/useCopilotPage.ts:
- Around line 244-246: reconnectAttemptsRef is never pruned which can accumulate
entries for visited sessions; add a cleanup effect that runs when sessionId
changes (similar to hasResumedRef handling) to remove stale entries from
reconnectAttemptsRef (e.g., delete all keys !== sessionId or reset the map if
null) so only the current session's retry count is kept; reference
reconnectAttemptsRef and sessionId inside that useEffect to perform the pruning.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 2136def and 142198d.

📒 Files selected for processing (5)
  • autogpt_platform/backend/backend/copilot/config.py
  • autogpt_platform/backend/backend/copilot/sdk/security_hooks.py
  • autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py
  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (15)
autogpt_platform/frontend/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

autogpt_platform/frontend/**/*.{ts,tsx,js,jsx}: Use Node.js 21+ with pnpm package manager for frontend development
Always run 'pnpm format' for formatting and linting code in frontend development

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
autogpt_platform/frontend/**/*.{tsx,ts}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

autogpt_platform/frontend/**/*.{tsx,ts}: Use function declarations for components and handlers (not arrow functions) in React components
Only use arrow functions for small inline lambdas (map, filter, etc.) in React components
Use PascalCase for component names and camelCase with 'use' prefix for hook names in React
Use Tailwind CSS utilities only for styling in frontend components
Use design system components from 'src/components/' (atoms, molecules, organisms) in frontend development
Never use 'src/components/legacy/' in frontend code
Only use Phosphor Icons (@phosphor-icons/react) for icons in frontend components
Use generated API hooks from '@/app/api/generated/endpoints/' instead of deprecated 'BackendAPI' or 'src/lib/autogpt-server-api/
'
Use React Query for server state (via generated hooks) in frontend development
Default to client components ('use client') in Next.js; only use server components for SEO or extreme TTFB needs
Use '' component for rendering errors in frontend UI; use toast notifications for mutation errors; use 'Sentry.captureException()' for manual exceptions
Separate render logic from data/behavior in React components; keep comments minimal (code should be self-documenting)

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
autogpt_platform/frontend/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

autogpt_platform/frontend/**/*.{ts,tsx}: No barrel files or 'index.ts' re-exports in frontend code
Regenerate API hooks with 'pnpm generate:api' after backend OpenAPI spec changes in frontend development

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
autogpt_platform/frontend/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (autogpt_platform/frontend/CLAUDE.md)

autogpt_platform/frontend/src/**/*.{ts,tsx}: Fully capitalize acronyms in symbols, e.g. graphID, useBackendAPI
Use function declarations (not arrow functions) for components and handlers
Separate render logic (.tsx) from business logic (use*.ts hooks)
Use shadcn/ui (Radix UI primitives) with Tailwind CSS styling for UI components
Use Phosphor Icons only for icons
Use ErrorCard for render errors, toast for mutations, and Sentry for exceptions
Use design system components from src/components/ (atoms, molecules, organisms)
Never use src/components/__legacy__/* components
Use generated API hooks from @/app/api/__generated__/endpoints/ with pattern use{Method}{Version}{OperationName}
Use Tailwind CSS only for styling, with design tokens
Do not use useCallback or useMemo unless asked to optimize a given function
Never type with any unless a variable/attribute can ACTUALLY be of any type

autogpt_platform/frontend/src/**/*.{ts,tsx}: Structure components as ComponentName/ComponentName.tsx + useComponentName.ts + helpers.ts and use design system components from src/components/ (atoms, molecules, organisms)
Use generated API hooks from @/app/api/__generated__/endpoints/ with pattern use{Method}{Version}{OperationName} and regenerate with pnpm generate:api
Use function declarations (not arrow functions) for components and handlers
Separate render logic from business logic with component.tsx + useComponent.ts + helpers.ts structure
Colocate state when possible, avoid creating large components, use sub-components in local /components folder
Avoid large hooks, abstract logic into helpers.ts files when sensible
Use arrow functions only for callbacks, not for component declarations
Avoid comments at all times unless the code is very complex
Do not use useCallback or useMemo unless asked to optimize a given function

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
autogpt_platform/frontend/src/**/*use*.ts

📄 CodeRabbit inference engine (autogpt_platform/frontend/CLAUDE.md)

Do not type hook returns, let TypeScript infer as much as possible

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
autogpt_platform/frontend/**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

autogpt_platform/frontend/**/*.{js,jsx,ts,tsx}: Format frontend code using pnpm format
Never use components from src/components/__legacy__/*

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
autogpt_platform/frontend/**/*.{js,jsx,ts,tsx,css}

📄 CodeRabbit inference engine (AGENTS.md)

Use Tailwind CSS only for styling, use design tokens, and use Phosphor Icons only

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
autogpt_platform/frontend/src/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Do not type hook returns, let Typescript infer as much as possible

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
autogpt_platform/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Never type with any, if no types available use unknown

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
autogpt_platform/backend/**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

autogpt_platform/backend/**/*.py: Use Python 3.11 (required; managed by Poetry via pyproject.toml) for backend development
Always run 'poetry run format' (Black + isort) before linting in backend development
Always run 'poetry run lint' (ruff) after formatting in backend development

Files:

  • autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py
  • autogpt_platform/backend/backend/copilot/config.py
  • autogpt_platform/backend/backend/copilot/sdk/security_hooks.py
autogpt_platform/backend/**/*.{py,txt}

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

Use poetry run prefix for all Python commands, including testing, linting, formatting, and migrations

Files:

  • autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py
  • autogpt_platform/backend/backend/copilot/config.py
  • autogpt_platform/backend/backend/copilot/sdk/security_hooks.py
autogpt_platform/backend/**/*_test.py

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

autogpt_platform/backend/**/*_test.py: Always review snapshot changes with git diff before committing when updating snapshots with poetry run pytest --snapshot-update
Use pytest with snapshot testing for API responses in test files
Colocate test files with source files using the *_test.py naming convention

Files:

  • autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py
autogpt_platform/backend/backend/**/*.py

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

Use Prisma ORM for database operations in PostgreSQL with pgvector for embeddings

Files:

  • autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py
  • autogpt_platform/backend/backend/copilot/config.py
  • autogpt_platform/backend/backend/copilot/sdk/security_hooks.py
autogpt_platform/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Format Python code with poetry run format

Files:

  • autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py
  • autogpt_platform/backend/backend/copilot/config.py
  • autogpt_platform/backend/backend/copilot/sdk/security_hooks.py
autogpt_platform/backend/**/*test*.py

📄 CodeRabbit inference engine (AGENTS.md)

Run poetry run test for backend testing (runs pytest with docker based postgres + prisma)

Files:

  • autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py
🔇 Additional comments (8)
autogpt_platform/backend/backend/copilot/config.py (1)

86-89: LGTM — description accurately reflects the new concurrency semantics.

The wording change from "spawn" to "concurrent" correctly aligns with the runtime behavior introduced in security_hooks.py where task_spawn_count now decrements on task completion/failure.

autogpt_platform/backend/backend/copilot/sdk/security_hooks.py (3)

248-260: Solid concurrency-release logic with proper underflow guard.

The task_spawn_count > 0 check on both the success and failure paths is a good defensive measure preventing negative drift if the SDK were to fire a post hook without a matching pre-increment (e.g., for a denied tool call). The nonlocal sharing across closures is correct given Python's single-threaded asyncio model.


291-313: Good addition — failed tasks now correctly release their concurrency slot.

Mirrors the completion path consistently. The logging distinguishes failure from success which aids debugging.


209-213: Improved denial message is clear and actionable.

The updated message tells the user both what the limit is and what they can do about it (wait or continue in the main conversation). Good UX improvement.

autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py (2)

209-218: Good refactor of the fixture to expose all three hook handlers.

Clean unpacking pattern that makes the new concurrency tests possible while remaining backward-compatible with existing tests via pre, _, _.


272-345: Thorough tests for both the completion and failure slot-release paths.

Both tests follow the same rigorous pattern: fill to capacity → verify denial → release one slot → verify a new task is allowed. This directly validates the core behavioral change of this PR.

autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts (1)

122-122: Clean exposure of the React Query refetch capability.

Minimal addition that enables the reconnect flow in useCopilotPage without introducing new state or side effects.

autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts (1)

19-20: Reasonable reconnect constants.

3 attempts with exponential backoff (1s → 2s → 4s) is a sensible default for SSE reconnection. Total wait before giving up is ~7 seconds, which balances user experience with recovery probability.

Comment thread autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts (2)

245-246: Minor: reconnectAttemptsRef entries for errored sessions are never cleaned up.

Entries are deleted on "ready" (line 265) but persist for sessions that exhaust retries. Over a long-lived page with many failed sessions, the Map grows (though practically this is negligible). Consider clearing entries when sessionId changes or when the component unmounts if you want to be thorough.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@autogpt_platform/frontend/src/app/`(platform)/copilot/useCopilotPage.ts
around lines 245 - 246, reconnectAttemptsRef currently holds Map entries for
sessions that exhaust retries and are only deleted on the "ready" path; add
cleanup to remove entries when the active session changes and on component
unmount to prevent indefinite growth. Specifically, in the hook where sessionId
is tracked (the same area that deletes entries on "ready"), add a useEffect that
watches sessionId and deletes reconnectAttemptsRef.current.get(oldSessionId) (or
remove the key for the previous session) whenever sessionId changes, and also
return a cleanup function from a top-level useEffect to clear
reconnectAttemptsRef.current (or delete relevant keys) on unmount; keep the
existing deletion-on-"ready" logic intact.

252-280: Reconnect logic looks solid overall — one edge case to consider.

The reconnect flow is well-designed: invalidate cache → backoff → refetch → resume effect re-triggers. The cleanup properly clears pending timers on effect re-runs.

One thing to note: if refetchSession() fires and the backend reports active_stream = false (i.e., the task finished naturally while we were retrying), the resume effect won't run and status will remain "error" with no further transitions. The stale error state may confuse users since the session is actually complete. Consider invalidating the cache and checking whether the session is done post-refetch, potentially resetting the error by setting messages from the refreshed session data.

That said, the cache invalidation on line 260–262 should trigger hydratedMessages to re-derive, and the hydration effect (lines 231–239) would update messages since status is no longer "streaming" or "submitted". So the messages should render correctly even if the status label stays "error". This may be acceptable as-is — flagging for awareness.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@autogpt_platform/frontend/src/app/`(platform)/copilot/useCopilotPage.ts
around lines 252 - 280, The reconnect effect may leave UI stuck in "error" if
refetchSession returns a session where active_stream is false; to fix, after
invalidating the cache call refetchSession and inspect its result (use the
existing refetchSession() call), and if the returned session indicates finished
(active_stream === false) then update state/hydration so the error is cleared —
e.g., trigger the same message hydration path used elsewhere (set messages from
the refreshed session or call the hydration helper), reset
reconnectAttemptsRef.current.delete(sessionId) and
hasResumedRef.current.delete(sessionId), and set status to "ready" (or invoke
the existing resume/ready handler) so the UI reflects the completed session;
keep the backoff flow otherwise. Ensure you reference
getGetV2GetSessionQueryKey, queryClient.invalidateQueries, refetchSession,
reconnectAttemptsRef, and hasResumedRef when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@autogpt_platform/frontend/src/app/`(platform)/copilot/useCopilotPage.ts:
- Around line 245-246: reconnectAttemptsRef currently holds Map entries for
sessions that exhaust retries and are only deleted on the "ready" path; add
cleanup to remove entries when the active session changes and on component
unmount to prevent indefinite growth. Specifically, in the hook where sessionId
is tracked (the same area that deletes entries on "ready"), add a useEffect that
watches sessionId and deletes reconnectAttemptsRef.current.get(oldSessionId) (or
remove the key for the previous session) whenever sessionId changes, and also
return a cleanup function from a top-level useEffect to clear
reconnectAttemptsRef.current (or delete relevant keys) on unmount; keep the
existing deletion-on-"ready" logic intact.
- Around line 252-280: The reconnect effect may leave UI stuck in "error" if
refetchSession returns a session where active_stream is false; to fix, after
invalidating the cache call refetchSession and inspect its result (use the
existing refetchSession() call), and if the returned session indicates finished
(active_stream === false) then update state/hydration so the error is cleared —
e.g., trigger the same message hydration path used elsewhere (set messages from
the refreshed session or call the hydration helper), reset
reconnectAttemptsRef.current.delete(sessionId) and
hasResumedRef.current.delete(sessionId), and set status to "ready" (or invoke
the existing resume/ready handler) so the UI reflects the completed session;
keep the backoff flow otherwise. Ensure you reference
getGetV2GetSessionQueryKey, queryClient.invalidateQueries, refetchSession,
reconnectAttemptsRef, and hasResumedRef when making the change.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 2136def and 142198d.

📒 Files selected for processing (5)
  • autogpt_platform/backend/backend/copilot/config.py
  • autogpt_platform/backend/backend/copilot/sdk/security_hooks.py
  • autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py
  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (15)
autogpt_platform/frontend/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

autogpt_platform/frontend/**/*.{ts,tsx,js,jsx}: Use Node.js 21+ with pnpm package manager for frontend development
Always run 'pnpm format' for formatting and linting code in frontend development

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
autogpt_platform/frontend/**/*.{tsx,ts}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

autogpt_platform/frontend/**/*.{tsx,ts}: Use function declarations for components and handlers (not arrow functions) in React components
Only use arrow functions for small inline lambdas (map, filter, etc.) in React components
Use PascalCase for component names and camelCase with 'use' prefix for hook names in React
Use Tailwind CSS utilities only for styling in frontend components
Use design system components from 'src/components/' (atoms, molecules, organisms) in frontend development
Never use 'src/components/legacy/' in frontend code
Only use Phosphor Icons (@phosphor-icons/react) for icons in frontend components
Use generated API hooks from '@/app/api/generated/endpoints/' instead of deprecated 'BackendAPI' or 'src/lib/autogpt-server-api/
'
Use React Query for server state (via generated hooks) in frontend development
Default to client components ('use client') in Next.js; only use server components for SEO or extreme TTFB needs
Use '' component for rendering errors in frontend UI; use toast notifications for mutation errors; use 'Sentry.captureException()' for manual exceptions
Separate render logic from data/behavior in React components; keep comments minimal (code should be self-documenting)

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
autogpt_platform/frontend/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

autogpt_platform/frontend/**/*.{ts,tsx}: No barrel files or 'index.ts' re-exports in frontend code
Regenerate API hooks with 'pnpm generate:api' after backend OpenAPI spec changes in frontend development

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
autogpt_platform/frontend/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (autogpt_platform/frontend/CLAUDE.md)

autogpt_platform/frontend/src/**/*.{ts,tsx}: Fully capitalize acronyms in symbols, e.g. graphID, useBackendAPI
Use function declarations (not arrow functions) for components and handlers
Separate render logic (.tsx) from business logic (use*.ts hooks)
Use shadcn/ui (Radix UI primitives) with Tailwind CSS styling for UI components
Use Phosphor Icons only for icons
Use ErrorCard for render errors, toast for mutations, and Sentry for exceptions
Use design system components from src/components/ (atoms, molecules, organisms)
Never use src/components/__legacy__/* components
Use generated API hooks from @/app/api/__generated__/endpoints/ with pattern use{Method}{Version}{OperationName}
Use Tailwind CSS only for styling, with design tokens
Do not use useCallback or useMemo unless asked to optimize a given function
Never type with any unless a variable/attribute can ACTUALLY be of any type

autogpt_platform/frontend/src/**/*.{ts,tsx}: Structure components as ComponentName/ComponentName.tsx + useComponentName.ts + helpers.ts and use design system components from src/components/ (atoms, molecules, organisms)
Use generated API hooks from @/app/api/__generated__/endpoints/ with pattern use{Method}{Version}{OperationName} and regenerate with pnpm generate:api
Use function declarations (not arrow functions) for components and handlers
Separate render logic from business logic with component.tsx + useComponent.ts + helpers.ts structure
Colocate state when possible, avoid creating large components, use sub-components in local /components folder
Avoid large hooks, abstract logic into helpers.ts files when sensible
Use arrow functions only for callbacks, not for component declarations
Avoid comments at all times unless the code is very complex
Do not use useCallback or useMemo unless asked to optimize a given function

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
autogpt_platform/frontend/src/**/*use*.ts

📄 CodeRabbit inference engine (autogpt_platform/frontend/CLAUDE.md)

Do not type hook returns, let TypeScript infer as much as possible

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
autogpt_platform/frontend/**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

autogpt_platform/frontend/**/*.{js,jsx,ts,tsx}: Format frontend code using pnpm format
Never use components from src/components/__legacy__/*

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
autogpt_platform/frontend/**/*.{js,jsx,ts,tsx,css}

📄 CodeRabbit inference engine (AGENTS.md)

Use Tailwind CSS only for styling, use design tokens, and use Phosphor Icons only

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
autogpt_platform/frontend/src/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Do not type hook returns, let Typescript infer as much as possible

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
autogpt_platform/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Never type with any, if no types available use unknown

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
autogpt_platform/backend/**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

autogpt_platform/backend/**/*.py: Use Python 3.11 (required; managed by Poetry via pyproject.toml) for backend development
Always run 'poetry run format' (Black + isort) before linting in backend development
Always run 'poetry run lint' (ruff) after formatting in backend development

Files:

  • autogpt_platform/backend/backend/copilot/sdk/security_hooks.py
  • autogpt_platform/backend/backend/copilot/config.py
  • autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py
autogpt_platform/backend/**/*.{py,txt}

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

Use poetry run prefix for all Python commands, including testing, linting, formatting, and migrations

Files:

  • autogpt_platform/backend/backend/copilot/sdk/security_hooks.py
  • autogpt_platform/backend/backend/copilot/config.py
  • autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py
autogpt_platform/backend/backend/**/*.py

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

Use Prisma ORM for database operations in PostgreSQL with pgvector for embeddings

Files:

  • autogpt_platform/backend/backend/copilot/sdk/security_hooks.py
  • autogpt_platform/backend/backend/copilot/config.py
  • autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py
autogpt_platform/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Format Python code with poetry run format

Files:

  • autogpt_platform/backend/backend/copilot/sdk/security_hooks.py
  • autogpt_platform/backend/backend/copilot/config.py
  • autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py
autogpt_platform/backend/**/*_test.py

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

autogpt_platform/backend/**/*_test.py: Always review snapshot changes with git diff before committing when updating snapshots with poetry run pytest --snapshot-update
Use pytest with snapshot testing for API responses in test files
Colocate test files with source files using the *_test.py naming convention

Files:

  • autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py
autogpt_platform/backend/**/*test*.py

📄 CodeRabbit inference engine (AGENTS.md)

Run poetry run test for backend testing (runs pytest with docker based postgres + prisma)

Files:

  • autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py
🧠 Learnings (1)
📚 Learning: 2026-02-04T16:49:42.490Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-02-04T16:49:42.490Z
Learning: Applies to autogpt_platform/frontend/**/*.{tsx,ts} : Use React Query for server state (via generated hooks) in frontend development

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
🧬 Code graph analysis (1)
autogpt_platform/backend/backend/copilot/sdk/security_hooks.py (2)
autogpt_platform/backend/backend/data/db_manager.py (1)
  • _ (175-184)
autogpt_platform/backend/backend/util/logging.py (3)
  • info (41-43)
  • error (49-51)
  • warning (45-47)
🔇 Additional comments (9)
autogpt_platform/backend/backend/copilot/config.py (1)

86-89: LGTM! Description accurately reflects the new concurrency-limit semantics introduced in security_hooks.py.

autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts (1)

122-122: LGTM! Clean exposure of the React Query refetch handle — enables the reconnect flow in useCopilotPage without altering existing behavior.

autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts (1)

19-20: LGTM on the reconnect constants. Exponential backoff with delays of 1 s → 2 s → 4 s and a 3-attempt cap is reasonable for SSE reconnect.

autogpt_platform/backend/backend/copilot/sdk/security_hooks.py (3)

297-313: LGTM — failure path mirrors completion path.

Slot release on failure ensures failed Tasks don't permanently consume concurrency slots. Consistent with the post_tool_use_hook pattern.


210-213: Good UX improvement on the denial message. The new message clearly communicates that this is a concurrency limit (not permanent) and gives actionable advice ("wait" or "continue in main conversation").


248-260: Remove the thread safety concern — SDK hooks run on a single asyncio event loop.

The code is safe. SDK hooks are dispatched asynchronously via start_soon() (single event loop, no threading), making the nonlocal int decrement atomic. The > 0 guard remains good defensive coding, preventing underflow if a completion hook fires without a matching pre-hook increment.

Likely an incorrect or invalid review comment.

autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py (3)

209-218: LGTM — fixture cleanly exposes all three hook handlers. Function-scoped by default, ensuring each test gets isolated task_spawn_count state.


272-307: Well-structured test for slot release on completion. The fill → deny → release → allow pattern clearly validates the concurrency accounting.


310-345: Good coverage of the failure path. Mirrors the completion test, ensuring failed Tasks also release their slots.

Use a per-session set (task_tool_use_ids) to record which tool_use_ids
actually consumed a concurrency slot. Post hooks only release a slot
if the tool_use_id is in the set, preventing spurious decrements if
PostToolUse fires for a pre-denied call or the same id completes twice.

Addresses CodeRabbit review feedback.
@majdyz

majdyz commented Feb 25, 2026

Copy link
Copy Markdown
Contributor Author

Addressed CodeRabbit's review in 3c7545c: slot accounting now uses a per-session task_tool_use_ids set. Post hooks only decrement task_spawn_count if the tool_use_id was actually tracked — prevents spurious releases from pre-denied calls or double-completes.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

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

⚠️ Outside diff range comments (1)
autogpt_platform/backend/backend/copilot/sdk/security_hooks.py (1)

192-236: ⚠️ Potential issue | 🟠 Major

Reserve a Task slot only after all pre-checks pass.

task_spawn_count is incremented before _validate_tool_access and _validate_user_isolation. If either check denies, the task never starts but the slot remains consumed, which can permanently exhaust session concurrency.

Proposed fix
             # Rate-limit Task (sub-agent) spawns per session
             if tool_name == "Task":
                 # Block background task execution first — denied calls
                 # should not consume a subtask slot.
                 if tool_input.get("run_in_background"):
                     logger.info(f"[SDK] Blocked background Task, user={user_id}")
                     return cast(
                         SyncHookJSONOutput,
                         _deny(
                             "Background task execution is not supported. "
                             "Run tasks in the foreground instead "
                             "(remove the run_in_background parameter)."
                         ),
                     )
-                if task_spawn_count >= max_subtasks:
-                    logger.warning(
-                        f"[SDK] Task limit reached ({max_subtasks}), user={user_id}"
-                    )
-                    return cast(
-                        SyncHookJSONOutput,
-                        _deny(
-                            f"Maximum {max_subtasks} concurrent sub-tasks. "
-                            "Wait for running sub-tasks to finish, "
-                            "or continue in the main conversation."
-                        ),
-                    )
-                task_spawn_count += 1
-                if tool_use_id:
-                    task_tool_use_ids.add(tool_use_id)

             # Strip MCP prefix for consistent validation
             is_copilot_tool = tool_name.startswith(MCP_TOOL_PREFIX)
             clean_name = tool_name.removeprefix(MCP_TOOL_PREFIX)
@@
             # Validate user isolation
             result = _validate_user_isolation(clean_name, tool_input, user_id)
             if result:
                 return cast(SyncHookJSONOutput, result)
+
+            # Reserve a slot only for Task calls that passed all validations.
+            if tool_name == "Task":
+                if task_spawn_count >= max_subtasks:
+                    logger.warning(
+                        f"[SDK] Task limit reached ({max_subtasks}), user={user_id}"
+                    )
+                    return cast(
+                        SyncHookJSONOutput,
+                        _deny(
+                            f"Maximum {max_subtasks} concurrent sub-tasks. "
+                            "Wait for running sub-tasks to finish, "
+                            "or continue in the main conversation."
+                        ),
+                    )
+                task_spawn_count += 1
+                if tool_use_id:
+                    task_tool_use_ids.add(tool_use_id)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@autogpt_platform/backend/backend/copilot/sdk/security_hooks.py` around lines
192 - 236, The code currently increments task_spawn_count and adds to
task_tool_use_ids before running _validate_tool_access and
_validate_user_isolation, which can consume a slot on denied requests; move the
reservation logic (task_spawn_count += 1 and task_tool_use_ids.add(tool_use_id))
so it only runs after both _validate_tool_access(clean_name, ...) and
_validate_user_isolation(clean_name, ...) succeed (i.e., after is_copilot_tool
handling and both validations return falsy), and ensure any early returns
(denies) happen before modifying task_spawn_count/task_tool_use_ids; keep
references to tool_name, tool_use_id, task_spawn_count, task_tool_use_ids,
_validate_tool_access, _validate_user_isolation, MCP_TOOL_PREFIX,
is_copilot_tool, and clean_name to locate where to move the lines.
🧹 Nitpick comments (1)
autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py (1)

272-346: Add regressions for untracked and duplicate tool_use_id post events.

These tests validate release on normal completion/failure, but they don’t lock in the new defensive behavior against spurious/duplicate callbacks. Add one test for an unknown tool_use_id and one for duplicate completion calls.

Suggested test additions
+@pytest.mark.skipif(not _sdk_available(), reason="claude_agent_sdk not installed")
+@pytest.mark.asyncio
+async def test_task_slot_not_released_for_untracked_completion(_hooks):
+    pre, post, _ = _hooks
+    for i in range(2):
+        result = await pre(
+            {"tool_name": "Task", "tool_input": {"prompt": "ok"}},
+            tool_use_id=f"tu-untracked-{i}",
+            context={},
+        )
+        assert not _is_denied(result)
+
+    # Unknown completion id should not free capacity
+    await post({"tool_name": "Task", "tool_input": {}}, tool_use_id="tu-unknown", context={})
+
+    result = await pre(
+        {"tool_name": "Task", "tool_input": {"prompt": "still full"}},
+        tool_use_id="tu-untracked-2",
+        context={},
+    )
+    assert _is_denied(result)
+
+
+@pytest.mark.skipif(not _sdk_available(), reason="claude_agent_sdk not installed")
+@pytest.mark.asyncio
+async def test_task_slot_released_only_once_for_duplicate_completion(_hooks):
+    pre, post, _ = _hooks
+    for i in range(2):
+        result = await pre(
+            {"tool_name": "Task", "tool_input": {"prompt": "ok"}},
+            tool_use_id=f"tu-dup-{i}",
+            context={},
+        )
+        assert not _is_denied(result)
+
+    await post({"tool_name": "Task", "tool_input": {}}, tool_use_id="tu-dup-0", context={})
+    await post({"tool_name": "Task", "tool_input": {}}, tool_use_id="tu-dup-0", context={})
+
+    # Only one slot should be freed
+    ok = await pre(
+        {"tool_name": "Task", "tool_input": {"prompt": "one free slot"}},
+        tool_use_id="tu-dup-2",
+        context={},
+    )
+    assert not _is_denied(ok)
+
+    denied = await pre(
+        {"tool_name": "Task", "tool_input": {"prompt": "no second free slot"}},
+        tool_use_id="tu-dup-3",
+        context={},
+    )
+    assert _is_denied(denied)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py` around
lines 272 - 346, Add two regression tests in security_hooks_test.py that
exercise untracked and duplicate post callbacks: use the existing fixtures and
helpers (pre, post, post_failure, and _is_denied) to (1) call post or
post_failure with a tool_use_id that was never accepted (e.g., "tu-unknown") and
assert it is treated as a no-op (no exception and capacity remains unchanged so
a subsequent pre for a new Task is still denied if at capacity), and (2) call
post twice for the same accepted tool_use_id and assert the second call is safe
(no exception and does not double-free a slot) by checking capacity with a
subsequent pre call. Ensure tests mirror the style of
test_task_slot_released_on_completion and test_task_slot_released_on_failure and
use tool_name "Task" and _is_denied to validate capacity.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@autogpt_platform/backend/backend/copilot/sdk/security_hooks.py`:
- Around line 192-236: The code currently increments task_spawn_count and adds
to task_tool_use_ids before running _validate_tool_access and
_validate_user_isolation, which can consume a slot on denied requests; move the
reservation logic (task_spawn_count += 1 and task_tool_use_ids.add(tool_use_id))
so it only runs after both _validate_tool_access(clean_name, ...) and
_validate_user_isolation(clean_name, ...) succeed (i.e., after is_copilot_tool
handling and both validations return falsy), and ensure any early returns
(denies) happen before modifying task_spawn_count/task_tool_use_ids; keep
references to tool_name, tool_use_id, task_spawn_count, task_tool_use_ids,
_validate_tool_access, _validate_user_isolation, MCP_TOOL_PREFIX,
is_copilot_tool, and clean_name to locate where to move the lines.

---

Nitpick comments:
In `@autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py`:
- Around line 272-346: Add two regression tests in security_hooks_test.py that
exercise untracked and duplicate post callbacks: use the existing fixtures and
helpers (pre, post, post_failure, and _is_denied) to (1) call post or
post_failure with a tool_use_id that was never accepted (e.g., "tu-unknown") and
assert it is treated as a no-op (no exception and capacity remains unchanged so
a subsequent pre for a new Task is still denied if at capacity), and (2) call
post twice for the same accepted tool_use_id and assert the second call is safe
(no exception and does not double-free a slot) by checking capacity with a
subsequent pre call. Ensure tests mirror the style of
test_task_slot_released_on_completion and test_task_slot_released_on_failure and
use tool_name "Task" and _is_denied to validate capacity.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 142198d and 3c7545c.

📒 Files selected for processing (2)
  • autogpt_platform/backend/backend/copilot/sdk/security_hooks.py
  • autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (6)
autogpt_platform/backend/**/*.py

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

autogpt_platform/backend/**/*.py: Use Python 3.11 (required; managed by Poetry via pyproject.toml) for backend development
Always run 'poetry run format' (Black + isort) before linting in backend development
Always run 'poetry run lint' (ruff) after formatting in backend development

Files:

  • autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py
  • autogpt_platform/backend/backend/copilot/sdk/security_hooks.py
autogpt_platform/backend/**/*.{py,txt}

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

Use poetry run prefix for all Python commands, including testing, linting, formatting, and migrations

Files:

  • autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py
  • autogpt_platform/backend/backend/copilot/sdk/security_hooks.py
autogpt_platform/backend/**/*_test.py

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

autogpt_platform/backend/**/*_test.py: Always review snapshot changes with git diff before committing when updating snapshots with poetry run pytest --snapshot-update
Use pytest with snapshot testing for API responses in test files
Colocate test files with source files using the *_test.py naming convention

Files:

  • autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py
autogpt_platform/backend/backend/**/*.py

📄 CodeRabbit inference engine (autogpt_platform/backend/CLAUDE.md)

Use Prisma ORM for database operations in PostgreSQL with pgvector for embeddings

Files:

  • autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py
  • autogpt_platform/backend/backend/copilot/sdk/security_hooks.py
autogpt_platform/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Format Python code with poetry run format

Files:

  • autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py
  • autogpt_platform/backend/backend/copilot/sdk/security_hooks.py
autogpt_platform/backend/**/*test*.py

📄 CodeRabbit inference engine (AGENTS.md)

Run poetry run test for backend testing (runs pytest with docker based postgres + prisma)

Files:

  • autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py
🧬 Code graph analysis (2)
autogpt_platform/backend/backend/copilot/sdk/security_hooks_test.py (1)
autogpt_platform/backend/backend/copilot/sdk/security_hooks.py (1)
  • create_security_hooks (145-381)
autogpt_platform/backend/backend/copilot/sdk/security_hooks.py (1)
autogpt_platform/backend/backend/util/logging.py (3)
  • info (41-43)
  • error (49-51)
  • warning (45-47)
🔇 Additional comments (1)
autogpt_platform/backend/backend/copilot/sdk/security_hooks.py (1)

257-320: Nice hardening on slot-release accounting.

Guarding decrement with tool_use_id in task_tool_use_ids in both success and failure hooks cleanly prevents double-release and untracked release paths.

- Reset prevStatusRef when sessionId changes to prevent stale status
  from the old session triggering false reconnect/invalidation logic.
- Clear pending reconnect timer on session switch.
- Show a toast when all reconnect attempts are exhausted so the user
  knows to refresh the page.

Addresses CodeRabbit review feedback.
@majdyz

majdyz commented Feb 25, 2026

Copy link
Copy Markdown
Contributor Author

Addressed all review comments in cff210f:

  1. Stale prevStatusRef on session switch — now reset when sessionId changes, preventing old session status from triggering false reconnect/invalidation logic.
  2. Reconnect timer cleanup — pending timer is cleared on session switch.
  3. No user feedback on reconnect exhaustion — now shows a destructive toast telling the user to refresh the page.
  4. reconnectAttemptsRef — already keyed by sessionId so it's safe across switches (no cross-session leakage).

Comment thread autogpt_platform/backend/backend/copilot/sdk/security_hooks.py Outdated
- Reduce refs from 6 to 2 (timer + toast flag)
- Use state for reconnect tracking (enables UI feedback)
- Consolidate scheduleReconnect + refetch into single handleReconnect
- Remove redundant message clearing effect (now inline)
- Simplify session cleanup into focused effects
- Change staleTime from 0 to Infinity (manual invalidation already in place)
- Add max reconnect attempts (5) with error toast
- On resume, reuse existing assistant message instead of creating new one
- Prevents first assistant message from being duplicated on each reconnect
- Only creates new assistant message on initial stream or after tool results
- Invalidate session cache when clearing messages on reconnect
- Prevents hydration from re-adding old assistant messages
- Fixes duplicate first assistant message appearing on each reconnect
- Remove message clearing that caused temporary message loss
- Implement context-based deduplication for assistant messages
- Keep most complete message when duplicates found after same user message
- Rely on deduplication instead of clearing for reconnect handling
- Remove complex context-based deduplication - not needed
- Remove cache invalidation on reconnect - not needed
- Use simple ID-based deduplication only
- Trust backend to have correct data
- Add simple content-based dedup for assistant messages
- Catches duplicate first message with different IDs (hydration vs stream)
- Minimal implementation - just compare content strings
Comment thread autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts Outdated
- Log all deduplication decisions
- Show message IDs and content being compared
- Help diagnose why first message still duplicates
- Content deduplication wasn't fixing duplicate first message
- Back to simple ID-only dedup
- Trust backend to provide correct data
@majdyz
majdyz enabled auto-merge February 26, 2026 13:19
- Prevents cross-session state bleeding
- prevStatusRef now resets when switching sessions
- Fixes stale status logic causing incorrect cache invalidation
- Addresses CodeRabbit review comment
@github-project-automation github-project-automation Bot moved this from 🆕 Needs initial review to 👍🏼 Mergeable in AutoGPT development kanban Feb 26, 2026
Comment thread autogpt_platform/backend/backend/copilot/sdk/service.py
@majdyz
majdyz added this pull request to the merge queue Feb 26, 2026
Merged via the queue into dev with commit 29ca034 Feb 26, 2026
30 checks passed
@github-project-automation github-project-automation Bot moved this from 👍🏼 Mergeable to ✅ Done in AutoGPT development kanban Feb 26, 2026
@github-project-automation github-project-automation Bot moved this to Done in Frontend Feb 26, 2026
@majdyz
majdyz deleted the fix/copilot-subtask-concurrency-limit branch February 26, 2026 13:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

platform/backend AutoGPT Platform - Back end platform/frontend AutoGPT Platform - Front end size/l size/xl

Projects

Status: ✅ Done
Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants