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

@openagentid/oas-did

v1.0.2

Published

DID parsing, entity kinds, and namespace validation for the Open Agent Specification

Readme

@openagentid/oas-did

DID parsing, entity kind taxonomy, and namespace validation for the Open Agent Specification (OAS).

This is the foundational package in the OAS TypeScript SDK. It parses and validates did:oas:<namespace>:<kind>:<identifier> strings, classifies entity kinds, and enforces the namespace and identifier rules from the OAS specification.

Installation

npm i @openagentid/oas-did

Requirements: Node.js >= 20, ESM-only.

Usage

Parse a DID

import { OasDid, EntityKind, isRootKind } from '@openagentid/oas-did';

const did = OasDid.parse('did:oas:l1fe:agent:analyzer');
console.log(did.namespace);   // 'l1fe'
console.log(did.kind);        // 'agent'
console.log(did.identifier);  // 'analyzer'
console.log(did.isRoot);      // false
console.log(did.toString());  // 'did:oas:l1fe:agent:analyzer'

Create a DID from components

import { OasDid, EntityKind } from '@openagentid/oas-did';

const did = OasDid.create('l1fe', EntityKind.Agent, 'my-bot');
console.log(did.toString()); // 'did:oas:l1fe:agent:my-bot'

Parse compound kinds

import { OasDid } from '@openagentid/oas-did';

const did = OasDid.parse('did:oas:l1fe:agent:instance:bot-7');
console.log(did.kind);        // 'agent:instance'
console.log(did.identifier);  // 'bot-7'

Validate namespaces and identifiers

import { validateNamespace, validateIdentifier, isReservedNamespace } from '@openagentid/oas-did';

validateNamespace('l1fe');     // OK
validateNamespace('my-org');   // OK
validateNamespace('L1FE');     // throws DidError (uppercase)

validateIdentifier('alice');           // OK
validateIdentifier('my-agent_v2.0');   // OK
validateIdentifier('');                // throws DidError (empty)

isReservedNamespace('test');   // true
isReservedNamespace('l1fe');   // false

Check entity kinds

import { EntityKind, isRootKind, entityKindFromString } from '@openagentid/oas-did';

isRootKind(EntityKind.Hmr);   // true
isRootKind(EntityKind.Agent); // false

const kind = entityKindFromString('agent:instance');
console.log(kind === EntityKind.AgentInstance); // true

const unknown = entityKindFromString('unknown');
console.log(unknown); // undefined

Error handling

import { OasDid, DidError, DidErrorCode } from '@openagentid/oas-did';

try {
  OasDid.parse('not-a-did');
} catch (e) {
  if (e instanceof DidError) {
    console.log(e.code);    // 'INVALID_PREFIX'
    console.log(e.message); // human-readable description
  }
}

API Reference

OasDid (class)

Immutable, frozen value object representing a parsed and validated did:oas identifier. Constructed via parse() or create() -- never via new.

class OasDid {
  /** The namespace component (e.g., "l1fe"). */
  readonly namespace: string;

  /** The entity kind (e.g., "agent", "agent:instance"). */
  readonly kind: EntityKind;

  /** The identifier component (e.g., "analyzer"). */
  readonly identifier: string;

  /**
   * Creates a new OasDid from validated components.
   * @param namespace - 1-63 chars, lowercase alphanumeric + hyphens.
   * @param kind - The entity kind.
   * @param identifier - 1-128 chars, [a-zA-Z0-9._-].
   * @returns A frozen OasDid instance.
   * @throws DidError if any component fails validation.
   */
  static create(namespace: string, kind: EntityKind, identifier: string): OasDid;

  /**
   * Parses a DID string into an OasDid.
   * @param input - The DID string (e.g., "did:oas:l1fe:agent:analyzer").
   * @returns A frozen OasDid instance.
   * @throws DidError if parsing or validation fails.
   */
  static parse(input: string): OasDid;

  /** Returns true if this DID represents a root entity (HMR, MHR, or ENR). */
  get isRoot(): boolean;

  /** Returns the number of colon-separated components in the kind (1 or 2). */
  get kindComponentCount(): number;

  /** Returns the canonical DID string. */
  toString(): string;

  /** Returns the canonical DID string for JSON serialization. */
  toJSON(): string;

  /** Compares two OasDid instances for equality. */
  equals(other: OasDid): boolean;
}

EntityKind

All recognized OAS entity kinds as a const object with a companion type.

const EntityKind = {
  Hmr: 'hmr',                    // Human Root -- trust anchor
  Mhr: 'mhr',                    // Multi-Human Root -- trust anchor
  Enr: 'enr',                    // Entity Name Record -- MHR-governed trust anchor
  Ao: 'ao',                      // Autonomous Organization
  Agent: 'agent',                // Autonomous software agent
  AgentInstance: 'agent:instance', // Runtime instance of an agent
  Tool: 'tool',                  // Callable capability
  Skill: 'skill',               // Composable behavior module
  Workflow: 'workflow',          // Multi-step orchestration
  Model: 'model',               // Machine learning model
  Dataset: 'dataset',           // Structured data source
  Service: 'service',           // Infrastructure service endpoint
} as const;

type EntityKind = (typeof EntityKind)[keyof typeof EntityKind];

Functions

/**
 * Parses a string into an EntityKind.
 * Returns undefined if the string is not recognized.
 */
function entityKindFromString(s: string): EntityKind | undefined;

/**
 * Returns the string representation of an entity kind.
 */
function entityKindToString(kind: EntityKind): string;

/**
 * Returns true if the entity kind is a root kind (HMR, MHR, or ENR).
 */
function isRootKind(kind: EntityKind): boolean;

/**
 * Returns the number of colon-separated components in the kind string.
 * Simple kinds return 1; compound kinds (agent:instance) return 2.
 */
function entityKindComponentCount(kind: EntityKind): number;

/**
 * Validates a namespace string against OAS Spec rules.
 * Valid: 1-63 chars, lowercase alphanumeric + hyphens, no leading/trailing hyphen.
 * @throws DidError with code INVALID_NAMESPACE on failure.
 */
function validateNamespace(namespace: string): void;

/**
 * Returns true if the namespace is reserved (oas, test, example).
 */
function isReservedNamespace(namespace: string): boolean;

/**
 * Validates an identifier string against OAS Spec rules.
 * Valid: 1-128 chars, [a-zA-Z0-9._-].
 * @throws DidError with code INVALID_IDENTIFIER on failure.
 */
function validateIdentifier(identifier: string): void;

Constants

/** Reserved namespaces: ['oas', 'test', 'example'] */
const RESERVED_NAMESPACES: ReadonlyArray<string>;

Error classes

class DidError extends Error {
  /** Machine-readable error code for programmatic matching. */
  readonly code: DidErrorCode;

  constructor(code: DidErrorCode, message: string);
}

const DidErrorCode = {
  Empty: 'EMPTY',
  InvalidPrefix: 'INVALID_PREFIX',
  TooFewComponents: 'TOO_FEW_COMPONENTS',
  InvalidNamespace: 'INVALID_NAMESPACE',
  UnknownEntityKind: 'UNKNOWN_ENTITY_KIND',
  InvalidIdentifier: 'INVALID_IDENTIFIER',
} as const;

type DidErrorCode = (typeof DidErrorCode)[keyof typeof DidErrorCode];

Dependencies

None. This package has zero runtime dependencies.

License

Copyright © 2026 L1fe Labs, Inc.

Licensed under either of Apache License 2.0 or MIT license, at your option.