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

@serverless-agents/harness

v0.1.0

Published

TypeScript contracts for durable Serverless Agents harnesses

Readme

TypeScript harness SDK

@serverless-agents/harness is the public author API for guest API v1. The SDK provides types; the platform-owned runner supplies web globals and ctx bindings. It has no platform credentials, HTTP client, or bootstrap side effects.

import type { HarnessDefinition } from '@serverless-agents/harness';

export default {
  async create(construction) {
    const restored = await construction.state.get();
    return {
      async run(ctx) {
        const current = await ctx.state.get();
        return {
          final_changes: {
            state: {
              expected_revision: current.revision,
              body: { ...current.body, started: true },
            },
            events: [],
            inputs: [],
          },
        };
      },
    };
  },
} satisfies HarnessDefinition;

Construction and hooks

The default export has an asynchronous create(ctx) factory returning an object with required asynchronous run(ctx) and optional initialize(ctx)/cleanup(ctx). Construction can read state/secrets and identity/config/limits. Invocation contexts also expose event/inbox reads, atomic commits and managed helpers. Initialize and cleanup cannot resolve inputs; Run must explicitly include input dispositions. Returning void means empty final changes. Returning typed final changes requests an atomic lifecycle completion through the authoritative platform transaction.

One isolate and harness instance belongs to one leased session activation. Run continuations keep ordinary JavaScript memory. Release disposes it; replacement and abort cleanup construct a fresh isolate and restore persisted state.

Platform bindings

  • ctx.state.get() returns the persisted object and revision.
  • ctx.events.get(id) / .list(query?) read session events.
  • ctx.inbox.get(id) / .list(query?) read durable inputs. .wait() awaits a coalesced availability hint. It does not consume inputs; list again after waking. The runner retains a watch cursor across list/wait so an intervening notice is not lost. Lease observations and host reconciliation recover missed transport hints.
  • ctx.secrets.get(name, { refresh: true }) explicitly bypasses the provider's short cache. Names come from private worker bindings; provider references and worker credentials are never installed in JavaScript.
  • ctx.prepare(changes, operationId?) validates and freezes semantic retry data.
  • ctx.commit(changes) prepares one operation, then commits it.
  • ctx.commitPrepared(operation) reuses an operation identity. On failure the thrown GuestError.operation retains the exact submitted snapshot. A failed transport or cancelled commit can have an unknown durable outcome; reuse that identity when retrying. Never assume rollback or generate a replacement ID.
  • ctx.spawn(async signal => ...) returns { join(), cancel() }. Helpers share the isolate's JavaScript thread, and platform/fetch operations inherit the helper's cancellation. Await join() for its result. Outstanding helpers stop with their invocation; detached work never prolongs durable lifecycle authority.

GuestError.code is cancelled, scope_closed, validation, platform, or resource_limit. platform_code preserves the platform error code (for example, revision_conflict) when present. Web APIs retain standard web errors such as AbortError. Revision/sequence/limit values use their generated decimal-string wire types; application JSON uses ordinary JavaScript number semantics.

Web environment and imports

The runtime provides HTTP/HTTPS fetch and standard request/response/header/body objects; web streams; abort controllers/signals; numeric timers and microtasks; encoding, URL/search parameters, Blob/File/FormData, base64, performance and console. Crypto provides secure randomness/UUIDs and the pinned Deno Web Crypto implementation. The qualified standard algorithms are recorded in the runtime environment guide. There is no cookie jar, automatic application-request retry policy, filesystem, process access, Deno/Node namespace, browser DOM, guest workers or shared-memory threading. Timer callbacks are functions. AbortSignal.timeout validates its millisecond duration using Web IDL and its timer belongs to the current scope.

Build application dependencies into one JavaScript ESM file. Type-only SDK imports are erased. Runtime npm/remote/dynamic imports and application ext: imports are rejected. Runner bootstrap modules are private. CLI scaffolding, strict checks, bundling, source maps, deployment and lightweight local execution are implemented.

Scope ownership

Construction and each hook get separate scopes and abort signals. The hook's Promise determines completion. Timers, helpers, outstanding requests and native stream/body handles close before another scope opens. Materialized plain data can remain in the instance; unread response bodies and old contexts cannot retain access. Saving an old ctx or continuing an old Promise does not grant the next hook's authority. Use ctx.signal for custom cancellation-aware work.

Guest CPU/allocation/operation budgets are enforced by the runner; limits are exposed as immutable activation snapshots. Console records carry session/worker/invocation identity and timestamps through bounded runner logging.

Package checks

pnpm --filter @serverless-agents/harness generate
pnpm --filter @serverless-agents/harness test

The package builds ESM and declarations in dist/. Generated DTOs come from schemas/javascript-contracts.openapi.json; handwritten interfaces describe the runner's callable guest API. The echo example shows explicit atomic state/event/input changes and fresh-instance cleanup.

Read-only bundled assets are available in every scope through await ctx.assets.read("assets/prompt.txt"), returning a Uint8Array. Only manifest-listed paths are accessible. Reads share the pending-operation, buffered-body and external-memory budgets and stop at scope teardown; streaming asset access is not implemented.

Standalone tooling

Install the approved CLI + runner archive and Node/pnpm, then:

serverless-agents init my-agent
cd my-agent
pnpm install
pnpm check
serverless-agents run --input '{"message":"hello"}'
pnpm dev
serverless-agents login
serverless-agents deploy

The SDK package includes pinned TypeScript/esbuild tooling and ./globals types for the supported runtime surface. The scaffold extends ./tsconfig, excluding shared-memory globals and browser ambient libraries from its editor profile. ./tooling executes in Node; it is never imported by guest code. Successful builds are content-addressed under .serverless-agents/builds. Declare {path,file} assets in harness.json. Local values live in a 0600, Git-ignored .dev.secrets.json; tooling rejects it as an import or asset. Declare required names in harness.json's secrets array. serverless-agents secrets put NAME prompts for a remote value, stores it encrypted, and adds only the name to configuration. secrets list returns metadata and secrets delete NAME removes/revokes the managed reference. Deployment checks required remote bindings without uploading local values. Failed builds leave the prior worker alive; successful reload starts a fresh session without replay or implicit abort cleanup. :abort explicitly runs cleanup, :reset starts another session. No platform source or credentials are needed for local execution. Full distributed recovery and Linux host limits require private integration/remote project testing.

Set the deployment name in harness.json (the scaffold does this). First deploy creates the remote harness and binds the folder to its organization. Later deploys publish new releases and promote for new sessions. Interrupted deploys resume matching bytes; --resume uses the original immutable package and --new supersedes it. Remote sessions retain their existing release pins. org use NAME switches the active organization; org use NAME --local explicitly changes the folder binding. The new SDK/toolchain must be supplied or published before registry installation.