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

@locusgraph/client

v0.4.0

Published

TypeScript SDK for LocusGraph memory system

Readme

LocusGraph TypeScript SDK

TypeScript/JavaScript SDK for the LocusGraph memory system — store events, recall memories with semantic search, traverse relationships, and reason over them.

npm install @locusgraph/client

Quick start

import { LocusGraphClient } from '@locusgraph/client';

const client = new LocusGraphClient({
  serverUrl: 'https://us-east-1.locusgraph.com', // region server (see "Connecting")
  agentSecret: process.env.LOCUSGRAPH_AGENT_SECRET,
  graphId: 'my-graph',                            // default graph for calls below
});

// Remember something
await client.storeEvent({
  graph_id: 'my-graph',
  event_kind: 'fact',
  source: 'user',
  context_id: 'preference:dark_mode',
  payload: { data: 'prefers dark mode' },
});

// Recall it later
const result = await client.retrieveMemories({ query: 'what theme do they like?' });
console.log(result.memories);

Concepts

A few ideas make the API click:

  • Graph — an isolated memory space, addressed by an id. One per user, workspace, or project.
  • Context — a named anchor in the graph, written type:slug (e.g. preference:dark_mode, user:alice). It's the stable handle you address memories by.
  • Locus (memory) — an actual stored memory event tied to one or more contexts. You store and search loci; you address them by context. One context can have many loci (reinforcement); one locus can reference many contexts.
  • Source (trust ladder) — every memory is stamped with where it came from. Higher = more trusted, and it feeds retrieval ranking. So a verified fact outranks an assistant guess.

The slug is the filing location — keep it short and canonical so the same idea always lands on the same context.


Connecting

