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

@lastshotlabs/slingshot-orchestration

v0.0.3

Published

Portable orchestration runtime, task/workflow DSL, and built-in memory/SQLite adapters for Slingshot

Readme


title: Human Guide description: Human-maintained guidance for @lastshotlabs/slingshot-orchestration

This package provides the portable orchestration contract for Slingshot.

It owns:

  • defineTask() and defineWorkflow() for application authoring
  • step(), parallel(), sleep(), and stepResult() for workflow composition
  • createOrchestrationRuntime() for framework-agnostic runtime composition
  • createMemoryAdapter() for in-process execution
  • createSqliteAdapter() for durable single-node execution

It does not depend on Slingshot plugin lifecycle or Hono routing. Slingshot-specific integration lives in @lastshotlabs/slingshot-orchestration-plugin.

Mental model

  • A task is a named, retryable unit of work with Zod-validated input and output.
  • A workflow is an ordered array of entries that can run sequentially, in parallel, or pause with sleep().
  • The runtime is portable. It can run in tests, workers, plain scripts, or inside Slingshot.
  • The adapter decides durability and infrastructure concerns. Task and workflow definitions stay the same.

Supported adapters in this package

  • memory: zero infrastructure, non-durable, best for tests and local development
  • sqlite: durable single-node execution, process-restart recovery, no external services

Current non-goals

  • No direct Slingshot plugin lifecycle in this package
  • No Hono HTTP router in this package
  • No manifest integration in this package
  • No Temporal or Trigger.dev support in this package

Those concerns live in outer adapters or later phases.

Recommended usage

For standalone runtime composition:

import {
  createMemoryAdapter,
  createOrchestrationRuntime,
  defineTask,
} from '@lastshotlabs/slingshot-orchestration';

For Slingshot integration, use @lastshotlabs/slingshot-orchestration-plugin and treat this package as the domain layer only.

Minimal example

import { z } from 'zod';
import {
  createMemoryAdapter,
  createOrchestrationRuntime,
  defineTask,
  defineWorkflow,
  step,
  stepResult,
} from '@lastshotlabs/slingshot-orchestration';

const quoteCarrier = defineTask({
  name: 'quote-carrier',
  input: z.object({ quoteId: z.string(), carrier: z.string() }),
  output: z.object({ carrier: z.string(), premiumCents: z.number().int() }),
  async handler(input) {
    return { carrier: input.carrier, premiumCents: 12500 };
  },
});

const quoteWorkflow = defineWorkflow({
  name: 'quote-policy',
  input: z.object({ quoteId: z.string(), carrier: z.string() }),
  output: z.object({ carrier: z.string(), premiumCents: z.number().int() }),
  outputMapper(results) {
    return stepResult(results, 'quote', quoteCarrier)!;
  },
  steps: [step('quote', quoteCarrier)],
});

const runtime = createOrchestrationRuntime({
  adapter: createMemoryAdapter({ concurrency: 10 }),
  tasks: [quoteCarrier],
  workflows: [quoteWorkflow],
});

const handle = await runtime.runWorkflow(
  quoteWorkflow,
  { quoteId: 'q_123', carrier: 'acme' },
  { tenantId: 'tenant-a', idempotencyKey: 'quote:q_123' },
);

const output = await handle.result();
const run = await runtime.getRun(handle.id);

Adapter choice

  • memory: fastest iteration path, in-process only, no durability, good for tests and local development.
  • sqlite: durable single-node execution, process restart recovery, good for one-node backoffice or embedded installs.
  • bullmq via @lastshotlabs/slingshot-orchestration-bullmq: Redis-backed multi-worker execution and scheduling.
  • temporal via @lastshotlabs/slingshot-orchestration-temporal: strongest fit for enterprise durability, signals, and distributed workflow control.

Registration model

This package registers orchestration definitions, not application services.

  • Register tasks and workflows by passing them into createOrchestrationRuntime({ tasks, workflows, adapter }).
  • In Slingshot apps, pass the same definitions into createOrchestrationPlugin() or reference exported handler names from manifest config.
  • Keep quote engines, carrier clients, rating services, ordering services, and document generators as normal application dependencies. Call them inside task handlers instead of trying to register them with the orchestration runtime.

Runtime surface

  • runTask() and runWorkflow() start work and return a RunHandle.
  • handle.result() waits for the final output.
  • getRun(id) returns the current portable run snapshot.
  • cancelRun(id) requests cancellation.
  • listRuns() and onProgress() are adapter capabilities, so check runtime.supports(...) when you depend on them.

Contract notes

  • task retry policies and task-level concurrency are validated when you call defineTask()
  • step retry and timeout overrides are validated when you call step()
  • dynamic sleep() durations are validated at workflow execution time, so invalid mapper output fails the run consistently across adapters instead of silently turning into an immediate timer
  • adapter-level idempotency is scoped by run type, definition name, and tenantId, so the same key can be reused safely across different tenants or different task/workflow definitions
  • reusing an idempotency key in the same scope returns the existing run handle; completed runs replay the stored result instead of failing because the original promise is no longer active
  • tenantId, tags, and metadata are adapter-portable run options, so use them for auditability and request correlation instead of baking routing concerns into task names