Skip to content

agent: @U0AJM7X8FBR Admin - I want a page to view the recent task runs for a sp#10

Merged
sweetmantech merged 4 commits intomainfrom
agent/-u0ajm7x8fbr-admin---i-want-a--1773666951576
Mar 16, 2026
Merged

agent: @U0AJM7X8FBR Admin - I want a page to view the recent task runs for a sp#10
sweetmantech merged 4 commits intomainfrom
agent/-u0ajm7x8fbr-admin---i-want-a--1773666951576

Conversation

@sweetmantech
Copy link
Copy Markdown
Contributor

@sweetmantech sweetmantech commented Mar 16, 2026

Automated PR from coding agent.

Prompt: @U0AJM7X8FBR Admin - I want a page to view the recent task runs for a specific account. More specifically, I want to see the Pulse tasks which are run for a specific account.Most important question: What Pulse emails has Alexis received in the past 7 days?Recommended implementationTasks - pulse - Have the existing bulk Pulse task spawn a new, pulse , sub-task which executes for one account AND tags the account for easy querying. The results of the pulse sub task should include the roomId so we can query emails associated with the room.Docs - GET /api/tasks/runs - Update the existing API Docs to allow an account_id param (optional) which is only applicable for org api keys. Use this param for getting all runs associated with a specific account which is different from the account authenticated via API keys. Follows documentation-driven development.API - GET /api/tasks/runs - Update the existing API endpoint following the Docs changes to add the account_id param. Follows documentation-driven development.Admin - Account Page - query the new GET /api/tasks/runs to show all recent task runs for a specific account.

Summary by CodeRabbit

  • New Features
    • Added account detail page displaying task run history with status badges and timing information
    • Integrated navigation links to account details throughout the application
    • Organized task runs display with dedicated sections for Pulse runs and complete run history
    • Added responsive task runs table showing run identifiers, status, duration, and run IDs

- /accounts/[account_id]: new page showing task runs per account
- AccountDetailPage: shows Pulse runs filtered from all runs, with
  a collapsible "all runs" section
- TaskRunsTable: table with status badges, duration, and run IDs
- AccountReposList: now shows clickable account email → /accounts/[id]
  with repo URL as secondary link
- sandboxesColumns: account email is now a clickable link to /accounts/[id]
- fetchAccountTaskRuns + useAccountTaskRuns: data layer for the page

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel bot commented Mar 16, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
admin Ready Ready Preview Mar 16, 2026 7:56pm

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 16, 2026

Warning

Rate limit exceeded

@sweetmantech has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 21 minutes and 36 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: eb9aa821-c2c4-4e9d-8f4d-f38f975af7f0

📥 Commits

Reviewing files that changed from the base of the PR and between 7690751 and ed446ea.

📒 Files selected for processing (6)
  • components/AccountDetail/AccountBreadcrumb.tsx
  • components/AccountDetail/AccountDetailPage.tsx
  • components/AccountDetail/TaskRunsTable.tsx
  • components/SandboxOrgs/AccountReposList.tsx
  • lib/tasks/formatRunDuration.ts
  • lib/tasks/getStatusBadgeColor.ts
📝 Walkthrough

Walkthrough

A new account detail page feature displays task runs for specific accounts. The implementation includes a dynamic Next.js page route, React components for account details and task run tables, a custom hook with auto-refetch capability using React Query and Privy authentication, API integration for fetching task runs, enriched type definitions, and refactored components to support account navigation.

Changes

