Skip to content

feat(memory): add createSupermemoryClient factory#83

Merged
khaliqgant merged 2 commits intomainfrom
feat/memory-supermemory-client
May 5, 2026
Merged

feat(memory): add createSupermemoryClient factory#83
khaliqgant merged 2 commits intomainfrom
feat/memory-supermemory-client

Conversation

@khaliqgant
Copy link
Copy Markdown
Member

Summary

  • New createSupermemoryClient(options) factory in @agent-assistant/memory
  • Wraps the official supermemory SDK (v4.21.1) with the timeout / retry / fetch wiring sage shipped in PR #198
  • Worker-safe EnvSource shape (no NodeJS.ProcessEnv in public surface, no process access at the no-arg path)
  • Independent of AA feat(proactive): runFollowUpBatch + decidePostingPolicy + block-counter interface #82 — different package, different surface
  • 7 new tests; existing 77 memory tests still pass; build + types clean

Why

Sage shipped this factory locally at src/integrations/supermemory-client.ts in PR #198 to fix the prod SEARCH_ERROR outage. It centralises 4 call sites that previously had subtly different defaults for endpoint, timeout, retries, and fetch wiring. Moving it upstream so future AA consumers don't reimplement the same wrapper.

Surface

export type EnvSource = Readonly<Record<string, string | undefined>>;

export interface CreateSupermemoryClientOptions {
  timeoutMs?: number;        // default 8000
  maxRetries?: number;       // default 2
  env?: EnvSource;           // default: globalThis.process?.env ?? {}
  apiKeyEnvVar?: string;     // default 'SUPERMEMORY_API_KEY'
  endpointEnvVar?: string;   // default 'SUPERMEMORY_ENDPOINT'
  fetch?: typeof globalThis.fetch;
}

export function createSupermemoryClient(
  options?: CreateSupermemoryClientOptions,
): Supermemory | null;  // null when no API key

Design notes

  • Defaults from sage's prod-validated PR #198. timeout: 8s is the per-call cap that fixed the 2026-05-04 SEARCH_ERROR outage; maxRetries: 2 matches the SDK default but is surfaced explicitly so callers know 5xx retries are happening.
  • Per-call globalThis.fetch closure. The SDK captures fetch at construction; without the closure, vi.stubGlobal('fetch', ...) set after construction is invisible. The SDK already calls fetch.call(undefined, url, init) internally to dodge the Cloudflare Workers "Illegal invocation" foot-gun (sdk-ts/src/client.ts:594), so passing the closure is purely for test ergonomics.
  • Worker-safe public surface. Same shape as AA PR feat(proactive): runFollowUpBatch + decidePostingPolicy + block-counter interface #82's readFailOpenFromEnv fix: EnvSource instead of NodeJS.ProcessEnv, no-arg path reads globalThis.process?.env ?? {} so Workers without nodejs_compat get null (no API key) instead of a process is not defined ReferenceError.
  • Configurable env var names. apiKeyEnvVar / endpointEnvVar lets surfaces namespace their secrets (e.g. MY_APP_SUPERMEMORY_API_KEY). Defaults match the de-facto Supermemory conventions.
  • Returns null on missing key. Callers no-op cleanly during local dev without a separate env-presence check. Sage's existing call sites already handle this branch.

Test plan

  • cd packages/memory && npm test — 84/84 pass (77 existing + 7 new)
    • missing / blank API key returns null
    • present API key constructs an SDK instance
    • custom apiKeyEnvVar honored
    • fetch override threaded to SDK
    • default endpoint
    • SUPERMEMORY_ENDPOINT override
    • delete globalThis.process Worker simulation does not throw
  • npm run build clean
  • No NodeJS.ProcessEnv / node:process in dist/supermemory-client.d.ts public signatures (only docstring mentions explaining why)

Out of scope (follow-up)

  • Version bump — handled by separate chore(release) commit per the existing convention
  • Sage adoption — src/integrations/supermemory-client.ts becomes a thin re-export alias for one minor compat cycle, then deletes; staged at sage workflows/proactive-batch-runner/03-aa-memory.ts + 04-sage-adopt.ts

Sequence status

