# Vercel AI SDK Adapter (/docs/adapters/ai-sdk) > Vercel AI SDK adapter for MemoFS runtime bridging, tool definitions, and memory context builders. The `@memofs/adapter-ai-sdk` adapter bridges MemoFS memory into [Vercel AI SDK](https://sdk.vercel.ai/) applications (`ai` package). It provides ready-to-use tool definitions, progressive prompt context builders, and multi-tenant scoping policies (`project`, `user`, `conversation`) for `generateText`, `streamText`, and AI agent loops. ## Installation [#installation] ```bash npm install @memofs/adapter-ai-sdk ai @ai-sdk/openai zod ``` ```bash pnpm add @memofs/adapter-ai-sdk ai @ai-sdk/openai zod ``` ```bash bun add @memofs/adapter-ai-sdk ai @ai-sdk/openai zod ``` ```bash deno add npm:@memofs/adapter-ai-sdk npm:ai npm:@ai-sdk/openai npm:zod ``` Requires **Node.js >= 22** and **`ai >= 5.0.0 < 7.0.0`**. ## Usage [#usage] Create an AI SDK runtime bridge with `createAiSdkRuntimeFromMemoFS()` and inject memory tools into `generateText`: ```ts import { createNodeMemoFs } from "@memofs/core/node-fs"; import { openai } from "@ai-sdk/openai"; import { generateText } from "ai"; import { createAiSdkRuntimeFromMemoFS, buildRuntimeMemoryToolDefinition, buildRuntimeMemoryContext, } from "@memofs/adapter-ai-sdk"; // 1. Initialize MemoFS and bridge to AI SDK runtime const memo = createNodeMemoFs({ rootDir: "." }); const runtime = createAiSdkRuntimeFromMemoFS(memo); // 2. Build initial prompt context (core memory + relevant recall) const memoryContext = await buildRuntimeMemoryContext({ runtime, query: "What are our database choices?", includeCoreMemory: true, includeRecall: true, }); // 3. Build Vercel AI SDK tool definition const memoryTool = buildRuntimeMemoryToolDefinition({ runtime, access: { projectId: "app-prod", userId: "usr_alice", }, allowWrites: true, allowCoreUpdates: false, }); // 4. Run AI generation with memory tool support const response = await generateText({ model: openai("gpt-4o"), system: `You are an AI assistant. Project Memory:\n${memoryContext.text}`, tools: { memory: memoryTool, }, prompt: "Save a decision that we use Cloudflare D1 for our relational store.", }); console.log(response.text); ``` ```ts import { createNodeMemoFs } from "@memofs/core/node-fs"; import { openai } from "@ai-sdk/openai"; import { streamText } from "ai"; import { createAiSdkRuntimeFromMemoFS, buildRuntimeMemoryToolDefinition, } from "@memofs/adapter-ai-sdk"; const memo = createNodeMemoFs({ rootDir: "." }); const runtime = createAiSdkRuntimeFromMemoFS(memo); const result = streamText({ model: openai("gpt-4o"), tools: { memory: buildRuntimeMemoryToolDefinition({ runtime, allowWrites: true, }), }, prompt: "What decisions have we recorded about API rate limits?", }); for await (const chunk of result.textStream) { process.stdout.write(chunk); } ``` ## Supported Tool Commands [#supported-tool-commands] The tool generated by `buildRuntimeMemoryToolDefinition` exposes a Zod schema (`runtimeMemoryToolInputSchema`) supporting 7 unified commands: | Command | Action | Key Parameters | | ------------------------ | ----------------------------------------------------------- | ------------------------------------------------------------- | | **`read_core_memory`** | Reads the root `rules.md` / core memory. | None | | **`update_core_memory`** | Updates core rules (requires `allowCoreUpdates: true`). | `content` | | **`remember`** | Stores a classified note in `notes.md` with tenant scoping. | `content`, `title?`, `kind?`, `tags?`, `scope?`, `metadata?` | | **`list_notes`** | Lists notes filtered by tenant access permissions. | `limit?`, `kind?`, `tag?` | | **`recall`** | Performs hybrid vector/keyword search with scope filters. | `query`, `topK?`, `strategy?`, `rerank?` | | **`build_context`** | Assembles formatted markdown context for prompt injection. | `query?`, `maxChars?`, `includeCoreMemory?`, `includeRecall?` | | **`index`** | Triggers asynchronous embedding index regeneration. | `mode?`, `force?` | ## Multi-Tenant Scoping & Security Policies [#multi-tenant-scoping--security-policies] `@memofs/adapter-ai-sdk` enforces tenant isolation and safety guardrails: ```ts interface AccessContext { projectId: string; userId?: string; conversationId?: string; role?: "system" | "admin" | "user" | "guest"; } ``` 1. **Scope Boundaries:** Memories can be written at `"project"`, `"user"`, or `"conversation"` scope. Reads and recall queries automatically filter out records that belong to different users or conversations. 2. **Secret Guardrails:** The tool scans content against private key and token regex patterns (`assertSafeContent`) before writing, rejecting accidental credential leaks unless `allowSecrets: true` is explicitly configured. 3. **Write Discipline:** Scoped notes are saved with `source: "ai-sdk"` and carry structured provenance metadata. ## Tool Configuration Options (`RuntimeMemoryToolOptions`) [#tool-configuration-options-runtimememorytooloptions] | Option | Type | Default | Description | | ------------------ | --------------------- | ---------------- | ----------------------------------------------------------------- | | `runtime` | `MemoFSMemoryRuntime` | — (**Required**) | Initialized runtime bridge from `createAiSdkRuntimeFromMemoFS()`. | | `access` | `AccessContext` | — | Multi-tenant user and session identity metadata. | | `allowWrites` | `boolean` | `true` | Whether the model can write memories via the `remember` command. | | `allowCoreUpdates` | `boolean` | `false` | Whether the model is permitted to mutate `rules.md`. | | `allowIndexing` | `boolean` | `false` | Whether to allow on-demand indexing commands. | | `allowSecrets` | `boolean` | `false` | Bypass secret scanning (for dedicated credential workflows only). | | `maxContentChars` | `number` | `50000` | Maximum character length allowed for written memory notes. | ## Core Functions Reference [#core-functions-reference] ### `createAiSdkRuntimeFromMemoFS(memo)` [#createaisdkruntimefrommemofsmemo] Wraps any `MemoFS` client into a `MemoFSMemoryRuntime` adapter. ### `buildRuntimeMemoryToolDefinition(options)` [#buildruntimememorytooldefinitionoptions] Generates an AI SDK compatible tool definition with full Zod input schemas and execution handlers. ### `buildRuntimeMemoryContext(options)` [#buildruntimememorycontextoptions] Assembles a unified markdown prompt block combining core rules, relevant notes, and semantic recall results. ### `buildAgentSessionInstructions(options)` [#buildagentsessioninstructionsoptions] Generates system prompt instructions for agents executing inside AgentFS virtual workspace sessions. ## See Also [#see-also] * [Adapters Overview](/adapters/) * [Vercel AI SDK Cookbook](/cookbooks/ai-sdk) * [Model Context Protocol (MCP)](/mcp/) * [Core Memory Runtime](/core/memory) --- # Adapters Overview (/docs/adapters) > Overview of storage and intelligence provider adapters for MemoFS: OpenAI, Voyage, Transformers.js, Cloudflare Workers AI, R2, Turso, and Vercel AI SDK. MemoFS keeps its core runtime (`@memofs/core`) free of vendor dependencies — no hard ties to specific LLM providers, vector databases, object stores, or cloud platforms. All external integrations — OpenAI embeddings, Voyage AI embeddings/reranking, local ONNX models, Cloudflare R2 blob storage, Turso / libSQL metadata, and the Vercel AI SDK — live in separate **adapter packages**. ## The Two Adapter Axes [#the-two-adapter-axes] Adapters fall along two axes: 1. **Storage Axis:** Translates the runtime's canonical `.memofs/` filesystem operations to remote serverless blobs and relational metadata manifests. 2. **Intelligence Axis:** Enriches local and cloud memory operations with vector embeddings, semantic reranking, graph entity extraction, and agent runtime toolkits. ## Available Adapter Packages [#available-adapter-packages] | Package | Category | Primary Interface | Target Environment | Key Purpose | | ------------------------------------------------------------ | --------------- | ----------------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------- | | **[`@memofs/adapter-openai`](/adapters/openai)** | Intelligence | `MemoryEmbedder` | Node.js (>= 22), Edge | Hosted vector embeddings via OpenAI `text-embedding-3-small`, `text-embedding-3-large`, and `ada-002`. | | **[`@memofs/adapter-voyage`](/adapters/voyage)** | Intelligence | `MemoryEmbedder` & `Reranker` | Node.js (>= 22), Edge | High-precision domain embeddings (`voyage-4`, `voyage-3`) and neural reranking (`rerank-2.5-lite`). | | **[`@memofs/adapter-transformers`](/adapters/transformers)** | Intelligence | `MemoryEmbedder` | Node.js (>= 22) | 100% offline, local ONNX sentence embeddings (`Xenova/bge-small-en-v1.5`) with zero API keys or cloud dependencies. | | **[`@memofs/adapter-workers-ai`](/adapters/workers-ai)** | Intelligence | `Extractor` | Cloudflare Workers | Serverless entity-relationship knowledge graph extraction using `@cf/meta/llama-3.1-8b-instruct`. | | **[`@memofs/adapter-r2`](/adapters/r2)** | Storage | `BlobClient` | Cloudflare Workers | Content-addressed raw byte storage (`r2_key === sha256`) for distributed serverless memory stores. | | **[`@memofs/adapter-turso`](/adapters/turso)** | Storage | `MetadataStore` | Node.js (>= 22), Cloudflare Workers | Project manifest metadata and serialized transaction locking (`BEGIN IMMEDIATE`) over libSQL `project_files`. | | **[`@memofs/adapter-ai-sdk`](/adapters/ai-sdk)** | Agent Framework | `MemoFSMemoryRuntime` | Node.js (>= 22), Edge | Vercel AI SDK tool definitions, prompt context builders, and multi-tenant memory scoping policies. | ## Contract Architecture & Provider Neutrality [#contract-architecture--provider-neutrality] Every adapter satisfies an interface defined strictly in `@memofs/core`: 1. **Storage Decoupling:** `RemoteBlobMemoryStore` in core composes an injected `BlobClient` and `MetadataStore`. The R2 blob client and Turso metadata store are published in separate packages so storage layers can be mixed and matched without N×M package bloat. 2. **Deterministic Defaults & Fallbacks:** If no embedder or extractor is configured, MemoFS continues to function safely using deterministic fallbacks (BM25 keyword search, fuzzy lexical matching, and regex rule-based graph extraction). Adding an adapter upgrades recall quality without changing your application code. 3. **No Secret Leaks:** Adapters handle client authentication locally in memory. Tokens and private keys never touch memory files or replicated git manifests. ## Composition Examples [#composition-examples] ### 1. Local Node.js with Transformers.js (Zero API Keys) [#1-local-nodejs-with-transformersjs-zero-api-keys] ```ts import { createNodeMemoFs } from "@memofs/core/node-fs"; import { createTransformersEmbedder } from "@memofs/adapter-transformers"; const memo = createNodeMemoFs({ rootDir: ".", embedder: createTransformersEmbedder(), }); ``` ```ts import { MemoFS } from "@memofs/core"; import { createNodeFsMemoryStore } from "@memofs/core/node-fs"; import { createTransformersEmbedder } from "@memofs/adapter-transformers"; const memo = new MemoFS({ store: createNodeFsMemoryStore({ rootDir: "." }), projectId: "local-app", mode: "local", embedder: createTransformersEmbedder(), }); ``` ### 2. Node.js with OpenAI Embeddings & Voyage Reranking [#2-nodejs-with-openai-embeddings--voyage-reranking] ```ts import { createNodeMemoFs } from "@memofs/core/node-fs"; import { createOpenAIEmbedder } from "@memofs/adapter-openai"; import { createVoyageReranker } from "@memofs/adapter-voyage"; const memo = createNodeMemoFs({ rootDir: ".", embedder: createOpenAIEmbedder({ apiKey: process.env.OPENAI_API_KEY!, model: "text-embedding-3-small", }), reranker: createVoyageReranker({ apiKey: process.env.VOYAGE_API_KEY!, model: "rerank-2.5-lite", }), }); ``` ```ts import { MemoFS } from "@memofs/core"; import { createNodeFsMemoryStore } from "@memofs/core/node-fs"; import { createOpenAIEmbedder } from "@memofs/adapter-openai"; import { createVoyageReranker } from "@memofs/adapter-voyage"; const memo = new MemoFS({ store: createNodeFsMemoryStore({ rootDir: "." }), projectId: "hybrid-app", mode: "local", embedder: createOpenAIEmbedder({ apiKey: process.env.OPENAI_API_KEY!, model: "text-embedding-3-small", }), reranker: createVoyageReranker({ apiKey: process.env.VOYAGE_API_KEY!, model: "rerank-2.5-lite", }), }); ``` ### 3. Serverless Cloudflare Worker with R2, Turso, and Workers AI [#3-serverless-cloudflare-worker-with-r2-turso-and-workers-ai] ```ts import { MemoFS, RemoteBlobMemoryStore } from "@memofs/core"; import { createR2BlobClient } from "@memofs/adapter-r2"; import { createTursoMetadataStore } from "@memofs/adapter-turso"; import { createWorkersAiExtractor } from "@memofs/adapter-workers-ai"; import { createClient } from "@libsql/client"; export interface Env { BLOBS: R2Bucket; TURSO_DATABASE_URL: string; TURSO_AUTH_TOKEN: string; AI: Ai; } export default { async fetch(request: Request, env: Env): Promise { const dbClient = createClient({ url: env.TURSO_DATABASE_URL, authToken: env.TURSO_AUTH_TOKEN, }); const projectId = "team-proj-123"; // Compose storage from decoupled R2 blob client and Turso metadata store const store = new RemoteBlobMemoryStore({ blobClient: createR2BlobClient({ binding: env.BLOBS }), metadata: createTursoMetadataStore({ client: dbClient, projectId }), rootKey: projectId, }); const memo = new MemoFS({ store, projectId, mode: "local", extractor: createWorkersAiExtractor({ ai: env.AI }), }); // Handle memory requests... const context = await memo.context({ query: "architecture standards" }); return new Response(JSON.stringify(context), { headers: { "Content-Type": "application/json" }, }); }, }; ``` ## See Also [#see-also] * [OpenAI Adapter Reference](/adapters/openai) * [Voyage AI Adapter Reference](/adapters/voyage) * [Transformers.js Adapter Reference](/adapters/transformers) * [Workers AI Adapter Reference](/adapters/workers-ai) * [Cloudflare R2 Adapter Reference](/adapters/r2) * [Turso / libSQL Adapter Reference](/adapters/turso) * [Vercel AI SDK Adapter Reference](/adapters/ai-sdk) --- # OpenAI Adapter (/docs/adapters/openai) > OpenAI embeddings adapter for MemoFS vector search and semantic recall. The `@memofs/adapter-openai` adapter provides vector embedding capabilities for MemoFS using OpenAI's embeddings API (`/v1/embeddings`). It implements the core [`MemoryEmbedder`](/api/core#memoryembedder) interface, providing automatic batch chunking, dimension truncation, exponential backoff retries with jitter, and robust input/response validation. ## Subpath Exports [#subpath-exports] | Export Path | Target Environment | Description | | ------------------------------------ | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | | **`@memofs/adapter-openai`** | Node.js (>= 22), Edge | **Root entry.** Exposes `OpenAIEmbedder`, `createOpenAIEmbedder`, `OpenAISdkEmbeddingsClient`, `createOpenAIClient`, model utilities, and error classes. | | **`@memofs/adapter-openai/testing`** | Test runners | Exposes `createFakeOpenAIClient` and `FakeOpenAIEmbeddingsClient` for deterministic unit and integration tests without network calls. | ## Installation [#installation] ```bash npm install @memofs/adapter-openai ``` ```bash pnpm add @memofs/adapter-openai ``` ```bash bun add @memofs/adapter-openai ``` ```bash deno add npm:@memofs/adapter-openai ``` Requires **Node.js >= 22** when running under the Node.js runtime. ## Usage [#usage] Instantiate the embedder with `createOpenAIEmbedder()` and pass it to your MemoFS instance: ```ts import { createNodeMemoFs } from "@memofs/core/node-fs"; import { createOpenAIEmbedder } from "@memofs/adapter-openai"; const memo = createNodeMemoFs({ rootDir: ".", embedder: createOpenAIEmbedder({ apiKey: process.env.OPENAI_API_KEY!, model: "text-embedding-3-small", dimensions: 1536, }), }); ``` ```ts import { MemoFS } from "@memofs/core"; import { createNodeFsMemoryStore } from "@memofs/core/node-fs"; import { createOpenAIEmbedder } from "@memofs/adapter-openai"; const memo = new MemoFS({ store: createNodeFsMemoryStore({ rootDir: "." }), projectId: "openai-app", mode: "local", embedder: createOpenAIEmbedder({ apiKey: process.env.OPENAI_API_KEY!, model: "text-embedding-3-small", dimensions: 1536, }), }); ``` ## Supported Models & Dimensions [#supported-models--dimensions] `@memofs/adapter-openai` provides built-in validation for known OpenAI embedding models and allows custom string model names for forward compatibility: | Model Identifier | Default Dimensions | Flexible Dimensions Supported | Typical Use Case | | --------------------------------- | ------------------ | ------------------------------------- | --------------------------------------------------------- | | **`text-embedding-3-small`** | `1536` | Yes (`<= 1536`, e.g. 512, 1024) | High efficiency, general coding and documentation recall. | | **`text-embedding-3-large`** | `3072` | Yes (`<= 3072`, e.g. 256, 1024, 1536) | Maximum semantic precision for large multi-hop codebases. | | **`text-embedding-ada-002`** | `1536` | No (fixed at 1536) | Legacy compatibility. | | **Custom string (`string & {}`)** | Model default | Configurable | Custom or fine-tuned OpenAI proxy deployments. | ## Configuration API (`OpenAIEmbedderConfig`) [#configuration-api-openaiembedderconfig] The `createOpenAIEmbedder(config)` factory accepts `OpenAIEmbedderConfig`: | Option | Type | Default | Description | | ----------------------------- | ------------------------ | -------------------------- | ------------------------------------------------------------------------------------------- | | `apiKey` | `string` | — | OpenAI API key. Mutually exclusive with `client`. Required unless `client` is provided. | | `client` | `OpenAIEmbeddingsClient` | — | Pre-configured client instance (e.g. `OpenAISdkEmbeddingsClient` or test fake). | | `model` | `OpenAIEmbeddingModel` | `"text-embedding-3-small"` | Model identifier to use for embeddings. | | `dimensions` | `number` | Model default | Target vector dimensions. Validated against model capabilities. | | `baseUrl` | `string` | `"https://api.openai.com"` | Base URL override for custom proxies or Azure OpenAI gateways. | | `organization` | `string` | — | OpenAI organization identifier (`OpenAI-Organization` header). | | `project` | `string` | — | OpenAI project identifier (`OpenAI-Project` header). | | `fetch` | `OpenAIFetchLike` | `globalThis.fetch` | Custom `fetch` implementation for edge runtimes or mock interceptors. | | `timeoutMs` | `number` | `30000` (30s) | Request timeout in milliseconds. | | `retry` | `OpenAIRetryOptions` | See below | Retry options for transient network and rate limit errors. | | `userAgent` | `string` | — | Custom User-Agent header string. | | `batchSize` | `number` | `128` | Maximum texts per API request (automatically chunked up to `OPENAI_MAX_BATCH_SIZE = 2048`). | | `encodingFormat` | `"float"` | `"float"` | Vector encoding format. Base64 is rejected because MemoFS expects numeric arrays. | | `user` | `string` | — | Unique end-user identifier forwarded to OpenAI for abuse monitoring. | | `expectedDimensions` | `number` | — | Strict expected dimension validation check. | | `allowEmptyText` | `boolean` | `false` | Whether to allow empty strings (`""`) without throwing validation errors. | | `allowUnknownModelDimensions` | `boolean` | `true` | Whether custom models can accept explicit dimensions without failing validation. | ### Retry Options (`OpenAIRetryOptions`) [#retry-options-openairetryoptions] ```ts interface OpenAIRetryOptions { maxRetries?: number; // Default: 2 baseDelayMs?: number; // Default: 1000ms maxDelayMs?: number; // Default: 30000ms jitter?: boolean; // Default: true retryableStatuses?: readonly number[]; // Default: [408, 409, 425, 429, 500, 502, 503, 504] } ``` ## Error Classes [#error-classes] All exceptions thrown by `@memofs/adapter-openai` inherit from `OpenAIEmbedderError` and expose a typed `.code` property: ```ts class OpenAIEmbedderError extends Error { readonly code: OpenAIErrorCode; readonly cause?: unknown; } ``` | Error Class | `.code` | Cause | | --------------------------- | --------------------------- | ------------------------------------------------------------------------------------------------------- | | `OpenAIConfigError` | `"OPENAI_CONFIG_ERROR"` | Missing API key, conflicting client configuration, or invalid credentials. | | `OpenAIValidationError` | `"OPENAI_VALIDATION_ERROR"` | Invalid model name, dimension out of bounds, base64 format requested, or empty text. | | `OpenAIAPIError` | `"OPENAI_API_ERROR"` | Upstream API HTTP error response. Exposes `.status`, `.providerCode`, `.providerType`, `.providerBody`. | | `OpenAINetworkError` | `"OPENAI_NETWORK_ERROR"` | Network-level connectivity failure or DNS resolution issue. | | `OpenAITimeoutError` | `"OPENAI_TIMEOUT_ERROR"` | Request exceeded configured `timeoutMs`. | | `OpenAIResponseError` | `"OPENAI_RESPONSE_ERROR"` | Malformed JSON response, missing vector data, or index mismatch from API. | | `OpenAIRetryExhaustedError` | `"OPENAI_RETRY_EXHAUSTED"` | All retry attempts failed. | ## Unit Testing with Fake Client [#unit-testing-with-fake-client] Use the `@memofs/adapter-openai/testing` subpath to write fast, deterministic unit tests without network requests or API costs: ```ts import { describe, it, expect } from "vitest"; import { OpenAIEmbedder } from "@memofs/adapter-openai"; import { createFakeOpenAIClient } from "@memofs/adapter-openai/testing"; describe("OpenAI embedding pipeline", () => { it("generates deterministic embeddings with test fake", async () => { const fakeClient = createFakeOpenAIClient({ dimensions: 1536, deterministic: true, }); const embedder = new OpenAIEmbedder({ client: fakeClient, model: "text-embedding-3-small", }); const result = await embedder.embedText("Authentication rules"); expect(result.embedding).toHaveLength(1536); expect(result.model).toBe("text-embedding-3-small"); }); }); ``` ## See Also [#see-also] * [Adapters Overview](/adapters/) * [Voyage AI Adapter Reference](/adapters/voyage) * [Transformers.js Local Adapter](/adapters/transformers) * [Core Recall Engine](/core/recall) --- # Cloudflare R2 Adapter (/docs/adapters/r2) > Cloudflare R2 blob storage adapter for MemoFS remote-blob memory stores. The `@memofs/adapter-r2` adapter provides serverless raw byte storage for MemoFS using Cloudflare R2 object storage buckets (`R2Bucket`). It implements core's provider-neutral [`BlobClient`](/api/core#blobclient) interface, allowing MemoFS's [`RemoteBlobMemoryStore`](/api/core#remoteblobmemorystore) to persist canonical `.memofs/` files across distributed edge runtimes. ## Installation [#installation] ```bash npm install @memofs/adapter-r2 ``` ```bash pnpm add @memofs/adapter-r2 ``` ```bash bun add @memofs/adapter-r2 ``` ```bash deno add npm:@memofs/adapter-r2 ``` Requires **Node.js >= 22** or the **Cloudflare Workers** runtime. ## Usage in Cloudflare Workers [#usage-in-cloudflare-workers] In your Cloudflare Worker, bind an R2 bucket (e.g. `env.BLOBS`), create a `BlobClient` with `createR2BlobClient()`, and pair it with a metadata store in `RemoteBlobMemoryStore`: ```ts import { MemoFS, RemoteBlobMemoryStore } from "@memofs/core"; import { createR2BlobClient } from "@memofs/adapter-r2"; import { createTursoMetadataStore } from "@memofs/adapter-turso"; import { createClient } from "@libsql/client"; export interface Env { BLOBS: R2Bucket; // R2 Bucket binding from wrangler.jsonc / wrangler.toml TURSO_DATABASE_URL: string; TURSO_AUTH_TOKEN: string; } export default { async fetch(request: Request, env: Env): Promise { const projectId = "team-workspace"; // 1. Initialize R2 Blob Client (implements BlobClient) const blobClient = createR2BlobClient({ binding: env.BLOBS, }); // 2. Initialize Turso Metadata Store (implements MetadataStore) const metadata = createTursoMetadataStore({ client: createClient({ url: env.TURSO_DATABASE_URL, authToken: env.TURSO_AUTH_TOKEN, }), projectId, }); // 3. Compose the provider-neutral RemoteBlobMemoryStore const store = new RemoteBlobMemoryStore({ blobClient, metadata, rootKey: projectId, }); // 4. Initialize MemoFS const memo = new MemoFS({ store, projectId, mode: "local", }); const coreMemory = await memo.core.read(); return new Response(coreMemory, { headers: { "Content-Type": "text/markdown" }, }); }, }; ``` ## Content Addressing & Storage Layout [#content-addressing--storage-layout] `@memofs/adapter-r2` adheres to MemoFS's content-addressed storage architecture: 1. **SHA-256 Keying:** The runtime computes the 64-character lowercase hexadecimal SHA-256 hash of the canonical file content and passes it as the blob key (`blobKey === sha256`). 2. **Exact Cloud Replica Parity:** Matches the cloud sync engine's file replica format (`r2_key === sha256`) exactly. Identical file contents across multiple projects or file paths share the same underlying blob storage without duplication. 3. **Idempotent Operations:** Because keys are derived strictly from file content, writing the same file repeatedly is fully idempotent. Deleting non-existent keys succeeds safely without errors. ## Configuration API (`CreateR2BlobClientOptions`) [#configuration-api-creater2blobclientoptions] The `createR2BlobClient(options)` factory accepts `CreateR2BlobClientOptions`: | Option | Type | Required | Description | | --------- | ---------- | -------- | --------------------------------------------------- | | `binding` | `R2Bucket` | **Yes** | The Cloudflare R2 bucket binding object from `env`. | ## Method Reference (`BlobClient`) [#method-reference-blobclient] The returned `BlobClient` exposes three provider-neutral methods: ```ts interface BlobClient { /** Reads raw bytes from R2; returns null if key is absent. */ get(key: string): Promise; /** Writes bytes or streams to R2 under the content-derived key. */ put(key: string, body: BufferSource | ReadableStream): Promise; /** Deletes a blob from R2; idempotent. */ delete(key: string): Promise; } ``` ## See Also [#see-also] * [Adapters Overview](/adapters/) * [Turso / libSQL Adapter Reference](/adapters/turso) * [Workers AI Adapter Reference](/adapters/workers-ai) * [Self-Hosting on Cloudflare](/server/cloudflare) --- # Transformers.js Adapter (/docs/adapters/transformers) > Local Hugging Face Transformers.js ONNX embedding adapter for 100% offline semantic recall in MemoFS. The `@memofs/adapter-transformers` adapter runs vector embeddings **100% locally and offline** in-process using ONNX runtime and Hugging Face's Transformers.js (`@huggingface/transformers`). It requires **no API keys, no external services, and zero network traffic** after the initial model weights are downloaded and cached in a shared user-level cache (`$XDG_CACHE_HOME/memofs/models`, or `~/.cache/memofs/models`) — one download per machine, shared across projects and runtimes. ## Subpath Exports [#subpath-exports] | Export Path | Target Environment | Description | | ------------------------------------------ | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- | | **`@memofs/adapter-transformers`** | Node.js (>= 22) | **Root entry.** Exposes `TransformersEmbedder`, `createTransformersEmbedder`, `resolveModelCacheDir`, error classes, and pipeline types. | | **`@memofs/adapter-transformers/testing`** | Test runners | Exposes `createFakePipeline` and `createFakePipelineFactory` for deterministic testing without loading ONNX weights. | ## Installation [#installation] ```bash npm install @memofs/adapter-transformers ``` ```bash pnpm add @memofs/adapter-transformers ``` ```bash bun add @memofs/adapter-transformers ``` ```bash deno add npm:@memofs/adapter-transformers ``` Requires **Node.js >= 22** when running under the Node.js runtime. ## Usage [#usage] Instantiate the local embedder with `createTransformersEmbedder()`: ```ts import { createNodeMemoFs } from "@memofs/core/node-fs"; import { createTransformersEmbedder } from "@memofs/adapter-transformers"; const memo = createNodeMemoFs({ rootDir: ".", embedder: createTransformersEmbedder({ model: "Xenova/bge-small-en-v1.5", // 384 dimensions device: "cpu", dtype: "q8", }), }); ``` ```ts import { MemoFS } from "@memofs/core"; import { createNodeFsMemoryStore } from "@memofs/core/node-fs"; import { createTransformersEmbedder } from "@memofs/adapter-transformers"; const memo = new MemoFS({ store: createNodeFsMemoryStore({ rootDir: "." }), projectId: "offline-app", mode: "local", embedder: createTransformersEmbedder({ model: "Xenova/bge-small-en-v1.5", device: "cpu", dtype: "q8", }), }); ``` ## Lazy Loading & Eager Prewarming [#lazy-loading--eager-prewarming] To ensure fast CLI and server startup, `@memofs/adapter-transformers` defers loading the heavy ONNX WebAssembly binary and model weights until the first `embedTexts()` call. If your application requires deterministic latency on the first search request, you can explicitly prewarm the model pipeline at startup: ```ts const embedder = createTransformersEmbedder({ model: "Xenova/bge-small-en-v1.5", }); // Eagerly compile the ONNX pipeline and load weights into memory await embedder.prewarm(); ``` ## Model Cache [#model-cache] Downloaded weights live in one shared, user-level directory resolved by the exported `resolveModelCacheDir()`: * `$XDG_CACHE_HOME/memofs/models` when `XDG_CACHE_HOME` is set to a non-empty value * `~/.cache/memofs/models` otherwise MemoFS runs from several working directories over the lifetime of a machine (`memofs init` from a project root, an MCP server launched by an IDE, test runners), and Transformers.js's default cache is relative to the process working directory — without an explicit shared path, each directory would re-download the same weights. The shared cache means the model that `memofs init` predownloads is the exact one an MCP server finds on connect. Pass an explicit `cacheDir` to `createTransformersEmbedder()` to override the location. ## Configuration API (`TransformersEmbedderOptions`) [#configuration-api-transformersembedderoptions] The `createTransformersEmbedder(options)` factory accepts `TransformersEmbedderOptions`: | Option | Type | Default | Description | | ----------------- | ------------------------------------ | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `model` | `string` | `"Xenova/bge-small-en-v1.5"` | Hugging Face model repository identifier. Generates 384-dimensional vectors. | | `cacheDir` | `string` | `resolveModelCacheDir()` | Directory used to cache downloaded ONNX weights. Defaults to a shared user-level cache so weights download once per machine. | | `device` | `"cpu" \| "gpu" \| "wasm"` | `"cpu"` | Hardware backend target for the ONNX execution engine. | | `dtype` | `"fp32" \| "fp16" \| "q8" \| "int8"` | `"q8"` | Tensor precision format for model weights. `"q8"` (quantized) is \~4x smaller to download and faster on CPU with negligible retrieval-quality loss; `"fp32"` is the most conservative choice. | | `batchSize` | `number` | `32` | Maximum number of text chunks processed in a single pipeline pass. | | `retries` | `number` | `2` | Maximum retry attempts when the initial model download/load fails with a transient network error. Set to `0` to disable. | | `onProgress` | `TransformersProgressCallback` | — | Callback invoked during model download with `{ status, file, progress }`. Use it to show a one-time "warming up" notice. | | `pipelineFactory` | `FeatureExtractionPipelineFactory` | — | Custom pipeline factory function (primarily used in testing). | ## Error Classes [#error-classes] All errors inherit from `TransformersEmbedderError`: ```ts class TransformersEmbedderError extends Error { readonly cause?: unknown; } ``` | Error Class | Cause | | ----------------------------- | ------------------------------------------------------------------------------------------------------------- | | `TransformersValidationError` | Thrown when an input text string exceeds `MAX_TEXT_LENGTH = 8192` characters or input structure is malformed. | | `TransformersInferenceError` | Thrown when the ONNX runtime fails during forward inference or returns an unexpected tensor shape. | ## Unit Testing with Fake Pipeline [#unit-testing-with-fake-pipeline] Use the `@memofs/adapter-transformers/testing` subpath to test embeddings logic without downloading or running ONNX models: ```ts import { describe, it, expect } from "vitest"; import { TransformersEmbedder } from "@memofs/adapter-transformers"; import { createFakePipelineFactory } from "@memofs/adapter-transformers/testing"; describe("Local transformer pipeline", () => { it("generates deterministic embeddings with fake pipeline", async () => { const pipelineFactory = createFakePipelineFactory({ dimensions: 384, deterministic: true, }); const embedder = new TransformersEmbedder({ pipelineFactory, }); const result = await embedder.embedText("Refactor database pooling"); expect(result.dimensions).toBe(384); expect(result.embedding).toHaveLength(384); }); }); ``` ## See Also [#see-also] * [Adapters Overview](/adapters/) * [OpenAI Adapter Reference](/adapters/openai) * [Voyage AI Adapter Reference](/adapters/voyage) * [Hybrid Recall Architecture](/core/recall) --- # Turso / libSQL Adapter (/docs/adapters/turso) > Turso / libSQL metadata manifest adapter for MemoFS remote-blob memory stores. The `@memofs/adapter-turso` adapter implements MemoFS's [`MetadataStore`](/api/core#metadatastore) contract over a Turso or libSQL SQLite database. It manages the canonical file manifest (`path` → `BlobEntry` mapping) and provides transactional serialization (`BEGIN IMMEDIATE`) to prevent concurrent write hazards in distributed environments. ## Installation [#installation] ```bash npm install @memofs/adapter-turso @libsql/client ``` ```bash pnpm add @memofs/adapter-turso @libsql/client ``` ```bash bun add @memofs/adapter-turso @libsql/client ``` ```bash deno add npm:@memofs/adapter-turso npm:@libsql/client ``` Requires **Node.js >= 22** or the **Cloudflare Workers** runtime. ## Usage [#usage] Create a `MetadataStore` with `createTursoMetadataStore()` and pass it alongside a `BlobClient` to `RemoteBlobMemoryStore`: ```ts import { MemoFS, RemoteBlobMemoryStore } from "@memofs/core"; import { createTursoMetadataStore } from "@memofs/adapter-turso"; import { createR2BlobClient } from "@memofs/adapter-r2"; import { createClient } from "@libsql/client"; // 1. Create a libSQL client instance const dbClient = createClient({ url: process.env.TURSO_DATABASE_URL!, authToken: process.env.TURSO_AUTH_TOKEN!, }); const projectId = "my-project-123"; // 2. Instantiate the Turso metadata store const metadata = createTursoMetadataStore({ client: dbClient, projectId, }); // 3. Compose with an R2 blob client into a RemoteBlobMemoryStore const store = new RemoteBlobMemoryStore({ blobClient: createR2BlobClient({ binding: env.BLOBS }), metadata, rootKey: projectId, }); // 4. Initialize MemoFS const memo = new MemoFS({ store, projectId, mode: "local", }); ``` ## Schema & Manifest Architecture [#schema--manifest-architecture] `@memofs/adapter-turso` operates against the `project_files` table, matching the MemoFS cloud replication layout: ```sql CREATE TABLE IF NOT EXISTS project_files ( id TEXT PRIMARY KEY, project_id TEXT NOT NULL, path TEXT NOT NULL, sha256 TEXT NOT NULL, r2_key TEXT NOT NULL, size_bytes INTEGER NOT NULL, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, UNIQUE(project_id, path) ); ``` ### Manifest Operations [#manifest-operations] * **`getEntry(path)`:** Queries `SELECT sha256, r2_key, size_bytes FROM project_files WHERE project_id = ? AND path = ?`. * **`upsertEntry(path, entry)`:** Performs `INSERT ... ON CONFLICT (project_id, path) DO UPDATE SET sha256 = excluded.sha256, r2_key = excluded.r2_key, size_bytes = excluded.size_bytes, updated_at = current_timestamp`. * **`deleteEntry(path)`:** Runs `DELETE FROM project_files WHERE project_id = ? AND path = ?`. * **`listEntries()`:** Streams all registered canonical paths for the project via `SELECT path, sha256, r2_key, size_bytes FROM project_files WHERE project_id = ?`. ## Concurrency Control (`withTransaction`) [#concurrency-control-withtransaction] When multiple AI coding agents write to the same project concurrently, interleaving non-atomic file writes can cause file corruption. `@memofs/adapter-turso` implements `MetadataStore.withTransaction`: 1. Opens a serialized transaction using `BEGIN IMMEDIATE`. 2. Guarantees that mutating operations (`write`, `append`, `delete`) execute atomically. 3. Automatically commits on success (`COMMIT`) or rolls back on exceptions (`ROLLBACK`). ## Configuration API (`CreateTursoMetadataStoreOptions`) [#configuration-api-createtursometadatastoreoptions] The `createTursoMetadataStore(options)` factory accepts `CreateTursoMetadataStoreOptions`: | Option | Type | Required | Description | | ----------- | -------- | -------- | --------------------------------------------------------------------- | | `client` | `Client` | **Yes** | An initialized `@libsql/client` instance (or Drizzle's `db.$client`). | | `projectId` | `string` | **Yes** | The project identifier scoping this manifest. | ## See Also [#see-also] * [Adapters Overview](/adapters/) * [Cloudflare R2 Adapter Reference](/adapters/r2) * [RemoteBlobMemoryStore API Reference](/api/core#remoteblobmemorystore) * [Self-Hosting on Cloudflare](/server/cloudflare) --- # Voyage AI Adapter (/docs/adapters/voyage) > Voyage AI embeddings and neural reranking adapter for high-precision code and document recall in MemoFS. The `@memofs/adapter-voyage` adapter provides first-class support for Voyage AI's domain-optimized embedding models (`/v1/embeddings`) and neural cross-encoder rerankers (`/v1/rerank`). It implements both the [`MemoryEmbedder`](/api/core#memoryembedder) and [`Reranker`](/api/core#reranker) core interfaces to deliver high semantic accuracy across hybrid vector search and retrieval passes. ## Subpath Exports [#subpath-exports] | Export Path | Target Environment | Description | | ------------------------------------ | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | | **`@memofs/adapter-voyage`** | Node.js (>= 22), Edge | **Root entry.** Exposes `VoyageEmbedder`, `createVoyageEmbedder`, `VoyageReranker`, `createVoyageReranker`, client factories, constants, and error classes. | | **`@memofs/adapter-voyage/testing`** | Test runners | Exposes `createFakeVoyageClient`, `FakeVoyageClient`, `createFakeVoyageRerankClient`, and `FakeVoyageRerankClient` for offline testing. | ## Installation [#installation] ```bash npm install @memofs/adapter-voyage ``` ```bash pnpm add @memofs/adapter-voyage ``` ```bash bun add @memofs/adapter-voyage ``` ```bash deno add npm:@memofs/adapter-voyage ``` Requires **Node.js >= 22** when running under the Node.js runtime. ## Usage [#usage] You can configure Voyage AI as an **Embedder**, a **Reranker**, or both: ```ts import { createNodeMemoFs } from "@memofs/core/node-fs"; import { createVoyageEmbedder, createVoyageReranker, } from "@memofs/adapter-voyage"; const memo = createNodeMemoFs({ rootDir: ".", // 1. Semantic embeddings embedder: createVoyageEmbedder({ apiKey: process.env.VOYAGE_API_KEY!, model: "voyage-3.5", outputDimension: 1024, }), // 2. Neural reranking reranker: createVoyageReranker({ apiKey: process.env.VOYAGE_API_KEY!, model: "rerank-2.5-lite", }), }); ``` ```ts import { MemoFS } from "@memofs/core"; import { createNodeFsMemoryStore } from "@memofs/core/node-fs"; import { createVoyageEmbedder, createVoyageReranker, } from "@memofs/adapter-voyage"; const memo = new MemoFS({ store: createNodeFsMemoryStore({ rootDir: "." }), projectId: "voyage-app", mode: "local", embedder: createVoyageEmbedder({ apiKey: process.env.VOYAGE_API_KEY!, model: "voyage-3.5", outputDimension: 1024, }), reranker: createVoyageReranker({ apiKey: process.env.VOYAGE_API_KEY!, model: "rerank-2.5-lite", }), }); ``` ## Voyage Embedder Reference [#voyage-embedder-reference] ### Supported Models [#supported-models] #### Flexible-Dimension Models (Matryoshka Embeddings) [#flexible-dimension-models-matryoshka-embeddings] These models support dynamic output dimensions (`256`, `512`, `1024`, `2048` via `outputDimension`): * `voyage-4-large`, `voyage-4`, `voyage-4-lite`, `voyage-4-nano` * `voyage-3.5`, `voyage-3.5-lite`, `voyage-3-large` * `voyage-code-3`, `voyage-multimodal-3.5` #### Fixed-Dimension Models [#fixed-dimension-models] * `voyage-3` (1024 dims), `voyage-3-lite` (512 dims) * `voyage-code-2` (1536 dims), `voyage-multilingual-2` (1024 dims) * `voyage-finance-2` (1024 dims), `voyage-law-2` (1024 dims) * `voyage-multimodal-3` (1024 dims) ### Embedder Configuration (`VoyageEmbedderConfig`) [#embedder-configuration-voyageembedderconfig] | Option | Type | Default | Description | | ----------------------------- | ------------------------------------------------------- | ---------------------------- | --------------------------------------------------------------------------------- | | `apiKey` | `string` | — | Voyage AI API key. Mutually exclusive with `client`. | | `client` | `VoyageEmbeddingsClient` | — | Pre-configured client instance or test fake. | | `model` | `string` | `"voyage-3.5"` | Voyage embedding model identifier. | | `outputDimension` | `256 \| 512 \| 1024 \| 2048` | Model default | Target vector dimension for flexible models. | | `outputDtype` | `"float" \| "int8" \| "uint8" \| "binary" \| "ubinary"` | `"float"` | Data type for output embeddings. | | `inputType` | `"query" \| "document" \| null` | `null` | Optional input type hint to optimize query/document representations. | | `baseUrl` | `string` | `"https://api.voyageai.com"` | API base URL. | | `fetch` | `VoyageFetchLike` | `globalThis.fetch` | Custom `fetch` function. | | `timeoutMs` | `number` | `30000` (30s) | Request timeout in milliseconds. | | `retry` | `VoyageRetryOptions` | Standard jittered retry | Retry configuration for 429 and 5xx responses. | | `batchSize` | `number` | `128` | Max items per batch (automatically chunked up to `VOYAGE_MAX_BATCH_SIZE = 1000`). | | `expectedDimensions` | `number` | — | Validation check on returned vector dimensions. | | `allowEmptyText` | `boolean` | `false` | Allow empty strings without throwing. | | `allowUnknownModelDimensions` | `boolean` | `true` | Allow custom models with explicit dimensions. | ## Voyage Reranker Reference [#voyage-reranker-reference] ### Supported Rerank Models [#supported-rerank-models] * `rerank-2.5` * `rerank-2.5-lite` (default — fast, cost-effective cross-encoder) * `rerank-2`, `rerank-2-lite` * `rerank-1`, `rerank-lite-1` ### Reranker Configuration (`VoyageRerankerConfig`) [#reranker-configuration-voyagererankerconfig] | Option | Type | Default | Description | | ------------------- | -------------------- | ---------------------------- | ------------------------------------------------------------------------------------------ | | `apiKey` | `string` | — | Voyage AI API key. Mutually exclusive with `client`. | | `client` | `VoyageRerankClient` | — | Injected rerank client or test fake. | | `model` | `string` | `"rerank-2.5-lite"` | Rerank model identifier. | | `maxDocuments` | `number` | `1000` | Maximum candidate documents sent per request (up to `VOYAGE_RERANK_MAX_DOCUMENTS = 1000`). | | `truncation` | `boolean` | `true` | Whether to truncate documents exceeding context limits instead of throwing. | | `allowUnknownModel` | `boolean` | `true` | Whether to permit newer unlisted Voyage rerank models. | | `baseUrl` | `string` | `"https://api.voyageai.com"` | API base URL. | | `fetch` | `VoyageFetchLike` | `globalThis.fetch` | Custom `fetch` implementation. | | `timeoutMs` | `number` | `30000` (30s) | Request timeout in milliseconds. | | `retry` | `VoyageRetryOptions` | Standard jittered retry | Retry configuration. | ## Error Classes [#error-classes] All exceptions inherit from base error classes and provide stable `.code` identifiers: ### Embedder Errors (`VoyageEmbedderError`) [#embedder-errors-voyageembeddererror] | Error Class | `.code` | Cause | | --------------------------- | --------------------------- | ---------------------------------------------------------------------------------------------- | | `VoyageConfigError` | `"VOYAGE_CONFIG_ERROR"` | Missing API key or conflicting client configuration. | | `VoyageValidationError` | `"VOYAGE_VALIDATION_ERROR"` | Invalid model, unsupported output dimension, or malformed input texts. | | `VoyageAPIError` | `"VOYAGE_API_ERROR"` | Upstream API HTTP error. Exposes `.status`, `.providerCode`, `.providerType`, `.providerBody`. | | `VoyageNetworkError` | `"VOYAGE_NETWORK_ERROR"` | Network connectivity failure. | | `VoyageTimeoutError` | `"VOYAGE_TIMEOUT_ERROR"` | Request exceeded configured timeout. | | `VoyageResponseError` | `"VOYAGE_RESPONSE_ERROR"` | Invalid response format or vector dimension mismatch. | | `VoyageRetryExhaustedError` | `"VOYAGE_RETRY_EXHAUSTED"` | All retry attempts failed. | ### Reranker Errors (`VoyageRerankError`) [#reranker-errors-voyagererankerror] | Error Class | `.code` | Cause | | --------------------------------- | ---------------------------------- | ---------------------------------------------------- | | `VoyageRerankConfigError` | `"VOYAGE_RERANK_CONFIG_ERROR"` | Missing API key or client. | | `VoyageRerankValidationError` | `"VOYAGE_RERANK_VALIDATION_ERROR"` | More than 1,000 documents provided or invalid model. | | `VoyageRerankApiError` | `"VOYAGE_RERANK_API_ERROR"` | Upstream rerank API HTTP error. | | `VoyageRerankNetworkError` | `"VOYAGE_RERANK_NETWORK_ERROR"` | Rerank network connection failure. | | `VoyageRerankTimeoutError` | `"VOYAGE_RERANK_TIMEOUT_ERROR"` | Rerank request timed out. | | `VoyageRerankResponseError` | `"VOYAGE_RERANK_RESPONSE_ERROR"` | Invalid index mapping from rerank response. | | `VoyageRerankRetryExhaustedError` | `"VOYAGE_RERANK_RETRY_EXHAUSTED"` | Retry attempts exhausted. | ## Unit Testing with Fake Clients [#unit-testing-with-fake-clients] The `@memofs/adapter-voyage/testing` subpath provides test doubles for both embedder and reranker pipelines: ```ts import { describe, it, expect } from "vitest"; import { VoyageEmbedder, VoyageReranker } from "@memofs/adapter-voyage"; import { createFakeVoyageClient, createFakeVoyageRerankClient, } from "@memofs/adapter-voyage/testing"; describe("Voyage pipeline tests", () => { it("runs embeddings and reranking offline", async () => { const embedder = new VoyageEmbedder({ client: createFakeVoyageClient({ outputDimension: 1024, deterministic: true }), model: "voyage-3.5", }); const reranker = new VoyageReranker({ client: createFakeVoyageRerankClient({ deterministic: true }), model: "rerank-2.5-lite", }); const embedding = await embedder.embedText("Query text"); expect(embedding.dimensions).toBe(1024); const ranked = await reranker.rerank({ query: "database", documents: [ { id: "1", text: "PostgreSQL setup" }, { id: "2", text: "Frontend buttons" }, ], topK: 1, }); expect(ranked).toHaveLength(1); expect(ranked[0].id).toBeDefined(); }); }); ``` ## See Also [#see-also] * [Adapters Overview](/adapters/) * [OpenAI Adapter Reference](/adapters/openai) * [Transformers.js Local Adapter](/adapters/transformers) * [Hybrid Recall & Reranking](/core/recall) --- # Cloudflare Workers AI Adapter (/docs/adapters/workers-ai) > Cloudflare Workers AI graph extractor adapter for serverless edge inference in MemoFS. The `@memofs/adapter-workers-ai` adapter provides LLM-based entity-relationship knowledge graph extraction for MemoFS running on Cloudflare Workers using serverless GPU inference (`env.AI`). It implements core's provider-neutral [`Extractor`](/api/core#extractor) interface, translating memory note text into structured graph nodes and typed relational edges using the canonical MemoFS relation vocabulary. ## Installation [#installation] ```bash npm install @memofs/adapter-workers-ai ``` ```bash pnpm add @memofs/adapter-workers-ai ``` ```bash bun add @memofs/adapter-workers-ai ``` ```bash deno add npm:@memofs/adapter-workers-ai ``` Requires **Node.js >= 22** or the **Cloudflare Workers** runtime. ## Usage in Cloudflare Workers [#usage-in-cloudflare-workers] In Cloudflare Workers, pass the `env.AI` binding to `createWorkersAiExtractor()` and provide it to your `MemoFS` instance: ```ts import { MemoFS, RemoteBlobMemoryStore } from "@memofs/core"; import { createWorkersAiExtractor } from "@memofs/adapter-workers-ai"; import { createR2BlobClient } from "@memofs/adapter-r2"; import { createTursoMetadataStore } from "@memofs/adapter-turso"; import { createClient } from "@libsql/client"; export interface Env { BLOBS: R2Bucket; TURSO_DATABASE_URL: string; TURSO_AUTH_TOKEN: string; AI: Ai; // Injected Cloudflare Workers AI binding } export default { async fetch(request: Request, env: Env): Promise { const projectId = "serverless-project"; // 1. Initialize remote blob memory store (R2 + Turso) const store = new RemoteBlobMemoryStore({ blobClient: createR2BlobClient({ binding: env.BLOBS }), metadata: createTursoMetadataStore({ client: createClient({ url: env.TURSO_DATABASE_URL, authToken: env.TURSO_AUTH_TOKEN, }), projectId, }), rootKey: projectId, }); // 2. Initialize MemoFS client with Workers AI extractor const memo = new MemoFS({ store, projectId, mode: "local", extractor: createWorkersAiExtractor({ ai: env.AI, model: "@cf/meta/llama-3.1-8b-instruct", }), }); // 3. Writing memories automatically extracts entities and relationships const result = await memo.writeMemory({ title: "Auth Middleware Migration", content: "The AuthModule depends on the RedisSessionStore and supersedes the LegacyCookieAuth.", kind: "decision", }); return new Response(JSON.stringify(result), { headers: { "Content-Type": "application/json" }, }); }, }; ``` ## Extraction & Graph Schema [#extraction--graph-schema] The Workers AI extractor prompts the model to parse input text into subject–predicate–object triples using MemoFS's canonical relation vocabulary: | Relation Type | Semantics | Example Extraction | | ------------- | --------------------------------------------------- | --------------------------------------------- | | `uses` | Component or library utilization | `[AuthService] --uses--> [Bcrypt]` | | `depends_on` | Structural or architectural dependency | `[BillingModule] --depends_on--> [StripeSDK]` | | `prefers` | Architectural convention or preference | `[Team] --prefers--> [pnpm]` | | `blocks` | Blocker or issue dependency | `[Bug #402] --blocks--> [Release v2.0]` | | `supersedes` | Replaces or invalidates older architecture/decision | `[v2Router] --supersedes--> [v1Router]` | | `owns` | Team or domain ownership | `[SecurityTeam] --owns--> [KMSVault]` | | `related_to` | General conceptual association | `[VectorIndex] --related_to--> [Recall]` | ## Defensive Parsing & Resilience [#defensive-parsing--resilience] The extractor employs strict defensive parsing: 1. **Zero Runtime Halts:** If the LLM generates malformed JSON, truncated markdown, or unexpected tokens, the adapter catches the error and returns an empty `{ nodes: [], edges: [] }` result rather than throwing. 2. **Resilient Write Path:** A failure in LLM extraction never aborts or blocks the primary memory note write; the markdown note is committed safely and the rule-based extractor acts as fallback. 3. **Provenance Stamping:** Every extracted node and edge automatically inherits the source memory note reference (`sourceRef`) for full traceability and auditability. ## Configuration API (`CreateWorkersAiExtractorOptions`) [#configuration-api-createworkersaiextractoroptions] The `createWorkersAiExtractor(options)` factory accepts `CreateWorkersAiExtractorOptions`: | Option | Type | Default | Description | | ----------------- | --------------- | ---------------------------------- | --------------------------------------------------------------------------------------- | | `ai` | `Ai` | — (**Required**) | Cloudflare Workers AI binding object (`env.AI`). | | `model` | `string` | `"@cf/meta/llama-3.1-8b-instruct"` | Cloudflare Workers AI model identifier. | | `defaultNodeType` | `GraphNodeType` | `"concept"` | Default node type assigned to entities (`"concept" \| "entity" \| "file" \| "module"`). | | `stampProvenance` | `boolean` | `true` | Whether to stamp the input's `sourceRef` onto all extracted nodes and edges. | ## See Also [#see-also] * [Adapters Overview](/adapters/) * [Cloudflare R2 Adapter Reference](/adapters/r2) * [Turso / libSQL Adapter Reference](/adapters/turso) * [Knowledge Graph Concepts](/core/graph) --- # @memofs/cli API Reference (/docs/api/cli) > Comprehensive technical API reference for @memofs/cli: runner, config writers, error hierarchy, protocol constants, and output formatters. The `@memofs/cli` package exports its programmatic runner, configuration generator, error classes, protocol constants, output writers, and memory filesystem inspection utilities. ## Package Subpaths [#package-subpaths] ```ts // Primary entry point (Node.js runtime) import { runMemoFsCli, createMemoFSFromCli, writeDefaultCliConfig, resolveSchemaPath, inspectMemoFs, CliError, CliUsageError, } from "@memofs/cli"; // JSON Schema for .memofs/config.json import configSchema from "@memofs/cli/schema/config.json" with { type: "json" }; ``` *** ## 1. CLI Runner & Client Factory [#1-cli-runner--client-factory] ### `runMemoFsCli(input: RunMemoFSCliInput): Promise` [#runmemofscliinput-runmemofscliinput-promiserunmemofscliresult] Executes the MemoFS CLI command pipeline programmatically using Commander, routing stdout and stderr to the output collector. ```ts import { runMemoFsCli } from "@memofs/cli"; const result = await runMemoFsCli({ argv: ["remember", "Use libSQL for local database", "--kind", "decision"], cwd: process.cwd(), }); console.log("Exit code:", result.exitCode); console.log("Stdout lines:", result.stdout); console.log("Stderr lines:", result.stderr); ``` #### Parameters [#parameters] ```ts interface RunMemoFSCliInput { argv: string[]; cwd?: string; output?: CliOutput; verbose?: boolean; quiet?: boolean; noColor?: boolean; stdinContent?: string; } interface RunMemoFSCliResult { exitCode: number; stdout: string[]; stderr: string[]; } ``` *** ### `createMemoFSFromCli(options?: CliMemoFSOptions): MemoFS` [#creatememofsfromclioptions-climemofsoptions-memofs] Instantiates and configures a [`MemoFS`](/api/core) class instance by resolving CLI flag options, environment variables, and project `.memofs/config.json`. ```ts import { createMemoFSFromCli } from "@memofs/cli"; // 1. Create client with CLI options (inherits env vars & config.json) const memo = createMemoFSFromCli({ root: "./my-project", runtime: "hybrid", cloudUrl: "https://memofs.dev/api/v1", apiKey: process.env.MEMOFS_API_KEY, timeoutMs: 15000, }); // 2. Perform core memory operations await memo.writeMemory({ content: "Use libSQL for local SQLite replication", kind: "decision", title: "Local Database Engine", tags: ["database", "storage"], }); // 3. Build token-budgeted prompt context const context = await memo.context({ query: "how to configure database storage", taskType: "coding", maxBytes: 12000, }); // 4. Query hybrid recall directly const recall = await memo.recall("database migrations", { limit: 5, }); // 5. Create snapshots const snapshot = await memo.snapshots.create({ label: "before-refactor" }); ``` #### Options [#options] ```ts interface CliMemoFSOptions { cwd?: string; root?: string; runtime?: string; cloudUrl?: string; apiKey?: string; workspaceId?: string; projectId?: string; timeoutMs?: string | number; } ``` *** ## 2. Configuration Management [#2-configuration-management] ### `writeDefaultCliConfig(input)` [#writedefaultcliconfiginput] Creates or overwrites `.memofs/config.json` with portable relative `$schema` references. ```ts import { writeDefaultCliConfig, resolveSchemaPath } from "@memofs/cli"; const result = await writeDefaultCliConfig({ cwd: process.cwd(), root: ".", force: false, config: { $schema: resolveSchemaPath(process.cwd()), runtime: "local", root: ".", }, }); console.log("Created:", result.created); console.log("Path:", result.path); ``` ### `resolveSchemaPath(rootDir: string): string` [#resolveschemapathrootdir-string-string] Returns a portable relative path (`../node_modules/@memofs/cli/schema/config.json`) if the package schema exists on disk, or the hosted fallback URL (`https://docs.memofs.dev/schema/config.json`). *** ## 3. Protocol Utilities & Inspection [#3-protocol-utilities--inspection] ### `inspectMemoFs(store: MemoryStore, rootDir: string): Promise` [#inspectmemofsstore-memorystore-rootdir-string-promisememofsinspection] Performs an audit and summary scan of workspace database files, JSONL records, and graph entities. ```ts import { inspectMemoFs } from "@memofs/cli"; import { createNodeFsMemoryStore } from "@memofs/core/node-fs"; const store = createNodeFsMemoryStore({ rootDir: "." }); const inspection = await inspectMemoFs(store, "."); console.log("Event count:", inspection.summary.eventCount); console.log("Graph nodes:", inspection.summary.graphNodeCount); ``` #### Output Structure [#output-structure] ```ts interface MemoFsInspection { rootDir: string; exists: boolean; manifest?: MemoFsCliManifest; files: Array<{ path: string; exists: boolean; bytes: number; lines?: number; records?: number; }>; summary: { eventCount: number; conversationCount: number; chunkCount: number; graphNodeCount: number; graphEdgeCount: number; snapshotCount: number; }; } ``` ### `parseJsonl(content: string, options?: JsonlParseOptions): JsonlRecord[]` [#parsejsonlcontent-string-options-jsonlparseoptions-jsonlrecord] Parses newline-delimited JSON strings into structured records with 1-based line numbers. ### `stringifyJsonl(records: readonly Record[]): string` [#stringifyjsonlrecords-readonly-recordstring-unknown-string] Serializes record arrays into newline-delimited JSON with a terminating newline. ### `validateManifest(value: unknown): MemoFsCliManifest` [#validatemanifestvalue-unknown-memofsclimanifest] Asserts and parses an unknown object against `ManifestSchema`. ### `createDefaultManifest(input?: { projectId?: string; now?: string }): MemoFsCliManifest` [#createdefaultmanifestinput--projectid-string-now-string--memofsclimanifest] Constructs a default manifest object with generated project UUID. *** ## 4. Helper Utilities [#4-helper-utilities] ### Snapshot Utilities [#snapshot-utilities] * **`validateSnapshotLabel(label: string): string`**: Validates a snapshot label (1–80 chars, alphanumeric + dots/dashes/underscores, starts with letter/number). * **`createSafeIdFromLabel(label: string, timestamp?: string): string`**: Builds a collision-safe snapshot identifier string (e.g. `manual-2026-08-16T00-00-00-000Z`). ### Secret Scanning [#secret-scanning] * **`scanForSecrets(content: string): SecretScanFinding[]`**: Scans text for API keys, private keys, JWTs, and credential assignments. * **`redactSecretPreview(value: string): string`**: Returns an edge-preserving redacted preview of a secret string (e.g. `sk-a…bc12`). ```ts interface SecretScanFinding { kind: string; index: number; preview: string; } ``` *** ## 5. Output Writers & Envelopes [#5-output-writers--envelopes] ### `createBufferedOutput(options?: BufferedOutputOptions): CliOutput` [#createbufferedoutputoptions-bufferedoutputoptions-clioutput] Constructs an in-memory buffered implementation of `CliOutput`. ```ts interface CliOutput { stdout: string[]; stderr: string[]; write(message: string): void; error(message: string): void; success(message: string): void; warn(message: string): void; spinner(options?: { json?: boolean }): CliSpinner; progress(options?: { json?: boolean }): CliProgressBar; } ``` ### `printJsonEnvelope(output: CliOutput, command: string, data: T): void` [#printjsonenvelopetoutput-clioutput-command-string-data-t-void] Standard envelope formatter for `--json` output: ```ts interface JsonEnvelope { ok: boolean; command: string; data?: T; error?: { code: string; message: string; details?: unknown; }; } ``` *** ## 6. Error Hierarchy [#6-error-hierarchy] All CLI errors extend `CliError` and carry a machine-readable `code` and numeric `exitCode`: ```ts type CliErrorCode = | "CLI_USAGE_ERROR" | "CLI_VALIDATION_ERROR" | "CLI_FS_ERROR" | "CLI_PROTOCOL_ERROR" | "CLI_JSONL_ERROR"; ``` *** ## 7. Constants [#7-constants] ```ts export const MEMOFS_DIR = ".memofs"; export const MEMOFS_CLI_PATHS = { manifest: ".memofs/manifest.json", coreMemory: ".memofs/memory/core.md", notesMemory: ".memofs/memory/notes.md", memoryEvents: ".memofs/events/memory-events.jsonl", conversations: ".memofs/events/conversations.jsonl", chunks: ".memofs/indexes/chunks.jsonl", graphNodes: ".memofs/graph/nodes.jsonl", graphEdges: ".memofs/graph/edges.jsonl", snapshots: ".memofs/snapshots/snapshots.jsonl", snapshotsDir: ".memofs/snapshots", tmpDir: ".memofs/tmp", } as const; export const REQUIRED_DIRS = [ ".memofs", ".memofs/memory", ".memofs/events", ".memofs/indexes", ".memofs/graph", ".memofs/snapshots", ".memofs/tmp", ] as const; export const REQUIRED_FILES = [ ".memofs/manifest.json", ".memofs/memory/core.md", ".memofs/memory/notes.md", ".memofs/events/memory-events.jsonl", ".memofs/events/conversations.jsonl", ".memofs/indexes/chunks.jsonl", ".memofs/indexes/embeddings.jsonl", ".memofs/graph/nodes.jsonl", ".memofs/graph/edges.jsonl", ".memofs/snapshots/snapshots.jsonl", ".memofs/connectors.json", ] as const; export const CORE_MEMORY_SOFT_LIMIT = 200; ``` --- # @memofs/connectors API (/docs/api/connectors) > API reference for @memofs/connectors: ingestion pipelines, connector registry, deterministic note ID generation, and third-party sources. The `@memofs/connectors` package manages ingestion pipelines from external sources (GitHub, Notion, and custom connectors) into MemoFS memory. ## Functions [#functions] ### `runConnectors` [#runconnectors] Orchestrates loading `.memofs/connectors.json`, resolving credentials through `SecretResolver`, executing enabled ingestion connectors, deduplicating records against existing event logs, and committing notes to MemoFS memory. ```ts function runConnectors(options: RunConnectorsOptions): Promise; ``` ### `createConnectorRegistry` [#createconnectorregistry] Creates a new `ConnectorRegistry` seeded with the built-in connectors (`GitHubConnector` and `NotionConnector`), plus any optional extra connectors. ```ts function createConnectorRegistry(extras?: readonly Connector[]): ConnectorRegistry; ``` ### `connectorNoteId` [#connectornoteid] Computes the deterministic `conn_<16 hex chars>` note ID for a `ConnectorRecord` using `sha256(externalId + ":" + content).slice(0, 16)`. Pure computation with zero wall-clock dependency. ```ts function connectorNoteId(record: ConnectorRecord): Promise; ``` ### `readConnectorsFile` [#readconnectorsfile] Reads and validates `.memofs/connectors.json` for a given project root. A missing file degrades gracefully to `EMPTY_CONNECTORS_FILE` (`{ connectors: [] }`) rather than throwing. Malformed files or files violating secret guardrails throw `ConnectorConfigError`. ```ts function readConnectorsFile(rootDir: string): Promise; ``` ### `validateConnectorsFile` [#validateconnectorsfile] Runs structural and secret-leak validation against a parsed `connectors.json` JSON payload. Rejects forbidden token keys, recursive substring matches, and credential pattern matches. ```ts function validateConnectorsFile(raw: unknown): ConnectorsFile; ``` ### `selectConnectors` [#selectconnectors] Filters a `ConnectorsFile` by `enabled` state and/or connector `type`. ```ts function selectConnectors( file: ConnectorsFile, opts?: { enabled?: boolean; type?: string } ): ConnectorConfig[]; ``` ## Classes [#classes] ### `ConnectorRegistry` [#connectorregistry] Mutable registry mapping a connector `type` identifier to a `Connector` implementation instance. ```ts class ConnectorRegistry { constructor(builtins?: readonly Connector[]); register(connector: Connector): this; get(type: string): Connector | undefined; has(type: string): boolean; types(): readonly string[]; } ``` ### `GitHubConnector` [#githubconnector] Built-in connector for GitHub issues, pull requests, and discussions (`type: "github"`). Implements `Connector`. ```ts class GitHubConnector implements Connector { readonly type = "github"; readonly displayName = "GitHub"; ingest(ctx: ConnectorIngestContext): Promise; } ``` ### `NotionConnector` [#notionconnector] Built-in connector for Notion database rows and workspace search pages (`type: "notion"`). Implements `Connector`. ```ts class NotionConnector implements Connector { readonly type = "notion"; readonly displayName = "Notion"; ingest(ctx: ConnectorIngestContext): Promise; } ``` ### `EnvSecretResolver` [#envsecretresolver] Dev/local fallback resolver. Reads `{ "secretRef": "token" }` maps from `.memofs/secrets.json` on disk (cached in memory). Implements `SecretResolver`. ```ts class EnvSecretResolver implements SecretResolver { constructor(options: FileSecretResolverOptions); resolve(secretRef: string): Promise; } ``` ### `StaticSecretResolver` [#staticsecretresolver] In-memory secret resolver for tests and programmatic embedding. Implements `SecretResolver`. ```ts class StaticSecretResolver implements SecretResolver { constructor(entries: Record); resolve(secretRef: string): Promise; } ``` ### `CloudSecretResolver` [#cloudsecretresolver] Production secret resolver that calls the MemoFS Cloud API endpoint `GET {cloudBaseUrl}/projects/:projectId/connectors/secret?ref=:secretRef`. Implements `SecretResolver`. ```ts class CloudSecretResolver implements SecretResolver { constructor(options: CloudSecretResolverOptions); resolve(secretRef: string): Promise; } ``` ## Interfaces & Types [#interfaces--types] ### `SecretResolver` [#secretresolver] Credential plane contract. Implementations resolve an opaque `secretRef` to a live plaintext token in memory. ```ts interface SecretResolver { resolve(secretRef: string): Promise; } ``` ### `Connector` [#connector] Provider-neutral plugin interface for data sources. ```ts interface Connector { readonly type: string; readonly displayName: string; ingest(ctx: ConnectorIngestContext): Promise; } ``` ### `ConnectorConfig` [#connectorconfig] Single connector instance row stored in `.memofs/connectors.json`. ```ts interface ConnectorConfig { readonly id: string; readonly type: string; readonly enabled: boolean; readonly schedule?: string; readonly sourceMapping?: JsonObject; readonly secretRef: string; } ``` ### `ConnectorsFile` [#connectorsfile] The parsed on-disk shape of `.memofs/connectors.json` (the 11th canonical sync unit). ```ts interface ConnectorsFile { readonly connectors: readonly ConnectorConfig[]; } ``` ### `ConnectorRecord` [#connectorrecord] A normalized external item produced by `Connector.ingest()`. ```ts interface ConnectorRecord { readonly externalId: string; readonly title: string; readonly content: string; readonly url?: string; readonly occurredAt?: string; readonly metadata?: JsonObject; } ``` ### `ConnectorIngestContext` [#connectoringestcontext] Runtime context passed into `Connector.ingest()`. ```ts interface ConnectorIngestContext { readonly config: ConnectorConfig; readonly token: string; readonly memo: MemoFS; readonly signal?: AbortSignal; } ``` ### `RunConnectorsOptions` [#runconnectorsoptions] Configuration options passed to `runConnectors()`. ```ts interface RunConnectorsOptions { readonly rootDir: string; readonly memo: MemoFS; readonly secretResolver: SecretResolver; readonly connectorRegistry?: ConnectorRegistry; readonly onlyType?: string; readonly signal?: AbortSignal; } ``` ### `RunConnectorsResult` [#runconnectorsresult] Aggregated result returned by `runConnectors()`. ```ts interface RunConnectorsResult { readonly written: readonly string[]; readonly skipped: readonly string[]; readonly errors: readonly ConnectorIngestError[]; readonly ran: readonly string[]; } ``` ### `ConnectorIngestResult` [#connectoringestresult] Result of a single connector pass before aggregation. ```ts interface ConnectorIngestResult { readonly written: readonly string[]; readonly skipped: readonly string[]; readonly errors: readonly ConnectorIngestError[]; } ``` ### `ConnectorIngestError` [#connectoringesterror] A recoverable error encountered during a connector pass. ```ts interface ConnectorIngestError { readonly connectorType: string; readonly message: string; readonly externalId?: string; readonly cause?: unknown; } ``` ### `FileSecretResolverOptions` [#filesecretresolveroptions] Constructor options for file-backed secret resolvers (`EnvSecretResolver`). ```ts interface FileSecretResolverOptions { readonly rootDir: string; } ``` ### `CloudSecretResolverOptions` [#cloudsecretresolveroptions] Constructor options for `CloudSecretResolver`. ```ts interface CloudSecretResolverOptions { readonly projectId: string; readonly apiKey: string; readonly cloudBaseUrl: string; } ``` ## Error Classes [#error-classes] All connector errors inherit from `ConnectorError` and provide a stable `.code` string: ```ts class ConnectorError extends Error { readonly code: string; constructor(code: string, message: string, options?: { cause?: unknown }); } ``` | Class | Base | `.code` | Properties | Thrown When | | ---------------------- | ---------------- | -------------------------- | ---------------------------- | --------------------------------------------------------------------------------------------------------------- | | `ConnectorConfigError` | `ConnectorError` | `"CONNECTOR_CONFIG_ERROR"` | — | `.memofs/connectors.json` is missing required structure, contains malformed rows, or violates token guardrails. | | `ConnectorSecretError` | `ConnectorError` | `"CONNECTOR_SECRET_ERROR"` | `readonly secretRef: string` | A `SecretResolver` fails to resolve a `secretRef`. | ## Constants [#constants] ### `EMPTY_CONNECTORS_FILE` [#empty_connectors_file] A frozen `{ connectors: [] }` default returned when `.memofs/connectors.json` is absent. ```ts const EMPTY_CONNECTORS_FILE: ConnectorsFile; ``` --- # @memofs/core API Reference (/docs/api/core) > Comprehensive technical API reference for @memofs/core, @memofs/core/node-fs, and @memofs/core/cloud-client. Complete TypeScript API reference for all exported classes, interfaces, types, constants, and functions across the three subpath entry points. ## Subpath Overview [#subpath-overview] ```ts // 1. Root entry (Worker-safe & environment-agnostic) import { MemoFS, RemoteBlobMemoryStore, InMemoryMemoryStore } from "@memofs/core"; // 2. Node.js filesystem adapter import { createNodeMemoFs, createNodeFsMemoryStore, NodeFsMemoryStore } from "@memofs/core/node-fs"; // 3. Cloud replication client import { createMemoFsCloudClient, createMemoFsCloudClientFromEnv } from "@memofs/core/cloud-client"; ``` ## 1. Primary Client & Factories [#1-primary-client--factories] ### `createNodeMemoFs(config?: MemoFsConfig): MemoFS` [#createnodememofsconfig-memofsconfig-memofs] *(Exported from `@memofs/core/node-fs`)* Constructs a `MemoFS` instance configured for Node.js. Automatically parses `.memofs/config.json`, instantiates a `NodeFsMemoryStore` at `rootDir`, and configures local embedders if enabled. ```ts import { createNodeMemoFs } from "@memofs/core/node-fs"; const memofs = createNodeMemoFs({ rootDir: ".", mode: "local", }); ``` ### `new MemoFS(config?: MemoFsConfig)` [#new-memofsconfig-memofsconfig] *(Exported from `@memofs/core`)* Instantiates the unified MemoFS client. In non-Node environments (Cloudflare Workers, Browsers), an explicit `store` must be provided. ```ts import { MemoFS, InMemoryMemoryStore } from "@memofs/core"; const memofs = new MemoFS({ store: new InMemoryMemoryStore(), projectId: "proj_123", mode: "local", }); ``` ## 2. Storage Adapters [#2-storage-adapters] ### `MemoryStore` [#memorystore] The fundamental 5-method interface required by all MemoFS storage adapters: ```ts interface MemoryStore { read(path: MemoryPath): Promise; write(path: MemoryPath, content: string): Promise; append(path: MemoryPath, content: string): Promise; exists(path: MemoryPath): Promise; delete(path: MemoryPath): Promise; } ``` ### `NodeFsMemoryStore` [#nodefsmemorystore] *(Exported from `@memofs/core/node-fs`)* Node.js POSIX filesystem implementation of `MemoryStore`. Supports directory creation, permissions, symlink traversal guards, and advisory cross-process locking (`.memofs/.lock`). ```ts import { createNodeFsMemoryStore } from "@memofs/core/node-fs"; const store = createNodeFsMemoryStore({ rootDir: "./workspace", createRoot: true, missingFileBehavior: "throw", // "throw" | "empty" disallowSymlinks: true, directoryMode: 0o700, fileMode: 0o600, lock: true, lockMaxAgeMs: 3600000, }); ``` ### `RemoteBlobMemoryStore` [#remoteblobmemorystore] *(Exported from `@memofs/core`)* Worker-safe implementation of `MemoryStore` backed by an opaque `BlobClient` (e.g. Cloudflare R2, S3) and a `MetadataStore` (e.g. Turso, SQLite, D1). ```ts import { RemoteBlobMemoryStore } from "@memofs/core"; const store = new RemoteBlobMemoryStore({ blobClient: r2BlobClient, metadata: tursoMetadataStore, rootKey: "project-123", }); ``` ### `InMemoryMemoryStore` [#inmemorymemorystore] *(Exported from `@memofs/core`)* Testing and ephemeral in-memory implementation of `MemoryStore`. ```ts import { InMemoryMemoryStore } from "@memofs/core"; const store = new InMemoryMemoryStore({ ".memofs/memory/core.md": "# Initial Rules\n", }); const snapshot = store.snapshot(); store.clear(); ``` ## 3. Provider Contracts [#3-provider-contracts] Core protocol contracts are strictly provider-neutral: ### `MemoryEmbedder` [#memoryembedder] ```ts interface MemoryEmbedder { readonly name: string; readonly dimension: number; embedText(text: string): Promise; embedTexts(texts: string[]): Promise; } ``` ### `Reranker` [#reranker] ```ts interface Reranker { rerank(input: { query: string; documents: Array<{ id: string; text: string; metadata?: Record }>; topK?: number; }): Promise }>>; } ``` ### `Extractor` [#extractor] ```ts interface Extractor { readonly name: string; extract(input: { text: string; sourceRef?: GraphSourceRef; defaultNodeType?: GraphNodeType; maxFacts?: number; mode?: "fast" | "balanced" | "quality"; }): Promise<{ nodes: GraphNode[]; edges: GraphEdge[]; contradictions?: Array<{ from: string; to: string; type: string }>; model?: string; usage?: { promptTokens?: number; totalTokens?: number }; }>; } ``` ### `LlmClient` [#llmclient] ```ts interface LlmClient { readonly name: string; complete(input: { system?: string; user: string; schema?: JsonObject; mode?: "fast" | "balanced" | "quality"; }): Promise<{ text: string; structured?: JsonObject; model?: string; usage?: { promptTokens?: number; totalTokens?: number }; }>; } ``` ### `MemoFSMemoryRuntime` [#memofsmemoryruntime] Framework-neutral runtime contract implemented by AI framework adapters (Vercel AI SDK, LangChain, Mastra): ```ts interface MemoFSMemoryRuntime { readCoreMemory(signal?: AbortSignal): Promise<{ content: string; updatedAt?: string; version?: number }>; updateCoreMemory(input: { content: string }, signal?: AbortSignal): Promise<{ content: string; updatedAt?: string; version?: number }>; listNotes(input?: MemoryRuntimeListNotesInput, signal?: AbortSignal): Promise>; createNote(input: MemoryRuntimeCreateNoteInput, signal?: AbortSignal): Promise; recall(input: MemoryRuntimeRecallInput, signal?: AbortSignal): Promise; index?(input?: MemoryRuntimeIndexInput, signal?: AbortSignal): Promise; } ``` ## 4. Graph Engine & Consolidation [#4-graph-engine--consolidation] ### `GraphStore` [#graphstore] ```ts interface GraphStore { upsertNodes(nodes: GraphNode[]): Promise; upsertEdges(edges: GraphEdge[]): Promise; getNode(id: string): Promise; getEdge(id: string): Promise; queryNodes(query?: GraphNodeQuery): Promise; queryEdges(query?: GraphEdgeQuery): Promise; neighbors(query: GraphNeighborQuery): Promise; fewestHopsPath(query: GraphShortestPathQuery): Promise; weightedShortestPath(query: GraphShortestPathQuery): Promise; mergeNodes(input: GraphMergeNodesInput): Promise; decayEdges(input: GraphDecayInput): Promise<{ updated: number; deleted: number }>; deleteNode(id: string, options?: { cascadeEdges?: boolean }): Promise; deleteEdge(id: string): Promise; clear(): Promise; stats(): Promise; exportSnapshot(): Promise; importSnapshot(snapshot: GraphSnapshot, options?: { clear?: boolean }): Promise; } ``` ### Graph Functions [#graph-functions] * `createRuleBasedExtractor(): Extractor`: Creates zero-dependency rule-based extractor. * `consolidateGraph(input: ConsolidationInput): ConsolidationResult`: Computes pure consolidation plan. * `applyConsolidation(store: ConsolidationStore, plan: ConsolidationResult): Promise<{ mergesApplied: number; retirementsApplied: number }>`: Persists consolidation plan. * `resolveCurrentFacts(options)`: Filters active facts for temporal validity. * `expandFromEntities(input)`: Graph traversal starting from seed entities. ## 5. Security & Write Intelligence [#5-security--write-intelligence] * `classifyDurability(input: DurabilityInput): DurabilityDecision`: Evaluates whether a memory is `"durable"` or `"transient"`. * `detectBlockedContent(text: string): BlocklistViolation[]`: Pure scanner detecting secret patterns. * `containsBlockedContent(text: string): boolean`: Quick boolean secret check. * `assertWriteAllowed(texts: string[], path?: string): void`: Throws `MemoryWriteBlockedError` if secrets are found. * `redactSecrets(message: string): string`: Redacts credentials from log and error strings. ## 6. Standalone Cloud Client [#6-standalone-cloud-client] *(Exported from `@memofs/core/cloud-client`)* ```ts import { createMemoFsCloudClient, createMemoFsCloudClientFromEnv, createProjectScopedClient, } from "@memofs/core/cloud-client"; const cloud = createMemoFsCloudClient({ baseUrl: "https://memofs.dev/api/v1", apiKey: "tm_live_...", defaultProjectId: "proj_123", }); const pushRes = await cloud.sync.push({ manifest: localManifest }); const commitRes = await cloud.sync.complete({ cursor: pushRes.cursor, uploaded: [] }); const pullRes = await cloud.sync.pull({ manifest: localManifest }); const statusRes = await cloud.sync.status(); ``` ## 7. Constants & Enums [#7-constants--enums] ```ts // Canonical Path Constants export const MEMOFS_DIR = ".memofs"; export const MANIFEST_PATH = ".memofs/manifest.json"; export const CORE_MEMORY_PATH = ".memofs/memory/core.md"; export const NOTES_MEMORY_PATH = ".memofs/memory/notes.md"; export const MEMORY_EVENTS_PATH = ".memofs/events/memory-events.jsonl"; export const CONVERSATIONS_MEMORY_PATH = ".memofs/events/conversations.jsonl"; export const CHUNKS_INDEX_PATH = ".memofs/indexes/chunks.jsonl"; export const EMBEDDINGS_INDEX_PATH = ".memofs/indexes/embeddings.jsonl"; export const GRAPH_NODES_PATH = ".memofs/graph/nodes.jsonl"; export const GRAPH_EDGES_PATH = ".memofs/graph/edges.jsonl"; export const SNAPSHOTS_INDEX_PATH = ".memofs/snapshots/snapshots.jsonl"; export const CONNECTORS_PATH = ".memofs/connectors.json"; // Taxonomy & Thresholds export const TASK_TYPES = ["coding", "debug", "refactor", "docs", "general"] as const; export const SESSION_OUTCOMES = ["success", "failure", "aborted"] as const; export const TRANSIENT_CONFIDENCE_THRESHOLD = 0.4; export const TRANSIENT_CONTENT_MIN_LENGTH = 20; export const EXPIRY_DAYS = { decision: 365, constraint: 180, reference: 180, goal: 120, preference: 90, summary: 60, note: 30, } as const; ``` ## 8. Error Hierarchy [#8-error-hierarchy] | Error Class | Base Class | Description | | ------------------------- | -------------------- | -------------------------------------------------------------------------------------------- | | `MemoFsError` | `Error` | Base class for all `@memofs/core` errors. | | `MemoryPathError` | `MemoFsError` | Thrown when a file path violates `.memofs/` boundary constraints or attempts path traversal. | | `MemoryNotFoundError` | `MemoFsError` | Thrown when a requested canonical document, snapshot, or node does not exist. | | `MemoryValidationError` | `MemoFsError` | Thrown on schema validation or malformed input structures. | | `MemoryParseError` | `MemoFsError` | Thrown on JSONL or Markdown document parsing failures. | | `MemoryCommandError` | `MemoFsError` | Thrown when an invalid `MemoryCommand` action is passed to `runCommand()`. | | `MemoryWriteBlockedError` | `MemoFsError` | Thrown by `assertWriteAllowed` when sensitive credentials or keys are detected. | | `MemoryStoreError` | `MemoFsError` | Base class for underlying storage driver failures. | | `FsMemoryStoreError` | `MemoryStoreError` | Filesystem I/O failures in `NodeFsMemoryStore`. | | `LockHeldError` | `FsMemoryStoreError` | Thrown when the advisory lock (`.memofs/.lock`) cannot be acquired. | | `GraphError` | `MemoFsError` | Knowledge graph cycle, missing node, or invalid edge type errors. | | `RerankError` | `MemoFsError` | Retrieval candidate reranking failures. | | `MemoFSCloudError` | `MemoFsError` | Base class for cloud sync and HTTP replication errors. | --- # API Reference Overview (/docs/api) > Complete API reference for MemoFS npm packages: @memofs/core, @memofs/server, @memofs/mcp-server, and @memofs/connectors. Welcome to the MemoFS API Reference documentation. MemoFS's application programming interfaces are structured around modular, scoped npm packages. ## Core Packages [#core-packages] * **[`@memofs/core`](./core)**: The central memory runtime, virtual AgentFS, graph engine, and hybrid recall router. * **[`@memofs/cli`](./cli)**: The command-line interface, configuration generator, and programmatic CLI runner. * **[`@memofs/server`](./server)**: The hosted, self-deployable server wrapping the memory engine behind a JSON-RPC 2.0 API. * **[`@memofs/mcp-server`](./mcp-server)**: Exposes memory-control tools to AI agents using the Model Context Protocol. * **[`@memofs/connectors`](./connectors)**: Local ingestion plug-in framework for loading third-party sources (e.g. GitHub, Notion). ## Provider Adapters [#provider-adapters] * **[`@memofs/adapter-openai`](/adapters/openai)**: Hosted vector embeddings via OpenAI `text-embedding-3`. * **[`@memofs/adapter-voyage`](/adapters/voyage)**: Domain embeddings (`voyage-4`/`3.5`) and neural reranking (`rerank-2.5-lite`). * **[`@memofs/adapter-transformers`](/adapters/transformers)**: 100% offline in-process ONNX embeddings (`Xenova/bge-small-en-v1.5`). * **[`@memofs/adapter-workers-ai`](/adapters/workers-ai)**: Cloudflare serverless GPU entity extraction with Llama 3.1 8B. * **[`@memofs/adapter-r2`](/adapters/r2)**: Content-addressed Cloudflare R2 blob client for serverless storage. * **[`@memofs/adapter-turso`](/adapters/turso)**: Manifest metadata and serialized transaction locking over Turso/libSQL. * **[`@memofs/adapter-ai-sdk`](/adapters/ai-sdk)**: Vercel AI SDK tools, prompt context builders, and multi-tenant scoping. ## Developer Utilities [#developer-utilities] * **`@memofs/json-rpc`**: Validation schemas and types for the JSON-RPC 2.0 protocol. * **`@memofs/testing`**: Reusable contract tests, mock fakes, and test fixtures. * **`@memofs/benchmark-kit`**: Workloads and statistical runners to profile memory components. --- # @memofs/mcp-server API Reference (/docs/api/mcp-server) > Comprehensive technical API reference for @memofs/mcp-server and @memofs/mcp-server/http: protocol servers, transports, runtime adapters, and SDK integration. The `@memofs/mcp-server` package implements a transport-agnostic Model Context Protocol (MCP) server for MemoFS, exposing memory tools, resources, and prompts over stdio, HTTP (Cloudflare Workers, Hono, Node.js fetch), and `@modelcontextprotocol/sdk` adapters. ## Package Subpaths [#package-subpaths] ```ts // 1. Primary Entrypoint (Stdio transport, protocol server, runtime adapter, SDK bridge) import { createMemoFSMcpRuntimeFromConfig, createMemoFSMcpRuntimeFromMemoFS, createMemoFSMcpProtocolServer, runStdioServer, registerMemoFSMcpCapabilities, MemoFSMcpError, } from "@memofs/mcp-server"; // 2. HTTP Entrypoint (Stateless Streamable HTTP for Cloudflare Workers & Hono) import { handleMemoFSMcpRequest, createMemoFSMcpFetchHandler, createHonoMemoFSMcpHandler, createMemoFSCloudMcpRuntime, } from "@memofs/mcp-server/http"; ``` *** ## 1. Composing a Stdio MCP Server [#1-composing-a-stdio-mcp-server] ```ts import { createNodeMemoFs } from "@memofs/core/node-fs"; import { createMemoFSMcpRuntimeFromMemoFS, createMemoFSMcpProtocolServer, runStdioServer, } from "@memofs/mcp-server"; // 1. Create or configure a MemoFS instance const memo = createNodeMemoFs({ rootDir: "." }); // 2. Wrap the MemoFS instance as an MCP runtime adapter const runtime = createMemoFSMcpRuntimeFromMemoFS(memo); // 3. Create the protocol server const server = createMemoFSMcpProtocolServer({ runtime, name: "memofs", version: "1.3.0", }); // 4. Run the stdio transport loop (reads stdin, writes stdout) await runStdioServer(server); ``` *** ## 2. Core Functions (`@memofs/mcp-server`) [#2-core-functions-memofsmcp-server] ### `createMemoFSMcpRuntimeFromConfig(options?: RuntimeFactoryOptions): MemoFSMcpRuntime` [#creatememofsmcpruntimefromconfigoptions-runtimefactoryoptions-memofsmcpruntime] Builds a `MemoFS` client from config options and wraps it as a `MemoFSMcpRuntime`. ```ts import { createMemoFSMcpRuntimeFromConfig } from "@memofs/mcp-server"; const runtime = createMemoFSMcpRuntimeFromConfig({ rootDir: "./my-project", mode: "hybrid", cloud: { baseUrl: "https://memofs.dev/api/v1", apiKey: process.env.MEMOFS_API_KEY, }, recall: { localEmbeddings: true, }, }); ``` ### `createMemoFSMcpRuntimeFromMemoFS(memo: MemoFS): MemoFSMcpRuntime` [#creatememofsmcpruntimefrommemofsmemo-memofs-memofsmcpruntime] Wraps an existing [`MemoFS`](/api/core) instance as a `MemoFSMcpRuntime`. ```ts import { MemoFS } from "@memofs/core"; import { createMemoFSMcpRuntimeFromMemoFS } from "@memofs/mcp-server"; const runtime = createMemoFSMcpRuntimeFromMemoFS(memo); ``` ### `createMemoFSMcpProtocolServer(options: MemoFSMcpOptions): MemoFSMcpProtocolServer` [#creatememofsmcpprotocolserveroptions-memofsmcpoptions-memofsmcpprotocolserver] Creates a transport-agnostic protocol handler that parses JSON-RPC 2.0 messages and routes tool, resource, and prompt requests to the runtime. ```ts const server = createMemoFSMcpProtocolServer({ runtime, readOnly: false, maxPageSize: 50, requestTimeoutMs: 30000, }); ``` ### `runStdioServer(server: MemoFSMcpProtocolServer): Promise` [#runstdioserverserver-memofsmcpprotocolserver-promisevoid] Runs a protocol server over stdio, reading newline-delimited JSON-RPC from standard input and writing responses to standard output. Resolves when standard input closes. ### `registerMemoFSMcpCapabilities(server: StructuralMcpServer, options: MemoFSMcpOptions): void` [#registermemofsmcpcapabilitiesserver-structuralmcpserver-options-memofsmcpoptions-void] Registers MemoFS tools, resources, and prompts directly onto an instantiated `@modelcontextprotocol/sdk` (or FastMCP) server object. ```ts import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { registerMemoFSMcpCapabilities, createMemoFSMcpRuntimeFromConfig } from "@memofs/mcp-server"; const mcpSdkServer = new McpServer({ name: "my-agent-server", version: "1.0.0" }); const runtime = createMemoFSMcpRuntimeFromConfig({ rootDir: "." }); registerMemoFSMcpCapabilities(mcpSdkServer, { runtime }); ``` *** ## 3. HTTP & Worker Functions (`@memofs/mcp-server/http`) [#3-http--worker-functions-memofsmcp-serverhttp] The `@memofs/mcp-server/http` subpath provides Web Fetch–compatible handlers designed for Cloudflare Workers, Hono, and hosted HTTP environments. ### `handleMemoFSMcpRequest(request: Request, options?: MemoFSMcpHttpOptions): Promise` [#handlememofsmcprequestrequest-request-options-memofsmcphttpoptions-promiseresponse] Handles an incoming Streamable HTTP POST/OPTIONS request, enforcing origin checks, CORS, bearer token authentication, header validation, and JSON-RPC dispatching. ```ts import { handleMemoFSMcpRequest } from "@memofs/mcp-server/http"; export default { async fetch(request: Request, env: Record): Promise { return handleMemoFSMcpRequest(request, { env, auth: { bearerToken: env.MEMOFS_MCP_BEARER_TOKEN, }, }); }, }; ``` ### `createMemoFSMcpFetchHandler(options?: MemoFSMcpHttpOptions): MemoFSMcpFetchHandler` [#creatememofsmcpfetchhandlerenvoptions-memofsmcphttpoptions-memofsmcpfetchhandlerenv] Constructs a standard Cloudflare Workers `fetch` handler function. ```ts import { createMemoFSMcpFetchHandler } from "@memofs/mcp-server/http"; export default { fetch: createMemoFSMcpFetchHandler({ cloud: { baseUrl: "https://memofs.dev/api/v1", }, }), }; ``` ### `createHonoMemoFSMcpHandler(options?: MemoFSMcpHttpOptions)` [#createhonomemofsmcphandleroptions-memofsmcphttpoptions] Creates an MCP route handler for Hono applications. ```ts import { Hono } from "hono"; import { createHonoMemoFSMcpHandler } from "@memofs/mcp-server/http"; const app = new Hono(); app.post("/mcp", createHonoMemoFSMcpHandler()); ``` ### `createMemoFSCloudMcpRuntime(options: MemoFSCloudMcpRuntimeOptions): MemoFSMcpRuntime` [#creatememofscloudmcpruntimeoptions-memofscloudmcpruntimeoptions-memofsmcpruntime] Creates a lightweight cloud-only `MemoFSMcpRuntime` backed by a remote MemoFS Cloud API endpoint. *** ## 4. Interfaces & Types [#4-interfaces--types] ### `MemoFSMcpOptions` [#memofsmcpoptions] ```ts interface MemoFSMcpOptions { runtime: MemoFSMcpRuntime; name?: string; version?: string; instructions?: string; readOnly?: boolean; defaultPageSize?: number; // default: 25 maxPageSize?: number; // default: 100 requestTimeoutMs?: number;// default: 30000 maxInputBytes?: number; // default: 256000 maxOutputBytes?: number; // default: 512000 authorize?: (context: AuthorizationContext) => Promise | boolean; redact?: (args: unknown) => unknown; } ``` ### `RuntimeFactoryOptions` [#runtimefactoryoptions] ```ts interface RuntimeFactoryOptions { mode?: "local" | "hybrid"; rootDir?: string; projectId?: string; workspaceId?: string; store?: MemoryStore; cloudClient?: MemoFsCloudClient; cloud?: { baseUrl?: string; apiKey?: string; workspaceId?: string; projectId?: string; timeoutMs?: number; userAgent?: string; requireApiKey?: boolean; retry?: { maxRetries?: number; backoffMs?: number }; }; recall?: { engine?: "lexical" | "vector" | "hybrid" | "auto"; localEmbeddings?: boolean; embeddingModel?: string; }; onModelProgress?: (info: { progress: number; status: string; file?: string }) => void; prewarm?: boolean; } ``` ### `MemoFSMcpHttpOptions` [#memofsmcphttpoptions] ```ts interface MemoFSMcpHttpOptions extends Omit { runtime?: MemoFSMcpRuntime; env?: MemoFSMcpHttpEnv; cloud?: Partial; auth?: { requireAuth?: boolean; bearerToken?: string; authenticate?: (request: Request) => boolean | Promise; }; allowedOrigins?: readonly string[]; } ``` *** ## 5. Error Hierarchy [#5-error-hierarchy] All MCP errors extend `MemoFSMcpError` and carry `.code` (stable machine string), `.status` (HTTP status code), and `.details`. | Class | `.code` | `.status` | Thrown when | | ----------------------- | ------------------------- | --------- | ------------------------------------------------------------------------- | | `McpValidationError` | `MCP_VALIDATION_ERROR` | 400 | A request fails schema or argument validation | | `McpAuthorizationError` | `MCP_AUTHORIZATION_ERROR` | 403 | A write tool is invoked without authorization or read-only mode is active | | `McpNotFoundError` | `MCP_NOT_FOUND` | 404 | An unknown tool, resource, or prompt is requested | | `McpTimeoutError` | `MCP_TIMEOUT` | 504 | An operation exceeds `requestTimeoutMs` | | `McpOutputLimitError` | `MCP_OUTPUT_LIMIT` | 413 | A response payload exceeds `maxOutputBytes` | | `MemoFSMcpError` | `MEMOFS_MCP_ERROR` | 500 | Base error class | ### `toSafeError(error: unknown)` [#tosafeerrorerror-unknown] Normalizes any caught error into a safe `{ name, message, code, status, details? }` payload suitable for JSON-RPC error responses. *** ## See Also [#see-also] * [MCP Server Overview](/mcp/) — stdio server configuration, CLI flags, and client configuration snippets. * [Hybrid Mode](/mcp/hybrid-mode) — local stdio server with cloud replica synchronization. * [Hosted MCP Endpoint](/mcp/hosted-mcp-endpoint) — Streamable HTTP endpoint for remote agents. * [Core API Reference](/api/core) — the underlying `MemoFS` runtime client. --- # @memofs/server API Reference (/docs/api/server) > Complete TypeScript API reference for @memofs/server: runtime assembly, HTTP core, Cloudflare Worker handler, and JSON-RPC dispatch. The `@memofs/server` package exports the hosted runtime assembly factory, framework-free HTTP core request handlers, Cloudflare Worker adapters, and JSON-RPC 2.0 protocol dispatchers. ## Assembly & Runtime Factories [#assembly--runtime-factories] ### `createHostedRuntime(options: HostedRuntimeOptions): MemoFS` [#createhostedruntimeoptions-hostedruntimeoptions-memofs] Assembles a unified `MemoFS` instance using an injected storage adapter and optional intelligence drivers (embedders, rerankers, extractors). ```ts import { createHostedRuntime } from "@memofs/server"; const memofs = createHostedRuntime({ store: memoryStore, projectId: "my-hosted-project", embedder: customEmbedder, }); ``` #### `HostedRuntimeOptions` [#hostedruntimeoptions] | Option | Type | Required | Description | | ------------- | ---------------- | -------- | ----------------------------------------------------------------------------------------------------- | | `store` | `MemoryStore` | **Yes** | Backing storage implementation (`NodeFsMemoryStore`, `RemoteBlobMemoryStore`, `InMemoryMemoryStore`). | | `projectId` | `string` | **Yes** | Project identifier scoping this runtime. | | `embedder` | `MemoryEmbedder` | No | Text embedder instance for vector indexing. | | `recallStore` | `RecallStore` | No | Vector index store. Auto-wired when embedder is present. | | `reranker` | `Reranker` | No | Reranking provider for recall candidates. | | `extractor` | `Extractor` | No | Entity and relationship extractor for knowledge graphs. | | `llmClient` | `LlmClient` | No | LLM transport for generative intelligence and consolidation. | | `name` | `string` | No | Runtime client name (default: `"memofs-server"`). | | `version` | `string` | No | Runtime version (default: `"0.1.0"`). | ## HTTP Core Handlers [#http-core-handlers] ### `handleRuntimeRequest(request: Request, options: RuntimeHttpOptions): Promise` [#handleruntimerequestrequest-request-options-runtimehttpoptions-promiseresponse] Framework-agnostic handler that processes HTTP requests containing standard JSON-RPC 2.0 payloads. ```ts import { handleRuntimeRequest } from "@memofs/server"; const response = await handleRuntimeRequest(request, { runtime: memofs, requireAuth: true, bearerToken: process.env.MEMOFS_SERVER_TOKEN, allowedOrigins: ["https://app.example.com"], }); ``` #### `RuntimeHttpOptions` [#runtimehttpoptions] | Option | Type | Required | Description | | ------------------ | ------------------- | -------- | -------------------------------------------------------------- | | `runtime` | `MemoFS` | **Yes** | Target runtime instance executing memory operations. | | `concurrencyLayer` | `ConcurrencyLayer` | No | Injected coordinator for gating/serializing mutating requests. | | `requireAuth` | `boolean` | No | Require a bearer token on `POST /` (default: `false`). | | `bearerToken` | `string` | No | The expected bearer token when `requireAuth` is `true`. | | `allowedOrigins` | `readonly string[]` | No | Allowed browser `Origin` values for CORS preflight. | ### `createRuntimeFetchHandler(options: RuntimeFetchHandlerOptions)` [#createruntimefetchhandleroptions-runtimefetchhandleroptions] *(Exported from `@memofs/server/worker` and `@memofs/server`)* Produces a standard Cloudflare Workers `fetch(request, env, ctx)` handler. ```ts import { createRuntimeFetchHandler } from "@memofs/server/worker"; export default { fetch: createRuntimeFetchHandler({ createRuntime: async (env, request) => { return createHostedRuntime({ store: getR2Store(env), projectId: request.headers.get("x-project-id") ?? "default", }); }, requireAuth: false, }), }; ``` ## JSON-RPC 2.0 Protocol Methods [#json-rpc-20-protocol-methods] All requests are dispatched as standard JSON-RPC 2.0 objects (`{ jsonrpc: "2.0", id: 1, method: "...", params: { ... } }`). ### Read-Only (Live) Methods [#read-only-live-methods] | Method | Parameters | Return Value | Description | | -------------------------- | ---------------------------------------------------------- | ----------------------------- | ------------------------------------------ | | `health` | `{}` | `MemoFSHealthResult` | Liveness check and component status. | | `recall` | `{ query: string, limit?: number, filter?: RecallFilter }` | `RecallResult` | Semantic and lexical retrieval. | | `context` | `MemoryContextInput` | `MemoryContextResult` | Formatted markdown/context briefing. | | `memory.readCore` | `{}` | `string` | Content of `memory/core.md`. | | `memory.readNotes` | `{}` | `string` | Content of `memory/notes.md`. | | `memory.readConversations` | `{ limit?: number }` | `ConversationEntry[]` | Chronological conversation logs. | | `memory.listRecent` | `{ limit?: number }` | `RecentMemoryResult` | Chronological log of recent memory events. | | `memory.validate` | `{ strict?: boolean }` | `ValidateMemoryResult` | Integrity and schema validation check. | | `graph.listNodes` | `ListGraphInput` | `{ items: GraphNodeInput[] }` | Entity nodes in knowledge graph. | | `graph.listEdges` | `ListGraphInput` | `{ items: GraphEdgeInput[] }` | Relationship edges in knowledge graph. | | `graph.neighbors` | `GraphNeighborsInput` | `GraphNeighborsResult` | Related entities and connections. | | `graph.path` | `GraphPathInput` | `GraphPathResult` | Shortest relation path between entities. | | `snapshots.list` | `{}` | `SnapshotRecord[]` | Checkpoints and rollback history. | ### Mutating (Gated) Methods [#mutating-gated-methods] Mutating methods require an active `concurrencyLayer` to serialize concurrent requests. When no concurrency layer is supplied, these methods safely return `503 Service Unavailable` with `CONCURRENCY_GATE_ERROR_CODE` (`-32000`). | Method | Parameters | Return Value | Description | | --------------------------- | ----------------------------- | ----------------------------- | ------------------------------------ | | `memory.write` | `WriteMemoryInput` | `WriteMemoryResult` | Stores a classified memory item. | | `memory.recordNote` | `TimestampedNoteInput` | `WriteMemoryResult` | Appends a timestamped log note. | | `memory.updateCore` | `{ content: string }` | `void` | Overwrites `memory/core.md`. | | `memory.appendConversation` | `ConversationEntry` | `void` | Appends a conversation record. | | `graph.upsertNodes` | `{ nodes: GraphNodeInput[] }` | `{ nodes: GraphNodeInput[] }` | Updates knowledge graph entities. | | `graph.upsertEdges` | `{ edges: GraphEdgeInput[] }` | `{ edges: GraphEdgeInput[] }` | Updates knowledge graph relations. | | `consolidate` | `ConsolidateMemoryInput` | `ConsolidateMemoryResult` | Merges/retires overlapping memories. | | `snapshots.create` | `SnapshotMemoryInput` | `SnapshotMemoryResult` | Takes a point-in-time checkpoint. | | `snapshots.restore` | `{ id: string }` | `void` | Reverts filesystem to checkpoint. | ## Direct Dispatch Utilities [#direct-dispatch-utilities] For custom network transports (WebSockets, IPC, Worker Service Bindings): ```ts import { dispatchRuntimeMessage, dispatchRuntimeText } from "@memofs/server"; // Dispatches parsed JSON-RPC payload across the runtime const response = await dispatchRuntimeMessage( memofs, { jsonrpc: "2.0", id: "req-1", method: "recall", params: { query: "auth" } }, { concurrencyLayer: myMutex } ); // Dispatches raw string payload const rawResponseString = await dispatchRuntimeText( memofs, '{"jsonrpc":"2.0","id":1,"method":"health"}' ); ``` ## Protocol Constants [#protocol-constants] | Constant | Value / Type | Description | | ------------------------------ | ----------------------------------------- | --------------------------------------------------------------------------------------------------- | | `RUNTIME_METHOD` | `Record` | Canonical dictionary mapping symbolic keys to JSON-RPC method strings. | | `LIVE_METHODS` | `ReadonlySet` | Set of live, read-only method names that execute concurrently without locking. | | `GATED_METHODS` | `ReadonlySet` | Set of mutating method names requiring an injected concurrency layer. | | `CONCURRENCY_GATE_ERROR_CODE` | `-32000` | Standard JSON-RPC server error code returned when mutating without concurrency layer. | | `CONCURRENCY_GATE_HTTP_STATUS` | `503` | HTTP status code carried in gate failure payload `data`. | | `CONCURRENCY_GATE_MESSAGE` | `string` | `"Concurrent writes require the concurrency layer. This method is read-only until it is injected."` | | `concurrencyGateFailure(id)` | `(id: JsonRpcId) => JsonRpcErrorResponse` | Helper function constructing the canonical 503 error envelope. | --- # Changelog (/docs/changelog) > All notable changes to MemoFS. All notable changes to MemoFS are documented here. Each MemoFS package maintains its own changelog. This page highlights notable changes across the project. **Per-package changelogs** — see each package's `CHANGELOG.md` for the full history: [`@memofs/core`](https://github.com/memo-fs/memofs/blob/main/packages/core/CHANGELOG.md) · [`@memofs/cli`](https://github.com/memo-fs/memofs/blob/main/packages/cli/CHANGELOG.md) · [`@memofs/mcp-server`](https://github.com/memo-fs/memofs/blob/main/packages/mcp-server/CHANGELOG.md) · [`@memofs/server`](https://github.com/memo-fs/memofs/blob/main/packages/server/CHANGELOG.md) · [all packages →](https://github.com/memo-fs/memofs/releases) **GitHub Releases** — [memo-fs/memofs/releases](https://github.com/memo-fs/memofs/releases) for tagged releases with notes. ## Unreleased [#unreleased] *No changes yet.* ## v1.3.0-beta.3 — August 17, 2026 [#v130-beta3--august-17-2026] Official Model Context Protocol Registry metadata, package ownership verification, and multi-transport support. ### MCP Server [#mcp-server] #### Added [#added] * Added official Model Context Protocol Registry manifest metadata for automated ecosystem discovery and subregistry indexing. * Added package ownership verification property to MCP server package configuration. * Added multi-transport support documenting local stdio runtime configuration and hosted streamable HTTP endpoints. ## v1.3.0-beta.2 — August 16, 2026 [#v130-beta2--august-16-2026] Typed note identifiers, write idempotency deduplication, and multi-dimensional status modeling. ### Core [#core] #### Added [#added-1] * Added typed identifier support to note and conversation document interfaces. * Added frontmatter and metadata normalization and serialization support for note identifiers. * Added write idempotency deduplication to memory write inputs, preventing duplicate appends to memory files and event logs during write retries. * Added orthogonal status dimensions (disputed, stale, unverified) to graph nodes and edges to avoid semantic collisions across deprecation, dispute, drift, and decay. * Updated graph conflict detection to flag disputed edges alongside legacy conflict status. ## v1.3.0-beta.1 — August 13, 2026 [#v130-beta1--august-13-2026] Anchor drift detection, memory decay floors, semantic GC archive/restore, and session outcomes. ### Core [#core-1] #### Added [#added-2] * Added anchor reference support with file paths, hashes, and optional symbols to memory write inputs and prose content via anchor markers. * Added write-time symbol path extraction for TypeScript files using the TypeScript Compiler API with path traversal security validation. * Added query-time drift detection inside memory recall and context building. Memories with modified or deleted target files transition to stale status, receive a stale flag on recall items, and get demoted in search relevance with a half score multiplier. * Added manifest hash caching with modification time invalidation and persistence for cross-session drift checks. * Added kind-specific decay floors for all seven memory kinds ranging from 30 days for notes to 365 days for decisions. * Added unverified status for graph facts. Active memories exceeding their decay floor transition to unverified status, set an unverified metadata flag on recall items, and receive a score demotion while remaining accessible for re-verification. * Added outcome parameters indicating success, failure, or aborted status, ephemeral cleanup flags, and failure reason inputs to session completion functions. * Implemented a five-row outcome matrix that gates durable memory promotion on successful outcome and durable memory extraction, while governing working and output directory cleanup. * Added support for session resumption across aborted completions by preserving workspace state. * Added session failure audit event logging with failure reason telemetry. ### CLI [#cli] #### Added [#added-3] * Added a CLI command to backfill anchor metadata onto existing structured note entries by parsing file and symbol references. * Added a CLI command option to move deprecated memory entries into cold storage archive files and remove them from active recall indexes. * Added a CLI command to restore archived memory records back to active memory files and reactivate their graph node status. * Added archived and restored audit event logging to memory events. * Added a fix option to the doctor command to automatically consolidate memory graph nodes and move deprecated memory entries into cold storage archive files. * Added a diagnostic check to the doctor command that warns when deprecated memory entries are pending archive. ### MCP Server [#mcp-server-1] #### Added [#added-4] * Added optional anchor parameters to memory write tool definitions and stale indicators to recall tool output. * Added outcome, ephemeral cleanup, and failure reason parameters to the agent session completion tool. ### Agent Behavior Enforcement [#agent-behavior-enforcement] #### Changed [#changed] * Strengthened generated agent rules files so the MemoFS memory workflow is binding rather than advisory, adding strict requirement headings, forbidding unverified assumptions, and adding task completion memory checks. * Generating agent rules targets now emits only the primary instructions file, while umbrella agent generation commands produce local workspace rules directories and git conventions files. * Generating Claude agent rules emits a single import reference when a root agents rules file already exists, maintaining a single source of truth without duplicating content. #### Added [#added-5] * Added advisory warnings to the workspace doctor command when core memory exceeds 200 lines to match instruction file soft limits. #### Removed [#removed] * Removed the pointers section from the generated agent rules template to streamline configuration. * Removed the hard limit and validation errors for maximum agent rules line counts, replacing it with soft line advisories on core memory. #### Fixed [#fixed] * Fixed Claude Code and Codex session hooks from failing silently when the CLI is not installed globally by adding automatic fallback execution. * Applied local execution fallback to generated opencode plugin events to ensure compliance markers and status notifications display properly. ## v1.2.0-beta.3 — August 6, 2026 [#v120-beta3--august-6-2026] Vercel AI SDK adapter schema refactoring, CLI UI/UX progress indicators, and terminal signal handling. ### Adapters [#adapters] #### Fixed [#fixed-1] * Refactored the Vercel AI SDK tool input schema to a root object format, fixing tool-calling compatibility with OpenAI, Anthropic, and Google Gemini models. * Exposed both parameters and inputSchema fields on the memory tool definition for full compatibility across Vercel AI SDK versions. ### CLI [#cli-1] #### Added [#added-6] * Added zero-dependency TTY step spinners and itemized progress bars for long-running cloud sync operations. * Added animated progress feedback during workspace integrity diagnostics and external connector runs. * Added SIGINT and SIGTERM terminal signal handlers to gracefully restore cursor visibility and handle cancellation. * Added automatic visual animation suppression when output is piped, NO\_COLOR is set, or JSON mode is active. ## v1.2.0-beta.2 — July 26, 2026 [#v120-beta2--july-26-2026] Project manifest fallback, global CLI flag polish, and cloud sync snapshot fixes. ### Core [#core-2] #### Fixed [#fixed-2] * Improved project ID resolution so local workspace operations automatically fall back to the project manifest when omitted in configuration or flags. ### CLI [#cli-2] #### Added [#added-7] * Added short flag support for global project ID selection across all cloud and sync subcommands. #### Fixed [#fixed-3] * Fixed an issue during cloud sync pulls where mandatory pre-sync snapshots were skipped prior to overwriting local workspace files. * Fixed cloud sync push to properly forward explicit base cursor values when confirming upload completion. ## v1.2.0-beta.1 — July 25, 2026 [#v120-beta1--july-25-2026] Core hardening, recall improvements, connector enhancements, and cloud app release. ### Cloud [#cloud] #### Added [#added-8] * [MemoFS Cloud](https://memofs.dev) is now live!. ### Core [#core-3] #### Fixed [#fixed-4] * Fixed a rare bug where two memory graph nodes could collide and silently overwrite each other. * Fixed a rare bug where two snapshots created in quick succession could end up with the same ID. * Fixed an issue where a failed write could leave the memory graph in a partially updated state instead of rolling back cleanly. * Fixed a file-locking bug on macOS that could stall under heavy load. * Fixed entity matching so short terms like "db" no longer incorrectly match unrelated longer words. * Fixed an issue where combining results from different memory sources could drop metadata. #### Changed [#changed-1] * Reduced memory growth during long-running sessions by capping internal caches. * Improved consistency between search and ranking so results match more reliably. * Improved search relevance for headings made up of multiple words. * Improved recall so results aren't held back when only one search method (keyword or vector) finds matches. * Improved reliability of context building across more JavaScript runtimes, including web workers. * Added optional logging for background operations like indexing and graph updates, to make debugging easier. * The recall pipeline now automatically resolves the appropriate recall store without requiring manual configuration. ### CLI [#cli-3] #### Fixed [#fixed-5] * Fixed an incorrect default schema URL in generated configuration files. #### Changed [#changed-2] * Optimized runtime configuration and commander option handling for lower startup overhead. ### MCP Server [#mcp-server-2] #### Added [#added-9] * Non-blocking HuggingFace model prewarming on server startup when `localEmbeddings` is enabled, eliminating cold-start latency on the first memory tool call. * Progress updates output to `stderr` during initial model weight downloads (`[memofs] Downloading local embedding model weights...`). #### Changed [#changed-3] * Increased default per-tool request timeout from 30s to 60s to prevent false timeout failures during first-time weight downloads on slower connections. ### Connectors [#connectors] #### Added [#added-10] * GitHub Discussions connector now maps the discussion category as a label on the resulting note. ### Agents / Hosted MCP [#agents--hosted-mcp] * Documentation updated for the agent generation and hook commands introduced in `1.1.0-beta.1` (agent rules and getting-started guides). ## v1.1.0-beta.1 — July 21, 2026 [#v110-beta1--july-21-2026] Persistence and reliability improvements across the core, CLI, and connectors — plus a new system that helps coding agents consistently load and use memory throughout a session. ### Core Reliability [#core-reliability] #### Fixed [#fixed-6] * Fixed an issue where restarting could cause previously saved memory and graph data to appear lost. * Fixed file-locking bugs that could cause conflicts between concurrent sessions. * Fixed a bug where missing remote data could silently corrupt a saved record instead of raising an error. * Fixed an issue where a failed memory write could be incorrectly reported as successful. #### Changed [#changed-4] * Improved compatibility so core hashing now works in more JavaScript environments, including web workers. ### Connectors [#connectors-1] #### Fixed [#fixed-7] * Fixed a bug in connector duplicate-detection that could cause repeated notes to be created on re-runs. #### Changed [#changed-5] * Unified timeout and retry handling across the built-in GitHub and Notion connectors for more consistent behavior. * Simplified shared formatting logic between the GitHub and Notion connectors. ### Agent Behavior Enforcement [#agent-behavior-enforcement-1] A new system that helps coding agents reliably load, consult, and save memory throughout a session. #### Added [#added-11] * Session hooks for Claude Code, Codex, Cursor, and opencode that automatically load memory context at the start of a session, refresh it after long-conversation compaction, and summarize memory usage when a session ends. * A compliance summary showing whether an agent loaded context, consulted memory, and saved new information during a session. * Task-aware memory retrieval, so agents get more relevant results based on the kind of work they're doing. * Support for opencode across all agent generation commands. #### Changed [#changed-6] * Workspace initialization now also generates a schema reference for editor validation and autocomplete. * Config schema references now resolve from your installed CLI version instead of a versioned docs URL, so they can't drift out of sync. * Generated agent instructions now include clearer workspace rules and links to project conventions. #### Fixed [#fixed-8] * Fixed an issue in Cloud sync where file manifests could be generated incorrectly. #### Removed [#removed-1] * The old versioned schema URL system, replaced by local schema resolution. ## v1.0.0-beta.2 — July 10, 2026 [#v100-beta2--july-10-2026] First public beta. ### Core [#core-4] #### Added [#added-12] * A file-first memory runtime — memory lives in your local workspace as the source of truth, not a database. * A virtual filesystem for project memory, with separate working and output areas. * A hybrid recall pipeline combining keyword, fuzzy, and vector search with pluggable embedders and rerankers. * Durable graph memory with nodes, edges, versioned snapshots, and conflict-free writes. * Support for pluggable embedders, rerankers, recall stores, extractors, and LLM clients. * A local filesystem-backed memory store for production use, and an in-memory store for testing. ### CLI [#cli-4] #### Added [#added-13] * A command to initialize a local memory workspace. * A command to save durable decisions, constraints, goals, and preferences. * A command to run hybrid semantic and keyword search over memory. * A command to build task-ready context from core memory, recall results, and recent notes. * A command to inspect current memory state. * A command to consolidate memory — merging duplicates and retiring outdated facts. * A command to sync workspace files with MemoFS Cloud. ### MCP Server [#mcp-server-3] #### Added [#added-14] * Four memory tools: context, recall, remember, and consolidate. * Six session tools for starting, reading, writing, appending, extracting, and completing agent sessions. * Nine resources covering health, context, core memory, notes, recent memory, and graph nodes and edges. * Configurable via runtime flags or environment variables, with a read-only mode. ### Server [#server] #### Added [#added-15] * A self-hostable, provider-neutral memory server, available as a Node binary or a Cloudflare Worker. * Deterministic defaults for every component — keyword-only recall, token-overlap reranking, rule-based extraction — so it works out of the box with no external API keys required. * Bearer-token authentication. * JSON-RPC 2.0 over HTTP. ### Adapters [#adapters-1] #### Added [#added-16] * OpenAI embeddings (three models supported). * Voyage AI embeddings and reranking. * Local embeddings via Transformers.js — no API key or cloud service required. * Cloudflare R2 for blob storage. * Turso/libSQL for metadata storage. * Cloudflare Workers AI for entity extraction. * A Vercel AI SDK bridge with tool definitions and context builders. ### Connectors [#connectors-2] #### Added [#added-17] * A local ingestion framework for external sources like GitHub and Notion. * Secure token handling — credentials are never written to disk. * Deduplication and stable source references for imported content. ### Shared Utilities [#shared-utilities] #### Added [#added-18] * A dependency-free JSON-RPC 2.0 protocol package. * A testing package with contract tests and fixtures for building your own adapters. * A benchmarking kit with statistical analysis and markdown reporting. --- # Agent Commands (/docs/cli/agent) > CLI commands for managing AgentFS-backed AI agent sessions and working memory. The `agent` command family manages local AgentFS session workspaces for AI agents (Codex, Claude Code, custom agent swarms, etc.). Sessions provide isolated scratch workspaces containing context snapshots, working progress files, and structured output files. ## Session Architecture & Layout [#session-architecture--layout] When an agent session starts, a dedicated directory structure is created under `/agent-sessions//`: ```text agent-sessions// ├── context/ │ ├── core.md # Snapshot of core memory at session start │ └── notes.md # Snapshot of notes memory at session start ├── working/ │ ├── plan.md # Current execution plan │ ├── commands.md # Shell commands executed during session │ ├── errors.md # Errors encountered and workarounds │ └── changes.md # Files modified and changelog └── output/ ├── summary.md # High-level task summary ├── durable-memory.md # Extracted facts to persist └── follow-ups.md # Suggested next steps ``` The latest active session is tracked locally at `.memofs/tmp/agent-sessions/latest.json`. ## `memofs agent start` [#memofs-agent-start] Starts a new AgentFS-style session workspace, initializing context snapshots and working scratch files. ```bash memofs agent start --task "Implement OAuth2 login flow" memofs agent start --task "Refactor query router" --session oauth-flow-v1 ``` ### Options [#options] | Flag | Description | Default | | ---------------- | ------------------------------- | ----------------------------- | | `--task ` | Agent task or brief (required) | — | | `--project ` | Explicit project ID | Resolved workspace project ID | | `--actor ` | Actor ID performing the task | — | | `--session ` | Explicit safe session ID string | Auto-generated UUID | ### Output [#output] Prints the session ID and formatted instructions directing the agent to read context files, update working files during progress, and write output files before finishing. ## `memofs agent paths` [#memofs-agent-paths] Prints the file paths for the latest or a selected agent session. ```bash memofs agent paths memofs agent paths --session oauth-flow-v1 ``` ### Options [#options-1] | Flag | Description | Default | | ---------------- | ---------------------- | -------- | | `--session ` | Session ID or `latest` | `latest` | ## `memofs agent extract` [#memofs-agent-extract] Extracts output sections (`summary.md`, `durable-memory.md`, `follow-ups.md`) from an agent session workspace. ```bash memofs agent extract memofs agent extract --session oauth-flow-v1 --json ``` ### Options [#options-2] | Flag | Description | Default | | ---------------- | ---------------------- | -------- | | `--session ` | Session ID or `latest` | `latest` | ## `memofs agent complete` [#memofs-agent-complete] Finalizes an agent session, optionally appending extracted durable memory into canonical `memory/notes.md` and creating a tagged repository checkpoint snapshot. ```bash memofs agent complete --extract --checkpoint-label "oauth-done" memofs agent complete --session oauth-flow-v1 --extract ``` ### Options [#options-3] | Flag | Description | Default | | ---------------------------- | -------------------------------------------------------- | -------- | | `--session ` | Session ID or `latest` | `latest` | | `--extract` | Append `output/durable-memory.md` into MemoFS `notes.md` | `false` | | `--checkpoint-label