npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@weaveintel/workflows

v0.1.3

Published

Workflow engine — definition builder, step execution, scheduling, compensation, checkpointing

Downloads

474

Readme

@weaveintel/workflows

A workflow engine: define a task as a graph of steps, run it durably, and recover, compensate, or replay it when things go wrong.

Why it exists

Some jobs are too important to leave to a model improvising each move. "Take the payment, reserve the stock, email the receipt" has to happen in that order, exactly once each, and if the email fails you'd better be able to undo the reservation. That's a workflow: a fixed recipe of steps with retries, checkpoints, and cleanup built in. Think of a factory line rather than a chef winging it — each station does one thing, the belt records where every item is, and if a station jams you can rewind to the last checkpoint or run the line backwards to unwind. This package is that line: you defineWorkflow, the engine runs it, and the state is persisted at every step so a crash resumes instead of restarting.

When to reach for it

Reach for @weaveintel/workflows when the sequence is known and you need it to be reliable, ordered, and auditable — payments, provisioning, multi-step ETL. If you instead want a model to decide the steps at runtime, use @weaveintel/agents. If you just need to start a workflow when something happens, that's @weaveintel/triggers. (Workflows and agents compose: a step can call an agent, and a workflow can emit a contract that triggers the next one.)

How to use it

import { createWorkflowEngine, defineWorkflow, createHandlerResolverRegistry, createDefaultResolvers } from '@weaveintel/workflows';

const registry = createHandlerResolverRegistry();
for (const r of createDefaultResolvers()) registry.register(r);

const def = defineWorkflow('greet')
  .addStep({ id: 'hello', type: 'script', handler: 'script:return { greeting: "hi " + input.name }', next: null })
  .build();

const engine = createWorkflowEngine({ resolverRegistry: registry });
const run = await engine.startRun(def, { name: 'Ada' });
const finished = await engine.tickRun(run.id);

console.log(finished.status); // 'completed' | 'failed' | 'waiting' | ...

What's in the box

| Export | What it does | |---|---| | createWorkflowEngine / DefaultWorkflowEngine | The engine: startRun, tickRun, persistence, optional contract emission. | | defineWorkflow / WorkflowBuilder | Fluent builder for a step graph. | | createHandlerResolverRegistry, createDefaultResolvers | Map a step's kind to how it runs — noop, script, tool, prompt, agent, mcp, subworkflow. | | createPlannerResolver | Opt-in resolver that lets a step expand into a sub-graph at runtime (dynamic graphs). | | InMemoryScheduler | Fire scheduled workflow runs. | | DefaultCompensationRegistry, runCompensations | Register and run "undo" handlers when a run fails. | | InMemoryCheckpointStore, JsonFileCheckpointStore, createDurableCheckpointStore | Snapshot run state so a crash resumes cleanly. | | WorkflowReplayRecorder, createReplayRegistry | Record a run and replay it deterministically — no LLM calls, byte-identical output. | | validateWorkflowInput, InMemoryCostMeter, CircuitBreaker, Bulkhead, InMemoryRunQueue, InMemoryWorkflowRateLimiter | Governance and resilience — input validation, cost ceilings, circuit breakers, bulkheads, queueing, rate limits. | | lintWorkflow, getWorkflowGraph, createWorkflowTestHarness | Developer tooling — lint a definition, inspect its graph, test it with mock handlers. | | buildEmittedContract, ContractEmitter | Publish a run's outputContract so downstream triggers or agents can react. | | weaveSqlite*, weavePostgres*, weaveMongoDb*, weaveRedis*, weaveDynamoDb* stores | DB-backed adapters for checkpoints, definitions, runs, idempotency, payloads, sleep, locks, rate limits, queues, and audit — one set per backend. |

One source of truth for SQL storage

The SQL adapters used to be written twice — once for Postgres, once for SQLite — and, like any copy, they slowly drifted apart ($1 vs ?, jsonb vs text, NOW() vs CURRENT_TIMESTAMP). That's now fixed for all ten SQL-backed stores — checkpoints, definitions, runs, idempotency, payloads, sleeps, step-locks, the run queue, rate limits, and the audit log. For each one, the query logic is written once with Drizzle and reused for both databases. Every weavePostgres* / weaveSqlite* factory keeps the exact same API — they're just thin wrappers around one shared implementation now, so there's nothing left to drift.

Nothing changed for you as a caller:

import pg from 'pg';
import { weavePostgresCheckpointStore, weaveSqliteCheckpointStore } from '@weaveintel/workflows';

// Production: Postgres
const pgStore = await weavePostgresCheckpointStore({ pool: new pg.Pool({ connectionString: process.env.DATABASE_URL }) });
// Edge / local / tests: SQLite — same behaviour, proven by the same tests
const liteStore = weaveSqliteCheckpointStore({ databasePath: './workflows.db' });

const cp = await pgStore.save('run-1', 'step-1', workflowState);
await pgStore.latest('run-1'); // resume from the newest checkpoint

There's exactly one place the two databases genuinely differ, and it's handled honestly: draining the run queue. Postgres uses FOR UPDATE SKIP LOCKED so a hundred workers can pull jobs in parallel without ever grabbing the same one; SQLite has a single writer so it doesn't need it. Everything else is identical.

How do we know both databases behave the same? The SQLite side is covered by the existing store tests, and the Postgres side runs the same operations against a real Postgres (Testcontainers) — including a 1,000-job concurrent queue drain where no job is ever handed out twice, and a durable "resume after a crash" where an agent checkpoints a real model's result to Postgres and a fresh process picks up exactly where it left off.

License

MIT.