Skip to content

feat(platform/copilot): live timer stats with persisted duration - #12583

Merged
0ubbe merged 11 commits into
devfrom
feat/copilot-live-timer-stats
Mar 30, 2026
Merged

feat(platform/copilot): live timer stats with persisted duration#12583
0ubbe merged 11 commits into
devfrom
feat/copilot-live-timer-stats

Conversation

@0ubbe

@0ubbe 0ubbe commented Mar 26, 2026

Copy link
Copy Markdown
Contributor

Why

The copilot chat had no indication of how long the AI spent "thinking" on a response. Users couldn't tell if a long wait was normal or something was stuck. Additionally, the thinking duration was lost on page reload since it was only tracked client-side.

What

  • Live elapsed timer: Shows elapsed time ("23s", "1m 5s") in the ThinkingIndicator while the AI is processing (appears after 20s to avoid spam on quick responses)
  • Frozen "Thought for Xm Ys": Displays the final thinking duration in TurnStatsBar after the response completes
  • Persisted duration: Saves durationMs on the last assistant message in the DB so the timer survives page reloads

How

Backend:

  • Added durationMs Int? column to ChatMessage (Prisma migration)
  • mark_session_completed in stream_registry.py computes wall-clock duration from Redis session created_at and saves it via DatabaseManager.set_turn_duration()
  • Invalidates Redis session cache after writing so GET returns fresh data

Frontend:

  • useElapsedTimer hook tracks client-side elapsed seconds during streaming
  • ThinkingIndicator shows only the elapsed time (no phrases) after 20s, with font-mono text-sm styling
  • TurnStatsBar displays "Thought for Xs" after completion, preferring live elapsedSeconds and falling back to persisted durationMs
  • convertChatSessionToUiMessages extracts duration_ms from historical messages into a Map<string, number> threaded through to ChatMessagesContainer

Test plan

  • Send a message in copilot — verify ThinkingIndicator shows elapsed time after 20s
  • After response completes — verify "Thought for Xs" appears below the response
  • Refresh the page — verify "Thought for Xs" still appears (persisted from DB)
  • Check older conversations — they should NOT show timer (no historical data)
  • Verify no Zod/SSE validation errors in browser console

🤖 Generated with Claude Code

0ubbe and others added 5 commits March 26, 2026 18:23
…lper

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…etion line

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… for live + frozen display

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add durationMs column to ChatMessage (Prisma migration)
- Compute wall-clock duration in mark_session_completed from session
  created_at and save it on the last assistant message via DatabaseManager
- Invalidate Redis session cache after setting duration so GET returns
  fresh data
- Frontend reads durationMs from historical messages and displays
  "Thought for Xm Ys" in TurnStatsBar on page reload
- Simplify ThinkingIndicator to show only elapsed time after 20s
  (no cycling phrases), with font-mono text-sm styling

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@0ubbe
0ubbe requested a review from a team as a code owner March 26, 2026 15:03
@0ubbe
0ubbe requested review from Swiftyos, Copilot and majdyz and removed request for a team March 26, 2026 15:03
@github-project-automation github-project-automation Bot moved this to 🆕 Needs initial review in AutoGPT development kanban Mar 26, 2026
@github-actions github-actions Bot added platform/frontend AutoGPT Platform - Front end platform/backend AutoGPT Platform - Back end conflicts Automatically applied to PRs with merge conflicts labels Mar 26, 2026
@github-actions

Copy link
Copy Markdown
Contributor

This pull request has conflicts with the base branch, please resolve those so we can evaluate the pull request.

@coderabbitai

coderabbitai Bot commented Mar 26, 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

Adds per-turn elapsed-time capture, persistence, and display: DB schema and models gain durationMs/duration_ms, backend computes/persists a turn duration on session completion and exposes set_turn_duration, and frontend threads historical durations and shows live elapsed timers during streaming.

Changes

Cohort / File(s) Summary
Backend Schema & Migration
autogpt_platform/backend/schema.prisma, autogpt_platform/backend/migrations/20260326120000_add_chat_message_duration_ms/migration.sql
Adds nullable durationMs Int? to ChatMessage and migration SQL to add the column.
Backend DB & Model
autogpt_platform/backend/backend/copilot/db.py, autogpt_platform/backend/backend/copilot/model.py
Batch insert accepts duration_ms → persisted durationMs; new async set_turn_duration(session_id, duration_ms) updates latest assistant ChatMessage and invalidates session cache.
Backend Session Flow
autogpt_platform/backend/backend/copilot/stream_registry.py
Parses created_at from Redis meta, computes/clamps wall-clock duration_ms on successful completion, persists via chat_db().set_turn_duration(...) before publishing StreamFinish.
Backend RPC Exposure
autogpt_platform/backend/backend/data/db_manager.py
Exposes set_turn_duration on DatabaseManager, DatabaseManagerClient, and DatabaseManagerAsyncClient.
Frontend Data Conversion
autogpt_platform/frontend/src/app/(platform)/copilot/helpers/convertChatSessionToUiMessages.ts
Includes duration_ms on raw messages; function now returns { messages, durations: Map<string, number> } mapping UI message IDs to persisted durations and preserves latest assistant segment duration when merging.
Frontend Hooks & Page
autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts, autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts, autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx
Adds and propagates historicalDurations: Map<string, number> from session hook through page hook to CopilotPage.
Frontend Prop Threading
autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx, autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/ChatMessagesContainer.tsx
Threads historicalDurations into messages container; passes per-message durationMs to TurnStatsBar and freezes elapsed when streaming stops.
Frontend Timing Utilities
autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/useElapsedTimer.ts, autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/formatElapsed.ts
Adds useElapsedTimer(isRunning) hook (1s ticks) and formatElapsed(totalSeconds) utility.
Frontend UI Updates
autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/ThinkingIndicator.tsx, autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/TurnStatsBar.tsx
ThinkingIndicator accepts elapsedSeconds and shows formatted elapsed after threshold; TurnStatsBar accepts elapsedSeconds/durationMs, prefers live elapsed, and updates separator/dot logic when time is shown.

Sequence Diagram(s)

sequenceDiagram
    participant Client as Frontend Client
    participant Stream as StreamRegistry
    participant DB as Database
    participant Cache as RedisCache

    Client->>Stream: Streaming session completes
    activate Stream
    Stream->>Stream: Read Redis meta.created_at\ncompute duration_ms = now - created_at (clamp >= 0)
    Stream->>DB: set_turn_duration(session_id, duration_ms)
    activate DB
    DB->>DB: Find latest assistant ChatMessage (max sequence)\nUpdate ChatMessage.durationMs
    DB->>Cache: invalidate_session_cache(session_id)
    activate Cache
    Cache->>Cache: Clear session cache
    deactivate Cache
    DB-->>Stream: Ack update
    deactivate DB
    Stream->>Stream: Publish StreamFinish
    deactivate Stream
    Stream-->>Client: StreamFinish event
    Client->>Client: Convert session to UI messages + durations Map
    Client->>Client: Render TurnStatsBar with persisted duration or live elapsed
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • Swiftyos
  • Bentlybro
  • Pwuts
  • kcze

Poem

🐰
I timed each hop from start to end,
From Redis burrow to DB I send,
Seconds tucked in every chat,
Shown in bars where thinkers sat,
A rabbit’s clock — precise and friend.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 37.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(platform/copilot): live timer stats with persisted duration' clearly and specifically describes the main change: adding a live timer feature to the copilot with persistent duration tracking.
Description check ✅ Passed The description is comprehensive and directly related to the changeset. It explains the why, what, and how of the feature, including both backend and frontend implementation details, and provides a test plan.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/copilot-live-timer-stats

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.

Comment thread autogpt_platform/backend/backend/copilot/stream_registry.py Outdated

Copilot AI 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.

Pull request overview

Adds end-to-end “thinking duration” tracking for Copilot turns: a live elapsed timer while streaming, plus a persisted final duration stored on the assistant message so it survives reloads.

Changes:

  • Frontend: introduce an elapsed timer hook + formatting utilities; display live elapsed time in the ThinkingIndicator (after 20s) and final “Thought for …” in the TurnStatsBar.
  • Frontend: plumb persisted durations from hydrated session history into the chat UI via a Map<messageId, durationMs>.
  • Backend: add durationMs to ChatMessage and persist wall-clock duration at stream completion.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts Exposes historicalDurations from session hydration to the page layer.
autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts Returns both hydrated UI messages and a durations map derived from session history.
autogpt_platform/frontend/src/app/(platform)/copilot/helpers/convertChatSessionToUiMessages.ts Extracts duration_ms from session messages and builds a durations map keyed by UI message id.
autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/useElapsedTimer.ts New hook to track live elapsed seconds while a stream is running.
autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/formatElapsed.ts New helper for rendering elapsed time strings (e.g., 1m 5s).
autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/TurnStatsBar.tsx Shows persisted/live “Thought for …” alongside existing counters.
autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/ThinkingIndicator.tsx Replaces cycling phrases with elapsed time display after 20s.
autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/ChatMessagesContainer.tsx Runs the timer during streaming, freezes final elapsed time, and passes persisted duration into TurnStatsBar.
autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx Threads historicalDurations into ChatMessagesContainer.
autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx Passes historicalDurations from hook layer into ChatContainer.
autogpt_platform/backend/schema.prisma Adds nullable durationMs column to ChatMessage.
autogpt_platform/backend/migrations/20260326120000_add_chat_message_duration_ms/migration.sql Prisma migration to add the durationMs column.
autogpt_platform/backend/backend/data/db_manager.py Exposes set_turn_duration through the DatabaseManager client/service wrapper.
autogpt_platform/backend/backend/copilot/stream_registry.py Computes wall-clock duration using Redis session created_at and persists it at completion.
autogpt_platform/backend/backend/copilot/model.py Adds duration_ms to API model mapping from Prisma and to DB save payloads.
autogpt_platform/backend/backend/copilot/db.py Writes durationMs on message creation and adds set_turn_duration() helper.
Comments suppressed due to low confidence (1)

