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

od-lite

v0.4.2

Published

## Installation

Readme

od-lite

Installation

Install the package with your favorite package manager.

bun add od-lite

# or

npm install od-lite

What is od-lite?

od-lite is a lightweight framework that provides the necessary abstractions to build OpenDevin-like autonomous software agents. It is based on the paper by Wang et al. (coming soon).

Table of Contents

General Overview

od-lite is built around three main concepts: actions, observations, and an event stream. An action represents something the agent wants to do, while an observation represents the result of the action. An event stream handles the events between the agent and the environment. These concepts are abstracted into the Agent and Runtime classes. A complementary Session class manages the interaction between the agent and runtime.

Actions and Observations

An action is an event that the agent wants to perform, while an observation is the result of that action. The Agent generates actions based on a query, and the Runtime processes these actions in the environment to generate observations.

Action

An action represents an event the agent wants to perform, such as running a terminal command, editing a file, or calling an API.

To define an action, od-lite provides an ActionEvent interface that you can extend. Below are examples of defining two actions: one for running a terminal command and another for reading the contents of a file.

import type { ActionEvent } from 'od-lite';

interface TerminalCommand extends ActionEvent {
  data: {
    command: string;
  };
}

interface ReadFile extends ActionEvent {
  data: {
    path: string;
  };
}

export type Action = TerminalCommand | ReadFile;

Observation

An observation is the result of an action, such as the output of a command, the contents of a file, or the response from an API.

To define an observation, od-lite provides an ObservationEvent interface that you can extend. Below are examples of defining two observations: one for the output of a command and another for the contents of a file.

import type { ObservationEvent } from 'od-lite';

interface TerminalOutput extends ObservationEvent {
  data: {
    output: string; // The output of the command.
  };
}

interface FileContents extends ObservationEvent {
  data: {
    output: string; // The contents of the file.
  };
}

export type Observation = TerminalOutput | FileContents;

Note: An observation must always include an output field.

Agents and Runtimes

An agent is an entity that interacts with the environment, generating actions based on queries and handling responses from the environment. An agent would typically be implemented with an LLM of your choice.

A runtime is an entity that handles actions in the environment and generates observations. It interacts with the environment and produces observations based on the received actions.

Agent

To define an agent, create a class that implements the Agent abstraction. For type support, pass the action type defined earlier as a generic parameter. The class must implement the query method, which returns an action. It is also recommended to return a Message as the default response if the agent cannot generate an action.

The example below defines an OpenAI agent, but you can define any agent you want.

import { type Agent, type Message, Topic } from 'od-lite';
import type { Action } from './actions'; // Import the action type you defined earlier.
import OpenAI from 'openai'; // Import your LLM of choice.

class OpenAIAgent implements Agent<Action> {
  private readonly openai: OpenAI;

  constructor(apiKey: string) {
    this.openai = new OpenAI({ apiKey });
  }

  public async query(message: string): Promise<Action | Message> {
    const response = await this.openai.chat.completions.create({
      mode: "gpt-3.5-turbo",
      messages: [{ role: 'user', content: message }],
    });

    // parse the response based on your prompt and return the data in the correct format.
    if (isCommand) return { type: Topic.ACTION, data: { command }};
    else if (isReadFile) return { type: Topic.ACTION, data: { path }};
    else return { type: Topic.MESSAGE, data: { role: 'ai', message }};
  }
}

Runtime

To define a runtime, create a class that implements the Runtime interface. For type support, pass the action and observation types defined earlier as generic parameters. The class must implement the handle method, which returns an observation.

import { type Runtime, Topic } from 'od-lite';
import type { Action, Observation } from './types'; // Import the action and observation types you defined earlier.

class NodeRuntime implements Runtime<Action, Observation> {
  public async handle(action: Action): Promise<Observation> {
    if (isTerminalCommand) {
      const output = await runCommand(action.data.command);
      return { type: Topic.OBSERVATION, data: { output }};
    } else if (isReadFile) {
      const output = await readFile(action.data.path);
      return { type: Topic.OBSERVATION, data: { output }};
    }
  }
}

Session

A session brings the agent and runtime together, handling their interaction behind the scenes. It is implemented using a pub/sub pattern and allows you to subscribe to messages, actions, and observations exchanged between the agent and runtime.

import { Session } from 'od-lite';
import { OpenAIAgent } from './agents'; // Import the agent you defined earlier.
import { NodeRuntime } from './runtimes'; // Import the runtime you defined earlier.

const agent = new OpenAIAgent('your-api-key');
const runtime = new NodeRuntime();

const session = new Session(agent, runtime); // Session type is inferred.

You can now query the agent and subscribe to the messages, actions, and observations exchanged between the agent and runtime.

// Query the agent.
session.pubsub.publish({ type: Topic.MESSAGE, data: { role: 'user', message: 'Please run ls in the terminal' });

// Subscribe to the messages, actions, and observations.
session.messages.subscribe((message) => {
  // user and ai messages.
  console.log(JSON.stringify(message, null, 2));
});

session.actions.subscribe((action) => {
  // actions sent to the runtime.
  console.log(JSON.stringify(action, null, 2));
});

session.observations.subscribe((observation) => {
  // observations sent by the runtime.
  console.log(JSON.stringify(observation, null, 2));
});

Custom Sessions

To create your own session implementation, use the RxPubSub class to create a custom pub/sub implementation. For reference, you can look at the existing Session class.

Examples

CLI: https://github.com/amanape/od-lite-cli VSCode Extension: Coming soon...