Skip to content

feat(backend): resend org invitation — fresh token + extended TTL - #13603

Open
ntindle wants to merge 7 commits into
feat/grant-credential-modesfrom
feat/invitation-resend
Open

feat(backend): resend org invitation — fresh token + extended TTL#13603
ntindle wants to merge 7 commits into
feat/grant-credential-modesfrom
feat/invitation-resend

Conversation

@ntindle

@ntindle ntindle commented Jul 18, 2026

Copy link
Copy Markdown
Member

Why

SECRT-2475 (org walkthrough feedback, item 5 remainder): a pending invitation's only management action is Revoke. If the invite email is lost or the 7-day token expires, the flow dead-ends — an expired invitation even disappears from the list endpoint, so the admin's only path is revoke + retype the address.

What

POST /api/orgs/{org_id}/invitations/{invitation_id}/resend (admin-gated via MANAGE_MEMBERS, same as create/revoke):

  • Pending invitations — including expired ones, the primary use case — get a rotated token, cleared tokenHash, and a fresh 7-day expiry.
  • Token rotation deliberately kills the previously emailed link: only the newest link works.
  • Already-accepted → 400; revoked → 400 (re-invite via create); other-org or missing → 404.
  • Email sending carries the same TODO as create (Postmark wiring doesn't exist yet for invitations).

How

Follows the existing org-scoped invitation route conventions (_verify_org_path, NotFoundError for 404s, permission dep). Response reuses InvitationCreateResponse so the caller gets the fresh token/link like on create.

Testing

6 new tests in routes_test.py (TestInvitationResend): token rotation + TTL extension asserted on the update payload, expired-pending success, accepted/revoked rejection with no write, cross-org 404 pattern, and 403 for non-admin members. 13/13 with the existing acceptance suite; pyright clean.

Checklist

  • MANAGE_MEMBERS-gated + _verify_org_path; invitation looked up by id and org-matched before any write
  • Tests added for all new behavior

🤖 Generated with Claude Code

https://claude.ai/code/session_01Jm3mCG9okfdGtAXtFaDF9A


Note

Medium Risk
Changes org invitation token lifecycle and listing (bearer tokens, cross-org 404 semantics); mitigated by MANAGE_MEMBERS, CAS updates, and explicit rejection of accepted/revoked invites.

Overview
Adds POST /api/orgs/{org_id}/invitations/{invitation_id}/resend so admins with MANAGE_MEMBERS can refresh a pending invite (including expired ones): new UUID token, cleared tokenHash, fresh 7-day expiresAt, and InvitationCreateResponse with the current row. Token rotation invalidates older emailed links.

The update uses update_many with a pending-state WHERE (compare-and-swap) so concurrent accept/revoke cannot be overwritten; on a lost race it re-reads and returns 400/404. The handler re-fetches by invitation id (not the minted token) so overlapping resends still return 200 with a valid token. teamIds are pruned on resend if teams were deleted or belong to another org.

List invitations gains optional include_expired=true (default still hides expired) so admins can discover lapsed invites to resend. Revoke/list lookup logic is centralized in _get_org_invitation and _reject_if_not_pending.

Adds HTTP contract tests in invitation_resend_test.py (concurrency, permissions, team pruning, list behavior) plus an OpenAPI snapshot for the resend response shape. Email delivery and resend rate limits remain TODO like create.

Reviewed by Cursor Bugbot for commit 4f851e1. Bugbot is set up for automated code reviews on this repo. Configure here.

@ntindle
ntindle requested a review from a team as a code owner July 18, 2026 01:45
@ntindle
ntindle requested review from 0ubbe and kcze and removed request for a team July 18, 2026 01:45
@github-project-automation github-project-automation Bot moved this to 🆕 Needs initial review in AutoGPT development kanban Jul 18, 2026
@ntindle

ntindle commented Jul 18, 2026

Copy link
Copy Markdown
Member Author

/batch

@github-actions github-actions Bot added platform/backend AutoGPT Platform - Back end size/l labels Jul 18, 2026
@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (1)
  • dev

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: be04b053-a64b-4b5c-b903-ff8a285bc78d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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 organization-scoped invitation resend support. The endpoint rotates tokens, refreshes expiration, reconciles team IDs, and validates invitation state. Listing can include expired invitations. HTTP tests and OpenAPI documentation cover the new behavior.

Changes

Invitation resend

Layer / File(s) Summary
Centralize invitation lookup and listing filters
autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py, autogpt_platform/frontend/src/app/api/openapi.json
Adds organization-scoped lookup and shared pending-state validation. Adds the optional include_expired listing parameter. Updates revocation to use the shared lookup.
Implement invitation resend
autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py, autogpt_platform/frontend/src/app/api/openapi.json
Adds the resend route with token rotation, token-hash clearing, expiration refresh, compare-and-swap protection, and team-ID reconciliation. Documents the secured endpoint.
Validate resend and listing behavior
autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py
Tests successful resends, expired invitations, token handling, concurrent state changes, team filtering, invalid states, organization mismatches, permissions, and listing filters.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant RequestContext
  participant resend_invitation
  participant Prisma
  RequestContext->>resend_invitation: Authenticate and authorize request
  resend_invitation->>Prisma: Load organization-scoped invitation
  resend_invitation->>Prisma: Rotate token and refresh expiration
  Prisma-->>resend_invitation: Return updated invitation
Loading

Possibly related PRs

Suggested reviewers: 0ubbe, kcze

Poem

A rabbit checks each invitation,
Rotates tokens with precision.
Teams stay aligned,
Expiry is refreshed in time,
Tests guard every transition.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The description clearly explains the invitation resend endpoint, expired invitation handling, authorization, token rotation, and tests. It also includes unrelated generated summary content, but the re…
Title check ✅ Passed The title clearly and concisely summarizes the main change: resending organization invitations with a fresh token and extended expiration.
Full details: Description check

Explanation

The description clearly explains the invitation resend endpoint, expired invitation handling, authorization, token rotation, and tests. It also includes unrelated generated summary content, but the relevant content is sufficient.

✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/invitation-resend

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.

@github-actions

github-actions Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

🔍 PR Overlap Detection

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

🔴 Merge Conflicts Detected

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

  • fix(backend): gate org credits routes behind MANAGE_BILLING #13527 (ntindle · updated 13d ago)

    • autogpt_platform/backend/.env.default (1 conflict, ~15 lines)
    • autogpt_platform/backend/backend/api/features/chat/routes.py (10 conflicts, ~102 lines)
    • autogpt_platform/backend/backend/api/features/chat/routes_test.py (7 conflicts, ~356 lines)
    • autogpt_platform/backend/backend/api/features/integrations/router.py (3 conflicts, ~35 lines)
    • autogpt_platform/backend/backend/api/features/integrations/webhook_ingress_test.py (1 conflict, ~142 lines)
    • autogpt_platform/backend/backend/api/features/library/_add_to_library.py (6 conflicts, ~100 lines)
    • autogpt_platform/backend/backend/api/features/library/_add_to_library_test.py (2 conflicts, ~82 lines)
    • autogpt_platform/backend/backend/api/features/library/db.py (5 conflicts, ~85 lines)
    • autogpt_platform/backend/backend/api/features/library/model_test.py (2 conflicts, ~10 lines)
    • autogpt_platform/backend/backend/api/features/library/routes/presets.py (1 conflict, ~29 lines)
    • autogpt_platform/backend/backend/api/features/library/triggers.py (4 conflicts, ~33 lines)
    • autogpt_platform/backend/backend/api/features/platform_linking/registry.py (2 conflicts, ~24 lines)
    • autogpt_platform/backend/backend/api/features/platform_linking/registry_test.py (2 conflicts, ~38 lines)
    • autogpt_platform/backend/backend/api/features/platform_linking/routes.py (1 conflict, ~5 lines)
    • autogpt_platform/backend/backend/api/features/platform_linking/routes_test.py (1 conflict, ~220 lines)
    • autogpt_platform/backend/backend/api/features/v1.py (12 conflicts, ~90 lines)
    • autogpt_platform/backend/backend/api/features/v1_credits_authz_test.py (9 conflicts, ~415 lines)
    • autogpt_platform/backend/backend/api/features/v1_test.py (1 conflict, ~4 lines)
    • autogpt_platform/backend/backend/api/rest_api.py (3 conflicts, ~13 lines)
    • autogpt_platform/backend/backend/blocks/autopilot.py (1 conflict, ~5 lines)
    • autogpt_platform/backend/backend/blocks/codex.py (2 conflicts, ~14 lines)
    • autogpt_platform/backend/backend/blocks/cost_leak_fixes_test.py (1 conflict, ~6 lines)
    • autogpt_platform/backend/backend/copilot/anthropic_rates.json (2 conflicts, ~12 lines)
    • autogpt_platform/backend/backend/copilot/baseline/service.py (3 conflicts, ~20 lines)
    • autogpt_platform/backend/backend/copilot/bot/README.md (2 conflicts, ~10 lines)
    • autogpt_platform/backend/backend/copilot/db.py (2 conflicts, ~34 lines)
    • autogpt_platform/backend/backend/copilot/db_test.py (2 conflicts, ~194 lines)
    • autogpt_platform/backend/backend/copilot/dream/apply.py (7 conflicts, ~45 lines)
    • autogpt_platform/backend/backend/copilot/dream/apply_test.py (2 conflicts, ~32 lines)
    • autogpt_platform/backend/backend/copilot/dream/batch_callbacks.py (2 conflicts, ~17 lines)
    • autogpt_platform/backend/backend/copilot/dream/orchestrator.py (1 conflict, ~8 lines)
    • autogpt_platform/backend/backend/copilot/executor/processor.py (4 conflicts, ~182 lines)
    • autogpt_platform/backend/backend/copilot/executor/utils.py (5 conflicts, ~25 lines)
    • autogpt_platform/backend/backend/copilot/graphiti/context.py (1 conflict, ~5 lines)
    • autogpt_platform/backend/backend/copilot/graphiti/context_test.py (2 conflicts, ~176 lines)
    • autogpt_platform/backend/backend/copilot/graphiti/falkordb_driver.py (2 conflicts, ~47 lines)
    • autogpt_platform/backend/backend/copilot/graphiti/ingest.py (6 conflicts, ~93 lines)
    • autogpt_platform/backend/backend/copilot/graphiti/ingest_test.py (3 conflicts, ~148 lines)
    • autogpt_platform/backend/backend/copilot/model.py (7 conflicts, ~48 lines)
    • autogpt_platform/backend/backend/copilot/model_router.py (1 conflict, ~138 lines)
    • autogpt_platform/backend/backend/copilot/model_test.py (1 conflict, ~160 lines)
    • autogpt_platform/backend/backend/copilot/response_model.py (1 conflict, ~7 lines)
    • autogpt_platform/backend/backend/copilot/sdk/env_test.py (1 conflict, ~74 lines)
    • autogpt_platform/backend/backend/copilot/sdk/service.py (8 conflicts, ~113 lines)
    • autogpt_platform/backend/backend/copilot/sdk/service_helpers_test.py (2 conflicts, ~766 lines)
    • autogpt_platform/backend/backend/copilot/service.py (1 conflict, ~5 lines)
    • autogpt_platform/backend/backend/copilot/stream_registry.py (1 conflict, ~4 lines)
    • autogpt_platform/backend/backend/copilot/stream_registry_test.py (1 conflict, ~63 lines)
    • autogpt_platform/backend/backend/copilot/tools/chat_platform.py (9 conflicts, ~70 lines)
    • autogpt_platform/backend/backend/copilot/tools/run_agent.py (1 conflict, ~4 lines)
    • autogpt_platform/backend/backend/copilot/tools/run_agent_test.py (3 conflicts, ~17 lines)
    • autogpt_platform/backend/backend/copilot/tools/schedule_followup.py (1 conflict, ~4 lines)
    • autogpt_platform/backend/backend/copilot/tools/sub_session_test.py (2 conflicts, ~13 lines)
    • autogpt_platform/backend/backend/copilot/tools/tool_schema_test.py (1 conflict, ~23 lines)
    • autogpt_platform/backend/backend/data/block_cost_config.py (2 conflicts, ~23 lines)
    • autogpt_platform/backend/backend/data/db_manager.py (5 conflicts, ~21 lines)
    • autogpt_platform/backend/backend/data/execution.py (6 conflicts, ~42 lines)
    • autogpt_platform/backend/backend/data/graph_test.py (1 conflict, ~380 lines)
    • autogpt_platform/backend/backend/data/onboarding.py (1 conflict, ~18 lines)
    • autogpt_platform/backend/backend/executor/scheduler.py (15 conflicts, ~132 lines)
    • autogpt_platform/backend/backend/executor/scheduler_unit_test.py (2 conflicts, ~370 lines)
    • autogpt_platform/backend/backend/executor/utils.py (3 conflicts, ~47 lines)
    • autogpt_platform/backend/backend/executor/utils_test.py (1 conflict, ~4 lines)
    • autogpt_platform/backend/backend/platform_linking/chat_test.py (1 conflict, ~66 lines)
    • autogpt_platform/backend/backend/util/feature_flag_test.py (1 conflict, ~88 lines)
    • autogpt_platform/backend/backend/util/metrics.py (1 conflict, ~62 lines)
    • autogpt_platform/backend/backend/util/metrics_test.py (2 conflicts, ~110 lines)
    • autogpt_platform/backend/backend/util/settings.py (1 conflict, ~20 lines)
    • autogpt_platform/backend/poetry.lock (1 conflict, ~5 lines)
    • autogpt_platform/backend/schema.prisma (5 conflicts, ~125 lines)
    • autogpt_platform/frontend/package.json (1 conflict, ~7 lines)
    • autogpt_platform/frontend/pnpm-lock.yaml (9 conflicts, ~54 lines)
    • autogpt_platform/frontend/src/app/(no-navbar)/link/[token]/__tests__/page.test.tsx (1 conflict, ~95 lines)
    • autogpt_platform/frontend/src/app/(no-navbar)/link/[token]/components/ReadyView.tsx (3 conflicts, ~27 lines)
    • autogpt_platform/frontend/src/app/(no-navbar)/link/[token]/components/SuccessView.tsx (1 conflict, ~8 lines)
    • autogpt_platform/frontend/src/app/(no-navbar)/onboarding/__tests__/page.test.tsx (3 conflicts, ~41 lines)
    • autogpt_platform/frontend/src/app/(platform)/PlatformChrome/PlatformChrome.tsx (3 conflicts, ~21 lines)
    • autogpt_platform/frontend/src/app/(platform)/PlatformChrome/usePlatformChrome.ts (2 conflicts, ~15 lines)
    • autogpt_platform/frontend/src/app/(platform)/admin/bots/components/helpers.ts (1 conflict, ~4 lines)
    • autogpt_platform/frontend/src/app/(platform)/admin/layout.tsx (1 conflict, ~111 lines)
    • autogpt_platform/frontend/src/app/(platform)/auth/callback/route.ts (1 conflict, ~14 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/CopilotChatHost.tsx (2 conflicts, ~9 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx (4 conflicts, ~16 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/__tests__/autopilot-errors.test.tsx (1 conflict, ~9 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ArtifactCard/ArtifactCard.tsx (3 conflicts, ~15 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ArtifactPanel/components/ArtifactPanelHeader.tsx (2 conflicts, ~16 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatContainer/ChatContainer.tsx (5 conflicts, ~181 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatInput/__tests__/ChatInput.test.tsx (2 conflicts, ~10 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/ChatMessagesContainer.tsx (6 conflicts, ~474 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/CollapsedToolGroup.tsx (deleted here, modified there)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/StepsCollapse.tsx (deleted here, modified there)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/TaskListNotice.tsx (deleted here, modified there)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/__tests__/StepsCollapse.test.tsx (deleted here, modified there)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatSidebar/ChatSidebar.tsx (2 conflicts, ~77 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ContextPanel/ContextPanel.tsx (3 conflicts, ~47 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ContextPanel/ContextPanelToggle.tsx (2 conflicts, ~15 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ContextPanel/components/FilesTab/FilesTab.tsx (deleted here, modified there)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ContextPanel/components/FilesTab/components/FileRow.tsx (deleted here, modified there)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ContextPanel/components/ProgressTab/ProgressTab.tsx (deleted here, modified there)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/EmptySession/EmptySession.tsx (4 conflicts, ~32 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/PanelResizeHandle.tsx (1 conflict, ~4 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/UsageLimits/UsagePopover/UsagePopover.tsx (2 conflicts, ~10 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/copilotStreamTransport.ts (1 conflict, ~4 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/store.ts (2 conflicts, ~18 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts (2 conflicts, ~16 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts (4 conflicts, ~34 lines)
    • autogpt_platform/frontend/src/app/(platform)/library/page.tsx (1 conflict, ~4 lines)
    • autogpt_platform/frontend/src/app/(platform)/marketplace/components/FeaturedSection/FeaturedSection.tsx (2 conflicts, ~16 lines)
    • autogpt_platform/frontend/src/app/(platform)/profile/(user)/layout.tsx (1 conflict, ~4 lines)
    • autogpt_platform/frontend/src/app/(platform)/reset-password/actions.ts (1 conflict, ~7 lines)
    • autogpt_platform/frontend/src/app/(platform)/settings/account/__tests__/main.test.tsx (1 conflict, ~4 lines)
    • autogpt_platform/frontend/src/app/(platform)/settings/bots/__tests__/main.test.tsx (1 conflict, ~75 lines)
    • autogpt_platform/frontend/src/app/(platform)/settings/bots/components/BotCard/BotCard.tsx (3 conflicts, ~25 lines)
    • autogpt_platform/frontend/src/app/(platform)/settings/bots/components/BotCard/BotCardServerList.tsx (2 conflicts, ~12 lines)
    • autogpt_platform/frontend/src/app/(platform)/settings/bots/components/BotsList/useBotsList.ts (2 conflicts, ~22 lines)
    • autogpt_platform/frontend/src/app/(platform)/settings/components/SettingsSidebar/helpers.ts (3 conflicts, ~12 lines)
    • autogpt_platform/frontend/src/app/(public)/tour/chat/components/TourMessageList/TourMessageList.tsx (1 conflict, ~13 lines)
    • autogpt_platform/frontend/src/app/(public)/tour/chat/components/TourSidebar/components/TourSidebarHeader.tsx (1 conflict, ~20 lines)
    • autogpt_platform/frontend/src/app/api/openapi.json (22 conflicts, ~840 lines)
    • autogpt_platform/frontend/src/app/api/proxy/[...path]/__tests__/route.helpers.test.ts (1 conflict, ~5 lines)
    • autogpt_platform/frontend/src/components/contextual/CredentialsInput/__tests__/CredentialsInput.test.tsx (1 conflict, ~405 lines)
    • autogpt_platform/frontend/src/components/contextual/CredentialsInput/helpers.ts (1 conflict, ~6 lines)
    • autogpt_platform/frontend/src/components/layout/AppSidebar/AppSidebar.tsx (3 conflicts, ~59 lines)
    • autogpt_platform/frontend/src/components/layout/AppSidebar/__tests__/AppSidebar.test.tsx (1 conflict, ~10 lines)
    • autogpt_platform/frontend/src/components/layout/AppSidebar/components/AppSidebarHeader/AppSidebarHeader.tsx (2 conflicts, ~103 lines)
    • autogpt_platform/frontend/src/components/layout/AppSidebar/components/RecentChats/RecentChats.tsx (5 conflicts, ~62 lines)
    • autogpt_platform/frontend/src/components/layout/AppSidebar/components/RecentChats/components/RecentChatItem/RecentChatItem.tsx (1 conflict, ~5 lines)
    • autogpt_platform/frontend/src/components/layout/AppSidebar/components/SidebarSearch/SidebarSearch.tsx (2 conflicts, ~47 lines)
    • autogpt_platform/frontend/src/components/organisms/PendingReviewsList/PendingReviewsList.tsx (1 conflict, ~5 lines)
    • autogpt_platform/frontend/src/lib/__tests__/utils.test.ts (2 conflicts, ~61 lines)
    • autogpt_platform/frontend/src/lib/autogpt-server-api/types.ts (1 conflict, ~6 lines)
    • autogpt_platform/frontend/src/lib/constants.ts (1 conflict, ~6 lines)
    • autogpt_platform/frontend/src/lib/direct-upload.ts (1 conflict, ~7 lines)
    • autogpt_platform/frontend/src/mocks/mock-handlers.ts (2 conflicts, ~8 lines)
    • autogpt_platform/frontend/src/providers/agent-credentials/credentials-provider.tsx (1 conflict, ~5 lines)
    • autogpt_platform/frontend/src/services/environment/index.ts (1 conflict, ~8 lines)
    • docs/integrations/block-integrations/llm.md (8 conflicts, ~47 lines)
    • docs/integrations/block-integrations/misc.md (1 conflict, ~5 lines)
    • docs/platform/SUMMARY.md (1 conflict, ~17 lines)
  • fix(backend): harden Copilot session tenancy #13650 (ntindle · updated 10d ago)

    • .secrets.baseline (1 conflict, ~5 lines)
    • autogpt_platform/backend/backend/api/features/chat/routes.py (8 conflicts, ~127 lines)
    • autogpt_platform/backend/backend/api/features/chat/routes_test.py (4 conflicts, ~39 lines)
    • autogpt_platform/backend/backend/api/features/experts/experts_db.py (14 conflicts, ~623 lines)
    • autogpt_platform/backend/backend/api/features/experts/experts_db_test.py (7 conflicts, ~630 lines)
    • autogpt_platform/backend/backend/api/features/experts/models.py (5 conflicts, ~221 lines)
    • autogpt_platform/backend/backend/api/features/experts/routes.py (1 conflict, ~20 lines)
    • autogpt_platform/backend/backend/api/features/experts/routes_test.py (1 conflict, ~102 lines)
    • autogpt_platform/backend/backend/api/features/experts/seed.py (2 conflicts, ~27 lines)
    • autogpt_platform/backend/backend/api/features/library/_add_to_library.py (2 conflicts, ~73 lines)
    • autogpt_platform/backend/backend/api/features/library/db.py (2 conflicts, ~51 lines)
    • autogpt_platform/backend/backend/api/features/library/triggers.py (1 conflict, ~7 lines)
    • autogpt_platform/backend/backend/api/features/orgs/db.py (2 conflicts, ~58 lines)
    • autogpt_platform/backend/backend/api/features/orgs/routes_test.py (1 conflict, ~722 lines)
    • autogpt_platform/backend/backend/api/features/search/content_handlers_integration_test.py (2 conflicts, ~29 lines)
    • autogpt_platform/backend/backend/api/features/v1.py (2 conflicts, ~17 lines)
    • autogpt_platform/backend/backend/api/rest_api.py (2 conflicts, ~20 lines)
    • autogpt_platform/backend/backend/blocks/autopilot.py (8 conflicts, ~112 lines)
    • autogpt_platform/backend/backend/copilot/baseline/service.py (1 conflict, ~4 lines)
    • autogpt_platform/backend/backend/copilot/db.py (1 conflict, ~8 lines)
    • autogpt_platform/backend/backend/copilot/db_test.py (1 conflict, ~105 lines)
    • autogpt_platform/backend/backend/copilot/dream/apply.py (7 conflicts, ~45 lines)
    • autogpt_platform/backend/backend/copilot/dream/apply_test.py (2 conflicts, ~32 lines)
    • autogpt_platform/backend/backend/copilot/dream/batch_callbacks.py (2 conflicts, ~17 lines)
    • autogpt_platform/backend/backend/copilot/dream/orchestrator.py (1 conflict, ~8 lines)
    • autogpt_platform/backend/backend/copilot/executor/processor.py (2 conflicts, ~60 lines)
    • autogpt_platform/backend/backend/copilot/executor/processor_test.py (4 conflicts, ~325 lines)
    • autogpt_platform/backend/backend/copilot/expert_context.py (2 conflicts, ~36 lines)
    • autogpt_platform/backend/backend/copilot/expert_context_test.py (4 conflicts, ~128 lines)
    • autogpt_platform/backend/backend/copilot/graphiti/context.py (1 conflict, ~5 lines)
    • autogpt_platform/backend/backend/copilot/graphiti/context_test.py (2 conflicts, ~176 lines)
    • autogpt_platform/backend/backend/copilot/graphiti/ingest.py (5 conflicts, ~83 lines)
    • autogpt_platform/backend/backend/copilot/graphiti/ingest_test.py (1 conflict, ~14 lines)
    • autogpt_platform/backend/backend/copilot/model.py (2 conflicts, ~15 lines)
    • autogpt_platform/backend/backend/copilot/sdk/service.py (3 conflicts, ~55 lines)
    • autogpt_platform/backend/backend/copilot/sdk/service_helpers_test.py (2 conflicts, ~766 lines)
    • autogpt_platform/backend/backend/copilot/sdk/session_waiter.py (1 conflict, ~9 lines)
    • autogpt_platform/backend/backend/copilot/tools/_test_data.py (1 conflict, ~8 lines)
    • autogpt_platform/backend/backend/copilot/tools/graphiti_forget_test.py (1 conflict, ~16 lines)
    • autogpt_platform/backend/backend/copilot/tools/helpers_test.py (1 conflict, ~9 lines)
    • autogpt_platform/backend/backend/copilot/tools/run_sub_session.py (2 conflicts, ~43 lines)
    • autogpt_platform/backend/backend/copilot/tools/schedule_followup.py (2 conflicts, ~28 lines)
    • autogpt_platform/backend/backend/copilot/tools/schedule_followup_test.py (1 conflict, ~8 lines)
    • autogpt_platform/backend/backend/copilot/tools/sub_session_test.py (3 conflicts, ~14 lines)
    • autogpt_platform/backend/backend/copilot/turn_queue.py (5 conflicts, ~25 lines)
    • autogpt_platform/backend/backend/copilot/turn_queue_test.py (2 conflicts, ~36 lines)
    • autogpt_platform/backend/backend/data/db_manager.py (5 conflicts, ~52 lines)
    • autogpt_platform/backend/backend/data/execution.py (2 conflicts, ~17 lines)
    • autogpt_platform/backend/backend/data/execution_cost_summary.py (1 conflict, ~5 lines)
    • autogpt_platform/backend/backend/data/graph.py (1 conflict, ~4 lines)
    • autogpt_platform/backend/backend/data/org_credit.py (1 conflict, ~4 lines)
    • autogpt_platform/backend/backend/executor/manager.py (1 conflict, ~8 lines)
    • autogpt_platform/backend/backend/executor/scheduler.py (6 conflicts, ~185 lines)
    • autogpt_platform/backend/backend/executor/scheduler_unit_test.py (12 conflicts, ~512 lines)
    • autogpt_platform/backend/backend/executor/utils.py (7 conflicts, ~132 lines)
    • autogpt_platform/backend/backend/executor/utils_test.py (1 conflict, ~54 lines)
    • autogpt_platform/backend/backend/util/exceptions.py (1 conflict, ~9 lines)
    • autogpt_platform/backend/backend/util/metrics.py (1 conflict, ~4 lines)
    • autogpt_platform/backend/backend/util/metrics_test.py (2 conflicts, ~47 lines)
    • autogpt_platform/backend/poetry.lock (1 conflict, ~5 lines)
    • autogpt_platform/backend/schema.prisma (2 conflicts, ~28 lines)
    • autogpt_platform/backend/snapshots/expert_templates_list (1 conflict, ~4 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ArtifactCard/ArtifactCard.tsx (1 conflict, ~5 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ArtifactPanel/components/ArtifactPanelHeader.tsx (2 conflicts, ~16 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/ChatMessagesContainer.tsx (5 conflicts, ~329 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/CollapsedToolGroup.tsx (deleted here, modified there)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/ExpertAvatar/ExpertAvatar.tsx (1 conflict, ~30 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/StepsCollapse.tsx (deleted here, modified there)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/TaskListNotice.tsx (deleted here, modified there)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/__tests__/StepsCollapse.test.tsx (deleted here, modified there)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ContextPanel/ContextPanel.tsx (3 conflicts, ~47 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ContextPanel/ContextPanelToggle.tsx (2 conflicts, ~15 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ContextPanel/components/FilesTab/FilesTab.tsx (deleted here, modified there)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ContextPanel/components/FilesTab/components/FileRow.tsx (deleted here, modified there)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ContextPanel/components/ProgressTab/ProgressTab.tsx (deleted here, modified there)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/EmptySession/EmptySession.tsx (1 conflict, ~13 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/copilotStreamTransport.ts (1 conflict, ~13 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/store.ts (1 conflict, ~8 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts (1 conflict, ~4 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/useExpertMap.ts (1 conflict, ~35 lines)
    • autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/NewAgentLibraryView/NewAgentLibraryView.tsx (1 conflict, ~31 lines)
    • autogpt_platform/frontend/src/app/(platform)/profile/(user)/layout.tsx (1 conflict, ~7 lines)
    • autogpt_platform/frontend/src/app/(platform)/settings/components/SettingsSidebar/helpers.ts (3 conflicts, ~12 lines)
    • autogpt_platform/frontend/src/app/(platform)/team/__tests__/main.test.tsx (5 conflicts, ~1037 lines)
    • autogpt_platform/frontend/src/app/(platform)/team/components/EmptyTeamState.tsx (1 conflict, ~5 lines)
    • autogpt_platform/frontend/src/app/(platform)/team/components/ExpertTeamCard/ExpertTeamCard.tsx (4 conflicts, ~42 lines)
    • autogpt_platform/frontend/src/app/(platform)/team/page.tsx (6 conflicts, ~63 lines)
    • autogpt_platform/frontend/src/app/(platform)/team/useTeamPage.ts (5 conflicts, ~121 lines)
    • autogpt_platform/frontend/src/app/(public)/tour/chat/components/TourSidebar/components/TourSidebarHeader.tsx (1 conflict, ~20 lines)
    • autogpt_platform/frontend/src/app/api/openapi.json (4 conflicts, ~66 lines)
    • autogpt_platform/frontend/src/components/contextual/CredentialsInput/helpers.ts (2 conflicts, ~10 lines)
    • autogpt_platform/frontend/src/components/contextual/CredentialsInput/useCredentialsInput.ts (2 conflicts, ~32 lines)
    • autogpt_platform/frontend/src/components/contextual/IntegrationsPanel/components/ConnectServiceDialog/components/DetailView/MethodPanel.tsx (1 conflict, ~12 lines)
    • autogpt_platform/frontend/src/components/layout/AppSidebar/AppSidebar.tsx (2 conflicts, ~27 lines)
    • autogpt_platform/frontend/src/components/layout/AppSidebar/components/AppSidebarHeader/AppSidebarHeader.tsx (2 conflicts, ~34 lines)
    • autogpt_platform/frontend/src/components/layout/AppSidebar/components/SidebarSearch/SidebarSearch.tsx (2 conflicts, ~47 lines)
    • autogpt_platform/frontend/src/components/renderers/InputRenderer/base/standard/widgets/SelectInput/SelectWidget.tsx (1 conflict, ~5 lines)
    • autogpt_platform/frontend/src/hooks/useCredentials.ts (3 conflicts, ~54 lines)
    • autogpt_platform/frontend/src/lib/oauth-popup.ts (1 conflict, ~52 lines)
    • autogpt_platform/frontend/src/services/feature-flags/use-get-flag.ts (3 conflicts, ~20 lines)
    • docs/platform/SUMMARY.md (1 conflict, ~17 lines)
  • fix(backend/copilot): refresh warm context on follow-up turns #13673 (kcze · updated 8d ago)

    • .secrets.baseline (1 conflict, ~5 lines)
    • autogpt_platform/backend/backend/api/features/chat/routes.py (6 conflicts, ~86 lines)
    • autogpt_platform/backend/backend/api/features/chat/routes_test.py (3 conflicts, ~35 lines)
    • autogpt_platform/backend/backend/api/features/experts/experts_db.py (14 conflicts, ~623 lines)
    • autogpt_platform/backend/backend/api/features/experts/experts_db_test.py (7 conflicts, ~630 lines)
    • autogpt_platform/backend/backend/api/features/experts/models.py (5 conflicts, ~221 lines)
    • autogpt_platform/backend/backend/api/features/experts/routes.py (1 conflict, ~20 lines)
    • autogpt_platform/backend/backend/api/features/experts/routes_test.py (1 conflict, ~102 lines)
    • autogpt_platform/backend/backend/api/features/experts/seed.py (2 conflicts, ~27 lines)
    • autogpt_platform/backend/backend/api/features/library/_add_to_library.py (2 conflicts, ~73 lines)
    • autogpt_platform/backend/backend/api/features/library/db.py (2 conflicts, ~51 lines)
    • autogpt_platform/backend/backend/api/features/library/triggers.py (1 conflict, ~7 lines)
    • autogpt_platform/backend/backend/api/features/orgs/routes_test.py (1 conflict, ~722 lines)
    • autogpt_platform/backend/backend/api/features/search/content_handlers_integration_test.py (2 conflicts, ~29 lines)
    • autogpt_platform/backend/backend/api/features/v1.py (2 conflicts, ~17 lines)
    • autogpt_platform/backend/backend/api/rest_api.py (1 conflict, ~4 lines)
    • autogpt_platform/backend/backend/blocks/autopilot.py (6 conflicts, ~101 lines)
    • autogpt_platform/backend/backend/copilot/baseline/service.py (2 conflicts, ~13 lines)
    • autogpt_platform/backend/backend/copilot/baseline/service_unit_test.py (1 conflict, ~240 lines)
    • autogpt_platform/backend/backend/copilot/db.py (1 conflict, ~8 lines)
    • autogpt_platform/backend/backend/copilot/db_test.py (1 conflict, ~105 lines)
    • autogpt_platform/backend/backend/copilot/dream/apply.py (7 conflicts, ~45 lines)
    • autogpt_platform/backend/backend/copilot/dream/apply_test.py (2 conflicts, ~32 lines)
    • autogpt_platform/backend/backend/copilot/dream/batch_callbacks.py (2 conflicts, ~17 lines)
    • autogpt_platform/backend/backend/copilot/dream/orchestrator.py (1 conflict, ~8 lines)
    • autogpt_platform/backend/backend/copilot/executor/processor.py (1 conflict, ~13 lines)
    • autogpt_platform/backend/backend/copilot/executor/processor_test.py (3 conflicts, ~20 lines)
    • autogpt_platform/backend/backend/copilot/expert_context.py (2 conflicts, ~36 lines)
    • autogpt_platform/backend/backend/copilot/expert_context_test.py (4 conflicts, ~128 lines)
    • autogpt_platform/backend/backend/copilot/graphiti/context.py (9 conflicts, ~301 lines)
    • autogpt_platform/backend/backend/copilot/graphiti/context_test.py (4 conflicts, ~387 lines)
    • autogpt_platform/backend/backend/copilot/graphiti/ingest.py (5 conflicts, ~83 lines)
    • autogpt_platform/backend/backend/copilot/graphiti/ingest_test.py (1 conflict, ~14 lines)
    • autogpt_platform/backend/backend/copilot/model.py (3 conflicts, ~26 lines)
    • autogpt_platform/backend/backend/copilot/sdk/service.py (2 conflicts, ~12 lines)
    • autogpt_platform/backend/backend/copilot/tools/_test_data.py (1 conflict, ~8 lines)
    • autogpt_platform/backend/backend/copilot/tools/graphiti_forget_test.py (1 conflict, ~16 lines)
    • autogpt_platform/backend/backend/copilot/tools/helpers_test.py (1 conflict, ~9 lines)
    • autogpt_platform/backend/backend/copilot/tools/run_sub_session.py (2 conflicts, ~43 lines)
    • autogpt_platform/backend/backend/copilot/tools/sub_session_test.py (3 conflicts, ~14 lines)
    • autogpt_platform/backend/backend/copilot/turn_queue.py (1 conflict, ~4 lines)
    • autogpt_platform/backend/backend/copilot/turn_queue_test.py (1 conflict, ~31 lines)
    • autogpt_platform/backend/backend/data/db_manager.py (2 conflicts, ~32 lines)
    • autogpt_platform/backend/backend/data/execution.py (2 conflicts, ~17 lines)
    • autogpt_platform/backend/backend/data/execution_cost_summary.py (1 conflict, ~5 lines)
    • autogpt_platform/backend/backend/data/org_credit.py (1 conflict, ~4 lines)
    • autogpt_platform/backend/backend/executor/manager.py (1 conflict, ~8 lines)
    • autogpt_platform/backend/backend/executor/scheduler.py (4 conflicts, ~41 lines)
    • autogpt_platform/backend/backend/executor/scheduler_unit_test.py (3 conflicts, ~138 lines)
    • autogpt_platform/backend/backend/executor/utils.py (7 conflicts, ~132 lines)
    • autogpt_platform/backend/backend/executor/utils_test.py (1 conflict, ~54 lines)
    • autogpt_platform/backend/backend/util/exceptions.py (1 conflict, ~9 lines)
    • autogpt_platform/backend/backend/util/metrics.py (1 conflict, ~4 lines)
    • autogpt_platform/backend/backend/util/metrics_test.py (2 conflicts, ~47 lines)
    • autogpt_platform/backend/poetry.lock (1 conflict, ~5 lines)
    • autogpt_platform/backend/schema.prisma (2 conflicts, ~28 lines)
    • autogpt_platform/backend/snapshots/expert_templates_list (1 conflict, ~4 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ArtifactCard/ArtifactCard.tsx (1 conflict, ~5 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ArtifactPanel/components/ArtifactPanelHeader.tsx (2 conflicts, ~16 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/ChatMessagesContainer.tsx (5 conflicts, ~329 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/CollapsedToolGroup.tsx (deleted here, modified there)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/ExpertAvatar/ExpertAvatar.tsx (1 conflict, ~30 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/StepsCollapse.tsx (deleted here, modified there)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/TaskListNotice.tsx (deleted here, modified there)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ChatMessagesContainer/components/__tests__/StepsCollapse.test.tsx (deleted here, modified there)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ContextPanel/ContextPanel.tsx (3 conflicts, ~47 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ContextPanel/ContextPanelToggle.tsx (2 conflicts, ~15 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ContextPanel/components/FilesTab/FilesTab.tsx (deleted here, modified there)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ContextPanel/components/FilesTab/components/FileRow.tsx (deleted here, modified there)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/ContextPanel/components/ProgressTab/ProgressTab.tsx (deleted here, modified there)
    • autogpt_platform/frontend/src/app/(platform)/copilot/components/EmptySession/EmptySession.tsx (1 conflict, ~13 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/copilotStreamTransport.ts (1 conflict, ~13 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/store.ts (1 conflict, ~8 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/useChatSession.ts (1 conflict, ~4 lines)
    • autogpt_platform/frontend/src/app/(platform)/copilot/useExpertMap.ts (1 conflict, ~35 lines)
    • autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/NewAgentLibraryView/NewAgentLibraryView.tsx (1 conflict, ~31 lines)
    • autogpt_platform/frontend/src/app/(platform)/profile/(user)/layout.tsx (1 conflict, ~7 lines)
    • autogpt_platform/frontend/src/app/(platform)/settings/components/SettingsSidebar/helpers.ts (3 conflicts, ~12 lines)
    • autogpt_platform/frontend/src/app/(platform)/team/__tests__/main.test.tsx (5 conflicts, ~1037 lines)
    • autogpt_platform/frontend/src/app/(platform)/team/components/EmptyTeamState.tsx (1 conflict, ~5 lines)
    • autogpt_platform/frontend/src/app/(platform)/team/components/ExpertTeamCard/ExpertTeamCard.tsx (4 conflicts, ~42 lines)
    • autogpt_platform/frontend/src/app/(platform)/team/page.tsx (6 conflicts, ~63 lines)
    • autogpt_platform/frontend/src/app/(platform)/team/useTeamPage.ts (5 conflicts, ~121 lines)
    • autogpt_platform/frontend/src/app/(public)/tour/chat/components/TourSidebar/components/TourSidebarHeader.tsx (1 conflict, ~20 lines)
    • autogpt_platform/frontend/src/app/api/openapi.json (4 conflicts, ~66 lines)
    • autogpt_platform/frontend/src/components/contextual/CredentialsInput/helpers.ts (2 conflicts, ~10 lines)
    • autogpt_platform/frontend/src/components/contextual/CredentialsInput/useCredentialsInput.ts (2 conflicts, ~32 lines)
    • autogpt_platform/frontend/src/components/contextual/IntegrationsPanel/components/ConnectServiceDialog/components/DetailView/MethodPanel.tsx (1 conflict, ~12 lines)
    • autogpt_platform/frontend/src/components/layout/AppSidebar/AppSidebar.tsx (2 conflicts, ~27 lines)
    • autogpt_platform/frontend/src/components/layout/AppSidebar/components/AppSidebarHeader/AppSidebarHeader.tsx (2 conflicts, ~34 lines)
    • autogpt_platform/frontend/src/components/layout/AppSidebar/components/SidebarSearch/SidebarSearch.tsx (2 conflicts, ~47 lines)
    • autogpt_platform/frontend/src/components/renderers/InputRenderer/base/standard/widgets/SelectInput/SelectWidget.tsx (1 conflict, ~5 lines)
    • autogpt_platform/frontend/src/hooks/useCredentials.ts (3 conflicts, ~54 lines)
    • autogpt_platform/frontend/src/lib/oauth-popup.ts (1 conflict, ~52 lines)
    • autogpt_platform/frontend/src/services/feature-flags/use-get-flag.ts (3 conflicts, ~20 lines)
  • feat(frontend): naming moment for existing users #14044 (Abhi1992002 · updated 10d ago)

    • 📁 autogpt_platform/
      • backend/backend/api/features/experts/experts_db.py (15 conflicts, ~281 lines)
      • backend/backend/api/features/experts/experts_db_test.py (29 conflicts, ~674 lines)
      • backend/backend/api/features/experts/models.py (2 conflicts, ~29 lines)
      • backend/backend/api/features/experts/routes.py (8 conflicts, ~121 lines)
      • backend/backend/api/features/experts/routes_test.py (18 conflicts, ~355 lines)
      • backend/backend/api/features/library/_add_to_library.py (6 conflicts, ~59 lines)
      • backend/backend/api/features/library/db.py (6 conflicts, ~95 lines)
      • backend/backend/api/features/library/db_test.py (1 conflict, ~5 lines)
      • backend/backend/data/db_manager_test.py (1 conflict, ~10 lines)
      • backend/snapshots/expert_raise_default (3 conflicts, ~14 lines)
      • frontend/src/app/(platform)/marketplace/__tests__/experts-section.test.tsx (1 conflict, ~172 lines)
      • frontend/src/app/(platform)/marketplace/components/ExpertsSection/ExpertsSection.tsx (2 conflicts, ~10 lines)
      • frontend/src/app/(platform)/raise/__tests__/main.test.tsx (19 conflicts, ~802 lines)
      • frontend/src/app/(platform)/raise/components/AssistantBubble/AssistantBubble.tsx (1 conflict, ~5 lines)
      • frontend/src/app/(platform)/raise/components/NameStep/NameStep.tsx (3 conflicts, ~122 lines)
      • frontend/src/app/(platform)/raise/components/RaiseFlow/RaiseFlow.tsx (2 conflicts, ~306 lines)
      • frontend/src/app/(platform)/raise/components/SoulPreviewPanel/SoulPreviewPanel.tsx (1 conflict, ~167 lines)
      • frontend/src/app/(platform)/raise/helpers.test.ts (4 conflicts, ~254 lines)
      • frontend/src/app/(platform)/raise/helpers.ts (8 conflicts, ~365 lines)
      • frontend/src/app/(platform)/raise/page.tsx (1 conflict, ~23 lines)
      • frontend/src/app/(platform)/raise/useRaisePage.ts (6 conflicts, ~266 lines)
      • frontend/src/app/api/openapi.json (7 conflicts, ~256 lines)
      • frontend/src/components/organisms/VoicePicker/VoicePicker.tsx (6 conflicts, ~54 lines)
      • frontend/src/components/organisms/VoicePicker/__tests__/VoicePicker.test.tsx (1 conflict, ~11 lines)
      • frontend/src/components/organisms/VoicePicker/components/CustomVoiceOption.tsx (5 conflicts, ~38 lines)
      • frontend/src/components/organisms/VoicePicker/components/SampleCard.tsx (6 conflicts, ~35 lines)
      • frontend/src/components/organisms/VoicePicker/styles.ts (2 conflicts, ~33 lines)
  • feat(backend): add workspace file move/copy and workspace folder tools #13700 (Abhi1992002 · updated 10d ago)

    • autogpt_platform/backend/backend/copilot/tools/__init__.py (1 conflict, ~20 lines)
    • autogpt_platform/backend/backend/copilot/tools/models.py (1 conflict, ~28 lines)
    • autogpt_platform/backend/backend/copilot/tools/tool_schema_test.py (1 conflict, ~32 lines)
    • docs/integrations/block-integrations/misc.md (1 conflict, ~5 lines)
  • feat(platform): replace the email system with the Briefing/Alert/Verdict/Ops design #14003 (Torantulino · updated 32m ago)

    • 📁 autogpt_platform/backend/backend/data/
      • db_manager.py (1 conflict, ~8 lines)
  • feat(backend/api): External API v2 #12206 (Pwuts · updated 18h ago)

🟡 Medium Risk — Some Line Overlap

These PRs have some overlapping changes:

  • feat(backend): tiered memory v1 — personal/team/org graphs, provenance-labeled recall, governed shared writes #13642 (ntindle · updated just now)

    • autogpt_platform/backend/backend/api/features/orgs/routes_test.py: L823-972, L1159-1164, L1303-1426, L2970-2972, L3232-3953
    • autogpt_platform/backend/backend/copilot/prompting.py: L682-704
    • autogpt_platform/backend/backend/copilot/baseline/service.py: L1587-1594
    • autogpt_platform/backend/backend/copilot/tools/tool_schema_test.py: L112-121, L165-179, L243-261, L273-284
    • autogpt_platform/backend/backend/copilot/graphiti/tiers.py: L1-428
    • autogpt_platform/backend/backend/copilot/graphiti/context.py: L11-44, L48-55, L57-164, L192-225, L227-233
    • autogpt_platform/backend/backend/copilot/tools/graphiti_search_test.py: L1-21, L33-56, L61-67, L82-90, L93-101, L115-117, L126-298
    • autogpt_platform/backend/backend/copilot/graphiti/client.py: L51-106
    • autogpt_platform/backend/backend/copilot/graphiti/context_test.py: L25-37, L40-57, L83-97, L99-160, L164-213, L218-224, L226-250, L252-260, L263-269, L273-279, L323-329, L342-348, L468-639
    • autogpt_platform/backend/backend/copilot/tools/graphiti_store.py: L3-9, L14-27, L52-57, L60-82, L164-169, L189-196, L227-243, L254-341, L361-368, L371-388
    • autogpt_platform/backend/backend/api/features/store/media_test.py: L64-90
    • autogpt_platform/backend/backend/copilot/graphiti/client_test.py: L11-18, L107-158, L232-240, L278-286
    • autogpt_platform/backend/backend/api/features/orgs/spend_test.py: L1-183
    • autogpt_platform/backend/backend/copilot/tools/graphiti_forget_test.py: L1-7, L17-43, L543-545, L558-631
    • autogpt_platform/backend/backend/api/features/orgs/routes.py: L1-7, L10-33, L108-113, L116-174, L239-244, L301-335
    • docs/platform/org-feature-map.md: L24-31
    • autogpt_platform/backend/backend/api/features/v1.py: L9-23, L667-688, L691-700, L708-714, L720-730, L739-748, L758-767, L793-799, L814-823, L1555-1561, L1569-1575, L1579-1588, L1594-1605, L1608-1614, L1624-1633, L1641-1650
    • autogpt_platform/backend/backend/copilot/tools/graphiti_store_test.py: L28-52, L420-422, L439-693
    • autogpt_platform/backend/backend/copilot/graphiti/ingest.py: L34-42, L245-253, L293-301, L328-335, L340-346, L410-416, L443-450, L457-532, L535-541, L557-598, L612-618
    • autogpt_platform/backend/backend/api/features/store/media.py: L61-77, L167-173, L176-185
    • autogpt_platform/backend/backend/copilot/graphiti/ingest_test.py: L26-32, L490-551
    • autogpt_platform/backend/backend/api/features/v1_credits_authz_test.py: L1-155
    • autogpt_platform/backend/backend/copilot/graphiti/tiers_test.py: L1-428
    • autogpt_platform/backend/backend/copilot/sdk/service.py: L5379-5396, L6255-6268
    • autogpt_platform/backend/backend/api/features/orgs/model.py: L117-122
    • autogpt_platform/backend/backend/copilot/tools/graphiti_forget.py: L51-67, L89-94, L100-114, L117-129, L138-149, L213-218, L228-233, L240-254, L264-270, L279-290
    • autogpt_platform/backend/backend/api/features/orgs/team_db.py: L38-108, L115-154, L198-204, L207-213, L230-243
    • autogpt_platform/backend/backend/api/features/orgs/team_model.py: L26-54
    • autogpt_platform/backend/backend/data/org_credit.py: L11-17, L260-329
    • autogpt_platform/backend/backend/copilot/sdk/responsiveness_test.py: L97-109, L118-136, L227-233, L239-253
    • autogpt_platform/backend/backend/api/features/orgs/team_routes.py: L1-16, L23-80, L82-100, L111-124, L130-141, L143-156, L167-173, L175-201, L212-227, L236-256, L259-272, L287-295, L304-315
    • autogpt_platform/backend/backend/api/features/orgs/regression_test.py: L3377-3417
    • autogpt_platform/backend/backend/copilot/tools/graphiti_search.py: L12-25, L62-83, L94-212, L217-230, L232-257
  • feat(backend): org avatar upload (stacked on per-team spend) #13663 (ntindle · updated just now)

    • autogpt_platform/backend/backend/api/features/orgs/routes_test.py: L823-972, L1159-1164, L1303-1426, L2970-2972, L3232-3953
    • autogpt_platform/backend/backend/api/features/orgs/model.py: L117-122
    • autogpt_platform/backend/backend/api/features/orgs/routes.py: L1-7, L10-33, L108-113, L116-174, L239-244, L301-335
    • autogpt_platform/backend/backend/api/features/orgs/spend_test.py: L1-183
    • docs/platform/org-feature-map.md: L24-31
    • autogpt_platform/backend/backend/api/features/v1.py: L9-23, L667-688, L691-700, L708-714, L720-730, L739-748, L758-767, L793-799, L814-823, L1555-1561, L1569-1575, L1579-1588, L1594-1605, L1608-1614, L1624-1633, L1641-1650
    • autogpt_platform/backend/backend/api/features/store/media_test.py: L64-90
    • autogpt_platform/backend/backend/api/features/store/media.py: L61-77, L167-173, L176-185
    • autogpt_platform/backend/backend/api/features/orgs/team_db.py: L38-108, L115-154, L198-204, L207-213, L230-243
    • autogpt_platform/backend/backend/api/features/orgs/team_model.py: L26-54
    • autogpt_platform/backend/backend/api/features/v1_credits_authz_test.py: L1-155
    • autogpt_platform/backend/backend/data/org_credit.py: L11-17, L260-329
    • autogpt_platform/backend/backend/api/features/orgs/team_routes.py: L1-16, L23-80, L82-100, L111-124, L130-141, L143-156, L167-173, L175-201, L212-227, L236-256, L259-272, L287-295, L304-315
    • autogpt_platform/backend/backend/api/features/orgs/regression_test.py: L3377-3417
  • feat(platform): org management UI — create org, settings, members, invitations #13496 (ntindle · updated just now)

    • autogpt_platform/backend/backend/copilot/prompting.py: L682-704
    • autogpt_platform/backend/snapshots/lib_agts_search: L40-47, L92-101
    • autogpt_platform/backend/backend/data/execution.py: L126-141, L209-214, L219-225, L364-369, L375-381
    • autogpt_platform/backend/backend/api/features/library/routes/agents.py: L215-239
    • autogpt_platform/backend/schema.prisma: L623-629, L1404-1430, L2084-2089, L2105-2111, L2241-2246, L2263-2305
    • autogpt_platform/backend/backend/copilot/graphiti/client.py: L51-106
    • autogpt_platform/backend/backend/executor/utils_credentials_owner_test.py: L1-363
    • autogpt_platform/backend/backend/api/features/store/media_test.py: L64-90
    • autogpt_platform/backend/backend/api/rest_api.py: L42-50, L516-531, L533-543
    • autogpt_platform/backend/backend/api/features/v1.py: L9-23, L667-688, L691-700, L708-714, L720-730, L739-748, L758-767, L793-799, L814-823, L1555-1561, L1569-1575, L1579-1588, L1594-1605, L1608-1614, L1624-1633, L1641-1650, L1728-1733, L1739-1744, L1753-1762, L1764-1834, L1836-1845, L1879-1901, L1907-1934, L1944-1962, L2412-2417, L2437-2442, L2469-2475, L2540-2554, L2574-2594, L2621-2627, L2803-2814, L2955-2983
    • autogpt_platform/backend/backend/copilot/graphiti/ingest.py: L34-42, L245-253, L293-301, L328-335, L340-346, L410-416, L443-450, L457-532, L535-541, L557-598, L612-618
    • autogpt_platform/backend/backend/api/features/orgs/memory_db.py: L1-230
    • autogpt_platform/backend/backend/util/test.py: L3-9, L234-263
    • autogpt_platform/backend/backend/copilot/graphiti/tiers_test.py: L1-428
    • autogpt_platform/backend/migrations/20260717151612_agent_graph_grants/migration.sql: L1-45
    • autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py: L1-346
    • autogpt_platform/backend/backend/api/features/orgs/team_routes.py: L1-16, L23-80, L82-100, L111-124, L130-141, L143-156, L167-173, L175-201, L212-227, L236-256, L259-272, L287-295, L304-315
    • autogpt_platform/backend/backend/executor/auto_credentials.py: L5-18, L30-80, L85-117, L122-142
    • autogpt_platform/backend/backend/api/features/orgs/grant_model.py: L1-77
    • autogpt_platform/backend/backend/data/db_manager_test.py: L20-29
    • autogpt_platform/backend/backend/api/features/orgs/routes_test.py: L823-972, L1159-1164, L1303-1426, L2970-2972, L3239-3953
    • autogpt_platform/backend/backend/copilot/tools/tool_schema_test.py: L112-121, L165-179, L243-261, L273-284
    • autogpt_platform/backend/backend/data/execution_stats_test.py: L6-17, L24-35, L99-101, L105-119
    • autogpt_platform/backend/backend/api/features/orgs/memory_model.py: L1-34
    • autogpt_platform/backend/backend/api/features/library/model.py: L42-49, L61-70, L227-239, L402-407, L409-416
    • autogpt_platform/backend/backend/copilot/tools/graphiti_store.py: L3-9, L14-27, L52-57, L60-82, L164-169, L189-196, L227-243, L254-341, L361-368, L371-388
    • autogpt_platform/backend/backend/data/graph_test.py: L60-81, L1194-1199, L1210-1262, L1483-1488, L1546-1598
    • autogpt_platform/backend/backend/copilot/tools/graphiti_forget_test.py: L1-7, L17-43, L543-545, L558-631
    • autogpt_platform/backend/backend/api/features/orgs/memory_routes_test.py: L1-430
    • autogpt_platform/backend/backend/copilot/tools/graphiti_store_test.py: L28-52, L420-422, L439-693
    • autogpt_platform/backend/backend/copilot/graphiti/ingest_test.py: L26-32, L490-551
    • autogpt_platform/autogpt_libs/autogpt_libs/auth/dependencies.py: L352-364
    • autogpt_platform/backend/backend/api/features/orgs/model.py: L18-27, L30-64, L70-77, L84-92, L117-122, L151-167
    • autogpt_platform/backend/backend/executor/utils_test.py: L11-17, L411-421, L493-592, L654-662, L890-895, L928-933, L935-940, L956-963, L987-996, L1029-1035, L1037-1043, L1059-1073, L1250-1255, L1360-1366, L1961-1966, L2008-2016, L2020-2025, L2072-2081, L2090-2100, L2102-2107, L2113-2119, L2123-2133, L2137-2151, L2215-2227, L2229-2235, L2241-2261, L2288-2452, L2706-2708, L3007-3060
    • autogpt_platform/backend/backend/copilot/tools/graphiti_forget.py: L51-67, L89-94, L100-114, L117-129, L138-149, L213-218, L228-233, L240-254, L264-270, L279-290
    • autogpt_platform/backend/backend/api/features/orgs/team_model.py: L26-54
    • autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py: L3-17, L29-34, L37-57, L94-108, L122-142, L162-163, L165-168, L170-258
    • autogpt_platform/backend/backend/api/features/v1_test.py: L8-17, L20-42, L814-824, L1050-1554, L1598-1600, L2097-2181
    • autogpt_platform/backend/backend/api/features/library/db.py: L769-789, L815-820, L822-843, L921-931, L944-966, L1250-1258, L1285-1291, L1521-1526, L1531-1536, L1554-1562, L1566-1573, L1594-1603, L2384-2395, L2425-2437, L2554-2560, L2562-2567, L2588-2594, L2596-2605, L2607-2615, L2636-2646, L2651-2658
    • autogpt_platform/backend/backend/api/features/orgs/grant_db.py: L1-227
    • autogpt_platform/backend/snapshots/invitation_resend_response: L1-7
    • autogpt_platform/backend/backend/copilot/graphiti/tiers.py: L1-428
    • autogpt_platform/backend/backend/copilot/graphiti/context.py: L11-44, L48-55, L57-164, L192-225, L227-233
    • autogpt_platform/backend/backend/api/features/orgs/grant_db_test.py: L1-299
    • autogpt_platform/backend/backend/api/features/library/routes/folders.py: L129-137, L140-159
    • autogpt_platform/backend/backend/executor/manager.py: L102-108, L212-263, L302-314, L352-365, L370-376, L380-392, L398-454, L464-485, L489-509, L515-549, L562-569, L577-584
    • autogpt_platform/backend/backend/api/features/chat/routes.py: L425-432, L544-553
    • autogpt_platform/backend/backend/api/features/orgs/spend_test.py: L1-183
    • autogpt_platform/backend/backend/api/features/orgs/memory_routes.py: L1-78
    • autogpt_platform/backend/backend/api/features/v1_credits_authz_test.py: L1-155
    • autogpt_platform/backend/backend/executor/utils.py: L5-20, L44-51, L399-409, L413-424, L444-472, L479-492, L494-507, L510-552, L567-602, L633-648, L659-665, L677-682, L696-701, L717-731, L736-762, L773-812, L847-862, L872-884, L891-897, L915-921, L929-938, L947-952, L998-1004, L1011-1021, L1054-1069, L1078-1084, L1193-1198, L1275-1280, L1287-1292, L1324-1361, L1391-1396, L1407-1412, L1433-1488, L1520-1538, L1544-1563, L1573-1579, L1609-1626, L1637-1645, L1666-1673, L1686-1694, L1696-1747
    • autogpt_platform/backend/backend/conftest.py: L49-68
    • autogpt_platform/backend/backend/data/graph.py: L5-11, L28-34, L1419-1453, L1738-1757, L1767-1807
    • autogpt_platform/backend/backend/api/features/library/routes_test.py: L97-104, L139-149, L311-313, L316-396
    • autogpt_platform/backend/backend/api/features/orgs/team_db.py: L38-108, L115-154, L198-204, L207-213, L230-243
    • autogpt_platform/backend/backend/data/org_credit.py: L11-17, L260-329
    • autogpt_platform/backend/backend/data/grants.py: L1-239
    • autogpt_platform/backend/backend/copilot/baseline/service.py: L1587-1594
    • autogpt_platform/backend/backend/data/grants_test.py: L1-565
    • autogpt_platform/backend/backend/api/features/store/model_test.py: L1-58
    • autogpt_platform/backend/snapshots/sub_success: L28-35
    • autogpt_platform/backend/backend/api/features/library/model_test.py: L13-20, L30-39, L105-145
    • autogpt_platform/backend/backend/copilot/tools/graphiti_search_test.py: L1-21, L33-56, L61-67, L82-90, L93-101, L115-117, L126-298
    • autogpt_platform/backend/backend/executor/manager_auto_credentials_test.py: L5-12, L56-64, L469-647
    • autogpt_platform/backend/backend/api/features/store/routes_test.py: L582-588, L607-616
    • autogpt_platform/backend/backend/copilot/graphiti/context_test.py: L25-37, L40-57, L83-97, L99-160, L164-213, L218-224, L226-250, L252-260, L263-269, L273-279, L323-329, L342-348, L468-639
    • autogpt_platform/backend/backend/copilot/graphiti/client_test.py: L11-18, L107-158, L232-240, L278-286
    • autogpt_platform/backend/backend/api/features/store/model.py: L217-228, L245-257, L277-282, L284-290
    • autogpt_platform/backend/backend/data/db_manager.py: L96-105, L370-381, L604-617, L722-727, L730-737
    • autogpt_platform/backend/backend/api/features/orgs/routes.py: L1-7, L10-33, L104-175, L239-244, L301-336
    • autogpt_platform/backend/backend/executor/manager_credential_lease_test.py: L156-415, L598-626, L638-655, L659-665
    • autogpt_platform/backend/backend/api/features/search/content_handlers_integration_test.py: L22-44, L46-53
    • autogpt_platform/backend/backend/api/features/store/media.py: L61-77, L167-173, L176-185
    • autogpt_platform/backend/backend/api/features/library/db_test.py: L425-433, L2249-2328
    • autogpt_platform/backend/backend/api/features/orgs/grant_routes.py: L1-117
    • autogpt_platform/backend/backend/api/features/orgs/db.py: L4-10, L24-50, L341-346, L362-382
    • autogpt_platform/backend/backend/api/features/chat/routes_test.py: L2358-2365, L2372-2381, L2431-2469
    • autogpt_platform/backend/backend/copilot/sdk/service.py: L5379-5396, L6255-6268
    • autogpt_platform/backend/backend/api/model.py: L43-71
    • autogpt_platform/backend/backend/copilot/sdk/responsiveness_test.py: L97-109, L118-136, L227-233, L239-253
    • autogpt_platform/backend/backend/api/features/orgs/regression_test.py: L202-212, L215-226, L1061-1077, L1215-1220, L1224-1232, L3377-3429
    • autogpt_platform/backend/backend/copilot/tools/graphiti_search.py: L12-25, L62-83, L94-212, L217-230, L232-257
  • feat(backend): agent-graph grants — share with teams (SECRT-2448, v1) #13599 (ntindle · updated 1m ago)

    • autogpt_platform/backend/backend/api/features/orgs/grant_db.py: L1-170
    • autogpt_platform/backend/backend/api/features/orgs/routes_test.py: L823-972, L1159-1164, L1303-1426, L2970-2972, L3232-3953
    • autogpt_platform/backend/backend/copilot/prompting.py: L682-704
    • autogpt_platform/backend/backend/copilot/baseline/service.py: L1587-1594
    • autogpt_platform/backend/snapshots/lib_agts_search: L40-47, L92-101
    • autogpt_platform/backend/backend/copilot/tools/tool_schema_test.py: L112-121, L165-179, L243-261, L273-284
    • autogpt_platform/backend/backend/data/grants_test.py: L1-148
    • autogpt_platform/backend/backend/api/features/store/model_test.py: L1-58
    • autogpt_platform/backend/backend/copilot/graphiti/tiers.py: L1-428
    • autogpt_platform/backend/snapshots/sub_success: L28-35
    • autogpt_platform/backend/backend/api/features/orgs/memory_model.py: L1-34
    • autogpt_platform/backend/backend/api/features/library/routes/agents.py: L215-239
    • autogpt_platform/backend/backend/copilot/graphiti/context.py: L11-44, L48-55, L57-164, L192-225, L227-233
    • autogpt_platform/backend/backend/api/features/library/model_test.py: L13-20, L30-39, L105-145
    • autogpt_platform/backend/backend/api/features/library/model.py: L42-49, L61-70, L227-239, L402-407, L409-416
    • autogpt_platform/backend/backend/api/features/orgs/grant_db_test.py: L1-199
    • autogpt_platform/backend/backend/api/features/library/routes/folders.py: L129-137, L140-159
    • autogpt_platform/backend/backend/copilot/tools/graphiti_search_test.py: L1-21, L33-56, L61-67, L82-90, L93-101, L115-117, L126-298
    • autogpt_platform/backend/schema.prisma: L623-629, L1404-1430, L2084-2089, L2105-2111, L2241-2246, L2263-2305
    • autogpt_platform/backend/backend/copilot/graphiti/client.py: L51-106
    • autogpt_platform/backend/backend/api/features/store/routes_test.py: L582-588, L607-616
    • autogpt_platform/backend/backend/copilot/graphiti/context_test.py: L25-37, L40-57, L83-97, L99-160, L164-213, L218-224, L226-250, L252-260, L263-269, L273-279, L323-329, L342-348, L468-639
    • autogpt_platform/backend/backend/copilot/tools/graphiti_store.py: L3-9, L14-27, L52-57, L60-82, L164-169, L189-196, L227-243, L254-341, L361-368, L371-388
    • autogpt_platform/backend/backend/api/features/store/media_test.py: L64-90
    • autogpt_platform/backend/backend/copilot/graphiti/client_test.py: L11-18, L107-158, L232-240, L278-286
    • autogpt_platform/backend/backend/api/rest_api.py: L42-50, L516-531, L533-543
    • autogpt_platform/backend/backend/data/graph_test.py: L60-81
    • autogpt_platform/backend/backend/api/features/store/model.py: L217-228, L245-257, L277-282, L284-290
    • autogpt_platform/backend/backend/api/features/chat/routes.py: L425-432, L544-553
    • autogpt_platform/backend/backend/api/features/orgs/spend_test.py: L1-183
    • autogpt_platform/backend/backend/copilot/tools/graphiti_forget_test.py: L1-7, L17-43, L543-545, L558-631
    • autogpt_platform/backend/backend/api/features/orgs/grant_model.py: L1-77
    • autogpt_platform/backend/backend/api/features/orgs/routes.py: L1-7, L10-33, L104-175, L239-244, L301-336
    • autogpt_platform/backend/backend/api/features/orgs/memory_routes.py: L1-78
    • autogpt_platform/backend/backend/api/features/orgs/memory_routes_test.py: L1-430
    • docs/platform/org-feature-map.md: L24-31
    • autogpt_platform/backend/backend/api/features/v1.py: L9-23, L667-688, L691-700, L708-714, L720-730, L739-748, L758-767, L793-799, L814-823, L1555-1561, L1569-1575, L1579-1588, L1594-1605, L1608-1614, L1624-1633, L1641-1650, L1728-1733, L1739-1744, L1753-1762, L1764-1834, L1836-1845, L1879-1901, L1907-1934, L1944-1962, L2412-2417, L2437-2442, L2469-2475, L2540-2554, L2574-2594, L2621-2627, L2803-2814, L2955-2983
    • autogpt_platform/backend/backend/copilot/tools/graphiti_store_test.py: L28-52, L420-422, L439-693
    • autogpt_platform/backend/backend/api/features/search/content_handlers_integration_test.py: L22-44, L46-53
    • autogpt_platform/backend/backend/copilot/graphiti/ingest.py: L34-42, L245-253, L293-301, L328-335, L340-346, L410-416, L443-450, L457-532, L535-541, L557-598, L612-618
    • autogpt_platform/backend/backend/api/features/orgs/memory_db.py: L1-230
    • autogpt_platform/backend/backend/api/features/store/media.py: L61-77, L167-173, L176-185
    • autogpt_platform/backend/backend/copilot/graphiti/ingest_test.py: L26-32, L490-551
    • autogpt_platform/backend/backend/api/features/v1_credits_authz_test.py: L1-155
    • autogpt_platform/backend/backend/util/test.py: L3-9, L234-263
    • autogpt_platform/autogpt_libs/autogpt_libs/auth/dependencies.py: L352-364
    • autogpt_platform/backend/backend/api/features/library/db_test.py: L425-433, L2249-2328
    • autogpt_platform/backend/backend/api/features/orgs/grant_routes.py: L1-117
    • autogpt_platform/backend/backend/conftest.py: L49-68
    • autogpt_platform/backend/backend/copilot/graphiti/tiers_test.py: L1-428
    • autogpt_platform/backend/backend/api/features/orgs/db.py: L4-10, L24-50, L341-346, L362-382
    • autogpt_platform/backend/backend/api/features/chat/routes_test.py: L2358-2365, L2372-2381, L2431-2469
    • autogpt_platform/backend/backend/api/features/orgs/model.py: L18-27, L30-64, L70-77, L84-92, L117-122, L151-167
    • autogpt_platform/backend/backend/copilot/sdk/service.py: L5379-5396, L6255-6268
    • autogpt_platform/backend/backend/data/graph.py: L5-11, L28-34, L1419-1449, L1738-1757, L1767-1804
    • autogpt_platform/backend/backend/api/features/library/routes_test.py: L97-104, L139-149, L311-313, L316-396
    • autogpt_platform/backend/migrations/20260717151612_agent_graph_grants/migration.sql: L1-45
    • autogpt_platform/backend/backend/api/model.py: L43-71
    • autogpt_platform/backend/backend/copilot/tools/graphiti_forget.py: L51-67, L89-94, L100-114, L117-129, L138-149, L213-218, L228-233, L240-254, L264-270, L279-290
    • autogpt_platform/backend/backend/api/features/orgs/team_db.py: L38-108, L115-154, L198-204, L207-213, L230-243
    • autogpt_platform/backend/backend/api/features/orgs/team_model.py: L26-54
    • autogpt_platform/backend/backend/api/features/v1_test.py: L8-17, L20-42, L814-824, L1050-1554, L1598-1600, L2097-2181
    • autogpt_platform/backend/backend/data/org_credit.py: L11-17, L260-329
    • autogpt_platform/backend/backend/copilot/sdk/responsiveness_test.py: L97-109, L118-136, L227-233, L239-253
    • autogpt_platform/backend/backend/api/features/orgs/team_routes.py: L1-16, L23-80, L82-100, L111-124, L130-141, L143-156, L167-173, L175-201, L212-227, L236-256, L259-272, L287-295, L304-315
    • autogpt_platform/backend/backend/api/features/library/db.py: L769-789, L815-820, L822-843, L921-931, L944-966, L1250-1258, L1285-1291, L1521-1526, L1531-1536, L1554-1562, L1566-1573, L1594-1603, L2384-2395, L2425-2437, L2554-2560, L2562-2567, L2588-2594, L2596-2605, L2607-2615, L2636-2646, L2651-2658
    • autogpt_platform/backend/backend/api/features/orgs/regression_test.py: L202-212, L215-226, L1061-1077, L1215-1220, L1224-1232, L3377-3429
    • autogpt_platform/backend/backend/data/grants.py: L1-85
    • autogpt_platform/backend/backend/copilot/tools/graphiti_search.py: L12-25, L62-83, L94-212, L217-230, L232-257
  • feat(backend): honor team context on api-key/fork/folder creates + team_id on list responses #13640 (ntindle · updated 1m ago)

    • autogpt_platform/backend/backend/api/features/orgs/routes_test.py: L823-972, L1159-1164, L1303-1426, L2970-2972, L3232-3953
    • autogpt_platform/backend/backend/copilot/prompting.py: L682-704
    • autogpt_platform/backend/backend/copilot/baseline/service.py: L1587-1594
    • autogpt_platform/backend/snapshots/lib_agts_search: L40-47, L92-101
    • autogpt_platform/backend/backend/copilot/tools/tool_schema_test.py: L112-121, L165-179, L243-261, L273-284
    • autogpt_platform/backend/backend/api/features/store/model_test.py: L1-58
    • autogpt_platform/backend/backend/copilot/graphiti/tiers.py: L1-428
    • autogpt_platform/backend/snapshots/sub_success: L28-35
    • autogpt_platform/backend/backend/api/features/orgs/memory_model.py: L1-34
    • autogpt_platform/backend/backend/api/features/library/routes/agents.py: L215-239
    • autogpt_platform/backend/backend/copilot/graphiti/context.py: L11-44, L48-55, L57-164, L192-225, L227-233
    • autogpt_platform/backend/backend/api/features/library/model.py: L42-49, L61-70, L227-239, L402-407, L409-416
    • autogpt_platform/backend/backend/api/features/library/model_test.py: L13-20, L30-39, L105-145
    • autogpt_platform/backend/backend/api/features/library/routes/folders.py: L129-137, L140-159
    • autogpt_platform/backend/backend/copilot/tools/graphiti_search_test.py: L1-21, L33-56, L61-67, L82-90, L93-101, L115-117, L126-298
    • autogpt_platform/backend/backend/copilot/graphiti/client.py: L51-106
    • autogpt_platform/backend/backend/api/features/store/routes_test.py: L582-588, L607-616
    • autogpt_platform/backend/backend/copilot/graphiti/context_test.py: L25-37, L40-57, L83-97, L99-160, L164-213, L218-224, L226-250, L252-260, L263-269, L273-279, L323-329, L342-348, L468-639
    • autogpt_platform/backend/backend/copilot/tools/graphiti_store.py: L3-9, L14-27, L52-57, L60-82, L164-169, L189-196, L227-243, L254-341, L361-368, L371-388
    • autogpt_platform/backend/backend/api/features/store/media_test.py: L64-90
    • autogpt_platform/backend/backend/copilot/graphiti/client_test.py: L11-18, L107-158, L232-240, L278-286
    • autogpt_platform/backend/backend/api/rest_api.py: L43-49, L516-527
    • autogpt_platform/backend/backend/api/features/store/model.py: L217-228, L245-257, L277-282, L284-290
    • autogpt_platform/backend/backend/api/features/chat/routes.py: L425-432, L544-553
    • autogpt_platform/backend/backend/api/features/orgs/spend_test.py: L1-183
    • autogpt_platform/backend/backend/copilot/tools/graphiti_forget_test.py: L1-7, L17-43, L543-545, L558-631
    • autogpt_platform/backend/backend/api/features/orgs/routes.py: L1-7, L10-33, L104-175, L239-244, L301-336
    • autogpt_platform/backend/backend/api/features/orgs/memory_routes.py: L1-78
    • autogpt_platform/backend/backend/api/features/orgs/memory_routes_test.py: L1-430
    • docs/platform/org-feature-map.md: L24-31
    • autogpt_platform/backend/backend/api/features/v1.py: L9-23, L667-688, L691-700, L708-714, L720-730, L739-748, L758-767, L793-799, L814-823, L1555-1561, L1569-1575, L1579-1588, L1594-1605, L1608-1614, L1624-1633, L1641-1650, L1728-1733, L1739-1744, L1753-1762, L1764-1834, L1836-1845, L1879-1901, L1907-1934, L1944-1962, L2412-2417, L2437-2442, L2469-2475, L2540-2554, L2574-2594, L2621-2627, L2803-2814, L2955-2983
    • autogpt_platform/backend/backend/copilot/tools/graphiti_store_test.py: L28-52, L420-422, L439-693
    • autogpt_platform/backend/backend/api/features/search/content_handlers_integration_test.py: L22-44, L46-53
    • autogpt_platform/backend/backend/copilot/graphiti/ingest.py: L34-42, L245-253, L293-301, L328-335, L340-346, L410-416, L443-450, L457-532, L535-541, L557-598, L612-618
    • autogpt_platform/backend/backend/api/features/orgs/memory_db.py: L1-230
    • autogpt_platform/backend/backend/api/features/store/media.py: L61-77, L167-173, L176-185
    • autogpt_platform/backend/backend/copilot/graphiti/ingest_test.py: L26-32, L490-551
    • autogpt_platform/backend/backend/api/features/v1_credits_authz_test.py: L1-155
    • autogpt_platform/backend/backend/util/test.py: L3-9, L234-263
    • autogpt_platform/autogpt_libs/autogpt_libs/auth/dependencies.py: L352-364
    • autogpt_platform/backend/backend/api/features/library/db_test.py: L425-433, L2249-2328
    • autogpt_platform/backend/backend/conftest.py: L49-68
    • autogpt_platform/backend/backend/copilot/graphiti/tiers_test.py: L1-428
    • autogpt_platform/backend/backend/api/features/orgs/db.py: L4-10, L24-50, L341-346, L362-382
    • autogpt_platform/backend/backend/api/features/chat/routes_test.py: L2358-2365, L2372-2381, L2431-2469
    • autogpt_platform/backend/backend/api/features/orgs/model.py: L18-27, L30-64, L70-77, L84-92, L117-122, L151-167
    • autogpt_platform/backend/backend/copilot/sdk/service.py: L5379-5396, L6255-6268
    • autogpt_platform/backend/backend/api/features/library/routes_test.py: L97-104, L139-149, L311-313, L316-396
    • autogpt_platform/backend/backend/api/model.py: L43-71
    • autogpt_platform/backend/backend/copilot/tools/graphiti_forget.py: L51-67, L89-94, L100-114, L117-129, L138-149, L213-218, L228-233, L240-254, L264-270, L279-290
    • autogpt_platform/backend/backend/api/features/orgs/team_db.py: L38-108, L115-154, L198-204, L207-213, L230-243
    • autogpt_platform/backend/backend/api/features/orgs/team_model.py: L26-54
    • autogpt_platform/backend/backend/api/features/v1_test.py: L8-17, L20-42, L814-824, L1050-1554, L1598-1600, L2097-2181
    • autogpt_platform/backend/backend/data/org_credit.py: L11-17, L260-329
    • autogpt_platform/backend/backend/copilot/sdk/responsiveness_test.py: L97-109, L118-136, L227-233, L239-253
    • autogpt_platform/backend/backend/api/features/orgs/team_routes.py: L1-16, L23-80, L82-100, L111-124, L130-141, L143-156, L167-173, L175-201, L212-227, L236-256, L259-272, L287-295, L304-315
    • autogpt_platform/backend/backend/api/features/library/db.py: L769-789, L815-820, L822-843, L921-931, L944-966, L1250-1258, L1285-1291, L1521-1526, L1531-1536, L1554-1562, L1566-1573, L1594-1603, L2384-2395, L2425-2437, L2554-2560, L2562-2567, L2588-2594, L2596-2605, L2607-2615, L2636-2646, L2651-2658
    • autogpt_platform/backend/backend/api/features/orgs/regression_test.py: L1061-1071, L1215-1220, L1224-1226, L3377-3423
    • autogpt_platform/backend/backend/copilot/tools/graphiti_search.py: L12-25, L62-83, L94-212, L217-230, L232-257

🟢 Low Risk — File Overlap Only

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

Summary: 7 conflict(s), 5 medium risk, 7 low risk (out of 19 PRs with file overlap)


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

@autogpt-batch-bot autogpt-batch-bot Bot added batch PR is queued in the batch-deploy rollup (batch-bot source of truth) and removed batch PR is queued in the batch-deploy rollup (batch-bot source of truth) labels Jul 18, 2026
@autogpt-batch-bot

Copy link
Copy Markdown

🤖 Removed from the batch — this PR conflicts with the rest of the current group and could not be merged onto batch/rollup (conflicting files). Rebase onto dev (or resolve against the other batched PRs) and re-add with /batch.

@autogpt-batch-bot autogpt-batch-bot Bot mentioned this pull request Jul 18, 2026
11 tasks
@autogpt-batch-bot

Copy link
Copy Markdown

🤖 Added #13603 to the batch. Current batch (6): #13599, #13574, #13541, #13540, #13532, #13530. Ejected: #13603.

Deploying the combined preview (#13537); /batch-merge lands them together.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

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

Inline comments:
In `@autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py`:
- Around line 137-179: Update resend_invitation’s prisma.orginvitation.update
call to catch the ORM not-found exception and translate it into NotFoundError
for invitation_id, including concurrent deletion cases. Remove the unreachable
refreshed-is-None check while preserving the existing response behavior for
successful updates.
🪄 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: d5e765b1-f2f9-48e4-b544-083fd1911a78

📥 Commits

Reviewing files that changed from the base of the PR and between ad61e7e and 88f82ce.

📒 Files selected for processing (2)
  • autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py
  • autogpt_platform/backend/backend/api/features/orgs/routes_test.py
📜 Review details
⏰ Context from checks skipped due to timeout. (14)
  • GitHub Check: check API types
  • GitHub Check: type-check (3.11)
  • GitHub Check: type-check (3.12)
  • GitHub Check: test (3.13)
  • GitHub Check: type-check (3.13)
  • GitHub Check: test (3.11)
  • GitHub Check: lint
  • GitHub Check: test (3.12)
  • GitHub Check: types
  • GitHub Check: Analyze (python)
  • GitHub Check: lint
  • GitHub Check: Analyze (typescript)
  • GitHub Check: end-to-end tests
  • GitHub Check: Check PR Status
🧰 Additional context used
📓 Path-based instructions (5)
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

autogpt_platform/backend/**/*.py: Use poetry run ... command for executing Python package dependencies
Use top-level imports only — avoid 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 are acceptable for sibling modules within the same package; avoid double-dot relative imports
Do not use duck typing — avoid hasattr/getattr/isinstance for type dispatch; use typed interfaces/unions/protocols instead
Use Pydantic models over dataclass/namedtuple/dict for structured data
Do not use linter suppressors — no # type: ignore, # noqa, # pyright: ignore; fix the type/code instead
Prefer list comprehensions over manual loop-and-append patterns
Use early return with guard clauses first to avoid deep nesting
Use %s for deferred interpolation in debug log statements for efficiency; use f-strings elsewhere for readability (e.g., logger.debug("Processing %s items", count) vs logger.info(f"Processing {count} items"))
Sanitize error paths by using os.path.basename() in error messages to avoid leaking directory structure
Be aware of TOCTOU (Time-Of-Check-Time-Of-Use) issues — avoid check-then-act patterns for file access and credit charging
Use transaction=True for Redis pipelines to ensure atomicity on multi-step 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 helpers, models, or a sub-module into a new file)
Keep functions under ~40 lines; extract named helpers when a function grows longer
...

Files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py
  • autogpt_platform/backend/backend/api/features/orgs/routes_test.py
autogpt_platform/backend/backend/api/features/**/*.py

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

Update routes in '/backend/backend/api/features/' and add/update Pydantic models in the same directory for API development

Files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py
  • autogpt_platform/backend/backend/api/features/orgs/routes_test.py
autogpt_platform/{backend,autogpt_libs}/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Format Python code with poetry run format

Files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py
  • autogpt_platform/backend/backend/api/features/orgs/routes_test.py
autogpt_platform/backend/**/api/**/*.py

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

autogpt_platform/backend/**/api/**/*.py: Use Security() instead of Depends() for authentication dependencies to get proper OpenAPI security specification
Follow SSE (Server-Sent Events) protocol: use data: lines for frontend-parsed events (must match Zod schema) and : comment lines for heartbeats/status

Files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py
  • autogpt_platform/backend/backend/api/features/orgs/routes_test.py
autogpt_platform/backend/**/*_test.py

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

autogpt_platform/backend/**/*_test.py: Use pytest with snapshot testing for API responses
Colocate test files with source files using *_test.py naming convention
Mock at boundaries — mock where the symbol is used, not where it's defined; after refactoring, update mock targets to match new module paths
Use AsyncMock from unittest.mock for async functions in tests
When writing tests, use Test-Driven Development (TDD): write failing tests marked with @pytest.mark.xfail before implementation, then remove the marker once the implementation is complete
When creating snapshots in tests, use poetry run pytest path/to/test.py --snapshot-update; always review snapshot changes with git diff before committing

Files:

  • autogpt_platform/backend/backend/api/features/orgs/routes_test.py
🧠 Learnings (11)
📚 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/api/features/orgs/invitation_routes.py
  • autogpt_platform/backend/backend/api/features/orgs/routes_test.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/api/features/orgs/invitation_routes.py
  • autogpt_platform/backend/backend/api/features/orgs/routes_test.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/api/features/orgs/invitation_routes.py
  • autogpt_platform/backend/backend/api/features/orgs/routes_test.py
📚 Learning: 2026-03-31T15:37:38.626Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12623
File: autogpt_platform/backend/backend/copilot/tools/agent_generator/fixer.py:37-47
Timestamp: 2026-03-31T15:37:38.626Z
Learning: When validating/constructing Anthropic API model IDs in Significant-Gravitas/AutoGPT, allow the hyphen-separated Claude Opus 4.6 model ID `claude-opus-4-6` (it corresponds to `LlmModel.CLAUDE_4_6_OPUS` in `autogpt_platform/backend/backend/blocks/llm.py`). Do NOT require the dot-separated form in Anthropic contexts. Only OpenRouter routing variants should use the dot separator (e.g., `anthropic/claude-opus-4.6`); `claude-opus-4-6` should be treated as correct when passed to Anthropic, and flagged only if it’s used in the OpenRouter path where the dot form is expected.

Applied to files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py
  • autogpt_platform/backend/backend/api/features/orgs/routes_test.py
📚 Learning: 2026-04-15T02:43:36.890Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 12780
File: autogpt_platform/backend/backend/copilot/tools/workspace_files.py:0-0
Timestamp: 2026-04-15T02:43:36.890Z
Learning: When reviewing Python exception handlers, do not flag `isinstance(e, X)` checks as dead/unreachable if the caught exception `X` is a subclass of the exception type being handled. For example, if `X` (e.g., `VirusScanError`) inherits from `ValueError` (directly or via an intermediate class) and it can be raised within an `except ValueError:` block, then `isinstance(e, X)` inside that handler is reachable and should not be treated as dead code.

Applied to files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py
  • autogpt_platform/backend/backend/api/features/orgs/routes_test.py
📚 Learning: 2026-05-23T05:29:43.085Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 13200
File: autogpt_platform/backend/backend/executor/scheduler.py:590-593
Timestamp: 2026-05-23T05:29:43.085Z
Learning: When reviewing Python code that uses Pydantic discriminated/tagged unions (e.g., `Annotated[Union[...], Field(discriminator="kind")]`), recognize that using `isinstance(x, SomeVariantInfo)` to narrow the union is an intentional and correct runtime guard and should also enable static type narrowing in tools like Pyright. Do not recommend replacing such `isinstance`-based narrowing with `cast(...)` when the check already proves the variant at runtime.

Applied to files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py
  • autogpt_platform/backend/backend/api/features/orgs/routes_test.py
📚 Learning: 2026-04-22T11:46:04.431Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12881
File: autogpt_platform/backend/backend/copilot/config.py:0-0
Timestamp: 2026-04-22T11:46:04.431Z
Learning: Do not flag the Claude Sonnet 4.6 model ID as incorrect when it uses the project’s established hyphenated convention: `anthropic/claude-sonnet-4-6`. This hyphen form is the intentional, production convention and should be treated as valid (including in files like llm.py, blocks tests, reasoning.py, `_is_anthropic_model` tests, and config defaults). Note that OpenRouter also accepts the dot variant `anthropic/claude-sonnet-4.6`, so either form may be tolerated, but `anthropic/claude-sonnet-4-6` should be considered the standard to match project usage.

Applied to files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py
  • autogpt_platform/backend/backend/api/features/orgs/routes_test.py
📚 Learning: 2026-04-22T11:46:12.892Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12881
File: autogpt_platform/backend/backend/copilot/baseline/service.py:322-332
Timestamp: 2026-04-22T11:46:12.892Z
Learning: In this codebase (Significant-Gravitas/AutoGPT), OpenRouter-routed Anthropic model IDs should use the hyphen-separated convention (e.g., `anthropic/claude-sonnet-4-6`, `anthropic/claude-opus-4-6`). Although OpenRouter may accept both hyphen and dot variants, treat the hyphen-separated form as the intended, correct codebase-wide convention and do not flag it as an error. Only flag the dot-separated variant (e.g., `anthropic/claude-sonnet-4.6`) as incorrect when reviewing/validating model ID strings for OpenRouter-routed Anthropic models.

Applied to files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py
  • autogpt_platform/backend/backend/api/features/orgs/routes_test.py
📚 Learning: 2026-05-07T18:48:14.242Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 13040
File: autogpt_platform/backend/backend/blocks/llm.py:0-0
Timestamp: 2026-05-07T18:48:14.242Z
Learning: In this repository, isort may split imports from the same module into separate blocks when some imports are aliased (e.g., `from module import X as Y`) and others are not. Preserve the two-block layout when it results from isort (such as keeping `from openai.types.chat import ChatCompletion as OpenAIChatCompletion` separate from non-aliased imports from `openai.types.chat`). Do not treat that split as a style issue during review; merging them into a single block can fail CI with `Imports are incorrectly sorted and/or formatted`.

Applied to files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py
  • autogpt_platform/backend/backend/api/features/orgs/routes_test.py
📚 Learning: 2026-05-26T14:24:34.866Z
Learnt from: Abhi1992002
Repo: Significant-Gravitas/AutoGPT PR: 13217
File: autogpt_platform/backend/backend/api/features/search/service.py:137-137
Timestamp: 2026-05-26T14:24:34.866Z
Learning: In the Significant-Gravitas/AutoGPT backend, treat `user_id` (an opaque UUID used only for correlation/tracing) as non-PII. Do not flag direct logging of `user_id` in `logger.warning`/`logger.info` statements as a PII exposure issue, as the established convention is to log `user_id` for tracing while reserving PII for fields like email or display name.

Applied to files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py
  • autogpt_platform/backend/backend/api/features/orgs/routes_test.py
📚 Learning: 2026-06-11T19:39:10.493Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 13337
File: autogpt_platform/backend/backend/copilot/graphiti/reranker.py:0-0
Timestamp: 2026-06-11T19:39:10.493Z
Learning: In the Significant-Gravitas/AutoGPT Python backend, when calling the OpenAI Python client `chat.completions.create`, construct the `messages` payload using the concrete typed-dict variants from `openai.types.chat` (e.g., `ChatCompletionSystemMessageParam`, `ChatCompletionUserMessageParam`, etc.) rather than trying to instantiate `ChatCompletionMessageParam` directly. `ChatCompletionMessageParam` is a `Union` alias and is not constructible, so `ChatCompletionMessageParam(role=..., content=...)` should fail type checking. Build each message element with the appropriate concrete typed dict and then annotate the resulting list as `list[ChatCompletionMessageParam]` (e.g., `messages: list[ChatCompletionMessageParam] = [ChatCompletionSystemMessageParam(...), ...]`).

Applied to files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py
  • autogpt_platform/backend/backend/api/features/orgs/routes_test.py

@codecov

codecov Bot commented Jul 18, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.73756% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 80.55%. Comparing base (aad3634) to head (4f851e1).

Additional details and impacted files
@@                       Coverage Diff                       @@
##           feat/grant-credential-modes   #13603      +/-   ##
===============================================================
+ Coverage                        80.53%   80.55%   +0.01%     
===============================================================
  Files                             3334     3335       +1     
  Lines                           256126   256343     +217     
  Branches                         23633    23643      +10     
===============================================================
+ Hits                            206280   206501     +221     
+ Misses                           44551    44534      -17     
- Partials                          5295     5308      +13     
Flag Coverage Δ
platform-backend 85.78% <97.73%> (+0.01%) ⬆️
platform-frontend 57.87% <ø> (-0.02%) ⬇️
platform-frontend-e2e 28.28% <ø> (-0.28%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
Platform Backend 85.78% <97.73%> (+0.01%) ⬆️
Platform Frontend 60.32% <ø> (-0.01%) ⬇️
AutoGPT Libs ∅ <ø> (∅)
Classic AutoGPT 28.43% <ø> (ø)
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ntindle

ntindle commented Jul 18, 2026

Copy link
Copy Markdown
Member Author

/batch

@autogpt-batch-bot autogpt-batch-bot Bot added the batch PR is queued in the batch-deploy rollup (batch-bot source of truth) label Jul 18, 2026
@autogpt-batch-bot

Copy link
Copy Markdown

🤖 Added #13603 to the batch. Current batch (8): #13604, #13599, #13574, #13541, #13540, #13532, #13530, #13603.

Deploying the combined preview (#13537); /batch-merge lands them together.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

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

Inline comments:
In
`@autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py`:
- Around line 77-85: Move the local imports from the _client method to the
module-level imports, adding get_request_context and org_router there. Keep
_client focused on creating the FastAPI app, including org_router, and
registering the dependency override without changing its behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ffbd938a-b471-4dbf-9a29-ce1666561732

📥 Commits

Reviewing files that changed from the base of the PR and between 88f82ce and fbf8541.

📒 Files selected for processing (1)
  • autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py
📜 Review details
⏰ Context from checks skipped due to timeout. (15)
  • GitHub Check: check API types
  • GitHub Check: Cursor Bugbot
  • GitHub Check: Check PR Status
  • GitHub Check: Analyze (python)
  • GitHub Check: Analyze (typescript)
  • GitHub Check: end-to-end tests
  • GitHub Check: types
  • GitHub Check: lint
  • GitHub Check: test (3.12)
  • GitHub Check: test (3.13)
  • GitHub Check: type-check (3.13)
  • GitHub Check: type-check (3.12)
  • GitHub Check: test (3.11)
  • GitHub Check: type-check (3.11)
  • GitHub Check: lint
🧰 Additional context used
📓 Path-based instructions (5)
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

autogpt_platform/backend/**/*.py: Use poetry run ... command for executing Python package dependencies
Use top-level imports only — avoid 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 are acceptable for sibling modules within the same package; avoid double-dot relative imports
Do not use duck typing — avoid hasattr/getattr/isinstance for type dispatch; use typed interfaces/unions/protocols instead
Use Pydantic models over dataclass/namedtuple/dict for structured data
Do not use linter suppressors — no # type: ignore, # noqa, # pyright: ignore; fix the type/code instead
Prefer list comprehensions over manual loop-and-append patterns
Use early return with guard clauses first to avoid deep nesting
Use %s for deferred interpolation in debug log statements for efficiency; use f-strings elsewhere for readability (e.g., logger.debug("Processing %s items", count) vs logger.info(f"Processing {count} items"))
Sanitize error paths by using os.path.basename() in error messages to avoid leaking directory structure
Be aware of TOCTOU (Time-Of-Check-Time-Of-Use) issues — avoid check-then-act patterns for file access and credit charging
Use transaction=True for Redis pipelines to ensure atomicity on multi-step 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 helpers, models, or a sub-module into a new file)
Keep functions under ~40 lines; extract named helpers when a function grows longer
...

Files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py
autogpt_platform/backend/backend/api/features/**/*.py

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

Update routes in '/backend/backend/api/features/' and add/update Pydantic models in the same directory for API development

Files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py
autogpt_platform/{backend,autogpt_libs}/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Format Python code with poetry run format

Files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py
autogpt_platform/backend/**/api/**/*.py

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

autogpt_platform/backend/**/api/**/*.py: Use Security() instead of Depends() for authentication dependencies to get proper OpenAPI security specification
Follow SSE (Server-Sent Events) protocol: use data: lines for frontend-parsed events (must match Zod schema) and : comment lines for heartbeats/status

Files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py
autogpt_platform/backend/**/*_test.py

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

autogpt_platform/backend/**/*_test.py: Use pytest with snapshot testing for API responses
Colocate test files with source files using *_test.py naming convention
Mock at boundaries — mock where the symbol is used, not where it's defined; after refactoring, update mock targets to match new module paths
Use AsyncMock from unittest.mock for async functions in tests
When writing tests, use Test-Driven Development (TDD): write failing tests marked with @pytest.mark.xfail before implementation, then remove the marker once the implementation is complete
When creating snapshots in tests, use poetry run pytest path/to/test.py --snapshot-update; always review snapshot changes with git diff before committing

Files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py
🧠 Learnings (11)
📚 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/api/features/orgs/invitation_resend_test.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/api/features/orgs/invitation_resend_test.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/api/features/orgs/invitation_resend_test.py
📚 Learning: 2026-03-31T15:37:38.626Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12623
File: autogpt_platform/backend/backend/copilot/tools/agent_generator/fixer.py:37-47
Timestamp: 2026-03-31T15:37:38.626Z
Learning: When validating/constructing Anthropic API model IDs in Significant-Gravitas/AutoGPT, allow the hyphen-separated Claude Opus 4.6 model ID `claude-opus-4-6` (it corresponds to `LlmModel.CLAUDE_4_6_OPUS` in `autogpt_platform/backend/backend/blocks/llm.py`). Do NOT require the dot-separated form in Anthropic contexts. Only OpenRouter routing variants should use the dot separator (e.g., `anthropic/claude-opus-4.6`); `claude-opus-4-6` should be treated as correct when passed to Anthropic, and flagged only if it’s used in the OpenRouter path where the dot form is expected.

Applied to files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py
📚 Learning: 2026-04-15T02:43:36.890Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 12780
File: autogpt_platform/backend/backend/copilot/tools/workspace_files.py:0-0
Timestamp: 2026-04-15T02:43:36.890Z
Learning: When reviewing Python exception handlers, do not flag `isinstance(e, X)` checks as dead/unreachable if the caught exception `X` is a subclass of the exception type being handled. For example, if `X` (e.g., `VirusScanError`) inherits from `ValueError` (directly or via an intermediate class) and it can be raised within an `except ValueError:` block, then `isinstance(e, X)` inside that handler is reachable and should not be treated as dead code.

Applied to files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py
📚 Learning: 2026-05-23T05:29:43.085Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 13200
File: autogpt_platform/backend/backend/executor/scheduler.py:590-593
Timestamp: 2026-05-23T05:29:43.085Z
Learning: When reviewing Python code that uses Pydantic discriminated/tagged unions (e.g., `Annotated[Union[...], Field(discriminator="kind")]`), recognize that using `isinstance(x, SomeVariantInfo)` to narrow the union is an intentional and correct runtime guard and should also enable static type narrowing in tools like Pyright. Do not recommend replacing such `isinstance`-based narrowing with `cast(...)` when the check already proves the variant at runtime.

Applied to files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py
📚 Learning: 2026-04-22T11:46:04.431Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12881
File: autogpt_platform/backend/backend/copilot/config.py:0-0
Timestamp: 2026-04-22T11:46:04.431Z
Learning: Do not flag the Claude Sonnet 4.6 model ID as incorrect when it uses the project’s established hyphenated convention: `anthropic/claude-sonnet-4-6`. This hyphen form is the intentional, production convention and should be treated as valid (including in files like llm.py, blocks tests, reasoning.py, `_is_anthropic_model` tests, and config defaults). Note that OpenRouter also accepts the dot variant `anthropic/claude-sonnet-4.6`, so either form may be tolerated, but `anthropic/claude-sonnet-4-6` should be considered the standard to match project usage.

Applied to files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py
📚 Learning: 2026-04-22T11:46:12.892Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12881
File: autogpt_platform/backend/backend/copilot/baseline/service.py:322-332
Timestamp: 2026-04-22T11:46:12.892Z
Learning: In this codebase (Significant-Gravitas/AutoGPT), OpenRouter-routed Anthropic model IDs should use the hyphen-separated convention (e.g., `anthropic/claude-sonnet-4-6`, `anthropic/claude-opus-4-6`). Although OpenRouter may accept both hyphen and dot variants, treat the hyphen-separated form as the intended, correct codebase-wide convention and do not flag it as an error. Only flag the dot-separated variant (e.g., `anthropic/claude-sonnet-4.6`) as incorrect when reviewing/validating model ID strings for OpenRouter-routed Anthropic models.

Applied to files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py
📚 Learning: 2026-05-07T18:48:14.242Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 13040
File: autogpt_platform/backend/backend/blocks/llm.py:0-0
Timestamp: 2026-05-07T18:48:14.242Z
Learning: In this repository, isort may split imports from the same module into separate blocks when some imports are aliased (e.g., `from module import X as Y`) and others are not. Preserve the two-block layout when it results from isort (such as keeping `from openai.types.chat import ChatCompletion as OpenAIChatCompletion` separate from non-aliased imports from `openai.types.chat`). Do not treat that split as a style issue during review; merging them into a single block can fail CI with `Imports are incorrectly sorted and/or formatted`.

Applied to files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py
📚 Learning: 2026-05-26T14:24:34.866Z
Learnt from: Abhi1992002
Repo: Significant-Gravitas/AutoGPT PR: 13217
File: autogpt_platform/backend/backend/api/features/search/service.py:137-137
Timestamp: 2026-05-26T14:24:34.866Z
Learning: In the Significant-Gravitas/AutoGPT backend, treat `user_id` (an opaque UUID used only for correlation/tracing) as non-PII. Do not flag direct logging of `user_id` in `logger.warning`/`logger.info` statements as a PII exposure issue, as the established convention is to log `user_id` for tracing while reserving PII for fields like email or display name.

Applied to files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py
📚 Learning: 2026-06-11T19:39:10.493Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 13337
File: autogpt_platform/backend/backend/copilot/graphiti/reranker.py:0-0
Timestamp: 2026-06-11T19:39:10.493Z
Learning: In the Significant-Gravitas/AutoGPT Python backend, when calling the OpenAI Python client `chat.completions.create`, construct the `messages` payload using the concrete typed-dict variants from `openai.types.chat` (e.g., `ChatCompletionSystemMessageParam`, `ChatCompletionUserMessageParam`, etc.) rather than trying to instantiate `ChatCompletionMessageParam` directly. `ChatCompletionMessageParam` is a `Union` alias and is not constructible, so `ChatCompletionMessageParam(role=..., content=...)` should fail type checking. Build each message element with the appropriate concrete typed dict and then annotate the resulting list as `list[ChatCompletionMessageParam]` (e.g., `messages: list[ChatCompletionMessageParam] = [ChatCompletionSystemMessageParam(...), ...]`).

Applied to files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.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: 1

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

Inline comments:
In
`@autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py`:
- Around line 159-166: Update the resend test around the
_client(_owner_ctx()).post call to normalize volatile timestamp fields in the
complete JSON response, then snapshot the normalized response using the
project’s pytest snapshot convention. Retain both existing token assertions
alongside the new full-response snapshot.
🪄 Autofix

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 Plus

Run ID: 9f08fe7e-141b-4125-b4e5-1c048d86ba27

📥 Commits

Reviewing files that changed from the base of the PR and between 25d880f and a9aca9e.

📒 Files selected for processing (2)
  • autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py
  • autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py
📜 Review details
⏰ Context from checks skipped due to timeout. (16)
  • GitHub Check: setup
  • GitHub Check: end-to-end tests
  • GitHub Check: type-check (3.13)
  • GitHub Check: test (3.11)
  • GitHub Check: test (3.12)
  • GitHub Check: lint
  • GitHub Check: test (3.13)
  • GitHub Check: type-check (3.12)
  • GitHub Check: type-check (3.11)
  • GitHub Check: setup
  • GitHub Check: Seer Code Review
  • GitHub Check: Check PR Status
  • GitHub Check: types
  • GitHub Check: lint
  • GitHub Check: Analyze (python)
  • GitHub Check: Analyze (typescript)
🧰 Additional context used
📓 Path-based instructions (5)
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

autogpt_platform/backend/**/*.py: Use poetry run ... command for executing Python package dependencies
Use top-level imports only — avoid 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 are acceptable for sibling modules within the same package; avoid double-dot relative imports
Do not use duck typing — avoid hasattr/getattr/isinstance for type dispatch; use typed interfaces/unions/protocols instead
Use Pydantic models over dataclass/namedtuple/dict for structured data
Do not use linter suppressors — no # type: ignore, # noqa, # pyright: ignore; fix the type/code instead
Prefer list comprehensions over manual loop-and-append patterns
Use early return with guard clauses first to avoid deep nesting
Use %s for deferred interpolation in debug log statements for efficiency; use f-strings elsewhere for readability (e.g., logger.debug("Processing %s items", count) vs logger.info(f"Processing {count} items"))
Sanitize error paths by using os.path.basename() in error messages to avoid leaking directory structure
Be aware of TOCTOU (Time-Of-Check-Time-Of-Use) issues — avoid check-then-act patterns for file access and credit charging
Use transaction=True for Redis pipelines to ensure atomicity on multi-step 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 helpers, models, or a sub-module into a new file)
Keep functions under ~40 lines; extract named helpers when a function grows longer
...

Files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py
  • autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py
autogpt_platform/backend/backend/api/features/**/*.py

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

Update routes in '/backend/backend/api/features/' and add/update Pydantic models in the same directory for API development

Files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py
  • autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py
autogpt_platform/{backend,autogpt_libs}/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Format Python code with poetry run format

Files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py
  • autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py
autogpt_platform/backend/**/api/**/*.py

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

autogpt_platform/backend/**/api/**/*.py: Use Security() instead of Depends() for authentication dependencies to get proper OpenAPI security specification
Follow SSE (Server-Sent Events) protocol: use data: lines for frontend-parsed events (must match Zod schema) and : comment lines for heartbeats/status

Files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py
  • autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py
autogpt_platform/backend/**/*_test.py

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

autogpt_platform/backend/**/*_test.py: Use pytest with snapshot testing for API responses
Colocate test files with source files using *_test.py naming convention
Mock at boundaries — mock where the symbol is used, not where it's defined; after refactoring, update mock targets to match new module paths
Use AsyncMock from unittest.mock for async functions in tests
When writing tests, use Test-Driven Development (TDD): write failing tests marked with @pytest.mark.xfail before implementation, then remove the marker once the implementation is complete
When creating snapshots in tests, use poetry run pytest path/to/test.py --snapshot-update; always review snapshot changes with git diff before committing

Files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py
🧠 Learnings (11)
📚 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/api/features/orgs/invitation_resend_test.py
  • autogpt_platform/backend/backend/api/features/orgs/invitation_routes.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/api/features/orgs/invitation_resend_test.py
  • autogpt_platform/backend/backend/api/features/orgs/invitation_routes.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/api/features/orgs/invitation_resend_test.py
  • autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py
📚 Learning: 2026-03-31T15:37:38.626Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12623
File: autogpt_platform/backend/backend/copilot/tools/agent_generator/fixer.py:37-47
Timestamp: 2026-03-31T15:37:38.626Z
Learning: When validating/constructing Anthropic API model IDs in Significant-Gravitas/AutoGPT, allow the hyphen-separated Claude Opus 4.6 model ID `claude-opus-4-6` (it corresponds to `LlmModel.CLAUDE_4_6_OPUS` in `autogpt_platform/backend/backend/blocks/llm.py`). Do NOT require the dot-separated form in Anthropic contexts. Only OpenRouter routing variants should use the dot separator (e.g., `anthropic/claude-opus-4.6`); `claude-opus-4-6` should be treated as correct when passed to Anthropic, and flagged only if it’s used in the OpenRouter path where the dot form is expected.

Applied to files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py
  • autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py
📚 Learning: 2026-04-15T02:43:36.890Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 12780
File: autogpt_platform/backend/backend/copilot/tools/workspace_files.py:0-0
Timestamp: 2026-04-15T02:43:36.890Z
Learning: When reviewing Python exception handlers, do not flag `isinstance(e, X)` checks as dead/unreachable if the caught exception `X` is a subclass of the exception type being handled. For example, if `X` (e.g., `VirusScanError`) inherits from `ValueError` (directly or via an intermediate class) and it can be raised within an `except ValueError:` block, then `isinstance(e, X)` inside that handler is reachable and should not be treated as dead code.

Applied to files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py
  • autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py
📚 Learning: 2026-05-23T05:29:43.085Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 13200
File: autogpt_platform/backend/backend/executor/scheduler.py:590-593
Timestamp: 2026-05-23T05:29:43.085Z
Learning: When reviewing Python code that uses Pydantic discriminated/tagged unions (e.g., `Annotated[Union[...], Field(discriminator="kind")]`), recognize that using `isinstance(x, SomeVariantInfo)` to narrow the union is an intentional and correct runtime guard and should also enable static type narrowing in tools like Pyright. Do not recommend replacing such `isinstance`-based narrowing with `cast(...)` when the check already proves the variant at runtime.

Applied to files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py
  • autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py
📚 Learning: 2026-04-22T11:46:04.431Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12881
File: autogpt_platform/backend/backend/copilot/config.py:0-0
Timestamp: 2026-04-22T11:46:04.431Z
Learning: Do not flag the Claude Sonnet 4.6 model ID as incorrect when it uses the project’s established hyphenated convention: `anthropic/claude-sonnet-4-6`. This hyphen form is the intentional, production convention and should be treated as valid (including in files like llm.py, blocks tests, reasoning.py, `_is_anthropic_model` tests, and config defaults). Note that OpenRouter also accepts the dot variant `anthropic/claude-sonnet-4.6`, so either form may be tolerated, but `anthropic/claude-sonnet-4-6` should be considered the standard to match project usage.

Applied to files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py
  • autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py
📚 Learning: 2026-04-22T11:46:12.892Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12881
File: autogpt_platform/backend/backend/copilot/baseline/service.py:322-332
Timestamp: 2026-04-22T11:46:12.892Z
Learning: In this codebase (Significant-Gravitas/AutoGPT), OpenRouter-routed Anthropic model IDs should use the hyphen-separated convention (e.g., `anthropic/claude-sonnet-4-6`, `anthropic/claude-opus-4-6`). Although OpenRouter may accept both hyphen and dot variants, treat the hyphen-separated form as the intended, correct codebase-wide convention and do not flag it as an error. Only flag the dot-separated variant (e.g., `anthropic/claude-sonnet-4.6`) as incorrect when reviewing/validating model ID strings for OpenRouter-routed Anthropic models.

Applied to files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py
  • autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py
📚 Learning: 2026-05-07T18:48:14.242Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 13040
File: autogpt_platform/backend/backend/blocks/llm.py:0-0
Timestamp: 2026-05-07T18:48:14.242Z
Learning: In this repository, isort may split imports from the same module into separate blocks when some imports are aliased (e.g., `from module import X as Y`) and others are not. Preserve the two-block layout when it results from isort (such as keeping `from openai.types.chat import ChatCompletion as OpenAIChatCompletion` separate from non-aliased imports from `openai.types.chat`). Do not treat that split as a style issue during review; merging them into a single block can fail CI with `Imports are incorrectly sorted and/or formatted`.

Applied to files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py
  • autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py
📚 Learning: 2026-05-26T14:24:34.866Z
Learnt from: Abhi1992002
Repo: Significant-Gravitas/AutoGPT PR: 13217
File: autogpt_platform/backend/backend/api/features/search/service.py:137-137
Timestamp: 2026-05-26T14:24:34.866Z
Learning: In the Significant-Gravitas/AutoGPT backend, treat `user_id` (an opaque UUID used only for correlation/tracing) as non-PII. Do not flag direct logging of `user_id` in `logger.warning`/`logger.info` statements as a PII exposure issue, as the established convention is to log `user_id` for tracing while reserving PII for fields like email or display name.

Applied to files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py
  • autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py
📚 Learning: 2026-06-11T19:39:10.493Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 13337
File: autogpt_platform/backend/backend/copilot/graphiti/reranker.py:0-0
Timestamp: 2026-06-11T19:39:10.493Z
Learning: In the Significant-Gravitas/AutoGPT Python backend, when calling the OpenAI Python client `chat.completions.create`, construct the `messages` payload using the concrete typed-dict variants from `openai.types.chat` (e.g., `ChatCompletionSystemMessageParam`, `ChatCompletionUserMessageParam`, etc.) rather than trying to instantiate `ChatCompletionMessageParam` directly. `ChatCompletionMessageParam` is a `Union` alias and is not constructible, so `ChatCompletionMessageParam(role=..., content=...)` should fail type checking. Build each message element with the appropriate concrete typed dict and then annotate the resulting list as `list[ChatCompletionMessageParam]` (e.g., `messages: list[ChatCompletionMessageParam] = [ChatCompletionSystemMessageParam(...), ...]`).

Applied to files:

  • autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py
  • autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py
🔇 Additional comments (2)
autogpt_platform/backend/backend/api/features/orgs/invitation_routes.py (1)

212-218: LGTM!

autogpt_platform/backend/backend/api/features/orgs/invitation_resend_test.py (1)

136-150: LGTM!

@github-actions github-actions Bot added cla: pending CLA not yet signed by all contributors and removed cla: signed CLA signed by all contributors labels Aug 6, 2026
@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

👋 Friendly reminder: This PR is waiting on a signed CLA.

All contributors need to sign our Contributor License Agreement before we can merge this PR.

➡️ Sign the CLA here

Why do we need a CLA?

The CLA protects both you and the project by clarifying the terms under which your contribution is made. It's a one-time process — once signed, it covers all your future contributions.

Common issues
  • Email mismatch: Make sure your Git commit email matches your GitHub account email
  • Stale branch: Sync your branch with the current dev branch and push the updated branch normally
  • Multiple authors: All commit authors need to sign, not just the PR author

If you have questions, just ask! 🙂

@github-actions github-actions Bot added cla: signed CLA signed by all contributors and removed cla: pending CLA not yet signed by all contributors labels Aug 6, 2026
@ntindle

ntindle commented Aug 6, 2026

Copy link
Copy Markdown
Member Author

/review

@autogpt-pr-reviewer

Copy link
Copy Markdown

Queued a review for PR #13603 at 77c7827.

+ timedelta(days=INVITATION_TTL_DAYS),
},
)
if updated_count == 0:

This comment was marked as outdated.

@autogpt-pr-reviewer autogpt-pr-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

INCONCLUSIVE

You've hit your session limit · resets 9am (UTC)

Risk level: medium | Human review: recommended | Duration: 932s | Reviewed: 25d880f4

Specialist Reports

Specialist Status Summary
security ⚠️ WARN You've hit your session limit · resets 9am (UTC)
architect ⚠️ WARN You've hit your session limit · resets 9am (UTC)
performance ⚠️ WARN You've hit your session limit · resets 9am (UTC)
testing ⚠️ WARN You've hit your session limit · resets 9am (UTC)
quality ⚠️ WARN You've hit your session limit · resets 9am (UTC)
product ⚠️ WARN You've hit your session limit · resets 9am (UTC)
discussion ⚠️ WARN You've hit your session limit · resets 9am (UTC)
ui-reviewer (local) ⚠️ WARN You've hit your session limit · resets 9am (UTC)
ui-reviewer (hosted) ✅ PASS Resend endpoint verified live end-to-end: token rotation, TTL extension, expired-invite recovery via include_expired, and full 400/401/403/404 authz matrix all pass with no server errors.

Findings: 🔴 0 critical | 🟠 0 high | 🟡 0 medium | 🟢 1 low

Should Fix

  • 🟢 autogpt_platform/frontend/src/app/api/openapi.json:9721 operationId 'postV2Resend invitation' contains a space and the tags array is duplicated (['v2','orgs','invitations','orgs','invitations']), which can produce awkward generated Orval hook names for this route.
    Suggestion: Give the route an explicit clean operation_id (e.g. resend_invitation) so the generated hook name is well-formed; dedupe the tags list.

Quality Checks

  • lint: cd autogpt_platform/frontend && pnpm lint: cd autogpt_platform/frontend && pnpm lint (80s)
  • lint: cd autogpt_platform/backend && poetry run lint: cd autogpt_platform/backend && poetry run lint (103s)
  • typecheck: cd autogpt_platform/frontend && pnpm types: cd autogpt_platform/frontend && pnpm types (51s)
  • test: cd autogpt_platform/frontend && mv .env /tmp/qa-env-stash 2>/dev/null; pnpm test:unit; rc=$?; [ -f /tmp/qa-env-stash ] && mv /tmp/qa-env-stash .env; exit $rc: cd autogpt_platform/frontend && mv .env /tmp/qa-env-stash 2>/dev/null; pnpm test:unit; rc=$?; [ -f /tmp/qa-env-stash ] && mv /tmp/qa-env-stash .env; exit $rc (393s)
  • build: cd autogpt_platform/frontend && pnpm build: cd autogpt_platform/frontend && pnpm build (294s)

"/api/orgs/{org_id}/invitations/{invitation_id}/resend": {
"post": {
"tags": ["v2", "orgs", "invitations", "orgs", "invitations"],
"summary": "Resend invitation",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 🟢 low (ui-reviewer/openapi-codegen)

operationId 'postV2Resend invitation' contains a space and the tags array is duplicated (['v2','orgs','invitations','orgs','invitations']), which can produce awkward generated Orval hook names for this route.

Suggestion: Give the route an explicit clean operation_id (e.g. resend_invitation) so the generated hook name is well-formed; dedupe the tags list.

@autogpt-pr-reviewer
autogpt-pr-reviewer Bot dismissed their stale review August 6, 2026 07:03

Superseded by a newer automated review.

@autogpt-pr-reviewer autogpt-pr-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

INCONCLUSIVE

You've hit your session limit · resets 9am (UTC)

Risk level: medium | Human review: recommended | Duration: 857s | Reviewed: a9aca9e9

Specialist Reports

Specialist Status Summary
security ⚠️ WARN You've hit your session limit · resets 9am (UTC)
architect ⚠️ WARN You've hit your session limit · resets 9am (UTC)
performance ⚠️ WARN You've hit your session limit · resets 9am (UTC)
testing ⚠️ WARN You've hit your session limit · resets 9am (UTC)
quality ⚠️ WARN You've hit your session limit · resets 9am (UTC)
product ⚠️ WARN You've hit your session limit · resets 9am (UTC)
discussion ⚠️ WARN You've hit your session limit · resets 9am (UTC)
ui-reviewer (local) ⚠️ WARN You've hit your session limit · resets 9am (UTC)
ui-reviewer (hosted) ❌ FAIL I'll start with the mandatory environment setup and auth. Token is empty. Let me try sign-up fallback and re-auth. No users exist — DB is fresh. Let me sign up a user with a valid password.

Quality Checks

  • lint: cd autogpt_platform/frontend && pnpm lint: cd autogpt_platform/frontend && pnpm lint (75s)
  • lint: cd autogpt_platform/backend && poetry run lint: cd autogpt_platform/backend && poetry run lint (96s)
  • typecheck: cd autogpt_platform/frontend && pnpm types: cd autogpt_platform/frontend && pnpm types (44s)
  • test: cd autogpt_platform/frontend && mv .env /tmp/qa-env-stash 2>/dev/null; pnpm test:unit; rc=$?; [ -f /tmp/qa-env-stash ] && mv /tmp/qa-env-stash .env; exit $rc: cd autogpt_platform/frontend && mv .env /tmp/qa-env-stash 2>/dev/null; pnpm test:unit; rc=$?; [ -f /tmp/qa-env-stash ] && mv /tmp/qa-env-stash .env; exit $rc (368s)
  • build: cd autogpt_platform/frontend && pnpm build: cd autogpt_platform/frontend && pnpm build (263s)

@autogpt-pr-reviewer autogpt-pr-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

INCONCLUSIVE

You've hit your session limit · resets 9am (UTC)

Risk level: medium | Human review: recommended | Duration: 829s | Reviewed: 77c7827a

Specialist Reports

Specialist Status Summary
security ⚠️ WARN You've hit your session limit · resets 9am (UTC)
architect ⚠️ WARN You've hit your session limit · resets 9am (UTC)
performance ⚠️ WARN You've hit your session limit · resets 9am (UTC)
testing ⚠️ WARN You've hit your session limit · resets 9am (UTC)
quality ⚠️ WARN You've hit your session limit · resets 9am (UTC)
product ⚠️ WARN You've hit your session limit · resets 9am (UTC)
discussion ⚠️ WARN You've hit your session limit · resets 9am (UTC)
ui-reviewer (local) ⚠️ WARN You've hit your session limit · resets 9am (UTC)
ui-reviewer (hosted) ❌ FAIL Variant 'hosted' failed: gh auth login failed: error validating token: Get "https://api.github.com/": net/http: TLS handshake timeout

|

Quality Checks

  • lint: cd autogpt_platform/frontend && pnpm lint: cd autogpt_platform/frontend && pnpm lint (72s)
  • lint: cd autogpt_platform/backend && poetry run lint: cd autogpt_platform/backend && poetry run lint (90s)
  • typecheck: cd autogpt_platform/frontend && pnpm types: cd autogpt_platform/frontend && pnpm types (42s)
  • test: cd autogpt_platform/frontend && mv .env /tmp/qa-env-stash 2>/dev/null; pnpm test:unit; rc=$?; [ -f /tmp/qa-env-stash ] && mv /tmp/qa-env-stash .env; exit $rc: cd autogpt_platform/frontend && mv .env /tmp/qa-env-stash 2>/dev/null; pnpm test:unit; rc=$?; [ -f /tmp/qa-env-stash ] && mv /tmp/qa-env-stash .env; exit $rc (355s)
  • build: cd autogpt_platform/frontend && pnpm build: cd autogpt_platform/frontend && pnpm build (259s)

@ntindle

ntindle commented Aug 6, 2026

Copy link
Copy Markdown
Member Author

/review

@autogpt-pr-reviewer

Copy link
Copy Markdown

Queued a review for PR #13603 at 77c7827.

@autogpt-pr-reviewer autogpt-pr-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📋 Automated Review — PR #13603

PR #13603 — feat(backend): resend org invitation — fresh token + extended TTL
Author: ntindle | Files: 4

🎯 Verdict: APPROVE

PR Description Quality

✅ Has Why + What + How — the ticket (SECRT-2475), the dead-end being fixed (revoke-and-retype), the token-rotation + TTL mechanics, and the include_expired list flag are all documented. The email-delivery and rate-limit gaps are called out as explicit TODOs.

What This PR Does

Previously, once an org invitation expired or the emailed link went stale, an admin had no recovery path except revoking it and re-typing the invitee's address. This PR adds an admin-gated POST /api/orgs/{org_id}/invitations/{invitation_id}/resend that rotates the invite token, clears tokenHash, re-bases the expiry to now+7 days, and prunes any teams deleted since the original invite. It also adds include_expired=true to the list endpoint so lapsed invitations become visible and recoverable. Backend-only; the fourth file is a regenerated openapi.json.

Specialist Findings

🛡️ Security ✅ — Auth gating (MANAGE_MEMBERS + _verify_org_path), no org enumeration (uniform 404), TOCTOU closed via compare-and-swap update_many re-asserting acceptedAt/revokedAt IS NULL, and cross-org team leak prevented by re-filtering on orgId. No secret leakage in logs. All findings are informational.
🔵 Token minted with uuid4() rather than secrets.token_urlsafe(32) (invitation_routes.py:195) — CSPRNG-backed in CPython, not exploitable, matches schema default.
🟡 No rate limiting on resend (invitation_routes.py:228) — acknowledged TODO; only a live vector once email delivery ships.

🏗️ Architecture ✅ — resend_invitation mirrors create/revoke exactly; _get_org_invitation/_reject_if_not_pending extraction removes prior copy-paste in revoke_invitation. CAS concurrency model and additive include_expired (backward-compatible) are sound.
🟠 Broken test cross-reference: comment at invitation_resend_test.py:127 cites test_resend_reads_back_the_row_it_wrote, which does not exist (real test is test_resend_reads_the_row_back_by_id at :142).

Performance ✅ — Admin-gated, low-frequency; no N+1 (_surviving_team_ids is one indexed IN query), CAS is a single indexed update. Resend does 4 sequential round trips — acceptable for a rare admin action.
🟡 include_expired=true drops the expiresAt filter and returns every unaccepted/unrevoked invite with no take/pagination (invitation_routes.py:138); expired rows are never GC'd, so the set grows unbounded per org.

🧪 Testing ✅/⚠️ — Genuinely strong suite: asserts the actual update_many payload/where-clause, token rotation (!= "tok-old"), tokenHash is None, TTL boundary, CAS shape, and the full 403/404 matrix. Two reachable branches in the concurrency-critical path are uncovered (see Should Fix).
🟠 "changed concurrently; retry" 400 branch (invitation_routes.py:213) and post-update refreshed is None 404 branch (invitation_routes.py:221) have no coverage.

📖 Quality ✅ — Readability grade A: precise naming (_surviving_team_ids, updated_count), justified concurrency comments placed exactly where needed, self-documenting tests.
🔵 _surviving_team_ids is a forward reference defined after its only caller (invitation_routes.py:236); re-read at :226 duplicates _get_org_invitation logic.

📦 Product ✅/⚠️ — API contract correctly closes the SECRT-2475 dead-end and QA confirmed the observable behavior. The end-to-end user outcome is not yet complete: nothing is delivered to the invitee (email is a TODO) and there's no frontend affordance — acceptable for a feat(backend)-scoped PR, consistent with the existing create path.
🔵 "Invitation was revoked" 400 (invitation_routes.py:52) gives the admin no next step.

📬 Discussion ✅ — 46/46 CI checks green, patch coverage 97.74%, MERGEABLE, no live conflicts. 9/11 review threads resolved; author diligently addressed the CAS race and openapi-regeneration feedback. Two open threads: a confirmed false-positive Sentry HIGH (claims update_many returns BatchPayload — it returns int in prisma-client-py, same pattern as library/db.py:963), and a real minor openapi operationId naming issue. No human approval on record yet.
🟠 openapi operationId "postV2Resend invitation" contains a space + duplicated tags (openapi.json ~:9721) → awkward generated Orval hook name.

🔎 QA ✅ — Verified end-to-end over HTTP against a live DB: all 12 scenarios passed (token rotation, expired-invite recovery, include_expired toggle, team pruning, and the full 400/401/403/404 matrix). Rejected states (accepted/revoked/cross-org) performed no write. No exceptions in server logs from the endpoints.

🟠 Should Fix

  1. Untested "changed concurrently; retry" 400 branch (invitation_routes.py:213) — fires when update_many returns 0 but the re-read is still pending; the existing race test only covers the concurrent-accept path. Add: update returns 0, re-read still pending → assert 400 with "concurrently". (Flagged by: testing)
  2. Untested post-update refreshed is None 404 branch (invitation_routes.py:221) — row deleted between update and read-back; distinct from the first-read missing case. Add: update returns 1, re-read returns None → assert 404. (Flagged by: testing)
  3. Broken test cross-reference comment (invitation_resend_test.py:127) — cites a nonexistent test name; repoint to test_resend_reads_the_row_back_by_id. (Flagged by: architect)
  4. openapi operationId has a space + duplicated tags (openapi.json ~:9721) — add an explicit operation_id to the route decorator and dedupe tags, then regenerate. Affects frontend Orval hook naming. (Flagged by: discussion, quality — 2 specialists)

🟡 Nice to Have

  1. Bound the include_expired list (invitation_routes.py:138) — add take=100 or cursor pagination; expired invites are never garbage-collected. (performance)
  2. Weak list assertion (invitation_resend_test.py:328) — assert "gt" in where["expiresAt"], not just key presence. (testing)
  3. Actionable revoked-error copy (invitation_routes.py:52) — e.g. "Invitation was revoked; create a new invitation instead." (product)

🔵 Nits

  1. Token generation (invitation_routes.py:195) — secrets.token_urlsafe(32) over uuid4() to signal credential intent. (security)
  2. Helper ordering (invitation_routes.py:236) — move _surviving_team_ids above its caller. (quality)
  3. Re-read duplication (invitation_routes.py:226) — reuse _get_org_invitation for the final load. (quality)

Note on the open Sentry thread

The Sentry HIGH flagging updated_count == 0 as always-False (because update_many supposedly returns BatchPayload) is a verified false positive — prisma-client-py's update_many returns int, and existing repo code (library/db.py:963,1006) uses the identical comparison. No code change needed; the thread should be resolved/dismissed to avoid misleading future readers.

Human Review Needed

YES — this change handles bearer-credential rotation and sits on the org permission/trust boundary (MANAGE_MEMBERS-gated token minting). Per policy, changes to how invitation credentials are generated and to authorization gating warrant a human sign-off; note that no human approval exists on the PR yet and the last automated pass was inconclusive.

Risk Assessment

Merge risk: LOW | Rollback: EASY (additive endpoint + backward-compatible list flag; no schema migration, revertable in one commit)

CI Status

GitHub CI (per PR discussion): ✅ 46/46 checks pass, patch coverage 97.74%, MERGEABLE.
Local harness: lint (frontend + backend), typecheck, and build all passed. The pnpm test:unit (frontend Vitest) run failed locally — the only frontend change in this PR is the regenerated openapi.json, and GitHub CI ran the same suite green on this head SHA, so this is environment skew in the review sandbox, not a real regression.


UI Testing — Variant Results

✅ local: Resend endpoint verified end-to-end over HTTP — token rotation, expired-invite recovery, list include_expired toggle, team pruning, and the full 400/401/403/404 matrix all behave exactly as specified with no writes on rejected states.

✅ hosted: Resend endpoint works end-to-end: token rotation, TTL extension, expired-invite recovery, include_expired listing, team pruning, and all error paths (401/404/400/cross-org 404) verified live with matching DB state.

  • low: Resend has no rate limit or minimum-interval per invite; each call rotates the token and (once email is wired) would send a fresh link, enabling email-bombing of the invitee.

invitation = await _get_org_invitation(org_id, invitation_id)
_reject_if_not_pending(invitation)

new_token = str(uuid4())

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 🟢 low (security/token-entropy)

Invitation bearer token is minted with str(uuid4()). While uuid4 is CSPRNG-backed in CPython and matches the schema default, a UUID is an identifier type being used as a security credential.

Suggestion: Use secrets.token_urlsafe(32) for the rotated token to signal intent and increase entropy; consider aligning the schema default too.

raise NotFoundError(f"Invitation {invitation_id} not found")

# TODO: Send email via Postmark with invitation link (same gap as create).
# Rate-limit resends (min-interval / per-invite cap) as part of that work —

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 🟢 low (security/rate-limiting)

The resend endpoint has no rate limiting. Currently low risk (admin-gated, email delivery not yet wired), but becomes an email-bombing vector once Postmark delivery ships.

Suggestion: Ship a per-invite min-interval and/or per-invite resend cap in the same change that wires up email delivery, as the TODO notes.

where={"id": invitation_id, "acceptedAt": None, "revokedAt": None},
data={
"token": new_token,
"tokenHash": None,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 🟢 low (security/secret-storage)

Resend persists the token in plaintext and nulls the unused tokenHash column. This mirrors pre-existing create/accept behavior, but a plaintext invite token is directly usable if the DB is compromised, and this line would silently clear any future hash-based verification.

Suggestion: Longer term, store only a hash of the invitation token (verify hash on accept) rather than the plaintext value; at minimum document why tokenHash is retained but unused.

# The response body is the whole point of the endpoint: it must carry
# the rotated token, not the stale pre-update one. (That the token
# returned is the one this request minted is covered by
# test_resend_reads_back_the_row_it_wrote.)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 🟡 medium (architect/comment-durability)

Comment references test 'test_resend_reads_back_the_row_it_wrote', which does not exist in the file; nearest real tests are test_resend_reads_the_row_back_by_id (:142) and test_resend_superseded_by_concurrent_resend_still_succeeds (:158). A future reader searching for the cited coverage will find nothing.

Suggestion: Point the parenthetical at an existing test, e.g. 'covered by test_resend_reads_the_row_back_by_id.'

}
if not include_expired:
where["expiresAt"] = {"gt": datetime.now(timezone.utc)}
invitations = await prisma.orginvitation.find_many(

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 🟢 low (performance/unbounded-query)

With include_expired=true the expiresAt filter is dropped, so list_invitations returns every unaccepted/unrevoked invitation for the org with no take/pagination. Expired invitations are never cleaned up, so this set grows without bound for orgs that repeatedly let invites lapse, inflating query time, memory, and response-mapping cost.

Suggestion: Add a take limit (e.g. take=100) or cursor pagination to the find_many query so worst-case result size is bounded, especially on the include_expired path.

if refreshed is None:
raise NotFoundError(f"Invitation {invitation_id} not found")

# TODO: Send email via Postmark with invitation link (same gap as create).

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 🟡 medium (product/feature-completeness)

The user-facing purpose of 'resend' is that the invitee receives the invitation email again, but email delivery is still a TODO. The endpoint only rotates the token and returns it in the API response, with no mechanism to actually deliver the new link to the invitee. Until Postmark is wired, an admin cannot complete the recovery flow this endpoint is meant to enable.

Suggestion: Track that SECRT-2475 remains open until email delivery + frontend wiring land; consider gating the endpoint behind the delivery work, or clearly document that the returned token must be surfaced to the admin in the UI as an interim delivery path.

if invitation.acceptedAt is not None:
raise HTTPException(400, detail="Invitation already accepted")
if invitation.revokedAt is not None:
raise HTTPException(400, detail="Invitation was revoked")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 🟢 low (product/error-copy)

The 'Invitation was revoked' 400 message gives the admin no next step, even though the intended recovery path (create a new invitation) is known. This risks reproducing the same dead-end confusion the ticket aims to remove.

Suggestion: Make the message actionable, e.g. 'Invitation was revoked; create a new invitation instead.'

"/api/orgs/{org_id}/invitations/{invitation_id}/resend": {
"post": {
"tags": ["v2", "orgs", "invitations", "orgs", "invitations"],
"summary": "Resend invitation",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 🟢 low (discussion/openapi-codegen)

Unresolved review thread (autogpt-pr-reviewer): the resend route's operationId is 'postV2Resend invitation' (contains a space) and the tags array is duplicated (['v2','orgs','invitations','orgs','invitations']), which yields an awkward generated Orval hook name.

Suggestion: Add an explicit operation_id (e.g. resend_invitation) to the @org_router.post decorator in invitation_routes.py and dedupe the tags list, then regenerate openapi.json.

+ timedelta(days=INVITATION_TTL_DAYS),
},
)
if updated_count == 0:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 🟢 low (discussion/unresolved-false-positive)

Unresolved Sentry thread claims 'updated_count == 0' is broken because update_many returns a BatchPayload. This is a false positive: prisma-client-py update_many returns int (root_selection=['count']), and existing code (library/db.py:963,1006) uses the same integer comparison. The code is correct but the open thread is misleading.

Suggestion: Reply to and resolve/dismiss the Sentry thread noting update_many returns an int in prisma-client-py; no code change required.

surviving = [tid for tid in invitation.teamIds if tid in valid_ids]
dropped = [tid for tid in invitation.teamIds if tid not in valid_ids]
if dropped:
logger.warning(

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 🟢 low (ui-reviewer/abuse-hardening)

Resend has no rate limit or minimum-interval per invite; each call rotates the token and (once email is wired) would send a fresh link, enabling email-bombing of the invitee.

Suggestion: Add a per-invitation min-interval / resend cap alongside the Postmark email wiring noted in the existing TODO.

assert "revoked" in resp.json()["detail"].lower()
self.prisma.orginvitation.update_many.assert_not_called()

def test_resend_invitation_from_other_org_not_found(self):

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.

🤖 🟡 Nice to Have: No test covers _verify_org_path on resend — i.e. path org_id differing from ctx.org_id. create_invitation and revoke_invitation each have exactly that regression test (routes_test.py:2554, :2569, added under the Bug: invitation routes missing _verify_org_path header), so the coverage is asymmetric for the one new route that needs it.

If the _verify_org_path(ctx, org_id) call at invitation_routes.py:191 is dropped in a refactor, this suite stays green while an admin of org A can POST /api/orgs/B/invitations/{id}/resend and mint a live token for org B's invitation — the invitation lookup is scoped by the path org id while the permission check reads ctx. This test varies the invitation's org, not the path's, so it doesn't cover that. (flagged by: Claude)

"""
_verify_org_path(ctx, org_id)
invitation = await _get_org_invitation(org_id, invitation_id)
_reject_if_not_pending(invitation)

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.

🤖 🟡 Nice to Have: Resend revives a pending invitation of any age with its original privilege flags, and takes no request body — so the admin clicking Resend never restates isAdmin / isBillingManager / teamIds. Combined with the new include_expired flag, which exists precisely to surface long-dead rows, an 18-month-old unaccepted invite carrying isAdmin=True (from a previous admin regime) can be resurrected with 7 fresh days. The only redemption gate is the email match, so whoever controls that mailbox today gets org admin.

Consider refusing resend when createdAt is older than some multiple of INVITATION_TTL_DAYS, forcing a deliberate re-create where the privileges are restated. (flagged by: Claude)

updated_count = await prisma.orginvitation.update_many(
where={"id": invitation_id, "acceptedAt": None, "revokedAt": None},
data={
"token": new_token,

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.

🤖 🟡 Nice to Have: A resend leaves no audit trail. invitedByUserId is untouched, so after a resend the invitation still names the original inviter, and OrgInvitation has no lastSentAt / resendCount column — nothing records who re-issued the credential or when.

Those same missing fields are what the rate-limit TODO below would need, so honoring it will require a schema migration rather than just handler logic. Worth capturing now while the model is being touched. (flagged by: Claude)

return []

teams = await prisma.team.find_many(where={"id": {"in": invitation.teamIds}})
valid_ids = {t.id for t in teams if t.orgId == invitation.orgId}

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.

🤖 🟡 Nice to Have: _surviving_team_ids filters on existence and orgId but not on Team.archivedAt, so an archived team survives the prune — despite the docstring's claim that pruning "keeps the stored invitation honest about what it confers."

list_teams filters archivedAt: None (team_db.py:49) and add_team_member doesn't check it either, so accepting a resent invite creates a TeamMember row in a team the user can never see. create_invitation has the same gap, so the fix probably belongs in both places. (flagged by: Claude)

@ntindle
ntindle force-pushed the feat/invitation-resend branch from 77c7827 to 39d74ec Compare August 26, 2026 00:31
@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Aug 26, 2026
@ntindle
ntindle changed the base branch from dev to feat/grant-credential-modes August 26, 2026 00:32
ntindle and others added 7 commits August 26, 2026 21:45
…CRT-2475)

Pending (including expired) invitations get a rotated token and a new
7-day expiry; the previously emailed link stops working on resend.
Accepted or revoked invitations are rejected with 400.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm3mCG9okfdGtAXtFaDF9A
…th org-UI stack

routes_test.py is heavily modified by the in-flight org-UI stack; appending
there made the rollup eject this PR on a test-file conflict.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Move get_request_context and org_router from the local _client import to
top-level imports, per the backend top-level-imports guideline.

Co-Authored-By: Claude Opus <noreply@anthropic.com>
…urate

Addresses review feedback on the resend endpoint:

- Regenerate openapi.json for the new /resend route (fixes red `check API
  types` CI) plus the new list query param.
- Add `include_expired` to `list_invitations`. The endpoint filtered
  `expiresAt > now`, so an admin could never obtain the invitation_id of an
  expired invite -- the resend feature's primary use case was unreachable
  end-to-end. Defaults to false, so existing clients are unchanged.
- Close the TOCTOU window between the state read and the write. `update()`
  only accepts a unique WHERE in prisma-client-python, so the rotation now
  goes through `update_many()` with `acceptedAt`/`revokedAt` re-asserted in
  the WHERE clause, and reads the row back by the freshly minted token. A
  concurrent accept/revoke now yields 400 instead of a 200 with a live token.
- Re-validate teamIds on resend: teams deleted since the invite was created
  are pruned (and logged) instead of silently promising access that accept
  can no longer grant.
- Extract the shared lookup+org-match guard into `_get_org_invitation`,
  reused by `revoke_invitation`.
- Tests: assert the response body carries the rotated token (was never
  checked), cover `find_unique -> None`, the CAS where-clause, the lost-race
  path, team pruning, and both `include_expired` modes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A second concurrent resend can rotate the token again between our
update_many and the read-back. Looking up the token this request minted
would then find nothing and raise NotFoundError -> 404, even though the
invitation exists and was just rotated.

Reading by id returns the committed state at or after our own write, so
the returned token is never the stale pre-update one, and a double
resend hands back a live token instead of a spurious 404.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…sponses

- Register the production NotFoundError -> 404 mapping on the test app so
  the cross-org and missing-invitation cases assert the status callers
  actually receive, instead of an opaque 500 from an unhandled exception.
  Removes the raise_server_exceptions bypass.
- Declare 400/403/404 in the resend route's OpenAPI responses so the
  generated client knows about the documented failure modes; regenerate
  openapi.json.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… docstring

- Add a pytest-snapshot assertion over the InvitationCreateResponse body so
  drift in any field beyond the token is caught. The token (a bearer
  credential) and the two timestamps are excluded from the snapshot per
  TESTING.md's guidance on sensitive and volatile data, and are asserted
  explicitly instead.
- Correct _expect_successful_resend's docstring, which still described the
  read-back as keying on the minted token.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@ntindle
ntindle force-pushed the feat/invitation-resend branch from 39d74ec to 4f851e1 Compare August 27, 2026 04:38
@github-actions github-actions Bot removed the documentation Improvements or additions to documentation label Aug 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

batch:orgs batch-bot batch membership batch PR is queued in the batch-deploy rollup (batch-bot source of truth) cla: signed CLA signed by all contributors platform/backend AutoGPT Platform - Back end platform/frontend AutoGPT Platform - Front end size/xl

Projects

Status: 🚧 Needs work
Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants