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

@lineai/memory

v1.0.25

Published

An memory sdk for Line AI agents and assistants.

Readme

@lineai/memory

A comprehensive memory orchestration SDK for Line AI applications, built on top of @lineai/cognee-api.

Overview

@lineai/memory provides a higher-level abstraction over the Cognee API with:

  • Automatic session management - Handle authentication and configuration seamlessly
  • Organization-based multi-tenancy - Strict data isolation between organizations
  • Smart dataset naming strategies - User, project, and organization-scoped datasets
  • Type-safe error handling - Discriminated unions for predictable error handling
  • Functional programming principles - Pure functions, immutability, composition
  • Built-in retry logic - Exponential backoff and circuit breaker patterns

Installation

npm install @lineai/memory
# or
yarn add @lineai/memory

Quick Start

import { createSession, remember, process, search } from '@lineai/memory';

// Create authenticated session
const sessionResult = await createSession({
  cogneeUrl: 'http://localhost:8000',
  credentials: { username: 'alice', password: 'secret' },
  organizationId: 'org-acme-corp',
  datasetStrategy: {
    scope: 'user',
    organizationId: 'org-acme-corp',
    userId: 'alice-123',
  },
});

if (!sessionResult.success) {
  console.error('Failed to create session:', sessionResult.error);
  return;
}

const session = sessionResult.value;

// Remember something
const memoryResult = await remember(session, {
  type: 'text',
  text: 'TypeScript is a typed superset of JavaScript',
});

if (memoryResult.success) {
  console.log('Remembered:', memoryResult.value);
}

// Process into knowledge graph
const processResult = await process(session);

// Search later
const searchResult = await search(session, {
  text: 'What is TypeScript?',
});

if (searchResult.success && searchResult.value.found) {
  console.log('Found:', searchResult.value.results);
}

Core Concepts

Sessions

Sessions represent an authenticated connection to Cognee with dataset strategy configuration:

type Session = {
  readonly cogneeUrl: string;
  readonly organizationId: string;
  readonly userId: string;
  readonly userName: string;
  readonly datasetStrategy: DatasetStrategy;
  readonly config: CogneeConfig;
};

Dataset Strategies

All datasets are organization-scoped for multi-tenant isolation:

// User-scoped: personal memories
const userStrategy: DatasetStrategy = {
  scope: 'user',
  organizationId: 'org-123',
  userId: 'user-456',
};
// Dataset name: "organization_org-123_user_user-456_memories"

// Project-scoped: shared team knowledge
const projectStrategy: DatasetStrategy = {
  scope: 'project',
  organizationId: 'org-123',
  projectId: 'proj-789',
};
// Dataset name: "organization_org-123_project_proj-789_knowledge"

// Organization-scoped: company-wide data
const orgStrategy: DatasetStrategy = {
  scope: 'organization',
  organizationId: 'org-123',
};
// Dataset name: "organization_org-123_shared"

// Custom: define your own naming
const customStrategy: DatasetStrategy = {
  scope: 'custom',
  namingFn: (context) =>
    `organization_${context.organizationId}_custom_${context.customField}`,
};

Error Handling

All functions return Outcome<T> for type-safe error handling:

const result = await remember(session, content);

if (result.success) {
  const memory = result.value;
  console.log('Success:', memory.id);
} else {
  const error = result.error;
  switch (error.error) {
    case 'authentication_failed':
      console.error('Auth failed:', error.message);
      break;
    case 'permission_denied':
      console.error('No access to dataset:', error.datasetId);
      break;
    case 'network_error':
      console.error('Network error:', error.statusCode);
      break;
  }
}

Authentication & Provisioning

@lineai/memory integrates with Cognee's multi-tenant authentication system. Line AI organizations map 1:1 to Cognee tenants, and Line AI users map to Cognee users.

Architecture

  • Cognee TenantLine AI Organization (1:1 mapping)
  • Cognee UserLine AI User (1:1 mapping)
  • Cognee Role ↔ Line AI user groups/roles
  • Dataset Permissions → Managed through Cognee's ACL system

Provisioning Flow

When a Line AI organization is created, you should:

  1. Create admin user (creates admin account without tenant)
  2. Provision organization (creates tenant owned by admin)
  3. Provision additional users (when Line AI users join the organization)
  4. Create roles (optional, for grouping users)

1. Create Admin User

import { provisionAdminUser } from '@lineai/memory';

