agentbnb 9.0.2 → 9.0.3

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/dist/cli/index.js CHANGED
@@ -299,7 +299,7 @@ Skills: ${skills2.skillCount} skill(s) in ${skills2.path}`);
299
299
  }
300
300
 
301
301
  // src/cli/index.ts
302
- var VERSION = true ? "9.0.2" : "0.0.0-dev";
302
+ var VERSION = true ? "9.0.3" : "0.0.0-dev";
303
303
  function loadIdentityAuth(owner) {
304
304
  const configDir = getConfigDir();
305
305
  let keys;
@@ -560,8 +560,8 @@ program.command("publish-skills").description("Publish capabilities from skills.
560
560
  db.close();
561
561
  }
562
562
  console.log(`Published ${skills2.length} skill(s) to local registry`);
563
- for (const skill of skills2) {
564
- console.log(` - ${skill.id}: ${skill.name} (${skill.pricing.credits_per_call} cr/call)`);
563
+ for (const skill2 of skills2) {
564
+ console.log(` - ${skill2.id}: ${skill2.name} (${skill2.pricing.credits_per_call} cr/call)`);
565
565
  }
566
566
  });
567
567
  program.command("sync").description("Push all local capability cards to the configured remote registry").option("--registry <url>", "Remote registry URL (overrides config.registry)").option("--json", "Output as JSON").action(async (opts) => {
@@ -735,10 +735,10 @@ ${displayName} (${shortId}) [${tags}]`);
735
735
  const skills2 = Array.isArray(raw["skills"]) ? raw["skills"] : [];
