@mingxy/cerebro 1.12.7 → 1.13.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/schema.json CHANGED
@@ -1,218 +1,249 @@
1
- {
2
- "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://www.mengxy.cc/schemas/cerebro-plugin-config.json",
4
- "title": "Cerebro Plugin Configuration",
5
- "description": "Configuration schema for @mingxy/cerebro OpenCode plugin",
6
- "type": "object",
7
- "properties": {
8
- "connection": {
9
- "type": "object",
10
- "description": "API endpoint and authentication for the Cerebro server",
11
- "properties": {
12
- "apiUrl": {
13
- "type": "string",
14
- "format": "uri",
15
- "description": "Cerebro server URL (env: OMEM_API_URL takes priority)",
16
- "default": "https://www.mengxy.cc"
17
- },
18
- "apiKey": {
19
- "type": "string",
20
- "description": "Your tenant API key (env: OMEM_API_KEY takes priority)",
21
- "default": ""
22
- },
23
- "requestTimeoutMs": {
24
- "type": "number",
25
- "description": "HTTP request timeout in milliseconds",
26
- "default": 15000,
27
- "minimum": 1000,
28
- "maximum": 120000
29
- }
30
- },
31
- "additionalProperties": false,
32
- "required": ["apiUrl", "apiKey"]
33
- },
34
- "content": {
35
- "type": "object",
36
- "description": "Limits for content processing and ingestion",
37
- "properties": {
38
- "maxQueryLength": {
39
- "type": "number",
40
- "description": "Max characters for recall queries",
41
- "default": 200,
42
- "minimum": 50,
43
- "maximum": 1000
44
- },
45
- "maxContentChars": {
46
- "type": "number",
47
- "description": "Max content chars sent to the server per ingestion",
48
- "default": 30000,
49
- "minimum": 1000,
50
- "maximum": 100000
51
- },
52
- "maxContentLength": {
53
- "type": "number",
54
- "description": "Max single content item length for auto-capture",
55
- "default": 500,
56
- "minimum": 100,
57
- "maximum": 5000
58
- }
59
- },
60
- "additionalProperties": false
61
- },
62
- "ingest": {
63
- "type": "object",
64
- "description": "Controls how memories are captured and stored",
65
- "properties": {
66
- "autoCaptureThreshold": {
67
- "type": "number",
68
- "description": "Minimum number of messages before auto-capture triggers",
69
- "default": 5,
70
- "minimum": 1,
71
- "maximum": 100
72
- },
73
- "ingestMode": {
74
- "type": "string",
75
- "description": "Ingestion mode: smart = LLM-powered extraction, raw = store as-is",
76
- "enum": ["smart", "raw"],
77
- "default": "smart"
78
- }
79
- },
80
- "additionalProperties": false
81
- },
82
- "recall": {
83
- "type": "object",
84
- "description": "Tuning for memory retrieval relevance",
85
- "properties": {
86
- "similarityThreshold": {
87
- "type": "number",
88
- "description": "Minimum cosine similarity to include a result (0.0-1.0)",
89
- "default": 0.4,
90
- "minimum": 0.0,
91
- "maximum": 1.0
92
- },
93
- "maxRecallResults": {
94
- "type": "number",
95
- "description": "Maximum number of memories returned per recall",
96
- "default": 10,
97
- "minimum": 1,
98
- "maximum": 50
99
- },
100
- "fetchMultiplier": {
101
- "type": "number",
102
- "description": "Search breadth multiplier: fetch_limit = max_results * N",
103
- "default": 3,
104
- "minimum": 1,
105
- "maximum": 10
106
- },
107
- "topkCapMultiplier": {
108
- "type": "number",
109
- "description": "Candidate cap multiplier: topk_cap = max_results * N",
110
- "default": 2,
111
- "minimum": 1,
112
- "maximum": 10
113
- },
114
- "mmrJaccardThreshold": {
115
- "type": "number",
116
- "description": "Jaccard similarity threshold for MMR diversity penalty",
117
- "default": 0.85,
118
- "minimum": 0.0,
119
- "maximum": 1.0
120
- },
121
- "mmrPenaltyFactor": {
122
- "type": "number",
123
- "description": "Score penalty factor for similar memories in MMR diversity",
124
- "default": 0.5,
125
- "minimum": 0.0,
126
- "maximum": 1.0
127
- },
128
- "phase2Multiplier": {
129
- "type": "number",
130
- "description": "Phase2 global fallback search multiplier",
131
- "default": 2,
132
- "minimum": 1,
133
- "maximum": 10
134
- },
135
- "llmMaxEval": {
136
- "type": "number",
137
- "description": "Maximum candidates sent to LLM for relevance evaluation",
138
- "default": 15,
139
- "minimum": 1,
140
- "maximum": 50
141
- },
142
- "refineStrategy": {
143
- "type": "string",
144
- "description": "LLM refinement strategy: strict (high only), balanced (high+medium), loose (keep all)",
145
- "enum": ["strict", "balanced", "loose"],
146
- "default": "balanced"
147
- },
148
- "refineMediumChars": {
149
- "type": "number",
150
- "description": "Character limit for medium-relevance content truncation",
151
- "default": 200,
152
- "minimum": 50,
153
- "maximum": 2000
154
- }
155
- },
156
- "additionalProperties": false
157
- },
158
- "logging": {
159
- "type": "object",
160
- "description": "Diagnostic logging for debugging plugin behavior",
161
- "properties": {
162
- "logEnabled": {
163
- "type": "boolean",
164
- "description": "Enable/disable file logging",
165
- "default": true
166
- },
167
- "logLevel": {
168
- "type": "string",
169
- "description": "Log verbosity",
170
- "enum": ["DEBUG", "INFO", "WARN", "ERROR"],
171
- "default": "INFO"
172
- },
173
- "logDir": {
174
- "type": "string",
175
- "description": "Directory for log files",
176
- "default": "~/.config/cerebro"
177
- }
178
- },
179
- "additionalProperties": false
180
- },
181
- "ui": {
182
- "type": "object",
183
- "description": "Terminal UI behavior tuning",
184
- "properties": {
185
- "toastDelayMs": {
186
- "type": "number",
187
- "description": "Delay in ms before toast notifications auto-dismiss",
188
- "default": 7000,
189
- "minimum": 1000,
190
- "maximum": 30000
191
- }
192
- },
193
- "additionalProperties": false
194
- },
195
- "agentMemoryPolicy": {
196
- "type": "object",
197
- "description": "Control which sub-agents can read/write memories",
198
- "additionalProperties": {
199
- "type": "string",
200
- "enum": ["none", "readonly", "readwrite"],
201
- "description": "Policy for this agent name"
202
- },
203
- "examples": [
204
- {
205
- "explore": "readonly",
206
- "librarian": "readonly"
207
- }
208
- ]
209
- },
210
- "defaultPolicy": {
211
- "type": "string",
212
- "description": "Default policy for agents not listed in agentMemoryPolicy",
213
- "enum": ["none", "readonly", "readwrite"],
214
- "default": "readwrite"
215
- }
216
- },
217
- "additionalProperties": false
218
- }
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://www.mengxy.cc/schemas/cerebro-plugin-config.json",
4
+ "title": "Cerebro Plugin Configuration",
5
+ "description": "Configuration schema for @mingxy/cerebro OpenCode plugin",
6
+ "type": "object",
7
+ "properties": {
8
+ "connection": {
9
+ "type": "object",
10
+ "description": "API endpoint and authentication for the Cerebro server",
11
+ "properties": {
12
+ "apiUrl": {
13
+ "type": "string",
14
+ "format": "uri",
15
+ "description": "Cerebro server URL (env: OMEM_API_URL takes priority)",
16
+ "default": "https://www.mengxy.cc"
17
+ },
18
+ "apiKey": {
19
+ "type": "string",
20
+ "description": "Your tenant API key (env: OMEM_API_KEY takes priority)",
21
+ "default": ""
22
+ },
23
+ "requestTimeoutMs": {
24
+ "type": "number",
25
+ "description": "HTTP request timeout in milliseconds",
26
+ "default": 15000,
27
+ "minimum": 1000,
28
+ "maximum": 120000
29
+ }
30
+ },
31
+ "additionalProperties": false,
32
+ "required": ["apiUrl", "apiKey"]
33
+ },
34
+ "content": {
35
+ "type": "object",
36
+ "description": "Limits for content processing and ingestion",
37
+ "properties": {
38
+ "maxQueryLength": {
39
+ "type": "number",
40
+ "description": "Max characters for recall queries",
41
+ "default": 200,
42
+ "minimum": 50,
43
+ "maximum": 1000
44
+ },
45
+ "maxContentChars": {
46
+ "type": "number",
47
+ "description": "Max content chars sent to the server per ingestion",
48
+ "default": 30000,
49
+ "minimum": 1000,
50
+ "maximum": 100000
51
+ },
52
+ "maxContentLength": {
53
+ "type": "number",
54
+ "description": "Max single content item length for auto-capture",
55
+ "default": 500,
56
+ "minimum": 100,
57
+ "maximum": 5000
58
+ }
59
+ },
60
+ "additionalProperties": false
61
+ },
62
+ "ingest": {
63
+ "type": "object",
64
+ "description": "Controls how memories are captured and stored",
65
+ "properties": {
66
+ "autoCaptureThreshold": {
67
+ "type": "number",
68
+ "description": "Minimum number of messages before auto-capture triggers",
69
+ "default": 5,
70
+ "minimum": 1,
71
+ "maximum": 100
72
+ },
73
+ "ingestMode": {
74
+ "type": "string",
75
+ "description": "Ingestion mode: smart = LLM-powered extraction, raw = store as-is",
76
+ "enum": ["smart", "raw"],
77
+ "default": "smart"
78
+ }
79
+ },
80
+ "additionalProperties": false
81
+ },
82
+ "recall": {
83
+ "type": "object",
84
+ "description": "Tuning for memory retrieval relevance",
85
+ "properties": {
86
+ "similarityThreshold": {
87
+ "type": "number",
88
+ "description": "Minimum cosine similarity to include a result (0.0-1.0)",
89
+ "default": 0.4,
90
+ "minimum": 0.0,
91
+ "maximum": 1.0
92
+ },
93
+ "maxRecallResults": {
94
+ "type": "number",
95
+ "description": "Maximum number of memories returned per recall",
96
+ "default": 10,
97
+ "minimum": 1,
98
+ "maximum": 50
99
+ },
100
+ "fetchMultiplier": {
101
+ "type": "number",
102
+ "description": "Search breadth multiplier: fetch_limit = max_results * N",
103
+ "default": 3,
104
+ "minimum": 1,
105
+ "maximum": 10
106
+ },
107
+ "topkCapMultiplier": {
108
+ "type": "number",
109
+ "description": "Candidate cap multiplier: topk_cap = max_results * N",
110
+ "default": 2,
111
+ "minimum": 1,
112
+ "maximum": 10
113
+ },
114
+ "mmrJaccardThreshold": {
115
+ "type": "number",
116
+ "description": "Jaccard similarity threshold for MMR diversity penalty",
117
+ "default": 0.85,
118
+ "minimum": 0.0,
119
+ "maximum": 1.0
120
+ },
121
+ "mmrPenaltyFactor": {
122
+ "type": "number",
123
+ "description": "Score penalty factor for similar memories in MMR diversity",
124
+ "default": 0.5,
125
+ "minimum": 0.0,
126
+ "maximum": 1.0
127
+ },
128
+ "phase2Multiplier": {
129
+ "type": "number",
130
+ "description": "Phase2 global fallback search multiplier",
131
+ "default": 2,
132
+ "minimum": 1,
133
+ "maximum": 10
134
+ },
135
+ "llmMaxEval": {
136
+ "type": "number",
137
+ "description": "Maximum candidates sent to LLM for relevance evaluation",
138
+ "default": 15,
139
+ "minimum": 1,
140
+ "maximum": 50
141
+ },
142
+ "refineStrategy": {
143
+ "type": "string",
144
+ "description": "LLM refinement strategy: strict (high only), balanced (high+medium), loose (keep all)",
145
+ "enum": ["strict", "balanced", "loose"],
146
+ "default": "balanced"
147
+ },
148
+ "refineMediumChars": {
149
+ "type": "number",
150
+ "description": "Character limit for medium-relevance content truncation",
151
+ "default": 200,
152
+ "minimum": 50,
153
+ "maximum": 2000
154
+ }
155
+ },
156
+ "additionalProperties": false
157
+ },
158
+ "logging": {
159
+ "type": "object",
160
+ "description": "Diagnostic logging for debugging plugin behavior",
161
+ "properties": {
162
+ "logEnabled": {
163
+ "type": "boolean",
164
+ "description": "Enable/disable file logging",
165
+ "default": true
166
+ },
167
+ "logLevel": {
168
+ "type": "string",
169
+ "description": "Log verbosity",
170
+ "enum": ["DEBUG", "INFO", "WARN", "ERROR"],
171
+ "default": "INFO"
172
+ },
173
+ "logDir": {
174
+ "type": "string",
175
+ "description": "Directory for log files",
176
+ "default": "~/.config/cerebro"
177
+ }
178
+ },
179
+ "additionalProperties": false
180
+ },
181
+ "ui": {
182
+ "type": "object",
183
+ "description": "Terminal UI behavior tuning",
184
+ "properties": {
185
+ "toastDelayMs": {
186
+ "type": "number",
187
+ "description": "Delay in ms before toast notifications auto-dismiss",
188
+ "default": 7000,
189
+ "minimum": 1000,
190
+ "maximum": 30000
191
+ }
192
+ },
193
+ "additionalProperties": false
194
+ },
195
+ "agentMemoryPolicy": {
196
+ "type": "object",
197
+ "description": "Control which sub-agents can read/write memories",
198
+ "additionalProperties": {
199
+ "type": "string",
200
+ "enum": ["none", "readonly", "readwrite"],
201
+ "description": "Policy for this agent name"
202
+ },
203
+ "examples": [
204
+ {
205
+ "explore": "readonly",
206
+ "librarian": "readonly"
207
+ }
208
+ ]
209
+ },
210
+ "defaultPolicy": {
211
+ "type": "string",
212
+ "description": "Default policy for agents not listed in agentMemoryPolicy",
213
+ "enum": ["none", "readonly", "readwrite"],
214
+ "default": "readwrite"
215
+ },
216
+ "soulWhisper": {
217
+ "type": "object",
218
+ "description": "Soul Whisper: inject memory reminders when LLM calls tools",
219
+ "properties": {
220
+ "enabled": {
221
+ "type": "boolean",
222
+ "description": "Enable/disable soul whisper injection",
223
+ "default": true
224
+ },
225
+ "tools": {
226
+ "type": "array",
227
+ "items": { "type": "string" },
228
+ "description": "Tool name whitelist. Use [\"*\"] to match all tools",
229
+ "default": ["*"]
230
+ },
231
+ "excludeTools": {
232
+ "type": "array",
233
+ "items": { "type": "string" },
234
+ "description": "Tool names to exclude from whisper injection",
235
+ "default": ["memory_store", "memory_search", "memory_get", "memory_toggle", "memory_ingest"]
236
+ },
237
+ "maxToolNames": {
238
+ "type": "number",
239
+ "description": "Max tool names shown in tool-specific whisper. Exceeding this falls back to generic version",
240
+ "default": 3,
241
+ "minimum": 1,
242
+ "maximum": 10
243
+ }
244
+ },
245
+ "additionalProperties": false
246
+ }
247
+ },
248
+ "additionalProperties": false
249
+ }
package/src/client.ts CHANGED
@@ -21,6 +21,7 @@ export interface IngestOptions {
21
21
  entityContext?: string;
22
22
  tags?: string[];
23
23
  projectName?: string;
24
+ projectPath?: string;
24
25
  }
