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

@letta-ai/trajectory

v0.2.5

Published

Normalize native agent transcripts into a shared trajectory format.

Downloads

115,577

Readme

trajectory

Normalize agent transcripts from different runtimes into one validated, model-ready record format.

Agent tools represent the same concepts—messages, reasoning, tool calls, and tool results—in incompatible native formats. trajectory provides one TypeScript API that turns those formats into deterministic, structured records for training, evaluation, analysis, and inference.

The caller supplies a transcript string and its source. The one exception is Deep Agents, whose sessions normalizeCheckpoint reads from its local LangGraph SQLite store by thread ID; see src/adapters/deepagents/.

Installation

The TypeScript package is published as @letta-ai/trajectory:

npm install @letta-ai/trajectory

The Python wrapper is published as agent-trajectory and imports as trajectory:

pip install agent-trajectory

Quick start

import { normalizeTranscript } from "@letta-ai/trajectory";

const { records, diagnostics } = normalizeTranscript({
  source: "codex",
  transcript: rawJsonl,
});

records contains the normalized trajectory. diagnostics is always present and is empty when the transcript required no recoverable cleanup.

{
  "records": [
    { "role": "meta", "source": "codex" },
    {
      "role": "user",
      "content": "Check the current directory.",
      "timestamp": "2026-07-10T12:00:00.000Z"
    },
    {
      "role": "assistant",
      "content": null,
      "tool_calls": [
        {
          "id": "call_1",
          "name": "exec_command",
          "args": "{\"cmd\":\"pwd\"}"
        }
      ],
      "timestamp": "2026-07-10T12:00:01.000Z"
    },
    {
      "role": "tool",
      "tool_call_id": "call_1",
      "content": "/workspace",
      "timestamp": "2026-07-10T12:00:02.000Z"
    }
  ],
  "diagnostics": []
}

Supported sources

| source | Accepted input format | Normalized meta.source | | --- | --- | --- | | claude-code | Native Claude Code JSONL | claude-code | | codex | Native Codex rollout JSONL | codex | | copilot-cli | Native GitHub Copilot CLI event JSONL | copilot-cli | | cursor | Cursor role/message content-block JSONL capture | cursor | | droid | Native Droid session JSONL | droid | | gemini-cli | Native Gemini CLI whole-session JSON | gemini-cli | | hermes | Session-store message-row array or a { "session": {...}, "messages": [...] } envelope | hermes | | letta-code | Letta Code client transcript.jsonl | letta-code | | omp | Native OMP (Oh My Pi) coding-agent session JSONL (pi-agent session format) | omp | | openclaw | Native OpenClaw session JSONL (pi-agent session format) | openclaw | | opencode | Native OpenCode { "info": ..., "messages": [...] } session JSON | opencode | | openhands | JSON event array or an events-API { "items": [...] } envelope | openhands | | pi | Native pi-coding-agent session JSONL | pi | | deepagents | Deep Agents CLI LangGraph SQLite store plus threadId | deepagents |

Tool result records may include ok: boolean when the source exposes an authoritative structured outcome, such as Pi/OpenClaw isError, Claude Code is_error, Letta Code resultOk, OpenHands/Cursor is_error, OpenCode/Gemini terminal state, or Copilot CLI success. The field is omitted when the source does not expose a reliable status; result text is never interpreted as success or failure.

Each adapter lives in its own folder under src/adapters/ with a README documenting the exact input contract, decoding behavior, and what the adapter drops.

Listing local trajectories

listTrajectories() enumerates the sessions in a source's standard local store, newest first, with cursor pagination. It is a discovery layer beside normalization — normalizeTranscript() itself never touches the filesystem. Copilot CLI, Cursor, Gemini CLI, and OpenCode are export-only input contracts and intentionally return listing_unavailable; callers locate and read the exports themselves.

import { listTrajectories } from "@letta-ai/trajectory";

let cursor: string | undefined;
do {
  const page = await listTrajectories({ source: "claude-code", limit: 100, cursor });
  for (const item of page.items) {
    // item.id, item.path, item.updatedAt?, item.title?, item.sizeBytes?
  }
  cursor = page.nextCursor;
} while (cursor);

Normalized records

A trajectory is an ordered array containing:

  • One leading meta record identifying the source and available session metadata.
  • user and assistant prose records.
  • Optional reasoning records when the source exposes reasoning.
  • Assistant tool-call records with stable IDs and stringified JSON-object arguments.
  • tool records linked to earlier calls by tool_call_id.

Every conversational record has an ISO timestamp. The complete contract is available as both runtime validation and schema/trajectory-v1.schema.json.

The public function is:

normalizeTranscript(input: NormalizeInput): NormalizeResult

Adding a source

Each native format is implemented as a focused adapter that decodes source events into the shared internal message/tool contract. Common validation, linking, repair, timestamp handling, and bounds remain in the normalization core.

Use prompts/add-source.md with a coding agent to add a source from a local transcript corpus. The prompt covers privacy-safe corpus inspection, sanitized fixtures, compatibility checks, and the transcript-only API boundary.

Development

Requires Node.js 20+ and Bun for development:

bun install
bun run check

bun run check runs typechecking, the complete test suite, and the package build. It also regenerates the JavaScript runtime embedded in the Python wheel and fails if the committed bundle was stale. Run the Python parity suite with:

PYTHONPATH=python/src python3 -m unittest discover -s python/tests -v

See PARITY.md for compatibility checks performed against real transcript corpora and production source adapters. See SOURCE_VERSION_AUDIT.md for the privacy-safe source-version inventory, observed format families, and current decoder gaps.

License

Apache-2.0. See LICENSE.