@fanchao8609/agent_brain_sync 0.1.0 → 0.1.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.
Files changed (2) hide show
  1. package/package.json +10 -2
  2. package/src/install.js +34 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fanchao8609/agent_brain_sync",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "agent-brain-sync: 跨会话 AI 编码记忆 — hook 纯触发 + CLI/MCP 读写 .brain markdown 图谱, 防并发写保护。",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -15,7 +15,15 @@
15
15
  "README.md"
16
16
  ],
17
17
  "keywords": [
18
- "memory", "agent", "brain", "markdown", "cross-session", "claude", "mcp", "knowledge-graph", "obsidian"
18
+ "memory",
19
+ "agent",
20
+ "brain",
21
+ "markdown",
22
+ "cross-session",
23
+ "claude",
24
+ "mcp",
25
+ "knowledge-graph",
26
+ "obsidian"
19
27
  ],
20
28
  "engines": {
21
29
  "node": ">=18"
package/src/install.js CHANGED
@@ -157,14 +157,26 @@ async function installCodex({ withMcp, withSkill, log }) {
157
157
  const p = join(process.env.CODEX_HOME || join(homedir(), '.codex'), 'hooks.json');
158
158
  await backup(p);
159
159
  const cfg = await readJson(p);
160
- cfg.hooks = cfg.hooks || [];
161
- // 去掉旧的 abs 条目再写(幂等)
162
- cfg.hooks = cfg.hooks.filter((h) => !String(h.command || '').includes('/.abs/hooks/'));
160
+ // Codex 真实结构是 {hooks: {EventName: [{matcher?, hooks:[{type,command}]}]}} (与 Claude 同形)。
161
+ // 兼容历史 bug 写出的扁平数组 {hooks: [{event, command}]}: 迁移成对象形态, 不丢既有 hook。
162
+ let hooks = cfg.hooks;
163
+ if (Array.isArray(hooks)) {
164
+ const migrated = {};
165
+ for (const h of hooks) {
166
+ if (!h || !h.event) continue;
167
+ (migrated[h.event] = migrated[h.event] || []).push({ hooks: [{ type: 'command', command: h.command }] });
168
+ }
169
+ hooks = migrated;
170
+ }
171
+ if (!hooks || typeof hooks !== 'object') hooks = {};
163
172
  for (const [ev, script] of Object.entries(scriptMap)) {
164
- cfg.hooks.push({ event: ev, command: script });
173
+ const existing = Array.isArray(hooks[ev]) ? hooks[ev] : [];
174
+ const kept = existing.filter((e) => !entryHasAbs(e)); // 去掉旧 abs 条目, 幂等; 保留既有 hook
175
+ hooks[ev] = [...kept, { hooks: [{ type: 'command', command: script }] }];
165
176
  }
177
+ cfg.hooks = hooks;
166
178
  await atomicWrite(p, JSON.stringify(cfg, null, 2));
167
- steps.push(`✓ hooks → ${p} (${Object.keys(scriptMap).length} 事件)`);
179
+ steps.push(`✓ hooks → ${p} (${Object.keys(scriptMap).length} 事件, 与既有 hook 共存)`);
168
180
 
169
181
  if (withMcp) {
170
182
  const mcpP = join(process.env.CODEX_HOME || join(homedir(), '.codex'), 'config.toml');
@@ -192,14 +204,27 @@ async function uninstallCodex() {
192
204
  const home = process.env.CODEX_HOME || join(homedir(), '.codex');
193
205
  const p = join(home, 'hooks.json');
194
206
  const cfg = await readJson(p);
195
- if (Array.isArray(cfg.hooks)) {
207
+ let changed = false;
208
+ if (Array.isArray(cfg.hooks)) { // 历史扁平数组形态
196
209
  const before = cfg.hooks.length;
197
210
  cfg.hooks = cfg.hooks.filter((h) => !String(h.command || '').includes('/.abs/hooks/'));
198
- if (cfg.hooks.length !== before) {
199
- await atomicWrite(p, JSON.stringify(cfg, null, 2));
200
- steps.push(`✓ hooks 已从 ${p} 移除`);
211
+ changed = cfg.hooks.length !== before;
212
+ } else if (cfg.hooks && typeof cfg.hooks === 'object') { // 对象形态 {EventName: [...]}
213
+ for (const ev of Object.keys(cfg.hooks)) {
214
+ const arr = cfg.hooks[ev];
215
+ if (!Array.isArray(arr)) continue;
216
+ const kept = arr.filter((e) => !entryHasAbs(e));
217
+ if (kept.length !== arr.length) {
218
+ changed = true;
219
+ if (kept.length) cfg.hooks[ev] = kept;
220
+ else delete cfg.hooks[ev]; // 无共存 hook 时整删该事件
221
+ }
201
222
  }
202
223
  }
224
+ if (changed) {
225
+ await atomicWrite(p, JSON.stringify(cfg, null, 2));
226
+ steps.push(`✓ hooks 已从 ${p} 移除`);
227
+ }
203
228
  const mcpP = join(home, 'config.toml');
204
229
  try {
205
230
  const text = await fs.readFile(mcpP, 'utf8');