PR Repo Status
sage #200 sage ✅ Merged
AA #81 (boundedParallel) agent-assistant ✅ Merged → @agent-assistant/coordination@0.4.25
AA #82 (runFollowUpBatch + policy + counter) agent-assistant 🟡 Open (review fix landed)
This PR agent-assistant 🟡 Open (independent of #82)
sage #4 (adoption) sage ⏳ Blocks on AA #82 + this PR publishing

🤖 Generated with Claude Code

Extracted from sage's `src/integrations/supermemory-client.ts` (originally
sage PR #198) so every AA consumer that talks to Supermemory shares the
same endpoint, timeout, retry, and Worker-fetch wiring instead of
re-rolling their own copy. Sage previously had four call sites with
subtly different defaults; centralising removes that drift class for all
future consumers.

Wraps the official `supermemory` SDK (v4.21.1) with:
  - Default `timeout: 8s` (matches the per-call cap that fixed the
    2026-05-04 SEARCH_ERROR outage in prod — sage PR #198)
  - Default `maxRetries: 2` (SDK default, surfaced explicitly so it's
    obvious from the call site that 5xx retries happen transparently)
  - Per-call `globalThis.fetch` closure for the SDK's `fetch` option
    (keeps `vi.stubGlobal('fetch', ...)` working — SDK captures the
    reference at construction time otherwise)
  - Returns `null` when the API key env var is unset so callers no-op
    cleanly during local dev without an explicit env-presence check

Worker-safe (matches AA PR #82's same-day fix):
  - Public surface uses `EnvSource = Readonly<Record<string, string |
    undefined>>` instead of `NodeJS.ProcessEnv` so Worker-only TS
    projects can consume the .d.ts
  - No-arg / default env path falls back to `globalThis.process?.env ??
    {}` via a private helper so Cloudflare Workers without nodejs_compat
    don't ReferenceError at the no-arg call site

Configurable env var names (`apiKeyEnvVar`, `endpointEnvVar`) for
surfaces that namespace their secrets. Defaults match the de-facto
Supermemory conventions (SUPERMEMORY_API_KEY, SUPERMEMORY_ENDPOINT).

7 new tests: missing/blank API key, present API key constructs the
client, custom apiKeyEnvVar, fetch override threading, default endpoint,
SUPERMEMORY_ENDPOINT override, no-globalThis.process Worker simulation.
84/84 memory tests pass (77 existing + 7 new); build clean.

Sage adoption (PR #4 in the proactive-batch-runner sequence) replaces
its local `src/integrations/supermemory-client.ts` with this factory.
The local file may stay as a thin re-export alias for one minor cycle
to avoid breaking direct importers, then be deleted.

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5b01fb196a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

"dependencies": {
"@agent-relay/memory": "^6.0.9"
"@agent-relay/memory": "^6.0.9",
"supermemory": "^4.21.1"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Regenerate lockfile after adding supermemory dependency

Adding "supermemory": "^4.21.1" to packages/memory/package.json without the corresponding package-lock.json update breaks reproducible installs and can fail CI on a clean checkout. I checked the repo workflows and both .github/workflows/ci.yml and .github/workflows/publish.yml run npm ci, which requires the lockfile to match package manifests; this commit introduces a new runtime dependency but leaves the lockfile out of sync.

Useful? React with 👍 / 👎.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 5, 2026

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7d158c23-cb8b-4bd7-aac3-5cadd8cab422

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR introduces a new Supermemory SDK integration to the @agent-assistant/memory package by adding a factory function that constructs authenticated Supermemory clients from environment variables and optional configuration overrides, along with comprehensive test coverage and public API exports.

Changes

Supermemory SDK Integration

Layer / File(s) Summary
Configuration Types
packages/memory/src/supermemory-client.ts
New exports: EnvSource (readonly string/undefined record), CreateSupermemoryClientOptions interface with optional timeoutMs, maxRetries, env, apiKeyEnvVar, endpointEnvVar, and fetch fields.
Core Factory
packages/memory/src/supermemory-client.ts
createSupermemoryClient(options?) resolves API key and endpoint from injected or process env, returns null if API key is missing/blank, otherwise constructs and returns a Supermemory instance with configured timeout, retries, and fetch implementation.
Public API
packages/memory/src/index.ts
Re-exports createSupermemoryClient function and CreateSupermemoryClientOptions, EnvSource types from the new module.
Dependency Declaration
packages/memory/package.json
Runtime dependency supermemory@^4.21.1 added to support SDK instantiation.
Test Coverage
packages/memory/src/supermemory-client.test.ts
Seven Vitest tests verify: null return when API key is missing/whitespace, successful client construction with valid key, custom API key env var support, fetch override forwarding, default and custom endpoint handling, and safe operation in environments without globalThis.process.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 Supermemory now takes root,
with SDK clients dressed to boot,
Environment whispers, configs in flight,
Factory patterns holding tight!
Tests keep watch through day and night.

🚥 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 accurately and concisely describes the main change: adding a new createSupermemoryClient factory function to the memory package.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, explaining the factory's purpose, design decisions, test coverage, and implementation details.
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.

✏️ 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 feat/memory-supermemory-client

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

`npm ci` failed on PR #83 because adding `supermemory@^4.21.1` to
packages/memory/package.json without refreshing package-lock.json puts
the lockfile out of sync. Unlike PR #81 (no new deps) and PR #82
(internal workspace dep), this PR is the first in the series to add a
real npm-registry dependency, so the lock must update.

Diff is in two parts, both unavoidable:
  1. New `node_modules/supermemory@4.21.1` entry — what this PR needs.
  2. Workspace package versions sync from 0.4.23 → 0.4.25 — the recent
     release commits (2740310, 941a840) bumped the workspace
     package.json files but never refreshed the lockfile. `npm ci`
     refuses any out-of-sync state, so the sync has to land here even
     though it's incidental to this feature.

Verified locally with the same install path CI runs:
  - rm -rf node_modules
  - npm install (regenerates lock)
  - cd packages/memory && npm test (84/84 pass)
  - npm run build (clean)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@khaliqgant khaliqgant merged commit bed51c9 into main May 5, 2026
2 checks passed
@khaliqgant khaliqgant deleted the feat/memory-supermemory-client branch May 5, 2026 11:16
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