// Step 1: Create admin user account
const adminResult = await provisionAdminUser({
  cogneeUrl: 'http://localhost:8000',
  superuserCreds: {
    username: '[email protected]',
    password: process.env.COGNEE_ADMIN_PASSWORD,
  },
  adminEmail: '[email protected]',
  // adminPassword is optional - will auto-generate if not provided
});

if (adminResult.success) {
  // IMPORTANT: Store credentials BEFORE creating organization
  await db.users.create({
    email: adminResult.value.email,
    cogneeUserId: adminResult.value.userId,
    cogneePassword: await encrypt(adminResult.value.password), // IMPORTANT: Encrypt!
    role: 'admin',
  });

  // Securely send password to admin
  await sendEmail(adminResult.value.email, adminResult.value.password);
}

2. Provision Organization

import { provisionOrganization } from '@lineai/memory';

// Step 2: Create organization tenant using admin credentials
const orgResult = await provisionOrganization({
  cogneeUrl: 'http://localhost:8000',
  adminEmail: adminResult.value.email,
  adminPassword: adminResult.value.password,
  organizationName: 'acme-corp', // Organization slug
});

if (orgResult.success) {
  // Store tenant ID
  await db.organizations.create({
    cogneeTenantId: orgResult.value.tenantId,
  });

  // Link admin user to organization
  await db.users.update(adminUserId, {
    organizationId: orgId,
  });
}

Why two steps? Separating admin user creation from organization creation prevents an irrecoverable state where the user exists but credentials were never returned. Always store admin credentials before attempting to create the organization.

3. Provision User

import { provisionUser } from '@lineai/memory';

// Get admin credentials (stored during org provisioning)
const org = await db.organizations.findById(orgId);
const admin = await db.users.findOne({ organizationId: orgId, role: 'admin' });
const adminPassword = await decrypt(admin.cogneePassword);

const result = await provisionUser({
  cogneeUrl: 'http://localhost:8000',
  adminEmail: admin.email,
  adminPassword: adminPassword,
  userEmail: '[email protected]',
  // password is optional - will auto-generate if not provided
});

if (result.success) {
  // IMPORTANT: Store userId and ENCRYPTED password
  await db.users.create({
    email: result.value.email,
    cogneeUserId: result.value.userId,
    cogneePassword: await encrypt(result.value.password),
    organizationId: orgId,
  });

  // Securely send password to user
  await sendEmail(result.value.email, result.value.password);
}

4. Create Roles (Optional)

import { createTenantRole } from '@lineai/memory';

// Get admin credentials
const admin = await db.users.findOne({ organizationId: orgId, role: 'admin' });
const adminPassword = await decrypt(admin.cogneePassword);

// Create role using admin credentials
const roleResult = await createTenantRole({
  cogneeUrl: 'http://localhost:8000',
  ownerEmail: admin.email,
  ownerPassword: adminPassword,
  roleName: 'data-scientists',
});

if (roleResult.success) {
  // Store role ID for later use
  await db.roles.create({
    name: 'data-scientists',
    cogneeRoleId: roleResult.value.roleId, // ✅ Real UUID now!
    tenantId: org.cogneeTenantId,
  });
}

Session Creation

Once users are provisioned, create sessions using their Cognee credentials:

import { createSession } from '@lineai/memory';

const sessionResult = await createSession({
  cogneeUrl: 'http://localhost:8000',
  credentials: {
    username: user.email, // Cognee username
    password: await decrypt(user.cogneePassword), // Decrypted password
  },
  organizationId: user.organizationId,
  datasetStrategy: {
    scope: 'user',
    organizationId: user.organizationId,
    userId: user.id,
  },
});

Security Best Practices

  1. Never store passwords in plain text - Always encrypt Cognee passwords before storing
  2. Use environment variables - Store superuser credentials in process.env
  3. Limit superuser access - Only use superuser credentials for provisioning operations
  4. Rotate passwords - Implement password rotation for long-lived users
  5. Use HTTPS - Always use https:// URLs in production

For more details, see AUTHENTICATION.md.

API Reference

Session Management

createSession(params: CreateSessionParams): Promise<Outcome<Session>>

Create a new authenticated session.

const result = await createSession({
  cogneeUrl: 'http://localhost:8000',
  credentials: { username: 'alice', password: 'secret' },
  organizationId: 'org-acme-corp',
  datasetStrategy: {
    scope: 'user',
    organizationId: 'org-acme-corp',
    userId: 'alice-123',
  },
});

