@memorilabs/openclaw-memori 0.0.1-beta → 0.0.1

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/README.md ADDED
@@ -0,0 +1,126 @@
1
+ [![Memori Labs](https://s3.us-east-1.amazonaws.com/images.memorilabs.ai/banner.png)](https://memorilabs.ai/)
2
+
3
+ <p align="center">
4
+ <strong>The memory fabric for enterprise AI</strong>
5
+ </p>
6
+
7
+ <p align="center">
8
+ <i>By default, OpenClaw agents forget everything between sessions. This plugin fixes that. It watches conversations, extracts what matters, and brings it back when relevant—automatically.</i>
9
+ </p>
10
+
11
+ <p align="center">
12
+ <a href="https://www.npmjs.com/package/@memorilabs/openclaw-memori">
13
+ <img src="https://img.shields.io/npm/v/@memorilabs/openclaw-memori.svg" alt="NPM version">
14
+ </a>
15
+ <a href="https://www.npmjs.com/package/@memorilabs/openclaw-memori">
16
+ <img src="https://img.shields.io/npm/dm/@memorilabs/openclaw-memori.svg" alt="NPM Downloads">
17
+ </a>
18
+ <a href="https://opensource.org/license/apache-2-0">
19
+ <img src="https://img.shields.io/badge/license-Apache%202.0-blue" alt="License">
20
+ </a>
21
+ <a href="https://discord.gg/abD4eGym6v">
22
+ <img src="https://img.shields.io/discord/1042405378304004156?logo=discord" alt="Discord">
23
+ </a>
24
+ </p>
25
+
26
+ ---
27
+
28
+ ## Key Features
29
+
30
+ - **Auto-Recall:** Before the agent responds, the plugin searches Memori for memories that match the current context and injects them directly into the prompt.
31
+ - **Auto-Capture:** After the agent responds, the plugin securely sends the exchange to Memori to extract new facts, update stale ones, and merge duplicates.
32
+ - **Bulletproof Sanitization:** Automatically strips OpenClaw system metadata, internal timestamps, and thinking blocks to prevent context pollution and feedback loops.
33
+ - **Stateless & Thread-Safe:** A completely stateless architecture ensures zero memory leaks and 100% thread safety for multi-agent OpenClaw gateways.
34
+
35
+ ## Getting Started
36
+
37
+ Run the following commands in your terminal to install and enable the plugin:
38
+
39
+ ```bash
40
+ # 1. Install the plugin from npm
41
+ openclaw plugins install @memorilabs/openclaw-memori
42
+
43
+ # 2. Enable it in your workspace
44
+ openclaw plugins enable openclaw-memori
45
+
46
+ # 3. Restart the OpenClaw gateway
47
+ openclaw gateway restart
48
+ ```
49
+
50
+ ## Configuration
51
+
52
+ The plugin needs your Memori API key and an Entity ID to function. You can configure this via the OpenClaw CLI, your `openclaw.json` file, or environment variables.
53
+
54
+ ### Option A: Via OpenClaw CLI (Recommended)
55
+
56
+ ```bash
57
+ openclaw config set plugins.entries.openclaw-memori.config.apiKey "YOUR_MEMORI_API_KEY"
58
+ openclaw config set plugins.entries.openclaw-memori.config.entityId "your-app-user-id"
59
+ ```
60
+
61
+ ### Option B: Via `openclaw.json`
62
+
63
+ Add the following to your `~/.openclaw/openclaw.json` file:
64
+
65
+ ```json
66
+ {
67
+ "plugins": {
68
+ "entries": {
69
+ "openclaw-memori": {
70
+ "enabled": true,
71
+ "config": {
72
+ "apiKey": "your-memori-api-key",
73
+ "entityId": "your-app-user-id"
74
+ }
75
+ }
76
+ }
77
+ }
78
+ }
79
+ ```
80
+
81
+ ### Configuration Options
82
+
83
+ | Option | Type | Required | Description |
84
+ | ---------- | -------- | -------- | --------------------------------------------------------------------------------------------------- |
85
+ | `apiKey` | `string` | **Yes** | Your Memori API key. |
86
+ | `entityId` | `string` | **Yes** | The unique identifier for the entity (e.g., user, agent, or tenant) to attribute these memories to. |
87
+
88
+ ## How It Works (The Hook Lifecycle)
89
+
90
+ This plugin integrates deeply with OpenClaw's event lifecycle to provide seamless memory without interfering with your agent's core logic:
91
+
92
+ 1. **`before_prompt_build` (Recall):** When a user sends a message, the plugin intercepts the event, queries the Memori API, and safely prepends relevant memories to the agent's system context.
93
+ 2. **`agent_end` (Capture):** Once the agent finishes generating its response, the plugin captures the final `user` and `assistant` messages, sanitizes them, and sends them to the Memori integration endpoint for long-term storage and entity mapping.
94
+
95
+ ## Contributing
96
+
97
+ We welcome contributions from the community! Please see our [Contributing Guidelines](https://github.com/MemoriLabs/Memori/blob/main/CONTRIBUTING.md) for details on code style, standards, and submitting pull requests.
98
+
99
+ To build from source:
100
+
101
+ ```bash
102
+ # Clone the repository
103
+ git clone https://github.com/memorilabs/openclaw-memori.git
104
+ cd openclaw-memori
105
+
106
+ # Install dependencies and build
107
+ npm install
108
+ npm run build
109
+
110
+ # Run formatting, linting, and type checking
111
+ npm run check
112
+ ```
113
+
114
+ ---
115
+
116
+ ## Support
117
+
118
+ - **Documentation**: [https://memorilabs.ai/docs](https://memorilabs.ai/docs)
119
+ - **Discord**: [https://discord.gg/abD4eGym6v](https://discord.gg/abD4eGym6v)
120
+ - **Issues**: [GitHub Issues](https://github.com/memorilabs/openclaw-memori/issues)
121
+
122
+ ---
123
+
124
+ ## License
125
+
126
+ Apache 2.0 - see [LICENSE](https://github.com/MemoriLabs/Memori/blob/main/LICENSE)
@@ -0,0 +1,11 @@
1
+ export declare const PLUGIN_CONFIG: {
2
+ readonly ID: "openclaw-memori";
3
+ readonly NAME: "Memori System";
4
+ readonly LOG_PREFIX: "[Memori]";
5
+ };
6
+ export declare const RECALL_CONFIG: {
7
+ readonly MIN_PROMPT_LENGTH: 2;
8
+ };
9
+ export declare const AUGMENTATION_CONFIG: {
10
+ readonly MAX_CONTEXT_MESSAGES: 5;
11
+ };
@@ -0,0 +1,11 @@
1
+ export const PLUGIN_CONFIG = {
2
+ ID: 'openclaw-memori',
3
+ NAME: 'Memori System',
4
+ LOG_PREFIX: '[Memori]',
5
+ };
6
+ export const RECALL_CONFIG = {
7
+ MIN_PROMPT_LENGTH: 2,
8
+ };
9
+ export const AUGMENTATION_CONFIG = {
10
+ MAX_CONTEXT_MESSAGES: 5,
11
+ };
@@ -0,0 +1,3 @@
1
+ import { OpenClawEvent, OpenClawContext, MemoriPluginConfig } from '../types.js';
2
+ import { MemoriLogger } from '../utils/index.js';
3
+ export declare function handleAugmentation(event: OpenClawEvent, ctx: OpenClawContext, config: MemoriPluginConfig, logger: MemoriLogger): Promise<void>;
@@ -0,0 +1,81 @@
1
+ import { extractContext, initializeMemoriClient } from '../utils/index.js';
2
+ import { cleanText, isSystemMessage } from '../sanitizer.js';
3
+ import { AUGMENTATION_CONFIG } from '../constants.js';
4
+ import { SDK_VERSION } from '../version.js';
5
+ function extractLLMMetadata(event) {
6
+ const messages = event.messages || [];
7
+ const lastAssistant = messages.findLast((m) => m.role === 'assistant');
8
+ return {
9
+ provider: lastAssistant?.provider || null,
10
+ model: lastAssistant?.model || null,
11
+ sdkVersion: null,
12
+ integrationSdkVersion: SDK_VERSION,
13
+ platform: 'openclaw',
14
+ };
15
+ }
16
+ export async function handleAugmentation(event, ctx, config, logger) {
17
+ logger.section('AUGMENTATION HOOK START');
18
+ if (!event.success || !event.messages || event.messages.length < 2) {
19
+ logger.info('No messages or unsuccessful event. Skipping augmentation.');
20
+ logger.endSection('AUGMENTATION HOOK END');
21
+ return;
22
+ }
23
+ try {
24
+ const recentMessages = event.messages.slice(-AUGMENTATION_CONFIG.MAX_CONTEXT_MESSAGES);
25
+ let lastUserMsg;
26
+ let lastAiMsg;
27
+ for (let i = recentMessages.length - 1; i >= 0; i--) {
28
+ const msg = recentMessages[i];
29
+ const role = msg.role;
30
+ if (role !== 'user' && role !== 'assistant')
31
+ continue;
32
+ const cleanedContent = cleanText(msg.content);
33
+ if (!cleanedContent)
34
+ continue;
35
+ let finalContent = cleanedContent;
36
+ if (role === 'assistant') {
37
+ finalContent = finalContent.replace(/^\[\[.*?\]\]\s*/, '');
38
+ }
39
+ if (role === 'assistant' && !lastAiMsg) {
40
+ lastAiMsg = { role, content: finalContent };
41
+ }
42
+ if (role === 'user' && !lastUserMsg) {
43
+ lastUserMsg = { role, content: finalContent };
44
+ }
45
+ if (lastUserMsg && lastAiMsg)
46
+ break;
47
+ }
48
+ if (!lastUserMsg || !lastAiMsg) {
49
+ logger.info('Missing user or assistant message. Skipping.');
50
+ logger.endSection('AUGMENTATION HOOK END');
51
+ return;
52
+ }
53
+ if (isSystemMessage(lastUserMsg.content)) {
54
+ logger.info('User message is a system message. Skipping augmentation.');
55
+ logger.endSection('AUGMENTATION HOOK END');
56
+ return;
57
+ }
58
+ if (lastAiMsg.content === 'NO_REPLY' || lastAiMsg.content === 'SILENT_REPLY') {
59
+ logger.info('Assistant used tool-based messaging. Using synthetic response.');
60
+ lastAiMsg = {
61
+ role: 'assistant',
62
+ content: "Okay, I'll remember that for you.",
63
+ };
64
+ }
65
+ const context = extractContext(event, ctx, config.entityId);
66
+ const memoriClient = initializeMemoriClient(config.apiKey, context);
67
+ const payload = {
68
+ userMessage: lastUserMsg.content,
69
+ agentResponse: lastAiMsg.content,
70
+ metadata: extractLLMMetadata(event),
71
+ };
72
+ await memoriClient.augmentation(payload);
73
+ logger.info('Augmentation successful!');
74
+ }
75
+ catch (err) {
76
+ logger.error(`Augmentation failed: ${err instanceof Error ? err.message : String(err)}`);
77
+ }
78
+ finally {
79
+ logger.endSection('AUGMENTATION HOOK END');
80
+ }
81
+ }
@@ -0,0 +1,5 @@
1
+ import { OpenClawEvent, OpenClawContext, MemoriPluginConfig } from '../types.js';
2
+ import { MemoriLogger } from '../utils/index.js';
3
+ export declare function handleRecall(event: OpenClawEvent, ctx: OpenClawContext, config: MemoriPluginConfig, logger: MemoriLogger): Promise<{
4
+ prependContext: string;
5
+ } | undefined>;
@@ -0,0 +1,34 @@
1
+ import { cleanText, isSystemMessage } from '../sanitizer.js';
2
+ import { RECALL_CONFIG } from '../constants.js';
3
+ import { extractContext, initializeMemoriClient } from '../utils/index.js';
4
+ export async function handleRecall(event, ctx, config, logger) {
5
+ logger.section('RECALL HOOK START');
6
+ try {
7
+ const context = extractContext(event, ctx, config.entityId);
8
+ const promptText = cleanText(event.prompt);
9
+ if (!promptText ||
10
+ promptText.length < RECALL_CONFIG.MIN_PROMPT_LENGTH ||
11
+ isSystemMessage(promptText)) {
12
+ logger.info('Prompt too short or is a system message. Aborting recall.');
13
+ return undefined;
14
+ }
15
+ const memoriClient = initializeMemoriClient(config.apiKey, context);
16
+ logger.info('Executing SDK Recall...');
17
+ const recallText = await memoriClient.recall(promptText);
18
+ const hookReturn = recallText ? { prependContext: recallText } : undefined;
19
+ if (hookReturn) {
20
+ logger.info('Successfully injected memory context.');
21
+ }
22
+ else {
23
+ logger.info('No relevant memories found.');
24
+ }
25
+ return hookReturn;
26
+ }
27
+ catch (err) {
28
+ logger.error(`Recall failed: ${err instanceof Error ? err.message : String(err)}`);
29
+ return undefined;
30
+ }
31
+ finally {
32
+ logger.endSection('RECALL HOOK END');
33
+ }
34
+ }
@@ -0,0 +1,8 @@
1
+ import type { OpenClawPluginApi } from 'openclaw/plugin-sdk';
2
+ declare const memoriPlugin: {
3
+ id: "openclaw-memori";
4
+ name: "Memori System";
5
+ description: string;
6
+ register(api: OpenClawPluginApi): void;
7
+ };
8
+ export default memoriPlugin;
package/dist/index.js ADDED
@@ -0,0 +1,26 @@
1
+ import { handleRecall } from './handlers/recall.js';
2
+ import { handleAugmentation } from './handlers/augmentation.js';
3
+ import { PLUGIN_CONFIG } from './constants.js';
4
+ import { MemoriLogger } from './utils/index.js';
5
+ const memoriPlugin = {
6
+ id: PLUGIN_CONFIG.ID,
7
+ name: PLUGIN_CONFIG.NAME,
8
+ description: 'Hosted memory backend',
9
+ register(api) {
10
+ const rawConfig = api.pluginConfig;
11
+ const config = {
12
+ apiKey: rawConfig?.apiKey,
13
+ entityId: rawConfig?.entityId,
14
+ };
15
+ if (!config.apiKey || !config.entityId) {
16
+ api.logger.warn(`${PLUGIN_CONFIG.LOG_PREFIX} Missing apiKey or entityId in config. Plugin disabled.`);
17
+ return;
18
+ }
19
+ const logger = new MemoriLogger(api);
20
+ logger.info(`\n=== ${PLUGIN_CONFIG.LOG_PREFIX} INITIALIZING PLUGIN ===`);
21
+ logger.info(`${PLUGIN_CONFIG.LOG_PREFIX} Tracking Entity ID: ${config.entityId}`);
22
+ api.on('before_prompt_build', (event, ctx) => handleRecall(event, ctx, config, logger));
23
+ api.on('agent_end', (event, ctx) => handleAugmentation(event, ctx, config, logger));
24
+ },
25
+ };
26
+ export default memoriPlugin;
@@ -0,0 +1,2 @@
1
+ export declare function isSystemMessage(text: string): boolean;
2
+ export declare function cleanText(rawContent: unknown): string;
@@ -0,0 +1,59 @@
1
+ const SYSTEM_MESSAGE_PATTERNS = [
2
+ 'a new session was started',
3
+ '/new or /reset',
4
+ 'session startup sequence',
5
+ 'use persona',
6
+ ];
7
+ const TIMESTAMP_PREFIX_REGEX = /^\[[A-Z][a-z]{2}\s+\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}\s+[A-Z]{2,4}\]\s*/;
8
+ function isMessageBlockArray(value) {
9
+ return Array.isArray(value) && value.every((item) => item !== null && typeof item === 'object');
10
+ }
11
+ export function isSystemMessage(text) {
12
+ if (!text)
13
+ return true;
14
+ const lowerText = text.toLowerCase();
15
+ return SYSTEM_MESSAGE_PATTERNS.some((pattern) => lowerText.includes(pattern));
16
+ }
17
+ /**
18
+ * Extracts the actual user message from OpenClaw's formatted content.
19
+ *
20
+ * OpenClaw wraps metadata in markdown code fences (triple tick).
21
+ * The actual message is always after the LAST closing fence.
22
+ * The message might aslo contain a timestamp prefix like: [Day YYYY-MM-DD HH:MM TZ], that will need to be removed
23
+ */
24
+ function extractRawUserMessage(content) {
25
+ let message = content;
26
+ if (message.includes('```')) {
27
+ const lastFenceIndex = message.lastIndexOf('```');
28
+ if (lastFenceIndex !== -1) {
29
+ message = message.substring(lastFenceIndex + 3).trim();
30
+ }
31
+ }
32
+ const timestampMatch = message.match(TIMESTAMP_PREFIX_REGEX);
33
+ if (timestampMatch) {
34
+ message = message.substring(timestampMatch[0].length).trim();
35
+ }
36
+ return message;
37
+ }
38
+ function extractMessageText(content) {
39
+ if (!content)
40
+ return '';
41
+ if (typeof content === 'string') {
42
+ return content;
43
+ }
44
+ if (isMessageBlockArray(content)) {
45
+ return content
46
+ .filter((block) => (block.type === 'text' || typeof block.text === 'string') && block.text)
47
+ .map((block) => block.text)
48
+ .join('\n\n');
49
+ }
50
+ return '';
51
+ }
52
+ export function cleanText(rawContent) {
53
+ let text = extractMessageText(rawContent);
54
+ if (!text)
55
+ return '';
56
+ text = extractRawUserMessage(text);
57
+ text = text.replace(/<memori_context>[\s\S]*?<\/memori_context>\s*/g, '');
58
+ return text.trim();
59
+ }
@@ -0,0 +1,34 @@
1
+ export interface MemoriPluginConfig {
2
+ apiKey: string;
3
+ entityId: string;
4
+ }
5
+ export interface OpenClawMessageBlock {
6
+ type?: string;
7
+ text?: string;
8
+ thinking?: string;
9
+ [key: string]: unknown;
10
+ }
11
+ export interface OpenClawMessage {
12
+ role: 'user' | 'assistant' | 'system';
13
+ content: string | OpenClawMessageBlock[];
14
+ timestamp?: number;
15
+ [key: string]: unknown;
16
+ }
17
+ export interface OpenClawEvent {
18
+ prompt?: string;
19
+ messages?: OpenClawMessage[];
20
+ completion?: string;
21
+ success?: boolean;
22
+ error?: string;
23
+ durationMs?: number;
24
+ userId?: string;
25
+ sessionId?: string;
26
+ messageProvider?: string;
27
+ }
28
+ export interface OpenClawContext {
29
+ agentId?: string;
30
+ sessionKey?: string;
31
+ sessionId?: string;
32
+ workspaceDir?: string;
33
+ messageProvider?: string;
34
+ }
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,20 @@
1
+ import { OpenClawEvent, OpenClawContext } from '../types.js';
2
+ /**
3
+ * Extracted context information from OpenClaw events
4
+ */
5
+ export interface ExtractedContext {
6
+ entityId: string;
7
+ sessionId: string;
8
+ provider: string;
9
+ }
10
+ /**
11
+ * Extracts and normalizes context information from OpenClaw event and context objects.
12
+ * Throws an error if required context fields cannot be resolved.
13
+ *
14
+ * @param event - OpenClaw event object
15
+ * @param ctx - OpenClaw context object
16
+ * @param configuredEntityId - Hardcoded entity ID from plugin config
17
+ * @returns Normalized context with entityId, sessionId, and provider
18
+ * @throws Error If entityId, sessionId, or provider cannot be determined
19
+ */
20
+ export declare function extractContext(event: OpenClawEvent, ctx: OpenClawContext, configuredEntityId: string): ExtractedContext;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Extracts and normalizes context information from OpenClaw event and context objects.
3
+ * Throws an error if required context fields cannot be resolved.
4
+ *
5
+ * @param event - OpenClaw event object
6
+ * @param ctx - OpenClaw context object
7
+ * @param configuredEntityId - Hardcoded entity ID from plugin config
8
+ * @returns Normalized context with entityId, sessionId, and provider
9
+ * @throws Error If entityId, sessionId, or provider cannot be determined
10
+ */
11
+ export function extractContext(event, ctx, configuredEntityId) {
12
+ const sessionId = ctx.sessionKey || event.sessionId;
13
+ const provider = ctx.messageProvider || event.messageProvider;
14
+ if (!sessionId) {
15
+ throw new Error('Failed to extract context: Missing sessionId in OpenClaw context and event.');
16
+ }
17
+ if (!provider) {
18
+ throw new Error('Failed to extract context: Missing message provider in OpenClaw context and event.');
19
+ }
20
+ return {
21
+ entityId: configuredEntityId,
22
+ sessionId,
23
+ provider,
24
+ };
25
+ }
@@ -0,0 +1,3 @@
1
+ export { extractContext, type ExtractedContext } from './context.js';
2
+ export { MemoriLogger } from './logger.js';
3
+ export { initializeMemoriClient } from './memori-client.js';
@@ -0,0 +1,3 @@
1
+ export { extractContext } from './context.js';
2
+ export { MemoriLogger } from './logger.js';
3
+ export { initializeMemoriClient } from './memori-client.js';
@@ -0,0 +1,11 @@
1
+ import type { OpenClawPluginApi } from 'openclaw/plugin-sdk';
2
+ export declare class MemoriLogger {
3
+ private api;
4
+ constructor(api: OpenClawPluginApi);
5
+ private prefix;
6
+ info(message: string): void;
7
+ warn(message: string): void;
8
+ error(message: string): void;
9
+ section(title: string): void;
10
+ endSection(title: string): void;
11
+ }
@@ -0,0 +1,25 @@
1
+ import { PLUGIN_CONFIG } from '../constants.js';
2
+ export class MemoriLogger {
3
+ api;
4
+ constructor(api) {
5
+ this.api = api;
6
+ }
7
+ prefix(msg) {
8
+ return `${PLUGIN_CONFIG.LOG_PREFIX} ${msg}`;
9
+ }
10
+ info(message) {
11
+ this.api.logger.info(this.prefix(message));
12
+ }
13
+ warn(message) {
14
+ this.api.logger.warn(this.prefix(message));
15
+ }
16
+ error(message) {
17
+ this.api.logger.error(this.prefix(message));
18
+ }
19
+ section(title) {
20
+ this.api.logger.info(`\n=== ${this.prefix(title)} ===`);
21
+ }
22
+ endSection(title) {
23
+ this.api.logger.info(`=== ${this.prefix(title)} ===\n`);
24
+ }
25
+ }
@@ -0,0 +1,10 @@
1
+ import { OpenClawIntegration } from '@memorilabs/memori/integrations';
2
+ import { ExtractedContext } from './context.js';
3
+ /**
4
+ * Initializes and configures a Memori OpenClaw integration instance
5
+ *
6
+ * @param apiKey - Memori API key
7
+ * @param context - Extracted context information
8
+ * @returns Configured OpenClawIntegration instance
9
+ */
10
+ export declare function initializeMemoriClient(apiKey: string, context: ExtractedContext): OpenClawIntegration;
@@ -0,0 +1,17 @@
1
+ import { Memori } from '@memorilabs/memori';
2
+ import { OpenClawIntegration } from '@memorilabs/memori/integrations';
3
+ /**
4
+ * Initializes and configures a Memori OpenClaw integration instance
5
+ *
6
+ * @param apiKey - Memori API key
7
+ * @param context - Extracted context information
8
+ * @returns Configured OpenClawIntegration instance
9
+ */
10
+ export function initializeMemoriClient(apiKey, context) {
11
+ const memori = new Memori();
12
+ memori.config.apiKey = apiKey;
13
+ const openclaw = memori.integrate(OpenClawIntegration);
14
+ openclaw.setAttribution(context.entityId, context.provider);
15
+ openclaw.setSession(context.sessionId);
16
+ return openclaw;
17
+ }
@@ -0,0 +1 @@
1
+ export declare const SDK_VERSION = "0.0.1";
@@ -0,0 +1 @@
1
+ export const SDK_VERSION = '0.0.1';
@@ -0,0 +1,37 @@
1
+ {
2
+ "id": "openclaw-memori",
3
+ "name": "Memori System",
4
+ "version": "0.0.1-beta",
5
+ "description": "Hosted memory backend",
6
+ "kind": "memory",
7
+ "main": "dist/index.js",
8
+ "uiHints": {
9
+ "apiKey": {
10
+ "label": "Memori API Key",
11
+ "sensitive": true,
12
+ "placeholder": "Enter your Memori API key...",
13
+ "help": "API key from memorilabs.ai (or use MEMORI_API_KEY env var)"
14
+ },
15
+ "entityId": {
16
+ "label": "Entity ID",
17
+ "placeholder": "e.g., your-app-user-id",
18
+ "help": "Required. The unique identifier to attribute these memories to."
19
+ }
20
+ },
21
+ "configSchema": {
22
+ "type": "object",
23
+ "properties": {
24
+ "apiKey": {
25
+ "type": "string",
26
+ "title": "API Key",
27
+ "description": "Memori API Key"
28
+ },
29
+ "entityId": {
30
+ "type": "string",
31
+ "title": "Entity ID",
32
+ "description": "Required. Hardcode a specific Entity ID for memories."
33
+ }
34
+ },
35
+ "required": []
36
+ }
37
+ }
package/package.json CHANGED
@@ -1,7 +1,71 @@
1
1
  {
2
2
  "name": "@memorilabs/openclaw-memori",
3
- "version": "0.0.1-beta",
4
- "private": false,
5
- "publishConfig": { "access": "public" }
3
+ "version": "0.0.1",
4
+ "description": "Official MemoriLabs.ai long-term memory plugin for OpenClaw",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "files": [
9
+ "dist",
10
+ "openclaw.plugin.json"
11
+ ],
12
+ "scripts": {
13
+ "build": "tsc",
14
+ "build:dev": "tsc --watch",
15
+ "typecheck": "tsc --noEmit",
16
+ "lint": "eslint .",
17
+ "lint:fix": "eslint . --fix",
18
+ "format": "prettier --write .",
19
+ "format:check": "prettier --check .",
20
+ "check": "npm run format:check && npm run lint && npm run typecheck",
21
+ "test": "vitest run",
22
+ "test:coverage": "vitest run --coverage"
23
+ },
24
+ "peerDependencies": {
25
+ "openclaw": "^2026.3.2"
26
+ },
27
+ "devDependencies": {
28
+ "@eslint/js": "^9.0.0",
29
+ "@types/node": "^20.0.0",
30
+ "@vitest/coverage-v8": "^4.0.18",
31
+ "eslint": "^9.0.0",
32
+ "eslint-config-prettier": "^10.1.8",
33
+ "eslint-plugin-tsdoc": "^0.5.1",
34
+ "prettier": "^3.0.0",
35
+ "typescript": "^5.0.0",
36
+ "typescript-eslint": "^8.0.0",
37
+ "vitest": "^4.0.18"
38
+ },
39
+ "keywords": [
40
+ "openclaw",
41
+ "plugin",
42
+ "memory",
43
+ "memori",
44
+ "long-term-memory"
45
+ ],
46
+ "author": "Memori Labs",
47
+ "license": "Apache-2.0",
48
+ "repository": {
49
+ "type": "git",
50
+ "url": "https://github.com/MemoriLabs/Memori.git",
51
+ "directory": "integrations/openclaw"
52
+ },
53
+ "bugs": {
54
+ "url": "https://github.com/MemoriLabs/Memori/issues"
55
+ },
56
+ "homepage": "https://github.com/MemoriLabs/Memori",
57
+ "openclaw": {
58
+ "extensions": [
59
+ "./dist/index.js"
60
+ ]
61
+ },
62
+ "engines": {
63
+ "node": ">=22.0.0"
64
+ },
65
+ "dependencies": {
66
+ "@memorilabs/memori": "^0.0.5"
67
+ },
68
+ "overrides": {
69
+ "@hono/node-server": "^1.19.10"
70
+ }
6
71
  }
7
-