feat: add AgencyZoom plugin with 99 operations - #369
Conversation
|
@Ayush7614 is attempting to deploy a commit to the corsair Team on Vercel. A member of the Team first needs to authorize it. |
Greptile SummaryThis PR adds the
Confidence Score: 5/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant Caller as Host App
participant Plugin as agencyzoom plugin
participant Factory as executeAgencyZoomOperation
participant Cache as syncAgencyZoomOperationCache
participant Client as makeAgencyZoomRequest
participant API as AgencyZoom API
Caller->>Plugin: endpoint.leads.createLead(ctx, input)
Plugin->>Factory: executeAgencyZoomOperation(ctx, input, route)
Factory->>Factory: check route.requiresAuth + ctx.key
Factory->>Client: "makeAgencyZoomRequest(path, apiKey, {method,body,query,headers})"
Client->>API: "POST /leads/create { Bearer JWT }"
API-->>Client: "201 { id, ... }"
Client-->>Factory: response
Factory->>Cache: syncAgencyZoomOperationCache(ctx, route, input, response)
Note over Cache: GROUP_CACHE_RULES["leads"] matched
Cache->>Cache: cacheItems() → upsertByEntityId(id, item)
Cache-->>Factory: done
Factory->>Factory: logAgencyZoomOperation(ctx, input, route, "completed")
Factory-->>Caller: response
Note over Factory,API: On error: status="failed", cache skipped, error rethrown
Note over Factory,API: requiresAuth:false routes (login/SSO) skip JWT check
Reviews (12): Last reviewed commit: "docs: note updateTask taskId stays in re..." | Re-trigger Greptile |
1 similar comment
Implements the AgencyZoom insurance CRM integration with JWT bearer auth, OpenAPI-mapped routes across leads, customers, opportunities, tasks, and reference data. Closes corsairdev#368.
Log failed operations with 'failed' status, add type assertion and unknown-field comments, and consolidate shared Zod schemas for dynamic AgencyZoom payload fields.
Cache leads, customers, and tasks via ctx.db upserts; rename endpoint files to kebab-case; remove generator script.
Correct risk labels, keep Authorization authoritative, disable 5xx retries on mutations, and let search filters pass through schemas.
7800f71 to
c15626b
Compare
|
Warning Review limit reached
Next review available in: 6 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (6)
📝 WalkthroughWalkthroughThe pull request adds an AgencyZoom Corsair plugin with 99 routed operations, typed schemas, API-key and JWT handling, cache synchronization, error classification, package configuration, provider registration, and integration tests. ChangesAgencyZoom integration
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
Suggested labels: Suggested reviewers: Sequence Diagram(s)sequenceDiagram
participant CorsairEndpoint
participant executeAgencyZoomOperation
participant makeAgencyZoomRequest
participant AgencyZoomAPI
participant AgencyZoomCache
CorsairEndpoint->>executeAgencyZoomOperation: Submit route and input
executeAgencyZoomOperation->>makeAgencyZoomRequest: Resolve path, query, body, and API key
makeAgencyZoomRequest->>AgencyZoomAPI: Send authenticated request
AgencyZoomAPI-->>makeAgencyZoomRequest: Return response or error
makeAgencyZoomRequest-->>executeAgencyZoomOperation: Return operation result
executeAgencyZoomOperation->>AgencyZoomCache: Synchronize cached entities
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
Comment |
Keep R1 scope to plugin + constants + lockfile; satisfy CI format.
Plugin PR scorecard —
|
| Check | Status | Notes |
|---|---|---|
| R1 — Scope: plugin files only | ✅ | |
| R2 — Tests with assertions | ✅ | |
| R3 — Description complete | ✅ | |
| R3 — Linked issue / claim | ✅ | |
| R4 — Demo video / recording | ✅ |
Rules: PLUGIN_PR_RULES.md · re-runs on every push
|
Hey @Ayush7614, thanks for the contribution! 🏴☠️ Before a maintainer reviews, please fix the items below — the review re-runs automatically on your next push. Must fix
Optional improvements (P2)
Rule Used: What: Type assertions in the plugins folder must b... (source) Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Rule Used: What: All uses of Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Rule Used: What: All uses of Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time! If anything remains after your next push, a bot commit will clean it up; a maintainer always does the final review and merge. |
Assert method/URL for deletes Greptile flagged so miswired paths fail CI.
|
@greptile review |
|
Remaining findings are being fixed by a bot commit — it will be re-reviewed automatically. |
Point getAListOfRecycleEvents at /leads/{leadId}/recycle-events and
evict task cache for POST destructive deletes like batchDeleteTask.
|
@greptile review |
Maintainer review neededAutomated rounds are exhausted. Remaining findings:
The only working path today is to use the explicit body-override field: Rule Used: Every endpoint must validate inputs and outputs wi... (source)
Rule Used: Every endpoint must validate inputs and outputs wi... (source) |
Allow login/SSO without a prior JWT, omit Bearer when empty, and map concrete Zod responses for auth/leads/customers/tasks/opportunities.
|
@greptile review |
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Match AgencyZoom wire-case firstname/lastname and reject empty batchCreateLead payloads missing leadDataRequests.
… into feat/agencyzoom-plugin
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (3)
packages/agencyzoom/endpoints/types.ts (2)
1794-1797: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd a compile-time check that both registries cover every route key.
AgencyZoomEndpointInputSchemasandAgencyZoomEndpointOutputSchemasare plain object literals.packages/agencyzoom/endpoints/index.tsindexes them byroute.keyat Lines 54-55. If a route is added toagencyZoomRouteswithout a matching schema entry, the lookup returnsundefinedat runtime instead of failing the build.Add a
satisfiesconstraint keyed off the route union to catch this at compile time.♻️ Proposed guard
+import type { AgencyZoomRoutes } from './routes'; + +type AgencyZoomRouteKey = AgencyZoomRoutes[number]['key']; + export const AgencyZoomEndpointInputSchemas = { authenticateForJwtviaV4Sso: AuthenticateForJwtviaV4SsoInputSchema, -} as const; +} as const satisfies Record<AgencyZoomRouteKey, z.ZodType>;Apply the same
satisfiesclause toAgencyZoomEndpointOutputSchemas.Also applies to: 1905-1908
🤖 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 `@packages/agencyzoom/endpoints/types.ts` around lines 1794 - 1797, Update the AgencyZoomEndpointInputSchemas and AgencyZoomEndpointOutputSchemas registry declarations to use a satisfies constraint keyed by the agencyZoomRoutes route-key union, ensuring every route key has a corresponding schema entry while preserving the existing schema values and inferred types.
1226-1232: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueReplace
.passthrough()with.loose()for consistency with Zod 4.Every other object schema in this file uses
.loose()(Lines 17, 33, 42, 55, 68, 80, 88). This schema uses.passthrough(). Zod 4 treats.passthrough()as a deprecated alias of the loose mode. Use one API across the file.♻️ Proposed change
const AgencyZoomSearchInputSchema = z .object({ body: AgencyZoomOptionalBodySchema, query: AgencyZoomQueryParamsSchema, headers: z.record(z.string(), z.string()).optional(), }) - .passthrough(); + .loose();Run the following check to confirm the declared Zod version and to find other
.passthrough()uses in the package:#!/bin/bash # Description: Confirm the Zod version and locate deprecated .passthrough() usage. set -euo pipefail fd -t f 'package.json' packages/agencyzoom --exec jq '{deps: .dependencies, peer: .peerDependencies, dev: .devDependencies}' {} echo '--- passthrough vs loose usage ---' rg -n --type=ts '\.passthrough\(\)|\.loose\(\)' packages/agencyzoom🤖 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 `@packages/agencyzoom/endpoints/types.ts` around lines 1226 - 1232, Update AgencyZoomSearchInputSchema to use Zod 4’s .loose() instead of .passthrough(), matching the object schemas throughout the file while preserving the schema’s handling of unknown fields.packages/agencyzoom/endpoints/routes.ts (1)
904-914: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider labeling POST search operations as
read.
searchCustomers,searchLeads, andsearchTasksonly retrieve data. They use POST because AgencyZoom accepts filters in the body. The catalog assignsriskLevel: 'write'to them. The same file assignsriskLevel: 'read'totextDetailThreadat Line 1009, which is also a POST retrieval. The classification is therefore inconsistent.Risk labels gate agent confirmation prompts. A
writelabel on a pure read forces unnecessary approvals. The same applies tosearchEmailThreads,searchSmsThreads,searchLeadsCount,searchLifeAndHealthLeads,searchBusinessClassifications,serviceTicketList,getThreadDetails, andgetLeadFiles.If the project intends to label every POST as
write, thentextDetailThreadneeds the same label for consistency.Also applies to: 928-938, 976-986
🤖 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 `@packages/agencyzoom/endpoints/routes.ts` around lines 904 - 914, Update the riskLevel classification for the POST-based retrieval operations searchCustomers, searchLeads, and searchTasks from write to read, and apply the same read classification to the other listed read-only operations: searchEmailThreads, searchSmsThreads, searchLeadsCount, searchLifeAndHealthLeads, searchBusinessClassifications, serviceTicketList, getThreadDetails, and getLeadFiles. Preserve write labels only for operations that mutate data.
🤖 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 `@packages/agencyzoom/client.ts`:
- Around line 45-50: Update the header construction in the client request flow
to remove caller-provided Content-Type and Authorization entries using
case-insensitive matching before spreading or adding plugin-owned headers.
Preserve all unrelated caller headers, then add the plugin’s JSON Content-Type
and conditional Bearer Authorization values so no differently cased reserved
header remains.
In `@packages/agencyzoom/endpoints/cache-sync.ts`:
- Around line 119-123: Update the delete path in the cache-sync handler around
cacheDeleteEntityIds and client.deleteByEntityId to normalize the explicit
input.body into the identifier lookup before iterating. Ensure requests using
body fields such as taskIds resolve their destructive identifiers and delete the
corresponding local cache entries.
In `@packages/agencyzoom/endpoints/factory.ts`:
- Around line 93-109: Update requestBody to exclude all path-parameter aliases
in addition to canonical names: for each entry in route.pathParams, add
camelToSnake(pathParam) and PATH_PARAM_ALIASES[pathParam] to the excluded path
parameter set before filtering input fields. Preserve the existing
query-parameter, control-key, and undefined-value filtering.
In `@packages/agencyzoom/endpoints/routes.ts`:
- Around line 843-853: Swap the descriptions for markThreadAsUnreadApiEndpoint
and unreadThread so each matches its route: the /email-thread/unread-thread
endpoint must describe marking an email thread, while /text-thread/unread-thread
must describe marking a text thread. Preserve the existing behavior and other
route metadata.
In `@packages/agencyzoom/schema/database.ts`:
- Around line 3-20: Align the cache schemas in
packages/agencyzoom/schema/database.ts with their API counterparts: in
AgencyZoomLead and AgencyZoomCustomer (lines 3-20), rename firstName and
lastName to firstname and lastname; in AgencyZoomTask (lines 22-29), widen
status to accept strings or numbers, matching AgencyZoomLeadSchema,
AgencyZoomCustomerSchema, and AgencyZoomTaskSchema in
packages/agencyzoom/endpoints/types.ts.
---
Nitpick comments:
In `@packages/agencyzoom/endpoints/routes.ts`:
- Around line 904-914: Update the riskLevel classification for the POST-based
retrieval operations searchCustomers, searchLeads, and searchTasks from write to
read, and apply the same read classification to the other listed read-only
operations: searchEmailThreads, searchSmsThreads, searchLeadsCount,
searchLifeAndHealthLeads, searchBusinessClassifications, serviceTicketList,
getThreadDetails, and getLeadFiles. Preserve write labels only for operations
that mutate data.
In `@packages/agencyzoom/endpoints/types.ts`:
- Around line 1794-1797: Update the AgencyZoomEndpointInputSchemas and
AgencyZoomEndpointOutputSchemas registry declarations to use a satisfies
constraint keyed by the agencyZoomRoutes route-key union, ensuring every route
key has a corresponding schema entry while preserving the existing schema values
and inferred types.
- Around line 1226-1232: Update AgencyZoomSearchInputSchema to use Zod 4’s
.loose() instead of .passthrough(), matching the object schemas throughout the
file while preserving the schema’s handling of unknown fields.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 82433ea1-8392-452f-ab1b-e9f1266156b6
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (30)
packages/agencyzoom/api.test.tspackages/agencyzoom/client.tspackages/agencyzoom/endpoints/auth.tspackages/agencyzoom/endpoints/cache-sync.tspackages/agencyzoom/endpoints/contact.tspackages/agencyzoom/endpoints/customers.tspackages/agencyzoom/endpoints/email-threads.tspackages/agencyzoom/endpoints/factory.tspackages/agencyzoom/endpoints/index.tspackages/agencyzoom/endpoints/leads.tspackages/agencyzoom/endpoints/life.tspackages/agencyzoom/endpoints/opportunities.tspackages/agencyzoom/endpoints/policies.tspackages/agencyzoom/endpoints/profile.tspackages/agencyzoom/endpoints/reference-data.tspackages/agencyzoom/endpoints/routes.tspackages/agencyzoom/endpoints/service-tickets.tspackages/agencyzoom/endpoints/tasks.tspackages/agencyzoom/endpoints/text-threads.tspackages/agencyzoom/endpoints/types.tspackages/agencyzoom/endpoints/v4sso.tspackages/agencyzoom/error-handlers.tspackages/agencyzoom/index.tspackages/agencyzoom/jest.config.jsonpackages/agencyzoom/package.jsonpackages/agencyzoom/schema/database.tspackages/agencyzoom/schema/index.tspackages/agencyzoom/tsconfig.jsonpackages/agencyzoom/tsup.config.tspackages/corsair/core/constants.ts
|
@greptile review |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/agencyzoom/api.test.ts (1)
76-86: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winAssert the non-empty
leadDataRequestscontract.The test rejects only
{}. It does not verify that{ leadDataRequests: [] }is rejected. Add that assertion to prevent a regression that accepts empty batch requests.🤖 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 `@packages/agencyzoom/api.test.ts` around lines 76 - 86, Extend the test for the leads.batchCreateLead input schema to assert that parsing { leadDataRequests: [] } throws, while preserving the existing missing-field rejection and valid non-empty request assertion.
🤖 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 `@packages/agencyzoom/api.test.ts`:
- Around line 76-86: Extend the test for the leads.batchCreateLead input schema
to assert that parsing { leadDataRequests: [] } throws, while preserving the
existing missing-field rejection and valid non-empty request assertion.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 3575bdc8-5b51-436e-a0b9-7a0258999e14
📒 Files selected for processing (2)
packages/agencyzoom/api.test.tspackages/agencyzoom/schema/database.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/agencyzoom/schema/database.ts
|
@greptile review |
|
@greptile review |
Description
Adds
@corsair-dev/agencyzoomwith all 99 AgencyZoom catalog operations over JWT bearer auth (api_key).Covers leads, customers, opportunities, tasks, email/SMS threads, policies, reference data, and V4 SSO/auth. Includes Zod schemas, error handlers, selective DB cache for leads/customers/tasks, and Jest coverage for plugin shape, auth headers, route mapping, and risk labels.
Claimed integration: https://corsair.dev/oss/agencyzoom
Closes #368
Checklist
pnpm lintand all checks passpnpm typecheckand there are no TypeScript errorspnpm buildand all packages build successfullypnpm testand all tests passScreenshots / Demos
Additional Notes
Auth: user-supplied JWT from
POST /auth/loginor V4 SSO.Summary by CodeRabbit
New Features
Tests