autogpt_platform/backend/backend/copilot/db.py:386

  • set_turn_duration updates the last assistant message in the entire session, which can be the wrong message when a turn finishes without writing a new assistant message (e.g., user cancels quickly, provider errors before any assistant chunk is persisted). In that case this will overwrite the duration of the previous turn. Consider scoping the update to the assistant message created during the current turn, e.g., by selecting the latest assistant message with createdAt >= turn_started_at (from stream meta), or by persisting a turn_id on messages and updating by turn_id.
async def set_turn_duration(session_id: str, duration_ms: int) -> None:
    """Set durationMs on the last assistant message in a session.

    Also invalidates the Redis session cache so the next GET returns
    the updated duration.
    """
    last_msg = await PrismaChatMessage.prisma().find_first(
        where={"sessionId": session_id, "role": "assistant"},
        order={"sequence": "desc"},
    )
    if last_msg:
        await PrismaChatMessage.prisma().update(
            where={"id": last_msg.id},
            data={"durationMs": duration_ms},
        )
        # Invalidate cache so the session is re-fetched from DB with durationMs
        from backend.copilot.model import invalidate_session_cache

        await invalidate_session_cache(session_id)

Comment thread autogpt_platform/backend/backend/copilot/stream_registry.py Outdated
Comment thread autogpt_platform/backend/backend/copilot/stream_registry.py

@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: 2

🧹 Nitpick comments (1)
autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/formatElapsed.ts (1)

1-7: Consider rounding seconds for consistent display.

If totalSeconds contains a fractional component (e.g., from durationMs / 1000), the modulo will preserve decimals, displaying "5.7s" instead of "6s". Since TurnStatsBar uses Math.round(durationMs / 1000) before calling this, it's currently safe, but making this function defensive would prevent future misuse.

🔧 Optional: Round seconds for robustness
 export function formatElapsed(totalSeconds: number): string {
-  const minutes = Math.floor(totalSeconds / 60);
-  const seconds = totalSeconds % 60;
+  const total = Math.round(totalSeconds);
+  const minutes = Math.floor(total / 60);
+  const seconds = total % 60;

   if (minutes === 0) return `${seconds}s`;
   return `${minutes}m ${seconds}s`;
 }
🤖 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/components/JobStatsBar/formatElapsed.ts
around lines 1 - 7, The formatElapsed function is vulnerable to fractional
seconds (e.g., 5.7s) because it computes seconds with a modulo that preserves
decimals; make it defensive by first rounding totalSeconds (or computing minutes
with Math.floor on totalSeconds and seconds with Math.round(totalSeconds -
minutes*60)), and handle the edge case where seconds rounds to 60 by
incrementing minutes and setting seconds to 0 before returning `${minutes}m
${seconds}s` or `${seconds}s`; update the function formatElapsed accordingly so
callers like TurnStatsBar are protected from fractional inputs.
🤖 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/db.py`:
- Around line 382-384: The local import of invalidate_session_cache should be
moved to the module-level imports; locate the inner import statement "from
backend.copilot.model import invalidate_session_cache" and remove it, then add
"from backend.copilot.model import invalidate_session_cache" to the top of the
file alongside the other imports so the function is imported at module load time
and no inner/local imports remain.

In `@autogpt_platform/backend/backend/copilot/stream_registry.py`:
- Around line 814-828: The inner import of chat_db inside stream_registry.py
should be moved to the module top-level imports: remove the local "from
backend.data.db_accessors import chat_db" and add that import alongside the
other top imports in stream_registry.py so chat_db is imported once at module
load; leave the duration calculation and the await
chat_db().set_turn_duration(session_id, duration_ms) call unchanged (references:
chat_db and set_turn_duration) to avoid inner imports that violate the project's
import guidelines.

---

Nitpick comments:
In
`@autogpt_platform/frontend/src/app/`(platform)/copilot/components/JobStatsBar/formatElapsed.ts:
- Around line 1-7: The formatElapsed function is vulnerable to fractional
seconds (e.g., 5.7s) because it computes seconds with a modulo that preserves
decimals; make it defensive by first rounding totalSeconds (or computing minutes
with Math.floor on totalSeconds and seconds with Math.round(totalSeconds -
minutes*60)), and handle the edge case where seconds rounds to 60 by
incrementing minutes and setting seconds to 0 before returning `${minutes}m
${seconds}s` or `${seconds}s`; update the function formatElapsed accordingly so
callers like TurnStatsBar are protected from fractional inputs.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 23952b29-d315-44b4-9c23-da546cfc20b3

📥 Commits

Reviewing files that changed from the base of the PR and between 28b26dd and cacdf60.

📒 Files selected for processing (16)
  • autogpt_platform/backend/backend/copilot/db.py
  • autogpt_platform/backend/backend/copilot/model.py
  • autogpt_platform/backend/backend/copilot/stream_registry.py
  • autogpt_platform/backend/backend/data/db_manager.py
  • autogpt_platform/backend/migrations/20260326120000_add_chat_message_duration_ms/migration.sql
  • autogpt_platform/backend/schema.prisma
  • autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/ChatMessagesContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/ThinkingIndicator.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/TurnStatsBar.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/formatElapsed.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/useElapsedTimer.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/helpers/convertChatSessionToUiMessages.ts
  • 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). (2)
  • GitHub Check: Agent
  • GitHub Check: Seer Code Review
🧰 Additional context used
📓 Path-based instructions (18)
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/components/JobStatsBar/formatElapsed.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/useElapsedTimer.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/ThinkingIndicator.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/ChatMessagesContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/helpers/convertChatSessionToUiMessages.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/TurnStatsBar.tsx
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/components/JobStatsBar/formatElapsed.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/useElapsedTimer.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/ThinkingIndicator.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/ChatMessagesContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/helpers/convertChatSessionToUiMessages.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/TurnStatsBar.tsx
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

autogpt_platform/frontend/**/*.{ts,tsx}: Fully capitalize acronyms in symbols, e.g. graphID, useBackendAPI
Use function declarations (not arrow functions) for components and handlers
No dark: Tailwind classes — the design system handles dark mode
No any types unless the value genuinely can be anything
No linter suppressors (// @ts-ignore``, // eslint-disable) — fix the actual issue instead
Keep files under ~200 lines; extract sub-components or hooks into their own files when a file grows beyond this threshold
Keep render functions and hooks under ~50 lines; extract named helpers or sub-components when they grow longer
Use generated API hooks from `@/app/api/generated/endpoints/` following the pattern `use{Method}{Version}{OperationName}`; regenerate with `pnpm generate:api`
Use Tailwind CSS only for styling; use design tokens and Phosphor Icons only (no other icon libraries)
Do not use `useCallback` or `useMemo` unless asked to optimize a given function

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/formatElapsed.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/useElapsedTimer.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/ThinkingIndicator.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/ChatMessagesContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/helpers/convertChatSessionToUiMessages.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/TurnStatsBar.tsx
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__/*

Refer to @frontend/CLAUDE.md for frontend-specific commands, architecture, and development patterns

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/formatElapsed.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/useElapsedTimer.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/ThinkingIndicator.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/ChatMessagesContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/helpers/convertChatSessionToUiMessages.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/TurnStatsBar.tsx
autogpt_platform/frontend/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

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/components/JobStatsBar/formatElapsed.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/useElapsedTimer.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/ThinkingIndicator.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/ChatMessagesContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/helpers/convertChatSessionToUiMessages.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/TurnStatsBar.tsx
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/components/JobStatsBar/formatElapsed.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/useElapsedTimer.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/ThinkingIndicator.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/ChatMessagesContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/helpers/convertChatSessionToUiMessages.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/TurnStatsBar.tsx
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/components/JobStatsBar/formatElapsed.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/useElapsedTimer.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/helpers/convertChatSessionToUiMessages.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/components/JobStatsBar/formatElapsed.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/useElapsedTimer.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/ThinkingIndicator.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/ChatMessagesContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/helpers/convertChatSessionToUiMessages.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/TurnStatsBar.tsx
autogpt_platform/frontend/**/*.ts

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

autogpt_platform/frontend/**/*.ts: Extract component logic into custom hooks grouped by concern, not by component; put each hook in its own .ts file
Do not type hook returns; let TypeScript infer as much as possible

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/formatElapsed.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/useElapsedTimer.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/helpers/convertChatSessionToUiMessages.ts
autogpt_platform/frontend/src/**

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

Avoid index and barrel files

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/formatElapsed.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/useElapsedTimer.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/ThinkingIndicator.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/ChatMessagesContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/helpers/convertChatSessionToUiMessages.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/TurnStatsBar.tsx
autogpt_platform/frontend/src/**/*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

Component props should be interface Props { ... } (not exported) unless the interface needs to be used outside the component

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/ThinkingIndicator.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/ChatMessagesContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/TurnStatsBar.tsx
autogpt_platform/frontend/src/app/(platform)/**/*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

If adding protected frontend routes, update frontend/lib/supabase/middleware.ts

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/ThinkingIndicator.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/ChatMessagesContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/TurnStatsBar.tsx
autogpt_platform/frontend/**/*.tsx

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

autogpt_platform/frontend/**/*.tsx: Use Next.js <Link> for internal navigation — never raw <a> tags
Put sub-components in local components/ folder; component props should be type Props = { ... } (not exported) unless it needs to be used outside the component
Use design system components from src/components/ (atoms, molecules, organisms); never use src/components/__legacy__/*

Files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/ThinkingIndicator.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/ChatMessagesContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/TurnStatsBar.tsx
autogpt_platform/backend/schema.prisma

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

Run database migrations with 'poetry run prisma migrate dev' and 'poetry run prisma generate' after schema changes in backend

Files:

  • autogpt_platform/backend/schema.prisma
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

Refer to @backend/CLAUDE.md for backend-specific commands, architecture, and development tasks

autogpt_platform/backend/**/*.py: Import only at the top level; no local/inner imports except for lazy imports of heavy optional dependencies like openpyxl
Use absolute imports with from backend.module import ... for cross-package imports; single-dot relative imports (from .sibling import ...) are acceptable for sibling modules within the same package; avoid double-dot relative imports (from ..parent import ...)
Do not use duck typing with hasattr(), getattr(), or isinstance() for type dispatch; use typed interfaces, unions, or protocols instead
Use Pydantic models for structured data instead of dataclasses, namedtuples, or dicts
Do not use linter suppressors; no # type: ignore, # noqa, or # pyright: ignore comments — fix the underlying type/code issue instead
Use list comprehensions instead of manual loop-and-append patterns
Use early return guard clauses to avoid deep nesting
Use %s for deferred interpolation in debug log statements; use f-strings for readability in other log levels (e.g., logger.debug("Processing %s items", count), logger.info(f"Processing {count} items"))
Sanitize error paths using os.path.basename() in error messages to avoid leaking directory structure
Avoid TOCTOU (time-of-check-time-of-use) patterns; do not use check-then-act patterns for file access and credit charging operations
Use Redis pipelines with transaction=True for atomicity on multi-step Redis operations
Use max(0, value) guards for computed values that should never be negative
Keep files under ~300 lines; if a file grows beyond this, split by responsibility (extract h...

Files:

  • autogpt_platform/backend/backend/copilot/model.py
  • autogpt_platform/backend/backend/copilot/db.py
  • autogpt_platform/backend/backend/copilot/stream_registry.py
  • autogpt_platform/backend/backend/data/db_manager.py
autogpt_platform/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Format Python code with poetry run format

Files:

  • autogpt_platform/backend/backend/copilot/model.py
  • autogpt_platform/backend/backend/copilot/db.py
  • autogpt_platform/backend/backend/copilot/stream_registry.py
  • autogpt_platform/backend/backend/data/db_manager.py
autogpt_platform/backend/backend/data/**/*.py

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

All data access in backend requires user ID checks; verify this for any 'data/*.py' changes

Files:

  • autogpt_platform/backend/backend/data/db_manager.py
autogpt_platform/**/data/*.py

📄 CodeRabbit inference engine (AGENTS.md)

For changes touching data/*.py, validate user ID checks or explain why not needed

Files:

  • autogpt_platform/backend/backend/data/db_manager.py
🧠 Learnings (25)
📓 Common learnings
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12445
File: autogpt_platform/backend/backend/copilot/sdk/service.py:1071-1072
Timestamp: 2026-03-17T06:48:26.471Z
Learning: In Significant-Gravitas/AutoGPT (autogpt_platform), the AI SDK enforces `z.strictObject({type, errorText})` on SSE `StreamError` responses, so additional fields like `retryable: bool` cannot be added to `StreamError` or serialized via `to_sse()`. Instead, retry signaling for transient Anthropic API errors is done via the `COPILOT_RETRYABLE_ERROR_PREFIX` constant prepended to persisted session messages (in `ChatMessage.content`). The frontend detects retryable errors by checking `markerType === "retryable_error"` from `parseSpecialMarkers()` — no SSE schema changes and no string matching on error text. This pattern was established in PR `#12445`, commit 64d82797b.
📚 Learning: 2026-02-26T17:02:22.448Z
Learnt from: Pwuts
Repo: Significant-Gravitas/AutoGPT PR: 12211
File: .pre-commit-config.yaml:160-179
Timestamp: 2026-02-26T17:02:22.448Z
Learning: Keep the pre-commit hook pattern broad for autogpt_platform/backend to ensure OpenAPI schema changes are captured. Do not narrow to backend/api/ alone, since the generated schema depends on Pydantic models across multiple directories (backend/data/, backend/blocks/, backend/copilot/, backend/integrations/, backend/util/). Narrowing could miss schema changes and cause frontend type desynchronization.

