Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a07788c719 | ||
|
|
0a82a8376c | ||
|
|
c95c660cbd |
@@ -4,6 +4,22 @@ description: "Release notes for the OpenClaw plugin and agent harness."
|
|||||||
mode: "wide"
|
mode: "wide"
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<Update label="2026-04-22" description="v1.0.9-beta.0">
|
||||||
|
|
||||||
|
**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">
|
<Update label="2026-04-21" description="v1.0.8">
|
||||||
|
|
||||||
**New Features:**
|
**New Features:**
|
||||||
|
|||||||
@@ -2,8 +2,14 @@
|
|||||||
"id": "openclaw-mem0",
|
"id": "openclaw-mem0",
|
||||||
"name": "Memory (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.",
|
"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",
|
"version": "1.0.9-beta.0",
|
||||||
"kind": "memory",
|
"kind": "memory",
|
||||||
|
"requiredEnvVars": {
|
||||||
|
"platform": ["MEM0_API_KEY"],
|
||||||
|
"open-source (OpenAI)": ["OPENAI_API_KEY"],
|
||||||
|
"open-source (Anthropic)": ["ANTHROPIC_API_KEY"],
|
||||||
|
"open-source (Ollama)": []
|
||||||
|
},
|
||||||
"skills": ["skills"],
|
"skills": ["skills"],
|
||||||
"commandAliases": [
|
"commandAliases": [
|
||||||
{
|
{
|
||||||
@@ -152,7 +158,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"apiKey": {
|
"apiKey": {
|
||||||
"type": "string"
|
"type": "string",
|
||||||
|
"sensitive": true,
|
||||||
|
"description": "Platform API key. Prefer SecretRef or ${MEM0_API_KEY} env var over plaintext."
|
||||||
},
|
},
|
||||||
"userId": {
|
"userId": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@@ -162,13 +170,19 @@
|
|||||||
"description": "API base URL override (default: https://api.mem0.ai)"
|
"description": "API base URL override (default: https://api.mem0.ai)"
|
||||||
},
|
},
|
||||||
"userEmail": {
|
"userEmail": {
|
||||||
"type": "string"
|
"type": "string",
|
||||||
|
"sensitive": true,
|
||||||
|
"description": "Email associated with Mem0 account. Set automatically during platform login."
|
||||||
},
|
},
|
||||||
"autoCapture": {
|
"autoCapture": {
|
||||||
"type": "boolean"
|
"type": "boolean",
|
||||||
|
"default": false,
|
||||||
|
"description": "Opt-in. When true, extracts durable facts after each agent turn. Disabled by default."
|
||||||
},
|
},
|
||||||
"autoRecall": {
|
"autoRecall": {
|
||||||
"type": "boolean"
|
"type": "boolean",
|
||||||
|
"default": false,
|
||||||
|
"description": "Opt-in. When true, injects relevant memories before each agent turn. Disabled by default."
|
||||||
},
|
},
|
||||||
"customInstructions": {
|
"customInstructions": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
@@ -286,6 +300,17 @@
|
|||||||
},
|
},
|
||||||
"required": []
|
"required": []
|
||||||
},
|
},
|
||||||
|
"dataLocations": {
|
||||||
|
"config": "~/.openclaw/openclaw.json",
|
||||||
|
"vectorStore": "~/.mem0/vector_store.db (open-source mode only)",
|
||||||
|
"historyDb": "~/.mem0/history.db (open-source mode only)",
|
||||||
|
"dreamState": "<pluginStateDir>/dream-state.json"
|
||||||
|
},
|
||||||
|
"privacy": {
|
||||||
|
"platformMode": "Conversation data is sent to mem0.ai cloud API for memory extraction and retrieval.",
|
||||||
|
"openSourceMode": "All data stays local. External API calls only for LLM/embedding providers you configure (OpenAI, Anthropic, or fully local with Ollama).",
|
||||||
|
"credentialStorage": "API keys in openclaw.json. Use SecretRef or ${ENV_VAR} syntax to avoid plaintext storage."
|
||||||
|
},
|
||||||
"setup": {
|
"setup": {
|
||||||
"providers": [
|
"providers": [
|
||||||
{
|
{
|
||||||
@@ -302,6 +327,18 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"requiresRuntime": false,
|
"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",
|
"name": "@mem0/openclaw-mem0",
|
||||||
"version": "1.0.8",
|
"version": "1.0.9-beta.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Mem0 memory backend for OpenClaw — platform or self-hosted open-source",
|
"description": "Mem0 memory backend for OpenClaw — platform or self-hosted open-source",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
|
|||||||
@@ -1738,9 +1738,7 @@ describe("registerCliCommands", () => {
|
|||||||
const { mem0 } = setup();
|
const { mem0 } = setup();
|
||||||
const initCmd = findCommand(mem0, "init")!;
|
const initCmd = findCommand(mem0, "init")!;
|
||||||
|
|
||||||
// Ensure env var is not set so validation fails
|
vi.stubEnv("OPENAI_API_KEY", "");
|
||||||
const savedEnv = process.env.OPENAI_API_KEY;
|
|
||||||
delete process.env.OPENAI_API_KEY;
|
|
||||||
|
|
||||||
await initCmd._action!({ mode: "open-source", ossLlm: "openai" });
|
await initCmd._action!({ mode: "open-source", ossLlm: "openai" });
|
||||||
|
|
||||||
@@ -1748,8 +1746,7 @@ describe("registerCliCommands", () => {
|
|||||||
expect.stringContaining("--oss-llm-key"),
|
expect.stringContaining("--oss-llm-key"),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Restore env var
|
vi.unstubAllEnvs();
|
||||||
if (savedEnv !== undefined) process.env.OPENAI_API_KEY = savedEnv;
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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";
|
import { bootstrapTelemetryFlag } from "../fs-safe.ts";
|
||||||
|
|
||||||
describe("bootstrapTelemetryFlag", () => {
|
describe("bootstrapTelemetryFlag", () => {
|
||||||
const originalEnv = process.env.MEM0_TELEMETRY;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
delete (globalThis as any).__mem0_telemetry_override;
|
delete (globalThis as any).__mem0_telemetry_override;
|
||||||
delete process.env.MEM0_TELEMETRY;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
delete (globalThis as any).__mem0_telemetry_override;
|
delete (globalThis as any).__mem0_telemetry_override;
|
||||||
if (originalEnv !== undefined) {
|
vi.unstubAllEnvs();
|
||||||
process.env.MEM0_TELEMETRY = originalEnv;
|
|
||||||
} else {
|
|
||||||
delete process.env.MEM0_TELEMETRY;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("sets globalThis override when MEM0_TELEMETRY is set", () => {
|
it("sets globalThis override when MEM0_TELEMETRY is set", () => {
|
||||||
process.env.MEM0_TELEMETRY = "false";
|
vi.stubEnv("MEM0_TELEMETRY", "false");
|
||||||
bootstrapTelemetryFlag();
|
bootstrapTelemetryFlag();
|
||||||
expect((globalThis as any).__mem0_telemetry_override).toBe("false");
|
expect((globalThis as any).__mem0_telemetry_override).toBe("false");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("does not set globalThis override when MEM0_TELEMETRY is unset", () => {
|
it("does not set globalThis override when MEM0_TELEMETRY is unset", () => {
|
||||||
|
vi.stubEnv("MEM0_TELEMETRY", undefined as unknown as string);
|
||||||
bootstrapTelemetryFlag();
|
bootstrapTelemetryFlag();
|
||||||
expect((globalThis as any).__mem0_telemetry_override).toBeUndefined();
|
expect((globalThis as any).__mem0_telemetry_override).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("passes through truthy values", () => {
|
it("passes through truthy values", () => {
|
||||||
process.env.MEM0_TELEMETRY = "true";
|
vi.stubEnv("MEM0_TELEMETRY", "true");
|
||||||
bootstrapTelemetryFlag();
|
bootstrapTelemetryFlag();
|
||||||
expect((globalThis as any).__mem0_telemetry_override).toBe("true");
|
expect((globalThis as any).__mem0_telemetry_override).toBe("true");
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user