endSession(session: Session): Promise<Outcome<void>>

End a session (logout).

await endSession(session);

Memory Operations

remember(session, content, options?): Promise<Outcome<Memory>>

Add content to memory (single item).

// Text content
await remember(session, {
  type: 'text',
  text: 'Important information',
});

// File content
await remember(session, {
  type: 'file',
  file: myFile,
});

// URL content
await remember(session, {
  type: 'url',
  url: 'https://example.com/document.pdf',
});

// With tags and custom dataset
await remember(
  session,
  { type: 'text', text: 'Data' },
  {
    tags: ['important', 'finance'],
    datasetName: 'organization_org-123_custom_dataset',
  }
);

rememberMany(session, contents, options?): Promise<Outcome<readonly Memory[]>>

Add multiple items to memory (batch operation).

await rememberMany(session, [
  { type: 'text', text: 'First item' },
  { type: 'text', text: 'Second item' },
  { type: 'text', text: 'Third item' },
]);

forget(session, memory, mode?): Promise<Outcome<void>>

Remove content from memory.

// Soft delete (default)
await forget(session, memory, 'soft');

// Hard delete
await forget(session, memory, 'hard');

process(session, options?): Promise<Outcome<ProcessingReference>>

Process memories into knowledge graph.

// Process with default dataset
const ref = await process(session);

// Process specific datasets in background
const ref = await process(session, {
  datasetIds: ['dataset-1', 'dataset-2'],
  background: true,
});

getProcessingStatus(session, reference): Promise<Outcome<ProcessingStatus>>

Check processing status.

const status = await getProcessingStatus(session, ref);

if (status.success) {
  if (status.value.complete) {
    console.log('Processing complete!');
  } else if (status.value.error) {
    console.log('Processing failed:', status.value.message);
  } else {
    console.log('Progress:', status.value.progress, '%');
  }
}

Search Operations

search(session, query): Promise<Outcome<SearchOutcome>>

Search across memories (GRAPH_COMPLETION).

const result = await search(session, {
  text: 'What did I learn about TypeScript?',
  topK: 5,
  datasetIds: ['dataset-1'], // Optional
  tags: ['programming'], // Optional
});

if (result.success && result.value.found) {
  result.value.results.forEach((item) => {
    console.log('Dataset:', item.datasetName);
    console.log('Content:', item.content);
  });
}

Specialized Search Functions

  • searchGraph(session, query) - INSIGHTS search
  • searchChunks(session, query) - CHUNKS search
  • searchInsights(session, query) - INSIGHTS search
  • searchSummaries(session, query) - SUMMARIES search
  • searchCode(session, query) - CODE search

getSearchHistory(session, filters?): Promise<Outcome<readonly SearchHistoryItem[]>>

Get search history.

const history = await getSearchHistory(session, {
  since: '2024-01-01',
});

Dataset Management

listDatasets(session): Promise<Outcome<readonly Dataset[]>>

List datasets accessible to user (automatically filtered by organization).

const datasets = await listDatasets(session);

createDataset(session, name): Promise<Outcome<Dataset>>

Create a new dataset explicitly.

await createDataset(session, 'organization_org-123_custom_dataset');

getDatasetGraph(session, datasetId): Promise<Outcome<DatasetGraph>>

Get dataset graph for visualization.

const graph = await getDatasetGraph(session, 'dataset-id-123');

deleteDataset(session, datasetId): Promise<Outcome<void>>

Delete a dataset.

await deleteDataset(session, 'dataset-id-123');

shareDataset(session, datasetId, userId, permissions): Promise<Outcome<void>>

Share dataset with another user.

await shareDataset(session, 'dataset-id-123', 'user-456', [
  'read',
  'write',
]);

Utilities

Retry Logic

import { withRetry, defaultRetryStrategy } from '@lineai/memory';

const result = await withRetry(
  () => remember(session, content),
  {
    ...defaultRetryStrategy,
    maxAttempts: 5,
    initialDelayMs: 500,
  }
);

Circuit Breaker

import { CircuitBreaker } from '@lineai/memory';

const breaker = new CircuitBreaker(5, 60000); // threshold, timeout

const result = await breaker.execute(() => remember(session, content));

Validation

import {
  validateDatasetName,
  validateOrganizationId,
  validateQuery,
  validateUrl,
} from '@lineai/memory';

const nameResult = validateDatasetName('my-dataset');
if (!nameResult.success) {
  console.error(nameResult.error.message);
}

