Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 72 additions & 86 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,126 +1,112 @@
# @ledgermem/migrate
# Mnemo Migrate

Importer CLI for moving memories from other providers (or raw JSONL) into [LedgerMem](https://proofly.dev). Resumable, concurrent, and dry-run friendly.
Resumable CLI for importing historical documents and memories into [Mnemo](https://mnemohq.com). It accepts common customer exports without giving Mnemo credentials to the source system.

## Install

```bash
npm install -g @ledgermem/migrate
npm install -g getmnemo-migrate
```

Until the package is published, run it from this repository with `npm run dev --`.

## Quickstart

```bash
export LEDGERMEM_API_KEY=...
export LEDGERMEM_WORKSPACE_ID=ws_...
export MEM0_API_KEY=...

ledgermem-migrate plan from mem0
ledgermem-migrate from mem0 --concurrency 5
ledgermem-migrate status
export GETMNEMO_API_KEY=mn_...
export GETMNEMO_WORKSPACE_ID=...

# Inspect a HubSpot-style CSV export. This makes no API calls.
getmnemo-migrate plan from raw-csv \
--file ./contacts.csv \
--map 'content=*,id=Record ID'

# Submit it to the isolated pilot container and wait for ingestion.
getmnemo-migrate from raw-csv \
--file ./contacts.csv \
--map 'content=*,id=Record ID' \
--container pilot:customer-name
```

## Commands

| Command | Description |
| --- | --- |
| `from <source>` | Run a migration from `<source>` into the configured LedgerMem workspace. |
| `plan from <source>` | Count records and print a sample — no writes. |
| `resume <jobId>` | Resume an interrupted job (skips records that were already written). |
| `status [jobId]` | Show one job's full state, or list the most recent jobs. |
| `cancel <jobId>` | Mark a running job as `paused` locally. |
The `content=*` mapping serializes each complete CSV or JSON record. For cleaner source data, map a specific field instead, such as `content=notes,id=record_id,company=company`.

Common flags: `--concurrency <n>` (default `5`), `--page-size <n>` (default `100`), `--user <id>`, `--base-url <url>`.
## Import Lanes

Job state is persisted to `~/.ledgermem/migrations/<jobId>.json`.
| Lane | Default sources | Behavior |
| --- | --- | --- |
| `document` | CSV, JSON, JSONL, Markdown, text, directories | Sends source material through Mnemo document ingestion so facts, provenance, entities, and time can be extracted. |
| `memory` | Mem0, Zep, Supermemory, Letta | Preserves already-extracted memory text as atomic memories. |

## Adapters
Override the default only when the source semantics require it with `--lane memory` or `--lane document`.

### `mem0`
## File Sources

Pulls memories from the [Mem0](https://mem0.ai) API.
| Source | Required option | Notes |
| --- | --- | --- |
| `raw-csv` | `--file export.csv` | RFC-compatible CSV parsing, including quoted multiline fields. |
| `raw-json` | `--file export.json` | Top-level arrays up to 50 MB. Convert larger files to JSONL. |
| `raw-jsonl` | `--file export.jsonl` | Streams one JSON object per line. |
| `text-file` | `--file notes.md` | Imports one Markdown or text document. |
| `directory` | `--file ./export` | Recursively imports supported files in deterministic order; ignores symlinks and unsupported files. |

- Required env: `MEM0_API_KEY`
- Optional: `--user <id>` to scope to a single Mem0 user, `--base-url` to override (default `https://api.mem0.ai`).
- Pagination: follows the `next` cursor returned by `/v1/memories/`.
Mappings use `target=source` pairs and support dotted source paths:

```bash
MEM0_API_KEY=... ledgermem-migrate from mem0 --user u_42
getmnemo-migrate from raw-json \
--file ./history.json \
--map 'content=payload.body,id=record.id,customer=account.id' \
--container pilot:customer-name
```

### `zep`

Pulls messages from [Zep Cloud](https://www.getzep.com).

- Required env: `ZEP_API_KEY`
- **Required flag:** `--user <id>` (Zep memories belong to a user).
- Optional: `--base-url` (default `https://api.getzep.com`).
- Walks every session belonging to the user and exports each message as a memory.
## Provider Sources

```bash
ZEP_API_KEY=... ledgermem-migrate from zep --user u_42
```

### `supermemory`
| Source | Source credentials | Useful options |
| --- | --- | --- |
| `mem0` | `MEM0_API_KEY` | `--user`, `--base-url` |
| `zep` | `ZEP_API_KEY` | `--user` is required, `--base-url` |
| `supermemory` | `SUPERMEMORY_API_KEY` | `--base-url` |
| `letta` | `LETTA_API_KEY`, `LETTA_BASE_URL` | Imports core and archival memory |

Pulls items from the Supermemory API.
## Safe Operating Flow

- Required env: `SUPERMEMORY_API_KEY`
- Optional: `--base-url` (default `https://api.supermemory.ai`).
- Uses the `/v3/memories` cursor pagination.
1. Export data from the source system.
2. Run `plan from ...` and inspect the count plus sample. No Mnemo credentials are needed for planning.
3. Import into a customer-specific container with conservative concurrency.
4. Keep the printed migration job ID.
5. Run `status <jobId>` or `reconcile <jobId>` to obtain the final completion report.
6. Validate retrieval against a small set of customer-approved questions before connecting an agent.

```bash
SUPERMEMORY_API_KEY=... ledgermem-migrate from supermemory
getmnemo-migrate status
getmnemo-migrate cancel mig_...
getmnemo-migrate resume mig_...
getmnemo-migrate reconcile mig_...
```

### `letta`
Cancellation pauses after the current bounded batch. Resume skips successful source records and retries unresolved ones. Mnemo custom IDs and idempotency keys also protect against duplicate writes if local state is lost.

Pulls both core memory blocks and archival memories from a Letta server.
Job state, processed IDs, remote job IDs, and failure journals are stored under `~/.getmnemo/migrations` with owner-only permissions. Set `GETMNEMO_MIGRATION_DIR` to use another state directory.

- Required env: `LETTA_API_KEY`, `LETTA_BASE_URL`
- Iterates every agent and exports core blocks (`core_block` kind) plus paginated archival memories (`archival` kind).

```bash
LETTA_API_KEY=... LETTA_BASE_URL=https://my-letta-host \
ledgermem-migrate from letta
```
## Reliability Limits

### `raw-jsonl`

Generic ingest from a local JSONL file. Each line is one record.

- Required flag: `--file <path>`
- Optional: `--map content=text,id=mem_id,topic=category` (default `content=content,id=id`).
- Dotted paths are supported in `--map` source keys (`content=payload.body`).

```bash
ledgermem-migrate from raw-jsonl \
--file ./memories.jsonl \
--map content=text,id=mem_id,user=user_id
```

## Resuming

Every successful write records the source's native id in the job state. Re-running with `resume <jobId>` skips those ids, so transient network failures are recoverable without dedup work.

```bash
ledgermem-migrate from mem0 --concurrency 10
# ... interrupted ...
ledgermem-migrate status
ledgermem-migrate resume mig_abc123...
```
- Concurrency is capped at 25 even if a larger value is requested.
- HTTP 429 and server/network failures retry up to five times with backoff.
- Documents larger than the API limit are split deterministically near line boundaries.
- Atomic memories longer than the memory endpoint limit are split with part metadata.
- JSON arrays are capped at 50 MB to avoid loading unbounded files into memory; JSONL and CSV stream.
- The completion report distinguishes accepted writes from completed and failed ingestion jobs.

## Environment

| Variable | Purpose |
| --- | --- |
| `LEDGERMEM_API_KEY` | Destination API key. **Required.** |
| `LEDGERMEM_WORKSPACE_ID` | Destination workspace. **Required.** |
| `LEDGERMEM_API_URL` | Destination API base URL (default `https://api.proofly.dev`). |
| `MEM0_API_KEY` | mem0 adapter |
| `ZEP_API_KEY` | zep adapter |
| `SUPERMEMORY_API_KEY` | supermemory adapter |
| `LETTA_API_KEY` + `LETTA_BASE_URL` | letta adapter |
| `GETMNEMO_API_KEY` | Destination API key. Required for writes and reconciliation. |
| `GETMNEMO_WORKSPACE_ID` | Destination workspace. Required for writes and reconciliation. |
| `GETMNEMO_API_URL` | API base URL. Defaults to `https://api.mnemohq.com`. |
| `GETMNEMO_CONTAINER_TAG` | Optional default destination container. |
| `GETMNEMO_MIGRATION_DIR` | Optional local checkpoint directory. |

See [Pilot integration contract](./docs/pilot-integration.md) for the boundary between source exports, Mnemo, governance, and agents.

## License

Expand Down
81 changes: 81 additions & 0 deletions docs/pilot-integration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Pilot Integration Contract

This is the minimum integration surface for the Kira, governance, and Mnemo pilot discussed on 22 July 2026.

## Responsibility Boundary

```text
customer-approved exports
|
v
Mnemo Migrate -> Mnemo ingestion and isolated memory
|
v
governance and guardrails
|
v
Kira and swarm agents
```

Mnemo owns historical import, source provenance, customer isolation, durable memory, and retrieval. The governance layer decides which memories an agent may use and applies business protocols. Kira and swarm agents own user interaction and task execution.

The pilot does not require Mnemo to hold HubSpot, Notion, database, or email credentials. The customer exports approved data, the import is reviewed locally, and only the approved export is sent to Mnemo. Native source connectors can be evaluated later from observed pilot demand.

## Pilot Inputs

Start with a bounded export rather than every available system:

- one customer;
- one source, such as a HubSpot CSV export;
- one Mnemo workspace and one customer-specific container;
- a small customer-approved retrieval question set;
- no secrets, credentials, or fields outside the agreed pilot scope.

## Import Procedure

```bash
getmnemo-migrate plan from raw-csv \
--file ./hubspot-export.csv \
--map 'content=*,id=Record ID'

getmnemo-migrate from raw-csv \
--file ./hubspot-export.csv \
--map 'content=*,id=Record ID' \
--container pilot:customer-name \
--concurrency 5
```

Record the migration job ID and keep the local migration directory until acceptance is complete. A paused or interrupted import is resumed with `getmnemo-migrate resume <jobId>`; it does not restart successful records.

## Runtime API Contract

The integrated system needs three Mnemo operations:

| Operation | Endpoint | Purpose |
| --- | --- | --- |
| Add source material | `POST /v1/documents` | Asynchronous ingestion with provenance and deterministic `customId`. |
| Check ingestion | `GET /v1/jobs?ids=...` | Completion and failure reconciliation in groups of at most 50 job IDs. |
| Retrieve context | `POST /v1/search` | Scoped retrieval for the governance layer before an agent acts. |

Authenticate with a Mnemo API key and `x-workspace-id`. Every document and search request must use the pilot customer container. API credentials stay in the server-side governance service, never in Kira’s browser or prompt.

The governance layer should call search with `includeSources: true` so it can retain evidence, then apply its own access rules before returning context to an agent.

## Acceptance Evidence

The pilot is ready for agent integration when all of the following are true:

- the import plan count matches the approved export;
- the final report has no pending jobs and any failed records are explained or retried;
- rerunning or resuming does not create duplicate source records;
- customer-approved test questions retrieve the expected current context and provenance;
- searches cannot cross the pilot customer’s workspace and container boundary;
- removing Mnemo access from the governance service prevents further reads and writes.

## Deliberately Deferred

- direct HubSpot or Notion OAuth connectors;
- continuous bidirectional synchronization;
- governance policy authoring inside Mnemo;
- Kira prompt conversion and swarm construction;
- broad ingestion of every customer system before pilot retrieval is validated.
Loading