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

@dot-agent/language-server

v0.4.1

Published

LSP server for .agent DSL files

Readme

Agent DSL Language Server

A standalone Language Server Protocol (LSP) server for the .agent DSL (.description, .type, .behavior) files. Shared by the VS Code and Zed extensions.

Features

| Capability | .description | .behavior | |---|---|---| | Hover | Keyword documentation | Keyword documentation | | Completion | Manifest keywords, custom types | Keywords, state names, memory domains (context., session., …) | | Diagnostics | Strict block lint, undeclared types | Dangling transition targets, dead-end interact | | Go-to-Definition | Type name → type declaration | transition to stateNamestate declaration | | Find References | All uses of a type | All transition references to a state | | Rename | Type and its references | State and all transition references | | Document Symbols | Agents, types | States, on event observers | | Formatting | 0 / 2-space indentation | 0 / 2 / 4-space indentation by block depth |

The VS Code extension adds two capabilities on top: Behavior Graph (Mermaid state diagram WebView) and status bar (current state indicator). Those are VS Code-specific and live in extension.js.

Architecture

┌──────────────┐   LSP/stdio   ┌─────────────────────────────────┐
│  VS Code     │ ←──────────── │  server.js                      │
│  Zed         │               │   ├── features/hover.js          │
│  Neovim/etc  │               │   ├── features/completions.js    │
└──────────────┘               │   ├── features/diagnostics.js    │
                               │   ├── features/definition.js     │
                               │   ├── features/references.js     │
                               │   ├── features/rename.js         │
                               │   ├── features/symbols.js        │
                               │   └── features/formatting.js     │
                               │   parser.js  (tree-sitter engine)│
                               └─────────────────────────────────┘

The server speaks LSP over stdio. Each editor starts it as a subprocess and communicates via JSON-RPC messages.

All structural analysis uses the tree-sitter parse trees from @dot-agent/tree-sitter. parser.js initializes the WASM-based parsers during initialize and maintains a per-document AST cache with incremental reparse.

Prerequisites

The grammar package must have its WASM binaries built before first use:

cd dsl/tree-sitter-agent
npm run build          # requires Emscripten; generates dist/*.wasm

When consuming the package from npm (published), dist/ is already included — no build step needed.

Installation

Standalone (Neovim, Helix, or any LSP-capable editor):

git clone [email protected]:daniloborges/language-server.git
cd language-server
# Build the grammar WASMs first (see Prerequisites above)
npm install

As a git submodule:

git submodule add [email protected]:daniloborges/language-server.git dsl/language-server

Usage

Run directly over stdio:

node server.js --stdio

Neovim (nvim-lspconfig)

local lspconfig = require('lspconfig')
local configs = require('lspconfig.configs')

if not configs.agent_dsl then
  configs.agent_dsl = {
    default_config = {
      cmd = { 'node', '/path/to/language-server/server.js', '--stdio' },
      filetypes = { 'description', 'behavior' },
      root_dir = lspconfig.util.root_pattern('.git'),
    },
  }
end

lspconfig.agent_dsl.setup {}

Helix (~/.config/helix/languages.toml)

[[language]]
name = "description"
language-servers = ["agent-dsl-lsp"]

[[language]]
name = "behavior"
language-servers = ["agent-dsl-lsp"]

[language-server.agent-dsl-lsp]
command = "node"
args = ["/path/to/language-server/server.js", "--stdio"]

VS Code Integration

The VS Code extension installs the server as an npm dependency and starts it automatically via vscode-languageclient. No manual setup needed — install the .vsix and the server starts with the editor.

Zed Integration

Configured in zed-agent/extension.toml under [language_servers.agent-dsl-lsp]. Note: Zed extensions with full LSP support may require Rust bindings depending on the Zed version.

Development

Adding a new LSP capability

  1. Create features/my-feature.js exporting a provideXxx(langId, tree, text, ...) function.
  2. Import and wire it in server.js via connection.onXxx(...), passing getTree(doc) and doc.getText().

Shared parsing helpers (parser.js)

| Export | Description | |---|---| | initParsers() | Async — initializes both WASM parsers. Called once inside onInitialize. | | parse(uri, langId, text, version) | Returns a cached Tree for the document, reparsing incrementally on version change. | | evict(uri) | Removes a document's cached tree on close. | | nodesOfType(tree, type) | SyntaxNode[] — all descendants of the given node type. | | nodeAtOffset(tree, offset) | The deepest node at a byte offset. | | nodeToRange(node) | Converts a SyntaxNode to an LSP Range via startPosition/endPosition. | | positionToOffset(text, line, character) | Converts an LSP {line, character} to a byte offset. | | wordAtPosition(text, line, character) | Extracts the identifier (including dots) around a cursor position. | | getContextNode(tree, offset) | Walks up past ERROR/MISSING nodes to find a clean context ancestor. |

Testing features manually

# Parse a real file and inspect the AST
node -e "
const { initParsers, parse, nodesOfType } = require('./parser');
(async () => {
  await initParsers();
  const text = require('fs').readFileSync('../examples/doctor/doctor.behavior', 'utf8');
  const tree = parse('f', 'behavior', text, 1);
  console.log(nodesOfType(tree, 'state_decl').map(n => n.childForFieldName('name').text));
})();
"

# Run a diagnostic check
node -e "
const { initParsers, parse } = require('./parser');
const { diagnose } = require('./features/diagnostics');
(async () => {
  await initParsers();
  const text = 'state greeting\n  interact\n  transition to missing\n';
  const tree = parse('f', 'behavior', text, 1);
  console.log(diagnose('behavior', tree, text));
})();
"

Testing the full LSP protocol

node -e "
const { spawn } = require('child_process');
const p = spawn('node', ['server.js', '--stdio']);
const msg = JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'initialize', params: { processId: null, rootUri: null, capabilities: {} } });
p.stdin.write('Content-Length: ' + Buffer.byteLength(msg) + '\r\n\r\n' + msg);
p.stdout.on('data', d => { console.log(d.toString()); p.kill(); });
"

License

Copyright (c) 2026 Danilo Borges (https://github.com/daniloborges)

Licensed under the Apache License, Version 2.0 — see LICENSE.