@bcmyguest/openmem 0.0.0-stage → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/openmem/SKILL.md +34 -0
- package/LICENSE +190 -0
- package/README.md +140 -2
- package/bin/hindsight-project-index +530 -0
- package/cli/coding-agent/access-policy.mjs +38 -0
- package/cli/coding-agent/agents.mjs +34 -0
- package/cli/coding-agent/bank-from-cwd.mjs +140 -0
- package/cli/coding-agent/capabilities.mjs +34 -0
- package/cli/coding-agent/context-store.mjs +81 -0
- package/cli/coding-agent/context-trim.mjs +897 -0
- package/cli/coding-agent/file-io.mjs +72 -0
- package/cli/coding-agent/hook-harnesses.mjs +88 -0
- package/cli/coding-agent/hook-runner.mjs +284 -0
- package/cli/coding-agent/install-access.mjs +119 -0
- package/cli/coding-agent/install-context-proxy.mjs +333 -0
- package/cli/coding-agent/install-rtk.mjs +60 -0
- package/cli/coding-agent/install-shim.mjs +201 -0
- package/cli/coding-agent/opencode-config.mjs +107 -0
- package/cli/coding-agent/opencode-plugin.mjs +132 -0
- package/cli/coding-agent/opencode2-plugin/index.js +299 -0
- package/cli/coding-agent/recall-frame.mjs +29 -0
- package/cli/coding-agent/remove-upstream-access.mjs +122 -0
- package/cli/coding-agent/runtime.mjs +40 -0
- package/cli/coding-agent/session-db.mjs +626 -0
- package/cli/coding-agent/session-facade.mjs +86 -0
- package/cli/coding-agent/toml-edit.mjs +161 -0
- package/cli/cognee-mcp.mjs +260 -0
- package/cli/context-management.mjs +254 -0
- package/cli/feed-sync.mjs +27 -0
- package/cli/install-coding-agent.mjs +298 -0
- package/cli/install-memory-mcp.mjs +426 -0
- package/cli/is-main.mjs +18 -0
- package/cli/mcp/context-sql-runner.mjs +58 -0
- package/cli/mcp/context-store.mjs +670 -0
- package/cli/mcp/context.mjs +61 -0
- package/cli/mcp/export/cognee-dataset-name.mjs +12 -0
- package/cli/mcp/export/cognee.mjs +119 -0
- package/cli/mcp/export/hindsight.mjs +48 -0
- package/cli/mcp/export/index.mjs +26 -0
- package/cli/mcp/export/mem0.mjs +31 -0
- package/cli/mcp/knowledge.mjs +333 -0
- package/cli/mcp/llm-synthesize.mjs +50 -0
- package/cli/mcp/mem0-scope-id.mjs +22 -0
- package/cli/mcp/memory-facade.mjs +521 -0
- package/cli/mcp/memory-reflect-consolidate.mjs +120 -0
- package/cli/mcp/notebooklm-banks.mjs +21 -0
- package/cli/mcp/notebooklm-hindsight-rest.mjs +45 -0
- package/cli/mcp/notebooklm-provider.mjs +225 -0
- package/cli/mcp/pmm-records.mjs +23 -0
- package/cli/mcp/portability.mjs +158 -0
- package/cli/mcp/stdio.mjs +65 -0
- package/cli/mcp/unified-mcp-install.mjs +65 -0
- package/cli/mem0-mcp.mjs +108 -0
- package/cli/notebooklm-mcp.mjs +236 -0
- package/cli/openmem-mcp.mjs +38 -0
- package/cli/openmem.mjs +222 -0
- package/cli/roots.mjs +85 -0
- package/cli/schedule.mjs +176 -0
- package/cli/stack.mjs +438 -0
- package/cli/switch-memory-provider.mjs +358 -0
- package/cli/wiring-report.mjs +125 -0
- package/compose.bench.yaml +12 -0
- package/compose.yaml +227 -0
- package/config/coding-agent.json +13 -0
- package/config/hindsight.env.example +26 -0
- package/config/index.yml +54 -0
- package/config/litellm.lemond.yaml +40 -0
- package/config/litellm.ollama.yaml +33 -0
- package/config/notebooklm.yml +33 -0
- package/config/openmem.toml.example +124 -0
- package/docs/OPENMEM.md +23 -0
- package/docs/architecture.md +245 -0
- package/docs/assets/README.md +10 -0
- package/docs/assets/setup-demo.gif +0 -0
- package/docs/coding-agent-hooks.md +75 -0
- package/docs/coding-agent-scopes.md +22 -0
- package/docs/coding-agents.md +71 -0
- package/docs/cognee.md +37 -0
- package/docs/compatibility.md +80 -0
- package/docs/concepts.md +135 -0
- package/docs/context-management.md +255 -0
- package/docs/context-proxy.md +115 -0
- package/docs/context-research.md +215 -0
- package/docs/context-store.md +277 -0
- package/docs/hindsight.md +77 -0
- package/docs/index-sources-roadmap.md +38 -0
- package/docs/index-sources.md +39 -0
- package/docs/indexer-sinks.md +122 -0
- package/docs/indexing.md +57 -0
- package/docs/manual-stack-setup.md +74 -0
- package/docs/mcp-install-guide.md +4 -0
- package/docs/mcp-setup.md +104 -0
- package/docs/mem0.md +141 -0
- package/docs/memory-portability.md +73 -0
- package/docs/memory-providers.md +246 -0
- package/docs/meridian-litellm.md +198 -0
- package/docs/model-configuration.md +106 -0
- package/docs/notebooklm.md +83 -0
- package/docs/npx-install.md +172 -0
- package/docs/openmem-config.md +194 -0
- package/docs/provider-wizard-hooks.md +222 -0
- package/docs/quickstart.md +107 -0
- package/docs/setup-wizard.md +117 -0
- package/docs/sources-feeds.md +39 -0
- package/docs/sources-readwise.md +23 -0
- package/docs/sources-zotero.md +22 -0
- package/glama.json +4 -0
- package/indexer/Dockerfile +38 -0
- package/indexer/code_outline.py +146 -0
- package/indexer/feed_sync.py +107 -0
- package/indexer/index_config.py +290 -0
- package/indexer/pytest.ini +5 -0
- package/indexer/sinks/__init__.py +148 -0
- package/indexer/sinks/_http.py +44 -0
- package/indexer/sinks/cognee.py +329 -0
- package/indexer/sinks/hindsight.py +107 -0
- package/indexer/sinks/mem0.py +247 -0
- package/indexer/watch.py +240 -0
- package/package.json +96 -4
- package/providers/_template/compose.yaml +52 -0
- package/providers/cognee/OPERATOR.md +82 -0
- package/providers/cognee/compose.yaml +89 -0
- package/providers/cognee/lib/clack.mjs +157 -0
- package/providers/cognee/lib/coding-agent.mjs +26 -0
- package/providers/cognee/lib/cognee-mcp-install.mjs +153 -0
- package/providers/cognee/lib/config.mjs +98 -0
- package/providers/cognee/lib/env-file.mjs +194 -0
- package/providers/cognee/lib/env-setup.mjs +83 -0
- package/providers/cognee/lib/llm-env.mjs +382 -0
- package/providers/cognee/lib/ports.mjs +25 -0
- package/providers/cognee/lib/smoke.mjs +246 -0
- package/providers/cognee/lib/stack-env.mjs +134 -0
- package/providers/cognee/lib/state.mjs +101 -0
- package/providers/cognee/lib/summary.mjs +56 -0
- package/providers/cognee/lib/validate.mjs +97 -0
- package/providers/cognee/manifest.json +56 -0
- package/providers/cognee/wizard.mjs +134 -0
- package/providers/graphiti/manifest.json +15 -0
- package/providers/hindsight/lib/clack.mjs +347 -0
- package/providers/hindsight/lib/coding-agent.mjs +204 -0
- package/providers/hindsight/lib/config.mjs +79 -0
- package/providers/hindsight/lib/env-setup.mjs +72 -0
- package/providers/hindsight/lib/litellm-routes.mjs +196 -0
- package/providers/hindsight/lib/meridian.mjs +307 -0
- package/providers/hindsight/lib/model-backend.mjs +243 -0
- package/providers/hindsight/lib/notebooklm-mcp-install.mjs +127 -0
- package/providers/hindsight/lib/ollama-compose.mjs +51 -0
- package/providers/hindsight/lib/ports.mjs +30 -0
- package/providers/hindsight/lib/probe.mjs +54 -0
- package/providers/hindsight/lib/stack-env.mjs +125 -0
- package/providers/hindsight/lib/state.mjs +80 -0
- package/providers/hindsight/lib/summary.mjs +57 -0
- package/providers/hindsight/lib/validate.mjs +81 -0
- package/providers/hindsight/manifest.json +58 -0
- package/providers/hindsight/wizard.mjs +150 -0
- package/providers/letta/manifest.json +29 -0
- package/providers/mem0/OPERATOR.md +143 -0
- package/providers/mem0/compose.yaml +79 -0
- package/providers/mem0/lib/coding-agent.mjs +58 -0
- package/providers/mem0/lib/config.mjs +45 -0
- package/providers/mem0/lib/configure.mjs +201 -0
- package/providers/mem0/lib/dotenv.mjs +71 -0
- package/providers/mem0/lib/env-file.mjs +110 -0
- package/providers/mem0/lib/http.mjs +69 -0
- package/providers/mem0/lib/litellm.mjs +457 -0
- package/providers/mem0/lib/mcp-install.mjs +165 -0
- package/providers/mem0/lib/secret.mjs +30 -0
- package/providers/mem0/lib/smoke.mjs +179 -0
- package/providers/mem0/lib/stack-env.mjs +255 -0
- package/providers/mem0/lib/state.mjs +67 -0
- package/providers/mem0/lib/summary.mjs +88 -0
- package/providers/mem0/lib/url.mjs +106 -0
- package/providers/mem0/lib/validate.mjs +158 -0
- package/providers/mem0/manifest.json +47 -0
- package/providers/mem0/wizard.mjs +146 -0
- package/providers/zep/manifest.json +29 -0
- package/proxy/config.yaml +33 -0
- package/proxy/openmem_context/__init__.py +6 -0
- package/proxy/openmem_context/adapters.py +504 -0
- package/proxy/openmem_context/compress.py +53 -0
- package/proxy/openmem_context/core.py +606 -0
- package/proxy/openmem_context/embed.py +212 -0
- package/proxy/openmem_context/recall.py +49 -0
- package/proxy/openmem_context/session.py +70 -0
- package/proxy/openmem_context/sessiondb.py +276 -0
- package/proxy/openmem_context/settings.py +134 -0
- package/proxy/openmem_context/store.py +129 -0
- package/proxy/openmem_context/tokens.py +123 -0
- package/proxy/openmem_context/ttl.py +78 -0
- package/proxy/openmem_context_hook.py +34 -0
- package/scripts/check-pack.mjs +219 -0
- package/scripts/gen-masks.mjs +83 -0
- package/scripts/gen-masks.sh +4 -0
- package/scripts/promotion-provider-smoke.mjs +34 -0
- package/scripts/run-setup.sh +30 -0
- package/scripts/setup.mjs +107 -0
- package/scripts/setup.sh +5 -0
- package/scripts/spin-up.sh +45 -0
- package/scripts/wizard.sh +5 -0
- package/server.json +34 -0
- package/sync/Dockerfile +27 -0
- package/sync/memory_backend.py +87 -0
- package/sync/notebooklm_sync.py +664 -0
- package/wizard/bin/pm.mjs +97 -0
- package/wizard/bin/setup.mjs +33 -0
- package/wizard/lib/compose-version.mjs +32 -0
- package/wizard/lib/compose.mjs +70 -0
- package/wizard/lib/context-step.mjs +140 -0
- package/wizard/lib/curl.mjs +103 -0
- package/wizard/lib/docker-build.mjs +148 -0
- package/wizard/lib/exec.mjs +41 -0
- package/wizard/lib/indexer.mjs +6 -0
- package/wizard/lib/litellm-env.mjs +55 -0
- package/wizard/lib/load-machine-env.mjs +4 -0
- package/wizard/lib/log.mjs +32 -0
- package/wizard/lib/notebooklm-agent-access.mjs +92 -0
- package/wizard/lib/notebooklm.mjs +214 -0
- package/wizard/lib/parse-args.mjs +87 -0
- package/wizard/lib/paths.mjs +39 -0
- package/wizard/lib/pm-config.mjs +371 -0
- package/wizard/lib/ports.mjs +94 -0
- package/wizard/lib/prompts.mjs +85 -0
- package/wizard/lib/provider-wizard/helpers.mjs +98 -0
- package/wizard/lib/provider-wizard/run-steps.mjs +129 -0
- package/wizard/lib/providers/registry.mjs +262 -0
- package/wizard/lib/run-clack.mjs +108 -0
- package/wizard/lib/run-wizard.mjs +750 -0
- package/wizard/lib/validate-setup.mjs +62 -0
- package/wizard/lib/wizard-action.mjs +34 -0
- package/wizard/lib/wizard-conf.mjs +71 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hindsight sub-wizard (hook API v2). Owns everything Hindsight-specific that the meta
|
|
3
|
+
* wizard used to do inline: the lemond / Ollama / custom model flow and LiteLLM routes,
|
|
4
|
+
* hindsight.env and litellm.env, the HINDSIGHT_PORT / HINDSIGHT_CP_PORT pair, Hindsight
|
|
5
|
+
* validation, and the summary lines. See lib/ for the implementations and
|
|
6
|
+
* docs/provider-wizard-hooks.md for the hook contract.
|
|
7
|
+
*
|
|
8
|
+
* This module must not import wizard/lib/run-wizard.mjs; it receives `helpers`.
|
|
9
|
+
*/
|
|
10
|
+
import { applyConfigEnv, configToml as buildConfigToml } from "./lib/config.mjs";
|
|
11
|
+
import { setupCodingAgent as linkCodingAgent } from "./lib/coding-agent.mjs";
|
|
12
|
+
import { clackSetup as askInClack } from "./lib/clack.mjs";
|
|
13
|
+
import { setupEnv as setupHindsightEnv, stackEnv as hindsightStackEnv } from "./lib/env-setup.mjs";
|
|
14
|
+
import { chooseModelBackend } from "./lib/model-backend.mjs";
|
|
15
|
+
import { ensureComposeOllamaModels } from "./lib/ollama-compose.mjs";
|
|
16
|
+
import { resolvePorts as resolveHindsightPorts } from "./lib/ports.mjs";
|
|
17
|
+
import { backendDefault, confGet, ensureState } from "./lib/state.mjs";
|
|
18
|
+
import { summary as hindsightSummary } from "./lib/summary.mjs";
|
|
19
|
+
import { validateHindsight } from "./lib/validate.mjs";
|
|
20
|
+
|
|
21
|
+
// Called by scripts/setup.mjs (the stack .env writer), not by the wizard.
|
|
22
|
+
export { migrateEnv, prepareStackEnv, setupNotices } from "./lib/stack-env.mjs";
|
|
23
|
+
|
|
24
|
+
/** @typedef {import('../../wizard/lib/provider-wizard/helpers.mjs').ProviderWizardHelpers} Helpers */
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Quiet: fill Hindsight's context fields, map [stack]/[model] TOML defaults into the
|
|
28
|
+
* environment (including LEMOND_BASE from [model].lemond.host).
|
|
29
|
+
* @param {Record<string, any>} ctx
|
|
30
|
+
* @param {Helpers} h
|
|
31
|
+
*/
|
|
32
|
+
export async function init(ctx, h) {
|
|
33
|
+
ensureState(ctx);
|
|
34
|
+
applyConfigEnv(ctx.pmMerged || {});
|
|
35
|
+
if (process.env.LEMOND_BASE) ctx.lemondBase = process.env.LEMOND_BASE;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @param {Record<string, any>} ctx
|
|
40
|
+
* @param {Helpers} h
|
|
41
|
+
*/
|
|
42
|
+
export async function afterProvider(ctx, h) {
|
|
43
|
+
h.info("Hindsight uses LiteLLM aliases (memory-retain / reflect / consolidate).");
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Step "3. Model backend": lemond, Ollama, a custom OpenAI-compatible URL or a Claude
|
|
48
|
+
* subscription through Meridian, behind the LiteLLM proxy.
|
|
49
|
+
* @param {Record<string, any>} ctx
|
|
50
|
+
* @param {Helpers} h
|
|
51
|
+
*/
|
|
52
|
+
export async function configureModelRouting(ctx, h) {
|
|
53
|
+
await chooseModelBackend(ctx, h);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Hindsight's API and control-plane ports. */
|
|
57
|
+
export const resolvePorts = resolveHindsightPorts;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Quiet: description and environment for the stack setup script (scripts/setup.mjs).
|
|
61
|
+
* @param {Record<string, any>} ctx
|
|
62
|
+
*/
|
|
63
|
+
export function stackEnv(ctx) {
|
|
64
|
+
return hindsightStackEnv(ctx);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** hindsight.env, litellm.env wiring. */
|
|
68
|
+
export const setupEnv = setupHindsightEnv;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Quiet: reload the model choice from wizard.conf for `--up`.
|
|
72
|
+
* @param {Record<string, any>} ctx
|
|
73
|
+
* @param {Helpers} h
|
|
74
|
+
*/
|
|
75
|
+
export async function hydrate(ctx, h) {
|
|
76
|
+
ensureState(ctx);
|
|
77
|
+
ctx.backend = confGet(ctx, h, "MEMORY_BACKEND") || backendDefault(ctx, h);
|
|
78
|
+
ctx.model = confGet(ctx, h, "MEMORY_MODEL") || ctx.lemondDefaultModel;
|
|
79
|
+
ctx.apiBase = confGet(ctx, h, "MEMORY_API_BASE") || "";
|
|
80
|
+
ctx.reflectModel = confGet(ctx, h, "MEMORY_REFLECT_MODEL") || "";
|
|
81
|
+
ctx.meridianBase = confGet(ctx, h, "MEMORY_MERIDIAN_URL") || "";
|
|
82
|
+
ctx.ollamaInCompose = confGet(ctx, h, "MEMORY_OLLAMA_IN_COMPOSE") === "1";
|
|
83
|
+
applyComposeProfiles(ctx);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Ensure compose profile `ollama` is on the up command when MEMORY_OLLAMA_IN_COMPOSE=1.
|
|
88
|
+
* @param {Record<string, any>} ctx
|
|
89
|
+
* @param {Helpers} _h
|
|
90
|
+
*/
|
|
91
|
+
export async function beforeStack(ctx, _h) {
|
|
92
|
+
ensureState(ctx);
|
|
93
|
+
applyComposeProfiles(ctx);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Pull models into compose Ollama after the stack is up (host has no ollama CLI).
|
|
98
|
+
* @param {Record<string, any>} ctx
|
|
99
|
+
* @param {Helpers} h
|
|
100
|
+
*/
|
|
101
|
+
export async function afterStackHealthy(ctx, h) {
|
|
102
|
+
await ensureComposeOllamaModels(ctx, h);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** @param {Record<string, any>} ctx */
|
|
106
|
+
function applyComposeProfiles(ctx) {
|
|
107
|
+
const extra = [...(ctx.extraComposeProfiles || [])];
|
|
108
|
+
if (ctx.ollamaInCompose && !extra.includes("ollama")) extra.push("ollama");
|
|
109
|
+
ctx.extraComposeProfiles = extra;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Quiet: tables merged into config.toml.
|
|
114
|
+
* @param {Record<string, any>} ctx
|
|
115
|
+
*/
|
|
116
|
+
export function configToml(ctx) {
|
|
117
|
+
ensureState(ctx);
|
|
118
|
+
return buildConfigToml(ctx);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Quiet: lines for the closing summary.
|
|
123
|
+
* @param {Record<string, any>} ctx
|
|
124
|
+
*/
|
|
125
|
+
export function summary(ctx) {
|
|
126
|
+
return hindsightSummary(ctx);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Appends to ctx.validationErrors / ctx.validationChecks after the shared checks.
|
|
131
|
+
* @param {Record<string, any>} ctx
|
|
132
|
+
* @param {Helpers} h
|
|
133
|
+
*/
|
|
134
|
+
export async function extendValidation(ctx, h) {
|
|
135
|
+
validateHindsight(ctx, h);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** Link ~/.hindsight/coding-agent.json and check optInPaths. */
|
|
139
|
+
export const setupCodingAgent = linkCodingAgent;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Clack-only: ask the model questions, return the environment that makes the wizard
|
|
143
|
+
* skip its own (see WIZARD_SKIP_BACKEND_STEP).
|
|
144
|
+
* @param {Record<string, any>} ctx
|
|
145
|
+
* @param {typeof import("@clack/prompts")} ui
|
|
146
|
+
* @param {Helpers} h
|
|
147
|
+
*/
|
|
148
|
+
export async function clackSetup(ctx, ui, h) {
|
|
149
|
+
return askInClack(ctx, ui, h);
|
|
150
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "letta",
|
|
3
|
+
"label": "Letta",
|
|
4
|
+
"status": "planned",
|
|
5
|
+
"notes": "Placeholder manifest. Letta (formerly MemGPT) server integration is not wired; track via issues before changing status.",
|
|
6
|
+
"settings": {
|
|
7
|
+
"nativeDocs": "https://docs.letta.com/",
|
|
8
|
+
"nativeConfigPaths": [],
|
|
9
|
+
"wizardOwns": []
|
|
10
|
+
},
|
|
11
|
+
"compose": {
|
|
12
|
+
"profile": "letta",
|
|
13
|
+
"files": [],
|
|
14
|
+
"services": [],
|
|
15
|
+
"healthService": null,
|
|
16
|
+
"healthPath": null,
|
|
17
|
+
"hostPortEnv": null,
|
|
18
|
+
"defaultHostPort": null
|
|
19
|
+
},
|
|
20
|
+
"indexer": {
|
|
21
|
+
"apiUrlEnv": "LETTA_API_URL",
|
|
22
|
+
"sink": "letta"
|
|
23
|
+
},
|
|
24
|
+
"codingAgent": {
|
|
25
|
+
"pluginPackage": null,
|
|
26
|
+
"configTemplate": null
|
|
27
|
+
},
|
|
28
|
+
"wizard": {}
|
|
29
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# mem0 operator runbook (URL-only)
|
|
2
|
+
|
|
3
|
+
This stack does **not** run a mem0 container. You run a [self-hosted mem0 REST
|
|
4
|
+
server](https://docs.mem0.ai/open-source/features/rest-api); `./setup` only points
|
|
5
|
+
the shared indexer at it.
|
|
6
|
+
|
|
7
|
+
**Not** the hosted platform at `https://api.mem0.ai`. That API shape differs
|
|
8
|
+
(`/v1/…`); the indexer sink and wizard smoke talk to the open-source REST
|
|
9
|
+
server only (no `/v1/` prefix).
|
|
10
|
+
|
|
11
|
+
## What `./setup` owns vs what you own
|
|
12
|
+
|
|
13
|
+
| You (provider-native) | This stack |
|
|
14
|
+
| --- | --- |
|
|
15
|
+
| Start the mem0 REST server (JWT, Postgres/pgvector, dashboard) | Write `MEM0_API_URL` / `MEM0_INDEXER_URL` into the stack `.env` |
|
|
16
|
+
| Embedder / LLM keys for mem0 itself | Indexer sink (`MEMORY_SINK=mem0`) and host-gateway rewrite |
|
|
17
|
+
| Create an API key (dashboard or `POST /api-keys`) | Store `MEM0_API_KEY` in `~/.config/personal-memory/mem0.env` (mode **600**) |
|
|
18
|
+
| Optional `AUTH_DISABLED=true` (dev only) | Smoke: `GET /docs`, retain, search, delete-by-id |
|
|
19
|
+
| Apply the printed `llm` / `embedder` blocks to mem0 (optional) | Optional stack LiteLLM for mem0's LLM: routes, `litellm.env`, profile `litellm` on `127.0.0.1` |
|
|
20
|
+
|
|
21
|
+
## URLs
|
|
22
|
+
|
|
23
|
+
- **`MEM0_API_URL`** — host view (what you curl from this machine), e.g.
|
|
24
|
+
`http://127.0.0.1:18888`. Default port in the manifest is **18888**.
|
|
25
|
+
- **`MEM0_INDEXER_URL`** — container view. `./setup` derives it from
|
|
26
|
+
`MEM0_API_URL` by rewriting loopback hosts (`127.0.0.1`, `localhost`,
|
|
27
|
+
`0.0.0.0`, `[::1]`) to `host.docker.internal`. Do not hand-edit it to
|
|
28
|
+
`127.0.0.1` inside the container; validation requires it to match that rewrite.
|
|
29
|
+
|
|
30
|
+
## Linux loopback
|
|
31
|
+
|
|
32
|
+
`host.docker.internal` is the docker bridge gateway, **not** the host's
|
|
33
|
+
`127.0.0.1`. A mem0 process bound only to `127.0.0.1` is unreachable from the
|
|
34
|
+
indexer container. Bind the server to `0.0.0.0` (or the bridge IP), or put a
|
|
35
|
+
real hostname in `MEM0_API_URL`. An `https://localhost` URL becomes
|
|
36
|
+
`https://host.docker.internal`, which usually fails TLS name checks — use a
|
|
37
|
+
hostname the certificate covers.
|
|
38
|
+
|
|
39
|
+
## API key file
|
|
40
|
+
|
|
41
|
+
```text
|
|
42
|
+
~/.config/personal-memory/mem0.env # mode 600; directory mode 700
|
|
43
|
+
MEM0_API_KEY=<key>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Never put `MEM0_API_KEY` in the stack `.env` (mode 644), `wizard.conf`, or
|
|
47
|
+
`config.toml`. Override the path with `MEM0_ENV_FILE` / `[memory.mem0] env_file`
|
|
48
|
+
if needed; then `./setup` must record that path in the stack `.env`.
|
|
49
|
+
|
|
50
|
+
With **`AUTH_DISABLED=true`** on the server (development only), no key is
|
|
51
|
+
required. Auth-enabled servers need a key or smoke/indexer calls return 401.
|
|
52
|
+
|
|
53
|
+
## Embedder
|
|
54
|
+
|
|
55
|
+
Search fails if the server's embedder is misconfigured. Smoke looks for the
|
|
56
|
+
fact stored with `infer: false`; a miss points at the embedder key and server
|
|
57
|
+
logs, not at this stack.
|
|
58
|
+
|
|
59
|
+
## Cleartext keys
|
|
60
|
+
|
|
61
|
+
Over plain `http://` to a non-loopback host, `X-API-Key` travels in cleartext.
|
|
62
|
+
Prefer `https://`, or keep the server on loopback / the same host.
|
|
63
|
+
|
|
64
|
+
## Coding agents
|
|
65
|
+
|
|
66
|
+
There is no `pluginPackage`. Agents talk to your server via the Python SDK,
|
|
67
|
+
the self-hosted MCP bridge, or direct REST (`POST /memories`, `POST /search`). The
|
|
68
|
+
wizard's coding-agent step prints those paths and can register Cursor MCP; see
|
|
69
|
+
`providers/mem0/lib/coding-agent.mjs`.
|
|
70
|
+
|
|
71
|
+
### Cursor MCP (`~/.cursor/mcp.json`)
|
|
72
|
+
|
|
73
|
+
Mem0's official MCP (`https://mcp.mem0.ai`) is **platform/cloud only**. For a
|
|
74
|
+
self-hosted REST server this repo registers [`@yeyuan98/mem0-mcp`](https://www.npmjs.com/package/@yeyuan98/mem0-mcp)
|
|
75
|
+
via the launcher `cli/mem0-mcp.mjs` (loads the key from the env file, then
|
|
76
|
+
`npx -y @yeyuan98/mem0-mcp`).
|
|
77
|
+
|
|
78
|
+
```sh
|
|
79
|
+
MEMORY_PROVIDER=mem0 npx openmem install-mcp --yes
|
|
80
|
+
# checkout: MEMORY_PROVIDER=mem0 node cli/openmem.mjs install-mcp --yes
|
|
81
|
+
# or accept the coding-agent MCP confirm in setup
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Shape written (URL and env-file **path** only — never the key value):
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"mcpServers": {
|
|
89
|
+
"mem0": {
|
|
90
|
+
"command": "node",
|
|
91
|
+
"args": ["/path/to/openmem/cli/mem0-mcp.mjs"],
|
|
92
|
+
"env": {
|
|
93
|
+
"MEM0_API_URL": "http://127.0.0.1:18888",
|
|
94
|
+
"MEM0_BASE_URL": "http://127.0.0.1:18888",
|
|
95
|
+
"MEM0_ENV_FILE": "~/.config/personal-memory/mem0.env"
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**API key:** the launcher reads `MEM0_API_KEY` from `MEM0_ENV_FILE` when the
|
|
103
|
+
variable is not already in the process environment. You can also
|
|
104
|
+
`export MEM0_API_KEY=…` (e.g. `set -a; source ~/.config/personal-memory/mem0.env; set +a`)
|
|
105
|
+
before starting Cursor so the agent inherits it. **Never** put `MEM0_API_KEY` in
|
|
106
|
+
`mcp.json`. Existing `hindsight` / `codegraph` / `notebooklm` servers are left alone.
|
|
107
|
+
|
|
108
|
+
Restart Cursor Agent after install.
|
|
109
|
+
|
|
110
|
+
### Switch to / from mem0
|
|
111
|
+
|
|
112
|
+
```sh
|
|
113
|
+
npx openmem switch mem0 --yes
|
|
114
|
+
# later: npx openmem switch hindsight --yes
|
|
115
|
+
# checkout: node cli/openmem.mjs switch mem0 --yes
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Updates `wizard.conf` (and `config.toml` `[memory].provider` when present), restarts the stack
|
|
119
|
+
unless `--no-stack`, and runs `install-mcp --provider-only` unless `--no-mcp`. Does **not**
|
|
120
|
+
migrate memories. Flags: [README — Switch memory provider](../../README.md#switch-memory-provider).
|
|
121
|
+
|
|
122
|
+
## Models through the stack LiteLLM
|
|
123
|
+
|
|
124
|
+
Optional (wizard step 3, or `MEM0_LITELLM=1` under `--yes`): mem0's LLM, and
|
|
125
|
+
its embedder when the backend has one, go through the stack LiteLLM. Inputs
|
|
126
|
+
under `--yes`: `MEM0_LITELLM_BACKEND` (`ollama`, `custom`, `anthropic`,
|
|
127
|
+
`meridian`), `MEM0_LITELLM_MODEL`, `MEM0_LITELLM_API_BASE`,
|
|
128
|
+
`MEM0_LITELLM_EMBED_MODEL` (`none` keeps mem0's embedder),
|
|
129
|
+
`MEM0_LITELLM_PORT` (default 4000), `ANTHROPIC_API_KEY`. The wizard writes
|
|
130
|
+
`~/.config/personal-memory/mem0-litellm.yaml`, keeps keys in
|
|
131
|
+
`~/.config/hindsight/litellm.env` (mode 600), and prints the mem0 `llm` /
|
|
132
|
+
`embedder` blocks (provider `openai`, `openai_base_url`
|
|
133
|
+
`http://127.0.0.1:<port>/v1`, `api_key` = `LITELLM_MASTER_KEY`). You apply
|
|
134
|
+
them; the wizard never edits the mem0 server config. Key sources and limits:
|
|
135
|
+
[docs/mem0.md](../../docs/mem0.md#models-through-the-stack-litellm-optional).
|
|
136
|
+
|
|
137
|
+
## Compose
|
|
138
|
+
|
|
139
|
+
`providers/mem0/compose.yaml` defines no mem0 service — only env +
|
|
140
|
+
`extra_hosts` on the shared `indexer`. Profile `mem0` selects that fragment.
|
|
141
|
+
It also overlays the base `litellm` service: under profile `litellm` it
|
|
142
|
+
publishes `127.0.0.1:${MEM0_LITELLM_PORT:-4000}` (never `0.0.0.0`) and its
|
|
143
|
+
entrypoint exits unless `LITELLM_MASTER_KEY` starts with `sk-`.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# mem0 compose fragment (URL-only mode). Layered over compose.yaml; the wizard passes both, then `up -d`:
|
|
2
|
+
# docker compose -f compose.yaml -f providers/mem0/compose.yaml --profile mem0 up -d
|
|
3
|
+
# Add `-f compose.override.yaml` when you use the generated secret masks (Compose skips that file once -f is given).
|
|
4
|
+
#
|
|
5
|
+
# URL-only: this fragment defines NO service. The indexer talks to a mem0 REST server you already run (usually on
|
|
6
|
+
# the host, or on another machine); nothing here starts, builds or pulls a mem0 container. The reason is that the
|
|
7
|
+
# current self-hosted mem0 server (JWT/API-key auth, dashboard, Postgres + pgvector) has no current published image:
|
|
8
|
+
# `mem0/mem0-api-server:latest` on Docker Hub predates the auth. A mem0 service is a documented follow-up: build
|
|
9
|
+
# `server/` from a pinned mem0 git ref next to `pgvector/pgvector:pg17`, pinned and verified. Until then there is no
|
|
10
|
+
# `mem0` profile service, so `--profile mem0` only selects this fragment; it starts the provider-neutral indexer
|
|
11
|
+
# and its state-init step and nothing else.
|
|
12
|
+
#
|
|
13
|
+
# What the base compose.yaml gives you:
|
|
14
|
+
# - `indexer` and `indexer-state-init` have no profile and no provider dependency, so they start for every
|
|
15
|
+
# provider. This fragment points the indexer at the mem0 server.
|
|
16
|
+
# - `hindsight` carries the profile "hindsight" and never starts here.
|
|
17
|
+
# - `litellm` also carries its own profile "litellm". It starts only when the wizard's "route mem0's LLM through the
|
|
18
|
+
# stack LiteLLM" option is on, which writes COMPOSE_PROFILES=mem0,litellm. This fragment then publishes it on
|
|
19
|
+
# 127.0.0.1:${MEM0_LITELLM_PORT:-4000} (loopback only, never 0.0.0.0) for a mem0 server on the host, and the
|
|
20
|
+
# entrypoint below refuses to start without LITELLM_MASTER_KEY (sk-...) from LITELLM_ENV_FILE. See docs/mem0.md.
|
|
21
|
+
# Compose still interpolates every service before it filters by profile, so the stack .env needs LITELLM_CONFIG
|
|
22
|
+
# even when litellm does not run. scripts/setup.mjs (providers/mem0/lib/stack-env.mjs) writes the mem0 route file
|
|
23
|
+
# when the option is on and an inert value otherwise.
|
|
24
|
+
#
|
|
25
|
+
# Loopback caveat (Linux): host.docker.internal resolves to the docker bridge gateway, not to the host's 127.0.0.1.
|
|
26
|
+
# A mem0 server bound only to 127.0.0.1 is therefore NOT reachable from the indexer container. Bind it to 0.0.0.0
|
|
27
|
+
# or to the docker bridge IP, or give MEM0_API_URL a real hostname. An https://localhost URL is rewritten to
|
|
28
|
+
# https://host.docker.internal, which will not match the server certificate name (use a hostname the certificate
|
|
29
|
+
# covers). ./setup prints a note when MEM0_API_URL is a loopback address.
|
|
30
|
+
#
|
|
31
|
+
# Stack .env keys read here (written by ./setup):
|
|
32
|
+
# MEM0_INDEXER_URL the server as the indexer container sees it. The wizard derives it from MEM0_API_URL (the host
|
|
33
|
+
# view) by rewriting localhost, 127.0.0.1, 0.0.0.0 and [::1] to host.docker.internal.
|
|
34
|
+
# MEM0_ENV_FILE optional; default ~/.config/personal-memory/mem0.env. Holds ONLY MEM0_API_KEY=... for the
|
|
35
|
+
# indexer (mode 600, outside the repo). Not needed when the server runs with AUTH_DISABLED.
|
|
36
|
+
# mem0's own server secrets (JWT_SECRET, ADMIN_API_KEY, embedder keys) are the operator's concern
|
|
37
|
+
# and never go through this stack.
|
|
38
|
+
|
|
39
|
+
services:
|
|
40
|
+
indexer:
|
|
41
|
+
environment:
|
|
42
|
+
# Selects indexer/sinks/mem0.py and gives it the server URL (container view, not the host view).
|
|
43
|
+
MEMORY_SINK: mem0
|
|
44
|
+
MEMORY_API_URL: ${MEM0_INDEXER_URL:?run ./setup (mem0 API URL)}
|
|
45
|
+
# required: false lets `config` and `up` run before the key file exists (Compose 2.24+).
|
|
46
|
+
env_file:
|
|
47
|
+
- path: ${MEM0_ENV_FILE:-${HOME}/.config/personal-memory/mem0.env}
|
|
48
|
+
required: false
|
|
49
|
+
# Reach a server on the host through host.docker.internal.
|
|
50
|
+
extra_hosts:
|
|
51
|
+
- "host.docker.internal:host-gateway"
|
|
52
|
+
# No depends_on: the server is external, and the indexer's watcher retries until it answers.
|
|
53
|
+
|
|
54
|
+
notebooklm:
|
|
55
|
+
environment:
|
|
56
|
+
MEMORY_SINK: mem0
|
|
57
|
+
MEMORY_API_URL: ${MEM0_INDEXER_URL:?run ./setup (mem0 API URL)}
|
|
58
|
+
env_file:
|
|
59
|
+
- path: ${MEM0_ENV_FILE:-${HOME}/.config/personal-memory/mem0.env}
|
|
60
|
+
required: false
|
|
61
|
+
extra_hosts:
|
|
62
|
+
- "host.docker.internal:host-gateway"
|
|
63
|
+
|
|
64
|
+
# Only under the "litellm" profile (see the header). Loopback publish for a mem0 server running on this host.
|
|
65
|
+
litellm:
|
|
66
|
+
ports:
|
|
67
|
+
- "127.0.0.1:${MEM0_LITELLM_PORT:-4000}:4000"
|
|
68
|
+
# The port is reachable by every local user and process, so an unauthenticated proxy is not allowed: exit unless
|
|
69
|
+
# the env file supplies an sk- master key. The routes' general_settings.master_key then makes LiteLLM enforce it.
|
|
70
|
+
entrypoint:
|
|
71
|
+
- /bin/sh
|
|
72
|
+
- -c
|
|
73
|
+
- |
|
|
74
|
+
case "$${LITELLM_MASTER_KEY:-}" in
|
|
75
|
+
sk-?*) ;;
|
|
76
|
+
*) echo "litellm: LITELLM_MASTER_KEY=sk-... is missing from LITELLM_ENV_FILE; rerun ./setup" >&2; exit 1 ;;
|
|
77
|
+
esac
|
|
78
|
+
exec docker/prod_entrypoint.sh "$$@"
|
|
79
|
+
- litellm
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Step "9. Coding-agent plugin", mem0 half: there is no npx pluginPackage for the
|
|
3
|
+
* self-hosted REST server. Print concrete SDK / MCP / direct-REST paths, then
|
|
4
|
+
* optionally merge the mem0 MCP into ~/.cursor/mcp.json (--yes or confirm).
|
|
5
|
+
*/
|
|
6
|
+
import { installMem0Mcp } from "./mcp-install.mjs";
|
|
7
|
+
import { ensureState } from "./state.mjs";
|
|
8
|
+
import { displayUrl, resolveApiUrl, urlProblem } from "./url.mjs";
|
|
9
|
+
|
|
10
|
+
/** @typedef {import("../../../wizard/lib/provider-wizard/helpers.mjs").ProviderWizardHelpers} Helpers */
|
|
11
|
+
|
|
12
|
+
const SDK_DOCS = "https://docs.mem0.ai/open-source/python-quickstart";
|
|
13
|
+
const MCP_PACKAGE = "https://www.npmjs.com/package/@yeyuan98/mem0-mcp";
|
|
14
|
+
const REST_DOCS = "https://docs.mem0.ai/open-source/features/rest-api";
|
|
15
|
+
const OPERATOR = "providers/mem0/OPERATOR.md";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @param {Record<string, any>} ctx
|
|
19
|
+
* @param {Helpers} h
|
|
20
|
+
*/
|
|
21
|
+
export async function setupCodingAgent(ctx, h) {
|
|
22
|
+
ensureState(ctx);
|
|
23
|
+
const raw = resolveApiUrl(ctx, h);
|
|
24
|
+
const base = urlProblem(raw) ? "(set MEM0_API_URL)" : displayUrl(raw);
|
|
25
|
+
|
|
26
|
+
h.info("mem0 has no coding-agent pluginPackage; use the self-hosted server directly:");
|
|
27
|
+
h.info(` 1. SDK — pip install mem0ai, point Memory at ${base} (see ${SDK_DOCS})`);
|
|
28
|
+
h.info(
|
|
29
|
+
` 2. MCP — MEMORY_PROVIDER=mem0 npm run install-mcp -- --yes` +
|
|
30
|
+
` (npx @yeyuan98/mem0-mcp via cli/mem0-mcp.mjs; see ${MCP_PACKAGE} and ${OPERATOR})`,
|
|
31
|
+
);
|
|
32
|
+
h.info(
|
|
33
|
+
` 3. REST — POST ${base}/memories and POST ${base}/search with X-API-Key` +
|
|
34
|
+
` (see ${REST_DOCS}; stack wiring in ${OPERATOR})`,
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const codeRoot = ctx.packageRoot || ctx.repoRoot;
|
|
38
|
+
const stackRoot = ctx.repoRoot;
|
|
39
|
+
const wantMcp =
|
|
40
|
+
Boolean(ctx.yes) ||
|
|
41
|
+
(await h.confirm(ctx, "Register mem0 MCP in ~/.cursor/mcp.json now?", "y"));
|
|
42
|
+
if (wantMcp) {
|
|
43
|
+
await installMem0Mcp(
|
|
44
|
+
{
|
|
45
|
+
home: ctx.home,
|
|
46
|
+
repoRoot: codeRoot,
|
|
47
|
+
stackRoot,
|
|
48
|
+
dry: Boolean(ctx.dry),
|
|
49
|
+
env: process.env,
|
|
50
|
+
},
|
|
51
|
+
h,
|
|
52
|
+
);
|
|
53
|
+
} else {
|
|
54
|
+
h.info("skip MCP merge; later: MEMORY_PROVIDER=mem0 npm run install-mcp -- --yes");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
h.ok("coding-agent: documented SDK / MCP / REST paths (pluginPackage remains null)");
|
|
58
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mem0's slice of ~/.config/personal-memory/config.toml: the [memory.mem0] table
|
|
3
|
+
* (api_url, optional env_file). Never a key.
|
|
4
|
+
*/
|
|
5
|
+
import { ensureState } from "./state.mjs";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @param {Record<string, unknown>} cfg merged TOML config
|
|
9
|
+
* @returns {{ apiUrl: string, envFile: string }}
|
|
10
|
+
*/
|
|
11
|
+
export function defaultsFromConfig(cfg) {
|
|
12
|
+
const memory = /** @type {Record<string, unknown>} */ (cfg?.memory || {});
|
|
13
|
+
const mem0 = /** @type {Record<string, unknown>} */ (memory.mem0 || {});
|
|
14
|
+
return {
|
|
15
|
+
apiUrl: mem0.api_url != null ? String(mem0.api_url).trim() : "",
|
|
16
|
+
envFile: mem0.env_file != null ? String(mem0.env_file).trim() : "",
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Seed ctx.mem0 from [memory.mem0]. Env vars still win over these (see resolveApiUrl).
|
|
22
|
+
* @param {Record<string, any>} ctx
|
|
23
|
+
*/
|
|
24
|
+
export function applyConfig(ctx) {
|
|
25
|
+
const state = ensureState(ctx);
|
|
26
|
+
const d = defaultsFromConfig(ctx.pmMerged || {});
|
|
27
|
+
if (d.apiUrl && !state.apiUrl) state.apiUrl = d.apiUrl;
|
|
28
|
+
if (d.envFile && !state.tomlEnvFile) state.tomlEnvFile = d.envFile;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Tables merged into config.toml: `memory.mem0`, which the wizard merges into [memory] (it
|
|
33
|
+
* always sets `provider` itself).
|
|
34
|
+
* @param {Record<string, any>} ctx
|
|
35
|
+
* @param {string} url the resolved host-view server URL
|
|
36
|
+
* @returns {Record<string, Record<string, unknown>>}
|
|
37
|
+
*/
|
|
38
|
+
export function configToml(ctx, url) {
|
|
39
|
+
const state = ensureState(ctx);
|
|
40
|
+
/** @type {Record<string, unknown>} */
|
|
41
|
+
const mem0 = { api_url: url };
|
|
42
|
+
const envFile = (process.env.MEM0_ENV_FILE || state.tomlEnvFile || "").trim();
|
|
43
|
+
if (envFile) mem0.env_file = envFile;
|
|
44
|
+
return { memory: { mem0 } };
|
|
45
|
+
}
|