@mingxy/cerebro-claude-code 0.3.8 → 0.3.9

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "cerebro",
3
3
  "description": "Persistent memory for Claude Code — memories survive across sessions, projects, and machines",
4
- "version": "0.3.8",
4
+ "version": "0.3.9",
5
5
  "author": {
6
6
  "name": "mingxy-cerebro",
7
7
  "email": "hi@cerebro.dev"
package/.mcp.json CHANGED
@@ -4,7 +4,8 @@
4
4
  "args": ["-y", "@mingxy/cerebro-mcp@latest"],
5
5
  "env": {
6
6
  "OMEM_API_KEY": "${OMEM_API_KEY}",
7
- "OMEM_API_URL": "${OMEM_API_URL:-https://www.mengxy.cc}"
7
+ "OMEM_API_URL": "${OMEM_API_URL:-https://www.mengxy.cc}",
8
+ "OMEM_DISABLE_STORE": "1"
8
9
  }
9
10
  }
10
11
  }
package/hooks/common.mjs CHANGED
@@ -26,6 +26,7 @@ const DEF = {
26
26
  requestTimeout: 15,
27
27
  recentCount: 8,
28
28
  searchCount: 8,
29
+ globalCount: 3,
29
30
  maxContent: 3000,
30
31
  maxQueryLength: 200,
31
32
  logDir: join(HOME, ".config/cerebro/logs"),
@@ -75,6 +76,7 @@ function loadConfig() {
75
76
  requestTimeout: num("MEM_REQUEST_TIMEOUT", c.requestTimeoutMs ? c.requestTimeoutMs / 1000 : null, DEF.requestTimeout),
76
77
  recentCount: num("MEM_RECENT_COUNT", i.recentCount, DEF.recentCount),
77
78
  searchCount: num("MEM_SEARCH_COUNT", i.searchCount, DEF.searchCount),
79
+ globalCount: num("MEM_GLOBAL_COUNT", i.globalCount, DEF.globalCount),
78
80
  maxContent: num("MEM_MAX_CONTENT", ct.maxContentLength || ct.maxContentChars, DEF.maxContent),
79
81
  maxQueryLength: num("MEM_MAX_QUERY_LENGTH", ct.maxQueryLength, DEF.maxQueryLength),
80
82
  logDir: (process.env.MEM_LOG_DIR || lg.logDir || DEF.logDir).replace(/^~/, HOME),
@@ -499,7 +501,7 @@ export async function flushSessionIngest(transcriptPath, sessionId, timeoutSec =
499
501
  const agentId = process.env.OMEM_AGENT_ID || "claude-code";
500
502
 
501
503
  if (messages.length > 0) {
502
- const body = { messages, agent_id: agentId };
504
+ const body = { messages, agent_id: agentId, home_path: HOME };
503
505
  if (sessionId) body.session_id = sessionId;
504
506
  if (pn) body.project_name = pn;
505
507
  if (pp) body.project_path = pp;
@@ -570,12 +572,13 @@ export function truncateAtBoundary(text, maxLength) {
570
572
  }
571
573
 
572
574
  // GET /v1/memories/search — 单路语义搜索
573
- export async function searchMemories(query, limit, projectPath) {
575
+ export async function searchMemories(query, limit, projectPath, excludeGlobal) {
574
576
  limit = limit || config.searchCount;
575
577
  const safeQ = truncateQuery(query);
576
578
  if (!safeQ) return [];
577
579
  const params = new URLSearchParams({ q: safeQ, limit: String(limit) });
578
580
  if (projectPath) params.set("project_path", projectPath);
581
+ if (excludeGlobal) params.set("exclude_global", "1");
579
582
  try {
580
583
  const resp = await fetch(`${config.apiUrl}/v1/memories/search?${params}`, {
581
584
  headers: { "X-API-Key": config.apiKey, Accept: "application/json" },
@@ -589,18 +592,23 @@ export async function searchMemories(query, limit, projectPath) {
589
592
  }
590
593
 
591
594
  // buildMemoryInjection — 对标 opencode hooks.ts:246-329
592
- // 三路并发:profile + recent + search(query)。query 为空跳过 search。
595
+ // 四路并发:profile + global + recent + search(query)。query 为空跳过 search。
596
+ // 拍板(issue #3):项目 recent/search 路带 exclude_global(专区已单列,项目路不混全局);
597
+ // 全局专区 globalCount 条(SessionStart q 为空,走 list 按时间取最新全局记忆)。
593
598
  export async function buildMemoryInjection(query, projectPath, options = {}) {
594
599
  const profileEnabled = options.profileEnabled !== false;
595
600
  const recentEnabled = options.recentEnabled !== false;
601
+ const globalEnabled = options.globalEnabled !== false;
596
602
  const hdrs = { "X-API-Key": config.apiKey, Accept: "application/json" };
597
603
  const recentCount = config.recentCount;
598
604
  const searchCount = config.searchCount;
605
+ const globalCount = config.globalCount;
599
606
  const profileQs = projectPath ? `?project_path=${encodeURIComponent(projectPath)}` : "";
600
- const recentQs = `?limit=${recentCount}&offset=0&sort=updated_at&order=desc${projectPath ? `&project_path=${encodeURIComponent(projectPath)}` : ""}`;
607
+ const recentQs = `?limit=${recentCount}&offset=0&sort=updated_at&order=desc&exclude_global=1${projectPath ? `&project_path=${encodeURIComponent(projectPath)}` : ""}`;
608
+ const globalQs = `?limit=${globalCount}&offset=0&sort=updated_at&order=desc&global_only=1`;
601
609
  const safeQ = truncateQuery(query);
602
610
 
603
- const [profileResp, recentResp, searchResp] = await Promise.all([
611
+ const [profileResp, recentResp, globalResp, searchResp] = await Promise.all([
604
612
  profileEnabled
605
613
  ? fetch(`${config.apiUrl}/v2/profile/inject${profileQs}`, { headers: hdrs, signal: AbortSignal.timeout(config.profileTimeoutMs) })
606
614
  .then((r) => r.text()).catch(() => "")
@@ -609,8 +617,12 @@ export async function buildMemoryInjection(query, projectPath, options = {}) {
609
617
  ? fetch(`${config.apiUrl}/v1/memories${recentQs}`, { headers: hdrs, signal: AbortSignal.timeout(config.recentTimeoutMs) })
610
618
  .then((r) => (r.ok ? r.text() : null)).catch(() => null)
611
619
  : Promise.resolve(""),
620
+ globalEnabled
621
+ ? fetch(`${config.apiUrl}/v1/memories${globalQs}`, { headers: hdrs, signal: AbortSignal.timeout(config.recentTimeoutMs) })
622
+ .then((r) => (r.ok ? r.text() : null)).catch(() => null)
623
+ : Promise.resolve(""),
612
624
  safeQ
613
- ? fetch(`${config.apiUrl}/v1/memories/search?q=${encodeURIComponent(safeQ)}&limit=${searchCount}${projectPath ? `&project_path=${encodeURIComponent(projectPath)}` : ""}`, { headers: hdrs, signal: AbortSignal.timeout(5000) })
625
+ ? fetch(`${config.apiUrl}/v1/memories/search?q=${encodeURIComponent(safeQ)}&limit=${searchCount}&exclude_global=1${projectPath ? `&project_path=${encodeURIComponent(projectPath)}` : ""}`, { headers: hdrs, signal: AbortSignal.timeout(5000) })
614
626
  .then((r) => r.text()).catch(() => "")
615
627
  : Promise.resolve(""),
616
628
  ]);
@@ -634,6 +646,13 @@ export async function buildMemoryInjection(query, projectPath, options = {}) {
634
646
  } catch {}
635
647
  }
636
648
 
649
+ // parse global (最新全局记忆,跨项目)
650
+ let globalMemories = [];
651
+ try {
652
+ const gd = JSON.parse(globalResp);
653
+ if (gd && !gd.error) globalMemories = gd.memories || [];
654
+ } catch {}
655
+
637
656
  // parse search
638
657
  let searchResults = [];
639
658
  try {
@@ -650,6 +669,16 @@ export async function buildMemoryInjection(query, projectPath, options = {}) {
650
669
  }
651
670
 
652
671
  const seenIds = new Set();
672
+ if (globalMemories.length > 0) {
673
+ sections.push("## Global Memories");
674
+ for (const m of globalMemories) {
675
+ if (m.id) seenIds.add(m.id);
676
+ const age = formatRelativeAge(m.updated_at || m.created_at);
677
+ sections.push(`- (${age}) ${m.content || ""}`);
678
+ }
679
+ sections.push("");
680
+ }
681
+
653
682
  if (projectMemories.length > 0) {
654
683
  sections.push("## Recent Project Activity");
655
684
  for (const m of projectMemories) {
@@ -682,6 +711,7 @@ export async function buildMemoryInjection(query, projectPath, options = {}) {
682
711
  return {
683
712
  text,
684
713
  profileCount: profileContent ? 1 : 0,
714
+ globalCount: globalMemories.length,
685
715
  projectMemoryCount: projectMemories.length,
686
716
  searchCount: dedupedResults.length,
687
717
  recentFailed,
@@ -158,9 +158,9 @@ if (startSource === "clear") {
158
158
  await postRecallEvent({
159
159
  sessionId: sid,
160
160
  recallType: "session_start",
161
- queryText: `Session Start · ${injection.projectMemoryCount} memories · ${injection.profileCount > 0 ? "profile" : "no profile"}`,
161
+ queryText: `Session Start · ${injection.globalCount} global · ${injection.projectMemoryCount} project · ${injection.profileCount > 0 ? "profile" : "no profile"}`,
162
162
  profileInjected: injection.profileCount > 0,
163
- keptCount: injection.projectMemoryCount,
163
+ keptCount: injection.globalCount + injection.projectMemoryCount,
164
164
  injectedContent: out,
165
165
  failureReason: injection.recentFailed ? "recent fetch failed/timeout" : "",
166
166
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mingxy/cerebro-claude-code",
3
- "version": "0.3.8",
3
+ "version": "0.3.9",
4
4
  "description": "Persistent memory for Claude Code — memories survive across sessions, projects, and machines",
5
5
  "author": {
6
6
  "name": "mingxy-cerebro",