Skip to content
PluginStats

@gnldev/durable weekly downloads statistics

By gnldev (2 listings) · npm · AI SDKs

Call-scoped exactly-once effect + deterministic-replay durability layer for Vercel AI SDK agents. Drop-in: generateText -> runDurable.

View on npm Stale · Oct 17, 2026

@gnldev/durable has 34 recorded weekly downloads on npm, a decrease of 51.4% over the past 30 days, ranking #1790 of 2,256 tracked listings.

Weekly downloads
34
Official API · Oct 17, 2026
7-day growth
-89.5%
-290 weekly downloads
30-day growth
-51.4%
-36 weekly downloads
90-day growth
—
Insufficient history
Rank
#1790
Among tracked npm listings

About @gnldev/durable

@gnldev/durable

Call-scoped exactly-once effect + deterministic-replay durability for Vercel AI SDK agents.

Wraps the AI SDK's agent loop (generateText/streamText) without changing it. After a crash/restart a completed tool call is never executed a second time, and the agent makes the same decisions (deterministic replay). The one thing neither other agent frameworks nor plain AI SDK give you structurally: correctness.

The precise guarantee is at-most-once for a side effect, because the crash window between executing a tool and journaling its result cannot be closed by any client-side library — see the callout below. gnl's answer to that window is to refuse to guess: it blocks and asks, rather than silently re-running or silently continuing.

Install: pnpm add @gnldev/durable — the storage adapters ship inside the same package. (Or clone the repo and pnpm install && pnpm -r build.)

Durability in 2 lines

If the process crashes mid-turn, call again with the same runId → it resumes where it left off, the card is never charged a second time:

One id is one JOB, never one session. runDurable is the raw surface: the string you pass is the identity, so a sessionId or a conversation id there makes every later turn replay the first one forever. Through createGnl you name the work instead (workKey) and the engine derives the id — see Work identity.

What "never charged twice" actually means: the guarantee is at-most-once. If a step already completed, it's replayed and skipped. But if the crash lands in the narrow window after the charge executed and before its success was journaled, resume can't know whether the charge went through — so for a side-effect tool with no recover() and no idempotent/approval, it does not silently re-run and does not silently continue: it blocks and asks a human. Safe direction (never a double charge), but resume is not always seamless.

Concretely, runDurable throws SideEffectRetryBlockedError — it does not come back in result.interrupts, which carries approval suspensions only. Catch it:

recover() is the way to avoid the human: it re-checks the provider and must return { done: true, output } or { done: false }. Any other shape is treated as "could not determine" and lands back on this same gate rather than re-running the effect.

If you know generateText, you already know this — same arguments, same return type. The only addition: runId + journal.

How it works

• durableTool — wraps a tool's execute. The key is the toolCallId the AI SDK assigns; on replay the model response is reproduced verbatim, so the same id is generated → a tool that already succeeded never runs again. • withDurableModel — via a wrapLanguageModel middleware, records every model response to the journal and replays it on resume → the agent reproduces the same tool chain. • Journal — an append-only log. InMemoryJournal (dev) · SqliteStorage().runs (prod, node:sqlite, zero native dependencies).

Guarantee: a side effect is never repeated for the same toolCallId (call-scoped, replay/resume-safe). Not "the LLM always produces the exact same text" — if there's a recorded entry, it's replayed; everything past the crash point runs live. A call whose outcome is unknown (after a crash/timeout) is first checked against the provider via tool.recover?(); if it's still unknown, the system blocks and asks for approval instead of silently retrying (see "Human-in-the-loop").

Scope caveat (important): the default dedup is keyed by toolCallId. If the model re-plans the same business action under a new toolCallId (with identical or slightly different args — a documented AI SDK pattern), the call-scoped key does not collapse it. With identical args the default limits.sideEffectDuplicates: 'suspend' stops the repeat and asks a human — without a key nothing can tell "the same work again" from "two of the same, on purpose". With different args it is a new call. For "this action happens once" without a question, give the tool its identity: idempotency: 'args' / idempotencyKey (next section). A tool that declares no sideEffect is treated as one — declare sideEffect: false on a read tool.

A run outlives its caller (createGnl)

A registry run — gnl.run(), gnl.stream(), and every door built on them — executes apart from the call that started it, on the process's executor (one per process per store). The caller follows it.…

Description from the npm listing.

  • ai
  • agent
  • llm
  • typescript
  • ai-sdk
  • durable
  • exactly-once
  • journal
  • replay
  • idempotency
  • crash-recovery

README badge

Show your rank in a README or on your website. The badge updates automatically.

Charts

Images: 30d · 1y · all time · 1600×900 dark

Adoption over time

@gnldev/durable weekly downloads on npm, last 90 days: 34 weekly downloads as of Oct 17, 2026.@gnldev/durableWeekly downloads on npm · Last 90 days34downloads / week02004006008001K1.2K1.4K1.6KJul 19Aug 3Aug 18Sep 2Sep 17Oct 2Oct 17downloads / weekobservedarchived (Internet Archive)no observationsJul 22, 2026 – Oct 17, 2026 · 88 observations · Updated Oc…pluginstats.com
@gnldev/durable weekly downloads on npm, last 90 days: 34 weekly downloads as of Oct 17, 2026.

7/30/90-day growth

@gnldev/durable weekly downloads growth on npm: -89.5% over 7 days, -51.4% over 30 days, 90-day growth unavailable.@gnldev/durableWeekly downloads growth on npm34downloads / week now7-day growth-290 weekly downloads-89.5%30-day growth-36 weekly downloads-51.4%90-day growth+34 weekly downloadsInsufficient historyGrowth vs. nearest observation to each baseline date · Updated Oct 17, 2026pluginstats.com
@gnldev/durable weekly downloads growth on npm: -89.5% over 7 days, -51.4% over 30 days, 90-day growth unavailable.

Ranking history

@gnldev/durable npm ranking history: currently #1790 (by weekly downloads).@gnldev/durablenpm ranking · by weekly downloads · Last 90 days#1790current rank#1782#1784#1786#1788#1790#1792Jul 21Aug 5Aug 20Sep 4Sep 19Oct 4Oct 19rankOct 18, 2026 – Oct 19, 2026 · 2 observations · Updated Oct 17, 2026pluginstats.com
@gnldev/durable npm ranking history: currently #1790 (by weekly downloads).

Listing placement

All npm2,256 listings · 113 pages · 1,129 shown · page 90, #11 (overall #1,791)
All npm: every listing in weekly downloads order

Listing placement

AI SDKs250 listings · 13 pages · page 13, #5 (overall #245)
AI SDKs: every listing in weekly downloads order

Filled points are observed values; hollow points come from Internet Archive snapshots of the listing page. Dashed segments span periods with no observations — values between points are not interpolated.

Each band is one page of 20. Weekly downloads on a linear scale. Placement is projected from weekly downloads, so it can differ from the marketplace's own sort order. Hover a dot to see the listing.

Recent observations

Full history (121)
Recent weekly downloads observations for @gnldev/durable
Date (UTC)Weekly downloadsChange vs. previous
34-12
46+13
33-10
43-15
580
58-259
317-7
324-6
330-26
356-123
479-419
898-203
1,101+257
844—

Similar npm AI SDKs plugins

All 20 @gnldev/durable alternatives

Data source

Weekly downloads (trailing 7 complete days) come from the official npm downloads API. Downloads include CI and mirrors and are not equivalent to installs or users. npm publishes no ratings.

Listing: https://www.npmjs.com/package/@gnldev/durable. First seen Oct 16, 2026; last successful collection Oct 19, 2026. See the methodology.