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

@hypergaas/core

v0.2.0

Published

An open-source agent SDK for B2B SaaS: a typed, multi-tenant action registry over your existing service layer.

Readme

hypergaas

License: Apache-2.0

Add agents to your SaaS — without rewriting your service layer.

The HyperGaaS SDK: a typed, multi-tenant action registry over the service layer you already have. Add @agentAction() to a method and it becomes a safe agent action — tenant-scoped, permission-checked, audited, with irreversible calls paused for approval. The tool schema is derived from your TypeScript types, so there's no parallel schema to maintain and no plumbing to hand-write.

Status: v0.2. Live on npm. Full docs coming soon.

Install

npm install @hypergaas/core

Quickstart

// 1. Bind your roles to the registry once, at module scope.
import { defineRoles, audience, createActionRegistry, type AgentContext } from "@hypergaas/core";

const roles = defineRoles({
  owner: { displayName: "Owner", seniority: 4, canApproveIrreversibleUpTo: "high" },
  dispatcher: { displayName: "Dispatcher", seniority: 3, canApproveIrreversibleUpTo: "medium" },
  technician: { displayName: "Technician", seniority: 1 },
});

const { agentAction, invoke } = createActionRegistry(roles);

// 2. Decorate a service method you already have. No parallel schema, no handler.
class JobService {
  @agentAction({
    description: "Get a technician's schedule for a given date",
    reversibility: "idempotent",
    requiredPermissions: ["schedule:read"],
    audienceRoles: ["dispatcher", "owner", audience.self((ctx, p) => ctx.userId === p.techId)],
    costWeight: 1,
  })
  async getTechSchedule(ctx: AgentContext, params: { techId: string; date: Date }) {
    return this.db.schedule.find({ tenantId: ctx.tenantId, ...params });
  }
}
import { createAgentContext, isOk } from "@hypergaas/core";

// 3. Build one context per request — the only source of tenant identity.
const ctx = createAgentContext({
  tenantId: "acme-hvac",
  userId: "u_marcus",
  role: "dispatcher",
  permissions: ["schedule:read"],
  autonomyLevel: "medium",
});

// 4. Invoke. Permissions and tenant scope are enforced before the body runs;
//    the result is typed, not thrown.
const result = await invoke("JobService.getTechSchedule", ctx, {
  techId: "u_marcus",
  date: new Date("2026-05-25"),
});

if (isOk(result)) {
  console.log(result.value); // the schedule, scoped to tenant "acme-hvac"
}

By the end you have a permission-checked, tenant-scoped call with a paired PROPOSED + COMPLETED audit record — and you wrote none of that plumbing. The default InMemoryAuditLogger swaps for a durable backend behind the same interface in production.

NestJS / TypeORM / Angular / legacy decorators — use registry.register(...)

@agentAction() is a TC39 standard decorator. It requires standard decorator mode — that is, experimentalDecorators must be false (or unset) in your tsconfig.json. NestJS, TypeORM, and Angular decorators (@Injectable, @Controller, @Entity, @Column, …) require the legacy mode ("experimentalDecorators": true). A TypeScript compilation unit has exactly one global decorator mode, so @agentAction cannot co-locate with those framework decorators in the same project. If you put @agentAction on a class that also uses legacy decorators, you'll hit a tsc TS1241 error and a runtime decorator kind "undefined" throw.

For those stacks, use the imperative, decorator-free registry.register(...) escape hatch. Your provider keeps its @Injectable (legacy) decorators and registers its action methods in the constructor or onModuleInit — no @agentAction anywhere:

import { Injectable } from "@nestjs/common";
import { createActionRegistry, type AgentContext, type BoundActionRegistry } from "@hypergaas/core";

const registry = createActionRegistry(roles); // module scope

@Injectable()
class BillingService {
  constructor(private readonly registry: BoundActionRegistry<typeof roles>) {
    this.registry.register({
      key: "BillingService.issueCredit",
      description: "Issue a goodwill credit to a customer",
      reversibility: "irreversible",
      requiredPermissions: ["billing:write"],
      audienceRoles: ["owner", "dispatcher"],
      costWeight: 1,
      handler: this.issueCredit.bind(this),
      // OPTIONAL: an explicit params schema — see "Build-time schema codegen".
      // paramsSchema: { type: "object", properties: { customerId: { type: "string" }, cents: { type: "number" } }, required: ["customerId", "cents"] },
    });
  }
  async issueCredit(ctx: AgentContext, params: { customerId: string; cents: number }) {
    // ...
  }
}

register takes the same metadata @agentAction() does (typed against your role registry — a non-role in audienceRoles is still a compile error), plus an explicit key (no decoration site to derive ClassName.methodName from) and the handler. Permission, audience, reversibility, audit, and idempotent re-registration all behave identically to the decorated path. The decorator remains the primary, canonical path; register is the escape hatch for projects that can't use it.

Build-time schema codegen

The hypergaas-extract CLI walks your tsconfig.json, finds @agentAction() methods, and emits a hypergaas.actions.json artifact with a tool schema derived from your method param types — no schema drift, no parallel definitions. It runs ahead of tsc in this package's build script.

Imperative actions and schemas. The extractor scans @agentAction() call sites, so an action registered via registry.register(...) has no decoration site for it to find. In v0.2.0 the imperative path is permissive by default (any params shape passes — same as a decorated action with no artifact). To enforce typed arguments on an imperative action, pass an explicit paramsSchema (the JsonSchema shape the codegen emits) in the register(...) declaration, or add an entry keyed by the action's key to the actionsArtifact you feed createActionRegistry(roles, { actionsArtifact }). (Auto-extracting imperative call sites is a planned follow-on.)

License

Apache-2.0.