Package Exports
- @elephance/core
Readme
@elephance/core
Local LanceDB-backed vector memory, rule memory, and project schema retrieval for TypeScript apps.
@elephance/core provides a small SDK for storing durable user memory, structured reusable rules, indexing project schema chunks, and retrieving relevant context with semantic search. It is local-first by default and stores vectors in a writable LanceDB directory.
Install
npm install @elephance/core openaiopenai is only required when you use the default OpenAI-compatible embedding provider.
Requirements
- Node.js 18 or later.
- A writable local directory for LanceDB data.
OPENAI_API_KEYwhen using the default embedding provider.
Quick Start
import { configure, queryMemory, upsertMemory } from "@elephance/core";
configure({
dbPath: "./data/.lancedb",
});
await upsertMemory("The user prefers concise TypeScript examples.", {
userId: "user-123",
label: "user_preference",
});
const hits = await queryMemory("How should I answer this user?", {
topK: 3,
});
console.log(hits);Configuration
import { configure, configureEmbedding } from "@elephance/core";
configure({
dbPath: "./data/.lancedb",
memoryTable: "memory",
schemaTable: "project_schema",
ruleTable: "rule_memory",
});
configureEmbedding({
model: "text-embedding-3-small",
});configure() resets the cached LanceDB connection, so call it before your first query or write.
Environment Variables
| Variable | Description |
|---|---|
OPENAI_API_KEY |
Required for the default OpenAI-compatible embedding provider. |
OPENAI_EMBEDDING_MODEL |
Embedding model. Defaults to text-embedding-3-small. |
OPENAI_RELAY_BASE_URL |
OpenAI-compatible base URL, such as a relay or proxy. |
OPENAI_BASE_URL |
Legacy base URL fallback. |
MEMORY_OVERWRITE_LABELS |
Comma-separated labels that overwrite per user and label. Defaults to user_preference. |
Rule Memory API
Use rule memory for durable behavior constraints such as user corrections, project conventions, coding style, UI preferences, and agent behavior. Rules are stored in the separate rule_memory table by default.
import {
listRules,
queryRules,
recordRuleHit,
updateRuleStatus,
upsertRule,
} from "@elephance/core";
const rule = await upsertRule(
"Button border radius should not exceed 8px in this project.",
{
label: "ui_preference",
scope: "project",
projectId: "my-app",
action: "Keep button radius at or below 8px.",
confidence: 0.9,
source: "manual",
}
);
const activeRules = await queryRules("building a button component", {
projectId: "my-app",
topK: 3,
recordHit: true,
});
const allProjectRules = await listRules({
projectId: "my-app",
includeInactive: true,
});
await recordRuleHit(rule.id);
await updateRuleStatus(rule.id, "deprecated");Rule statuses are candidate, active, conflicted, deprecated, and archived. queryRules() returns active rules by default; pass includeInactive: true or an explicit status filter to inspect inactive rules.
Rule Observations and Promotion
For collective rule evolution, keep the default local-first behavior and record explicit evidence before promoting a rule:
import { proposeRulePromotion, recordRuleObservation } from "@elephance/core";
await recordRuleObservation(rule.id, {
outcome: "success",
task: "Implemented a matching button component.",
evidenceId: "task-2026-04-30-button",
client: "codex",
});
const proposal = await proposeRulePromotion(rule.id, {
minEvidence: 2,
minSuccesses: 2,
sharedRepository: "team-rules",
dryRun: true,
});proposeRulePromotion() never uploads or syncs data. When dryRun is false and the evidence gates pass, it only marks the local rule as promotionStatus: "proposed" and records metadata such as origin, privacyLevel, promotedFrom, and sharedRepository.
Memory API
Use memory for short, durable facts such as preferences, notes, summaries, and stable user context.
import { clearUserMemory, queryMemory, upsertMemory } from "@elephance/core";
await upsertMemory("The user prefers pnpm in this project.", {
userId: "user-123",
label: "user_preference",
source: "settings",
});
const memories = await queryMemory("package manager preference", {
topK: 3,
});
await clearUserMemory("user-123");Labels listed in MEMORY_OVERWRITE_LABELS overwrite by userId + label. By default, user_preference behaves like a stable slot per user, while labels such as note, summary, or fact can accumulate multiple rows.
Project Schema API
Use schema storage for database table docs, API contracts, domain models, or any project context that should be retrieved by semantic search.
import {
batchQueryProjectSchema,
deleteProjectSchemaBySource,
queryProjectSchema,
queryProjectSchemaByTableNames,
replaceProjectSchemaForSource,
} from "@elephance/core";
await replaceProjectSchemaForSource(
"tables/billing_invoice.md",
new Date().toISOString(),
[
"## Fields\n- id: primary key\n- customer_id: customer reference",
"## Relations\nInvoices join payments through invoice_id.",
]
);
const semanticHits = await queryProjectSchema("invoice payment join", {
minimal: true,
topK: 3,
});
const exactHits = await queryProjectSchemaByTableNames(
["billing_invoice", "billing_payment"],
{ minimal: true }
);
const mergedHits = await batchQueryProjectSchema(
["invoice", "payment", "customer"],
{ mergedTopK: 4 }
);
await deleteProjectSchemaBySource("tables/billing_invoice.md");Query Options
| Option | Description |
|---|---|
topK |
Maximum returned results. Defaults to 3. |
minimal |
Return compact schema text when true. Defaults to true for schema queries. |
maxTextChars |
Maximum text length per schema result in minimal mode. Defaults to 420. |
candidateLimit |
Vector search candidate limit before merging. Defaults to 8. |
maxChunksPerSource |
Maximum chunks merged for each source. Defaults to 1. |
mergedTopK |
Maximum merged results for batchQueryProjectSchema. Defaults to 4. |
Rule search also accepts rule filters such as label, scope, userId, projectId, repoPath, client, status, includeInactive, and recordHit.
Research Context
@elephance/core intentionally stays model-free. It implements the local storage, status, retrieval, and hit-feedback layer needed by rule memory, while extraction and judgment live in higher packages.
The shape follows recent agent-memory work: Memory for Autonomous LLM Agents frames memory as write/manage/read; AutoSkill and MemSkill motivate reusable, evolving artifacts; De Jure informs structured rule fields that can be judged, merged, deprecated, or archived; and SkillClaw motivates local evidence tracking before any team/shared promotion.
Custom Embedding Provider
You can replace the default OpenAI-compatible provider with your own embedding backend.
import { setEmbeddingProvider } from "@elephance/core";
setEmbeddingProvider({
async embed(text) {
return myEmbeddingClient.embed(text);
},
async embedBatch(texts) {
return myEmbeddingClient.embedBatch(texts);
},
});All rows in the same LanceDB table should use the same embedding model and vector dimension. Use a new dbPath or table name when changing models.
Connection Helpers
import {
connect,
getTableNames,
openTable,
resetConnection,
tableExists,
} from "@elephance/core";These helpers are exposed for diagnostics, tests, and advanced LanceDB workflows.
Safety Notes
- Do not store secrets, access tokens, passwords, private keys, or sensitive personal data.
- Keep memories short, specific, and independently understandable.
- Keep rules short, actionable, and scoped. Prefer
projectorreposcope for project conventions anduserscope for personal preferences. - Do not delete old rules directly when they become stale. Mark them
deprecatedorarchived. - Add
.lancedbto.gitignoreunless you intentionally want to commit local vector data. - Keep vectors in the same table on the same embedding model and dimensionality.
Related Package
Use @elephance/mcp to expose the same memory and schema tools to Cursor or another MCP-compatible client.