npm package: @memoryengine/client
Description: Client library for memory engine
Latest version: 0.2.12

# @memoryengine/client

TypeScript client for memory engine. Full type inference from shared Zod schemas — no manual type duplication.

## Install

```bash
npm install @memoryengine/client
```

## Quick Start

```ts
import { createClient } from "@memoryengine/client";

const me = createClient({
  server: "http://localhost:3000",
  apiKey: "me_...",
});

// Store a memory
const memory = await me.memory.create({
  content: "The project deadline is March 15th",
  meta: { source: "meeting-notes", priority: "high" },
  tree: "work.projects.launch",
});

// Search memories (hybrid BM25 + semantic)
const results = await me.memory.search({
  fulltext: "project deadline",
  semantic: "what are the upcoming deadlines?",
  limit: 10,
});

// Get current user
const whoami = await me.auth.whoami();
```

## API

`createClient(options?)` returns a client with namespaced methods:

### Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `server` | `string` | `"http://localhost:3000"` | Server URL |
| `apiKey` | `string` | — | Bearer token for authentication |
| `timeout` | `number` | `30000` | Request timeout (ms) |
| `retries` | `number` | `3` | Max retries with exponential backoff |

### memory

```ts
// Create a memory
await me.memory.create({
  content: "Remember this",
  meta: { source: "chat" },        // optional JSONB metadata
  tree: "work.projects.me",        // optional hierarchical path
  temporal: { start: "2025-03-15" }, // optional time range
});

// Get by ID
await me.memory.get({ id: "019..." });

// Update content, metadata, tree, or temporal
await me.memory.update({
  id: "019...",
  content: "Updated content",
  meta: { source: "chat", reviewed: true },
});

// Delete by ID
await me.memory.delete({ id: "019..." });

// Batch create (up to 1000)
await me.memory.batchCreate({
  memories: [
    { content: "First memory", tree: "notes" },
    { content: "Second memory", tree: "notes" },
  ],
});

// Search — fulltext (BM25), semantic (vector), or both (hybrid)
await me.memory.search({ fulltext: "deadline" });
await me.memory.search({ semantic: "upcoming deadlines" });
await me.memory.search({
  fulltext: "deadline",
  semantic: "upcoming deadlines",
  meta: { source: "meeting-notes" },  // filter by metadata
  tree: "work.*",                      // filter by tree path
  limit: 20,
});

// Move memories between tree paths
await me.memory.mv({
  source: "work.old_project",
  destination: "archive.old_project",
});
```

### auth

```ts
// Login with email/username + password
const { key, principal } = await me.auth.login({
  identifier: "alice@example.com",
  password: "secret",
});

// Get current principal
const whoami = await me.auth.whoami();

// Create an API key
const { key, id } = await me.auth.createApiKey({ name: "ci-bot" });

// List API keys
const keys = await me.auth.listApiKeys();

// Revoke an API key
await me.auth.revokeApiKey({ keyId: "key_id_here" });
```

### principal

```ts
// Create a user
await me.principal.create({
  name: "alice",
  email: "alice@example.com",
  password: "securepass",
  can_login: true,
});

// Create an agent (no login, no email)
await me.principal.create({ name: "indexer-bot" });

// Get principal by name
await me.principal.get({ name: "alice" });

// List all principals
await me.principal.list();

// Set password
await me.principal.setPassword({ name: "alice", password: "newpass123" });

// Delete principal
await me.principal.delete({ name: "alice" });
```

### grant

Tree-based access control — grant read/create/update/delete on hierarchical paths.

```ts
// Grant access
await me.grant.create({
  principal_name: "alice",
  tree_path: "work.projects",
  actions: ["read", "create", "update"],
});

// Check access
await me.grant.check({ tree_path: "work.projects.me", action: "read" });

// List grants (optionally filter by principal)
await me.grant.list();
await me.grant.list({ principal_name: "alice" });

// Revoke access
await me.grant.revoke({
  principal_name: "alice",
  tree_path: "work.projects",
});
```

### owner

Assign ownership of tree paths to principals.

```ts
// Set owner
await me.owner.set({
  tree_path: "work.projects.me",
  principal_name: "alice",
});

// Get owner of a path
await me.owner.get({ tree_path: "work.projects.me" });

// List all ownerships
await me.owner.list();
await me.owner.list({ principal_name: "alice" });

// Remove ownership
await me.owner.remove({ tree_path: "work.projects.me" });
```

### role

Role-based membership for grouping principals.

```ts
// Add member to role
await me.role.addMember({
  role_name: "engineers",
  member_name: "alice",
});

// List role members
await me.role.listMembers({ role_name: "engineers" });

// List roles for a principal
await me.role.listForPrincipal({ principal_name: "alice" });
await me.role.listForPrincipal(); // current principal

// Remove member from role
await me.role.removeMember({
  role_name: "engineers",
  member_name: "alice",
});
```

## Schemas

Import Zod schemas directly for validation or type extraction:

```ts
import { createMemorySchema, memorySchema } from "@memoryengine/client/schemas";
import type { RpcInput, RpcOutput } from "@memoryengine/client/schemas";

// Validate input
const parsed = createMemorySchema.parse(data);

// Extract types from any RPC method
type SearchParams = RpcInput<"memory.search">;
type SearchResult = RpcOutput<"memory.search">;
```

## Low-Level API

```ts
// Typed RPC call
const result = await me.call("memory.search", { semantic: "test" });

// Batch multiple requests in one HTTP round-trip
const [a, b] = await me.batch([
  { method: "memory.get", params: { id: "..." } },
  { method: "auth.whoami" },
]);
```