Applied to files:

  • autogpt_platform/backend/migrations/20260326120000_add_chat_message_duration_ms/migration.sql
  • autogpt_platform/backend/schema.prisma
  • autogpt_platform/backend/backend/copilot/model.py
  • autogpt_platform/backend/backend/copilot/db.py
  • autogpt_platform/backend/backend/copilot/stream_registry.py
  • autogpt_platform/backend/backend/data/db_manager.py
📚 Learning: 2026-03-24T02:23:31.305Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12526
File: autogpt_platform/frontend/src/app/(platform)/copilot/components/RateLimitResetDialog/RateLimitResetDialog.tsx:0-0
Timestamp: 2026-03-24T02:23:31.305Z
Learning: In the Copilot platform UI code, follow the established Orval hook `onError` error-handling convention: first explicitly detect/handle `ApiError`, then read `error.response?.detail` (if present) as the primary message; if not available, fall back to `error.message`; and finally fall back to a generic string message. This convention should be used for generated Orval hooks even if the custom Orval mutator already maps details into `ApiError.message`, to keep consistency across hooks/components (e.g., `useCronSchedulerDialog.ts`, `useRunGraph.ts`, and rate-limit/reset flows).

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/formatElapsed.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/useElapsedTimer.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/ThinkingIndicator.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/ChatMessagesContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/helpers/convertChatSessionToUiMessages.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/TurnStatsBar.tsx
📚 Learning: 2026-03-11T08:40:59.673Z
Learnt from: kcze
Repo: Significant-Gravitas/AutoGPT PR: 12328
File: autogpt_platform/frontend/src/app/(platform)/copilot/useLoadMoreMessages.ts:49-61
Timestamp: 2026-03-11T08:40:59.673Z
Learning: In `autogpt_platform/frontend/src/app/(platform)/copilot/useLoadMoreMessages.ts`, clearing `olderMessages` (and resetting `oldestSequence`/`hasMore`) when `initialOldestSequence` shifts on the same session is intentional. Pages already fetched were based on a now-stale cursor; retaining them risks sequence gaps or duplicates. `ScrollPreserver` keeps the currently visible viewport intact, so only unvisited older pages are dropped. This is a deliberate safe-refetch design tradeoff.

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/ChatMessagesContainer.tsx
📚 Learning: 2026-03-17T06:18:51.570Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12445
File: autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx:55-67
Timestamp: 2026-03-17T06:18:51.570Z
Learning: In `autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx`, an explicit `isBusy` guard on the retry handler (`handleRetry`) is not needed. Once `onSend` is invoked, the chat status immediately transitions to "submitted", which causes the `ErrorCard` (containing the retry button) to unmount before a second click can register, making double-send impossible by design.

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/ThinkingIndicator.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/ChatMessagesContainer.tsx
📚 Learning: 2026-02-26T10:12:58.845Z
Learnt from: 0ubbe
Repo: Significant-Gravitas/AutoGPT PR: 12207
File: autogpt_platform/frontend/src/components/ai-elements/conversation.tsx:0-0
Timestamp: 2026-02-26T10:12:58.845Z
Learning: Guideline: Do not apply dark mode CSS classes (e.g., dark:text-*) to copilot UI components until dark mode support is implemented. Applies to all copilot-related components (paths containing /copilot/). When reviewing, search for dark:* class names within copilot components and refactor to use conditional class sets or feature-flag gates, ensuring no dark-mode styles are present in the code paths that render copilot UI unless dark mode support is officially enabled.

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/ThinkingIndicator.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/ChatMessagesContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/TurnStatsBar.tsx
📚 Learning: 2026-02-27T10:45:49.499Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12213
File: autogpt_platform/frontend/src/app/(platform)/copilot/tools/RunMCPTool/helpers.tsx:23-24
Timestamp: 2026-02-27T10:45:49.499Z
Learning: Prefer using generated OpenAPI types from '@/app/api/__generated__/' for payloads defined in openapi.json (e.g., MCPToolsDiscoveredResponse, MCPToolOutputResponse). Use inline TypeScript interfaces only for payloads that are SSE-stream-only and not exposed via OpenAPI. Apply this pattern to frontend tool components (e.g., RunMCPTool) and related areas where similar SSE/openapi-discrepancies occur; avoid re-implementing types when a generated type is available.

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/ThinkingIndicator.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/ChatMessagesContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/TurnStatsBar.tsx
📚 Learning: 2026-03-24T02:05:04.672Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12526
File: autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx:0-0
Timestamp: 2026-03-24T02:05:04.672Z
Learning: When gating React component logic on a React Query result (e.g., hooks like `useQuery` / `useGetV2GetCopilotUsage`), prefer destructuring and checking `isSuccess` (or aliasing it to a meaningful boolean like `isSuccess: hasUsage`) instead of relying on `!isLoading`. Reason: `isLoading` can be `false` in error/idle states where `data` may still be `undefined`, while `isSuccess` indicates the query completed successfully and `data` is populated.

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/ThinkingIndicator.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/ChatMessagesContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/TurnStatsBar.tsx
📚 Learning: 2026-03-04T23:58:18.476Z
Learnt from: Pwuts
Repo: Significant-Gravitas/AutoGPT PR: 12284
File: autogpt_platform/frontend/src/app/api/openapi.json:11897-11900
Timestamp: 2026-03-04T23:58:18.476Z
Learning: Repo: Significant-Gravitas/AutoGPT — PR `#12284`
Backend/frontend OpenAPI codegen convention: In backend/api/features/store/model.py, the StoreSubmission and StoreSubmissionAdminView models define submitted_at: datetime | None, changes_summary: str | None, and instructions: str | None with no default. This is intentional to produce “required but nullable” fields in OpenAPI (properties appear in required[] and use anyOf [type, null]). This matches Prisma’s submittedAt DateTime? and changesSummary String?. Do not flag this as a required/nullable mismatch.

