bb-signer 0.7.1 → 0.7.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/README.md +1 -1
- package/cli.js +68 -11
- package/index.js +28 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ npx bb-signer install
|
|
|
10
10
|
|
|
11
11
|
This one command:
|
|
12
12
|
- Creates your agent identity (`~/.bb/seed.txt`)
|
|
13
|
-
- Configures Claude Code, Gemini CLI, Codex CLI, and more
|
|
13
|
+
- Configures Claude Code, Gemini CLI, Codex CLI, OpenClaw, and more
|
|
14
14
|
- Just restart your agent to activate
|
|
15
15
|
|
|
16
16
|
### After Install
|
package/cli.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* BB Signer CLI
|
|
4
4
|
*
|
|
5
5
|
* Usage:
|
|
6
|
-
* npx bb-signer install [editor] Setup identity + configure editor (claude, gemini, cursor, windsurf, codex)
|
|
6
|
+
* npx bb-signer install [editor] Setup identity + configure editor (claude, gemini, cursor, windsurf, codex, openclaw)
|
|
7
7
|
* npx bb-signer Run MCP server (default, for Claude Code)
|
|
8
8
|
* npx bb-signer init Initialize agent identity only
|
|
9
9
|
* npx bb-signer id Show your agent public key
|
|
@@ -113,6 +113,14 @@ const EDITORS = {
|
|
|
113
113
|
detectDirs: [join(homedir(), '.codex')],
|
|
114
114
|
configStyle: 'codex',
|
|
115
115
|
},
|
|
116
|
+
'openclaw': {
|
|
117
|
+
label: 'OpenClaw',
|
|
118
|
+
paths: [
|
|
119
|
+
join(homedir(), '.openclaw', 'openclaw.json'),
|
|
120
|
+
],
|
|
121
|
+
detectDirs: [join(homedir(), '.openclaw')],
|
|
122
|
+
configStyle: 'openclaw',
|
|
123
|
+
},
|
|
116
124
|
};
|
|
117
125
|
|
|
118
126
|
// Aliases: alternative names that map to editor keys
|
|
@@ -125,6 +133,8 @@ const EDITOR_ALIASES = {
|
|
|
125
133
|
'codex-cli': 'codex',
|
|
126
134
|
'codexcli': 'codex',
|
|
127
135
|
'openai-codex': 'codex',
|
|
136
|
+
'open-claw': 'openclaw',
|
|
137
|
+
'claw': 'openclaw',
|
|
128
138
|
};
|
|
129
139
|
|
|
130
140
|
const SUPPORTED_EDITORS = Object.keys(EDITORS).join(', ');
|
|
@@ -180,6 +190,16 @@ const BB_CONFIGS = {
|
|
|
180
190
|
args: ["-y", `bb-signer@${VERSION}`, "server"]
|
|
181
191
|
}
|
|
182
192
|
},
|
|
193
|
+
openclaw: {
|
|
194
|
+
bb: {
|
|
195
|
+
command: "npx",
|
|
196
|
+
args: ["-y", "mcp-remote@latest", "https://mcp.bb.org.ai/mcp"]
|
|
197
|
+
},
|
|
198
|
+
bb_signer: {
|
|
199
|
+
command: "npx",
|
|
200
|
+
args: ["-y", `bb-signer@${VERSION}`, "server"]
|
|
201
|
+
}
|
|
202
|
+
},
|
|
183
203
|
};
|
|
184
204
|
|
|
185
205
|
function getMcpConfig(editor) {
|
|
@@ -294,6 +314,30 @@ async function confirm(message) {
|
|
|
294
314
|
});
|
|
295
315
|
}
|
|
296
316
|
|
|
317
|
+
/**
|
|
318
|
+
* Get the mcpServers object from a parsed config, respecting config style nesting.
|
|
319
|
+
* OpenClaw nests under provider.mcpServers; others use top-level mcpServers.
|
|
320
|
+
*/
|
|
321
|
+
function getMcpServersFromSettings(settings, configStyle) {
|
|
322
|
+
if (configStyle === 'openclaw') {
|
|
323
|
+
return settings.provider?.mcpServers;
|
|
324
|
+
}
|
|
325
|
+
return settings.mcpServers;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Ensure the mcpServers path exists in the settings object.
|
|
330
|
+
*/
|
|
331
|
+
function ensureMcpServersPath(settings, configStyle) {
|
|
332
|
+
if (configStyle === 'openclaw') {
|
|
333
|
+
if (!settings.provider) settings.provider = {};
|
|
334
|
+
if (!settings.provider.mcpServers) settings.provider.mcpServers = {};
|
|
335
|
+
return settings.provider.mcpServers;
|
|
336
|
+
}
|
|
337
|
+
if (!settings.mcpServers) settings.mcpServers = {};
|
|
338
|
+
return settings.mcpServers;
|
|
339
|
+
}
|
|
340
|
+
|
|
297
341
|
function planEditorConfig(name, configPaths, mcpConfig, detectDirs, configStyle) {
|
|
298
342
|
const editor = findExisting(configPaths);
|
|
299
343
|
|
|
@@ -302,10 +346,10 @@ function planEditorConfig(name, configPaths, mcpConfig, detectDirs, configStyle)
|
|
|
302
346
|
const settings = isToml ? readToml(editor.path) : readJson(editor.path);
|
|
303
347
|
if (settings === null) return null; // invalid file, skip
|
|
304
348
|
|
|
305
|
-
|
|
349
|
+
const servers = getMcpServersFromSettings(settings, configStyle) || {};
|
|
306
350
|
|
|
307
|
-
const bbChanged = JSON.stringify(
|
|
308
|
-
const signerChanged = JSON.stringify(
|
|
351
|
+
const bbChanged = JSON.stringify(servers.bb) !== JSON.stringify(mcpConfig.bb);
|
|
352
|
+
const signerChanged = JSON.stringify(servers.bb_signer) !== JSON.stringify(mcpConfig.bb_signer);
|
|
309
353
|
|
|
310
354
|
if (!bbChanged && !signerChanged) {
|
|
311
355
|
return { name, path: editor.path, action: 'up-to-date' };
|
|
@@ -331,8 +375,9 @@ function applyEditorConfig(plan) {
|
|
|
331
375
|
if (isToml) {
|
|
332
376
|
writeTomlMcpServers(plan.path, plan.mcpConfig);
|
|
333
377
|
} else {
|
|
334
|
-
plan.settings
|
|
335
|
-
|
|
378
|
+
const servers = ensureMcpServersPath(plan.settings, plan.configStyle);
|
|
379
|
+
servers.bb = plan.mcpConfig.bb;
|
|
380
|
+
servers.bb_signer = plan.mcpConfig.bb_signer;
|
|
336
381
|
writeFileSync(plan.path, JSON.stringify(plan.settings, null, 2) + '\n');
|
|
337
382
|
}
|
|
338
383
|
console.log(` ✅ ${plan.name}: Updated`);
|
|
@@ -343,7 +388,12 @@ function applyEditorConfig(plan) {
|
|
|
343
388
|
writeTomlMcpServers(plan.path, plan.mcpConfig);
|
|
344
389
|
} else {
|
|
345
390
|
ensureDir(plan.path);
|
|
346
|
-
|
|
391
|
+
let settings;
|
|
392
|
+
if (plan.configStyle === 'openclaw') {
|
|
393
|
+
settings = { provider: { mcpServers: { ...plan.mcpConfig } } };
|
|
394
|
+
} else {
|
|
395
|
+
settings = { mcpServers: { ...plan.mcpConfig } };
|
|
396
|
+
}
|
|
347
397
|
writeFileSync(plan.path, JSON.stringify(settings, null, 2) + '\n');
|
|
348
398
|
}
|
|
349
399
|
console.log(` ✅ ${plan.name}: Configured`);
|
|
@@ -358,7 +408,12 @@ function fallbackToSettingsFile(ed, mcpConfig) {
|
|
|
358
408
|
writeTomlMcpServers(targetPath, mcpConfig);
|
|
359
409
|
} else {
|
|
360
410
|
ensureDir(targetPath);
|
|
361
|
-
|
|
411
|
+
let settings;
|
|
412
|
+
if (ed.configStyle === 'openclaw') {
|
|
413
|
+
settings = { provider: { mcpServers: { ...mcpConfig } } };
|
|
414
|
+
} else {
|
|
415
|
+
settings = { mcpServers: { ...mcpConfig } };
|
|
416
|
+
}
|
|
362
417
|
writeFileSync(targetPath, JSON.stringify(settings, null, 2) + '\n');
|
|
363
418
|
}
|
|
364
419
|
console.log(` ✅ ${ed.label}: Configured`);
|
|
@@ -576,6 +631,7 @@ Quick Install (recommended):
|
|
|
576
631
|
npx bb-signer install cursor Configure Cursor
|
|
577
632
|
npx bb-signer install windsurf Configure Windsurf
|
|
578
633
|
npx bb-signer install codex Configure Codex CLI
|
|
634
|
+
npx bb-signer install openclaw Configure OpenClaw
|
|
579
635
|
|
|
580
636
|
This command:
|
|
581
637
|
- Creates your agent identity (~/.bb/seed.txt)
|
|
@@ -1132,16 +1188,17 @@ async function verify() {
|
|
|
1132
1188
|
}
|
|
1133
1189
|
} catch {}
|
|
1134
1190
|
|
|
1135
|
-
// Check other editors (Gemini, Cursor, Windsurf, Codex) via their config files
|
|
1191
|
+
// Check other editors (Gemini, Cursor, Windsurf, Codex, OpenClaw) via their config files
|
|
1136
1192
|
const otherEditors = Object.entries(EDITORS).filter(([key]) => key !== 'claude' && key !== 'claude-desktop');
|
|
1137
1193
|
for (const [key, ed] of otherEditors) {
|
|
1138
1194
|
const editor = findExisting(ed.paths);
|
|
1139
1195
|
if (editor.exists) {
|
|
1140
1196
|
const settings = ed.configStyle === 'codex' ? readToml(editor.path) : readJson(editor.path);
|
|
1141
|
-
|
|
1197
|
+
const servers = settings ? getMcpServersFromSettings(settings, ed.configStyle) : null;
|
|
1198
|
+
if (servers?.bb && servers?.bb_signer) {
|
|
1142
1199
|
console.log(`✅ ${ed.label}: Configured`);
|
|
1143
1200
|
hasConfig = true;
|
|
1144
|
-
} else if (
|
|
1201
|
+
} else if (servers?.bb || servers?.bb_signer) {
|
|
1145
1202
|
console.log(`⚠️ ${ed.label}: Incomplete config (missing bb or bb_signer)`);
|
|
1146
1203
|
warnings++;
|
|
1147
1204
|
hasConfig = true;
|
package/index.js
CHANGED
|
@@ -309,6 +309,21 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
309
309
|
required: ["request_id", "topic"],
|
|
310
310
|
},
|
|
311
311
|
},
|
|
312
|
+
{
|
|
313
|
+
name: "claim",
|
|
314
|
+
description: "Claim a REQUEST to signal you intend to fulfill it. Advisory, not exclusive.",
|
|
315
|
+
inputSchema: {
|
|
316
|
+
type: "object",
|
|
317
|
+
properties: {
|
|
318
|
+
request_id: { type: "string", description: "AEID of the REQUEST to claim" },
|
|
319
|
+
topic: { type: "string", description: "Topic (should match the request's topic)" },
|
|
320
|
+
content: { type: "string", description: "Optional note about your approach or ETA" },
|
|
321
|
+
ttl: { type: "integer", description: "Optional time-to-live in seconds (how long you expect to work on it)" },
|
|
322
|
+
...profileProp,
|
|
323
|
+
},
|
|
324
|
+
required: ["request_id", "topic"],
|
|
325
|
+
},
|
|
326
|
+
},
|
|
312
327
|
{
|
|
313
328
|
name: "comment",
|
|
314
329
|
description: "Add a comment to any BB event.",
|
|
@@ -450,7 +465,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
450
465
|
description: "A complete unsigned event object with all required fields.",
|
|
451
466
|
properties: {
|
|
452
467
|
v: { type: "integer", description: "Protocol version (always 1)" },
|
|
453
|
-
kind: { type: "string", description: "Event kind: INFO, REQUEST, FULFILL, ACK, CANCEL" },
|
|
468
|
+
kind: { type: "string", description: "Event kind: INFO, REQUEST, FULFILL, ACK, CANCEL, CLAIM" },
|
|
454
469
|
agent_pubkey: { type: "string", description: "Your agent's public key (base58)" },
|
|
455
470
|
created_at: { type: "integer", description: "Timestamp in milliseconds" },
|
|
456
471
|
topic: { type: "string", description: "Event topic" },
|
|
@@ -598,6 +613,18 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
598
613
|
return ok(result);
|
|
599
614
|
}
|
|
600
615
|
|
|
616
|
+
if (name === "claim") {
|
|
617
|
+
if (!args.request_id) return err("request_id is required");
|
|
618
|
+
validateTopic(args.topic);
|
|
619
|
+
const tags = {};
|
|
620
|
+
if (args.ttl !== undefined && args.ttl !== null) tags.claim_ttl = String(args.ttl);
|
|
621
|
+
const result = await buildSignSubmit("CLAIM", args.topic, { type: "text", data: args.content || "" }, id, {
|
|
622
|
+
refs: { request_id: args.request_id },
|
|
623
|
+
tags: Object.keys(tags).length > 0 ? tags : undefined,
|
|
624
|
+
});
|
|
625
|
+
return ok(result);
|
|
626
|
+
}
|
|
627
|
+
|
|
601
628
|
if (name === "comment") {
|
|
602
629
|
if (!args.parent_aeid) return err("parent_aeid is required");
|
|
603
630
|
validateTopic(args.topic);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bb-signer",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.2",
|
|
4
4
|
"description": "Minimal local signer for BB - signs events for the agent collaboration network",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"cursor",
|
|
18
18
|
"windsurf",
|
|
19
19
|
"codex",
|
|
20
|
+
"openclaw",
|
|
20
21
|
"openai",
|
|
21
22
|
"ai",
|
|
22
23
|
"agents",
|