Skip to content

feat(frontend): prompt top-up when out of automation credits - #13208

Merged
0ubbe merged 24 commits into
devfrom
feature/top-up-automation
May 28, 2026
Merged

feat(frontend): prompt top-up when out of automation credits#13208
0ubbe merged 24 commits into
devfrom
feature/top-up-automation

Conversation

@0ubbe

@0ubbe 0ubbe commented May 25, 2026

Copy link
Copy Markdown
Contributor

Why / What / How

Screenshot 2026-05-28 at 16 50 09 Screenshot 2026-05-28 at 16 53 29 Screenshot 2026-05-28 at 16 50 14

Why: When a user runs out of automation credits in prod, there's no call-to-action anywhere in the app to top up. Agents started manually or via Autopilot still launch and then fail, and the failure messaging doesn't make the cause clear. This adds the missing top-up prompts so users can recover in-place. (Origin: eng-general discussion.)

What: Three coordinated, payment-flag-gated surfaces that appear only when the automation-credit balance is at $0 and auto-refill is not enabled:

  • A once-per-day modal that auto-opens on first app load of the day.
  • A dismissable banner + CTA on the Library page.
  • A dismissable banner + CTA on the Autopilot (Copilot) page.

All three open the same inline top-up dialog, which reuses the existing requestTopUp → Stripe checkout flow (no new payment paths).

How: A single TopUpPromptProvider is mounted in (platform)/layout.tsx. It reads the balance + auto-refill config via the existing useCredits hook and derives one source of truth, isOutOfCredits (ENABLE_PLATFORM_PAYMENT on, credits <= 0, auto-refill config loaded, and auto-refill not active). It owns the shared TopUpDialog and exposes { isOutOfCredits, openTopUp } via context. A DailyTopUpAutoOpener — mounted only when out of credits — opens the dialog once per day (guarded by a localStorage date stamp, via the shared useMountEffect; no raw useEffect). The two banners are thin context consumers that dismiss-for-the-day. The inline amount form was extracted from WalletRefill's one-time top-up tab into a shared TopUpForm so both reuse identical Stripe logic.

Out of scope (intentionally separate): clarifying the run/task failure message for insufficient credits — that needs a new backend error code and is better as its own PR.

Changes 🏗️

  • New src/components/layout/TopUpPrompt/:
    • TopUpPromptProvider.tsx + useTopUpPrompt.ts — context, isOutOfCredits derivation, shared dialog state.
    • DailyTopUpAutoOpener.tsx — once-per-day modal auto-open (conditional-mount + useMountEffect).
    • TopUpDialog/TopUpDialog.tsx — controlled, responsive dialog (drawer on mobile).
    • TopUpForm/ (TopUpForm.tsx + useTopUpForm.ts) — inline amount entry, extracted from WalletRefill.
    • LowCreditBanner/ (LowCreditBanner.tsx + useLowCreditBanner.ts) — dismissable warning banner.
    • helpers.tswasShownToday / markShownToday date helpers.
  • Modified src/app/(platform)/layout.tsx — mount the provider around page content.
  • Modified src/app/(platform)/library/page.tsx and copilot/CopilotPage.tsx — render the banner.
  • Modified WalletRefill.tsx — consume the shared TopUpForm (behavior-preserving).
  • Modified src/services/storage/local-storage.ts — two new keys (modal-shown / banner-dismissed).
  • Tests — integration tests for the Library banner, Autopilot banner, and provider (daily modal + auto-refill/flag suppression), plus a unit test for the date helpers.

Known follow-ups (non-blocking):

  • If GET /credits/auto-top-up errors, the prompt fails closed (no nudge); intentional, worth a documenting comment later.
  • TopUpForm inherited a __legacy__ Form/FormField import from WalletRefill (pre-existing); migrate both off legacy form primitives in a dedicated cleanup.

Checklist 📋

For code changes:

  • I have clearly listed my changes in the PR description
  • I have made a test plan
  • I have tested my changes according to the test plan:
    • Automated (added in this PR): Library banner shows at credits=0, CTA opens the dialog, hidden when credits remain; Autopilot banner shows at credits=0, hidden otherwise; provider auto-opens the modal once/day, stays closed when already shown today, and suppresses everything when auto-refill is enabled or the payment flag is off; date helpers.
    • Manual — out of credits: with ENABLE_PLATFORM_PAYMENT on and a $0 account (no auto-refill), load the app → daily modal appears once; reload same day → no modal; visit Library and Autopilot → banner + "Top up" CTA; click → dialog → enter amount → redirected to Stripe checkout.
    • Manual — suppression: enable auto-refill → no modal/banner at $0; with a positive balance → nothing shows.
    • Manual — dismissal: dismiss the banner → stays hidden for the rest of the day; modal does not reappear same day.
    • Manual — mobile: dialog renders as a bottom drawer.

For configuration changes:

  • .env.default is updated or already compatible with my changes
  • docker-compose.yml is updated or already compatible with my changes
  • I have included a list of my configuration changes in the PR description (under Changes)

No configuration changes.

0ubbe and others added 10 commits May 25, 2026 15:16
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…dits

useCredits fetches the balance and the auto-top-up config independently.
If credits (=0) resolved before the config loaded, isOutOfCredits briefly
flipped true, mounting DailyTopUpAutoOpener and firing the daily modal
(and stamping localStorage) for users who actually have auto-refill on.
Require autoTopUpConfig to be loaded before treating the user as out.

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

coderabbitai Bot commented May 25, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

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 a low-credit top-up system: local-storage date helpers, TopUpPrompt context/provider, TopUpForm and hook, LowCreditBanner and TopUpDialog UI, daily auto-opener, layout/page wiring (Copilot, Library), Wallet one-time top-up refactor, comprehensive Vitest tests using MSW and localStorage isolation, and a backend change removing null-credential normalization.

Changes

Top-Up Prompt Infrastructure and Integration