736
736
  if (skills2.length > 0) {
737
737
  console.log(" Skills:");
738
- for (const skill of skills2) {
739
- const price = String(skill.pricing?.credits_per_call ?? "?");
740
- const desc = (skill.description ?? "").slice(0, 50);
741
- console.log(` ${col(skill.id, 24)} ${col(price + " cr", 8)} ${desc}`);
738
+ for (const skill2 of skills2) {
739
+ const price = String(skill2.pricing?.credits_per_call ?? "?");
740
+ const desc = (skill2.description ?? "").slice(0, 50);
741
+ console.log(` ${col(skill2.id, 24)} ${col(price + " cr", 8)} ${desc}`);
742
742
  }
743
743
  totalSkills += skills2.length;
744
744
  } else if (card.pricing?.credits_per_call != null) {
@@ -1496,12 +1496,12 @@ openclaw.command("sync").description("Read SOUL.md and publish/update a v2.0 cap
1496
1496
  try {
1497
1497
  const card = publishFromSoulV2(db, content, config.owner, sharedSkills);
1498
1498
  console.log(`Published card ${card.id} with ${card.skills.length} skill(s) (from ${resolvedSoulPath})`);
1499
- for (const skill of card.skills) {
1500
- const stats = getPricingStats(db, skill.name);
1499
+ for (const skill2 of card.skills) {
1500
+ const stats = getPricingStats(db, skill2.name);
1501
1501
  if (stats.count > 0) {
1502
- console.log(` ${skill.name}: ${skill.pricing.credits_per_call} cr (market: ${stats.min}-${stats.max} cr, median ${stats.median}, ${stats.count} providers)`);
1502
+ console.log(` ${skill2.name}: ${skill2.pricing.credits_per_call} cr (market: ${stats.min}-${stats.max} cr, median ${stats.median}, ${stats.count} providers)`);
1503
1503
  } else {
1504
- console.log(` ${skill.name}: ${skill.pricing.credits_per_call} cr (no market data yet)`);
1504
+ console.log(` ${skill2.name}: ${skill2.pricing.credits_per_call} cr (no market data yet)`);
1505
1505
  }
1506
1506
  }
1507
1507
  } catch (err) {
@@ -1531,8 +1531,8 @@ openclaw.command("status").description("Show OpenClaw integration status, tier c
1531
1531
  console.log(`Balance: ${status.balance} credits`);
1532
1532
  console.log(`Reserve: ${status.reserve} credits`);
1533
1533
  console.log(`Skills: ${status.skills.length}`);
1534
- for (const skill of status.skills) {
1535
- console.log(` - ${skill.id}: ${skill.name} (idle: ${skill.idle_rate ?? "N/A"}, online: ${skill.online})`);
1534
+ for (const skill2 of status.skills) {
1535
+ console.log(` - ${skill2.id}: ${skill2.name} (idle: ${skill2.idle_rate ?? "N/A"}, online: ${skill2.online})`);
1536
1536
  }
1537
1537
  } finally {
1538
1538
  db.close();
@@ -1694,6 +1694,11 @@ Feedback for skill: ${opts.skill} (${feedbacks.length} entries)
1694
1694
  }
1695
1695
  });
1696
1696
  program.command("quickstart").alias("qs").description("One-command setup: init + skills.yaml + MCP registration + serve daemon").option("--owner <name>", "Agent owner name").option("--port <port>", "Gateway port", "7700").option("--no-serve", "Skip starting background daemon").option("--no-mcp", "Skip MCP registration with Claude Code").option("--json", "Output as JSON").action(runQuickstart);
1697
+ var skill = program.command("skill").description("Skill management commands");
1698
+ skill.command("wrap").description("Wrap a CLI command as a rentable AgentBnB skill").option("--name <name>", "Skill name").option("--command <cmd>", "Command template with ${params.x} placeholders").option("--description <desc>", "Short description").option("--price <credits>", 'Price per call (number or "auto")').option("--category <cat>", "Category for pricing hints").option("--inputs <json>", "Input schema JSON override").option("--outputs <json>", "Output schema JSON override").option("--tags <tags>", "Comma-separated tags").option("--auto <binary>", "Auto-detect subcommands from CLI binary").option("--from-help <binary>", "Parse --help to generate skill definition").option("--scan", "Scan PATH for all cli-anything-* binaries").option("--dry-run", "Preview without writing").option("-y, --yes", "Skip confirmation prompts").action(async (opts) => {
1699
+ const { runSkillWrap } = await import("../skill-wrap-YLCJMFEJ.js");
1700
+ await runSkillWrap(opts);
1701
+ });
1697
1702
  var did = program.command("did").description("Decentralized Identity commands");
1698
1703
  did.command("show").description("Display local agent DID identifiers").option("--json", "Output as JSON").action(async (opts) => {
1699
1704
  const { didShow, didShowJson } = await import("../did-action-MQLDT4RF.js");
@@ -1722,7 +1727,7 @@ credits.command("grant <agent_id> <amount>").description("Admin: grant credits t
1722
1727
  await creditsGrant(agentId, amount);
1723
1728
  });
1724
1729
  program.command("mcp-server").description("Start an MCP (Model Context Protocol) server for IDE integration").action(async () => {
1725
- const { startMcpServer } = await import("../server-TGV2OPUM.js");
1730
+ const { startMcpServer } = await import("../server-OCCAVVDF.js");
1726
1731
  await startMcpServer();
1727
1732
  });
1728
1733
  await program.parseAsync(process.argv);
@@ -258,7 +258,7 @@ function registerPublishTool(server, ctx) {
258
258
  }
259
259
 
260
260
  // src/mcp/server.ts
261
- var VERSION = true ? "9.0.2" : "0.0.0-dev";
261
+ var VERSION = true ? "9.0.3" : "0.0.0-dev";
262
262
  async function startMcpServer() {
263
263
  const config = loadConfig();
264
264
  if (!config) {
@@ -0,0 +1,364 @@
1
+ import {
2
+ getConfigDir
3
+ } from "./chunk-3XPBFF6H.js";
4
+
5
+ // src/cli/skill-wrap.ts
6
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
7
+ import { join } from "path";
8
+ import { execSync } from "child_process";
9
+ import { createInterface } from "readline";
10
+ import yaml from "js-yaml";
11
+ var CATEGORY_PRICES = {
12
+ "3d-rendering": 15,
13
+ "image-processing": 8,
14
+ "video-editing": 12,
15
+ "audio-processing": 8,
16
+ "document-generation": 5,
17
+ "code-execution": 5,
18
+ "web-crawling": 3,
19
+ "data-analysis": 10,
20
+ "custom": 5
21
+ };
22
+ var BINARY_CATEGORY_HINTS = [
23
+ [["blender", "3d", "render"], "3d-rendering"],
24
+ [["gimp", "imagemagick", "magick", "sharp", "image"], "image-processing"],
25
+ [["ffmpeg", "video", "premiere", "davinci"], "video-editing"],
26
+ [["sox", "audio", "elevenlabs", "tts", "whisper"], "audio-processing"],
27
+ [["libreoffice", "pandoc", "latex", "pdf", "doc"], "document-generation"],
28
+ [["node", "python", "ruby", "code", "claude"], "code-execution"],
29
+ [["curl", "wget", "crawl", "scrape", "fetch"], "web-crawling"],
30
+ [["pandas", "data", "csv", "sql", "analyze"], "data-analysis"]
31
+ ];
32
+ function extractParamsFromTemplate(command) {
33
+ const regex = /\$\{params\.(\w+)\}/g;
34
+ const params = [];
35
+ let match;
36
+ while ((match = regex.exec(command)) !== null) {
37
+ if (!params.includes(match[1])) {
38
+ params.push(match[1]);
39
+ }
40
+ }
41
+ return params;
42
+ }
43
+ function parseHelpOutput(text) {
44
+ const lines = text.split("\n");
45
+ const subcommands = [];
46
+ let description = "";
47
+ for (const line of lines) {
48
+ const trimmed = line.trim();
49
+ if (!trimmed) continue;
50
+ if (/^(usage|options|commands|flags):/i.test(trimmed)) continue;
51
+ if (trimmed.startsWith("-")) continue;
52
+ if (trimmed.startsWith("$")) continue;
53
+ description = trimmed;
54
+ break;
55
+ }
56
+ let inCommandSection = false;
57
+ for (const line of lines) {
58
+ const trimmed = line.trim();
59
+ if (/^(commands|available commands|subcommands|positional arguments):/i.test(trimmed)) {
60
+ inCommandSection = true;
61
+ continue;
62
+ }
63
+ if (inCommandSection && /^(options|flags|global|examples):/i.test(trimmed)) {
64
+ inCommandSection = false;
65
+ continue;
66
+ }
67
+ if (inCommandSection && trimmed) {
68
+ const match = trimmed.match(/^(\S+)\s{2,}(.+)$/);
69
+ if (match) {
70
+ subcommands.push({ name: match[1], description: match[2].trim() });
71
+ }
72
+ }
73
+ }
74
+ return { description, subcommands };
75
+ }
76
+ async function detectCliInfo(binary) {
77
+ try {
78
+ execSync(`which ${binary}`, { stdio: "pipe", timeout: 5e3 });
79
+ } catch {
80
+ throw new Error(`CLI not found: ${binary}. Is it installed and on PATH?`);
81
+ }
82
+ let helpText = "";
83
+ try {
84
+ helpText = execSync(`${binary} --help 2>&1`, { encoding: "utf-8", timeout: 1e4 });
85
+ } catch (err) {
86
+ const stderr = err.stdout ?? "";
87
+ helpText = stderr || `CLI tool: ${binary}`;
88
+ }
89
+ const parsed = parseHelpOutput(helpText);
90
+ const baseName = binary.replace(/^cli-anything-/, "");
91
+ return {
92
+ name: baseName,
93
+ description: parsed.description || `CLI tool: ${binary}`,
94
+ subcommands: parsed.subcommands
95
+ };
96
+ }
97
+ function suggestPrice(binary, category) {
98
+ if (category && CATEGORY_PRICES[category] !== void 0) {
99
+ return CATEGORY_PRICES[category];
100
+ }
101
+ const lower = binary.toLowerCase();
102
+ for (const [keywords, cat] of BINARY_CATEGORY_HINTS) {
103
+ if (keywords.some((kw) => lower.includes(kw))) {
104
+ return CATEGORY_PRICES[cat] ?? 5;
105
+ }
106
+ }
107
+ return 5;
108
+ }
109
+ function getSkillsYamlPath(configDir) {
110
+ return join(configDir ?? getConfigDir(), "skills.yaml");
111
+ }
112
+ function appendToSkillsYaml(skillDef, configDir) {
113
+ const dir = configDir ?? getConfigDir();
114
+ const yamlPath = getSkillsYamlPath(dir);
115
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
116
+ let skills = [];
117
+ if (existsSync(yamlPath)) {
118
+ const content = readFileSync(yamlPath, "utf-8");
119
+ const parsed = yaml.load(content);
120
+ if (Array.isArray(parsed)) {
121
+ skills = parsed;
122
+ } else if (parsed && typeof parsed === "object" && "skills" in parsed) {
123
+ skills = parsed.skills ?? [];
124
+ }
125
+ }
126
+ const newId = skillDef["id"];
127
+ const existing = skills.find((s) => s["id"] === newId);
128
+ if (existing) {
129
+ throw new Error(`Skill "${newId}" already exists in skills.yaml. Remove it first or use a different name.`);
130
+ }
131
+ skills.push(skillDef);
132
+ const header = "# AgentBnB skills configuration \u2014 managed by agentbnb skill wrap\n";
133
+ writeFileSync(yamlPath, header + yaml.dump(skills, { lineWidth: 120 }), "utf-8");
134
+ }
135
+ function scanCliAnythingBinaries() {
136
+ try {
137
+ const result = execSync(`bash -c 'compgen -c | grep "^cli-anything-" | sort -u'`, {
138
+ encoding: "utf-8",
139
+ timeout: 1e4
140
+ });
141
+ return result.trim().split("\n").filter(Boolean);
142
+ } catch {
143
+ const pathDirs = (process.env["PATH"] ?? "").split(":");
144
+ const found = /* @__PURE__ */ new Set();
145
+ for (const dir of pathDirs) {
146
+ try {
147
+ const entries = execSync(`ls "${dir}" 2>/dev/null | grep "^cli-anything-"`, {
148
+ encoding: "utf-8",
149
+ timeout: 5e3
150
+ });
151
+ for (const entry of entries.trim().split("\n").filter(Boolean)) {
152
+ found.add(entry);
153
+ }
154
+ } catch {
155
+ }
156
+ }
157
+ return [...found].sort();
158
+ }
159
+ }
160
+ async function prompt(question, defaultVal) {
161
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
162
+ const suffix = defaultVal ? ` (${defaultVal})` : "";
163
+ return new Promise((resolve) => {
164
+ rl.question(`${question}${suffix}: `, (answer) => {
165
+ rl.close();
166
+ resolve(answer.trim() || defaultVal || "");
167
+ });
168
+ });
169
+ }
170
+ async function runSkillWrap(opts) {
171
+ if (opts.scan) {
172
+ const binaries = scanCliAnythingBinaries();
173
+ if (binaries.length === 0) {
174
+ console.log("No cli-anything-* binaries found on PATH.");
175
+ return;
176
+ }
177
+ console.log(`Found ${binaries.length} CLI-Anything tool(s):`);
178
+ binaries.forEach((b) => console.log(` ${b}`));
179
+ if (!opts.yes && !opts.dryRun) {
180
+ const confirm = await prompt("\nWrap all as skills? (Y/n)", "Y");
181
+ if (confirm.toLowerCase() === "n") return;
182
+ }
183
+ let totalSkills = 0;
184
+ for (const binary of binaries) {
185
+ try {
186
+ const info = await detectCliInfo(binary);
187
+ const created = await wrapDetectedCli(binary, info, opts);
188
+ totalSkills += created;
189
+ } catch (err) {
190
+ console.error(` Skipping ${binary}: ${err.message}`);
191
+ }
192
+ }
193
+ console.log(`
194
+ Created ${totalSkills} skill(s) from ${binaries.length} CLI(s).`);
195
+ if (!opts.dryRun) {
196
+ console.log(`Run 'agentbnb serve' to start accepting requests.`);
197
+ }
198
+ return;
199
+ }
200
+ if (opts.auto) {
201
+ const info = await detectCliInfo(opts.auto);
202
+ await wrapDetectedCli(opts.auto, info, opts);
203
+ return;
204
+ }
205
+ if (opts.fromHelp) {
206
+ const info = await detectCliInfo(opts.fromHelp);
207
+ if (info.subcommands.length === 0) {
208
+ const name = opts.name ?? info.name;
209
+ const price2 = resolvePrice(opts.price, opts.fromHelp, opts.category);
210
+ await wrapSingleSkill({
211
+ name,
212
+ command: `${opts.fromHelp} \${params.input}`,
213
+ description: opts.description ?? info.description,
214
+ price: price2,
215
+ category: opts.category,
216
+ tags: opts.tags,
217
+ dryRun: opts.dryRun
218
+ });
219
+ } else {
220
+ await wrapDetectedCli(opts.fromHelp, info, opts);
221
+ }
222
+ return;
223
+ }
224
+ if (!opts.name && !opts.command) {
225
+ const command = await prompt("CLI command to wrap");
226
+ if (!command) {
227
+ console.error("Command is required.");
228
+ process.exit(1);
229
+ }
230
+ const baseName = command.split(/\s+/)[0].replace(/^.*\//, "").replace(/^cli-anything-/, "");
231
+ const name = await prompt("Skill name", baseName);
232
+ const description = await prompt("Short description");
233
+ const priceStr = await prompt("Price (credits per call)", "5");
234
+ const category = await prompt("Category (optional)");
235
+ opts = { ...opts, name, command, description, price: priceStr, category: category || void 0 };
236
+ }
237
+ if (!opts.name || !opts.command) {
238
+ console.error("Error: --name and --command are required (or use --auto/--from-help/--scan).");
239
+ process.exit(1);
240
+ }
241
+ const price = resolvePrice(opts.price, opts.command, opts.category);
242
+ await wrapSingleSkill({
243
+ name: opts.name,
244
+ command: opts.command,
245
+ description: opts.description,
246
+ price,
247
+ category: opts.category,
248
+ tags: opts.tags,
249
+ inputs: opts.inputs,
250
+ outputs: opts.outputs,
251
+ dryRun: opts.dryRun
252
+ });
253
+ }
254
+ function resolvePrice(priceStr, binary, category) {
255
+ if (!priceStr || priceStr === "auto") {
256
+ return suggestPrice(binary, category);
257
+ }
258
+ const n = parseInt(priceStr, 10);
259
+ if (!Number.isFinite(n) || n < 1) {
260
+ console.error('Error: --price must be a positive integer or "auto".');
261
+ process.exit(1);
262
+ }
263
+ return n;
264
+ }
265
+ async function wrapSingleSkill(opts) {
266
+ const params = extractParamsFromTemplate(opts.command);
267
+ const baseCommand = opts.command.split(/\s+/)[0] ?? "";
268
+ const skillDef = {
269
+ id: opts.name,
270
+ type: "command",
271
+ name: opts.name,
272
+ description: opts.description || `Wrapped CLI: ${baseCommand}`,
273
+ command: opts.command,
274
+ output_type: "text",
275
+ pricing: { credits_per_call: opts.price }
276
+ };
277
+ if (opts.category) {
278
+ skillDef["category"] = opts.category;
279
+ }
280
+ const tags = opts.tags ? opts.tags.split(",").map((t) => t.trim()).filter(Boolean) : [];
281
+ if (tags.length > 0) {
282
+ skillDef["metadata"] = { tags };
283
+ }
284
+ if (opts.inputs) {
285
+ try {
286
+ skillDef["_input_hint"] = JSON.parse(opts.inputs);
287
+ } catch {
288
+ }
289
+ }
290
+ if (opts.dryRun) {
291
+ console.log("--- Dry Run Preview ---");
292
+ console.log(yaml.dump([skillDef], { lineWidth: 120 }));
293
+ console.log(`Parameters detected: ${params.length > 0 ? params.join(", ") : "(none)"}`);
294
+ console.log(`Price: ${opts.price} cr/call`);
295
+ return;
296
+ }
297
+ try {
298
+ appendToSkillsYaml(skillDef);
299
+ } catch (err) {
300
+ console.error(`Error: ${err.message}`);
301
+ process.exit(1);
302
+ }
303
+ console.log(`Created skill: ${opts.name} (${opts.price} cr/call)`);
304
+ console.log(` Command: ${opts.command}`);
305
+ if (params.length > 0) console.log(` Params: ${params.join(", ")}`);
306
+ console.log(` Added to ${getSkillsYamlPath()}`);
307
+ console.log(` Run 'agentbnb serve' to start accepting requests.`);
308
+ }
309
+ async function wrapDetectedCli(binary, info, opts) {
310
+ const baseName = binary.replace(/^cli-anything-/, "");
311
+ if (info.subcommands.length === 0) {
312
+ const price = resolvePrice(opts.price, binary, opts.category);
313
+ await wrapSingleSkill({
314
+ name: opts.name ?? baseName,
315
+ command: `${binary} \${params.input}`,
316
+ description: opts.description ?? info.description,
317
+ price,
318
+ category: opts.category,
319
+ tags: opts.tags,
320
+ dryRun: opts.dryRun
321
+ });
322
+ return 1;
323
+ }
324
+ console.log(`
325
+ ${binary} \u2014 ${info.description}`);
326
+ console.log(`Found ${info.subcommands.length} subcommand(s):`);
327
+ for (const sub of info.subcommands) {
328
+ const price = suggestPrice(`${baseName}-${sub.name}`, opts.category);
329
+ console.log(` ${sub.name.padEnd(20)} ${String(price).padEnd(4)} cr ${sub.description}`);
330
+ }
331
+ if (!opts.yes && !opts.dryRun) {
332
+ const confirm = await prompt("\nCreate skills for all subcommands? (Y/n)", "Y");
333
+ if (confirm.toLowerCase() === "n") return 0;
334
+ }
335
+ let created = 0;
336
+ for (const sub of info.subcommands) {
337
+ const skillName = `${baseName}-${sub.name}`;
338
+ const price = resolvePrice(opts.price, `${baseName}-${sub.name}`, opts.category);
339
+ try {
340
+ await wrapSingleSkill({
341
+ name: skillName,
342
+ command: `${binary} ${sub.name} \${params.input}`,
343
+ description: sub.description,
344
+ price,
345
+ category: opts.category,
346
+ tags: opts.tags,
347
+ dryRun: opts.dryRun
348
+ });
349
+ created++;
350
+ } catch (err) {
351
+ console.error(` Skipping ${skillName}: ${err.message}`);
352
+ }
353
+ }
354
+ return created;
355
+ }
356
+ export {
357
+ appendToSkillsYaml,
358
+ detectCliInfo,
359
+ extractParamsFromTemplate,
360
+ parseHelpOutput,
361
+ runSkillWrap,
362
+ scanCliAnythingBinaries,
363
+ suggestPrice
364
+ };
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "workspaces": [
4
4
  "packages/*"
5
5
  ],
6
- "version": "9.0.2",
6
+ "version": "9.0.3",
7
7
  "description": "P2P Agent Capability Sharing Protocol — Airbnb for AI agent pipelines",
8
8
  "type": "module",
9
9
  "main": "dist/index.js",