Cohort / File(s) Summary
Account Detail Page
app/accounts/[account_id]/page.tsx
New Next.js dynamic route page with generateMetadata for SEO and async Page component that passes resolved accountId to AccountDetailPage component.
Account Detail Components
components/AccountDetail/AccountDetailPage.tsx, components/AccountDetail/TaskRunsTable.tsx
New AccountDetailPage component renders breadcrumbs, header, and pulse-specific task runs; TaskRunsTable displays task run metadata (identifier, status, duration, run ID) with status badge styling and empty state handling.
Type Definitions
types/sandbox.ts
Added AccountRepo interface (account_id, email, repo_url); TaskRun interface (id, taskIdentifier, status, timestamps, tags); AccountTaskRunsResponse interface; updated OrgRepoRow.account_repos from string[] to AccountRepo[].
Task Run Data Fetching
hooks/useAccountTaskRuns.ts, lib/recoup/fetchAccountTaskRuns.ts
New useAccountTaskRuns hook integrates Privy authentication and React Query for auto-refetching task runs every 10 seconds; fetchAccountTaskRuns constructs authenticated API requests with error handling and response parsing.
Account Navigation & Component Updates
components/SandboxOrgs/AccountReposList.tsx, components/Sandboxes/sandboxesColumns.tsx
AccountReposList refactored to iterate over AccountRepo objects (instead of string URLs), extracting repo_name and display_label, and linking to account detail pages; sandboxesColumns updated to wrap account emails in links to /accounts/{accountId}.

Sequence Diagram

sequenceDiagram
    participant Client as Client/Browser
    participant Page as Next.js Page<br/>(app/accounts/[account_id])
    participant AccountDetail as AccountDetailPage<br/>Component
    participant Hook as useAccountTaskRuns<br/>Hook
    participant Auth as Privy Auth<br/>Service
    participant API as Backend API<br/>(/api/tasks/runs)

    Client->>Page: Navigate to /accounts/{account_id}
    Page->>Page: Resolve params.account_id
    Page->>AccountDetail: Render with accountId
    AccountDetail->>Hook: useAccountTaskRuns(accountId)
    Hook->>Auth: Check if ready & authenticated
    Auth-->>Hook: Ready & authenticated status
    Hook->>Auth: getAccessToken()
    Auth-->>Hook: Access token
    Hook->>API: GET /api/tasks/runs?account_id=X&limit=20<br/>(Authorization: Bearer token)
    API-->>Hook: TaskRun[] | error
    Hook-->>AccountDetail: {data, isLoading, error}
    AccountDetail->>AccountDetail: Filter pulseRuns<br/>(taskIdentifier === "send-pulse-task")
    AccountDetail->>AccountDetail: Render breadcrumbs,<br/>pulse stats, TaskRunsTable
    AccountDetail-->>Client: Display account detail view
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 A new account page hops into view,
With task runs displayed—all numbered and true!
Privy guards the gates, React Query refreshes with care,
Links bloom through the orgs, connections laid fair! 🌿✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.22% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The pull request title is truncated and incomplete, ending mid-word ('sp' instead of a complete word), making it impossible to assess whether it accurately describes the changeset. Complete and clarify the pull request title to accurately summarize the main objective, such as 'Add account page to view recent task runs'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch agent/-u0ajm7x8fbr-admin---i-want-a--1773666951576
📝 Coding Plan
  • Generate coding plan for human review comments

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.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
lib/recoup/fetchAccountTaskRuns.ts (1)

22-24: Consider adding a request timeout for resilience.

The fetch call has no timeout, which could cause the request to hang indefinitely if the server is unresponsive. This is a minor resilience concern.

