@mingxy/cerebro 1.15.13 → 1.16.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/src/index.ts CHANGED
@@ -4,7 +4,7 @@ import { join, dirname } from "node:path";
4
4
  import { tmpdir } from "node:os";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import { CerebroClient } from "./client.js";
7
- import { autoRecallHook, memoryInjectionHook, autocontinueHook, compactingHook, keywordDetectionHook, sessionIdleHook, soulWhisperToolTracker, pendingToolCalls, buildWhisperText, recallCache, profileInjectedSessions, buildProfileBlock } from "./hooks.js";
7
+ import { autoRecallHook, autocontinueHook, compactingHook, keywordDetectionHook, sessionIdleHook, showToast as hooksShowToast } from "./hooks.js";
8
8
  import { getUserTag, getProjectTag } from "./tags.js";
9
9
  import { buildTools } from "./tools.js";
10
10
  import { logInfo, logDebug, logError } from "./logger.js";
@@ -42,24 +42,6 @@ export function setAutoStoreEnabled(sessionId: string, enabled: boolean): void {
42
42
 
43
43
  (globalThis as any).__cerebro_autoStoreMap = autoStoreSessions;
44
44
 
45
- function showToast(tui: any, title: string, message?: string, variant: string = "info", duration: number = 5000) {
46
- if (!tui) return;
47
- setTimeout(() => {
48
- try {
49
- const body: any = { variant, duration };
50
- if (message) {
51
- body.title = title;
52
- body.message = message;
53
- } else {
54
- body.message = title;
55
- }
56
- tui.showToast({ body });
57
- } catch (err) {
58
- logError("showToast failed", { error: String(err) });
59
- }
60
- }, 3000);
61
- }
62
-
63
45
  const OmemPlugin: Plugin = async (input) => {
64
46
  const { directory, client } = input;
65
47
  // Proxy: dynamically resolve client.tui on each access so toast works
@@ -85,14 +67,14 @@ const OmemPlugin: Plugin = async (input) => {
85
67
  // 启动时检测连接状态
86
68
  try {
87
69
  await cerebroClient.getStats();
88
- showToast(tui, "🧠 Cerebro · Connected", `Version v${pluginVersion}`, "success", 6000);
70
+ hooksShowToast(tui, "🧠 Cerebro · Connected", `Version v${pluginVersion}`, "success", 6000);
89
71
  logInfo(`Connected to ${config.connection.apiUrl}`);
90
72
  } catch (err) {
91
73
  const errMsg = err instanceof Error ? err.message : String(err);
92
74
  logError(`Connection failed: ${errMsg}`);
93
75
  if (errMsg.includes("[cerebro]")) {
94
76
  const cleanMsg = errMsg.replace(/^\[cerebro\]\s*/, "");
95
- showToast(
77
+ hooksShowToast(
96
78
  tui,
97
79
  `🧠 Cerebro v${pluginVersion} · Server Error`,
98
80
  cleanMsg.substring(0, 150),
@@ -100,7 +82,7 @@ const OmemPlugin: Plugin = async (input) => {
100
82
  8000
101
83
  );
102
84
  } else {
103
- showToast(
85
+ hooksShowToast(
104
86
  tui,
105
87
  `🧠 Cerebro v${pluginVersion} · Connection Failed`,
106
88
  `Unable to reach ${config.connection.apiUrl}`,
@@ -119,50 +101,7 @@ const OmemPlugin: Plugin = async (input) => {
119
101
  let mainSessionLocked = false;
120
102
  let cachedAgentName: string | undefined;
121
103
 
122
- const soulWhisperSystemHook = async (input: any, output: any) => {
123
- // ── Soul Whisper: inject to system prompt (v2 — system.transform) ──
124
- if (config.soulWhisper?.enabled !== false) {
125
- const sid = input.sessionID || "_default";
126
- const sessionCalls = pendingToolCalls.get(sid);
127
- if (sessionCalls && sessionCalls.size > 0) {
128
- const toolNames = [...new Set([...sessionCalls.values()].map(v => v.toolName))];
129
- const maxToolNames = config.soulWhisper?.maxToolNames ?? 3;
130
- const whisperText = buildWhisperText(toolNames, maxToolNames);
131
- if (whisperText) {
132
- if (output.system.length > 0) {
133
- output.system[0] += "\n\n" + whisperText;
134
- } else {
135
- output.system.push(whisperText);
136
- }
137
- logDebug("soulWhisper injected to output.system", { sessionId: sid, toolNames });
138
- }
139
- pendingToolCalls.delete(sid);
140
- }
141
- }
142
- };
143
-
144
- // ── Fallback strategy: "parts" (new) vs "system" (legacy) ──
145
- const strategy = config.injectionStrategy ?? "parts";
146
-
147
- const chatMessageHook = strategy === "parts"
148
- ? async (input: any, output: any) => {
149
- // New path: keyword detection + memory injection
150
- await keywordDetectionHook(cerebroClient, containerTags, config.ingest.autoCaptureThreshold, tui, config.ingest.ingestMode, config, agentId)(input, output);
151
- await memoryInjectionHook(cerebroClient, containerTags, tui, config, () => cachedAgentName || agentId, directory)(input, output);
152
- }
153
- : async (input: any, output: any) => {
154
- // Fallback: keyword detection only (memory injection via system.transform legacy autoRecallHook)
155
- await keywordDetectionHook(cerebroClient, containerTags, config.ingest.autoCaptureThreshold, tui, config.ingest.ingestMode, config, agentId)(input, output);
156
- };
157
-
158
- const systemTransformHook = strategy === "parts"
159
- ? soulWhisperSystemHook
160
- : async (input: any, output: any) => {
161
- // Fallback: legacy autoRecallHook + soulWhisper
162
- const recallHook = autoRecallHook(cerebroClient, containerTags, tui, config, () => cachedAgentName || agentId, directory);
163
- await recallHook(input, output);
164
- await soulWhisperSystemHook(input, output);
165
- };
104
+ const recallHook = autoRecallHook(cerebroClient, containerTags, tui, config, () => cachedAgentName || agentId, directory);
166
105
 
167
106
  return {
168
107
  config: async (cfg: any) => {
@@ -173,40 +112,19 @@ const OmemPlugin: Plugin = async (input) => {
173
112
  };
174
113
  },
175
114
  "experimental.chat.system.transform": async (input: any, output: any) => {
176
- logDebug("transform input", { sessionID: input.sessionID, strategy });
115
+ logDebug("transform input", { sessionID: input.sessionID });
177
116
  if (input.sessionID && !mainSessionLocked) {
178
117
  mainSessionId = input.sessionID;
179
118
  mainSessionLocked = true;
180
119
  logInfo("mainSessionId locked", { sessionId: input.sessionID });
181
120
  }
182
- const sid = input.sessionID;
183
- if (sid) {
184
- const cached = recallCache.get(sid);
185
- if (!cached || !cached.profileBlock) {
186
- cerebroClient.getProfile().then(profile => {
187
- if (profile) {
188
- const built = buildProfileBlock(profile);
189
- if (built) {
190
- recallCache.set(sid, {
191
- profileBlock: built.block,
192
- recallResult: null as any,
193
- profileData: { countText: built.countText },
194
- timestamp: Date.now(),
195
- });
196
- profileInjectedSessions.set(sid, Date.now());
197
- }
198
- }
199
- }).catch(() => {});
200
- }
201
- }
202
- return systemTransformHook(input, output);
121
+ return recallHook(input, output);
203
122
  },
204
- "chat.message": chatMessageHook,
123
+ "chat.message": keywordDetectionHook(cerebroClient, containerTags, config.ingest.autoCaptureThreshold, tui, config.ingest.ingestMode, config, agentId),
205
124
  "experimental.session.compacting": compactingHook(cerebroClient, containerTags, tui, config.ingest.ingestMode, isAutoStoreEnabled, () => mainSessionId, client, config, agentId, directory),
206
125
  "experimental.compaction.autocontinue": autocontinueHook(cerebroClient, containerTags, tui, config.ingest.ingestMode, isAutoStoreEnabled, () => mainSessionId, client, config, agentId, directory),
207
126
  tool: buildTools(cerebroClient, containerTags, { agentId, getSessionId: () => mainSessionId, getAgentName: () => cachedAgentName || agentId, getProjectPath: () => directory }),
208
127
  event: sessionIdleHook(cerebroClient, containerTags, tui, client, config.ingest.ingestMode, config.ingest.autoCaptureThreshold, () => mainSessionId, isAutoStoreEnabled, agentId, config, (name: string) => { cachedAgentName = name; }, directory),
209
- "tool.execute.before": (() => { const tracker = soulWhisperToolTracker(config); return tracker; })(),
210
128
  "shell.env": async (_input: any, output: any) => {
211
129
  if (directory) {
212
130
  output.env.OMEM_PROJECT_DIR = directory;