Applied to files:

  • autogpt_platform/backend/schema.prisma
  • autogpt_platform/backend/backend/copilot/model.py
📚 Learning: 2026-03-17T06:48:26.471Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12445
File: autogpt_platform/backend/backend/copilot/sdk/service.py:1071-1072
Timestamp: 2026-03-17T06:48:26.471Z
Learning: In Significant-Gravitas/AutoGPT (autogpt_platform), the AI SDK enforces `z.strictObject({type, errorText})` on SSE `StreamError` responses, so additional fields like `retryable: bool` cannot be added to `StreamError` or serialized via `to_sse()`. Instead, retry signaling for transient Anthropic API errors is done via the `COPILOT_RETRYABLE_ERROR_PREFIX` constant prepended to persisted session messages (in `ChatMessage.content`). The frontend detects retryable errors by checking `markerType === "retryable_error"` from `parseSpecialMarkers()` — no SSE schema changes and no string matching on error text. This pattern was established in PR `#12445`, commit 64d82797b.

Applied to files:

  • autogpt_platform/backend/schema.prisma
  • autogpt_platform/backend/backend/copilot/stream_registry.py
  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/ChatMessagesContainer.tsx
📚 Learning: 2026-03-05T00:13:52.412Z
Learnt from: Pwuts
Repo: Significant-Gravitas/AutoGPT PR: 12284
File: autogpt_platform/backend/schema.prisma:284-284
Timestamp: 2026-03-05T00:13:52.412Z
Learning: In `autogpt_platform/backend/schema.prisma`, the `AgentGraph` ↔ `StoreListing` relation uses the pattern: `AgentGraph` declares `StoreListing? relation(fields: [id], references: [agentGraphId], onDelete: NoAction)` and `StoreListing` declares `AgentGraph AgentGraph[]` with `agentGraphId String unique`. This is intentional and valid because `AgentGraph` has a composite PK `@id([id, version])` (multiple rows per graph id, one per version), while `StoreListing.agentGraphId` is `unique` (one listing per graph id). The `fields: [id], references: [agentGraphId]` on the `AgentGraph` side joins `AgentGraph.id` against `StoreListing.agentGraphId`. Do NOT flag this as a cardinality mismatch or malformed relation — `prisma validate` passes cleanly.

Applied to files:

  • autogpt_platform/backend/schema.prisma
📚 Learning: 2026-03-04T08:04:35.881Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12273
File: autogpt_platform/backend/backend/copilot/tools/workspace_files.py:216-220
Timestamp: 2026-03-04T08:04:35.881Z
Learning: In the AutoGPT Copilot backend, ensure that SVG images are not treated as vision image types by excluding 'image/svg+xml' from INLINEABLE_MIME_TYPES and MULTIMODAL_TYPES in tool_adapter.py; the Claude API supports PNG, JPEG, GIF, and WebP for vision. SVGs (XML text) should be handled via the text path instead, not the vision path.

Applied to files:

  • autogpt_platform/backend/backend/copilot/model.py
  • autogpt_platform/backend/backend/copilot/db.py
  • autogpt_platform/backend/backend/copilot/stream_registry.py
📚 Learning: 2026-03-05T15:42:08.207Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 12297
File: .claude/skills/backend-check/SKILL.md:14-16
Timestamp: 2026-03-05T15:42:08.207Z
Learning: In Python files under autogpt_platform/backend (recursively), rely on poetry run format to perform formatting (Black + isort) and linting (ruff). Do not run poetry run lint as a separate step after poetry run format, since format already includes linting checks.

Applied to files:

  • autogpt_platform/backend/backend/copilot/model.py
  • autogpt_platform/backend/backend/copilot/db.py
  • autogpt_platform/backend/backend/copilot/stream_registry.py
  • autogpt_platform/backend/backend/data/db_manager.py
📚 Learning: 2026-03-16T16:35:40.236Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12440
File: autogpt_platform/backend/backend/api/features/workflow_import.py:54-63
Timestamp: 2026-03-16T16:35:40.236Z
Learning: Avoid using the word 'competitor' in public-facing identifiers and text. Use neutral naming for API paths, model names, function names, and UI text. Examples: rename 'CompetitorFormat' to 'SourcePlatform', 'convert_competitor_workflow' to 'convert_workflow', '/competitor-workflow' to '/workflow'. Apply this guideline to files under autogpt_platform/backend and autogpt_platform/frontend.

Applied to files:

  • autogpt_platform/backend/backend/copilot/model.py
  • autogpt_platform/backend/backend/copilot/db.py
  • autogpt_platform/backend/backend/copilot/stream_registry.py
  • autogpt_platform/backend/backend/data/db_manager.py
📚 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 PascalCase for component names and camelCase with 'use' prefix for hook names in React

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/useElapsedTimer.ts
  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
📚 Learning: 2026-03-20T09:30:38.372Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: autogpt_platform/frontend/CLAUDE.md:0-0
Timestamp: 2026-03-20T09:30:38.372Z
Learning: Applies to autogpt_platform/frontend/**/*.{ts,tsx} : Do not use `useCallback` or `useMemo` unless asked to optimize a given function

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/useElapsedTimer.ts
📚 Learning: 2026-02-04T16:50:51.495Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-04T16:50:51.495Z
Learning: Applies to autogpt_platform/frontend/src/**/*.{ts,tsx} : Do not use `useCallback` or `useMemo` unless asked to optimize a given function

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/useElapsedTimer.ts
📚 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 function declarations for components and handlers (not arrow functions) in React components

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/useElapsedTimer.ts
📚 Learning: 2026-03-20T09:30:38.372Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: autogpt_platform/frontend/CLAUDE.md:0-0
Timestamp: 2026-03-20T09:30:38.372Z
Learning: Applies to autogpt_platform/frontend/**/*.{ts,tsx} : Use function declarations (not arrow functions) for components and handlers

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/useElapsedTimer.ts
📚 Learning: 2026-03-13T15:49:44.961Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12385
File: autogpt_platform/backend/backend/copilot/rate_limit.py:0-0
Timestamp: 2026-03-13T15:49:44.961Z
Learning: In `autogpt_platform/backend/backend/copilot/rate_limit.py`, the original per-session token window (with a TTL-based reset) was replaced with fixed daily and weekly windows. `resets_at` is now derived from `_daily_reset_time()` (midnight UTC) and `_weekly_reset_time()` (next Monday 00:00 UTC) — deterministic fixed-boundary calculations that require no Redis TTL introspection.

Applied to files:

  • autogpt_platform/backend/backend/copilot/stream_registry.py
📚 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} : Separate render logic from data/behavior in React components; keep comments minimal (code should be self-documenting)

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/ThinkingIndicator.tsx
📚 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/useChatSession.ts
📚 Learning: 2026-03-24T02:05:04.672Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12526
File: autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx:0-0
Timestamp: 2026-03-24T02:05:04.672Z
Learning: In `Significant-Gravitas/AutoGPT` (autogpt_platform frontend), when gating logic on a React Query result being available (e.g., `useGetV2GetCopilotUsage`), prefer destructuring `isSuccess` (e.g., `const { data, isSuccess: hasUsage } = useQuery(...)`) over checking `!isLoading`. `isLoading` can be `false` in error/idle states where `data` is still `undefined`, while `isSuccess` guarantees the query completed successfully and `data` is populated. This pattern was established in `CopilotPage.tsx` (PR `#12526`, commit e9dfd1f76).

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts
📚 Learning: 2026-03-20T09:30:38.372Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: autogpt_platform/frontend/CLAUDE.md:0-0
Timestamp: 2026-03-20T09:30:38.372Z
Learning: Applies to autogpt_platform/frontend/**/*.tsx : Put sub-components in local `components/` folder; component props should be `type Props = { ... }` (not exported) unless it needs to be used outside the component

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/TurnStatsBar.tsx
📚 Learning: 2026-03-20T09:30:38.372Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: autogpt_platform/frontend/CLAUDE.md:0-0
Timestamp: 2026-03-20T09:30:38.372Z
Learning: Applies to autogpt_platform/frontend/**/*.{ts,tsx} : No linter suppressors (`// ts-ignore`, `// eslint-disable`) — fix the actual issue instead

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/TurnStatsBar.tsx
🔇 Additional comments (23)
autogpt_platform/backend/schema.prisma (1)

249-250: LGTM!

