@fanchao8609/agent_brain_sync 1.3.0 → 1.3.2
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/bin/mcp.js +17 -9
- package/package.json +1 -1
- package/src/install.js +39 -4
package/bin/mcp.js
CHANGED
|
@@ -59,8 +59,16 @@ const server = new McpServer({
|
|
|
59
59
|
version: pkgVersion(),
|
|
60
60
|
});
|
|
61
61
|
|
|
62
|
+
// 统一注册入口(总是经 withTrace)。
|
|
63
|
+
// 坑: 以前 9 处工具各自直接调 server.tool(...) 而不包 withTrace, 导致 withTrace 定义了
|
|
64
|
+
// 但从未被调用 → mcp.log 永远不生成。可观测性静默缺失(无任何症状), 藏了很久。
|
|
65
|
+
// 现在工具只经本函数注册, 包 trace 这件事无法再被遗漏。
|
|
66
|
+
function tool(name, description, schema, handler) {
|
|
67
|
+
server.tool(name, description, schema, withTrace(name, handler));
|
|
68
|
+
}
|
|
69
|
+
|
|
62
70
|
// 工具面(narrow on purpose — 只暴露读/查/记状态,不做深提炼)
|
|
63
|
-
|
|
71
|
+
tool(
|
|
64
72
|
'abs_resolve_project',
|
|
65
73
|
'定位当前项目的 .brain 图谱根(从给定目录向上找最近 .brain/)。多项目隔离的唯一入口。',
|
|
66
74
|
{ cwd: z.string().describe('当前工作目录,默认进程 cwd') },
|
|
@@ -73,7 +81,7 @@ server.tool(
|
|
|
73
81
|
}
|
|
74
82
|
);
|
|
75
83
|
|
|
76
|
-
|
|
84
|
+
tool(
|
|
77
85
|
'abs_board',
|
|
78
86
|
'读取当前项目 todo 看板(含断点/Next-Step)。先 resolve 得到项目,再传其根目录。',
|
|
79
87
|
{ cwd: z.string().describe('项目内任意目录') },
|
|
@@ -84,7 +92,7 @@ server.tool(
|
|
|
84
92
|
}
|
|
85
93
|
);
|
|
86
94
|
|
|
87
|
-
|
|
95
|
+
tool(
|
|
88
96
|
'abs_load',
|
|
89
97
|
'开机读状态:index 路线 + todo 看板 + 最近 log。跨会话续接的入口。',
|
|
90
98
|
{ cwd: z.string().describe('项目内任意目录') },
|
|
@@ -95,7 +103,7 @@ server.tool(
|
|
|
95
103
|
}
|
|
96
104
|
);
|
|
97
105
|
|
|
98
|
-
|
|
106
|
+
tool(
|
|
99
107
|
'abs_task',
|
|
100
108
|
'任务实时落盘(幂等键 = id)。add/start 登记 / note 补断点(改到哪个文件哪行) / blocked 碰壁 / done 完成归位。',
|
|
101
109
|
{
|
|
@@ -113,7 +121,7 @@ server.tool(
|
|
|
113
121
|
}
|
|
114
122
|
);
|
|
115
123
|
|
|
116
|
-
|
|
124
|
+
tool(
|
|
117
125
|
'abs_status',
|
|
118
126
|
'当前项目 + 图谱概要(各类页数)。',
|
|
119
127
|
{ cwd: z.string().describe('项目内任意目录') },
|
|
@@ -124,7 +132,7 @@ server.tool(
|
|
|
124
132
|
}
|
|
125
133
|
);
|
|
126
134
|
|
|
127
|
-
|
|
135
|
+
tool(
|
|
128
136
|
'abs_query',
|
|
129
137
|
'检索当前项目 .brain/ 知识页(多词 OR):以前踩过什么坑、哪页记了 X。',
|
|
130
138
|
{ cwd: z.string().describe('项目内任意目录'), terms: z.array(z.string()).min(1).describe('检索词') },
|
|
@@ -135,7 +143,7 @@ server.tool(
|
|
|
135
143
|
}
|
|
136
144
|
);
|
|
137
145
|
|
|
138
|
-
|
|
146
|
+
tool(
|
|
139
147
|
'abs_lint',
|
|
140
148
|
'图谱体检:死链/孤岛/缺 frontmatter/超尺寸/sources 堆积/index 漏列。',
|
|
141
149
|
{ cwd: z.string().describe('项目内任意目录') },
|
|
@@ -146,7 +154,7 @@ server.tool(
|
|
|
146
154
|
}
|
|
147
155
|
);
|
|
148
156
|
|
|
149
|
-
|
|
157
|
+
tool(
|
|
150
158
|
'abs_note',
|
|
151
159
|
'经验实时暂存:把刚踩的坑/技巧/结论一句话落进 sources/(防 context 断了流失)。Teardown 时再提炼进 concepts/。',
|
|
152
160
|
{
|
|
@@ -161,7 +169,7 @@ server.tool(
|
|
|
161
169
|
}
|
|
162
170
|
);
|
|
163
171
|
|
|
164
|
-
|
|
172
|
+
tool(
|
|
165
173
|
'abs_wrapup',
|
|
166
174
|
'收尾保险:把当前 todo 未完成任务快照到 ~/.abs/log/wrapup.log(下会话 load 时展示滞留对账)。',
|
|
167
175
|
{ cwd: z.string().describe('项目内任意目录') },
|
package/package.json
CHANGED
package/src/install.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
// - OpenCode / Pi: 官方只吃 TS plugin/extension(无 shell-hook 配置) → 初版给出手工指引。
|
|
7
7
|
// 纪律: 幂等(重复安装=更新)、原子写(tmp+rename)、卸载只删自己装的、写入前备份。
|
|
8
8
|
import { promises as fs } from 'node:fs';
|
|
9
|
+
import * as fsSync from 'node:fs';
|
|
9
10
|
import { homedir } from 'node:os';
|
|
10
11
|
import { join, dirname, resolve } from 'node:path';
|
|
11
12
|
import { fileURLToPath } from 'node:url';
|
|
@@ -15,6 +16,31 @@ const ABS_DIR = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
|
15
16
|
const HOOK_TEMPLATE = join(ABS_DIR, 'hooks', 'event.sh');
|
|
16
17
|
const SKILL_SOURCE = join(ABS_DIR, 'skill', 'SKILL.md');
|
|
17
18
|
|
|
19
|
+
/**
|
|
20
|
+
* 写进宿主 MCP 配置的 mcp.js 路径。
|
|
21
|
+
* 坑: 直接用 ABS_DIR 是不稳定的 —— ABS_DIR = "install.js 自己住哪", 从仓库跑
|
|
22
|
+
* `abs install` 就把仓库路径写进宿主配置。之后若卸载/移动全局包, 该路径直接失效;
|
|
23
|
+
* 而 Codex 分支又"已存在即跳过", 一旦写错永不修正。
|
|
24
|
+
* 现在优先解析本包的稳定安装位置(全局 node_modules),解析不到才回退 ABS_DIR。
|
|
25
|
+
*/
|
|
26
|
+
function mcpEntryPath() {
|
|
27
|
+
// 本包名(package.json),用于反查全局安装位置
|
|
28
|
+
let pkgName = '@fanchao8609/agent_brain_sync';
|
|
29
|
+
try {
|
|
30
|
+
pkgName = JSON.parse(fsSync.readFileSync(join(ABS_DIR, 'package.json'), 'utf8')).name || pkgName;
|
|
31
|
+
} catch { /* 保持默认 */ }
|
|
32
|
+
const candidates = [
|
|
33
|
+
// npm 全局根(最常见)
|
|
34
|
+
join(dirname(process.execPath), '..', 'lib', 'node_modules', pkgName, 'bin', 'mcp.js'),
|
|
35
|
+
join(process.env.npm_config_prefix || '', 'lib', 'node_modules', pkgName, 'bin', 'mcp.js'),
|
|
36
|
+
];
|
|
37
|
+
for (const c of candidates) {
|
|
38
|
+
try { if (fsSync.existsSync(c)) return c; } catch { /* 试下一个 */ }
|
|
39
|
+
}
|
|
40
|
+
// 回退:仓库/本地安装形态
|
|
41
|
+
return join(ABS_DIR, 'bin', 'mcp.js');
|
|
42
|
+
}
|
|
43
|
+
|
|
18
44
|
const MARK = '// abs-managed (agent-brain-sync)'; // TS plugin 标记
|
|
19
45
|
const JSON_MARK_KEY = 'abs-managed'; // JSON 内我们的命名空间
|
|
20
46
|
|
|
@@ -103,7 +129,7 @@ async function installClaudeCode({ withMcp, withSkill, log }) {
|
|
|
103
129
|
settings.mcpServers = settings.mcpServers || {};
|
|
104
130
|
settings.mcpServers['abs'] = {
|
|
105
131
|
command: process.execPath,
|
|
106
|
-
args: [
|
|
132
|
+
args: [mcpEntryPath()],
|
|
107
133
|
};
|
|
108
134
|
await atomicWrite(settingsP, JSON.stringify(settings, null, 2));
|
|
109
135
|
steps.push(`✓ MCP → settings.json mcpServers.abs (stdio)`);
|
|
@@ -183,12 +209,21 @@ async function installCodex({ withMcp, withSkill, log }) {
|
|
|
183
209
|
let text = '';
|
|
184
210
|
try { text = await fs.readFile(mcpP, 'utf8'); } catch {}
|
|
185
211
|
if (!text.includes('[mcp_servers.abs]')) {
|
|
186
|
-
const block = `\n[mcp_servers.abs]\ncommand = "${process.execPath}"\nargs = ["${
|
|
212
|
+
const block = `\n[mcp_servers.abs]\ncommand = "${process.execPath}"\nargs = ["${mcpEntryPath()}"]\n`;
|
|
187
213
|
await backup(mcpP);
|
|
188
214
|
await atomicWrite(mcpP, text.replace(/\s*$/, '') + '\n' + block);
|
|
189
215
|
steps.push(`✓ MCP → ${mcpP} [mcp_servers.abs]`);
|
|
190
216
|
} else {
|
|
191
|
-
|
|
217
|
+
// 已存在也要校对路径: 旧版可能写入了仓库路径(不稳定) 或全局包已迁移。
|
|
218
|
+
const want = mcpEntryPath();
|
|
219
|
+
const re = /(\[mcp_servers\.abs\][^\[]*?args\s*=\s*\[)"[^"]*"(\])/s;
|
|
220
|
+
if (re.test(text) && !text.includes(`"${want}"`)) {
|
|
221
|
+
await backup(mcpP);
|
|
222
|
+
await atomicWrite(mcpP, text.replace(re, `$1"${want}"$2`));
|
|
223
|
+
steps.push(`✓ MCP → ${mcpP} 路径已校正 → ${want}`);
|
|
224
|
+
} else {
|
|
225
|
+
steps.push(`• MCP → ${mcpP} 已存在且路径正确, 跳过`);
|
|
226
|
+
}
|
|
192
227
|
}
|
|
193
228
|
}
|
|
194
229
|
if (withSkill) {
|
|
@@ -526,7 +561,7 @@ async function installOpenCode({ withMcp, withSkill, log }) {
|
|
|
526
561
|
cfg.mcp = cfg.mcp || {};
|
|
527
562
|
cfg.mcp['abs'] = {
|
|
528
563
|
type: 'local',
|
|
529
|
-
command: [process.execPath,
|
|
564
|
+
command: [process.execPath, mcpEntryPath()],
|
|
530
565
|
};
|
|
531
566
|
await backup(mcpP);
|
|
532
567
|
await atomicWrite(mcpP, JSON.stringify(cfg, null, 2));
|