Layer / File(s) Summary
Storage Keys and Date Helpers
autogpt_platform/frontend/src/services/storage/local-storage.ts, autogpt_platform/frontend/src/components/layout/TopUpPrompt/helpers.ts, autogpt_platform/frontend/src/components/layout/TopUpPrompt/__tests__/helpers.test.ts
Add TOP_UP_MODAL_LAST_SHOWN and LOW_CREDIT_BANNER_DISMISSED keys and implement wasShownToday/markShownToday helpers and tests.
Context and Consumer Hook
autogpt_platform/frontend/src/components/layout/TopUpPrompt/useTopUpPrompt.ts
Introduce TopUpPromptContext and useTopUpPrompt() with an inert fallback when no provider is present.
Top-Up Form & Hook + Tests
autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/useTopUpForm.ts, autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/TopUpForm.tsx, autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/__tests__/*
Add useTopUpForm() (Zod validation, min $5), TopUpForm component wired to submission, and tests verifying cents conversion, min-amount validation, and in-flight UI.
Dialog, Banner & Visibility Hook
autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpDialog/TopUpDialog.tsx, autogpt_platform/frontend/src/components/layout/TopUpPrompt/LowCreditBanner/LowCreditBanner.tsx, autogpt_platform/frontend/src/components/layout/TopUpPrompt/LowCreditBanner/useLowCreditBanner.ts
Implement TopUpDialog controlled by isOpen, LowCreditBanner that shows when useLowCreditBanner() reports visible, and dismissal wiring persisted per-day.
TopUpPromptProvider Orchestration
autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpPromptProvider.tsx
Create provider that reads feature flag, credits, and auto-top-up, computes isOutOfCredits, exposes context, manages dialog open/close, and conditionally renders the daily auto-opener.
Daily Auto-Opener
autogpt_platform/frontend/src/components/layout/TopUpPrompt/DailyTopUpAutoOpener.tsx
Add DailyTopUpAutoOpener which triggers openTopUp() once per day when isOutOfCredits is true.
Platform Layout Integration
autogpt_platform/frontend/src/app/(platform)/layout.tsx
Wrap PaywallGate/children with TopUpPromptProvider so pages consume top-up context.
Page Banner Integration
autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx, autogpt_platform/frontend/src/app/(platform)/library/page.tsx
Render LowCreditBanner in Copilot (after MobileHeader) and Library (before LibraryActionHeader).
WalletRefill Form Refactor
autogpt_platform/frontend/src/components/layout/Navbar/components/Wallet/components/WalletRefill.tsx
Replace local one-time top-up form logic with TopUpForm submitLabel="Top up", retaining auto-refill configuration handling.
Comprehensive Tests
autogpt_platform/frontend/src/components/layout/TopUpPrompt/__tests__/TopUpPromptProvider.test.tsx, autogpt_platform/frontend/src/app/(platform)/copilot/__tests__/low-credit-banner.test.tsx, autogpt_platform/frontend/src/app/(platform)/library/__tests__/low-credit-banner.test.tsx, and other related test files
Vitest suites validate date helpers, provider auto-open/suppression logic, banner visibility/dismissal, dialog opening, TopUpForm behavior, and WalletRefill integration using MSW and localStorage isolation.
Backend credential handling
autogpt_platform/backend/backend/copilot/tools/helpers.py, autogpt_platform/backend/backend/copilot/tools/helpers_test.py
Removed normalization that stripped input fields explicitly set to null before credential resolution; corresponding tests were removed.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes


Possibly related PRs


Suggested labels

size/l


Suggested reviewers

  • Swiftyos
  • Bentlybro
  • Pwuts

"🐰 I hop to nudge a tiny sign,
When credits fade, the banner shines.
Click 'Top up' — a carrot near,
Autopilot hums and hops back clear.
Hooray — small hops, big cheer!"

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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
Title check ✅ Passed The title clearly describes the main feature: prompting users to top up when out of automation credits, which is the primary objective of this PR.
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 PR description is detailed and clearly related to the changeset, explaining the motivation, implementation, and testing approach for adding top-up prompts.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/top-up-automation

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions github-actions Bot added platform/frontend AutoGPT Platform - Front end size/xl labels May 25, 2026
@github-actions

github-actions Bot commented May 25, 2026

Copy link
Copy Markdown
Contributor

🔍 PR Overlap Detection

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

🔴 Merge Conflicts Detected

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

  • refactor(frontend/copilot): remove ARTIFACTS feature flag #13113 (ntindle · updated 13d ago)

    • 📁 autogpt_platform/frontend/src/app/(platform)/copilot/components/
      • ChatContainer/__tests__/ChatContainer.test.tsx (2 conflicts, ~10 lines)
      • ChatMessagesContainer/components/MessageAttachments.tsx (2 conflicts, ~42 lines)
      • ChatMessagesContainer/components/MessagePartRenderer.tsx (2 conflicts, ~27 lines)
  • refactor(frontend): remove artifacts feature flag #13063 (ntindle · updated 13d ago)

    • 📁 autogpt_platform/frontend/src/app/(platform)/copilot/components/
      • ChatContainer/__tests__/ChatContainer.test.tsx (2 conflicts, ~10 lines)
      • ChatMessagesContainer/components/MessageAttachments.tsx (2 conflicts, ~42 lines)
      • ChatMessagesContainer/components/MessagePartRenderer.tsx (2 conflicts, ~27 lines)

🟡 Medium Risk — Some Line Overlap

These PRs have some overlapping changes:

  • feat(frontend): AutoPilot context panel V1 (shell + Files tab) #13228 (0ubbe · updated 9m ago)
    • autogpt_platform/frontend/src/components/layout/Navbar/components/Wallet/components/__tests__/WalletRefill.test.tsx: L1-19
    • autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx: L1-6, L55-62
    • autogpt_platform/frontend/src/components/layout/TopUpPrompt/DailyTopUpAutoOpener.tsx: L1-20
    • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/TopUpForm.tsx: L1-36
    • autogpt_platform/frontend/src/components/layout/TopUpPrompt/LowCreditBanner/LowCreditBanner.tsx: L1-37
    • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/useTopUpForm.ts: L1-36
    • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpDialog/TopUpDialog.tsx: L1-41
    • autogpt_platform/frontend/src/services/storage/local-storage.ts: L21-28
    • autogpt_platform/frontend/src/components/layout/TopUpPrompt/__tests__/TopUpPromptProvider.test.tsx: L1-201
    • autogpt_platform/frontend/src/components/layout/TopUpPrompt/LowCreditBanner/useLowCreditBanner.ts: L1-20
    • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/__tests__/TopUpForm.test.tsx: L1-71
    • autogpt_platform/frontend/src/components/layout/TopUpPrompt/__tests__/helpers.test.ts: L1-22
    • autogpt_platform/frontend/src/app/(platform)/library/__tests__/low-credit-banner.test.tsx: L1-136
    • autogpt_platform/frontend/src/app/(platform)/layout.tsx: L4-10, L15-24
    • autogpt_platform/frontend/src/app/(platform)/copilot/__tests__/low-credit-banner.test.tsx: L1-152
    • autogpt_platform/frontend/src/components/layout/Navbar/components/Wallet/components/WalletRefill.tsx: L11-29, L41-60, L65-70, L73-89, L105-111, L124-155
    • autogpt_platform/frontend/src/components/layout/TopUpPrompt/useTopUpPrompt.ts: L1-24
    • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpPromptProvider.tsx: L1-58
    • autogpt_platform/frontend/src/components/layout/TopUpPrompt/helpers.ts: L1-9

🟢 Low Risk — File Overlap Only

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

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


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

@codecov

codecov Bot commented May 25, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.64706% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 72.42%. Comparing base (50cb6c6) to head (6a3f84f).

Additional details and impacted files
@@            Coverage Diff             @@
##              dev   #13208      +/-   ##
==========================================
+ Coverage   72.38%   72.42%   +0.03%     
==========================================
  Files        2304     2313       +9     
  Lines      173347   173356       +9     
  Branches    17560    17566       +6     
==========================================
+ Hits       125484   125551      +67     
+ Misses      44140    44076      -64     
- Partials     3723     3729       +6     
Flag Coverage Δ
platform-frontend 39.48% <92.53%> (+0.38%) ⬆️
platform-frontend-e2e 31.23% <34.69%> (+0.02%) ⬆️

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

Components Coverage Δ
Platform Backend 80.36% <ø> (-0.01%) ⬇️
Platform Frontend 44.11% <92.64%> (+0.27%) ⬆️
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.

@0ubbe
0ubbe marked this pull request as ready for review May 25, 2026 08:48
@0ubbe
0ubbe requested a review from a team as a code owner May 25, 2026 08:48
@0ubbe
0ubbe requested review from Pwuts and Swiftyos and removed request for a team May 25, 2026 08:48

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (2)
autogpt_platform/frontend/src/app/(platform)/copilot/__tests__/low-credit-banner.test.tsx (1)

2-2: ⚡ Quick win

Remove redundant cleanup() from integration test teardown.

Line 125 duplicates global RTL cleanup handled by the shared Vitest setup; keeping both adds noise and can obscure real teardown needs.

Proposed diff
-import { render, screen, cleanup } from "`@/tests/integrations/test-utils`";
+import { render, screen } from "`@/tests/integrations/test-utils`";
@@
 afterEach(() => {
-  cleanup();
   localStorage.clear();
 });

Based on learnings: testing-library/react cleanup is already handled globally after each test via src/tests/integrations/vitest.setup.tsx, so redundant afterEach(() => cleanup()) should not be added in integration tests.

Also applies to: 124-126

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

In
`@autogpt_platform/frontend/src/app/`(platform)/copilot/__tests__/low-credit-banner.test.tsx
at line 2, The test imports and calls cleanup manually even though global RTL
cleanup is configured; remove the redundant cleanup usage by deleting cleanup
from the import list (leave render and screen) and remove the afterEach(() =>
cleanup()) teardown in the low-credit-banner.test.tsx test file so the global
vitest.setup.tsx handles cleanup automatically.
autogpt_platform/frontend/src/components/layout/TopUpPrompt/__tests__/TopUpPromptProvider.test.tsx (1)

33-49: ⚡ Quick win

Gate suppression assertions on both backend reads, not only credits fetch.

On Line 45-Line 48, waitForCreditsFetch only confirms /user-credits was hit. These tests assert behavior derived from both credits and auto-top-up config; if auto-top-up fetch regresses, the test can still pass. Please wait for both handlers before absence assertions.

Proposed diff
 function setupCredits(args: {
   credits: number;
   amount: number;
   threshold: number;
 }) {
   let creditsRequested = false;
+  let autoTopUpRequested = false;
   server.use(
     getGetV1GetUserCreditsMockHandler(() => {
       creditsRequested = true;
       return { credits: args.credits };
     }),
-    getGetV1GetAutoTopUpMockHandler({
-      amount: args.amount,
-      threshold: args.threshold,
-    }),
+    getGetV1GetAutoTopUpMockHandler(() => {
+      autoTopUpRequested = true;
+      return {
+        amount: args.amount,
+        threshold: args.threshold,
+      };
+    }),
   );
   return {
-    waitForCreditsFetch: () =>
+    waitForConfigFetches: () =>
       waitFor(() => {
         expect(creditsRequested).toBe(true);
+        expect(autoTopUpRequested).toBe(true);
       }),
   };
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@autogpt_platform/frontend/src/components/layout/TopUpPrompt/__tests__/TopUpPromptProvider.test.tsx`
around lines 33 - 49, The test only gates on the /user-credits handler; add a
second flag (e.g. autoTopUpRequested) tied to getGetV1GetAutoTopUpMockHandler
and update the returned waitForCreditsFetch to waitFor both flags instead of
just creditsRequested so the test awaits both backend reads (reference
getGetV1GetUserCreditsMockHandler, getGetV1GetAutoTopUpMockHandler and the
waitForCreditsFetch helper).
🤖 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/frontend/src/components/layout/TopUpPrompt/TopUpDialog/TopUpDialog.tsx`:
- Around line 20-22: Replace the inline arrow assigned to controlled.set with a
named handler function: create a function declaration (e.g., function
handleControlledSet(open: boolean) { if (!open) onClose(); }) and pass that
function reference to controlled.set instead of the inline arrow; update any
existing references to controlled.set to use the new handler name and keep the
existing behavior (call onClose() when open is false) in TopUpDialog's component
scope.

In
`@autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/useTopUpForm.ts`:
- Around line 24-28: The submitTopUp function currently sets isLoading true,
awaits requestTopUp(...).catch(...), then sets isLoading false, but if an
unexpected error escapes the catch the loading state can remain true; wrap the
await in a try/finally so setIsLoading(false) always runs. Update the
submitTopUp implementation (function submitTopUp) to call
requestTopUp(data.amount * 100) inside a try block and move setIsLoading(false)
into a finally block, keeping the existing toastOnFail("request top-up") error
handling around the requestTopUp call.

In
`@autogpt_platform/frontend/src/components/layout/TopUpPrompt/useTopUpPrompt.ts`:
- Around line 12-16: The failing tests are caused by useTopUpPrompt throwing
when not wrapped with TopUpPromptProvider; update the shared test render helpers
(or a central mock) so components rendered in tests—especially those that render
LowCreditBanner—are wrapped with TopUpPromptProvider (or provide a mocked
context value). Locate useTopUpPrompt and TopUpPromptProvider in the diff and
modify your test utility (the common renderWrapper/renderWithProviders helper)
to include TopUpPromptProvider around the tree or add a centralized mock for
useTopUpPrompt to return a safe default, ensuring tests no longer crash before
assertions.

---

Nitpick comments:
In
`@autogpt_platform/frontend/src/app/`(platform)/copilot/__tests__/low-credit-banner.test.tsx:
- Line 2: The test imports and calls cleanup manually even though global RTL
cleanup is configured; remove the redundant cleanup usage by deleting cleanup
from the import list (leave render and screen) and remove the afterEach(() =>
cleanup()) teardown in the low-credit-banner.test.tsx test file so the global
vitest.setup.tsx handles cleanup automatically.

In
`@autogpt_platform/frontend/src/components/layout/TopUpPrompt/__tests__/TopUpPromptProvider.test.tsx`:
- Around line 33-49: The test only gates on the /user-credits handler; add a
second flag (e.g. autoTopUpRequested) tied to getGetV1GetAutoTopUpMockHandler
and update the returned waitForCreditsFetch to waitFor both flags instead of
just creditsRequested so the test awaits both backend reads (reference
getGetV1GetUserCreditsMockHandler, getGetV1GetAutoTopUpMockHandler and the
waitForCreditsFetch helper).
🪄 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: a2dc8993-bb0c-49e5-9939-635aabad5e8a

📥 Commits

Reviewing files that changed from the base of the PR and between a13e70f and 17fcaa6.

📒 Files selected for processing (18)
  • autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx
  • autogpt_platform/frontend/src/app/(platform)/copilot/__tests__/low-credit-banner.test.tsx
  • autogpt_platform/frontend/src/app/(platform)/layout.tsx
  • autogpt_platform/frontend/src/app/(platform)/library/__tests__/low-credit-banner.test.tsx
  • autogpt_platform/frontend/src/app/(platform)/library/page.tsx
  • autogpt_platform/frontend/src/components/layout/Navbar/components/Wallet/components/WalletRefill.tsx
  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/DailyTopUpAutoOpener.tsx
  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/LowCreditBanner/LowCreditBanner.tsx
  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/LowCreditBanner/useLowCreditBanner.ts
  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpDialog/TopUpDialog.tsx
  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/TopUpForm.tsx
  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/useTopUpForm.ts
  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpPromptProvider.tsx
  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/__tests__/TopUpPromptProvider.test.tsx
  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/__tests__/helpers.test.ts
  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/helpers.ts
  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/useTopUpPrompt.ts
  • autogpt_platform/frontend/src/services/storage/local-storage.ts

Comment thread autogpt_platform/frontend/src/components/layout/TopUpPrompt/useTopUpPrompt.ts Outdated
0ubbe and others added 4 commits May 25, 2026 18:17
useTopUpPrompt threw when no TopUpPromptProvider was an ancestor, which
crashed every existing Library/Autopilot page test (they render the page
without the layout) and would white-screen the page in prod if the
provider were ever absent. The prompt is an optional enhancement, so fall
back to an inert value instead.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- TopUpDialog: named handler instead of inline arrow for controlled.set
- useTopUpForm: reset isLoading via try/finally on submit
- LowCreditBanner: wrap the action row so it stays usable at 375px
- tests: drop redundant cleanup(); gate the suppression waiter on both
  the credits and auto-top-up reads

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

0ubbe commented May 26, 2026

Copy link
Copy Markdown
Contributor Author

/review

@autogpt-pr-reviewer

Copy link
Copy Markdown

Queued a review for PR #13208 at ddb220a.

@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 #13208

PR #13208 — feat(frontend): prompt top-up when out of automation credits
Author: 0ubbe | Files: 18

🎯 Verdict: REQUEST_CHANGES

PR Description Quality

✅ Has Why + What + How — clear description of the three surfaces (daily modal, Library banner, Copilot banner), gating logic, and acknowledged tech debt (legacy form imports). PR checklist items are present but all unchecked.

What This PR Does

When a user runs out of automation credits and doesn't have auto-refill enabled, there's currently no in-app prompt to top up. This PR adds three coordinated UI surfaces — a once-per-day modal dialog, a persistent banner on the Library page, and a persistent banner on the Copilot page — all gated behind the ENABLE_PLATFORM_PAYMENT feature flag and the user's credit balance. A shared TopUpPromptProvider context coordinates state, and the top-up form was extracted from WalletRefill into a reusable TopUpForm component that reuses the existing Stripe checkout flow.

Specialist Findings

🛡️ Security ✅ — No new attack surface. This is a UI-only change reusing the existing server-validated Stripe checkout path. No new API endpoints, no secrets in code, no XSS vectors. The localStorage-based daily gate controls UX only, not authorization.

  • 🟡 Legacy Form import from @/components/__legacy__/ui/form extends reliance on unmaintained code (TopUpForm.tsx:1) — acknowledged by author as follow-up.

🏗️ Architecture ✅ — Well-structured context + provider + consumer pattern. Clean extraction of TopUpForm from WalletRefill eliminates duplication. File organization follows the ComponentName/ComponentName.tsx + useComponentName.ts + helpers.ts convention throughout.

  • 🟠 useCredits may be called twice per platform page load — once by TopUpPromptProvider (TopUpPromptProvider.tsx:19) and once by the Navbar Wallet. If useCredits doesn't deduplicate via React Query, this doubles credit-fetch API traffic for every authenticated user. (Flagged by: architect, performance — 2)
  • 🟡 Context only exposes openTopUp but not closeTopUp (useTopUpPrompt.ts:4) — minor extensibility gap for future consumers.

Performance ✅ — All operations are O(1). No unbounded loops, no memory leaks. Main concern is the potential duplicate credit fetch noted above. localStorage reads are synchronous but occur only on mount — negligible impact.

🧪 Testing ⚠️ — 12/12 existing tests pass with good MSW usage and suppression-path coverage. However, critical gaps exist:

  • 🔴 The extracted TopUpForm / useTopUpForm — which calls requestTopUp(amount * 100) to initiate Stripe checkout — has zero tests (useTopUpForm.ts:24-30). The refactoring introduced a try/finally pattern that differs from the original WalletRefill behavior. This is payment-touching code. (Flagged by: testing — 1)
  • 🟠 No test for the banner dismiss button (LowCreditBanner.tsx:27-33) — clicking X should write to localStorage and hide the banner. The Library test clicks the CTA but never dismiss. (Flagged by: testing — 1)
  • 🟠 No regression test for WalletRefill after the extraction (WalletRefill.tsx:108) — the one-time top-up tab was refactored to use <TopUpForm> but nothing verifies it still works. (Flagged by: testing — 1)
  • 🟡 useTopUpPrompt inert fallback (useTopUpPrompt.ts:15-18) is documented but untested.

📖 Quality ✅ — Clean, well-named code. Function declarations throughout, no barrel files, Phosphor icons, proper separation of concerns.

  • 🔵 Mixed error handling in useTopUpForm.ts:25-30: try/finally wrapping .catch() is functionally correct but reads confusingly — the .catch() swallows the rejection so try never throws.
  • 🔵 Long inline comment at TopUpPromptProvider.tsx:24 (130+ chars).

📦 Product ✅ — Feature delivers exactly what's described: three coordinated payment-gated surfaces with proper suppression logic. Daily-limit prevents annoyance, Stripe flow is reused.

  • 🟠 No loading feedback on the top-up form (TopUpForm.tsx:30) — the button stays as "Top up" while isLoading is true. On slow connections, users won't know a Stripe redirect is in progress. (Flagged by: product — 1)
  • 🟡 Dialog doesn't suggest auto-refill as an alternative (TopUpDialog.tsx:27).

📬 Discussion ⚠️ — Author addressed all 3 CodeRabbit actionable items promptly with commit fixes. However:

  • 🟠 Sentry bot's concern about fail-closed behavior (TopUpPromptProvider.tsx:28-33) is unacknowledged — no reply and no documenting code comment.
  • 🟠 PR checklist manual test items are all unchecked — author hasn't confirmed manual verification of the payment flow.
  • No human reviewer has approved yet.

🔎 QA ✅ — All 12 integration tests pass. Feature correctly gated behind ENABLE_PLATFORM_PAYMENT flag — invisible in local mode. Negative auth tests confirm endpoint protection. No regressions in service logs.

QA Screenshots

Screenshot Description
Library page authed Library page with payment flag off + 100 credits — no banner visible ✅
Copilot page Copilot page with payment flag off — no banner or modal visible ✅

🔴 Blockers

  1. Untested payment-touching code (TopUpForm/useTopUpForm.ts:24-30) — The extracted useTopUpForm hook calls requestTopUp(amount * 100) to initiate Stripe checkout and has zero tests. The refactoring also introduced a try/finally error-recovery pattern that differs from the original WalletRefill. Add tests for: (a) valid submission calls requestTopUp with cents, (b) $5 minimum validation rejects lower amounts, (c) button disabled during loading. (Flagged by: testing — 1)

🟠 Should Fix

  1. Banner dismiss flow untested (LowCreditBanner.tsx:27-33) — No test verifies the dismiss X button writes to localStorage and hides the banner. (Flagged by: testing — 1)
  2. WalletRefill regression coverage missing (WalletRefill.tsx:108) — The one-time top-up tab was refactored to use <TopUpForm> but has no smoke test after extraction. (Flagged by: testing — 1)
  3. No loading feedback on top-up submit (TopUpForm.tsx:30) — Button label stays "Top up" during Stripe redirect. Show a spinner or "Redirecting…" text. (Flagged by: product — 1)
  4. Verify useCredits deduplication (TopUpPromptProvider.tsx:19) — If useCredits isn't backed by React Query or similar, every platform page load now fires duplicate credit-fetch requests. Confirm and document. (Flagged by: architect, performance — 2)
  5. Acknowledge Sentry bot feedback (TopUpPromptProvider.tsx:28-33) — Reply to the thread and add a code comment explaining the intentional fail-closed design. (Flagged by: discussion — 1)
  6. Complete PR checklist — All manual test items are unchecked. Confirm manual verification before requesting merge. (Flagged by: discussion — 1)

🟡 Nice to Have

  1. Add aria-live="polite" to LowCreditBanner (LowCreditBanner.tsx:17) — Screen readers won't announce the dynamically-appearing banner without it. (quality)
  2. Suggest auto-refill in dialog (TopUpDialog.tsx:27) — A secondary link like "Or enable auto-refill" could reduce future prompt occurrences. (product)
  3. Test useTopUpPrompt inert fallback (useTopUpPrompt.ts:15-18) — Prevents crashes if provider is accidentally removed from the tree. (testing)
  4. Plan legacy form migration (TopUpForm.tsx:1) — File a follow-up to migrate both TopUpForm and WalletRefill off @/components/__legacy__/ui/form. (security, architect, quality)

🔵 Nits

  1. Mixed error-handling pattern (useTopUpForm.ts:25-30) — try/finally wrapping .catch() is confusing. Use either try/catch/finally or .catch().finally(), not both.
  2. Long inline comment (TopUpPromptProvider.tsx:24) — 130+ character line; split to a block comment above.

Human Review Needed

YES — This is a payment-related feature touching Stripe checkout flows. While the backend is unchanged, the extracted TopUpForm is the entry point for real-money transactions, and 18 files were modified including layout-level provider changes. A human reviewer should verify the useCredits deduplication behavior and confirm the suppression logic works correctly in the deployed environment.

Risk Assessment

Merge risk: LOW | Rollback: EASY

Feature is entirely frontend, gated behind a LaunchDarkly flag (ENABLE_PLATFORM_PAYMENT), and reuses existing Stripe infrastructure. Can be disabled instantly via flag toggle. No database migrations, no backend changes. 4 other open PRs may conflict if merged after this one — coordinate with @ntindle.

CI Status

⚠️ 2/6 quality checks pass, 4/6 fail:

  • ✅ Frontend lint, Backend lint
  • ❌ Frontend typecheck, Backend tests, Frontend unit tests, Frontend build

Note: Backend test failure appears to be an environment issue (0s runtime), not related to this PR. Frontend failures should be investigated — they may indicate issues introduced by this PR or pre-existing CI flakiness.



UI Testing — Variant Results

✅ local: All 12 integration tests pass, feature correctly gated behind payment flag (invisible in local mode), no regressions or payment UI leakage detected.

✅ hosted: All 12 integration tests pass, pages render correctly with positive credits (banners properly suppressed), auth protection verified, no regressions in logs

@github-project-automation github-project-automation Bot moved this from 🆕 Needs initial review to 🚧 Needs work in AutoGPT development kanban May 26, 2026
0ubbe and others added 3 commits May 26, 2026 21:07
- Migrate TopUpForm off the legacy __legacy__/ui/form import to the
  design-system molecules/Form primitives.
- Show "Redirecting…" on the submit button while a checkout is in flight.
- Replace the misleading try/finally in useTopUpForm with a promise
  .finally() chain.
- Document the fail-closed auto-top-up-config behaviour in the provider
  and add a symmetric closeTopUp to the context.
- Add aria-live and a dismiss title to the LowCreditBanner for a11y.
- Offer an "enable auto-refill" link in the top-up dialog.

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

- TopUpForm: valid submission posts the amount in cents; sub-$5 amounts
  are rejected without hitting the API.
- WalletRefill: regression smoke test that the one-time top-up tab still
  renders the extracted TopUpForm.
- LowCreditBanner: dismissing hides it for the day and records the date.
- useTopUpPrompt: consumers without a provider fall back to an inert
  value instead of throwing.

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

Completes the payment-form coverage by holding the request open and
verifying the submit button shows "Redirecting…" and is disabled.

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/__tests__/TopUpForm.test.tsx (1)

69-69: ⚡ Quick win

Consider using the jest-dom toBeDisabled() matcher.

The type assertion and property access work correctly, but jest-dom's toBeDisabled() matcher is more idiomatic and provides clearer error messages.

♻️ Suggested refinement
-    const button = await screen.findByRole("button", { name: /redirecting/i });
-    expect((button as HTMLButtonElement).disabled).toBe(true);
+    const button = await screen.findByRole("button", { name: /redirecting/i });
+    expect(button).toBeDisabled();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/__tests__/TopUpForm.test.tsx`
at line 69, Replace the explicit type assertion and property check in
TopUpForm.test.tsx—expect((button as
HTMLButtonElement).disabled).toBe(true)—with the jest-dom matcher
expect(button).toBeDisabled() to be more idiomatic; ensure the test file (or
your test setup like setupTests.ts) imports jest-dom matchers (e.g., import
'`@testing-library/jest-dom/extend-expect`') so toBeDisabled() is available and
confirm the queried element stored in button is a DOM element returned by RTL
(e.g., getByRole/getByTestId) so the matcher can operate on it.
🤖 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.

Nitpick comments:
In
`@autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/__tests__/TopUpForm.test.tsx`:
- Line 69: Replace the explicit type assertion and property check in
TopUpForm.test.tsx—expect((button as
HTMLButtonElement).disabled).toBe(true)—with the jest-dom matcher
expect(button).toBeDisabled() to be more idiomatic; ensure the test file (or
your test setup like setupTests.ts) imports jest-dom matchers (e.g., import
'`@testing-library/jest-dom/extend-expect`') so toBeDisabled() is available and
confirm the queried element stored in button is a DOM element returned by RTL
(e.g., getByRole/getByTestId) so the matcher can operate on it.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5f8d9141-f2a3-42c1-8806-8dacbe677863

📥 Commits

Reviewing files that changed from the base of the PR and between 190d13f and 79417ab.

📒 Files selected for processing (1)
  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/__tests__/TopUpForm.test.tsx
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Seer Code Review
🧰 Additional context used
📓 Path-based instructions (15)
autogpt_platform/frontend/**/*.{ts,tsx,js,jsx}

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

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