The new nullable durationMs column is well-placed and correctly typed. The inline comment clearly explains its purpose for wall-clock timing of assistant turns.

autogpt_platform/backend/migrations/20260326120000_add_chat_message_duration_ms/migration.sql (1)

1-2: LGTM!

Simple, safe additive migration. The nullable column addition requires no default value and is backward-compatible.

autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/ThinkingIndicator.tsx (1)

12-23: LGTM!

Clean refactor that replaces the cycling phrase animation with a conditional elapsed-time display. The 20-second threshold prevents noise for quick responses, and tabular-nums ensures stable layout as digits change.

autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx (1)

92-94: LGTM!

Clean prop threading of historicalDurations from the hook through to ChatContainer.

Also applies to: 148-148

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

42-43: LGTM!

Proper pass-through of historicalDurations from useChatSession to the component layer.

Also applies to: 379-381

autogpt_platform/backend/backend/copilot/model.py (3)

57-57: LGTM!

Correct addition of duration_ms field to the Pydantic model with proper nullable typing.


70-70: LGTM!

Proper mapping from Prisma's durationMs to Pydantic's duration_ms in the from_db factory method.


566-566: LGTM!

Correctly includes duration_ms in the message data payload for database persistence.

autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx (1)

30-31: LGTM!

Well-documented optional prop with proper typing. Clean threading of historicalDurations to ChatMessagesContainer for downstream consumption.

Also applies to: 49-49, 87-87

autogpt_platform/backend/backend/copilot/db.py (2)

220-222: LGTM!

The mapping from duration_ms in the incoming message dict to durationMs in the Prisma column follows the existing pattern for optional fields in this function.


367-385: ⚠️ Potential issue | 🔴 Critical

Correct the ownership validation claim and verify set_turn_duration's exposure via RPC.

The original review comment incorrectly states that mark_session_completed validates session ownership—it does not. mark_session_completed only validates that the session status is "running" using atomic compare-and-swap. Session ownership is NOT checked within the function itself.

Additionally, set_turn_duration is exposed as an RPC endpoint via DatabaseManager (db_manager.py:347) and DatabaseManagerAsyncClient (db_manager.py:544), meaning it can be called from other services without user_id validation. The function accepts only session_id and duration_ms—no ownership parameter.

Required action: Either add an explicit user_id parameter to set_turn_duration and validate session ownership within the function, OR ensure all callers—especially those via RPC—validate ownership before invoking it. The current design relies entirely on caller responsibility, which is fragile.

⛔ Skipped due to learnings
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/constants.py:9-12
Timestamp: 2026-03-10T08:39:22.025Z
Learning: In Significant-Gravitas/AutoGPT PR `#12356`, the `COPILOT_SYNTHETIC_ID_PREFIX = "copilot-"` check in `create_auto_approval_record` (human_review.py) is intentional and safe. The `graph_exec_id` passed to this function comes from server-side `PendingHumanReview` DB records (not from user input); the API only accepts `node_exec_id` from users. Synthetic `copilot-*` IDs are only ever created server-side in `run_block.py`. The prefix skip avoids a DB lookup for a `AgentGraphExecution` record that legitimately does not exist for CoPilot sessions, while `user_id` scoping is enforced at the auth layer and on the resulting auto-approval record.
autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/useElapsedTimer.ts (1)

1-31: LGTM!

The hook correctly manages the interval lifecycle:

  • Resets elapsed time and starts the timer when isRunning becomes true
  • Uses Math.floor for consistent whole-second display
  • Properly cleans up the interval on unmount or when streaming ends
  • The startTimeRef check prevents timer reset if already running
autogpt_platform/backend/backend/copilot/stream_registry.py (1)

114-131: LGTM!

The created_at parsing logic handles edge cases well:

  • Falls back to current UTC time when the field is missing or invalid
  • Uses fromisoformat which matches the format stored in create_session
  • Catches both ValueError and TypeError for robustness
autogpt_platform/backend/backend/data/db_manager.py (2)

347-347: LGTM!

The set_turn_duration endpoint is properly wired to the underlying chat_db.set_turn_duration function following the established pattern.


544-544: LGTM!

The async client properly exposes the new set_turn_duration method, consistent with how other CoPilot Chat Session methods are wired.

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

64-79: LGTM!

The hook correctly:

  • Returns an empty Map as fallback when session isn't ready
  • Destructures both messages and durations from the updated convertChatSessionMessagesToUiMessages
  • Maintains proper memoization to prevent infinite loops

133-133: LGTM!

The historicalDurations is properly exposed in the hook's return value for downstream consumption.

autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/ChatMessagesContainer.tsx (2)

145-161: LGTM with a note on the pattern.

The ref-based state tracking correctly:

  • Resets the frozen elapsed time when a new streaming turn begins
  • Captures the latest elapsed value during streaming
  • Preserves the final value when streaming ends for display in TurnStatsBar

This pattern avoids unnecessary re-renders while tracking mutable state across renders.


259-275: LGTM!

The timing data is correctly passed:

  • TurnStatsBar receives elapsedSeconds only for the final message (live timer fallback)
  • TurnStatsBar receives durationMs from historicalDurations for persisted display
  • ThinkingIndicator receives the live elapsedSeconds for real-time display
autogpt_platform/frontend/src/app/(platform)/copilot/components/JobStatsBar/TurnStatsBar.tsx (2)

11-28: LGTM!

The display logic correctly prioritizes:

  1. Live elapsedSeconds when actively streaming
  2. Persisted durationMs (converted to seconds) for historical messages
  3. Falls back gracefully when neither is available

30-49: LGTM!

The "Thought for X" prefix with tabular-nums styling and correct dot separator logic provides a clean display that integrates well with the existing work counters.

autogpt_platform/frontend/src/app/(platform)/copilot/helpers/convertChatSessionToUiMessages.ts (2)

104-123: LGTM!

The function signature and return type are correctly updated to return both messages and the durations map. The explicit return type is appropriate for this helper function (not a hook).


194-212: LGTM!

The duration handling correctly:

  • Captures the last assistant segment's duration when merging consecutive messages (line 198)
  • Associates durations with the final msgId for both merged and new assistant messages
  • Only stores non-null durations in the map

Comment thread autogpt_platform/backend/backend/copilot/db.py Outdated
Comment thread autogpt_platform/backend/backend/copilot/stream_registry.py Outdated
Comment thread autogpt_platform/backend/backend/copilot/stream_registry.py
Comment thread autogpt_platform/backend/backend/copilot/db.py
Comment thread autogpt_platform/backend/backend/copilot/model.py Outdated
Comment thread autogpt_platform/backend/backend/copilot/stream_registry.py
Comment thread autogpt_platform/backend/backend/copilot/db.py Outdated
- Skip duration persistence on error (sentry bug report)
- Check raw created_at from Redis instead of parsed fallback to avoid
  storing durationMs=0 for pre-existing sessions (majdyz, copilot-reviewer)
- Handle naive datetime by normalizing to UTC (copilot-reviewer)
- Move chat_db import to top-level in stream_registry.py (coderabbitai)
- Move invalidate_session_cache import to top-level in db.py (coderabbitai, majdyz)
- Remove duration_ms from _save_session_to_db to prevent race condition
  where delayed cache flush could overwrite correct value (majdyz)
- Move ref mutations from render phase to useEffect in
  ChatMessagesContainer (majdyz)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot removed the conflicts Automatically applied to PRs with merge conflicts label Mar 27, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Conflicts have been resolved! 🎉 A maintainer will review the pull request shortly.

@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 (1)
autogpt_platform/backend/backend/copilot/stream_registry.py (1)

115-122: Consider normalizing naive datetimes in _parse_session_meta for consistency.

The mark_session_completed function (line 824-825) normalizes naive datetimes by adding UTC timezone, but _parse_session_meta does not. If Redis contains a naive datetime string (without timezone info), ActiveSession.created_at will be naive while datetime.now(timezone.utc) is aware.

This could cause subtle issues in get_active_session (line 978) where created_at is used for age calculations. While Python 3.11+ may handle mixed-awareness subtraction, it's safer to be consistent.

♻️ Suggested fix for consistency
     created_at = datetime.now(timezone.utc)
     created_at_raw = meta.get("created_at")
     if created_at_raw:
         try:
             created_at = datetime.fromisoformat(str(created_at_raw))
+            if created_at.tzinfo is None:
+                created_at = created_at.replace(tzinfo=timezone.utc)
         except (ValueError, TypeError):
             pass
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@autogpt_platform/backend/backend/copilot/stream_registry.py` around lines 115
- 122, _parsed_session_meta currently parses created_at with
datetime.fromisoformat but doesn't normalize naive datetimes, causing
ActiveSession.created_at to be naive while mark_session_completed and other code
expect UTC-aware datetimes; update _parse_session_meta to detect if the parsed
datetime (from created_at_raw) has no tzinfo and, in that case, set
tzinfo=timezone.utc (or call .replace(tzinfo=timezone.utc)) so
ActiveSession.created_at is consistently timezone-aware; reference the
_parse_session_meta function, the created_at/created_at_raw variables, and
mark_session_completed/get_active_session to ensure consistent behavior across
the codebase.
🤖 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/backend/backend/copilot/stream_registry.py`:
- Around line 115-122: _parsed_session_meta currently parses created_at with
datetime.fromisoformat but doesn't normalize naive datetimes, causing
ActiveSession.created_at to be naive while mark_session_completed and other code
expect UTC-aware datetimes; update _parse_session_meta to detect if the parsed
datetime (from created_at_raw) has no tzinfo and, in that case, set
tzinfo=timezone.utc (or call .replace(tzinfo=timezone.utc)) so
ActiveSession.created_at is consistently timezone-aware; reference the
_parse_session_meta function, the created_at/created_at_raw variables, and
mark_session_completed/get_active_session to ensure consistent behavior across
the codebase.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 80659896-3b6d-4ccc-81b4-e01da9672c12

📥 Commits

Reviewing files that changed from the base of the PR and between cacdf60 and ea46596.

📒 Files selected for processing (6)
  • autogpt_platform/backend/backend/copilot/db.py
  • autogpt_platform/backend/backend/copilot/model.py
  • autogpt_platform/backend/backend/copilot/stream_registry.py
  • autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/ChatMessagesContainer.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • autogpt_platform/backend/backend/copilot/model.py
  • autogpt_platform/backend/backend/copilot/db.py
  • autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/ChatMessagesContainer.tsx
📜 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). (12)
  • GitHub Check: check API types
  • GitHub Check: integration_test
  • GitHub Check: Seer Code Review
  • GitHub Check: type-check (3.11)
  • GitHub Check: test (3.13)
  • GitHub Check: type-check (3.12)
  • GitHub Check: test (3.12)
  • GitHub Check: test (3.11)
  • GitHub Check: type-check (3.13)
  • GitHub Check: Check PR Status
  • GitHub Check: Analyze (python)
  • GitHub Check: end-to-end tests
🧰 Additional context used
📓 Path-based instructions (12)
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/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/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

autogpt_platform/frontend/**/*.{ts,tsx}: Fully capitalize acronyms in symbols, e.g. graphID, useBackendAPI
Use function declarations (not arrow functions) for components and handlers
No dark: Tailwind classes — the design system handles dark mode
No any types unless the value genuinely can be anything
No linter suppressors (// @ts-ignore``, // eslint-disable) — fix the actual issue instead
Keep files under ~200 lines; extract sub-components or hooks into their own files when a file grows beyond this threshold
Keep render functions and hooks under ~50 lines; extract named helpers or sub-components when they grow longer
Use generated API hooks from `@/app/api/generated/endpoints/` following the pattern `use{Method}{Version}{OperationName}`; regenerate with `pnpm generate:api`
Use Tailwind CSS only for styling; use design tokens and Phosphor Icons only (no other icon libraries)
Do not use `useCallback` or `useMemo` unless asked to optimize a given function

Files:

  • 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__/*

Refer to @frontend/CLAUDE.md for frontend-specific commands, architecture, and development patterns

Files:

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

📄 CodeRabbit inference engine (AGENTS.md)

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/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/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/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/useCopilotPage.ts
autogpt_platform/frontend/**/*.ts

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

autogpt_platform/frontend/**/*.ts: Extract component logic into custom hooks grouped by concern, not by component; put each hook in its own .ts file
Do not type hook returns; let TypeScript infer as much as possible

Files:

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

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

Avoid index and barrel files

Files:

  • 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

Refer to @backend/CLAUDE.md for backend-specific commands, architecture, and development tasks

autogpt_platform/backend/**/*.py: Import only at the top level; no local/inner imports except for lazy imports of heavy optional dependencies like openpyxl
Use absolute imports with from backend.module import ... for cross-package imports; single-dot relative imports (from .sibling import ...) are acceptable for sibling modules within the same package; avoid double-dot relative imports (from ..parent import ...)
Do not use duck typing with hasattr(), getattr(), or isinstance() for type dispatch; use typed interfaces, unions, or protocols instead
Use Pydantic models for structured data instead of dataclasses, namedtuples, or dicts
Do not use linter suppressors; no # type: ignore, # noqa, or # pyright: ignore comments — fix the underlying type/code issue instead
Use list comprehensions instead of manual loop-and-append patterns
Use early return guard clauses to avoid deep nesting
Use %s for deferred interpolation in debug log statements; use f-strings for readability in other log levels (e.g., logger.debug("Processing %s items", count), logger.info(f"Processing {count} items"))
Sanitize error paths using os.path.basename() in error messages to avoid leaking directory structure
Avoid TOCTOU (time-of-check-time-of-use) patterns; do not use check-then-act patterns for file access and credit charging operations
Use Redis pipelines with transaction=True for atomicity on multi-step Redis operations
Use max(0, value) guards for computed values that should never be negative
Keep files under ~300 lines; if a file grows beyond this, split by responsibility (extract h...

Files:

  • autogpt_platform/backend/backend/copilot/stream_registry.py
autogpt_platform/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Format Python code with poetry run format

Files:

  • autogpt_platform/backend/backend/copilot/stream_registry.py
🧠 Learnings (8)
📓 Common learnings
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12445
File: autogpt_platform/backend/backend/copilot/sdk/service.py:1071-1072
Timestamp: 2026-03-17T06:48:26.471Z
Learning: In Significant-Gravitas/AutoGPT (autogpt_platform), the AI SDK enforces `z.strictObject({type, errorText})` on SSE `StreamError` responses, so additional fields like `retryable: bool` cannot be added to `StreamError` or serialized via `to_sse()`. Instead, retry signaling for transient Anthropic API errors is done via the `COPILOT_RETRYABLE_ERROR_PREFIX` constant prepended to persisted session messages (in `ChatMessage.content`). The frontend detects retryable errors by checking `markerType === "retryable_error"` from `parseSpecialMarkers()` — no SSE schema changes and no string matching on error text. This pattern was established in PR `#12445`, commit 64d82797b.
📚 Learning: 2026-03-24T02:23:31.305Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12526
File: autogpt_platform/frontend/src/app/(platform)/copilot/components/RateLimitResetDialog/RateLimitResetDialog.tsx:0-0
Timestamp: 2026-03-24T02:23:31.305Z
Learning: In the Copilot platform UI code, follow the established Orval hook `onError` error-handling convention: first explicitly detect/handle `ApiError`, then read `error.response?.detail` (if present) as the primary message; if not available, fall back to `error.message`; and finally fall back to a generic string message. This convention should be used for generated Orval hooks even if the custom Orval mutator already maps details into `ApiError.message`, to keep consistency across hooks/components (e.g., `useCronSchedulerDialog.ts`, `useRunGraph.ts`, and rate-limit/reset flows).

Applied to files:

  • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts
📚 Learning: 2026-03-13T15:49:44.961Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12385
File: autogpt_platform/backend/backend/copilot/rate_limit.py:0-0
Timestamp: 2026-03-13T15:49:44.961Z
Learning: In `autogpt_platform/backend/backend/copilot/rate_limit.py`, the original per-session token window (with a TTL-based reset) was replaced with fixed daily and weekly windows. `resets_at` is now derived from `_daily_reset_time()` (midnight UTC) and `_weekly_reset_time()` (next Monday 00:00 UTC) — deterministic fixed-boundary calculations that require no Redis TTL introspection.

Applied to files:

  • autogpt_platform/backend/backend/copilot/stream_registry.py
📚 Learning: 2026-03-17T06:48:26.471Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12445
File: autogpt_platform/backend/backend/copilot/sdk/service.py:1071-1072
Timestamp: 2026-03-17T06:48:26.471Z
Learning: In Significant-Gravitas/AutoGPT (autogpt_platform), the AI SDK enforces `z.strictObject({type, errorText})` on SSE `StreamError` responses, so additional fields like `retryable: bool` cannot be added to `StreamError` or serialized via `to_sse()`. Instead, retry signaling for transient Anthropic API errors is done via the `COPILOT_RETRYABLE_ERROR_PREFIX` constant prepended to persisted session messages (in `ChatMessage.content`). The frontend detects retryable errors by checking `markerType === "retryable_error"` from `parseSpecialMarkers()` — no SSE schema changes and no string matching on error text. This pattern was established in PR `#12445`, commit 64d82797b.

Applied to files:

  • autogpt_platform/backend/backend/copilot/stream_registry.py
📚 Learning: 2026-02-26T17:02:22.448Z
Learnt from: Pwuts
Repo: Significant-Gravitas/AutoGPT PR: 12211
File: .pre-commit-config.yaml:160-179
Timestamp: 2026-02-26T17:02:22.448Z
Learning: Keep the pre-commit hook pattern broad for autogpt_platform/backend to ensure OpenAPI schema changes are captured. Do not narrow to backend/api/ alone, since the generated schema depends on Pydantic models across multiple directories (backend/data/, backend/blocks/, backend/copilot/, backend/integrations/, backend/util/). Narrowing could miss schema changes and cause frontend type desynchronization.

Applied to files:

  • autogpt_platform/backend/backend/copilot/stream_registry.py
📚 Learning: 2026-03-04T08:04:35.881Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12273
File: autogpt_platform/backend/backend/copilot/tools/workspace_files.py:216-220
Timestamp: 2026-03-04T08:04:35.881Z
Learning: In the AutoGPT Copilot backend, ensure that SVG images are not treated as vision image types by excluding 'image/svg+xml' from INLINEABLE_MIME_TYPES and MULTIMODAL_TYPES in tool_adapter.py; the Claude API supports PNG, JPEG, GIF, and WebP for vision. SVGs (XML text) should be handled via the text path instead, not the vision path.

Applied to files:

  • autogpt_platform/backend/backend/copilot/stream_registry.py
📚 Learning: 2026-03-05T15:42:08.207Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 12297
File: .claude/skills/backend-check/SKILL.md:14-16
Timestamp: 2026-03-05T15:42:08.207Z
Learning: In Python files under autogpt_platform/backend (recursively), rely on poetry run format to perform formatting (Black + isort) and linting (ruff). Do not run poetry run lint as a separate step after poetry run format, since format already includes linting checks.

Applied to files:

  • autogpt_platform/backend/backend/copilot/stream_registry.py
📚 Learning: 2026-03-16T16:35:40.236Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12440
File: autogpt_platform/backend/backend/api/features/workflow_import.py:54-63
Timestamp: 2026-03-16T16:35:40.236Z
Learning: Avoid using the word 'competitor' in public-facing identifiers and text. Use neutral naming for API paths, model names, function names, and UI text. Examples: rename 'CompetitorFormat' to 'SourcePlatform', 'convert_competitor_workflow' to 'convert_workflow', '/competitor-workflow' to '/workflow'. Apply this guideline to files under autogpt_platform/backend and autogpt_platform/frontend.

Applied to files:

  • autogpt_platform/backend/backend/copilot/stream_registry.py
🔇 Additional comments (3)
autogpt_platform/backend/backend/copilot/stream_registry.py (2)

33-33: LGTM!

The chat_db import is correctly placed at the top level, addressing the previous review feedback.


815-841: LGTM!

The duration computation logic correctly addresses the previous review feedback:

  • Only persists duration when created_at was actually present in Redis meta (not a fallback value)
  • Skips persistence on error sessions
  • Properly normalizes naive datetimes to UTC
  • Uses max(0, ...) guard against negative values
  • Appropriate error handling with warning logs
autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts (1)

42-42: LGTM!

Clean pass-through of historicalDurations from useChatSession to the hook consumers. The implementation follows the established patterns in the file and correctly threads the duration data for the timer stats feature.

Also applies to: 381-382

- Sort chat_db import alphabetically (isort)
- Combine invalidate_session_cache with sibling .model imports
- Join multiline log string onto one line (black)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

@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 (1)
autogpt_platform/backend/backend/copilot/stream_registry.py (1)

829-833: Use f-string formatting for this warning log.

At Line 829, this warning currently uses %s/%r placeholders; repo rules prefer f-strings outside debug logs.

♻️ Proposed fix
-                logger.warning(
-                    "Failed to compute session duration for %s (created_at=%r)",
-                    session_id,
-                    created_at_raw,
-                )
+                logger.warning(
+                    f"Failed to compute session duration for {session_id} "
+                    f"(created_at={created_at_raw!r})"
+                )
As per coding guidelines, "Use `%s` for deferred interpolation in `debug` log statements; use f-strings for readability in other log levels".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@autogpt_platform/backend/backend/copilot/stream_registry.py` around lines 829
- 833, Replace the logger.warning call that uses %-style placeholders with an
f-string: update the call to logger.warning so the message text is an f-string
that interpolates session_id and created_at_raw (use the !r conversion for
created_at_raw to preserve the raw repr). Keep the same message wording ("Failed
to compute session duration for ... (created_at=...)") and only change the
formatting style in the existing logger.warning call.
🤖 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/backend/backend/copilot/stream_registry.py`:
- Around line 829-833: Replace the logger.warning call that uses %-style
placeholders with an f-string: update the call to logger.warning so the message
text is an f-string that interpolates session_id and created_at_raw (use the !r
conversion for created_at_raw to preserve the raw repr). Keep the same message
wording ("Failed to compute session duration for ... (created_at=...)") and only
change the formatting style in the existing logger.warning call.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d9748b1a-8505-4817-aae7-4976780b64a7

📥 Commits

Reviewing files that changed from the base of the PR and between ea46596 and 333d8ca.

📒 Files selected for processing (2)
  • autogpt_platform/backend/backend/copilot/db.py
  • autogpt_platform/backend/backend/copilot/stream_registry.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • autogpt_platform/backend/backend/copilot/db.py
📜 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). (12)
  • GitHub Check: check API types
  • GitHub Check: Seer Code Review
  • GitHub Check: end-to-end tests
  • GitHub Check: test (3.11)
  • GitHub Check: type-check (3.13)
  • GitHub Check: type-check (3.11)
  • GitHub Check: type-check (3.12)
  • GitHub Check: test (3.12)
  • GitHub Check: test (3.13)
  • GitHub Check: Analyze (typescript)
  • GitHub Check: Analyze (python)
  • GitHub Check: Check PR Status
🧰 Additional context used
📓 Path-based instructions (2)
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

Refer to @backend/CLAUDE.md for backend-specific commands, architecture, and development tasks

autogpt_platform/backend/**/*.py: Import only at the top level; no local/inner imports except for lazy imports of heavy optional dependencies like openpyxl
Use absolute imports with from backend.module import ... for cross-package imports; single-dot relative imports (from .sibling import ...) are acceptable for sibling modules within the same package; avoid double-dot relative imports (from ..parent import ...)
Do not use duck typing with hasattr(), getattr(), or isinstance() for type dispatch; use typed interfaces, unions, or protocols instead
Use Pydantic models for structured data instead of dataclasses, namedtuples, or dicts
Do not use linter suppressors; no # type: ignore, # noqa, or # pyright: ignore comments — fix the underlying type/code issue instead
Use list comprehensions instead of manual loop-and-append patterns
Use early return guard clauses to avoid deep nesting
Use %s for deferred interpolation in debug log statements; use f-strings for readability in other log levels (e.g., logger.debug("Processing %s items", count), logger.info(f"Processing {count} items"))
Sanitize error paths using os.path.basename() in error messages to avoid leaking directory structure
Avoid TOCTOU (time-of-check-time-of-use) patterns; do not use check-then-act patterns for file access and credit charging operations
Use Redis pipelines with transaction=True for atomicity on multi-step Redis operations
Use max(0, value) guards for computed values that should never be negative
Keep files under ~300 lines; if a file grows beyond this, split by responsibility (extract h...

Files:

  • autogpt_platform/backend/backend/copilot/stream_registry.py
autogpt_platform/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Format Python code with poetry run format

Files:

  • autogpt_platform/backend/backend/copilot/stream_registry.py
🧠 Learnings (11)
📓 Common learnings
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12445
File: autogpt_platform/backend/backend/copilot/sdk/service.py:1071-1072
Timestamp: 2026-03-17T06:48:26.471Z
Learning: In Significant-Gravitas/AutoGPT (autogpt_platform), the AI SDK enforces `z.strictObject({type, errorText})` on SSE `StreamError` responses, so additional fields like `retryable: bool` cannot be added to `StreamError` or serialized via `to_sse()`. Instead, retry signaling for transient Anthropic API errors is done via the `COPILOT_RETRYABLE_ERROR_PREFIX` constant prepended to persisted session messages (in `ChatMessage.content`). The frontend detects retryable errors by checking `markerType === "retryable_error"` from `parseSpecialMarkers()` — no SSE schema changes and no string matching on error text. This pattern was established in PR `#12445`, commit 64d82797b.
📚 Learning: 2026-03-13T15:49:44.961Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12385
File: autogpt_platform/backend/backend/copilot/rate_limit.py:0-0
Timestamp: 2026-03-13T15:49:44.961Z
Learning: In `autogpt_platform/backend/backend/copilot/rate_limit.py`, the original per-session token window (with a TTL-based reset) was replaced with fixed daily and weekly windows. `resets_at` is now derived from `_daily_reset_time()` (midnight UTC) and `_weekly_reset_time()` (next Monday 00:00 UTC) — deterministic fixed-boundary calculations that require no Redis TTL introspection.

Applied to files:

  • autogpt_platform/backend/backend/copilot/stream_registry.py
📚 Learning: 2026-03-17T06:48:26.471Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12445
File: autogpt_platform/backend/backend/copilot/sdk/service.py:1071-1072
Timestamp: 2026-03-17T06:48:26.471Z
Learning: In Significant-Gravitas/AutoGPT (autogpt_platform), the AI SDK enforces `z.strictObject({type, errorText})` on SSE `StreamError` responses, so additional fields like `retryable: bool` cannot be added to `StreamError` or serialized via `to_sse()`. Instead, retry signaling for transient Anthropic API errors is done via the `COPILOT_RETRYABLE_ERROR_PREFIX` constant prepended to persisted session messages (in `ChatMessage.content`). The frontend detects retryable errors by checking `markerType === "retryable_error"` from `parseSpecialMarkers()` — no SSE schema changes and no string matching on error text. This pattern was established in PR `#12445`, commit 64d82797b.

Applied to files:

  • autogpt_platform/backend/backend/copilot/stream_registry.py
📚 Learning: 2026-03-17T10:57:12.953Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12440
File: autogpt_platform/backend/backend/copilot/workflow_import/converter.py:0-0
Timestamp: 2026-03-17T10:57:12.953Z
Learning: In Significant-Gravitas/AutoGPT PR `#12440`, `autogpt_platform/backend/backend/copilot/workflow_import/converter.py` was fully rewritten (commit 732960e2d) to no longer make direct LLM/OpenAI API calls. The converter now builds a structured text prompt for AutoPilot/CoPilot instead. There is no `response.choices` access or any direct LLM client usage in this file. Do not flag `response.choices` access or LLM client initialization patterns as issues in this file.

Applied to files:

  • autogpt_platform/backend/backend/copilot/stream_registry.py
📚 Learning: 2026-03-04T23:58:18.476Z
Learnt from: Pwuts
Repo: Significant-Gravitas/AutoGPT PR: 12284
File: autogpt_platform/frontend/src/app/api/openapi.json:11897-11900
Timestamp: 2026-03-04T23:58:18.476Z
Learning: Repo: Significant-Gravitas/AutoGPT — PR `#12284`
Backend/frontend OpenAPI codegen convention: In backend/api/features/store/model.py, the StoreSubmission and StoreSubmissionAdminView models define submitted_at: datetime | None, changes_summary: str | None, and instructions: str | None with no default. This is intentional to produce “required but nullable” fields in OpenAPI (properties appear in required[] and use anyOf [type, null]). This matches Prisma’s submittedAt DateTime? and changesSummary String?. Do not flag this as a required/nullable mismatch.

Applied to files:

  • autogpt_platform/backend/backend/copilot/stream_registry.py
📚 Learning: 2026-03-10T08:39:22.025Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12356
File: autogpt_platform/backend/backend/copilot/constants.py:9-12
Timestamp: 2026-03-10T08:39:22.025Z
Learning: In Significant-Gravitas/AutoGPT PR `#12356`, the `COPILOT_SYNTHETIC_ID_PREFIX = "copilot-"` check in `create_auto_approval_record` (human_review.py) is intentional and safe. The `graph_exec_id` passed to this function comes from server-side `PendingHumanReview` DB records (not from user input); the API only accepts `node_exec_id` from users. Synthetic `copilot-*` IDs are only ever created server-side in `run_block.py`. The prefix skip avoids a DB lookup for a `AgentGraphExecution` record that legitimately does not exist for CoPilot sessions, while `user_id` scoping is enforced at the auth layer and on the resulting auto-approval record.

Applied to files:

  • autogpt_platform/backend/backend/copilot/stream_registry.py
📚 Learning: 2026-03-25T06:59:27.324Z
Learnt from: CR
Repo: Significant-Gravitas/AutoGPT PR: 0
File: autogpt_platform/backend/CLAUDE.md:0-0
Timestamp: 2026-03-25T06:59:27.324Z
Learning: Applies to autogpt_platform/backend/**/*.py : Use absolute imports with `from backend.module import ...` for cross-package imports; single-dot relative imports (`from .sibling import ...`) are acceptable for sibling modules within the same package; avoid double-dot relative imports (`from ..parent import ...`)

Applied to files:

  • autogpt_platform/backend/backend/copilot/stream_registry.py
📚 Learning: 2026-02-26T17:02:22.448Z
Learnt from: Pwuts
Repo: Significant-Gravitas/AutoGPT PR: 12211
File: .pre-commit-config.yaml:160-179
Timestamp: 2026-02-26T17:02:22.448Z
Learning: Keep the pre-commit hook pattern broad for autogpt_platform/backend to ensure OpenAPI schema changes are captured. Do not narrow to backend/api/ alone, since the generated schema depends on Pydantic models across multiple directories (backend/data/, backend/blocks/, backend/copilot/, backend/integrations/, backend/util/). Narrowing could miss schema changes and cause frontend type desynchronization.

Applied to files:

  • autogpt_platform/backend/backend/copilot/stream_registry.py
📚 Learning: 2026-03-04T08:04:35.881Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12273
File: autogpt_platform/backend/backend/copilot/tools/workspace_files.py:216-220
Timestamp: 2026-03-04T08:04:35.881Z
Learning: In the AutoGPT Copilot backend, ensure that SVG images are not treated as vision image types by excluding 'image/svg+xml' from INLINEABLE_MIME_TYPES and MULTIMODAL_TYPES in tool_adapter.py; the Claude API supports PNG, JPEG, GIF, and WebP for vision. SVGs (XML text) should be handled via the text path instead, not the vision path.

Applied to files:

  • autogpt_platform/backend/backend/copilot/stream_registry.py
📚 Learning: 2026-03-05T15:42:08.207Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 12297
File: .claude/skills/backend-check/SKILL.md:14-16
Timestamp: 2026-03-05T15:42:08.207Z
Learning: In Python files under autogpt_platform/backend (recursively), rely on poetry run format to perform formatting (Black + isort) and linting (ruff). Do not run poetry run lint as a separate step after poetry run format, since format already includes linting checks.

Applied to files:

  • autogpt_platform/backend/backend/copilot/stream_registry.py
📚 Learning: 2026-03-16T16:35:40.236Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12440
File: autogpt_platform/backend/backend/api/features/workflow_import.py:54-63
Timestamp: 2026-03-16T16:35:40.236Z
Learning: Avoid using the word 'competitor' in public-facing identifiers and text. Use neutral naming for API paths, model names, function names, and UI text. Examples: rename 'CompetitorFormat' to 'SourcePlatform', 'convert_competitor_workflow' to 'convert_workflow', '/competitor-workflow' to '/workflow'. Apply this guideline to files under autogpt_platform/backend and autogpt_platform/frontend.

Applied to files:

  • autogpt_platform/backend/backend/copilot/stream_registry.py
🔇 Additional comments (4)
autogpt_platform/backend/backend/copilot/stream_registry.py (4)

29-29: Top-level chat_db import placement looks good.

This now follows the backend import rule and avoids inner-import churn.


115-121: created_at parsing in session meta is a solid backward-compatible addition.

Parsing Redis metadata with a safe fallback keeps older/in-flight sessions readable.

Also applies to: 131-131


815-827: Duration computation guard is correctly implemented.

The created_at presence check plus max(0, ...) clamp prevents meaningless/negative durations from being persisted.


836-840: Best-effort persistence handling is appropriate here.

Graceful failure logging around set_turn_duration(...) avoids blocking stream completion on DB-write issues.

0ubbe and others added 3 commits March 27, 2026 18:27
Always show [Pulse] [Thinking phrase]... with cycling fade transitions.
After 20s elapsed, append "• 23s" at the end instead of replacing the
phrase with just the timer.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove font-mono and text-sm overrides from elapsed time span so it
inherits the same font-size, family and colour as the phrase text.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Apply the same animate-pulse shimmer to the "• 27s" span as the
thinking phrase.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@majdyz

majdyz commented Mar 28, 2026

Copy link
Copy Markdown
Contributor

🤖 PR Review — #12583

Live timer stats — Shows elapsed thinking time with persistence. Good UX improvement.

CI: 0 failures | Diff: ~591 lines

Review in progress — will post inline findings if any.

@majdyz

majdyz commented Mar 28, 2026

Copy link
Copy Markdown
Contributor

🤖 PR Review — #12583 (Live Timer Stats)

Verdict: ✅ APPROVED

Clean implementation. DB migration adds duration_ms to ChatMessage. ThinkingIndicator component shows elapsed time. Stream registry tracks start time. Good separation: backend persists, frontend displays.

Findings: No blockers.

All CI checks green.

@majdyz majdyz 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.

🤖 LGTM — reviewed code, CI green, no blockers found.

@github-project-automation github-project-automation Bot moved this from 🆕 Needs initial review to 👍🏼 Mergeable in AutoGPT development kanban Mar 28, 2026
Comment thread autogpt_platform/backend/backend/copilot/db.py
Comment thread autogpt_platform/backend/backend/copilot/model.py
@0ubbe
0ubbe merged commit 7ba0536 into dev Mar 30, 2026
29 checks passed
@0ubbe
0ubbe deleted the feat/copilot-live-timer-stats branch March 30, 2026 09:46
@github-project-automation github-project-automation Bot moved this from 👍🏼 Mergeable to ✅ Done in AutoGPT development kanban Mar 30, 2026
@github-project-automation github-project-automation Bot moved this to Done in Frontend Mar 30, 2026
majdyz added a commit that referenced this pull request Apr 3, 2026
…rn_duration

set_turn_duration (from #12583) called invalidate_session_cache() which
deletes the Redis key. This creates a window where concurrent
get_chat_session() calls re-populate the cache from DB with stale data,
causing the executor to miss the user message and re-append a duplicate.

Replace with in-place cache update: read the cached session, patch the
duration on the last assistant message, and write it back.
itsababseh added a commit that referenced this pull request Apr 10, 2026
- Themed Prompt Categories (#12515)
- Live Timer Stats (#12583)
- Redesigned Onboarding (#12640)
- Copy Your Prompts (#12571)
- 18 improvements, 9 UI/UX updates, 17 bug fixes
itsababseh added a commit that referenced this pull request Apr 10, 2026
## v0.6.54 Changelog — Smarter Starts, Faster Feedback

**Date range:** 23 March – 9 April 2026

### Hero Features
- 🎯 **Themed Prompt Categories** — CoPilot empty-session screen now
shows Learn, Create, Automate, and Organize categories with contextual
prompts (#12515)
- ⏱️ **Live Timer Stats** — Live elapsed timer in the CoPilot thinking
indicator with persisted duration badge (#12583)
- 🚀 **Redesigned Onboarding** — New 4-step Autopilot-first onboarding
with role-based personalization (#12640)
- 📋 **Copy Your Prompts** — One-click copy button on your own prompt
messages in CoPilot (#12571)

### Also includes
- ✨ 18 improvements
- 🎨 9 UI/UX updates
- 🐛 17 bug fixes

### Files changed
- `docs/platform/changelog/march-23-april-9-2026.md` — Full changelog
- `docs/platform/.gitbook/assets/v0654-*-hero.png` — 4 hero images
- `docs/platform/SUMMARY.md` — Navigation updated
- `docs/platform/changelog/README.md` — Table updated

---------

Co-authored-by: Toran Bruce Richards <22963551+Torantulino@users.noreply.github.com>
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

Projects

Status: ✅ Done
Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants