fix: remove the process env from the tests and fix the plugin manifest (#4927)
This commit is contained in:
@@ -4,6 +4,22 @@ description: "Release notes for the OpenClaw plugin and agent harness."
|
||||
mode: "wide"
|
||||
---
|
||||
|
||||
<Update label="2026-04-22" description="v1.0.9">
|
||||
|
||||
**Security & Compliance:**
|
||||
- Added top-level `requiredEnvVars` to plugin manifest, declaring env vars per mode (platform, OSS OpenAI, OSS Anthropic, OSS Ollama). Fixes ClaHub scanner "required env vars: none" mismatch
|
||||
- Added `sensitive: true` and descriptions to `apiKey` and `userEmail` in `configSchema` — previously only declared in `uiHints`
|
||||
- Added `default: false` with descriptions to `autoCapture` and `autoRecall` in `configSchema` so scanner can confirm opt-in defaults
|
||||
- Added `dataLocations` field to manifest declaring all persistence paths (config, vectorStore, historyDb, dreamState)
|
||||
- Added `privacy` field to manifest documenting data flow for platform vs open-source mode and credential storage guidance
|
||||
- Added `externalEndpoints` to `setup` section declaring api.mem0.ai and app.mem0.ai with purpose and requirement context
|
||||
|
||||
**Tests:**
|
||||
- Replaced direct `process.env` access in `tests/cli-commands.test.ts` and `tests/fs-safe.test.ts` with `vi.stubEnv`/`vi.unstubAllEnvs`. Fixes ClaHub static analysis flag for "environment variable access combined with network send"
|
||||
- 421 tests across 15 test files
|
||||
|
||||
</Update>
|
||||
|
||||
<Update label="2026-04-21" description="v1.0.8">
|
||||
|
||||
**New Features:**
|
||||
|
||||
+36
-38
@@ -19,46 +19,9 @@ openclaw --version
|
||||
|
||||
## Quick Start
|
||||
|
||||
The fastest way is to install directly from your OpenClaw chat — no CLI or config editing needed.
|
||||
|
||||
Copy and paste this into your OpenClaw chat (Telegram, WhatsApp, default chat, or any channel where your agent lives):
|
||||
|
||||
```
|
||||
Setup Mem0 from mem0.ai/claw-setup
|
||||
```
|
||||
|
||||
OpenClaw installs the plugin, prompts you for your email, and connects your Mem0 account with OTP verification. See [Chat Setup](#chat-setup-recommended) below for the full walkthrough.
|
||||
|
||||
If you prefer the OpenClaw CLI, or are setting up self-hosted / open-source mode, see [Manual Config](#manual-config) and [Open-Source (Self-hosted)](#open-source-self-hosted) below.
|
||||
|
||||
### Platform (Mem0 Cloud)
|
||||
|
||||
There are two ways to set up `@mem0/openclaw-mem0` on the Mem0 platform:
|
||||
|
||||
- **Chat setup (recommended)** — run the setup inside any OpenClaw chat. No config editing, no API key handling.
|
||||
- **Manual config** — edit `openclaw.json` directly.
|
||||
|
||||
#### Chat Setup (Recommended)
|
||||
|
||||
You no longer need manual config editing to get started. Everything happens inside the OpenClaw chat itself.
|
||||
|
||||
1. **Send the setup command to your OpenClaw agent.** Open any OpenClaw channel and paste:
|
||||
|
||||
```
|
||||
Setup Mem0 from mem0.ai/claw-setup
|
||||
```
|
||||
|
||||
OpenClaw responds with a Mem0 setup card and asks: *"What's your email address? I'll send you a verification code to connect your Mem0 account."*
|
||||
|
||||
2. **Enter your email.** Type your email address and send it. Mem0 replies: *"Check your email for a 6-digit code and paste it here."*
|
||||
|
||||
3. **Paste the OTP.** Copy the 6-digit code from your email inbox and paste it into the chat. You'll see: *"Connected to Mem0."*
|
||||
|
||||
That's it. No API key, no config file editing, no environment variables. The plugin is now active and auto-capture and auto-recall are running on every turn.
|
||||
|
||||
> The chat flow uses the same underlying config as manual setup — it writes `apiKey` and `userId` into `openclaw.json` for you. You can still open the file to inspect or override values afterward.
|
||||
|
||||
#### Manual Config
|
||||
#### Install and Configure
|
||||
|
||||
1. **Install the plugin via the OpenClaw CLI:**
|
||||
|
||||
@@ -319,6 +282,41 @@ All fields optional. Defaults: `text-embedding-3-small` embeddings, local SQLite
|
||||
| `oss.llm.config` | `object` | — | Provider config (`apiKey`, `model`, `baseURL`) |
|
||||
| `oss.historyDbPath` | `string` | — | SQLite path for edit history |
|
||||
|
||||
## Privacy & Security
|
||||
|
||||
### Data Flow
|
||||
|
||||
| Mode | Where data goes | Credentials needed |
|
||||
|------|----------------|-------------------|
|
||||
| **Platform** | Conversations sent to `api.mem0.ai` for memory extraction and retrieval | `MEM0_API_KEY` |
|
||||
| **Open-Source (OpenAI)** | LLM/embedding calls to OpenAI API; vectors stored locally at `~/.mem0/vector_store.db` | `OPENAI_API_KEY` |
|
||||
| **Open-Source (Ollama)** | Fully local — LLM, embeddings, and vectors all on your machine | None |
|
||||
|
||||
### Credential Storage
|
||||
|
||||
The plugin stores configuration in `~/.openclaw/openclaw.json`. If you use the chat setup flow or `openclaw mem0 init`, your API key and user ID are written to this file.
|
||||
|
||||
To avoid plaintext credentials:
|
||||
- Use env var references: `"apiKey": "${MEM0_API_KEY}"`
|
||||
- Use SecretRef: `"apiKey": {"source": "env", "provider": "default", "id": "MEM0_API_KEY"}`
|
||||
|
||||
### Auto-Capture & Auto-Recall
|
||||
|
||||
Both are **disabled by default** (`false`). When enabled:
|
||||
- `autoCapture`: sends conversation content to your configured backend (cloud or local) after each agent turn
|
||||
- `autoRecall`: queries your memory store before each agent turn and injects results into agent context
|
||||
|
||||
Do not enable `autoCapture` in platform mode if your conversations contain sensitive data you do not want stored on Mem0 cloud.
|
||||
|
||||
### Persistence Locations
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `~/.openclaw/openclaw.json` | Plugin configuration (API keys, user ID, settings) |
|
||||
| `~/.mem0/vector_store.db` | Local vector store (open-source mode only) |
|
||||
| `~/.mem0/history.db` | Memory edit history (open-source mode only) |
|
||||
| `<pluginStateDir>/dream-state.json` | Memory consolidation state |
|
||||
|
||||
## License
|
||||
|
||||
[Apache 2.0](LICENSE)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"id": "openclaw-mem0",
|
||||
"name": "Memory (Mem0)",
|
||||
"description": "Mem0 memory backend for OpenClaw — platform or self-hosted open-source. PLATFORM MODE: Sends conversation data to mem0.ai cloud (requires MEM0_API_KEY). OPEN-SOURCE MODE: Stores vectors locally (~/.mem0/history.db) but uses external APIs for embeddings/LLM (default: OpenAI, requires OPENAI_API_KEY). Auto-recall injects relevant memories into agent context before each turn; auto-capture extracts durable facts after turns. Both are opt-in via autoRecall/autoCapture config settings (default: false). The plugin injects a memory triage protocol into system context when skills mode is enabled. Config stored in ~/.openclaw/openclaw.json.",
|
||||
"version": "1.0.8",
|
||||
"description": "Mem0 memory backend for OpenClaw — platform (mem0.ai cloud) or self-hosted open-source. Auto-recall and auto-capture are opt-in (disabled by default). Supports OpenAI, Anthropic, Ollama (fully local), Qdrant, and PGVector providers.",
|
||||
"version": "1.0.9",
|
||||
"kind": "memory",
|
||||
"skills": ["skills"],
|
||||
"commandAliases": [
|
||||
@@ -149,10 +149,13 @@
|
||||
"enum": [
|
||||
"platform",
|
||||
"open-source"
|
||||
]
|
||||
],
|
||||
"description": "Required. 'platform' requires MEM0_API_KEY. 'open-source' requires OPENAI_API_KEY (default) or no keys with Ollama."
|
||||
},
|
||||
"apiKey": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"sensitive": true,
|
||||
"description": "Platform API key. Prefer SecretRef or ${MEM0_API_KEY} env var over plaintext."
|
||||
},
|
||||
"userId": {
|
||||
"type": "string"
|
||||
@@ -162,13 +165,19 @@
|
||||
"description": "API base URL override (default: https://api.mem0.ai)"
|
||||
},
|
||||
"userEmail": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"sensitive": true,
|
||||
"description": "Email associated with Mem0 account. Set automatically during platform login."
|
||||
},
|
||||
"autoCapture": {
|
||||
"type": "boolean"
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Opt-in. When true, extracts durable facts after each agent turn. Disabled by default."
|
||||
},
|
||||
"autoRecall": {
|
||||
"type": "boolean"
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Opt-in. When true, injects relevant memories before each agent turn. Disabled by default."
|
||||
},
|
||||
"customInstructions": {
|
||||
"type": "string"
|
||||
@@ -302,6 +311,18 @@
|
||||
}
|
||||
],
|
||||
"requiresRuntime": false,
|
||||
"postInstallHint": "Run 'openclaw mem0 init' to configure mode and credentials"
|
||||
"postInstallHint": "Run 'openclaw mem0 init' to configure mode and credentials",
|
||||
"externalEndpoints": [
|
||||
{
|
||||
"url": "https://api.mem0.ai",
|
||||
"purpose": "Platform mode API — memory storage and retrieval",
|
||||
"required": "platform mode only"
|
||||
},
|
||||
{
|
||||
"url": "https://app.mem0.ai",
|
||||
"purpose": "Account dashboard and API key management",
|
||||
"required": "platform mode only"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@mem0/openclaw-mem0",
|
||||
"version": "1.0.8",
|
||||
"version": "1.0.9",
|
||||
"type": "module",
|
||||
"description": "Mem0 memory backend for OpenClaw — platform or self-hosted open-source",
|
||||
"license": "Apache-2.0",
|
||||
|
||||
@@ -7,7 +7,7 @@ description: >
|
||||
Also triggers automatically after sufficient activity (configurable).
|
||||
user-invocable: true
|
||||
metadata:
|
||||
{"openclaw": {"emoji": "💤", "requires": {"env": ["MEM0_API_KEY"], "bins": []}}}
|
||||
{"openclaw": {"injected": true, "emoji": "💤", "requires": {"env": ["MEM0_API_KEY", "OPENAI_API_KEY", "ANTHROPIC_API_KEY"], "bins": []}}}
|
||||
---
|
||||
|
||||
# Memory Consolidation
|
||||
|
||||
@@ -7,7 +7,7 @@ description: >
|
||||
projects, and relationships. Loaded by the openclaw-mem0 plugin when skills mode is active.
|
||||
user-invocable: false
|
||||
metadata:
|
||||
{"openclaw": {"always": false, "emoji": "🧠", "requires": {"env": ["MEM0_API_KEY"], "bins": []}}}
|
||||
{"openclaw": {"always": false, "injected": true, "emoji": "🧠", "requires": {"env": ["MEM0_API_KEY", "OPENAI_API_KEY", "ANTHROPIC_API_KEY"], "bins": []}}}
|
||||
---
|
||||
|
||||
# Memory Protocol
|
||||
|
||||
@@ -1738,9 +1738,7 @@ describe("registerCliCommands", () => {
|
||||
const { mem0 } = setup();
|
||||
const initCmd = findCommand(mem0, "init")!;
|
||||
|
||||
// Ensure env var is not set so validation fails
|
||||
const savedEnv = process.env.OPENAI_API_KEY;
|
||||
delete process.env.OPENAI_API_KEY;
|
||||
vi.stubEnv("OPENAI_API_KEY", "");
|
||||
|
||||
await initCmd._action!({ mode: "open-source", ossLlm: "openai" });
|
||||
|
||||
@@ -1748,8 +1746,7 @@ describe("registerCliCommands", () => {
|
||||
expect.stringContaining("--oss-llm-key"),
|
||||
);
|
||||
|
||||
// Restore env var
|
||||
if (savedEnv !== undefined) process.env.OPENAI_API_KEY = savedEnv;
|
||||
vi.unstubAllEnvs();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,36 +1,30 @@
|
||||
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
||||
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
||||
import { bootstrapTelemetryFlag } from "../fs-safe.ts";
|
||||
|
||||
describe("bootstrapTelemetryFlag", () => {
|
||||
const originalEnv = process.env.MEM0_TELEMETRY;
|
||||
|
||||
beforeEach(() => {
|
||||
delete (globalThis as any).__mem0_telemetry_override;
|
||||
delete process.env.MEM0_TELEMETRY;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
delete (globalThis as any).__mem0_telemetry_override;
|
||||
if (originalEnv !== undefined) {
|
||||
process.env.MEM0_TELEMETRY = originalEnv;
|
||||
} else {
|
||||
delete process.env.MEM0_TELEMETRY;
|
||||
}
|
||||
vi.unstubAllEnvs();
|
||||
});
|
||||
|
||||
it("sets globalThis override when MEM0_TELEMETRY is set", () => {
|
||||
process.env.MEM0_TELEMETRY = "false";
|
||||
vi.stubEnv("MEM0_TELEMETRY", "false");
|
||||
bootstrapTelemetryFlag();
|
||||
expect((globalThis as any).__mem0_telemetry_override).toBe("false");
|
||||
});
|
||||
|
||||
it("does not set globalThis override when MEM0_TELEMETRY is unset", () => {
|
||||
vi.stubEnv("MEM0_TELEMETRY", undefined as unknown as string);
|
||||
bootstrapTelemetryFlag();
|
||||
expect((globalThis as any).__mem0_telemetry_override).toBeUndefined();
|
||||
});
|
||||
|
||||
it("passes through truthy values", () => {
|
||||
process.env.MEM0_TELEMETRY = "true";
|
||||
vi.stubEnv("MEM0_TELEMETRY", "true");
|
||||
bootstrapTelemetryFlag();
|
||||
expect((globalThis as any).__mem0_telemetry_override).toBe("true");
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user