Format frontend code using pnpm format

autogpt_platform/frontend/**/*.{ts,tsx,js,jsx}: Fully capitalize acronyms in symbols, e.g. graphID, useBackendAPI
No linter suppressors (// @ts-ignore``, // eslint-disable) — fix the actual issue

Files:

  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/__tests__/TopUpForm.test.tsx
autogpt_platform/frontend/**/*.{tsx,ts}

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

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

Files:

  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/__tests__/TopUpForm.test.tsx
autogpt_platform/frontend/**/*.{ts,tsx}

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

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

autogpt_platform/frontend/**/*.{ts,tsx}: Use function declarations (not arrow functions) for components/handlers
No any types unless the value genuinely can be anything
Keep render functions and hooks under ~50 lines; extract named helpers or sub-components when they grow longer

Files:

  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/__tests__/TopUpForm.test.tsx
autogpt_platform/frontend/src/components/**/*.{tsx,ts}

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

Structure React components as: ComponentName/ComponentName.tsx + useComponentName.ts + helpers.ts (exception: small 3-4 line components can be inline; render-only components can be direct files)

Files:

  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/__tests__/TopUpForm.test.tsx
autogpt_platform/frontend/src/components/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Structure components as ComponentName/ComponentName.tsx + useComponentName.ts + helpers.ts, use design system components from src/components/ (atoms, molecules, organisms), and never use src/components/__legacy__/*

Files:

  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/__tests__/TopUpForm.test.tsx
autogpt_platform/frontend/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

autogpt_platform/frontend/src/**/*.{ts,tsx}: Use generated API hooks from @/app/api/__generated__/endpoints/ following the pattern use{Method}{Version}{OperationName}, and regenerate with pnpm generate:api
Separate render logic from business logic using component.tsx + useComponent.ts + helpers.ts pattern, colocate state when possible and avoid creating large components, use sub-components in local /components folder
Use function declarations for components and handlers, use arrow functions only for callbacks
Do not use useCallback or useMemo unless asked to optimise a given function

autogpt_platform/frontend/src/**/*.{ts,tsx}: Keep files under ~200 lines; extract sub-components or hooks into their own files when a file grows beyond this
Use generated API hooks from @/app/api/__generated__/endpoints/ with pattern use{Method}{Version}{OperationName}
Always import the -Icon-suffixed alias from @phosphor-icons/react (e.g. TrashIcon, PlusIcon, SquareIcon) — bare exports are deprecated
Do not use useCallback or useMemo unless asked to optimize a given function
Never use src/components/__legacy__/* — use design system components from src/components/

Files:

  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/__tests__/TopUpForm.test.tsx
autogpt_platform/frontend/**/*.{tsx,css}

📄 CodeRabbit inference engine (AGENTS.md)

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

Files:

  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/__tests__/TopUpForm.test.tsx
autogpt_platform/frontend/src/**/*.tsx

📄 CodeRabbit inference engine (AGENTS.md)

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

Files:

  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/__tests__/TopUpForm.test.tsx
autogpt_platform/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Never type with any, if no types available use unknown

Files:

  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/__tests__/TopUpForm.test.tsx
autogpt_platform/frontend/**/*.{test,spec}.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

autogpt_platform/frontend/**/*.{test,spec}.{ts,tsx}: Use Vitest + RTL + MSW for integration tests as the primary testing approach (~90%, page-level), use Playwright for E2E critical flows, and use Storybook for design system components
Run frontend integration tests with pnpm test:unit (Vitest + RTL + MSW)

Files:

  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/__tests__/TopUpForm.test.tsx
autogpt_platform/frontend/**/*.{tsx,jsx}

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

autogpt_platform/frontend/**/*.{tsx,jsx}: No dark: Tailwind classes — the design system handles dark mode
Use Next.js <Link> for internal navigation — never raw <a> tags
Use Tailwind CSS only for styling with design tokens and Phosphor Icons only

Files:

  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/__tests__/TopUpForm.test.tsx
autogpt_platform/frontend/src/**/components/**/*.{tsx,jsx}

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

Put sub-components in local components/ folder; component props should be type Props = { ... } (not exported) unless used outside the component

Files:

  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/__tests__/TopUpForm.test.tsx
autogpt_platform/frontend/src/**/components/**/*.{ts,tsx}

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

Structure components as ComponentName/ComponentName.tsx + useComponentName.ts + helpers.ts

Files:

  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/__tests__/TopUpForm.test.tsx
autogpt_platform/frontend/src/**/__tests__/**/*.{test,spec}.{ts,tsx}

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

Use Orval-generated MSW handlers from @/app/api/__generated__/endpoints/{tag}/{tag}.msw.ts for API mocking

Files:

  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/__tests__/TopUpForm.test.tsx
autogpt_platform/frontend/src/**/*.{ts,tsx,js,jsx}

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

Avoid index and barrel files

Files:

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

Applied to files:

  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/__tests__/TopUpForm.test.tsx
📚 Learning: 2026-04-01T18:54:16.035Z
Learnt from: Bentlybro
Repo: Significant-Gravitas/AutoGPT PR: 12633
File: autogpt_platform/frontend/src/app/(platform)/library/components/AgentFilterMenu/AgentFilterMenu.tsx:3-10
Timestamp: 2026-04-01T18:54:16.035Z
Learning: In the frontend, the legacy Select component at `@/components/__legacy__/ui/select` is an intentional, codebase-wide visual-consistency pattern. During code reviews, do not flag or block PRs merely for continuing to use this legacy Select. If a migration to the newer design-system Select is desired, bundle it into a single dedicated cleanup/migration PR that updates all Select usages together (e.g., avoid piecemeal replacements).

Applied to files:

  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/__tests__/TopUpForm.test.tsx
📚 Learning: 2026-04-07T09:24:16.582Z
Learnt from: 0ubbe
Repo: Significant-Gravitas/AutoGPT PR: 12686
File: autogpt_platform/frontend/src/app/(no-navbar)/onboarding/steps/__tests__/PainPointsStep.test.tsx:1-19
Timestamp: 2026-04-07T09:24:16.582Z
Learning: In Significant-Gravitas/AutoGPT’s `autogpt_platform/frontend` (Vite + `vitejs/plugin-react` with the automatic JSX transform), do not flag usages of React types/components (e.g., `React.ReactNode`) in `.ts`/`.tsx` files as missing `React` imports. Since the React namespace is made available by the project’s TS/Vite setup, an explicit `import React from 'react'` or `import type { ReactNode } ...` is not required; only treat it as missing if typechecking (e.g., `pnpm types`) would actually fail.

Applied to files:

  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/__tests__/TopUpForm.test.tsx
📚 Learning: 2026-04-02T05:43:49.128Z
Learnt from: 0ubbe
Repo: Significant-Gravitas/AutoGPT PR: 12640
File: autogpt_platform/frontend/src/app/(no-navbar)/onboarding/steps/WelcomeStep.tsx:13-13
Timestamp: 2026-04-02T05:43:49.128Z
Learning: Do not flag `import { Question } from "phosphor-icons/react"` as an invalid import. `Question` is a valid named export from `phosphor-icons/react` (as reflected in the package’s generated `.d.ts` files and re-exports via `dist/index.d.ts`), so it should be treated as a supported named export during code reviews.

Applied to files:

  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/__tests__/TopUpForm.test.tsx
📚 Learning: 2026-04-13T13:11:07.445Z
Learnt from: 0ubbe
Repo: Significant-Gravitas/AutoGPT PR: 12764
File: autogpt_platform/frontend/src/app/(platform)/library/components/SitrepItem/SitrepItem.tsx:143-145
Timestamp: 2026-04-13T13:11:07.445Z
Learning: In `autogpt_platform/frontend`, do not flag direct interpolation of `executionID` UUID strings into URL query parameters (e.g., `activeItem=${executionID}` in JSX/Next links). If the value is a UUID string matching `[0-9a-f-]`, it contains no reserved URL characters, so additional `encodeURIComponent` or Next.js object-based `href` encoding is unnecessary. Only treat it as an encoding issue if the query-param value is not guaranteed to be UUID-formatted (i.e., may include characters outside `[0-9a-f-]`).

Applied to files:

  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/__tests__/TopUpForm.test.tsx
📚 Learning: 2026-04-15T22:49:06.896Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 11235
File: autogpt_platform/frontend/src/app/(platform)/admin/diagnostics/components/ExecutionsTable.tsx:0-0
Timestamp: 2026-04-15T22:49:06.896Z
Learning: In the AutoGPT frontend (React Query + toast/ErrorCard patterns), do not require `Sentry.captureException` in React Query mutation `catch` blocks. React Query handles error propagation for mutation paths, so follow the established pattern: show toast notifications for mutation errors and use `ErrorCard` for render/fetch errors. Only add `Sentry.captureException` for truly manual/unexpected exception paths that are outside React Query’s control (e.g., standalone async utilities or event handlers not wired through React Query).

Applied to files:

  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/__tests__/TopUpForm.test.tsx
📚 Learning: 2026-04-20T13:17:39.951Z
Learnt from: 0ubbe
Repo: Significant-Gravitas/AutoGPT PR: 12854
File: autogpt_platform/frontend/src/app/(platform)/library/__tests__/briefing.test.tsx:84-84
Timestamp: 2026-04-20T13:17:39.951Z
Learning: In the AutoGPT frontend, `testing-library/react` cleanup is already handled globally after each test via `src/tests/integrations/vitest.setup.tsx`. Therefore, for integration test files under `__tests__/`, do NOT add redundant `afterEach(() => cleanup())`. Only add local `afterEach` teardown for resources that are not covered globally—specifically, when using fake timers, add `afterEach(() => vi.useRealTimers())` (or equivalent) to restore real timers and prevent cross-test interference.

Applied to files:

  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/__tests__/TopUpForm.test.tsx
📚 Learning: 2026-04-20T20:07:22.981Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 11235
File: autogpt_platform/frontend/src/app/(platform)/admin/diagnostics/__tests__/ExecutionsTable.test.tsx:27-76
Timestamp: 2026-04-20T20:07:22.981Z
Learning: In this codebase, Orval-generated API modules under `src/app/api/__generated__/` are not committed to git and must be generated via `pnpm generate:api` (requires a running backend). In integration tests, it’s acceptable—and expected—to stub generated hooks/modules by mocking them with `vi.mock("`@/app/api/__generated__/endpoints/`{tag}/{tag}")`. Do not treat `vi.mock` of these generated hook modules as a violation of the MSW handler guideline, since the corresponding MSW handlers cannot be imported at test time when generated files are absent.

Applied to files:

  • autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/__tests__/TopUpForm.test.tsx
🔇 Additional comments (1)
autogpt_platform/frontend/src/components/layout/TopUpPrompt/TopUpForm/__tests__/TopUpForm.test.tsx (1)

53-70: LGTM!

0ubbe and others added 3 commits May 28, 2026 16:56
Move the low-credit banner into the Library "All" tab (above the agent
grid) instead of stacking at the top of the page, and align the
copilot placement via an optional wrapper className on the banner so
each surface controls its own padding.

Banner: warm-orange "Top up" CTA, ghost dismiss button with a
peach-tinted hover that blends with the warning surface, copy reads
as two sentences without an em dash.

Top-up dialog: lucide warning icon (matching the alert) prefixes the
heading, body and billing-link copy merged into a single text-base
paragraph, input and submit button use the design system's default
sizes.
Add an optional `size` prop to TopUpForm so the wallet refill popover
can render small input + button (matching the surrounding auto-refill
controls), while the top-up modal keeps the design system's default
sizes.
Comment thread autogpt_platform/backend/backend/copilot/tools/helpers.py
0ubbe and others added 3 commits May 28, 2026 19:17
…commit

LLMs sometimes pass `"credentials": null` instead of omitting the field.
Reinstates the strip-on-null guard and its tests from #13185 that were
accidentally removed by an earlier "chore: changes" commit on this branch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The component dropped the `visible` boolean returned by
`useLowCreditBanner`, so the banner ignored both the credit balance and
the daily-dismissal state. Destructure `visible` and early-return null
when it is false.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`getUserCredit` swallowed errors and returned `{ credits: 0 }`, which
the new TopUpPromptProvider treated as out-of-credits. A flaky GET
/credits then nudged users to top up unnecessarily.

Return `{ credits: null }` on error so `credits !== null` in the
provider short-circuits, and cover the regression with an integration
test that mocks the credits endpoint to 500.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot removed the platform/backend AutoGPT Platform - Back end label May 28, 2026
@0ubbe
0ubbe merged commit 2cad7c4 into dev May 28, 2026
34 of 35 checks passed
@0ubbe
0ubbe deleted the feature/top-up-automation branch May 28, 2026 10:33
@github-project-automation github-project-automation Bot moved this from 🚧 Needs work to ✅ Done in AutoGPT development kanban May 28, 2026
@github-project-automation github-project-automation Bot moved this to Done in Frontend May 28, 2026
0ubbe added a commit that referenced this pull request Jun 1, 2026
The pre-merge branch rendered LowCreditBanner at the top of the page,
and the dev merge added a second copy inside LibraryAgentList (the
intended placement per PR #13208). Keep only the LibraryAgentList one.

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

Labels

platform/frontend AutoGPT Platform - Front end size/xl

Projects

Status: ✅ Done
Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant