Repository navigation
Conversation
Co-authored-by: Cursor <cursoragent@cursor.com>
🦋 Changeset detectedLatest commit: 748deb2 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Qodex review(no summary) Effort: ●●●○○ (3/5) · No findings worth raising. The diff reads clean. Since last review: 0 addressed, 0 new. Scope: the changes since the last review (delta: only what changed since the previously reviewed commit 25c2026 is reviewed; findings are anchored on the whole change). WalkthroughWhat Qodex checkedLenses (openqodex review with checked answers, all dimensions)
Scanners
Quality filters
Verification (M1b probes against PR preview)
Cross-review dedup
Output
Reviewer: 0 tool calls served, 0 model calls, 0 correction rounds, 0.0s. The library does not report tool calls asked apart from those it served, or a step cap. Every dimension is reviewed. Bugs, security, and performance post inline; low-severity style and convention notes are collected in the group above rather than dropped. Mark a finding resolved or flag a false positive in the Qodex Pull Requests view. |
| this.#client = new ZepClient({ | ||
| apiKey: options.apiKey, | ||
| baseUrl: options.baseUrl.replace(/\/+$/, ''), | ||
| timeoutInSeconds: DEFAULT_TIMEOUT_SECONDS, |
There was a problem hiding this comment.
Medium: Preserve the response-body deadline
In SDK 4.1.0, makeRequest() clears its timeout after headers arrive, before getResponseBody() reads the body, so timeoutInSeconds does not preserve the removed AbortSignal.timeout protection against trickling responses. (raw.githubusercontent.com) Pass a separate deadline through the SDK's abortSignal option that remains active until body consumption completes, combined with caller cancellation where supplied; otherwise one unfinished ingestion request blocks the sequential ingestion pass for subsequent tenants.
PR overviewThe PR switches the Zep memory provider to use Zep’s official SDK for API calls, including ingestion requests. One issue remains open: the SDK timeout ends when response headers arrive, leaving response-body consumption without the previous deadline protection. A slow or trickling response could therefore keep an ingestion request pending indefinitely; a separate deadline covering body consumption is still needed. No issues have been addressed yet. Open issues (1)
Fixed/addressed: 0 · PR risk: 4/10 |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 99f38f9. Configure here.
| if (listed.status === 404) { | ||
| return false; | ||
| } | ||
| return ZepMessagesResponseSchema.parse(listed.body).items.some( |
There was a problem hiding this comment.
Search crashes on null facts
Low Severity
Edge search no longer treats a null fact as empty. The old response schema allowed nullish facts and skipped them; calling trim() on null now throws and fails the whole search instead of returning the remaining facts.
Reviewed by Cursor Bugbot for commit 99f38f9. Configure here.
There was a problem hiding this comment.
The SDK deserializes a null fact to undefined (checked: {"fact": null} parses to {}), which the edge.fact === undefined guard already skips.


Summary
Moves every Zep call in the memory provider from hand-written HTTP requests to the official Zep SDK (
@getzep/zep-cloud4.1.0), so we no longer define or maintain Zep's request and response types ourselves.Fixes AGE-2737
Changes
ZepMemoryProvidernow uses the SDK's typed methods for user lookup/create/node, thread create, add/list messages, edge search and episode add.Retry-Afterparsing) and the manual idempotency key; the SDK sends one key per call and reuses it across retries.#callwrapper keeps per-operation logs, maps SDK errors toZepRequestError(operation + status), and treats a 404 as "not found" where that's expected.Behaviour differences: network errors are no longer retried within a call (the SDK retries only on status codes; ingestion retries next run), the SDK may wait up to 60s on
Retry-After(was 30s), and failures are logged once per operation instead of once per attempt.How was this tested?
fetch: same paths,snake_casebodies andApi-Keyheader as beforememory_add, summary and search, and unknown users returning nothing instead of failingtscfor the server and unit tests (thetests/dbtypecheck has 4 pre-existing errors onmain)Checklist
.env.exampleupdated if configuration or behavior changed (no configuration change)Note
Medium Risk
Memory ingestion and retrieval now depend on the Zep SDK’s retry and error behaviour; idempotency for saved notes no longer uses our UUID header, and non-idempotent paths may fail faster without in-call network retries.
Overview
Replaces the hand-rolled Zep HTTP layer with
@getzep/zep-cloud, wiringZepMemoryProviderthroughZepClientfor users, threads, messages, graph search and episodes.Removes custom fetch wrappers, Zod response schemas, manual backoff/
Retry-Afterhandling and the explicit idempotency header on saved notes; adds a thin#callhelper for logging and mapping SDK/ZepErrorintoZepRequestError, with 404 treated as “missing” where appropriate.Behaviour shifts: message ingestion still uses a single SDK attempt (
maxRetries: 0) so duplicates aren’t risked; other calls rely on the SDK’s retries (408/429/5xx, up to three). Session-start summary and similar paths pin one attempt via options. Tests are reworked (fake timers for SDK backoff, stricter “no retry” expectations foradd_messages, dropped cases that only covered the old HTTP retry stack).Adds a changeset (patch) and lockfile entry for the new dependency.
Reviewed by Cursor Bugbot for commit 748deb2. Bugbot is set up for automated code reviews on this repo. Configure here.