Deploy-to-Agent-Relay button + restore intended agent resilience#3
Conversation
…dge (preview) - assets/deploy-button.svg: rounded CTA matching banner.svg aesthetic (brand-blue gradient echoing the logo-mark colors, white→#C9DDEE wordmark-gradient label, Sora-first font stack, soft halo glow). The glyph is the Agent Workforce logo mark lifted from banner.svg, recolored to light tones for contrast on the blue button. Vector, ~2.4KB, renders on light + dark GitHub backgrounds. - granola/README.md: badge under the title linking to https://agentrelay.com/cloud/deploy?agent=granola Preview-first: granola only. Roll to the other 5 agents + top README pending design/URL sign-off. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
These robustness changes were described in 090833b's commit message but never actually staged (that commit only touched granola/linear/review). Restoring the intended behavior: - hn-monitor, vendor-monitor: try/catch around fetch so a transient outage returns [] / undefined instead of crashing the run. - spotify-releases: fetch each artist's releases in parallel via Promise.allSettled so one failing artist doesn't sink the whole check. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request introduces a new deploy button asset, adds a deployment badge to the Granola Agent README, and enhances the resilience of several background monitor agents (Hacker News, Spotify, and npm registry) by wrapping network calls in try/catch blocks to prevent transient failures from crashing the runs. Feedback on these changes highlights potential rate-limiting issues with parallelizing Spotify API requests, and suggests logging swallowed errors in the Hacker News and npm registry monitors to aid in future troubleshooting.
| // Fetch every artist's releases in parallel; one failing artist shouldn't | ||
| // sink the whole check. | ||
| const perArtist = await Promise.allSettled( | ||
| artists.map((artist) => latestReleases(token, artist)) | ||
| ); | ||
| const releases = perArtist.flatMap((r) => (r.status === 'fulfilled' ? r.value : [])).filter((rel) => rel.date > since); |
There was a problem hiding this comment.
Executing up to 50 concurrent requests to the Spotify API in parallel via Promise.allSettled can easily trigger rate limits (HTTP 429) or socket exhaustion. Since this is a background cron job, running the requests sequentially with a try/catch block is safer, avoids rate limiting, and still ensures that one failing artist does not sink the entire run.
// Fetch every artist's releases sequentially with try/catch to prevent rate limiting
// and ensure one failing artist doesn't sink the whole check.
const releases: Release[] = [];
for (const artist of artists) {
try {
const artistReleases = await latestReleases(token, artist);
releases.push(...artistReleases.filter((rel) => rel.date > since));
} catch {
// Skip failing artist
}
}| if (!res.ok) return []; | ||
| const data = (await res.json()) as { hits: Array<{ objectID: string; title: string; url: string | null; points: number }> }; | ||
| return data.hits.map((h) => ({ | ||
| id: Number(h.objectID), | ||
| title: h.title, | ||
| url: h.url ?? `https://news.ycombinator.com/item?id=${h.objectID}`, | ||
| points: h.points | ||
| })); | ||
| } catch { | ||
| return []; | ||
| } |
There was a problem hiding this comment.
Swallowing all network and parsing errors silently makes troubleshooting and debugging extremely difficult when the API is down or its response structure changes. Logging the errors to console.error provides visibility into failures without crashing the run.
| if (!res.ok) return []; | |
| const data = (await res.json()) as { hits: Array<{ objectID: string; title: string; url: string | null; points: number }> }; | |
| return data.hits.map((h) => ({ | |
| id: Number(h.objectID), | |
| title: h.title, | |
| url: h.url ?? `https://news.ycombinator.com/item?id=${h.objectID}`, | |
| points: h.points | |
| })); | |
| } catch { | |
| return []; | |
| } | |
| if (!res.ok) { | |
| console.error(`HN API returned status ${res.status}`); | |
| return []; | |
| } | |
| const data = (await res.json()) as { hits: Array<{ objectID: string; title: string; url: string | null; points: number }> }; | |
| return data.hits.map((h) => ({ | |
| id: Number(h.objectID), | |
| title: h.title, | |
| url: h.url ?? `https://news.ycombinator.com/item?id=${h.objectID}`, | |
| points: h.points | |
| })); | |
| } catch (error) { | |
| console.error('Error fetching HN front page:', error); | |
| return []; | |
| } |
| } catch { | ||
| return undefined; | ||
| } |
There was a problem hiding this comment.
Swallowing all network and parsing errors silently makes troubleshooting and debugging extremely difficult when the API is down or its response structure changes. Logging the errors to console.error provides visibility into failures without crashing the run.
} catch (error) {
console.error(`Error fetching latest version for ${pkg}:`, error);
return undefined;
}
📝 WalkthroughWalkthroughThis PR improves resilience across three monitoring agents and updates deployment documentation. HN monitor and vendor monitor now catch external service failures and return safe defaults instead of propagating errors. Spotify monitor switches to parallel per-artist fetching via ChangesAgent Resilience and Documentation
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (3)
hn-monitor/agent.ts (1)
41-56: ⚡ Quick winDon’t swallow HN fetch failures silently.
Returning
[]is good for resilience, but at Line 54 this hides operational failures as normal “no news” runs. Emit a warning before fallback.Proposed patch
- const stories = await fetchFrontPage(); + const stories = await fetchFrontPage((error) => + ctx.log('warn', 'hn-monitor.fetch-front-page-failed', { error: String(error) }) + ); -async function fetchFrontPage(): Promise<Story[]> { +async function fetchFrontPage(onError?: (error: unknown) => void): Promise<Story[]> { try { const res = await fetch('https://hn.algolia.com/api/v1/search?tags=front_page&hitsPerPage=30'); if (!res.ok) return []; @@ - } catch { + } catch (error) { + onError?.(error); return []; } }🤖 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 `@hn-monitor/agent.ts` around lines 41 - 56, The fetchFrontPage function currently swallows failures and returns [] without any visibility; update fetchFrontPage to log a warning when the fetch fails or when res.ok is false—include the HTTP status and statusText for non-ok responses and include the caught error (message/stack) in the catch handler so operational failures are visible; reference the fetchFrontPage function, the res.ok check, and the catch block when adding the logging call (use the project logger if available or console.warn).spotify-releases/agent.ts (1)
30-35: ⚡ Quick winLog partial Spotify failures for run visibility.
At Lines 32-35, rejected artist fetches are dropped silently. Add a warning count so degraded runs are observable.
Proposed patch
const perArtist = await Promise.allSettled( artists.map((artist) => latestReleases(token, artist)) ); + const failedArtists = perArtist.filter((r) => r.status === 'rejected').length; + if (failedArtists > 0) { + ctx.log('warn', 'spotify-releases.partial-fetch-failure', { + failedArtists, + totalArtists: artists.length + }); + } const releases = perArtist.flatMap((r) => (r.status === 'fulfilled' ? r.value : [])).filter((rel) => rel.date > since);🤖 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 `@spotify-releases/agent.ts` around lines 30 - 35, The code currently drops rejected Promise results from perArtist silently; after awaiting Promise.allSettled(artists.map(...)) compute the number of failures by counting entries where status === 'rejected' and emit a warning (e.g., via the module's logger or console.warn) reporting that count and brief context so degraded runs are visible; keep building releases as before from fulfilled results (perArtist.flatMap(...)... filter(...)) but ensure the warning references perArtist and latestReleases so reviewers can find where to add the log.vendor-monitor/agent.ts (1)
38-47: ⚡ Quick winPreserve fallback, but emit warning on registry fetch exceptions.
Line 45 currently returns
undefinedsilently; add a warning so repeated npm/API outages are diagnosable.Proposed patch
- const version = await latestVersion(pkg); + const version = await latestVersion(ctx, pkg); -async function latestVersion(pkg: string): Promise<string | undefined> { +async function latestVersion(ctx: WorkforceCtx, pkg: string): Promise<string | undefined> { try { const res = await fetch(`https://registry.npmjs.org/${encodeURIComponent(pkg)}/latest`); if (!res.ok) return undefined; return ((await res.json()) as { version?: string }).version; - } catch { + } catch (error) { + ctx.log('warn', 'vendor-monitor.latest-version-fetch-failed', { pkg, error: String(error) }); return undefined; } }🤖 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 `@vendor-monitor/agent.ts` around lines 38 - 47, The latestVersion function currently swallows network/JSON errors; keep returning undefined on failure but log a warning with the package name and the error so outages are diagnosable. In the latestVersion function's catch block, change it to catch the thrown error (e.g. catch (err)) and call a warning logger (console.warn or an existing logger) with a descriptive message including pkg and err, then return undefined; leave the existing res.ok early-return behavior unchanged.
🤖 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 `@hn-monitor/agent.ts`:
- Around line 41-56: The fetchFrontPage function currently swallows failures and
returns [] without any visibility; update fetchFrontPage to log a warning when
the fetch fails or when res.ok is false—include the HTTP status and statusText
for non-ok responses and include the caught error (message/stack) in the catch
handler so operational failures are visible; reference the fetchFrontPage
function, the res.ok check, and the catch block when adding the logging call
(use the project logger if available or console.warn).
In `@spotify-releases/agent.ts`:
- Around line 30-35: The code currently drops rejected Promise results from
perArtist silently; after awaiting Promise.allSettled(artists.map(...)) compute
the number of failures by counting entries where status === 'rejected' and emit
a warning (e.g., via the module's logger or console.warn) reporting that count
and brief context so degraded runs are visible; keep building releases as before
from fulfilled results (perArtist.flatMap(...)... filter(...)) but ensure the
warning references perArtist and latestReleases so reviewers can find where to
add the log.
In `@vendor-monitor/agent.ts`:
- Around line 38-47: The latestVersion function currently swallows network/JSON
errors; keep returning undefined on failure but log a warning with the package
name and the error so outages are diagnosable. In the latestVersion function's
catch block, change it to catch the thrown error (e.g. catch (err)) and call a
warning logger (console.warn or an existing logger) with a descriptive message
including pkg and err, then return undefined; leave the existing res.ok
early-return behavior unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: a52bf931-6d2b-463e-b753-95a651a2f2ab
⛔ Files ignored due to path filters (1)
assets/deploy-button.svgis excluded by!**/*.svg
📒 Files selected for processing (4)
granola/README.mdhn-monitor/agent.tsspotify-releases/agent.tsvendor-monitor/agent.ts
Replace assets/deploy-button.svg with the canonical "Launch Agent" badge from https://agentrelay.com/launch-agent.svg (renamed to launch-agent.svg) and update the granola badge label/path to match. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reference https://agentrelay.com/launch-agent.svg directly so the badge tracks the canonical hosted asset; drop the local copy. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
All six agents now carry the hosted Launch Agent badge linking to their respective cloud deploy URL (?agent=<name>), matching granola. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Brings this branch up to date with
mainand lands two changes on top:assets/deploy-button.svg(branded "Deploy to Agent Relay" CTA matching the banner aesthetic) and a badge under the granola title linking to the cloud deploy URL. Preview-first on granola; remaining agents + top-level README pending design/URL sign-off.main's commit090833bdescribes adding fetch resilience tohn-monitor,vendor-monitor, andspotify-releases, but that commit only actually touched granola/linear/review — the changes were never staged. This restores them:hn-monitor,vendor-monitor:try/catcharoundfetchso a transient outage returns[]/undefinedinstead of crashing the run.spotify-releases: fetch each artist's releases in parallel viaPromise.allSettledso one failing artist doesn't sink the whole check.Net diff vs
mainTesting
npx tsc --noEmitpasses.🤖 Generated with Claude Code
Summary by cubic
Adds a hosted “Launch Agent” badge to all agent READMEs with one-click deploy links. Restores resilience in
hn-monitor,vendor-monitor, andspotify-releasesso transient errors don’t crash runs.New Features
granola,hn-monitor,linear,review,spotify-releases,vendor-monitor), linking to https://agentrelay.com/cloud/deploy?agent= and using https://agentrelay.com/launch-agent.svg.Bug Fixes
hn-monitor: wrap front-page fetch; return[]on failure.vendor-monitor: guard npm latest fetch; returnundefinedon failure.spotify-releases: fetch per-artist releases withPromise.allSettled; skip failures.Written for commit 5ba0e80. Summary will update on new commits. Review in cubic