@evermind-ai/openclaw-plugin 1.1.0 → 1.3.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/README.md +98 -328
- package/README.zh.md +98 -328
- package/SKILL.md +333 -0
- package/bin/install.js +354 -0
- package/index.js +152 -61
- package/openclaw.plugin.json +8 -8
- package/package.json +7 -2
- package/src/assembler.js +6 -6
- package/src/config.js +2 -2
- package/src/formatter.js +1 -1
- package/src/http-client.js +2 -1
- package/src/memory-api.js +18 -22
- package/src/subagent.js +3 -3
- package/src/compaction.js +0 -85
- package/src/context-engine.js +0 -283
- package/src/lifecycle.js +0 -65
package/README.md
CHANGED
|
@@ -1,152 +1,115 @@
|
|
|
1
|
-
#
|
|
1
|
+
# EverOS OpenClaw Plugin
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Persistent memory for **OpenClaw** through normal conversation.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
This plugin keeps the current OpenClaw `context-engine` architecture and connects it to a self-hosted EverOS backend powered by [EverMemOS](https://github.com/EverMind-AI/EverMemOS).
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## What it does
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
- Recalls relevant memory before each reply through `assemble()`
|
|
10
|
+
- Saves new conversation content after each turn through `afterTurn()`
|
|
11
|
+
- Works through normal natural-language chat
|
|
12
|
+
- Does not require manual `memory_store` or `memory_search` tool calls
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
- **Assemble**: Query-aware context retrieval before each agent turn
|
|
13
|
-
- **AfterTurn**: Timely memory extraction after each turn (not just session end)
|
|
14
|
-
- **Compact**: Session compaction participation for context window optimization
|
|
15
|
-
- **Boundary Detection**: Smart memory extraction via EverMemOS's boundary detection algorithm
|
|
14
|
+
Important:
|
|
16
15
|
|
|
17
|
-
|
|
16
|
+
- This is a `context-engine` plugin
|
|
17
|
+
- This is not a `memory` slot plugin like official `mem9`
|
|
18
|
+
- To avoid conflicts, installation sets `plugins.slots.memory = "none"`
|
|
18
19
|
|
|
19
|
-
## Quick
|
|
20
|
+
## Quick start
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
| Requirement | Version | Notes |
|
|
24
|
-
|-------------|---------|-------|
|
|
25
|
-
| **Node.js** | 18+ | For the plugin |
|
|
26
|
-
| **Python** | 3.10+ | For EverMemOS backend |
|
|
27
|
-
| **Docker** | 20.10+ | For infrastructure services |
|
|
28
|
-
| **OpenClaw** | 3.8+ | With ContextEngine support |
|
|
29
|
-
|
|
30
|
-
---
|
|
31
|
-
|
|
32
|
-
## Step 1: Install EverMemOS Backend
|
|
33
|
-
|
|
34
|
-
### Clone and Setup
|
|
22
|
+
Recommended install:
|
|
35
23
|
|
|
36
24
|
```bash
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
cd EverMemOS
|
|
40
|
-
|
|
41
|
-
# Start Docker services (MongoDB, Elasticsearch, Milvus, Redis)
|
|
42
|
-
docker compose up -d
|
|
25
|
+
npx --yes --package @evermind-ai/openclaw-plugin everos-install
|
|
26
|
+
```
|
|
43
27
|
|
|
44
|
-
|
|
45
|
-
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
28
|
+
The installer:
|
|
46
29
|
|
|
47
|
-
|
|
48
|
-
|
|
30
|
+
- reuses `~/.openclaw/openclaw.json` if it already exists
|
|
31
|
+
- adds the plugin path to `plugins.load.paths`
|
|
32
|
+
- adds `@evermind-ai/openclaw-plugin` to `plugins.allow`
|
|
33
|
+
- sets `plugins.slots.contextEngine = "@evermind-ai/openclaw-plugin"`
|
|
34
|
+
- sets `plugins.slots.memory = "none"`
|
|
35
|
+
- creates or updates the plugin entry with sane defaults
|
|
49
36
|
|
|
50
|
-
|
|
51
|
-
cp env.template .env
|
|
52
|
-
# Edit .env and set your LLM_API_KEY and VECTORIZE_API_KEY
|
|
37
|
+
After install:
|
|
53
38
|
|
|
54
|
-
|
|
55
|
-
|
|
39
|
+
```bash
|
|
40
|
+
openclaw gateway restart
|
|
56
41
|
```
|
|
57
42
|
|
|
58
|
-
|
|
43
|
+
Then verify with natural language:
|
|
59
44
|
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
|
|
45
|
+
```text
|
|
46
|
+
Remember: I like espresso.
|
|
47
|
+
What coffee do I like?
|
|
63
48
|
```
|
|
64
49
|
|
|
65
|
-
|
|
50
|
+
## Backend
|
|
66
51
|
|
|
67
|
-
|
|
52
|
+
Default backend URL:
|
|
68
53
|
|
|
69
|
-
|
|
54
|
+
```text
|
|
55
|
+
http://localhost:1995
|
|
56
|
+
```
|
|
70
57
|
|
|
71
|
-
|
|
58
|
+
Health check:
|
|
72
59
|
|
|
73
60
|
```bash
|
|
74
|
-
|
|
75
|
-
git clone https://github.com/EverMind-AI/evermemos-openclaw-plugin.git
|
|
76
|
-
cd evermemos-openclaw-plugin
|
|
77
|
-
|
|
78
|
-
# Install dependencies
|
|
79
|
-
npm install
|
|
61
|
+
curl http://localhost:1995/health
|
|
80
62
|
```
|
|
81
63
|
|
|
82
|
-
|
|
64
|
+
If you have not started the EverOS backend yet:
|
|
83
65
|
|
|
84
66
|
```bash
|
|
85
|
-
|
|
67
|
+
git clone https://github.com/EverMind-AI/EverMemOS.git
|
|
68
|
+
cd EverMemOS
|
|
69
|
+
docker compose up -d
|
|
70
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
71
|
+
uv sync
|
|
72
|
+
cp env.template .env
|
|
73
|
+
# edit .env
|
|
74
|
+
uv run python src/run.py
|
|
86
75
|
```
|
|
87
76
|
|
|
88
|
-
|
|
77
|
+
## How natural-language memory works
|
|
89
78
|
|
|
90
|
-
|
|
79
|
+
Runtime flow:
|
|
91
80
|
|
|
92
|
-
|
|
81
|
+
1. The user sends a normal message.
|
|
82
|
+
2. `assemble()` searches the EverOS backend for relevant memory.
|
|
83
|
+
3. Matching memory is injected as context.
|
|
84
|
+
4. OpenClaw replies normally.
|
|
85
|
+
5. `afterTurn()` saves the new turn back to the EverOS backend.
|
|
93
86
|
|
|
94
|
-
|
|
87
|
+
This means the user experience is:
|
|
95
88
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
"plugins": {
|
|
99
|
-
"load": {
|
|
100
|
-
"paths": [
|
|
101
|
-
"/path/to/openclaw/extensions/feishu",
|
|
102
|
-
"/path/to/openclaw/extensions/memory-openviking",
|
|
103
|
-
"/Users/admin/EverMind/evermemos-openclaw-plugin" // Add this line
|
|
104
|
-
]
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
```
|
|
89
|
+
- "Remember: I prefer dark mode"
|
|
90
|
+
- later: "What UI style do I prefer?"
|
|
109
91
|
|
|
110
|
-
|
|
92
|
+
without any explicit memory tool usage.
|
|
111
93
|
|
|
112
|
-
|
|
113
|
-
{
|
|
114
|
-
"plugins": {
|
|
115
|
-
"allow": [
|
|
116
|
-
"memory-openviking",
|
|
117
|
-
"feishu",
|
|
118
|
-
"mem9",
|
|
119
|
-
"evermemos-openclaw-plugin" // Add this line
|
|
120
|
-
]
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
```
|
|
94
|
+
## OpenClaw config
|
|
124
95
|
|
|
125
|
-
|
|
96
|
+
Expected config shape:
|
|
126
97
|
|
|
127
98
|
```json
|
|
128
99
|
{
|
|
129
100
|
"plugins": {
|
|
101
|
+
"allow": ["@evermind-ai/openclaw-plugin"],
|
|
130
102
|
"slots": {
|
|
131
103
|
"memory": "none",
|
|
132
|
-
"contextEngine": "
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
### 3.4 Add Plugin Configuration
|
|
139
|
-
|
|
140
|
-
```json
|
|
141
|
-
{
|
|
142
|
-
"plugins": {
|
|
104
|
+
"contextEngine": "@evermind-ai/openclaw-plugin"
|
|
105
|
+
},
|
|
143
106
|
"entries": {
|
|
144
|
-
"
|
|
107
|
+
"@evermind-ai/openclaw-plugin": {
|
|
145
108
|
"enabled": true,
|
|
146
109
|
"config": {
|
|
147
110
|
"baseUrl": "http://localhost:1995",
|
|
148
|
-
"userId": "
|
|
149
|
-
"groupId": "
|
|
111
|
+
"userId": "everos-user",
|
|
112
|
+
"groupId": "everos-group",
|
|
150
113
|
"topK": 5,
|
|
151
114
|
"memoryTypes": ["episodic_memory", "profile", "agent_skill", "agent_case"],
|
|
152
115
|
"retrieveMethod": "hybrid"
|
|
@@ -157,243 +120,50 @@ Edit `~/.openclaw/openclaw.json`:
|
|
|
157
120
|
}
|
|
158
121
|
```
|
|
159
122
|
|
|
160
|
-
---
|
|
161
|
-
|
|
162
|
-
## Step 4: Restart OpenClaw
|
|
163
|
-
|
|
164
|
-
```bash
|
|
165
|
-
openclaw gateway restart
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
---
|
|
169
|
-
|
|
170
|
-
## Step 5: Verify Installation
|
|
171
|
-
|
|
172
|
-
Check the OpenClaw logs for successful plugin loading:
|
|
173
|
-
|
|
174
|
-
```
|
|
175
|
-
[evermemos] Registering EverMemOS ContextEngine plugin
|
|
176
|
-
[evermemos] bootstrap: session=xxx, key=xxx
|
|
177
|
-
[evermemos] bootstrap: backend healthy, status=ok
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
---
|
|
181
|
-
|
|
182
|
-
## Testing
|
|
183
|
-
|
|
184
|
-
### Test Memory Storage
|
|
185
|
-
|
|
186
|
-
Send a message to your agent:
|
|
187
|
-
```
|
|
188
|
-
记住:我最喜欢的颜色是蓝色
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
### Test Memory Retrieval
|
|
192
|
-
|
|
193
|
-
Later in the conversation, ask:
|
|
194
|
-
```
|
|
195
|
-
我最喜欢什么颜色?
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
The agent should recall the information from EverMemOS.
|
|
199
|
-
|
|
200
|
-
---
|
|
201
|
-
|
|
202
123
|
## Configuration
|
|
203
124
|
|
|
204
|
-
|
|
|
205
|
-
|
|
206
|
-
| `baseUrl` |
|
|
207
|
-
| `userId` |
|
|
208
|
-
| `groupId` |
|
|
209
|
-
| `topK` |
|
|
210
|
-
| `memoryTypes` |
|
|
211
|
-
| `retrieveMethod` |
|
|
212
|
-
|
|
213
|
-
### Memory Types
|
|
214
|
-
|
|
215
|
-
| Value | Description |
|
|
216
|
-
|-------|-------------|
|
|
217
|
-
| `episodic_memory` | Past conversation episodes |
|
|
218
|
-
| `profile` | User profile and preferences |
|
|
219
|
-
| `agent_case` | Similar historical cases |
|
|
220
|
-
| `agent_skill` | Agent skill knowledge |
|
|
221
|
-
|
|
222
|
-
### Retrieval Strategies
|
|
125
|
+
| Field | Default | Description |
|
|
126
|
+
| --- | --- | --- |
|
|
127
|
+
| `baseUrl` | `http://localhost:1995` | EverOS backend URL |
|
|
128
|
+
| `userId` | `everos-user` | Memory owner identity |
|
|
129
|
+
| `groupId` | `everos-group` | Shared memory namespace |
|
|
130
|
+
| `topK` | `5` | Max retrieved entries |
|
|
131
|
+
| `memoryTypes` | `["episodic_memory", "profile", "agent_skill", "agent_case"]` | Memory types to search |
|
|
132
|
+
| `retrieveMethod` | `hybrid` | Retrieval mode |
|
|
223
133
|
|
|
224
|
-
|
|
225
|
-
|-------|-------------|
|
|
226
|
-
| `keyword` | Full-text keyword search |
|
|
227
|
-
| `vector` | Semantic vector search |
|
|
228
|
-
| `hybrid` | Keyword + vector fusion |
|
|
229
|
-
| `rrf` | Reciprocal Rank Fusion |
|
|
230
|
-
| `agentic` | Agent-driven adaptive retrieval |
|
|
134
|
+
## Manual install
|
|
231
135
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
```
|
|
237
|
-
┌─────────────────────────────────────────────────────────────────┐
|
|
238
|
-
│ OpenClaw Core │
|
|
239
|
-
│ ┌─────────────┐ ┌──────────────┐ ┌─────────────────────────┐ │
|
|
240
|
-
│ │ Message │ │ Session │ │ Token Budget Mgmt │ │
|
|
241
|
-
│ │ Flow │ │ Management │ │ (Compaction) │ │
|
|
242
|
-
│ └──────┬──────┘ └──────┬───────┘ └──────────┬──────────────┘ │
|
|
243
|
-
└─────────┼────────────────┼─────────────────────┼────────────────┘
|
|
244
|
-
│ │ │
|
|
245
|
-
▼ ▼ ▼
|
|
246
|
-
┌─────────────────────────────────────────────────────────────────┐
|
|
247
|
-
│ EverMemOS ContextEngine │
|
|
248
|
-
│ ┌─────────┐ ┌─────────┐ ┌──────────┐ ┌──────────────────┐ │
|
|
249
|
-
│ │bootstrap│ │ ingest │ │afterTurn │ │ assemble │ │
|
|
250
|
-
│ └────┬────┘ └────┬────┘ └────┬─────┘ └────────┬─────────┘ │
|
|
251
|
-
└───────┼─────────────┼─────────────┼─────────────────┼─────────────┘
|
|
252
|
-
│ │ │ │
|
|
253
|
-
▼ ▼ ▼ ▼
|
|
254
|
-
┌─────────────────────────────────────────────────────────────────┐
|
|
255
|
-
│ EverMemOS Backend │
|
|
256
|
-
│ http://localhost:1995 │
|
|
257
|
-
│ │
|
|
258
|
-
│ • Boundary Detection • Memory Extraction • Vector Search │
|
|
259
|
-
│ • Profile Building • Clustering • Foresight │
|
|
260
|
-
└─────────────────────────────────────────────────────────────────┘
|
|
136
|
+
```bash
|
|
137
|
+
npm install -g @evermind-ai/openclaw-plugin
|
|
138
|
+
everos-install
|
|
261
139
|
```
|
|
262
140
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
## OpenClaw 3.8+ ContextEngine API
|
|
266
|
-
|
|
267
|
-
This plugin leverages OpenClaw 3.8's **ContextEngine API** for fine-grained lifecycle control:
|
|
268
|
-
|
|
269
|
-
| Lifecycle Hook | When Called | What Plugin Does |
|
|
270
|
-
|----------------|-------------|------------------|
|
|
271
|
-
| `bootstrap()` | Session starts | Health check, initialize state |
|
|
272
|
-
| `assemble()` | Before each agent turn | Retrieve relevant memories, inject as context |
|
|
273
|
-
| `afterTurn()` | After each agent turn | Save new messages to EverMemOS |
|
|
274
|
-
| `compact()` | When token budget exceeded | Evaluate compaction needs |
|
|
275
|
-
| `dispose()` | Session ends | Clean up session state |
|
|
276
|
-
|
|
277
|
-
### Difference from Legacy Memory Plugins
|
|
278
|
-
|
|
279
|
-
| Legacy Memory Hook | ContextEngine API |
|
|
280
|
-
|--------------------|-------------------|
|
|
281
|
-
| Simple storage/retrieval | Full lifecycle management |
|
|
282
|
-
| Automatic timing | Controlled timing |
|
|
283
|
-
| Limited context control | Query-aware assembly |
|
|
284
|
-
|
|
285
|
-
---
|
|
286
|
-
|
|
287
|
-
## Lifecycle Flow
|
|
141
|
+
Or from a local checkout:
|
|
288
142
|
|
|
143
|
+
```bash
|
|
144
|
+
git clone https://github.com/EverMind-AI/evermemos-openclaw-plugin.git
|
|
145
|
+
cd evermemos-openclaw-plugin
|
|
146
|
+
npm install
|
|
147
|
+
node ./bin/install.js
|
|
289
148
|
```
|
|
290
|
-
┌──────────────┐
|
|
291
|
-
│ bootstrap() │ → Health check, initialize session state
|
|
292
|
-
└──────┬───────┘
|
|
293
|
-
│
|
|
294
|
-
▼
|
|
295
|
-
┌──────────────┐ ┌──────────────────┐
|
|
296
|
-
│ assemble() │ ── │ Memory Search │ → Inject context as system message
|
|
297
|
-
│ (each turn) │ │ GET /memories/ │
|
|
298
|
-
└──────┬───────┘ │ search │
|
|
299
|
-
│ └──────────────────┘
|
|
300
|
-
▼
|
|
301
|
-
┌──────────────────┐
|
|
302
|
-
│ [Agent Turn] │
|
|
303
|
-
└──────┬───────────┘
|
|
304
|
-
│
|
|
305
|
-
▼
|
|
306
|
-
┌──────────────┐ ┌──────────────────┐
|
|
307
|
-
│ afterTurn() │ ── │ Save Memories │ → POST /memories
|
|
308
|
-
│ (each turn) │ │ Boundary Detect │
|
|
309
|
-
└──────┬───────┘ └──────────────────┘
|
|
310
|
-
│
|
|
311
|
-
▼
|
|
312
|
-
┌──────────────┐
|
|
313
|
-
│ compact() │ → Evaluate if compaction needed
|
|
314
|
-
└──────────────┘
|
|
315
|
-
```
|
|
316
|
-
|
|
317
|
-
---
|
|
318
149
|
|
|
319
150
|
## Troubleshooting
|
|
320
151
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
2. Check `baseUrl` configuration matches backend URL
|
|
337
|
-
3. Check firewall/network settings
|
|
338
|
-
|
|
339
|
-
### Memories not being saved
|
|
340
|
-
|
|
341
|
-
**Symptom**: No memory extraction in backend logs
|
|
342
|
-
|
|
343
|
-
**Solution**:
|
|
344
|
-
1. Verify `plugins.slots.contextEngine` is set to `"evermemos-openclaw-plugin"`
|
|
345
|
-
2. Send more messages - EverMemOS uses boundary detection and needs sufficient context
|
|
346
|
-
3. Check backend logs for `[Boundary Detection]` messages
|
|
347
|
-
|
|
348
|
-
### Memories not being retrieved
|
|
349
|
-
|
|
350
|
-
**Symptom**: Agent doesn't recall previous information
|
|
351
|
-
|
|
352
|
-
**Solution**:
|
|
353
|
-
1. Verify memories were extracted (check backend logs for "Successfully extracted MemCell")
|
|
354
|
-
2. Check query length is ≥ 3 characters
|
|
355
|
-
3. Increase `topK` value to retrieve more memories
|
|
356
|
-
4. Try different `retrieveMethod` (e.g., `hybrid` or `agentic`)
|
|
357
|
-
|
|
358
|
-
### Vector service errors
|
|
359
|
-
|
|
360
|
-
**Symptom**: `VllmVectorizeService API error: 502`
|
|
361
|
-
|
|
362
|
-
**Solution**: This is normal - EverMemOS automatically falls back to alternative embedding services. Memory extraction continues working.
|
|
363
|
-
|
|
364
|
-
---
|
|
365
|
-
|
|
366
|
-
## Project Structure
|
|
367
|
-
|
|
368
|
-
```
|
|
369
|
-
├── index.js # ContextEngine factory & main entry
|
|
370
|
-
├── package.json
|
|
371
|
-
├── openclaw.plugin.json # Plugin metadata (kind: context-engine)
|
|
372
|
-
├── README.md # English documentation
|
|
373
|
-
├── README.zh.md # Chinese documentation
|
|
374
|
-
└── src/
|
|
375
|
-
├── config.js # Configuration parsing
|
|
376
|
-
├── memory-api.js # EverMemOS REST API client
|
|
377
|
-
├── formatter.js # Memory response parsing & formatting
|
|
378
|
-
├── message-utils.js # Message collection & format conversion
|
|
379
|
-
├── http-client.js # HTTP client with timeout & retry
|
|
380
|
-
├── types.js # JSDoc type definitions
|
|
381
|
-
├── assembler.js # Query-aware context assembly
|
|
382
|
-
├── lifecycle.js # Turn-level ingestion hooks
|
|
383
|
-
├── compaction.js # Compaction evaluation logic
|
|
384
|
-
├── subagent.js # Subagent lifecycle tracking
|
|
385
|
-
└── context-engine.js # Core ContextEngine implementation
|
|
386
|
-
```
|
|
387
|
-
|
|
388
|
-
---
|
|
389
|
-
|
|
390
|
-
## Links
|
|
391
|
-
|
|
392
|
-
- [EverMemOS](https://github.com/EverMind-AI/EverMemOS) - Backend memory system
|
|
393
|
-
- [OpenClaw](https://github.com/openclaw-org/openclaw) - Agent framework
|
|
394
|
-
- [中文文档](README.zh.md) - Chinese documentation
|
|
395
|
-
|
|
396
|
-
---
|
|
152
|
+
| Problem | Fix |
|
|
153
|
+
| --- | --- |
|
|
154
|
+
| Plugin not loading | Check `plugins.allow`, `plugins.load.paths`, and `plugins.slots.contextEngine` |
|
|
155
|
+
| Backend connection failed | Verify `baseUrl` and run `curl <baseUrl>/health` |
|
|
156
|
+
| Memory not recalled | Check backend data and try a more specific query |
|
|
157
|
+
| Memory not saved | Verify the EverOS backend write API is healthy |
|
|
158
|
+
| Conflict with another memory plugin | Ensure `plugins.slots.memory = "none"` |
|
|
159
|
+
|
|
160
|
+
## Related files
|
|
161
|
+
|
|
162
|
+
- `index.js`: ContextEngine registration and lifecycle hooks
|
|
163
|
+
- `bin/install.js`: installer and config bootstrap
|
|
164
|
+
- `src/memory-api.js`: EverOS backend REST client
|
|
165
|
+
- `src/message-utils.js`: message normalization and turn collection
|
|
166
|
+
- `openclaw.plugin.json`: plugin metadata and config schema
|
|
397
167
|
|
|
398
168
|
## License
|
|
399
169
|
|