25
26
 
26
27
  export interface SearchResult {
@@ -192,6 +193,7 @@ export class CerebroClient {
192
193
  sessionId?: string,
193
194
  visibility?: string,
194
195
  category?: string,
196
+ projectPath?: string,
195
197
  ): Promise<MemoryDto | null> {
196
198
  const safeContent = sanitizeContent(content, this.getCfg("content", "maxContentChars", 30000));
197
199
  return this.post<MemoryDto>("/v1/memories", {
@@ -203,6 +205,7 @@ export class CerebroClient {
203
205
  session_id: sessionId,
204
206
  visibility,
205
207
  category,
208
+ project_path: projectPath,
206
209
  });
207
210
  }
208
211
 
@@ -211,11 +214,13 @@ export class CerebroClient {
211
214
  limit = 10,
212
215
  scope?: string,
213
216
  tags?: string[],
217
+ projectPath?: string,
214
218
  ): Promise<SearchResult[]> {
215
219
  const safeQ = truncateQuery(query, this.getCfg("content", "maxQueryLength", 200));
216
220
  const params = new URLSearchParams({ q: safeQ, limit: String(limit) });
217
221
  if (scope) params.set("scope", scope);
218
222
  if (tags && tags.length > 0) params.set("tags", tags.join(","));
223
+ if (projectPath) params.set("project_path", projectPath);
219
224
  const res = await this.request<SearchResponse>(
220
225
  `/v1/memories/search?${params}`,
221
226
  {},
@@ -259,6 +264,7 @@ export class CerebroClient {
259
264
  entity_context: opts.entityContext,
260
265
  tags: opts.tags,
261
266
  project_name: opts.projectName,
267
+ project_path: opts.projectPath,
262
268
  });
263
269
  }
264
270
 
@@ -350,6 +356,7 @@ export class CerebroClient {
350
356
  refine_strategy?: string;
351
357
  refine_medium_chars?: number;
352
358
  },
359
+ projectPath?: string,
353
360
  ): Promise<ShouldRecallResponse | null> {
354
361
  const res = await this.post<ShouldRecallResponse>("/v1/should-recall", {
355
362
  query_text,
@@ -360,6 +367,7 @@ export class CerebroClient {
360
367
  project_tags,
361
368
  conversation_context,
362
369
  ...recall_overrides,
370
+ project_path: projectPath,
363
371
  }, 20_000);
364
372
  return res;
365
373
  }
@@ -410,6 +418,7 @@ export class CerebroClient {
410
418
  agentId?: string,
411
419
  sessionTitle?: string,
412
420
  projectName?: string,
421
+ projectPath?: string,
413
422
  ): Promise<unknown> {
414
423
  return this.post("/v1/memories/session-ingest", {
415
424
  messages,
@@ -417,6 +426,7 @@ export class CerebroClient {
417
426
  agent_id: agentId,
418
427
  session_title: sessionTitle,
419
428
  project_name: projectName,
429
+ project_path: projectPath,
420
430
  }, 60000);
421
431
  }
422
432
  }
package/src/config.ts CHANGED
@@ -39,6 +39,12 @@ export interface OmemPluginConfig {
39
39
  ui: {
40
40
  toastDelayMs: number;
41
41
  };
42
+ soulWhisper?: {
43
+ enabled: boolean;
44
+ tools: string[];
45
+ excludeTools: string[];
46
+ maxToolNames: number;
47
+ };
42
48
  agentMemoryPolicy?: Record<string, "none" | "readonly" | "readwrite">;
43
49
  defaultPolicy?: "none" | "readonly" | "readwrite";
44
50
  }
@@ -80,6 +86,12 @@ const DEFAULTS: OmemPluginConfig = {
80
86
  ui: {
81
87
  toastDelayMs: 7000,
82
88
  },
89
+ soulWhisper: {
90
+ enabled: true,
91
+ tools: ["*"],
92
+ excludeTools: ["memory_store", "memory_search", "memory_get", "memory_toggle", "memory_ingest"],
93
+ maxToolNames: 3,
94
+ },
83
95
  };
84
96
 
85
97
  // ── Flat-to-nested migration ─────────────────────────────────────────
@@ -161,6 +173,7 @@ function deepMerge(base: OmemPluginConfig, overrides: Partial<OmemPluginConfig>)
161
173
  logging: { ...base.logging, ...overrides.logging },
162
174
  ui: { ...base.ui, ...overrides.ui },
163
175
  };
176
+ result.soulWhisper = { ...base.soulWhisper!, ...overrides.soulWhisper };
164
177
  if (overrides.agentMemoryPolicy) result.agentMemoryPolicy = overrides.agentMemoryPolicy;
165
178
  if (overrides.defaultPolicy) result.defaultPolicy = overrides.defaultPolicy;
166
179
  return result;