@fanchao8609/agent_brain_sync 1.28.0 → 1.28.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/bin/abs.js +72 -3
  2. package/package.json +1 -1
package/bin/abs.js CHANGED
@@ -9,7 +9,7 @@ import { cmdSummon } from '../src/brain/summon-cmd.js';
9
9
  import { cmdIngest } from '../src/brain/ingest.js';
10
10
  import { setUser, getUser, userConfigPath } from '../src/userconfig.js';
11
11
  import { runInstall, runUninstall } from '../src/install.js';
12
- import { readFileSync } from 'node:fs';
12
+ import { existsSync, readFileSync } from 'node:fs';
13
13
  import { join, dirname, resolve } from 'node:path';
14
14
  import { fileURLToPath } from 'node:url';
15
15
  import { spawn } from 'node:child_process';
@@ -84,9 +84,78 @@ async function cmdUpdate({ yes }) {
84
84
  process.exit(1);
85
85
  }
86
86
  console.log(r);
87
+ // ★ 重装宿主必须交给**刚装好的那份新代码**去做,不能用本进程(2026-11-07 实报)。
88
+ //
89
+ // 病根:本进程是旧版 bin/abs.js,通过 import 加载的也是**旧版 src/install.js**。
90
+ // 旧 install.js 里的 stableBinPath() 用 process.execPath 推导全局包路径,
91
+ // 于是 hook 模板里的 @@ABS_BIN@@ 被烧成**旧副本**的路径,模板快照也是旧的。
92
+ // 结果:npm 已升到新版(npm ls -g 显示 1.28.0),但 ~/.pi/ 里写的还是旧模板,
93
+ // 界面一点没变,而且 hook 从此指向旧副本 —— 下一版继续错。
94
+ // 实测(fxh-mb):/usr/bin/abs -> /usr/lib/...(1.26.0,PATH 优先)
95
+ // 与 /opt/node.../bin/abs -> /opt/...(1.28.0,npm 的 prefix,不在 PATH)。
96
+ //
97
+ // 修法:升级后用 `npm prefix -g` 算出新包的真实路径,把「刷新宿主」转交给
98
+ // 那个新包的 bin/abs.js 执行(子进程)。它算 stableBinPath 时会指向自己。
99
+ // 找不到新包才退回本进程的 runInstall(至少不比原来差)。
100
+ const freshEntry = await freshInstallEntry();
87
101
  console.log('\n刷新四宿主 hook/skill(hook 脚本烧的是绝对路径 + 模板快照,升级后必须重装)…');
88
- await runInstall({ agent: undefined, mcp: true, skill: true, yes: yes !== false });
89
- console.log(`\n完成。重启宿主(pi / omp / opencode / claude-code / codex)后新 hook 生效。`);
102
+ if (freshEntry) {
103
+ if (freshEntry !== resolveBinPath()) console.log(` 用新装的副本执行: ${freshEntry}`);
104
+ // --all:update 的语义是「把升好的版本铺到所有已装宿主」,不能二次弹窗重选。
105
+ // 旧代码调 runInstall({agent: undefined}) 在 TTY 下会弹菜单,回车只装 pi ——
106
+ // 另装过 omp / Claude Code 的机器升级后那几个宿主永远不刷新(2026-11-07 实报)。
107
+ const args = ['install', '--all'];
108
+ if (yes) args.push('--yes');
109
+ const code = await runInherit(process.execPath, [freshEntry, ...args]);
110
+ if (code !== 0) {
111
+ console.error(`\n✗ 刷新宿主失败(退出码 ${code})。手动重跑:node ${freshEntry} install --all`);
112
+ process.exit(1);
113
+ }
114
+ } else {
115
+ console.log(' ⚠ 未定位到新安装的副本,用当前进程刷新(可能仍是旧模板)');
116
+ await runInstall({ agent: undefined, mcp: true, skill: true, yes: yes !== false });
117
+ }
118
+ console.log('\n完成。重启宿主(pi / omp / opencode / claude-code / codex)后新 hook 生效。');
119
+ }
120
+
121
+ /** 本进程正在跑的那个 bin/abs.js 的绝对路径(用于判断是否需要转交)。 */
122
+ function resolveBinPath() {
123
+ try { return resolve(fileURLToPath(import.meta.url)); } catch { return ''; }
124
+ }
125
+
126
+ /**
127
+ * 找出**刚升级好的**那份 bin/abs.js。找不到返回 null。
128
+ *
129
+ * 为何不用 ABS_DIR:那正是本进程所在目录 —— 在「PATH 里的 abs 与 npm prefix 不是同一份」
130
+ * 的机器上它就是旧副本(fxh-mb 实测:PATH 里是 /usr/bin/abs 指向 1.26.0,
131
+ * npm 把 1.28.0 装在 /opt/node.../lib/node_modules)。
132
+ */
133
+ async function freshInstallEntry() {
134
+ let pkgName = '';
135
+ try { pkgName = JSON.parse(readFileSync(join(ABS_DIR, 'package.json'), 'utf8')).name || ''; } catch { return null; }
136
+ if (!pkgName) return null;
137
+ // ① npm 自己报告的全局 prefix 最可信 —— 它正是刚 `npm i -g` 写入的位置。
138
+ const prefix = await runCmd('npm', ['prefix', '-g']);
139
+ const cands = [];
140
+ if (prefix) {
141
+ cands.push(join(prefix, 'lib', 'node_modules', pkgName, 'bin', 'abs.js'));
142
+ cands.push(join(prefix, 'node_modules', pkgName, 'bin', 'abs.js'));
143
+ }
144
+ // ② 本进程 node 所在根(nvm 形态与 prefix 一致;跨副本情况靠 ① 兜)
145
+ try { cands.push(join(dirname(dirname(process.execPath)), 'lib', 'node_modules', pkgName, 'bin', 'abs.js')); } catch {}
146
+ for (const c of cands) {
147
+ try { if (existsSync(c)) return c; } catch {}
148
+ }
149
+ return null;
150
+ }
151
+
152
+ /** 跑子进程并把输出直接接到本进程。返回退出码。 */
153
+ function runInherit(cmd, args) {
154
+ return new Promise((resolvePromise) => {
155
+ const c = spawn(cmd, args, { stdio: 'inherit' });
156
+ c.on('error', () => resolvePromise(1));
157
+ c.on('close', (code) => resolvePromise(code === null ? 1 : code));
158
+ });
90
159
  }
91
160
 
92
161
  const [,, cmd, ...rest] = process.argv;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fanchao8609/agent_brain_sync",
3
- "version": "1.28.0",
3
+ "version": "1.28.1",
4
4
  "description": "agent-brain-sync: 跨会话 AI 编码记忆 — hook 纯触发 + CLI/MCP 读写 .brain markdown 图谱, 防并发写保护。",
5
5
  "type": "module",
6
6
  "license": "MIT",