The SDK authenticates with an agent bearer secret and talks directly to a region server (e.g. https://us-east-1.locusgraph.com), not the dashboard/proxy host.

const client = new LocusGraphClient({
  serverUrl: process.env.LOCUSGRAPH_SERVER_URL,   // default: https://us-east-1.locusgraph.com
  agentSecret: process.env.LOCUSGRAPH_AGENT_SECRET,
  graphId: process.env.LOCUSGRAPH_GRAPH_ID,       // optional default graph
});

| Option | Env var | Notes | |--------|---------|-------| | serverUrl | LOCUSGRAPH_SERVER_URL | Region server base URL | | agentSecret | LOCUSGRAPH_AGENT_SECRET | Bearer token. Unscoped tokens can create graphs; graph-scoped tokens are limited to one graph | | graphId | — | Default graph; per-call graphId overrides it |

graphId can be passed per call; methods throw a clear error if no graph is resolvable.


API reference

All methods return the unwrapped response (the { success, data } envelope is handled for you) and throw an Error on non-2xx responses.

Graphs

// Create a graph (needs an unscoped secret)
const g = await client.createGraph('research-notes', 'Papers and findings');
// → { graph_id, name, description, owner_agent_id, created_at }

// List accessible graphs
const { graphs } = await client.listGraphs({ page: 0, page_size: 50 });

Events (writing memory)

// One event
await client.storeEvent({
  graph_id: 'my-graph',
  event_kind: 'fact',           // see "Event kinds"
  source: 'user',               // see "Sources"
  context_id: 'person:alice',   // primary context (type:slug)
  related_to: ['org:acme'],     // optional relationship links
  extends: ['user:alice'],
  payload: { data: 'Alice joined Acme' },
});

// Many events in one round-trip, processed IN ORDER (max 1000)
const batch = await client.storeEventsBatch([
  { event_kind: 'fact', context_id: 'service:auth', payload: { data: 'Auth API' } },
  { event_kind: 'fact', context_id: 'endpoint:login', extends: ['service:auth'], payload: { data: '/login' } },
], 'my-graph');
// → { stored, filtered, failed, results: [...] }

Memories & insights (reading)

// Semantic search
const result = await client.retrieveMemories({
  query: 'what do we know about billing?',
  limit: 10,
  format: 'markdown',          // 'markdown' (default) | 'toon' | 'json'
});

// Reason over memories → a synthesized answer with confidence
const insight = await client.generateInsights({ task: 'Why did we choose Postgres?' });
// → { insight, recommendation, confidence }

Advanced recallretrieveMemories accepts:

| Option | What it does | |--------|--------------| | contextIds | Restrict search to these contexts (intersect) | | boostContextIds | Additively widen: pull in memories linked to these contexts even if text search misses them | | coverageContextIds + coverageGroupPrefix | Spread a share of results across the contexts' timeline — for "list everything" questions | | contextTypes | Filter by { type: [names] } | | sources | Only these provenance sources (e.g. ['user', 'verified']) | | expandDepth | Expand context hierarchy / locus links (default 1) |

// "Everything about Alice", even what text search would miss
await client.retrieveMemories({
  query: 'recent activity',
  boostContextIds: ['user:alice'],
  coverageContextIds: ['user:alice'],
  coverageGroupPrefix: 'session:',
  sources: ['user', 'verified'],
});

Contexts (inspecting & curating)

await client.listContextTypes();                       // types + counts
await client.listContextsByType('preference');         // all contexts of a type
await client.searchContexts('billing');                // keyword/name search
await client.getContextByName('dark_mode');            // by name (throws if 404)
await client.getContext({ context_id: 'preference:dark_mode' }); // by id
await client.batchGetContext(['preference:dark_mode', 'fact:works_at_acme']);

// Delete a context; cascades to its links and orphaned loci
await client.forgetContext({ contextType: 'preference', contextName: 'dark_mode' });

Relationship-aware search. Pass include / format to fold in how matched contexts already connect:

const res = await client.searchContexts('dark', undefined, {
  include: 'relationships',
  format: 'mindmap',          // 'json' (default) | 'mindmap' | 'toon'
});
console.log(res.relationships_text);
// preference:dark_mode
//   └─ contradicted_by ← preference:light_mode
  • format: 'json'res.relationships (a { contextId: ContextLink[] } map)
  • format: 'mindmap' / 'toon'res.relationships_text (one LLM-ready string)

Relationship traversal

// A context's edges
await client.getContextRelationships({
  contextType: 'service', contextName: 'auth',
  linkType: 'extends',          // related_to | extends | reinforces | contradicts
  direction: 'incoming',        // outgoing | incoming | both
});

// Memories from related contexts, in one call
await client.getRelatedMemories({
  contextType: 'service', contextName: 'auth',
  linkType: 'extends', direction: 'incoming',
  query: 'error rates',
});

Resolution (forward references)

When a memory references a context whose locus doesn't exist yet, the link is left unresolved. Reconcile it later:

await client.getUnresolvedOverview();                  // graph-wide unresolved links
await client.getUnresolvedLinks('person:alice');       // for one context
await client.resolve({ context_id: 'person:alice', locus_id: 'locus_123' });
await client.batchResolve({ resolutions: [{ context_id: '...', locus_id: '...' }] });

Event kinds

event_kind categorizes a memory and maps to an internal kind + a default source.

| Group | Kinds | |-------|-------| | Knowledge | fact, knowledge, observation, learned, feedback | | Rules | constraint, rule, constraint_violation | | Actions | action, task, operation, execution, completed | | Decisions | decision, choice, selection, determination | | Routine | routine, heartbeat, status | | Noise | noise, debug, log (filtered from ranking) |

Sources (trust ladder)

source is the provenance of a memory. Higher trust = higher base confidence, and confidence is ~25% of retrieval rank — so the source you stamp matters when memories conflict.

| Source | Trust | Meaning | Aliases | |--------|------|---------|---------| | policy | 0.95 | Organizational mandate | | | verified | 0.90 | Authoritative / validated | validator | | tool | 0.80 | Reliable tool output | executor | | document | 0.75 | Published source (e.g. a file) | | | user | 0.70 | User feedback | | | assistant | 0.60 | Model inference | agent, model | | derived | 0.55 | Second-hand synthesis | | | system | 0.50 | System-generated | |

Context links

Connect contexts when storing an event (each takes context ids):

| Field | Meaning | |-------|---------| | context_id | The memory's primary context | | extends | This is a more specific detail of another (hierarchy) | | related_to | Lateral association | | reinforces | Strengthens an existing memory | | contradicts | Conflicts with / supersedes an existing memory |


Error handling

Methods throw an Error with the status and body on failure; single-context reads throw on 404.

try {
  await client.getContext({ context_id: 'missing:thing' });
} catch (err) {
  console.error(err.message); // "Context not found"
}

TypeScript

Fully typed — every request and response has an exported interface (CreateEventApiRequest, ContextQuery, ContextSearchResponse, …). Import them from the package root:

import { LocusGraphClient, type ContextQuery, type StoreEventResponse } from '@locusgraph/client';

License

MIT