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

@devpilot.sh/conductor-agent

v0.1.0

Published

The DevPilot conductor as a LangGraph agent — plan, review, dispatch and advance a wave plan as one resumable graph

Readme

@devpilot.sh/conductor-agent

The DevPilot conductor as a LangGraph agent: plan → score → refine → human review → dispatch → advance, as one resumable graph.

MIT. No dependency on DevPilot — implement six functions and it runs anywhere.

npm i @devpilot.sh/conductor-agent

The idea

Most "agent orchestration" puts the model in charge of sequencing. This does the opposite: the graph owns control flow, the model only produces plans. Which wave runs next, when to refine, when to retry, when to stop and ask a human — all of that is declared as edges, and none of it is left to a model to remember.

Effects live behind ConductorPorts, so the agent never touches your database, your API keys, or your dispatch layer.

generate ─▶ score gate ─┬─(below threshold, budget left)─▶ refine ─┐
                        └─(good enough / out of budget)─▶ review ◀─┘
                                                            │
                     ┌────────(refine w/ constraints)───────┤
                     ▼                          (approve)   ▼
                  refine                                 persist
                                                            │
                                    ┌───────────────────────┘
                                    ▼
                                dispatch ─▶ awaitWave ─┬─(ok)─▶ advance ─┬─(more)─▶ dispatch
                                    ▲                  │                 └─(none)─▶ finish
                                    └──(retry)─────────┴─(failed)─▶ fail

Usage

import { createConductorGraph, Command } from '@devpilot.sh/conductor-agent';
import { MemorySaver } from '@langchain/langgraph';

const graph = createConductorGraph({
  ports: {
    generatePlan: async (input) => ({ plan: await myPlanner(input), tokensUsed: 0 }),
    refinePlan:   async (input) => ({ plan: await myRefiner(input) }),
    scorePlan:    (plan) => ({ parallelizationScore: myScorer(plan) }),
    persistPlan:  async (plan) => ({ wavePlanId: await save(plan) }),
    dispatchWave: async (id, i) => myDispatcher(id, i),
    // waitForWave omitted → the graph interrupts and you resume it
  },
  config: { minParallelizationScore: 70, maxRefinementIterations: 3 },
  checkpointer: new MemorySaver(),
});

const cfg = { configurable: { thread_id: 'item-42' } };

// Runs until it needs a human.
const paused = await graph.invoke(
  { itemId: 'item-42', itemTitle: 'Add batch ops', repo: 'acme/widget', specContent: spec },
  cfg
);

paused.__interrupt__[0].value;   // → ReviewRequest: the plan, its score, why it stopped

// Resume with a decision.
await graph.invoke(new Command({ resume: { action: 'approve' } }), cfg);

The conductor can also send it back:

await graph.invoke(
  new Command({ resume: { action: 'refine', constraints: ['do not touch src/db'] } }),
  cfg
);

Those constraints land in state and re-enter the refinement prompt. The refinement budget is deliberately not reset — a human who keeps rejecting should hit review again, not spin the model indefinitely.


Waiting for a wave

A wave is a fleet of coding agents that may run for hours. Two options:

  • Omit waitForWave (recommended). The graph interrupt()s after dispatch and checkpoints. Resume it from your completion callbacks with new Command({ resume: { state: 'complete' } }). Survives a process restart.
  • Provide waitForWave for tests or short synchronous runs, where holding a promise open is fine.

Config

| Option | Default | Meaning | |---|---|---| | minParallelizationScore | 70 | Refinement stops once the score reaches this | | maxRefinementIterations | 3 | Hard cap on refinement passes | | requireReview | true | false dispatches a plan no human has seen | | failurePolicy | 'halt' | 'continue' advances past a failed wave | | waveRetryLimit | 1 | Re-dispatch attempts before the policy applies |


Design notes

A refinement is kept only if it scored better. The model will happily return a different plan that parallelises worse; accepting it because it is newer turns the loop into a random walk. Iterations count up either way, so a run that cannot improve still terminates.

scorePlan must stay deterministic. It is the gate the refinement loop branches on. An LLM there makes the loop unfalsifiable.

State is one serialisable object. Every field the graph branches on lives in the state channel, which is what lets a checkpointer suspend a run at any node and resume it later.