🛡️ Optional: Add AbortController timeout
 export async function fetchAccountTaskRuns(
   accessToken: string,
   accountId: string,
   limit = 20,
 ): Promise<TaskRun[]> {
   const url = new URL(`${API_BASE_URL}/api/tasks/runs`);
   url.searchParams.set("account_id", accountId);
   url.searchParams.set("limit", String(limit));

+  const controller = new AbortController();
+  const timeoutId = setTimeout(() => controller.abort(), 30_000);
+
-  const res = await fetch(url.toString(), {
-    headers: { Authorization: `Bearer ${accessToken}` },
-  });
+  try {
+    const res = await fetch(url.toString(), {
+      headers: { Authorization: `Bearer ${accessToken}` },
+      signal: controller.signal,
+    });
+    clearTimeout(timeoutId);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/recoup/fetchAccountTaskRuns.ts` around lines 22 - 24, Add a timeout using
AbortController around the fetch in fetchAccountTaskRuns: create an
AbortController, start a setTimeout that calls controller.abort() after a chosen
timeout (e.g., 10s), pass controller.signal to fetch(url.toString(), { headers:
{ Authorization: `Bearer ${accessToken}` }, signal }), and clear the timeout
after fetch completes to avoid leaks; handle AbortError/timeout appropriately
where res is used.
components/AccountDetail/AccountDetailPage.tsx (1)

82-93: Consider whether "All task runs" should exclude pulse runs already shown.

The collapsible section displays all runs including the pulse runs already shown above. This may be intentional for a complete view, but could cause confusion. If you want to avoid redundancy, filter out pulse runs:

💡 Optional: Show only non-pulse runs in collapsible section
         {!isLoading && !error && runs && runs.length > pulseRuns.length && (
           <details className="mt-6">
             <summary className="cursor-pointer text-sm font-medium text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100">
-              All task runs ({runs.length})
+              Other task runs ({runs.length - pulseRuns.length})
             </summary>
             <div className="mt-3">
-              <TaskRunsTable runs={runs} />
+              <TaskRunsTable runs={runs.filter(r => r.taskIdentifier !== "send-pulse-task")} />
             </div>
           </details>
         )}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/AccountDetail/AccountDetailPage.tsx` around lines 82 - 93, The
collapsible "All task runs" currently renders the full runs list including
pulseRuns, causing duplication; update AccountDetailPage to compute a
nonPulseRuns array (e.g., filter runs by excluding IDs present in pulseRuns) and
use that for the collapsible section's header count and TaskRunsTable render,
and adjust the visibility condition to check nonPulseRuns.length instead of
comparing runs.length to pulseRuns.length; reference symbols: isLoading, error,
pulseRuns, runs, nonPulseRuns (new), TaskRunsTable, AccountDetailPage.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@types/sandbox.ts`:
- Line 26: Import the AccountRepo type into
components/SandboxOrgs/sandboxOrgsColumns.tsx and update the sorting/value
extraction to use the correct type: replace getValue<string[]>("account_repos")
with getValue<AccountRepo[]>("account_repos") (or otherwise annotate the column
accessor as AccountRepo[]), and ensure any downstream code that assumes strings
handles AccountRepo objects (e.g., accessing repo name via the appropriate
property). This touches the column definition / sorting function that references
account_repos and the file-level imports—add AccountRepo to the import list and
update the type parameter in the sorting/getValue call.

---

Nitpick comments:
In `@components/AccountDetail/AccountDetailPage.tsx`:
- Around line 82-93: The collapsible "All task runs" currently renders the full
runs list including pulseRuns, causing duplication; update AccountDetailPage to
compute a nonPulseRuns array (e.g., filter runs by excluding IDs present in
pulseRuns) and use that for the collapsible section's header count and
TaskRunsTable render, and adjust the visibility condition to check
nonPulseRuns.length instead of comparing runs.length to pulseRuns.length;
reference symbols: isLoading, error, pulseRuns, runs, nonPulseRuns (new),
TaskRunsTable, AccountDetailPage.

In `@lib/recoup/fetchAccountTaskRuns.ts`:
- Around line 22-24: Add a timeout using AbortController around the fetch in
fetchAccountTaskRuns: create an AbortController, start a setTimeout that calls
controller.abort() after a chosen timeout (e.g., 10s), pass controller.signal to
fetch(url.toString(), { headers: { Authorization: `Bearer ${accessToken}` },
signal }), and clear the timeout after fetch completes to avoid leaks; handle
AbortError/timeout appropriately where res is used.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 711b8ad5-dc7e-42a4-9705-0a693c2d97e9

📥 Commits

Reviewing files that changed from the base of the PR and between 6018454 and 7690751.

📒 Files selected for processing (8)
  • app/accounts/[account_id]/page.tsx
  • components/AccountDetail/AccountDetailPage.tsx
  • components/AccountDetail/TaskRunsTable.tsx
  • components/SandboxOrgs/AccountReposList.tsx
  • components/Sandboxes/sandboxesColumns.tsx
  • hooks/useAccountTaskRuns.ts
  • lib/recoup/fetchAccountTaskRuns.ts
  • types/sandbox.ts

earliest_committed_at: string;
latest_committed_at: string;
account_repos: string[];
account_repos: AccountRepo[];
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify the stale type assertion in sandboxOrgsColumns.tsx
rg -n "getValue<string\[\]>.*account_repos" --type ts

Repository: recoupable/admin

Length of output: 303


🏁 Script executed:

# Check the type definition in types/sandbox.ts around line 26
sed -n '20,30p' types/sandbox.ts

Repository: recoupable/admin

Length of output: 335


🏁 Script executed:

# Check the imports in sandboxOrgsColumns.tsx to see if AccountRepo is imported
head -30 components/SandboxOrgs/sandboxOrgsColumns.tsx | grep -E "import|from"

Repository: recoupable/admin

Length of output: 378


🏁 Script executed:

# Search for any other getValue calls with account_repos to ensure we catch all instances
rg -n "getValue.*account_repos" components/SandboxOrgs/sandboxOrgsColumns.tsx

Repository: recoupable/admin

Length of output: 285


Add AccountRepo import and update type annotations in sorting function.

The account_repos field changed from string[] to AccountRepo[] in types/sandbox.ts. The sorting function in components/SandboxOrgs/sandboxOrgsColumns.tsx (lines 50-51) still uses the incorrect getValue<string[]>("account_repos") type. Additionally, AccountRepo is not imported in this file.

Update the import statement and the sorting function:

Required changes in sandboxOrgsColumns.tsx
-import type { OrgRepoRow } from "@/types/sandbox";
+import type { OrgRepoRow, AccountRepo } from "@/types/sandbox";
     sortingFn: (rowA, rowB) => {
-      const a = (rowA.getValue<string[]>("account_repos") ?? []).length;
-      const b = (rowB.getValue<string[]>("account_repos") ?? []).length;
+      const a = (rowA.getValue<AccountRepo[]>("account_repos") ?? []).length;
+      const b = (rowB.getValue<AccountRepo[]>("account_repos") ?? []).length;
       return a - b;
     },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@types/sandbox.ts` at line 26, Import the AccountRepo type into
components/SandboxOrgs/sandboxOrgsColumns.tsx and update the sorting/value
extraction to use the correct type: replace getValue<string[]>("account_repos")
with getValue<AccountRepo[]>("account_repos") (or otherwise annotate the column
accessor as AccountRepo[]), and ensure any downstream code that assumes strings
handles AccountRepo objects (e.g., accessing repo name via the appropriate
property). This touches the column definition / sorting function that references
account_repos and the file-level imports—add AccountRepo to the import list and
update the type parameter in the sorting/getValue call.

SRP: move getStatusBadgeColor and formatRunDuration to lib/tasks/
so TaskRunsTable only handles rendering.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
SRP: move breadcrumb rendering out of AccountDetailPage.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment on lines +44 to +48
{isLoading && (
<div className="py-12 text-center text-sm text-gray-500 dark:text-gray-400">
Loading task runs…
</div>
)}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

DRY / SRP

  • actual: defining loading text in Page component
  • required: use existing skeleton components instead of loading text

if (runs.length === 0) {
return (
<p className="text-sm text-gray-500 dark:text-gray-400 py-8 text-center">
No task runs found for this account.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

False positive

  • actual: on initial page land, I see this error message instead of the loading skeleton.
  • required: on initial page load, I see the skeleton. This message should only appear if the query has run.

title={repo_url}
>
{name}
{repoName}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

remove repo name. we only want to see the emails.

1. Use existing TableSkeleton instead of loading text
2. Return null for empty runs to prevent false positive on initial load
3. Remove repo name from AccountReposList, only show emails

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant