@domusnext/ai-memory
v1.0.2
Published
TypeScript SDK and trusted HTTP server for Nori family memory.
Readme
nori-memory
TypeScript SDK and trusted Hono HTTP server for Nori memory.
Scope
- Tenant isolation uses
orgId. - Input is asynchronous:
inputMemory()only createsmemory_inputsand a queuedmemory_runsrecord. - A worker calls
processMemoryRun()to extract memory and write resources/items/categories. Category summaries are marked dirty and refreshed byprocessCategoryRefreshJob(). - Recall returns only shared memory plus the requester member's private memory.
- Production storage is PostgreSQL with pgvector.
- HTTP server does not include authentication. It is intended for trusted backend-to-backend calls.
SDK
import {
OpenAICompatibleEmbeddingClient,
OpenAICompatibleLlmClient,
PostgresMemoryRepository,
createCloudWatchStdoutTelemetry,
createNoriMemory
} from "nori-memory";
const memory = createNoriMemory({
repository: new PostgresMemoryRepository({
connectionString: postgresConnectionString
}),
llmClient: new OpenAICompatibleLlmClient({
baseUrl: "https://openrouter.ai/api/v1",
apiKey: extractionApiKey,
model: "openai/gpt-4.1-mini"
}),
embeddingClient: new OpenAICompatibleEmbeddingClient(
{
baseUrl: "https://openrouter.ai/api/v1",
apiKey: embeddingApiKey,
model: "openai/text-embedding-3-small"
},
1536
),
telemetry: createCloudWatchStdoutTelemetry({
environment: "prod",
service: "nori_memory"
})
});
const input = await memory.inputMemory({
orgId: "org_1",
actorMemberId: "mom",
idempotencyKey: "conversation_1:turn_10",
occurredAt: new Date().toISOString(),
messages: [{ role: "user", content: "不要在晚上9点以后安排日程" }],
memberContext: {
actorMemberId: "mom",
members: [{ memberId: "mom", nickname: "mary", roleName: "mom" }]
}
});
await memory.processMemoryRun({ runId: input.runId });
await memory.processCategoryRefreshJob();If telemetry is omitted, NoriMemory emits CloudWatch Embedded Metric Format JSON to stdout with environment="unknown" and service="nori_memory".
NoriMemory depends on LlmClient and EmbeddingClient only. Owning services can inject OpenAI-compatible adapters, AI SDK adapters, or their own implementations. The standalone server builds AI SDK clients from llm.memory_infer, llm.memory_embedding, and secret config.
createNoriMemory() does not require config when callers inject llmClient and embeddingClient. config now contains runtime strategy only, such as recall and category refresh defaults.
Worker
import { runNoriMemoryWorker } from "nori-memory/worker";
await runNoriMemoryWorker({
memory,
pollIntervalMs: 2000,
reapIntervalMs: 60000,
categoryRefreshBatchSize: 1,
batchSize: 1,
signal
});HTTP
import { createNoriMemoryServer } from "nori-memory/http";
const app = createNoriMemoryServer({ memory });Routes:
POST /v1/memory/inputsGET /v1/memory/runs/:run_idPOST /v1/memory/recallPOST /v1/memory/itemsPATCH /v1/memory/items/:item_idDELETE /v1/memory/items/:item_idGET /v1/memory/itemsGET /v1/memory/categoriesGET /healthz
The SDK core never reads environment variables. Load secrets in the owning service and pass repository/client implementations into createNoriMemory().