Examples

Simple Chatbot

import {
  createSession,
  remember,
  process,
  search,
  endSession,
} from '@lineai/memory';

const session = await createSession({
  cogneeUrl: 'http://localhost:8000',
  credentials: { username: 'alice', password: 'secret' },
  organizationId: 'org-acme-corp',
  datasetStrategy: {
    scope: 'user',
    organizationId: 'org-acme-corp',
    userId: 'alice-123',
  },
});

if (!session.success) {
  throw new Error('Failed to create session');
}

const s = session.value;

// Remember conversation
await remember(s, {
  type: 'text',
  text: 'User: What is the capital of France?\nBot: Paris',
});

// Process into knowledge graph
await process(s);

// Search later
const outcome = await search(s, {
  text: 'What did I ask about France?',
});

if (outcome.success && outcome.value.found) {
  console.log(outcome.value.results[0].content);
}

await endSession(s);

Multi-user Document System

// Alice creates project dataset
const aliceSession = await createSession({
  cogneeUrl: 'http://localhost:8000',
  credentials: { username: 'alice', password: 'secret' },
  organizationId: 'org-acme-corp',
  datasetStrategy: {
    scope: 'project',
    organizationId: 'org-acme-corp',
    projectId: 'proj-456',
  },
});

// Add project documents
const memory = await remember(aliceSession.value, {
  type: 'file',
  file: projectDoc,
});

// Share with Bob
if (memory.success) {
  await shareDataset(aliceSession.value, memory.value.datasetId, 'bob-789', [
    'read',
  ]);
}

// Bob searches
const bobSession = await createSession({
  cogneeUrl: 'http://localhost:8000',
  credentials: { username: 'bob', password: 'secret' },
  organizationId: 'org-acme-corp',
  datasetStrategy: {
    scope: 'project',
    organizationId: 'org-acme-corp',
    projectId: 'proj-456',
  },
});

const outcome = await search(bobSession.value, {
  text: 'project requirements',
});

RAG Pipeline

import { createSession, remember, process, searchChunks } from '@lineai/memory';

const ragPipeline = async (documents: File[], userQuery: string) => {
  const session = await createSession({
    /* ... */
  });

  if (!session.success) {
    throw new Error('Failed to create session');
  }

  const s = session.value;

  // Ingest documents
  for (const doc of documents) {
    await remember(s, { type: 'file', file: doc });
  }

  // Process
  await process(s, { background: false });

  // Search for relevant chunks
  const outcome = await searchChunks(s, {
    text: userQuery,
    topK: 5,
  });

  if (!outcome.success || !outcome.value.found) {
    return 'No relevant information found';
  }

  // Use chunks as context for LLM
  const context = outcome.value.results.map((r) => r.content).join('\n\n');

  return generateResponse(context, userQuery);
};

Design Principles

  1. Functional Purity - All functions are pure with explicit dependencies
  2. Deterministic Patterns - Discriminated unions instead of status fields
  3. Minimal Abstraction - Direct mapping to domain concepts
  4. Explicit Configuration - All configuration visible at call site
  5. Composition Over Configuration - Compose behaviors instead of flags

Migration from @lineai/cognee-api

Before

import { login, addData, cognify, search, CogneeConfig } from '@lineai/cognee-api';

const config: CogneeConfig = { baseUrl: 'http://localhost:8000' };

await login(config, { username: 'alice', password: 'secret' });
const file = new File(['content'], 'doc.txt');
await addData(config, [file], { datasetName: 'my-dataset' });
await cognify(config, { datasets: ['my-dataset'] });
const results = await search(config, { query: 'test', dataset_name: 'my-dataset' });

After

import { createSession, remember, process, search } from '@lineai/memory';

const session = await createSession({
  cogneeUrl: 'http://localhost:8000',
  credentials: { username: 'alice', password: 'secret' },
  organizationId: 'org-acme-corp',
  datasetStrategy: { scope: 'user', organizationId: 'org-acme-corp', userId: 'alice' },
});

await remember(session.value, { type: 'file', file: new File(['content'], 'doc.txt') });
await process(session.value);
const outcome = await search(session.value, { text: 'test' });

Benefits

  • ✅ Automatic dataset naming with organization isolation
  • ✅ Type-safe error handling with discriminated unions
  • ✅ Built-in session management
  • ✅ Permission enforcement
  • ✅ Retry logic and circuit breaker patterns

License

MIT

Contributing

Issues and pull requests welcome!