@bcmyguest/openmem 0.0.0-stage → 0.6.3
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/LICENSE +190 -0
- package/README.md +136 -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 +23 -0
- package/cli/coding-agent/hook-harnesses.mjs +87 -0
- package/cli/coding-agent/hook-runner.mjs +260 -0
- package/cli/coding-agent/install-access.mjs +93 -0
- package/cli/coding-agent/install-shim.mjs +97 -0
- package/cli/coding-agent/opencode-config.mjs +91 -0
- package/cli/coding-agent/opencode-plugin.mjs +96 -0
- package/cli/coding-agent/runtime.mjs +39 -0
- package/cli/coding-agent/session-facade.mjs +62 -0
- package/cli/cognee-mcp.mjs +260 -0
- package/cli/feed-sync.mjs +11 -0
- package/cli/install-coding-agent.mjs +165 -0
- package/cli/install-memory-mcp.mjs +426 -0
- package/cli/is-main.mjs +18 -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/llm-synthesize.mjs +50 -0
- package/cli/mcp/mem0-scope-id.mjs +22 -0
- package/cli/mcp/memory-facade.mjs +455 -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 +35 -0
- package/cli/openmem.mjs +205 -0
- package/cli/roots.mjs +85 -0
- package/cli/stack.mjs +436 -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 +164 -0
- package/config/coding-agent.json +13 -0
- package/config/hindsight.env.example +24 -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 +62 -0
- package/docs/OPENMEM.md +23 -0
- package/docs/architecture.md +219 -0
- package/docs/assets/README.md +10 -0
- package/docs/assets/setup-demo.gif +0 -0
- package/docs/coding-agent-hooks.md +51 -0
- package/docs/coding-agent-scopes.md +22 -0
- package/docs/coding-agents.md +51 -0
- package/docs/cognee.md +37 -0
- package/docs/concepts.md +112 -0
- package/docs/hindsight.md +74 -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 +101 -0
- package/docs/mem0.md +103 -0
- package/docs/memory-portability.md +73 -0
- package/docs/memory-providers.md +246 -0
- package/docs/model-configuration.md +84 -0
- package/docs/notebooklm.md +83 -0
- package/docs/npx-install.md +170 -0
- package/docs/openmem-config.md +194 -0
- package/docs/provider-wizard-hooks.md +222 -0
- package/docs/quickstart.md +101 -0
- package/docs/setup-wizard.md +116 -0
- package/docs/sources-feeds.md +52 -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 +95 -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 +245 -0
- package/providers/hindsight/lib/coding-agent.mjs +204 -0
- package/providers/hindsight/lib/config.mjs +73 -0
- package/providers/hindsight/lib/env-setup.mjs +71 -0
- package/providers/hindsight/lib/litellm-routes.mjs +187 -0
- package/providers/hindsight/lib/model-backend.mjs +214 -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 +33 -0
- package/providers/hindsight/lib/stack-env.mjs +132 -0
- package/providers/hindsight/lib/state.mjs +75 -0
- package/providers/hindsight/lib/summary.mjs +43 -0
- package/providers/hindsight/lib/validate.mjs +75 -0
- package/providers/hindsight/manifest.json +58 -0
- package/providers/hindsight/wizard.mjs +149 -0
- package/providers/letta/manifest.json +29 -0
- package/providers/mem0/OPERATOR.md +124 -0
- package/providers/mem0/compose.yaml +57 -0
- package/providers/mem0/lib/coding-agent.mjs +58 -0
- package/providers/mem0/lib/config.mjs +45 -0
- package/providers/mem0/lib/configure.mjs +135 -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/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 +216 -0
- package/providers/mem0/lib/state.mjs +67 -0
- package/providers/mem0/lib/summary.mjs +60 -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 +133 -0
- package/providers/zep/manifest.json +29 -0
- package/scripts/check-pack.mjs +218 -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 +94 -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/skills/openmem/SKILL.md +29 -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/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/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 +163 -0
- package/wizard/lib/ports.mjs +94 -0
- package/wizard/lib/prompts.mjs +57 -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 +755 -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,82 @@
|
|
|
1
|
+
# Cognee operator notes
|
|
2
|
+
|
|
3
|
+
Self-hosted graph/RAG memory via a pinned `cognee/cognee` image on a loopback
|
|
4
|
+
port (`COGNEE_PORT`, default **8766**). Auth is off in this stack. Cognify
|
|
5
|
+
defaults to **local GLiNER + FastEmbed** (no API key). Optional secrets
|
|
6
|
+
(`LLM_API_KEY` for OpenAI/Ollama paths, `COGNEE_API_KEY` if you enable auth)
|
|
7
|
+
live in env files under `~/.config/personal-memory/`, never in the stack
|
|
8
|
+
`.env`, `wizard.conf`, or `mcp.json`.
|
|
9
|
+
|
|
10
|
+
See also [docs/memory-providers.md](../../docs/memory-providers.md) and
|
|
11
|
+
[docs/openmem-config.md](../../docs/openmem-config.md).
|
|
12
|
+
|
|
13
|
+
## Cognify defaults (GLiNER + FastEmbed)
|
|
14
|
+
|
|
15
|
+
Fresh setup / `./setup --yes` with no LLM answers writes:
|
|
16
|
+
|
|
17
|
+
```env
|
|
18
|
+
GRAPH_EXTRACTOR=gliner_demo
|
|
19
|
+
EMBEDDING_PROVIDER=fastembed
|
|
20
|
+
EMBEDDING_MODEL=BAAI/bge-small-en-v1.5
|
|
21
|
+
EMBEDDING_DIMENSIONS=384
|
|
22
|
+
AUTO_FEEDBACK=false
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The pinned image already includes `gliner2` and `fastembed`. First cognify
|
|
26
|
+
downloads ~800 MB of models into `HF_HOME` / `FASTEMBED_CACHE_PATH` under the
|
|
27
|
+
`cognee-data` volume (`/cognee-storage/.cache/...`). Changing embedding
|
|
28
|
+
dimensions (for example from Ollama's 768 to FastEmbed's 384) requires
|
|
29
|
+
rebuilding vectors — prune datasets or recreate the `cognee-data` volume.
|
|
30
|
+
|
|
31
|
+
Overrides: `PM_COGNEE_LLM_PROVIDER=ollama` (Ollama LLM + embeddings), or
|
|
32
|
+
`PM_COGNEE_LLM_API_KEY` / Clack "OpenAI-compatible". `EMBEDDING_PROVIDER=fastembed`
|
|
33
|
+
is allowed with Ollama LLM.
|
|
34
|
+
|
|
35
|
+
## Coding agents (no plugin package)
|
|
36
|
+
|
|
37
|
+
Agents use the REST API (`/docs`, `/health`, `/api/v1/add`, `/cognify`, `/search`)
|
|
38
|
+
or the **read-only** stdio MCP shipped in this repo.
|
|
39
|
+
|
|
40
|
+
### Cursor MCP (`~/.cursor/mcp.json`)
|
|
41
|
+
|
|
42
|
+
When `MEMORY_PROVIDER=cognee`:
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
npx openmem install-mcp --yes --provider-only
|
|
46
|
+
# checkout: npx . install-mcp --yes --provider-only
|
|
47
|
+
# or during setup: coding-agent step registers the same entry
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
That merges a `cognee` server pointing at `cli/cognee-mcp.mjs` with
|
|
51
|
+
`env.COGNEE_API_URL` only (host URL; **never** `COGNEE_API_KEY`). Existing
|
|
52
|
+
`hindsight` / `codegraph` / `notebooklm` / `mem0` entries are left alone.
|
|
53
|
+
|
|
54
|
+
| Tool | Purpose |
|
|
55
|
+
| --- | --- |
|
|
56
|
+
| `cognee_health` | `GET /health` |
|
|
57
|
+
| `cognee_search` | `POST /api/v1/search` (`query`, optional `searchType`, `datasets`) |
|
|
58
|
+
|
|
59
|
+
Run by hand:
|
|
60
|
+
|
|
61
|
+
```sh
|
|
62
|
+
node cli/cognee-mcp.mjs
|
|
63
|
+
# or: openmem-cognee-mcp
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Base URL resolution inside the MCP: `COGNEE_API_URL` / `COGNEE_URL`, else
|
|
67
|
+
`http://127.0.0.1:${COGNEE_PORT|8766}`. If you enable auth in compose, export
|
|
68
|
+
`COGNEE_API_KEY` in the agent environment (not in `mcp.json`).
|
|
69
|
+
|
|
70
|
+
v1 MCP is read-only (no add/cognify). Ingest stays with the indexer or curl.
|
|
71
|
+
|
|
72
|
+
### Switch to / from Cognee
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
npx openmem switch cognee --yes
|
|
76
|
+
# later: npx openmem switch hindsight --yes
|
|
77
|
+
# checkout: npx . switch cognee --yes
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Updates `wizard.conf` (and `config.toml` `[memory].provider` when present), restarts the stack
|
|
81
|
+
unless `--no-stack`, and runs `install-mcp --provider-only` unless `--no-mcp`. Does **not**
|
|
82
|
+
migrate memories. Flags: [README — Switch memory provider](../../README.md#switch-memory-provider).
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Cognee provider fragment: one `cognee` service (single container, SQLite + LanceDB + Ladybug under /cognee-storage)
|
|
2
|
+
# and the wiring that points the shared indexer at it. Modeled on Cognee's official minimal compose file
|
|
3
|
+
# (docs/minimal-docker-compose.md in github.com/topoteretes/cognee), with a pinned image and a loopback-only port.
|
|
4
|
+
#
|
|
5
|
+
# Layering (the wizard passes both, then `up -d`):
|
|
6
|
+
# docker compose -f compose.yaml -f providers/cognee/compose.yaml --profile cognee up -d
|
|
7
|
+
# Add `-f compose.override.yaml` when you use the generated secret masks (Compose skips that file once -f is given).
|
|
8
|
+
#
|
|
9
|
+
# Notes:
|
|
10
|
+
# - The indexer maps each bank to a Cognee dataset (see indexer/sinks/cognee.py). Ingestion is asynchronous: the
|
|
11
|
+
# sink adds documents, then its flush() step runs cognify per dataset, so a document is stored first and becomes
|
|
12
|
+
# searchable only after cognify finishes. Cognify needs a working LLM key (below).
|
|
13
|
+
# - Cognify defaults to local GLiNER + FastEmbed (no API key) in cognee.env; optional LLM_* / Ollama overrides
|
|
14
|
+
# go there too (mode 600). HF_HOME / FASTEMBED_CACHE_PATH under /cognee-storage persist model downloads on the
|
|
15
|
+
# cognee-data volume. The indexer reads a SEPARATE env file (COGNEE_API_KEY only, never LLM_API_KEY). The
|
|
16
|
+
# directory holding cognee.env (~/.config/personal-memory) is masked from the indexer's $HOME mount by
|
|
17
|
+
# compose.override.yaml once the wizard has created it; until then the read-only $HOME mount can see it.
|
|
18
|
+
# - Authentication: ENABLE_BACKEND_ACCESS_CONTROL is pinned to "false" below and overrides the env file, so
|
|
19
|
+
# REQUIRE_AUTHENTICATION=true in cognee.env alone cannot turn auth on. To enable auth you must change that
|
|
20
|
+
# compose pin and set REQUIRE_AUTHENTICATION=true; the indexer then needs COGNEE_API_KEY in
|
|
21
|
+
# cognee-indexer.env (the sink sends it as X-Api-Key).
|
|
22
|
+
# - Both env files are optional (required: false, Compose 2.24+) so `config` and `up` work before they exist.
|
|
23
|
+
|
|
24
|
+
services:
|
|
25
|
+
cognee:
|
|
26
|
+
profiles: ["cognee"]
|
|
27
|
+
# Release 1.6.5, pinned by index digest (pushed 2026-10-16; `latest` pointed at the same digest then).
|
|
28
|
+
# Do not use the `main` tag from the minimal compose file. Bump deliberately.
|
|
29
|
+
image: cognee/cognee@sha256:29427e968f8b273db0bb7b037a7bb119d7695d960f73a59d649f00c5111a85bd
|
|
30
|
+
# Loopback only. Host port from .env (COGNEE_PORT); the container listens on 8000.
|
|
31
|
+
ports:
|
|
32
|
+
- "127.0.0.1:${COGNEE_PORT:-8766}:8000"
|
|
33
|
+
env_file:
|
|
34
|
+
- path: ${COGNEE_ENV_FILE:-${HOME}/.config/personal-memory/cognee.env}
|
|
35
|
+
required: false
|
|
36
|
+
environment:
|
|
37
|
+
# Documented single-user mode: no auth, one shared set of databases. Safe here because the only published port
|
|
38
|
+
# is bound to 127.0.0.1 and the indexer reaches the server on the compose network.
|
|
39
|
+
ENABLE_BACKEND_ACCESS_CONTROL: "false"
|
|
40
|
+
# Persist Hugging Face / FastEmbed / GLiNER model downloads across container recreates (under the data volume).
|
|
41
|
+
HF_HOME: /cognee-storage/.cache/huggingface
|
|
42
|
+
FASTEMBED_CACHE_PATH: /cognee-storage/.cache/fastembed
|
|
43
|
+
volumes:
|
|
44
|
+
# /cognee-storage is baked into the image owned by its non-root user (uid 1000), and the image defaults
|
|
45
|
+
# DATA_ROOT_DIRECTORY / SYSTEM_ROOT_DIRECTORY under it. A fresh named volume copies that ownership; a volume
|
|
46
|
+
# at any other path would be root-owned and unwritable.
|
|
47
|
+
- cognee-data:/cognee-storage
|
|
48
|
+
extra_hosts:
|
|
49
|
+
# A local LLM or embedding server on the host is reachable as http://host.docker.internal:<port>.
|
|
50
|
+
- "host.docker.internal:host-gateway"
|
|
51
|
+
restart: unless-stopped
|
|
52
|
+
# Upstream's compose uses 15s: the server drains background tasks and checkpoints SQLite on shutdown.
|
|
53
|
+
stop_grace_period: 15s
|
|
54
|
+
healthcheck:
|
|
55
|
+
# The image is Python, so python3 is there; curl may not be.
|
|
56
|
+
test: ["CMD", "python3", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=5)"]
|
|
57
|
+
interval: 15s
|
|
58
|
+
timeout: 10s
|
|
59
|
+
retries: 10
|
|
60
|
+
start_period: 90s
|
|
61
|
+
|
|
62
|
+
indexer:
|
|
63
|
+
environment:
|
|
64
|
+
# Selects indexer/sinks/cognee.py and gives it the API base URL (the compose service name, not localhost).
|
|
65
|
+
MEMORY_SINK: cognee
|
|
66
|
+
MEMORY_API_URL: http://cognee:8000
|
|
67
|
+
env_file:
|
|
68
|
+
# Only COGNEE_API_KEY belongs here. Never put LLM_API_KEY in this file.
|
|
69
|
+
- path: ${COGNEE_INDEXER_ENV_FILE:-${HOME}/.config/personal-memory/cognee-indexer.env}
|
|
70
|
+
required: false
|
|
71
|
+
depends_on:
|
|
72
|
+
# Hard dependency (required defaults to true): this fragment is only layered together with --profile cognee,
|
|
73
|
+
# so a missing profile fails loudly instead of starting an indexer with nothing to write to.
|
|
74
|
+
cognee:
|
|
75
|
+
condition: service_healthy
|
|
76
|
+
|
|
77
|
+
notebooklm:
|
|
78
|
+
environment:
|
|
79
|
+
MEMORY_SINK: cognee
|
|
80
|
+
MEMORY_API_URL: http://cognee:8000
|
|
81
|
+
env_file:
|
|
82
|
+
- path: ${COGNEE_INDEXER_ENV_FILE:-${HOME}/.config/personal-memory/cognee-indexer.env}
|
|
83
|
+
required: false
|
|
84
|
+
depends_on:
|
|
85
|
+
cognee:
|
|
86
|
+
condition: service_healthy
|
|
87
|
+
|
|
88
|
+
volumes:
|
|
89
|
+
cognee-data:
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cognee's Clack setup UI: choose local GLiNER+FastEmbed (default), Ollama, or an
|
|
3
|
+
* OpenAI-compatible key. Answers travel to the wizard only as PM_COGNEE_* in the wizard
|
|
4
|
+
* process's own environment (never on a command line, never written anywhere but cognee.env).
|
|
5
|
+
* `configureModelRouting` removes secrets from the environment once read.
|
|
6
|
+
*/
|
|
7
|
+
import net from "node:net";
|
|
8
|
+
import {
|
|
9
|
+
KEY_NAME,
|
|
10
|
+
OLLAMA_API_KEY,
|
|
11
|
+
GLINER_FASTEMBED_DEFAULTS,
|
|
12
|
+
ollamaDefaultsForEnv,
|
|
13
|
+
} from "./llm-env.mjs";
|
|
14
|
+
import { readEnvFile } from "./env-file.mjs";
|
|
15
|
+
import { applyConfig } from "./config.mjs";
|
|
16
|
+
import fs from "node:fs";
|
|
17
|
+
import path from "node:path";
|
|
18
|
+
|
|
19
|
+
/** @typedef {import("../../../wizard/lib/provider-wizard/helpers.mjs").ProviderWizardHelpers} Helpers */
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Best-effort TCP probe of host Ollama (127.0.0.1:11434). Never throws.
|
|
23
|
+
* @returns {Promise<boolean>}
|
|
24
|
+
*/
|
|
25
|
+
function probeHostOllama() {
|
|
26
|
+
return new Promise((resolve) => {
|
|
27
|
+
const socket = net.connect({ host: "127.0.0.1", port: 11434 });
|
|
28
|
+
const done = (/** @type {boolean} */ ok) => {
|
|
29
|
+
socket.removeAllListeners();
|
|
30
|
+
socket.destroy();
|
|
31
|
+
resolve(ok);
|
|
32
|
+
};
|
|
33
|
+
socket.setTimeout(500);
|
|
34
|
+
socket.once("connect", () => done(true));
|
|
35
|
+
socket.once("timeout", () => done(false));
|
|
36
|
+
socket.once("error", () => done(false));
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @param {{ repoRoot: string, home: string, pmMerged?: Record<string, unknown> }} ctx
|
|
42
|
+
* @param {typeof import("@clack/prompts")} ui the @clack/prompts module
|
|
43
|
+
* @param {Helpers} h
|
|
44
|
+
* @returns {Promise<Record<string, string>>} environment for the wizard process
|
|
45
|
+
*/
|
|
46
|
+
export async function clackSetup(ctx, ui, h) {
|
|
47
|
+
const state = /** @type {Record<string, any>} */ (ctx);
|
|
48
|
+
state.pmMerged ||= {};
|
|
49
|
+
applyConfig(state, h);
|
|
50
|
+
/** @type {Record<string, string>} */
|
|
51
|
+
const handoff = { WIZARD_SKIP_BACKEND_STEP: "1" };
|
|
52
|
+
|
|
53
|
+
const stored = readEnvFile(state.cognee.envFile).values.get(KEY_NAME);
|
|
54
|
+
if (stored) {
|
|
55
|
+
if (typeof ui.confirm !== "function") return handoff;
|
|
56
|
+
const replace = await ui.confirm({
|
|
57
|
+
message: `${state.cognee.envFile} already has an LLM_API_KEY. Replace cognify settings?`,
|
|
58
|
+
initialValue: false,
|
|
59
|
+
});
|
|
60
|
+
if (ui.isCancel(replace)) {
|
|
61
|
+
ui.cancel("Setup cancelled.");
|
|
62
|
+
process.exit(0);
|
|
63
|
+
}
|
|
64
|
+
if (!replace) return handoff;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
let choice = "gliner";
|
|
68
|
+
if (typeof ui.select === "function") {
|
|
69
|
+
const picked = await ui.select({
|
|
70
|
+
message: "How should Cognee build its knowledge graph (cognify)?",
|
|
71
|
+
options: [
|
|
72
|
+
{
|
|
73
|
+
value: "gliner",
|
|
74
|
+
label: "Local GLiNER + FastEmbed (default)",
|
|
75
|
+
hint: "no API key; CPU embeddings (BAAI/bge-small-en-v1.5)",
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
value: "ollama",
|
|
79
|
+
label: "Ollama on this host",
|
|
80
|
+
hint: "LLM + embeddings via Ollama; host.docker.internal or PM_COGNEE_OLLAMA_COMPOSE=1",
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
value: "openai",
|
|
84
|
+
label: "OpenAI-compatible API key",
|
|
85
|
+
hint: "stored in cognee.env (mode 600)",
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
initialValue: "gliner",
|
|
89
|
+
});
|
|
90
|
+
if (ui.isCancel(picked)) {
|
|
91
|
+
ui.cancel("Setup cancelled.");
|
|
92
|
+
process.exit(0);
|
|
93
|
+
}
|
|
94
|
+
choice = String(picked);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (choice === "gliner") {
|
|
98
|
+
ui.log?.info?.(
|
|
99
|
+
"Cognee will use local GLiNER extraction and FastEmbed embeddings (first cognify downloads ~800 MB of models).",
|
|
100
|
+
);
|
|
101
|
+
handoff.PM_COGNEE_GRAPH_EXTRACTOR = GLINER_FASTEMBED_DEFAULTS.GRAPH_EXTRACTOR;
|
|
102
|
+
handoff.PM_COGNEE_EMBEDDING_PROVIDER = GLINER_FASTEMBED_DEFAULTS.EMBEDDING_PROVIDER;
|
|
103
|
+
handoff.PM_COGNEE_EMBEDDING_MODEL = GLINER_FASTEMBED_DEFAULTS.EMBEDDING_MODEL;
|
|
104
|
+
handoff.PM_COGNEE_EMBEDDING_DIMENSIONS = GLINER_FASTEMBED_DEFAULTS.EMBEDDING_DIMENSIONS;
|
|
105
|
+
handoff.PM_COGNEE_AUTO_FEEDBACK = GLINER_FASTEMBED_DEFAULTS.AUTO_FEEDBACK;
|
|
106
|
+
return handoff;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (choice === "ollama") {
|
|
110
|
+
const up = await probeHostOllama();
|
|
111
|
+
if (up) ui.log?.info?.("Ollama answered on 127.0.0.1:11434");
|
|
112
|
+
else ui.log?.warn?.("Ollama is not answering on 127.0.0.1:11434; start it before cognify, or point LLM_ENDPOINT elsewhere in cognee.env");
|
|
113
|
+
// Prefer compose service DNS when this machine already uses compose Ollama (loopback-only).
|
|
114
|
+
const confPath = path.join(ctx.home || "", ".config/hindsight/wizard.conf");
|
|
115
|
+
let composeOllama = process.env.PM_COGNEE_OLLAMA_COMPOSE === "1" || process.env.MEMORY_OLLAMA_IN_COMPOSE === "1";
|
|
116
|
+
if (!composeOllama && fs.existsSync(confPath)) {
|
|
117
|
+
composeOllama = /^MEMORY_OLLAMA_IN_COMPOSE=1\s*$/m.test(fs.readFileSync(confPath, "utf8"));
|
|
118
|
+
}
|
|
119
|
+
const defaults = ollamaDefaultsForEnv(
|
|
120
|
+
composeOllama ? { ...process.env, PM_COGNEE_OLLAMA_COMPOSE: "1" } : process.env,
|
|
121
|
+
);
|
|
122
|
+
if (composeOllama) {
|
|
123
|
+
ui.log?.info?.(
|
|
124
|
+
"Compose Ollama detected: writing http://ollama:11434 (attach Cognee to the same Docker network).",
|
|
125
|
+
);
|
|
126
|
+
handoff.PM_COGNEE_OLLAMA_COMPOSE = "1";
|
|
127
|
+
}
|
|
128
|
+
handoff.PM_COGNEE_LLM_PROVIDER = "ollama";
|
|
129
|
+
handoff.PM_COGNEE_LLM_API_KEY = OLLAMA_API_KEY;
|
|
130
|
+
handoff.PM_COGNEE_LLM_ENDPOINT = defaults.LLM_ENDPOINT;
|
|
131
|
+
handoff.PM_COGNEE_EMBEDDING_PROVIDER = defaults.EMBEDDING_PROVIDER;
|
|
132
|
+
handoff.PM_COGNEE_EMBEDDING_MODEL = defaults.EMBEDDING_MODEL;
|
|
133
|
+
handoff.PM_COGNEE_EMBEDDING_ENDPOINT = defaults.EMBEDDING_ENDPOINT;
|
|
134
|
+
handoff.PM_COGNEE_EMBEDDING_DIMENSIONS = defaults.EMBEDDING_DIMENSIONS;
|
|
135
|
+
return handoff;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (typeof ui.password !== "function") return handoff;
|
|
139
|
+
ui.log.info("Cognee builds its graph with an LLM; the key is stored in cognee.env (mode 600), never in the repo.");
|
|
140
|
+
const key = await ui.password({
|
|
141
|
+
message: "Cognee LLM_API_KEY (input hidden; press Enter to skip — falls back to GLiNER + FastEmbed)",
|
|
142
|
+
});
|
|
143
|
+
if (ui.isCancel(key)) {
|
|
144
|
+
ui.cancel("Setup cancelled.");
|
|
145
|
+
process.exit(0);
|
|
146
|
+
}
|
|
147
|
+
if (String(key ?? "").trim()) {
|
|
148
|
+
handoff.PM_COGNEE_LLM_API_KEY = String(key).trim();
|
|
149
|
+
} else {
|
|
150
|
+
handoff.PM_COGNEE_GRAPH_EXTRACTOR = GLINER_FASTEMBED_DEFAULTS.GRAPH_EXTRACTOR;
|
|
151
|
+
handoff.PM_COGNEE_EMBEDDING_PROVIDER = GLINER_FASTEMBED_DEFAULTS.EMBEDDING_PROVIDER;
|
|
152
|
+
handoff.PM_COGNEE_EMBEDDING_MODEL = GLINER_FASTEMBED_DEFAULTS.EMBEDDING_MODEL;
|
|
153
|
+
handoff.PM_COGNEE_EMBEDDING_DIMENSIONS = GLINER_FASTEMBED_DEFAULTS.EMBEDDING_DIMENSIONS;
|
|
154
|
+
handoff.PM_COGNEE_AUTO_FEEDBACK = GLINER_FASTEMBED_DEFAULTS.AUTO_FEEDBACK;
|
|
155
|
+
}
|
|
156
|
+
return handoff;
|
|
157
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cognee has no coding-agent plugin package. This hook prints REST paths and registers
|
|
3
|
+
* the read-only Cognee MCP in ~/.cursor/mcp.json (health + search).
|
|
4
|
+
*/
|
|
5
|
+
import { installCogneeMcp } from "./cognee-mcp-install.mjs";
|
|
6
|
+
import { currentPort, ensureState } from "./state.mjs";
|
|
7
|
+
|
|
8
|
+
/** @typedef {import("../../../wizard/lib/provider-wizard/helpers.mjs").ProviderWizardHelpers} Helpers */
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {Record<string, any>} ctx
|
|
12
|
+
* @param {Helpers} h
|
|
13
|
+
*/
|
|
14
|
+
export async function setupCodingAgent(ctx, h) {
|
|
15
|
+
ensureState(ctx);
|
|
16
|
+
const url = ctx.cogneeUrl || `http://127.0.0.1:${currentPort(ctx)}`;
|
|
17
|
+
h.info(`Cognee has no coding-agent plugin package. Agents talk to it over REST at ${url}:`);
|
|
18
|
+
h.info(` OpenAPI docs ${url}/docs`);
|
|
19
|
+
h.info(` Health GET ${url}/health`);
|
|
20
|
+
h.info(` Ingest POST ${url}/api/v1/add (multipart; then cognify)`);
|
|
21
|
+
h.info(` Cognify POST ${url}/api/v1/cognify`);
|
|
22
|
+
h.info(` Search POST ${url}/api/v1/search`);
|
|
23
|
+
h.info(" Auth is off in this stack (loopback only). Set X-Api-Key only if you enable auth in compose.");
|
|
24
|
+
h.info("Read-only Cursor MCP: cognee_health / cognee_search (cli/cognee-mcp.mjs).");
|
|
25
|
+
await installCogneeMcp(ctx, h);
|
|
26
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merge a "cognee" stdio MCP into ~/.cursor/mcp.json.
|
|
3
|
+
* Preserves existing hindsight / codegraph / notebooklm / mem0 entries. Never writes secrets.
|
|
4
|
+
*/
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { envValue } from "../../../wizard/lib/paths.mjs";
|
|
8
|
+
import { currentPort, DEFAULT_PORT, ensureState } from "./state.mjs";
|
|
9
|
+
|
|
10
|
+
/** @typedef {import("../../../wizard/lib/provider-wizard/helpers.mjs").ProviderWizardHelpers} Helpers */
|
|
11
|
+
|
|
12
|
+
/** Sibling MCP servers this merge must never rewrite. */
|
|
13
|
+
export const PRESERVE_MCP_SERVERS = Object.freeze(["hindsight", "codegraph", "notebooklm", "mem0"]);
|
|
14
|
+
|
|
15
|
+
/** @param {string} repoRoot */
|
|
16
|
+
export function cogneeMcpScriptPath(repoRoot) {
|
|
17
|
+
return path.resolve(repoRoot, "cli/cognee-mcp.mjs");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Host-view Cognee URL (no secrets). Order: COGNEE_API_URL / COGNEE_URL, ctx.cogneeUrl,
|
|
22
|
+
* COGNEE_PORT (env / stack .env / wizard.conf / ctx), then default port.
|
|
23
|
+
* @param {{
|
|
24
|
+
* home?: string,
|
|
25
|
+
* stackRoot?: string,
|
|
26
|
+
* repoRoot?: string,
|
|
27
|
+
* env?: NodeJS.ProcessEnv,
|
|
28
|
+
* cogneeUrl?: string,
|
|
29
|
+
* portCognee?: string | number,
|
|
30
|
+
* }} [opts]
|
|
31
|
+
*/
|
|
32
|
+
export function resolveCogneeApiUrl(opts = {}) {
|
|
33
|
+
const env = opts.env || process.env;
|
|
34
|
+
const fromUrl = String(env.COGNEE_API_URL || env.COGNEE_URL || opts.cogneeUrl || "").trim();
|
|
35
|
+
if (fromUrl) return fromUrl.replace(/\/+$/, "");
|
|
36
|
+
|
|
37
|
+
const home = opts.home || "";
|
|
38
|
+
const stackRoot = opts.stackRoot || opts.repoRoot || "";
|
|
39
|
+
const candidates = [
|
|
40
|
+
env.COGNEE_PORT,
|
|
41
|
+
opts.portCognee,
|
|
42
|
+
stackRoot ? envValue(path.join(stackRoot, ".env"), "COGNEE_PORT") : "",
|
|
43
|
+
home ? envValue(path.join(home, ".config/hindsight/wizard.conf"), "COGNEE_PORT") : "",
|
|
44
|
+
];
|
|
45
|
+
const port = String(candidates.map((v) => String(v || "").trim()).find((v) => /^\d+$/.test(v)) || DEFAULT_PORT);
|
|
46
|
+
return `http://127.0.0.1:${port}`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* mcp.json entry: node + script + COGNEE_API_URL only (never COGNEE_API_KEY).
|
|
51
|
+
* @param {string} scriptPath
|
|
52
|
+
* @param {string} [apiUrl]
|
|
53
|
+
*/
|
|
54
|
+
export function cogneeMcpEntry(scriptPath, apiUrl) {
|
|
55
|
+
const url = String(apiUrl || `http://127.0.0.1:${DEFAULT_PORT}`).replace(/\/+$/, "");
|
|
56
|
+
return {
|
|
57
|
+
command: "node",
|
|
58
|
+
args: [scriptPath],
|
|
59
|
+
env: {
|
|
60
|
+
COGNEE_API_URL: url,
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** @deprecated alias — use cogneeMcpEntry */
|
|
66
|
+
export const cogneeMcpStubEntry = cogneeMcpEntry;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @param {Record<string, any>} mcp
|
|
70
|
+
* @param {string} scriptPath
|
|
71
|
+
* @param {string} [apiUrl]
|
|
72
|
+
* @returns {{ mcp: Record<string, any>, changed: boolean, skipped?: string, refused?: string }}
|
|
73
|
+
*/
|
|
74
|
+
export function mergeCogneeMcpServer(mcp, scriptPath, apiUrl) {
|
|
75
|
+
const out = { ...mcp };
|
|
76
|
+
const servers = { ...(mcp.mcpServers && typeof mcp.mcpServers === "object" ? mcp.mcpServers : {}) };
|
|
77
|
+
const before = Object.fromEntries(PRESERVE_MCP_SERVERS.map((k) => [k, servers[k]]));
|
|
78
|
+
const next = cogneeMcpEntry(scriptPath, apiUrl);
|
|
79
|
+
const prev = servers.cognee;
|
|
80
|
+
const same = prev && JSON.stringify(prev) === JSON.stringify(next);
|
|
81
|
+
if (same) {
|
|
82
|
+
return { mcp: { ...out, mcpServers: servers }, changed: false, skipped: "already configured" };
|
|
83
|
+
}
|
|
84
|
+
servers.cognee = next;
|
|
85
|
+
for (const k of PRESERVE_MCP_SERVERS) {
|
|
86
|
+
if (before[k] !== undefined && servers[k] !== before[k]) {
|
|
87
|
+
return { mcp, changed: false, refused: `refusing to alter ${k} MCP entry` };
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return { mcp: { ...out, mcpServers: servers }, changed: true };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* @param {Record<string, any>} ctx
|
|
95
|
+
* @param {Helpers} h
|
|
96
|
+
*/
|
|
97
|
+
export async function installCogneeMcp(ctx, h) {
|
|
98
|
+
ensureState(ctx);
|
|
99
|
+
const script = cogneeMcpScriptPath(ctx.repoRoot);
|
|
100
|
+
if (!fs.existsSync(script)) {
|
|
101
|
+
h.warn(`cognee MCP script missing: ${script}`);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const apiUrl =
|
|
106
|
+
ctx.cogneeUrl ||
|
|
107
|
+
resolveCogneeApiUrl({
|
|
108
|
+
home: ctx.home,
|
|
109
|
+
stackRoot: ctx.repoRoot,
|
|
110
|
+
repoRoot: ctx.repoRoot,
|
|
111
|
+
env: process.env,
|
|
112
|
+
portCognee: ctx.portCognee || currentPort(ctx),
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
const mcpPath = path.join(ctx.home, ".cursor", "mcp.json");
|
|
116
|
+
let existing = {};
|
|
117
|
+
if (fs.existsSync(mcpPath)) {
|
|
118
|
+
try {
|
|
119
|
+
existing = JSON.parse(fs.readFileSync(mcpPath, "utf8"));
|
|
120
|
+
} catch (err) {
|
|
121
|
+
h.warn(`cannot parse ${mcpPath}: ${err instanceof Error ? err.message : err}`);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const snapshots = Object.fromEntries(
|
|
127
|
+
PRESERVE_MCP_SERVERS.map((k) => [k, existing.mcpServers?.[k]]),
|
|
128
|
+
);
|
|
129
|
+
const { mcp, changed, skipped, refused } = mergeCogneeMcpServer(existing, script, apiUrl);
|
|
130
|
+
if (refused) {
|
|
131
|
+
h.warn(refused);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
for (const k of PRESERVE_MCP_SERVERS) {
|
|
135
|
+
if (snapshots[k] && mcp.mcpServers?.[k] !== snapshots[k]) {
|
|
136
|
+
h.warn(`refusing to alter ${k} MCP entry`);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (!changed) {
|
|
142
|
+
h.ok(`cognee MCP already in ${mcpPath}${skipped ? ` (${skipped})` : ""}`);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (ctx.dry) {
|
|
146
|
+
h.info(`[dry-run] merge cognee MCP into ${mcpPath} → node ${script} (COGNEE_API_URL=${apiUrl}; no API key)`);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
fs.mkdirSync(path.dirname(mcpPath), { recursive: true });
|
|
150
|
+
fs.writeFileSync(mcpPath, `${JSON.stringify(mcp, null, 2)}\n`);
|
|
151
|
+
h.ok(`registered cognee MCP in ${mcpPath}`);
|
|
152
|
+
h.info("Never put COGNEE_API_KEY in mcp.json; export it in the agent environment if auth is enabled");
|
|
153
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cognee's slice of ~/.config/personal-memory/config.toml: the `[memory.cognee]` table
|
|
3
|
+
* (`port`, `env_file`, `indexer_env_file`). It never holds a secret.
|
|
4
|
+
*/
|
|
5
|
+
import {
|
|
6
|
+
DEFAULT_ENV_FILE,
|
|
7
|
+
DEFAULT_INDEXER_ENV_FILE,
|
|
8
|
+
currentPort,
|
|
9
|
+
ensureState,
|
|
10
|
+
resolveFile,
|
|
11
|
+
tildePath,
|
|
12
|
+
} from "./state.mjs";
|
|
13
|
+
|
|
14
|
+
/** @typedef {import("../../../wizard/lib/provider-wizard/helpers.mjs").ProviderWizardHelpers} Helpers */
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @param {unknown} value
|
|
18
|
+
* @returns {string} the port as a string, or "" when unset
|
|
19
|
+
*/
|
|
20
|
+
function portText(value) {
|
|
21
|
+
if (value === undefined || value === null || value === "") return "";
|
|
22
|
+
return String(value);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The `[memory.cognee]` table from a merged TOML config.
|
|
27
|
+
* @param {Record<string, unknown>} cfg
|
|
28
|
+
* @returns {{ port: string, envFile: string, indexerEnvFile: string }}
|
|
29
|
+
*/
|
|
30
|
+
export function defaultsFromConfig(cfg) {
|
|
31
|
+
const memory = /** @type {Record<string, any>} */ (cfg.memory || {});
|
|
32
|
+
const table = /** @type {Record<string, unknown>} */ (
|
|
33
|
+
memory.cognee && typeof memory.cognee === "object" ? memory.cognee : {}
|
|
34
|
+
);
|
|
35
|
+
return {
|
|
36
|
+
port: portText(table.port),
|
|
37
|
+
envFile: String(table.env_file || ""),
|
|
38
|
+
indexerEnvFile: String(table.indexer_env_file || ""),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Map `[memory.cognee]` into the wizard context and, where the table is the only source,
|
|
44
|
+
* into the environment compose and the stack setup script read (COGNEE_PORT,
|
|
45
|
+
* COGNEE_ENV_FILE). The environment and the CLI keep precedence.
|
|
46
|
+
* @param {Record<string, any>} ctx
|
|
47
|
+
* @param {Helpers} h
|
|
48
|
+
*/
|
|
49
|
+
export function applyConfig(ctx, h) {
|
|
50
|
+
ensureState(ctx);
|
|
51
|
+
const d = defaultsFromConfig(ctx.pmMerged || {});
|
|
52
|
+
if (d.port) {
|
|
53
|
+
if (!/^\d+$/.test(d.port) || Number(d.port) < 1 || Number(d.port) > 65535) {
|
|
54
|
+
h.die(`[memory.cognee] port must be a number from 1 to 65535 (got: ${d.port})`);
|
|
55
|
+
}
|
|
56
|
+
ctx.cognee.port = d.port;
|
|
57
|
+
if (!process.env.COGNEE_PORT) process.env.COGNEE_PORT = d.port;
|
|
58
|
+
}
|
|
59
|
+
const defaults = {
|
|
60
|
+
COGNEE_ENV_FILE: DEFAULT_ENV_FILE,
|
|
61
|
+
COGNEE_INDEXER_ENV_FILE: DEFAULT_INDEXER_ENV_FILE,
|
|
62
|
+
};
|
|
63
|
+
for (const [setting, name, field] of /** @type {const} */ ([
|
|
64
|
+
[d.envFile, "COGNEE_ENV_FILE", "configEnvFile"],
|
|
65
|
+
[d.indexerEnvFile, "COGNEE_INDEXER_ENV_FILE", "configIndexerEnvFile"],
|
|
66
|
+
])) {
|
|
67
|
+
if (process.env[name]?.startsWith("~")) process.env[name] = resolveFile(process.env[name], ctx);
|
|
68
|
+
if (setting) {
|
|
69
|
+
ctx.cognee[field] = setting;
|
|
70
|
+
// Compose reads the path from the environment (or the stack .env, which the stack
|
|
71
|
+
// setup script fills from this export), so a TOML value must be a real absolute path.
|
|
72
|
+
// The shipped default location needs no export (and no .env line).
|
|
73
|
+
const file = resolveFile(setting, ctx);
|
|
74
|
+
if (!process.env[name] && file !== resolveFile(defaults[name], ctx)) process.env[name] = file;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
ensureState(ctx);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Tables merged into config.toml when the wizard saves it. `memory` replaces the meta
|
|
82
|
+
* wizard's own `[memory]` table, so it carries `provider` too.
|
|
83
|
+
* @param {Record<string, any>} ctx
|
|
84
|
+
* @returns {Record<string, Record<string, unknown>>}
|
|
85
|
+
*/
|
|
86
|
+
export function configToml(ctx) {
|
|
87
|
+
ensureState(ctx);
|
|
88
|
+
return {
|
|
89
|
+
memory: {
|
|
90
|
+
provider: "cognee",
|
|
91
|
+
cognee: {
|
|
92
|
+
port: Number(currentPort(ctx)),
|
|
93
|
+
env_file: tildePath(ctx.cognee.envFile, ctx.home) || DEFAULT_ENV_FILE,
|
|
94
|
+
indexer_env_file: tildePath(ctx.cognee.indexerEnvFile, ctx.home) || DEFAULT_INDEXER_ENV_FILE,
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
}
|