agentbnb 6.0.0 → 7.0.0

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 (58) hide show
  1. package/README.md +245 -39
  2. package/dist/{card-REW7BSWW.js → card-EX2EYGCZ.js} +1 -1
  3. package/dist/{chunk-C6KPAFCC.js → chunk-3LWBH7P3.js} +94 -3
  4. package/dist/{chunk-YRRVFTDR.js → chunk-5AAFG2V2.js} +3 -3
  5. package/dist/{chunk-C2T4BMRW.js → chunk-5GME4KJZ.js} +8 -6
  6. package/dist/{chunk-VPQ44XKE.js → chunk-64AK4FJM.js} +2 -2
  7. package/dist/{chunk-2TLZ6G2B.js → chunk-7EF3HYVZ.js} +158 -18
  8. package/dist/{chunk-JR6TJDIF.js → chunk-ALX4WS3A.js} +9 -4
  9. package/dist/{chunk-7XHDSWRD.js → chunk-B2VJTKO5.js} +2 -2
  10. package/dist/{chunk-TR6UZDNX.js → chunk-C537SFHV.js} +8 -6
  11. package/dist/{chunk-F53QQIM2.js → chunk-CUONY5TO.js} +1 -1
  12. package/dist/chunk-D6RKW2XG.js +395 -0
  13. package/dist/{chunk-NYV3NE5Z.js → chunk-E2OKP5CY.js} +4 -4
  14. package/dist/{chunk-TQDV254A.js → chunk-FTZTEHYG.js} +117 -117
  15. package/dist/{chunk-Y7T6IMM3.js → chunk-GKVTD4EZ.js} +1 -1
  16. package/dist/{chunk-VMH2YS2I.js → chunk-KF3TZHA5.js} +1 -1
  17. package/dist/{chunk-574W3HHE.js → chunk-LJM7FHPM.js} +1 -1
  18. package/dist/chunk-NWIQJ2CL.js +108 -0
  19. package/dist/{chunk-KA2VIEGM.js → chunk-O2OYBAVR.js} +1 -1
  20. package/dist/{chunk-NQTE577Q.js → chunk-OCSU2S6W.js} +9 -0
  21. package/dist/{chunk-PSQHUZ7X.js → chunk-OH7BP5NP.js} +1 -1
  22. package/dist/chunk-SSK653A6.js +169 -0
  23. package/dist/{chunk-BP3L2TET.js → chunk-TBJ3FZKZ.js} +2 -2
  24. package/dist/{chunk-3CIMVISQ.js → chunk-WVY2W7AA.js} +4 -0
  25. package/dist/{chunk-OZXCRLP3.js → chunk-X32NE6V4.js} +5 -2
  26. package/dist/{chunk-7YLFLC5C.js → chunk-YHY7OG6S.js} +5 -5
  27. package/dist/{chunk-JOY533UH.js → chunk-Z4MCGKTL.js} +6 -2
  28. package/dist/cli/index.js +530 -269
  29. package/dist/{client-HRYRJKSA.js → client-HKV3QWZ3.js} +3 -3
  30. package/dist/{conduct-LF6FYPLD.js → conduct-W6XF6DJW.js} +14 -13
  31. package/dist/conduct-YB64OHI6.js +22 -0
  32. package/dist/{conductor-mode-NUDQLZFM.js → conductor-mode-2GSLHVN6.js} +7 -4
  33. package/dist/{conductor-mode-YQ6QSPPT.js → conductor-mode-AKREGDIU.js} +11 -10
  34. package/dist/execute-AYQWORVH.js +15 -0
  35. package/dist/{execute-ITHIYYOX.js → execute-EPE6MZLT.js} +4 -3
  36. package/dist/index.d.ts +502 -12
  37. package/dist/index.js +706 -53
  38. package/dist/{process-guard-QCCBGILS.js → process-guard-GH5LRNWO.js} +1 -1
  39. package/dist/{publish-capability-TS6CNR5G.js → publish-capability-AH2HDW54.js} +3 -3
  40. package/dist/reliability-metrics-QG7WC5QK.js +18 -0
  41. package/dist/{request-P6QCTCCG.js → request-HCCXSKAY.js} +15 -14
  42. package/dist/{serve-skill-EZOL7UYN.js → serve-skill-SZAQT5T5.js} +9 -8
  43. package/dist/{server-3G6ZTASA.js → server-MHMAYXWZ.js} +12 -11
  44. package/dist/{service-coordinator-CRSE4GWC.js → service-coordinator-WGH6B2VT.js} +572 -68
  45. package/dist/{skill-config-4W5W5O6T.js → skill-config-FETXPNVP.js} +1 -1
  46. package/dist/skills/agentbnb/bootstrap.js +594 -73
  47. package/dist/{websocket-client-WRN3HO73.js → websocket-client-4Z5P54RU.js} +1 -1
  48. package/dist/websocket-client-QOVARTRN.js +7 -0
  49. package/openclaw.plugin.json +2 -2
  50. package/package.json +18 -11
  51. package/skills/agentbnb/bootstrap.test.ts +9 -0
  52. package/skills/agentbnb/bootstrap.ts +51 -26
  53. package/skills/agentbnb/install.sh +0 -0
  54. package/dist/chunk-QT7TEVNV.js +0 -82
  55. package/dist/chunk-RVYQSC6L.js +0 -212
  56. package/dist/conduct-QAFZIEY6.js +0 -21
  57. package/dist/execute-PNJFABVJ.js +0 -14
  58. package/dist/websocket-client-6IIDGXKB.js +0 -7
package/dist/cli/index.js CHANGED
@@ -6,53 +6,57 @@ import {
6
6
  detectOpenPorts,
7
7
  discoverLocalAgents,
8
8
  getPricingStats
9
- } from "../chunk-TQDV254A.js";
9
+ } from "../chunk-FTZTEHYG.js";
10
10
  import {
11
11
  ensureIdentity
12
- } from "../chunk-PSQHUZ7X.js";
13
- import {
14
- createLedger
15
- } from "../chunk-YRRVFTDR.js";
12
+ } from "../chunk-OH7BP5NP.js";
16
13
  import {
17
14
  releaseRequesterEscrow,
18
15
  settleRequesterEscrow
19
- } from "../chunk-OZXCRLP3.js";
16
+ } from "../chunk-X32NE6V4.js";
17
+ import {
18
+ createLedger
19
+ } from "../chunk-5AAFG2V2.js";
20
20
  import {
21
21
  parseSoulMd
22
- } from "../chunk-BP3L2TET.js";
22
+ } from "../chunk-TBJ3FZKZ.js";
23
23
  import {
24
24
  AutoRequestor,
25
25
  BudgetManager,
26
26
  DEFAULT_BUDGET_CONFIG
27
- } from "../chunk-C2T4BMRW.js";
27
+ } from "../chunk-5GME4KJZ.js";
28
28
  import {
29
29
  fetchRemoteCards,
30
30
  mergeResults
31
- } from "../chunk-VMH2YS2I.js";
31
+ } from "../chunk-KF3TZHA5.js";
32
32
  import {
33
33
  DEFAULT_AUTONOMY_CONFIG
34
- } from "../chunk-Y7T6IMM3.js";
34
+ } from "../chunk-GKVTD4EZ.js";
35
35
  import {
36
36
  filterCards,
37
37
  searchCards
38
- } from "../chunk-574W3HHE.js";
38
+ } from "../chunk-LJM7FHPM.js";
39
39
  import {
40
40
  bootstrapAgent,
41
+ createAgentRecord,
41
42
  getBalance,
42
43
  getTransactions,
43
44
  holdEscrow,
45
+ lookupAgent,
46
+ lookupAgentByOwner,
44
47
  migrateOwner,
45
48
  openCreditDb
46
- } from "../chunk-RVYQSC6L.js";
49
+ } from "../chunk-D6RKW2XG.js";
50
+ import "../chunk-NWIQJ2CL.js";
47
51
  import {
48
52
  requestCapability
49
- } from "../chunk-VPQ44XKE.js";
53
+ } from "../chunk-64AK4FJM.js";
50
54
  import {
51
55
  generateKeyPair,
52
56
  loadKeyPair,
53
57
  saveKeyPair,
54
58
  signEscrowReceipt
55
- } from "../chunk-F53QQIM2.js";
59
+ } from "../chunk-CUONY5TO.js";
56
60
  import {
57
61
  findPeer,
58
62
  loadPeers,
@@ -70,27 +74,28 @@ import {
70
74
  insertCard,
71
75
  listCards,
72
76
  openDatabase
73
- } from "../chunk-KA2VIEGM.js";
77
+ } from "../chunk-O2OYBAVR.js";
74
78
  import {
75
79
  AgentBnBError,
76
80
  AnyCardSchema,
77
81
  CapabilityCardV2Schema
78
- } from "../chunk-3CIMVISQ.js";
82
+ } from "../chunk-WVY2W7AA.js";
79
83
 
80
84
  // src/cli/index.ts
81
85
  import { Command } from "commander";
82
- import { readFileSync as readFileSync3 } from "fs";
86
+ import { readFileSync as readFileSync4 } from "fs";
83
87
  import { createRequire } from "module";
84
- import { randomBytes, randomUUID as randomUUID4 } from "crypto";
85
- import { join as join2 } from "path";
86
- import { networkInterfaces } from "os";
87
- import { createInterface as createInterface2 } from "readline";
88
+ import { randomUUID as randomUUID4 } from "crypto";
89
+ import { join as join4 } from "path";
90
+ import { networkInterfaces as networkInterfaces2 } from "os";
91
+ import { createInterface as createInterface3 } from "readline";
88
92
 
89
93
  // src/credit/escrow-receipt.ts
90
94
  import { z } from "zod";
91
95
  import { randomUUID } from "crypto";
92
96
  var EscrowReceiptSchema = z.object({
93
97
  requester_owner: z.string().min(1),
98
+ requester_agent_id: z.string().optional(),
94
99
  requester_public_key: z.string().min(1),
95
100
  amount: z.number().positive(),
96
101
  card_id: z.string().min(1),
@@ -103,6 +108,7 @@ function createSignedEscrowReceipt(db, privateKey, publicKey, opts) {
103
108
  const escrowId = holdEscrow(db, opts.owner, opts.amount, opts.cardId);
104
109
  const receiptData = {
105
110
  requester_owner: opts.owner,
111
+ ...opts.agent_id ? { requester_agent_id: opts.agent_id } : {},
106
112
  requester_public_key: publicKey.toString("hex"),
107
113
  amount: opts.amount,
108
114
  card_id: opts.cardId,
@@ -118,183 +124,8 @@ function createSignedEscrowReceipt(db, privateKey, publicKey, opts) {
118
124
  return { escrowId, receipt };
119
125
  }
120
126
 
121
- // src/onboarding/index.ts
122
- import { randomUUID as randomUUID2 } from "crypto";
123
- import { existsSync, readFileSync } from "fs";
124
- import { join } from "path";
125
-
126
- // src/onboarding/capability-templates.ts
127
- var API_PATTERNS = [
128
- {
129
- pattern: /openai|gpt-4|gpt-3|chatgpt|dall-e/i,
130
- capability: { key: "openai", name: "OpenAI Text Generation", category: "Text Gen", credits_per_call: 3, tags: ["llm", "text", "generation"] }
131
- },
132
- {
133
- pattern: /elevenlabs|eleven.?labs/i,
134
- capability: { key: "elevenlabs", name: "ElevenLabs TTS", category: "TTS", credits_per_call: 5, tags: ["tts", "audio", "voice"] }
135
- },
136
- {
137
- pattern: /anthropic|claude/i,
138
- capability: { key: "anthropic", name: "Anthropic Claude", category: "Text Gen", credits_per_call: 3, tags: ["llm", "text", "generation"] }
139
- },
140
- {
141
- pattern: /recraft/i,
142
- capability: { key: "recraft", name: "Recraft V4 Image Gen", category: "Image Gen", credits_per_call: 8, tags: ["image", "generation", "design"] }
143
- },
144
- {
145
- pattern: /kling/i,
146
- capability: { key: "kling", name: "Kling AI Video Gen", category: "Video Gen", credits_per_call: 10, tags: ["video", "generation"] }
147
- },
148
- {
149
- pattern: /stable.?diffusion|sdxl|comfyui/i,
150
- capability: { key: "stable-diffusion", name: "Stable Diffusion Image Gen", category: "Image Gen", credits_per_call: 6, tags: ["image", "generation", "diffusion"] }
151
- },
152
- {
153
- pattern: /whisper|speech.?to.?text|stt/i,
154
- capability: { key: "whisper", name: "Whisper Speech-to-Text", category: "STT", credits_per_call: 3, tags: ["stt", "audio", "transcription"] }
155
- },
156
- {
157
- pattern: /puppeteer|playwright|selenium/i,
158
- capability: { key: "puppeteer", name: "Web Scraping & Automation", category: "Web Scraping", credits_per_call: 2, tags: ["scraping", "automation", "browser"] }
159
- },
160
- {
161
- pattern: /ffmpeg/i,
162
- capability: { key: "ffmpeg", name: "FFmpeg Media Processing", category: "Media Processing", credits_per_call: 3, tags: ["media", "audio", "video", "processing"] }
163
- },
164
- {
165
- pattern: /tesseract|ocr/i,
166
- capability: { key: "tesseract", name: "OCR Text Extraction", category: "OCR", credits_per_call: 4, tags: ["ocr", "text", "extraction"] }
167
- }
168
- ];
169
- var INTERACTIVE_TEMPLATES = [
170
- { key: "openai", name: "Text Generation (GPT-4o / Claude / Gemini)", category: "Text Gen", credits_per_call: 3, tags: ["llm", "text", "generation"] },
171
- { key: "image-gen", name: "Image Generation (DALL-E / Recraft / Stable Diffusion)", category: "Image Gen", credits_per_call: 8, tags: ["image", "generation"] },
172
- { key: "tts", name: "TTS / Voice (ElevenLabs / Google TTS)", category: "TTS", credits_per_call: 5, tags: ["tts", "audio", "voice"] },
173
- { key: "video-gen", name: "Video Generation (Kling / Runway)", category: "Video Gen", credits_per_call: 10, tags: ["video", "generation"] },
174
- { key: "code-review", name: "Code Review / Analysis", category: "Code", credits_per_call: 3, tags: ["code", "review", "analysis"] },
175
- { key: "scraping", name: "Web Scraping / Data Extraction", category: "Web Scraping", credits_per_call: 2, tags: ["scraping", "data", "extraction"] },
176
- { key: "translation", name: "Translation", category: "Translation", credits_per_call: 3, tags: ["translation", "language", "text"] },
177
- { key: "custom", name: "Custom (describe it)", category: "Custom", credits_per_call: 5, tags: ["custom"] }
178
- ];
179
-
180
- // src/onboarding/detect-from-docs.ts
181
- function detectFromDocs(content) {
182
- if (!content || content.trim().length === 0) {
183
- return [];
184
- }
185
- const seen = /* @__PURE__ */ new Set();
186
- const results = [];
187
- for (const entry of API_PATTERNS) {
188
- if (entry.pattern.test(content) && !seen.has(entry.capability.key)) {
189
- seen.add(entry.capability.key);
190
- results.push({ ...entry.capability });
191
- }
192
- }
193
- return results;
194
- }
195
-
196
- // src/onboarding/interactive.ts
197
- import { createInterface } from "readline";
198
- async function interactiveTemplateMenu() {
199
- console.log("\nNo capabilities auto-detected.\n");
200
- console.log("What can your agent do? Pick from templates:\n");
201
- for (let i = 0; i < INTERACTIVE_TEMPLATES.length; i++) {
202
- console.log(` ${i + 1}. ${INTERACTIVE_TEMPLATES[i].name}`);
203
- }
204
- const rl = createInterface({ input: process.stdin, output: process.stdout });
205
- const answer = await new Promise((resolve) => {
206
- rl.question("\nSelect [1-8, comma-separated]: ", (ans) => {
207
- rl.close();
208
- resolve(ans);
209
- });
210
- });
211
- return parseSelection(answer);
212
- }
213
- function parseSelection(input) {
214
- if (!input || input.trim().length === 0) {
215
- return [];
216
- }
217
- const selected = [];
218
- const seen = /* @__PURE__ */ new Set();
219
- const parts = input.split(",").map((s) => s.trim());
220
- for (const part of parts) {
221
- const num = parseInt(part, 10);
222
- if (isNaN(num) || num < 1 || num > INTERACTIVE_TEMPLATES.length) {
223
- continue;
224
- }
225
- const template = INTERACTIVE_TEMPLATES[num - 1];
226
- if (!seen.has(template.key)) {
227
- seen.add(template.key);
228
- selected.push({ ...template });
229
- }
230
- }
231
- return selected;
232
- }
233
-
234
- // src/onboarding/index.ts
235
- var DOC_FILES = ["SOUL.md", "CLAUDE.md", "AGENTS.md", "README.md"];
236
- function detectCapabilities(opts = {}) {
237
- const cwd = opts.cwd ?? process.cwd();
238
- if (opts.fromFile) {
239
- const filePath = opts.fromFile.startsWith("/") ? opts.fromFile : join(cwd, opts.fromFile);
240
- if (existsSync(filePath)) {
241
- const content = readFileSync(filePath, "utf-8");
242
- const capabilities = detectFromDocs(content);
243
- if (capabilities.length > 0) {
244
- return { source: "docs", capabilities, sourceFile: filePath };
245
- }
246
- }
247
- return { source: "none", capabilities: [] };
248
- }
249
- for (const fileName of DOC_FILES) {
250
- const filePath = join(cwd, fileName);
251
- if (!existsSync(filePath)) continue;
252
- const content = readFileSync(filePath, "utf-8");
253
- if (fileName === "SOUL.md") {
254
- return { source: "soul", capabilities: [], soulContent: content, sourceFile: filePath };
255
- }
256
- const capabilities = detectFromDocs(content);
257
- if (capabilities.length > 0) {
258
- return { source: "docs", capabilities, sourceFile: filePath };
259
- }
260
- }
261
- const envKeys = detectApiKeys(KNOWN_API_KEYS);
262
- if (envKeys.length > 0) {
263
- return { source: "env", capabilities: [], envKeys };
264
- }
265
- return { source: "none", capabilities: [] };
266
- }
267
- function capabilitiesToV2Card(capabilities, owner, agentName) {
268
- const now = (/* @__PURE__ */ new Date()).toISOString();
269
- const skills = capabilities.map((cap) => ({
270
- id: cap.key,
271
- name: cap.name,
272
- description: `${cap.name} capability \u2014 ${cap.category}`,
273
- level: 1,
274
- category: cap.category.toLowerCase().replace(/\s+/g, "_"),
275
- inputs: [{ name: "input", type: "text", required: true }],
276
- outputs: [{ name: "output", type: "text", required: true }],
277
- pricing: { credits_per_call: cap.credits_per_call },
278
- availability: { online: true },
279
- metadata: {
280
- tags: cap.tags
281
- }
282
- }));
283
- const card = {
284
- spec_version: "2.0",
285
- id: randomUUID2(),
286
- owner,
287
- agent_name: agentName ?? owner,
288
- skills,
289
- availability: { online: true },
290
- created_at: now,
291
- updated_at: now
292
- };
293
- return CapabilityCardV2Schema.parse(card);
294
- }
295
-
296
127
  // src/openclaw/soul-sync.ts
297
- import { randomUUID as randomUUID3 } from "crypto";
128
+ import { randomUUID as randomUUID2 } from "crypto";
298
129
  var SKILL_META_GLOBAL_RE = /(?:^|\s)-\s*(capability_types|requires(?:_capabilities)?|visibility)\s*:\s*([^-][^]*?)(?=\s+-\s+(?:capability_types|requires(?:_capabilities)?|visibility)\s*:|$)/gi;
299
130
  function extractSkillMeta(raw) {
300
131
  let capability_types;
@@ -329,7 +160,7 @@ function parseSoulMdV2(content) {
329
160
  const parsed = parseSoulMd(content);
330
161
  const skills = parsed.capabilities.map((cap) => {
331
162
  const sanitizedId = cap.name.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "");
332
- const id = sanitizedId.length > 0 ? sanitizedId : randomUUID3();
163
+ const id = sanitizedId.length > 0 ? sanitizedId : randomUUID2();
333
164
  const { description: cleanDesc, capability_types, requires_capabilities, visibility } = extractSkillMeta(cap.description);
334
165
  const finalDescription = (cleanDesc || cap.name).slice(0, 500);
335
166
  const skill = {
@@ -383,7 +214,7 @@ function publishFromSoulV2(db, soulContent, owner, sharedSkills) {
383
214
  (c) => c.spec_version === "2.0"
384
215
  );
385
216
  const now = (/* @__PURE__ */ new Date()).toISOString();
386
- const cardId = existingV2?.id ?? randomUUID3();
217
+ const cardId = existingV2?.id ?? randomUUID2();
387
218
  const card = {
388
219
  spec_version: "2.0",
389
220
  id: cardId,
@@ -408,7 +239,7 @@ function publishFromSoulV2(db, soulContent, owner, sharedSkills) {
408
239
  }
409
240
 
410
241
  // src/openclaw/heartbeat-writer.ts
411
- import { readFileSync as readFileSync2, writeFileSync, existsSync as existsSync2 } from "fs";
242
+ import { readFileSync, writeFileSync, existsSync } from "fs";
412
243
  var HEARTBEAT_MARKER_START = "<!-- agentbnb:start -->";
413
244
  var HEARTBEAT_MARKER_END = "<!-- agentbnb:end -->";
414
245
  function generateHeartbeatSection(autonomy, budget) {
@@ -444,11 +275,11 @@ function generateHeartbeatSection(autonomy, budget) {
444
275
  ].join("\n");
445
276
  }
446
277
  function injectHeartbeatSection(heartbeatPath, section) {
447
- if (!existsSync2(heartbeatPath)) {
278
+ if (!existsSync(heartbeatPath)) {
448
279
  writeFileSync(heartbeatPath, section + "\n", "utf-8");
449
280
  return;
450
281
  }
451
- let content = readFileSync2(heartbeatPath, "utf-8");
282
+ let content = readFileSync(heartbeatPath, "utf-8");
452
283
  const startIdx = content.indexOf(HEARTBEAT_MARKER_START);
453
284
  const endIdx = content.indexOf(HEARTBEAT_MARKER_END);
454
285
  if (startIdx !== -1 && endIdx !== -1) {
@@ -493,9 +324,188 @@ function getOpenClawStatus(config, db, creditDb) {
493
324
  };
494
325
  }
495
326
 
496
- // src/cli/index.ts
497
- var require2 = createRequire(import.meta.url);
498
- var pkg = require2("../../package.json");
327
+ // src/cli/init-action.ts
328
+ import { randomBytes } from "crypto";
329
+ import { join as join2 } from "path";
330
+ import { networkInterfaces } from "os";
331
+
332
+ // src/onboarding/index.ts
333
+ import { randomUUID as randomUUID3 } from "crypto";
334
+ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
335
+ import { join } from "path";
336
+
337
+ // src/onboarding/capability-templates.ts
338
+ var API_PATTERNS = [
339
+ {
340
+ pattern: /openai|gpt-4|gpt-3|chatgpt|dall-e/i,
341
+ capability: { key: "openai", name: "OpenAI Text Generation", category: "Text Gen", credits_per_call: 3, tags: ["llm", "text", "generation"] }
342
+ },
343
+ {
344
+ pattern: /elevenlabs|eleven.?labs/i,
345
+ capability: { key: "elevenlabs", name: "ElevenLabs TTS", category: "TTS", credits_per_call: 5, tags: ["tts", "audio", "voice"] }
346
+ },
347
+ {
348
+ pattern: /anthropic|claude/i,
349
+ capability: { key: "anthropic", name: "Anthropic Claude", category: "Text Gen", credits_per_call: 3, tags: ["llm", "text", "generation"] }
350
+ },
351
+ {
352
+ pattern: /recraft/i,
353
+ capability: { key: "recraft", name: "Recraft V4 Image Gen", category: "Image Gen", credits_per_call: 8, tags: ["image", "generation", "design"] }
354
+ },
355
+ {
356
+ pattern: /kling/i,
357
+ capability: { key: "kling", name: "Kling AI Video Gen", category: "Video Gen", credits_per_call: 10, tags: ["video", "generation"] }
358
+ },
359
+ {
360
+ pattern: /stable.?diffusion|sdxl|comfyui/i,
361
+ capability: { key: "stable-diffusion", name: "Stable Diffusion Image Gen", category: "Image Gen", credits_per_call: 6, tags: ["image", "generation", "diffusion"] }
362
+ },
363
+ {
364
+ pattern: /whisper|speech.?to.?text|stt/i,
365
+ capability: { key: "whisper", name: "Whisper Speech-to-Text", category: "STT", credits_per_call: 3, tags: ["stt", "audio", "transcription"] }
366
+ },
367
+ {
368
+ pattern: /puppeteer|playwright|selenium/i,
369
+ capability: { key: "puppeteer", name: "Web Scraping & Automation", category: "Web Scraping", credits_per_call: 2, tags: ["scraping", "automation", "browser"] }
370
+ },
371
+ {
372
+ pattern: /ffmpeg/i,
373
+ capability: { key: "ffmpeg", name: "FFmpeg Media Processing", category: "Media Processing", credits_per_call: 3, tags: ["media", "audio", "video", "processing"] }
374
+ },
375
+ {
376
+ pattern: /tesseract|ocr/i,
377
+ capability: { key: "tesseract", name: "OCR Text Extraction", category: "OCR", credits_per_call: 4, tags: ["ocr", "text", "extraction"] }
378
+ }
379
+ ];
380
+ var INTERACTIVE_TEMPLATES = [
381
+ { key: "openai", name: "Text Generation (GPT-4o / Claude / Gemini)", category: "Text Gen", credits_per_call: 3, tags: ["llm", "text", "generation"] },
382
+ { key: "image-gen", name: "Image Generation (DALL-E / Recraft / Stable Diffusion)", category: "Image Gen", credits_per_call: 8, tags: ["image", "generation"] },
383
+ { key: "tts", name: "TTS / Voice (ElevenLabs / Google TTS)", category: "TTS", credits_per_call: 5, tags: ["tts", "audio", "voice"] },
384
+ { key: "video-gen", name: "Video Generation (Kling / Runway)", category: "Video Gen", credits_per_call: 10, tags: ["video", "generation"] },
385
+ { key: "code-review", name: "Code Review / Analysis", category: "Code", credits_per_call: 3, tags: ["code", "review", "analysis"] },
386
+ { key: "scraping", name: "Web Scraping / Data Extraction", category: "Web Scraping", credits_per_call: 2, tags: ["scraping", "data", "extraction"] },
387
+ { key: "translation", name: "Translation", category: "Translation", credits_per_call: 3, tags: ["translation", "language", "text"] },
388
+ { key: "custom", name: "Custom (describe it)", category: "Custom", credits_per_call: 5, tags: ["custom"] }
389
+ ];
390
+
391
+ // src/onboarding/detect-from-docs.ts
392
+ function detectFromDocs(content) {
393
+ if (!content || content.trim().length === 0) {
394
+ return [];
395
+ }
396
+ const seen = /* @__PURE__ */ new Set();
397
+ const results = [];
398
+ for (const entry of API_PATTERNS) {
399
+ if (entry.pattern.test(content) && !seen.has(entry.capability.key)) {
400
+ seen.add(entry.capability.key);
401
+ results.push({ ...entry.capability });
402
+ }
403
+ }
404
+ return results;
405
+ }
406
+
407
+ // src/onboarding/interactive.ts
408
+ import { createInterface } from "readline";
409
+ async function interactiveTemplateMenu() {
410
+ console.log("\nNo capabilities auto-detected.\n");
411
+ console.log("What can your agent do? Pick from templates:\n");
412
+ for (let i = 0; i < INTERACTIVE_TEMPLATES.length; i++) {
413
+ console.log(` ${i + 1}. ${INTERACTIVE_TEMPLATES[i].name}`);
414
+ }
415
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
416
+ const answer = await new Promise((resolve) => {
417
+ rl.question("\nSelect [1-8, comma-separated]: ", (ans) => {
418
+ rl.close();
419
+ resolve(ans);
420
+ });
421
+ });
422
+ return parseSelection(answer);
423
+ }
424
+ function parseSelection(input) {
425
+ if (!input || input.trim().length === 0) {
426
+ return [];
427
+ }
428
+ const selected = [];
429
+ const seen = /* @__PURE__ */ new Set();
430
+ const parts = input.split(",").map((s) => s.trim());
431
+ for (const part of parts) {
432
+ const num = parseInt(part, 10);
433
+ if (isNaN(num) || num < 1 || num > INTERACTIVE_TEMPLATES.length) {
434
+ continue;
435
+ }
436
+ const template = INTERACTIVE_TEMPLATES[num - 1];
437
+ if (!seen.has(template.key)) {
438
+ seen.add(template.key);
439
+ selected.push({ ...template });
440
+ }
441
+ }
442
+ return selected;
443
+ }
444
+
445
+ // src/onboarding/index.ts
446
+ var DOC_FILES = ["SOUL.md", "CLAUDE.md", "AGENTS.md", "README.md"];
447
+ function detectCapabilities(opts = {}) {
448
+ const cwd = opts.cwd ?? process.cwd();
449
+ if (opts.fromFile) {
450
+ const filePath = opts.fromFile.startsWith("/") ? opts.fromFile : join(cwd, opts.fromFile);
451
+ if (existsSync2(filePath)) {
452
+ const content = readFileSync2(filePath, "utf-8");
453
+ const capabilities = detectFromDocs(content);
454
+ if (capabilities.length > 0) {
455
+ return { source: "docs", capabilities, sourceFile: filePath };
456
+ }
457
+ }
458
+ return { source: "none", capabilities: [] };
459
+ }
460
+ for (const fileName of DOC_FILES) {
461
+ const filePath = join(cwd, fileName);
462
+ if (!existsSync2(filePath)) continue;
463
+ const content = readFileSync2(filePath, "utf-8");
464
+ if (fileName === "SOUL.md") {
465
+ return { source: "soul", capabilities: [], soulContent: content, sourceFile: filePath };
466
+ }
467
+ const capabilities = detectFromDocs(content);
468
+ if (capabilities.length > 0) {
469
+ return { source: "docs", capabilities, sourceFile: filePath };
470
+ }
471
+ }
472
+ const envKeys = detectApiKeys(KNOWN_API_KEYS);
473
+ if (envKeys.length > 0) {
474
+ return { source: "env", capabilities: [], envKeys };
475
+ }
476
+ return { source: "none", capabilities: [] };
477
+ }
478
+ function capabilitiesToV2Card(capabilities, owner, agentName) {
479
+ const now = (/* @__PURE__ */ new Date()).toISOString();
480
+ const skills = capabilities.map((cap) => ({
481
+ id: cap.key,
482
+ name: cap.name,
483
+ description: `${cap.name} capability \u2014 ${cap.category}`,
484
+ level: 1,
485
+ category: cap.category.toLowerCase().replace(/\s+/g, "_"),
486
+ inputs: [{ name: "input", type: "text", required: true }],
487
+ outputs: [{ name: "output", type: "text", required: true }],
488
+ pricing: { credits_per_call: cap.credits_per_call },
489
+ availability: { online: true },
490
+ metadata: {
491
+ tags: cap.tags
492
+ }
493
+ }));
494
+ const card = {
495
+ spec_version: "2.0",
496
+ id: randomUUID3(),
497
+ owner,
498
+ agent_name: agentName ?? owner,
499
+ skills,
500
+ availability: { online: true },
501
+ created_at: now,
502
+ updated_at: now
503
+ };
504
+ return CapabilityCardV2Schema.parse(card);
505
+ }
506
+
507
+ // src/cli/init-action.ts
508
+ import { createInterface as createInterface2 } from "readline";
499
509
  async function confirm(question) {
500
510
  const rl = createInterface2({ input: process.stdin, output: process.stdout });
501
511
  try {
@@ -508,6 +518,15 @@ async function confirm(question) {
508
518
  rl.close();
509
519
  }
510
520
  }
521
+ function getLanIp() {
522
+ const nets = networkInterfaces();
523
+ for (const ifaces of Object.values(nets)) {
524
+ for (const iface of ifaces ?? []) {
525
+ if (iface.family === "IPv4" && !iface.internal) return iface.address;
526
+ }
527
+ }
528
+ return "localhost";
529
+ }
511
530
  function loadIdentityAuth(owner) {
512
531
  const configDir = getConfigDir();
513
532
  let keys;
@@ -524,41 +543,25 @@ function loadIdentityAuth(owner) {
524
543
  privateKey: keys.privateKey
525
544
  };
526
545
  }
527
- function getLanIp() {
528
- const nets = networkInterfaces();
529
- for (const ifaces of Object.values(nets)) {
530
- for (const iface of ifaces ?? []) {
531
- if (iface.family === "IPv4" && !iface.internal) return iface.address;
532
- }
533
- }
534
- return "localhost";
535
- }
536
- var program = new Command();
537
- program.name("agentbnb").description("P2P Agent Capability Sharing Protocol \u2014 Airbnb for AI agent pipelines").version(pkg.version);
538
- program.command("init").description("Initialize AgentBnB config and create agent identity").option("--owner <name>", "Agent owner name").option("--agent-id <id>", "Agent identity (alias for --owner, for genesis-template compat)").option("--port <port>", "Gateway port", "7700").option("--host <ip>", "Override gateway host IP (default: auto-detected LAN IP)").option("--yes", "Auto-confirm all draft cards (non-interactive)").option("--non-interactive", "Non-interactive mode (alias for --yes)").option("--no-detect", "Skip API key detection").option("--from <file>", "Parse a specific file for capability detection").option("--json", "Output as JSON").action(async (opts) => {
546
+ async function performInit(opts) {
539
547
  const configDir = getConfigDir();
540
548
  const dbPath = join2(configDir, "registry.db");
541
549
  const creditDbPath = join2(configDir, "credit.db");
542
550
  const port = parseInt(opts.port, 10);
543
551
  const ip = opts.host ?? getLanIp();
544
552
  const yesMode = opts.yes ?? opts.nonInteractive ?? false;
545
- opts.yes = yesMode;
546
553
  const existingConfig = loadConfig();
547
554
  const owner = opts.agentId ?? opts.owner ?? existingConfig?.owner ?? `agent-${randomBytes(4).toString("hex")}`;
548
555
  const config = {
549
556
  ...existingConfig,
550
- // Preserve all existing keys (registry, autonomy, budget, etc.)
551
557
  owner,
552
558
  gateway_url: `http://${ip}:${port}`,
553
559
  gateway_port: port,
554
560
  db_path: dbPath,
555
561
  credit_db_path: creditDbPath,
556
562
  token: existingConfig?.token ?? randomBytes(32).toString("hex"),
557
- // Preserve existing token
558
563
  api_key: existingConfig?.api_key ?? randomBytes(32).toString("hex"),
559
- // Default registry for fresh installs: auto-set in --yes (automated) mode only.
560
- // Interactive init leaves registry unset so users can configure it explicitly.
561
- ...existingConfig?.registry ? { registry: existingConfig.registry } : opts.yes ? { registry: "https://agentbnb.fly.dev" } : {}
564
+ ...existingConfig?.registry ? { registry: existingConfig.registry } : yesMode ? { registry: "https://agentbnb.fly.dev" } : {}
562
565
  };
563
566
  saveConfig(config);
564
567
  let keypairStatus = "existing";
@@ -616,6 +619,22 @@ program.command("init").description("Initialize AgentBnB config and create agent
616
619
  console.log(`Migrated local credits: ${existingConfig.owner} \u2192 ${owner}`);
617
620
  }
618
621
  }
622
+ const existingAgent = lookupAgent(creditDb, identity.agent_id) ?? lookupAgentByOwner(creditDb, owner);
623
+ if (!existingAgent) {
624
+ try {
625
+ createAgentRecord(creditDb, {
626
+ agent_id: identity.agent_id,
627
+ display_name: config.display_name ?? owner,
628
+ public_key: identity.public_key,
629
+ legacy_owner: owner
630
+ });
631
+ } catch {
632
+ }
633
+ }
634
+ if (!config.agent_id || config.agent_id !== identity.agent_id) {
635
+ config.agent_id = identity.agent_id;
636
+ saveConfig(config);
637
+ }
619
638
  bootstrapAgent(creditDb, owner, 100);
620
639
  creditDb.close();
621
640
  let registryBalance;
@@ -664,12 +683,12 @@ program.command("init").description("Initialize AgentBnB config and create agent
664
683
  }
665
684
  }
666
685
  const card = capabilitiesToV2Card(result.capabilities, owner);
667
- if (opts.yes) {
686
+ if (yesMode) {
668
687
  const db = openDatabase(dbPath);
669
688
  try {
670
689
  db.prepare(
671
690
  `INSERT OR REPLACE INTO capability_cards (id, owner, data, created_at, updated_at)
672
- VALUES (?, ?, ?, ?, ?)`
691
+ VALUES (?, ?, ?, ?, ?)`
673
692
  ).run(card.id, card.owner, JSON.stringify(card), card.created_at, card.updated_at);
674
693
  publishedCards.push({ id: card.id, name: card.agent_name });
675
694
  if (!opts.json) {
@@ -686,7 +705,7 @@ Publish these ${card.skills.length} capabilities? [y/N] `);
686
705
  try {
687
706
  db.prepare(
688
707
  `INSERT OR REPLACE INTO capability_cards (id, owner, data, created_at, updated_at)
689
- VALUES (?, ?, ?, ?, ?)`
708
+ VALUES (?, ?, ?, ?, ?)`
690
709
  ).run(card.id, card.owner, JSON.stringify(card), card.created_at, card.updated_at);
691
710
  publishedCards.push({ id: card.id, name: card.agent_name });
692
711
  console.log(` Published v2.0 card: ${card.agent_name} (${card.skills.length} skills)`);
@@ -711,7 +730,7 @@ Publish these ${card.skills.length} capabilities? [y/N] `);
711
730
  console.log(` Found services on ports: ${detectedPorts.join(", ")}`);
712
731
  }
713
732
  const drafts = detectedKeys.map((key) => buildDraftCard(key, owner)).filter((card) => card !== null);
714
- if (opts.yes) {
733
+ if (yesMode) {
715
734
  const db = openDatabase(dbPath);
716
735
  try {
717
736
  for (const card of drafts) {
@@ -746,7 +765,7 @@ Publish these ${card.skills.length} capabilities? [y/N] `);
746
765
  }
747
766
  }
748
767
  } else {
749
- if (process.stdout.isTTY && !opts.yes && !opts.json) {
768
+ if (process.stdout.isTTY && !yesMode && !opts.json) {
750
769
  const selected = await interactiveTemplateMenu();
751
770
  if (selected.length > 0) {
752
771
  const card = capabilitiesToV2Card(selected, owner);
@@ -754,7 +773,7 @@ Publish these ${card.skills.length} capabilities? [y/N] `);
754
773
  try {
755
774
  db.prepare(
756
775
  `INSERT OR REPLACE INTO capability_cards (id, owner, data, created_at, updated_at)
757
- VALUES (?, ?, ?, ?, ?)`
776
+ VALUES (?, ?, ?, ?, ?)`
758
777
  ).run(card.id, card.owner, JSON.stringify(card), card.created_at, card.updated_at);
759
778
  publishedCards.push({ id: card.id, name: card.agent_name });
760
779
  console.log(`
@@ -768,36 +787,277 @@ Publish these ${card.skills.length} capabilities? [y/N] `);
768
787
  }
769
788
  }
770
789
  }
790
+ return {
791
+ config,
792
+ owner,
793
+ configDir,
794
+ publishedCards,
795
+ registryBalance,
796
+ identity: { agent_id: identity.agent_id },
797
+ keypairStatus,
798
+ detectedSource
799
+ };
800
+ }
801
+
802
+ // src/cli/quickstart.ts
803
+ import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
804
+ import { join as join3 } from "path";
805
+ import { homedir } from "os";
806
+ import { execSync } from "child_process";
807
+ var SKILLS_YAML_TEMPLATE = `skills:
808
+ # General-purpose AI task execution via Claude Code CLI
809
+ - id: claude-code-run
810
+ type: command
811
+ name: Claude Code Task Runner
812
+ description: "Execute any text-based AI task via Claude Code"
813
+ command: claude -p "\${params.prompt}"
814
+ output_type: text
815
+ allowed_commands:
816
+ - claude
817
+ timeout_ms: 180000
818
+ pricing:
819
+ credits_per_call: 5
820
+
821
+ # Code review skill
822
+ - id: claude-code-review
823
+ type: command
824
+ name: Code Review
825
+ description: "Review code for bugs, style, and improvements"
826
+ command: claude -p "Review this code for bugs, style issues, and improvements:\\n\\n\${params.code}"
827
+ output_type: text
828
+ allowed_commands:
829
+ - claude
830
+ timeout_ms: 120000
831
+ pricing:
832
+ credits_per_call: 3
833
+
834
+ # Text summarization skill
835
+ - id: claude-code-summarize
836
+ type: command
837
+ name: Text Summarizer
838
+ description: "Summarize long text into concise key points"
839
+ command: claude -p "Summarize the following text into concise key points:\\n\\n\${params.text}"
840
+ output_type: text
841
+ allowed_commands:
842
+ - claude
843
+ timeout_ms: 120000
844
+ pricing:
845
+ credits_per_call: 2
846
+ `;
847
+ function generateSkillsYaml(configDir) {
848
+ const skillsPath = join3(configDir, "skills.yaml");
849
+ if (existsSync3(skillsPath)) {
850
+ const content = readFileSync3(skillsPath, "utf-8");
851
+ const matches = content.match(/^\s+-\s+id:/gm);
852
+ return { generated: false, path: skillsPath, skillCount: matches?.length ?? 0 };
853
+ }
854
+ writeFileSync2(skillsPath, SKILLS_YAML_TEMPLATE, "utf-8");
855
+ return { generated: true, path: skillsPath, skillCount: 3 };
856
+ }
857
+ function registerMcpWithClaudeCode() {
858
+ const claudeDir = join3(homedir(), ".claude");
859
+ if (!existsSync3(claudeDir)) {
860
+ return {
861
+ registered: false,
862
+ reason: "Claude Code not detected. Add MCP manually: claude mcp add agentbnb -- agentbnb mcp-server"
863
+ };
864
+ }
865
+ const settingsPath = join3(claudeDir, "settings.json");
866
+ let agentbnbCommand = "agentbnb";
867
+ try {
868
+ const resolved = execSync("which agentbnb", { encoding: "utf-8" }).trim();
869
+ if (resolved) agentbnbCommand = resolved;
870
+ } catch {
871
+ }
872
+ let settings = {};
873
+ if (existsSync3(settingsPath)) {
874
+ try {
875
+ settings = JSON.parse(readFileSync3(settingsPath, "utf-8"));
876
+ } catch {
877
+ try {
878
+ writeFileSync2(`${settingsPath}.bak`, readFileSync3(settingsPath, "utf-8"), "utf-8");
879
+ } catch {
880
+ }
881
+ settings = {};
882
+ }
883
+ }
884
+ const mcpServers = settings.mcpServers ?? {};
885
+ if (mcpServers.agentbnb) {
886
+ return { registered: false, path: settingsPath, reason: "already registered" };
887
+ }
888
+ mcpServers.agentbnb = {
889
+ command: agentbnbCommand,
890
+ args: ["mcp-server"]
891
+ };
892
+ settings.mcpServers = mcpServers;
893
+ writeFileSync2(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
894
+ return { registered: true, path: settingsPath };
895
+ }
896
+ async function runQuickstart(opts) {
897
+ const jsonMode = opts.json ?? false;
898
+ const skipServe = opts.serve === false;
899
+ const skipMcp = opts.mcp === false;
900
+ if (!jsonMode) console.log("Initializing AgentBnB...");
901
+ const initResult = await performInit({
902
+ owner: opts.owner,
903
+ port: opts.port,
904
+ yes: true,
905
+ detect: true,
906
+ json: false
907
+ // We handle output ourselves
908
+ });
909
+ const skills = generateSkillsYaml(initResult.configDir);
910
+ if (!jsonMode) {
911
+ if (skills.generated) {
912
+ console.log(`
913
+ Generated skills.yaml with ${skills.skillCount} Claude Code skills`);
914
+ } else {
915
+ console.log(`
916
+ Skills: ${skills.skillCount} skill(s) in ${skills.path}`);
917
+ }
918
+ }
919
+ let mcpResult = { registered: false, reason: "skipped" };
920
+ if (!skipMcp) {
921
+ mcpResult = registerMcpWithClaudeCode();
922
+ if (!jsonMode) {
923
+ if (mcpResult.registered) {
924
+ console.log(`MCP: registered in ${mcpResult.path}`);
925
+ } else if (mcpResult.reason === "already registered") {
926
+ console.log(`MCP: already registered in ${mcpResult.path}`);
927
+ } else {
928
+ console.log(`MCP: ${mcpResult.reason}`);
929
+ }
930
+ }
931
+ }
932
+ let daemonStatus = { running: false, reason: "skipped" };
933
+ if (!skipServe) {
934
+ try {
935
+ const { ProcessGuard } = await import("../process-guard-GH5LRNWO.js");
936
+ const { ServiceCoordinator } = await import("../service-coordinator-WGH6B2VT.js");
937
+ const guard = new ProcessGuard(join3(initResult.configDir, ".pid"));
938
+ const coordinator = new ServiceCoordinator(initResult.config, guard);
939
+ const result = await coordinator.ensureRunning({
940
+ port: initResult.config.gateway_port,
941
+ skillsYamlPath: join3(initResult.configDir, "skills.yaml"),
942
+ registryUrl: initResult.config.registry,
943
+ relay: true
944
+ });
945
+ if (result === "already_running") {
946
+ daemonStatus = { running: true, reason: "already running" };
947
+ } else {
948
+ const meta = guard.getRunningMeta();
949
+ daemonStatus = { running: true, pid: meta?.pid };
950
+ }
951
+ if (!jsonMode) {
952
+ if (result === "already_running") {
953
+ console.log(`Daemon: already running`);
954
+ } else {
955
+ console.log(`Daemon: started (pid ${daemonStatus.pid ?? "unknown"})`);
956
+ }
957
+ }
958
+ } catch (err) {
959
+ daemonStatus = { running: false, reason: err.message };
960
+ if (!jsonMode) {
961
+ console.warn(`Daemon: failed to start \u2014 ${err.message}`);
962
+ console.warn(` Start manually with: agentbnb serve`);
963
+ }
964
+ }
965
+ }
966
+ if (jsonMode) {
967
+ console.log(JSON.stringify({
968
+ success: true,
969
+ owner: initResult.owner,
970
+ config_dir: initResult.configDir,
971
+ gateway_url: initResult.config.gateway_url,
972
+ registry: initResult.config.registry,
973
+ credits: initResult.registryBalance ?? 100,
974
+ skills: { count: skills.skillCount, generated: skills.generated, path: skills.path },
975
+ mcp: mcpResult,
976
+ daemon: daemonStatus,
977
+ published_cards: initResult.publishedCards
978
+ }, null, 2));
979
+ } else {
980
+ console.log("\n--- AgentBnB quickstart complete! ---\n");
981
+ console.log(` Owner: ${initResult.owner}`);
982
+ console.log(` Gateway: ${initResult.config.gateway_url}`);
983
+ console.log(` Credits: ${initResult.registryBalance ?? 100}`);
984
+ console.log(` Registry: ${initResult.config.registry ?? "not configured"}`);
985
+ console.log(` Skills: ${skills.skillCount} loaded`);
986
+ console.log(` MCP: ${mcpResult.registered ? "registered" : mcpResult.reason}`);
987
+ console.log(` Daemon: ${daemonStatus.running ? `running${daemonStatus.pid ? ` (pid ${daemonStatus.pid})` : ""}` : `not running \u2014 ${daemonStatus.reason}`}`);
988
+ console.log("");
989
+ console.log(" You are now both a consumer and provider on AgentBnB.");
990
+ console.log("");
991
+ console.log(" Consumer: In Claude Code, use agentbnb_discover and agentbnb_request");
992
+ console.log(" Provider: Your claude -p skills are live and accepting requests");
993
+ console.log(` Dashboard: http://localhost:7701/hub/#/myagent`);
994
+ }
995
+ }
996
+
997
+ // src/cli/index.ts
998
+ var require2 = createRequire(import.meta.url);
999
+ var pkg = require2("../../package.json");
1000
+ function loadIdentityAuth2(owner) {
1001
+ const configDir = getConfigDir();
1002
+ let keys;
1003
+ try {
1004
+ keys = loadKeyPair(configDir);
1005
+ } catch {
1006
+ keys = generateKeyPair();
1007
+ saveKeyPair(configDir, keys);
1008
+ }
1009
+ const identity = ensureIdentity(configDir, owner);
1010
+ return {
1011
+ agentId: identity.agent_id,
1012
+ publicKey: identity.public_key,
1013
+ privateKey: keys.privateKey
1014
+ };
1015
+ }
1016
+ function getLanIp2() {
1017
+ const nets = networkInterfaces2();
1018
+ for (const ifaces of Object.values(nets)) {
1019
+ for (const iface of ifaces ?? []) {
1020
+ if (iface.family === "IPv4" && !iface.internal) return iface.address;
1021
+ }
1022
+ }
1023
+ return "localhost";
1024
+ }
1025
+ var program = new Command();
1026
+ program.name("agentbnb").description("P2P Agent Capability Sharing Protocol \u2014 Airbnb for AI agent pipelines").version(pkg.version);
1027
+ program.command("init").description("Initialize AgentBnB config and create agent identity").option("--owner <name>", "Agent owner name").option("--agent-id <id>", "Agent identity (alias for --owner, for genesis-template compat)").option("--port <port>", "Gateway port", "7700").option("--host <ip>", "Override gateway host IP (default: auto-detected LAN IP)").option("--yes", "Auto-confirm all draft cards (non-interactive)").option("--non-interactive", "Non-interactive mode (alias for --yes)").option("--no-detect", "Skip API key detection").option("--from <file>", "Parse a specific file for capability detection").option("--json", "Output as JSON").action(async (opts) => {
1028
+ const result = await performInit(opts);
771
1029
  if (opts.json) {
772
1030
  const jsonOutput = {
773
1031
  success: true,
774
- owner,
775
- config_dir: configDir,
776
- token: config.token,
777
- gateway_url: config.gateway_url,
778
- keypair: keypairStatus,
779
- agent_id: identity.agent_id
1032
+ owner: result.owner,
1033
+ config_dir: result.configDir,
1034
+ token: result.config.token,
1035
+ gateway_url: result.config.gateway_url,
1036
+ keypair: result.keypairStatus,
1037
+ agent_id: result.identity.agent_id
780
1038
  };
781
- if (registryBalance !== void 0) {
782
- jsonOutput.registry_balance = registryBalance;
1039
+ if (result.registryBalance !== void 0) {
1040
+ jsonOutput.registry_balance = result.registryBalance;
783
1041
  }
784
- if (!skipDetect) {
785
- jsonOutput.detected_source = detectedSource;
786
- jsonOutput.published_cards = publishedCards;
1042
+ if (opts.detect !== false) {
1043
+ jsonOutput.detected_source = result.detectedSource;
1044
+ jsonOutput.published_cards = result.publishedCards;
787
1045
  }
788
1046
  console.log(JSON.stringify(jsonOutput, null, 2));
789
1047
  } else {
1048
+ const ip = opts.host ?? getLanIp2();
1049
+ const port = parseInt(opts.port, 10);
790
1050
  console.log(`AgentBnB initialized.`);
791
- console.log(` Owner: ${owner}`);
792
- console.log(` Token: ${config.token}`);
793
- console.log(` Config: ${configDir}/config.json`);
794
- if (registryBalance !== void 0) {
795
- console.log(` Registry balance: ${registryBalance} credits`);
1051
+ console.log(` Owner: ${result.owner}`);
1052
+ console.log(` Token: ${result.config.token}`);
1053
+ console.log(` Config: ${result.configDir}/config.json`);
1054
+ if (result.registryBalance !== void 0) {
1055
+ console.log(` Registry balance: ${result.registryBalance} credits`);
796
1056
  } else {
797
1057
  console.log(` Credits: 100 (starter grant)`);
798
1058
  }
799
- console.log(` Keypair: ${keypairStatus === "generated" ? "generated (Ed25519)" : "preserved (existing)"}`);
800
- console.log(` Agent ID: ${identity.agent_id}`);
1059
+ console.log(` Keypair: ${result.keypairStatus === "generated" ? "generated (Ed25519)" : "preserved (existing)"}`);
1060
+ console.log(` Agent ID: ${result.identity.agent_id}`);
801
1061
  console.log(` Gateway: http://${ip}:${port}`);
802
1062
  }
803
1063
  });
@@ -809,7 +1069,7 @@ program.command("publish <card.json>").description("Publish a Capability Card to
809
1069
  }
810
1070
  let raw;
811
1071
  try {
812
- raw = readFileSync3(cardPath, "utf-8");
1072
+ raw = readFileSync4(cardPath, "utf-8");
813
1073
  } catch {
814
1074
  console.error(`Error: cannot read file: ${cardPath}`);
815
1075
  process.exit(1);
@@ -916,12 +1176,12 @@ program.command("publish-skills").description("Publish capabilities from skills.
916
1176
  console.error("Error: not initialized. Run `agentbnb init` first.");
917
1177
  process.exit(1);
918
1178
  }
919
- const { parseSkillsFile } = await import("../skill-config-4W5W5O6T.js");
920
- const { skillConfigToSkill } = await import("../publish-capability-TS6CNR5G.js");
1179
+ const { parseSkillsFile } = await import("../skill-config-FETXPNVP.js");
1180
+ const { skillConfigToSkill } = await import("../publish-capability-AH2HDW54.js");
921
1181
  const skillsPath = typeof opts.fromSkills === "string" ? opts.fromSkills : "./skills.yaml";
922
1182
  let yamlContent;
923
1183
  try {
924
- yamlContent = readFileSync3(skillsPath, "utf-8");
1184
+ yamlContent = readFileSync4(skillsPath, "utf-8");
925
1185
  } catch {
926
1186
  console.error(`Error: cannot read skills.yaml at ${skillsPath}`);
927
1187
  process.exit(1);
@@ -1168,7 +1428,7 @@ program.command("request [card-id]").description("Request a capability from anot
1168
1428
  }
1169
1429
  let batchPayload;
1170
1430
  try {
1171
- const raw = readFileSync3(opts.batch, "utf-8");
1431
+ const raw = readFileSync4(opts.batch, "utf-8");
1172
1432
  batchPayload = JSON.parse(raw);
1173
1433
  } catch (err) {
1174
1434
  console.error(`Error: could not read batch file: ${err.message}`);
@@ -1229,8 +1489,8 @@ Batch Results (${res.results.length} items):`);
1229
1489
  process.exit(1);
1230
1490
  }
1231
1491
  }
1232
- const registryDb = openDatabase(join2(getConfigDir(), "registry.db"));
1233
- const creditDb = openCreditDb(join2(getConfigDir(), "credit.db"));
1492
+ const registryDb = openDatabase(join4(getConfigDir(), "registry.db"));
1493
+ const creditDb = openCreditDb(join4(getConfigDir(), "credit.db"));
1234
1494
  registryDb.pragma("busy_timeout = 5000");
1235
1495
  creditDb.pragma("busy_timeout = 5000");
1236
1496
  try {
@@ -1270,7 +1530,7 @@ Batch Results (${res.results.length} items):`);
1270
1530
  let token;
1271
1531
  let isRemoteRequest = false;
1272
1532
  let targetOwner;
1273
- const identityAuth = loadIdentityAuth(config.owner);
1533
+ const identityAuth = loadIdentityAuth2(config.owner);
1274
1534
  if (opts.peer) {
1275
1535
  const peer = findPeer(opts.peer);
1276
1536
  if (!peer) {
@@ -1350,7 +1610,7 @@ Batch Results (${res.results.length} items):`);
1350
1610
  process.exit(1);
1351
1611
  }
1352
1612
  if (useRegistryLedger) {
1353
- const reqIdentityAuth = loadIdentityAuth(config.owner);
1613
+ const reqIdentityAuth = loadIdentityAuth2(config.owner);
1354
1614
  requestLedger = createLedger({
1355
1615
  registryUrl: config.registry,
1356
1616
  ownerPublicKey: reqIdentityAuth.publicKey,
@@ -1373,7 +1633,7 @@ Batch Results (${res.results.length} items):`);
1373
1633
  }
1374
1634
  } else if (gatewayUrl) {
1375
1635
  const configDir = getConfigDir();
1376
- const creditDb = openCreditDb(join2(configDir, "credit.db"));
1636
+ const creditDb = openCreditDb(join4(configDir, "credit.db"));
1377
1637
  creditDb.pragma("busy_timeout = 5000");
1378
1638
  try {
1379
1639
  const keys = loadKeyPair(configDir);
@@ -1408,7 +1668,7 @@ Batch Results (${res.results.length} items):`);
1408
1668
  if (!opts.json) console.log(`Escrow settled: ${opts.cost} credits deducted.`);
1409
1669
  } else if (escrowReceipt) {
1410
1670
  const configDir = getConfigDir();
1411
- const creditDb = openCreditDb(join2(configDir, "credit.db"));
1671
+ const creditDb = openCreditDb(join4(configDir, "credit.db"));
1412
1672
  creditDb.pragma("busy_timeout = 5000");
1413
1673
  try {
1414
1674
  settleRequesterEscrow(creditDb, escrowId);
@@ -1426,7 +1686,7 @@ Batch Results (${res.results.length} items):`);
1426
1686
  if (!opts.json) console.log("Escrow released: credits refunded.");
1427
1687
  } else if (escrowReceipt) {
1428
1688
  const configDir = getConfigDir();
1429
- const creditDb = openCreditDb(join2(configDir, "credit.db"));
1689
+ const creditDb = openCreditDb(join4(configDir, "credit.db"));
1430
1690
  creditDb.pragma("busy_timeout = 5000");
1431
1691
  try {
1432
1692
  releaseRequesterEscrow(creditDb, escrowId);
@@ -1450,8 +1710,8 @@ Batch Results (${res.results.length} items):`);
1450
1710
  return msg.includes("NETWORK_ERROR") || msg.includes("ECONNREFUSED") || msg.includes("fetch failed") || msg.includes("Network error");
1451
1711
  };
1452
1712
  const tryViaRelay = async () => {
1453
- const { RelayClient } = await import("../websocket-client-6IIDGXKB.js");
1454
- const { requestViaRelay } = await import("../client-HRYRJKSA.js");
1713
+ const { RelayClient } = await import("../websocket-client-QOVARTRN.js");
1714
+ const { requestViaRelay } = await import("../client-HKV3QWZ3.js");
1455
1715
  const requesterId = `${config.owner}:req:${randomUUID4()}`;
1456
1716
  const tempRelay = new RelayClient({
1457
1717
  registryUrl: config.registry,
@@ -1529,7 +1789,7 @@ program.command("status").description("Show credit balance and recent transactio
1529
1789
  let transactions;
1530
1790
  let heldEscrows;
1531
1791
  if (config.registry) {
1532
- const statusIdentityAuth = loadIdentityAuth(config.owner);
1792
+ const statusIdentityAuth = loadIdentityAuth2(config.owner);
1533
1793
  const statusLedger = createLedger({
1534
1794
  registryUrl: config.registry,
1535
1795
  ownerPublicKey: statusIdentityAuth.publicKey,
@@ -1580,15 +1840,15 @@ program.command("serve").description("Start the AgentBnB gateway server").option
1580
1840
  console.error("Error: not initialized. Run `agentbnb init` first.");
1581
1841
  process.exit(1);
1582
1842
  }
1583
- const { ProcessGuard } = await import("../process-guard-QCCBGILS.js");
1584
- const { ServiceCoordinator } = await import("../service-coordinator-CRSE4GWC.js");
1843
+ const { ProcessGuard } = await import("../process-guard-GH5LRNWO.js");
1844
+ const { ServiceCoordinator } = await import("../service-coordinator-WGH6B2VT.js");
1585
1845
  const port = opts.port ? parseInt(opts.port, 10) : config.gateway_port;
1586
1846
  const registryPort = parseInt(opts.registryPort, 10);
1587
1847
  if (!Number.isFinite(port) || !Number.isFinite(registryPort)) {
1588
1848
  console.error("Error: --port and --registry-port must be valid numbers.");
1589
1849
  process.exit(1);
1590
1850
  }
1591
- const guard = new ProcessGuard(join2(getConfigDir(), ".pid"));
1851
+ const guard = new ProcessGuard(join4(getConfigDir(), ".pid"));
1592
1852
  const coordinator = new ServiceCoordinator(config, guard);
1593
1853
  try {
1594
1854
  await coordinator.ensureRunning({
@@ -1856,7 +2116,7 @@ cardsCmd.command("delete <card-id>").description("Delete a published capability
1856
2116
  console.log(` Skills: ${skillCount}`);
1857
2117
  console.log(` ID: ${card.id}`);
1858
2118
  if (!opts.force && process.stdin.isTTY) {
1859
- const rl = createInterface2({ input: process.stdin, output: process.stdout });
2119
+ const rl = createInterface3({ input: process.stdin, output: process.stdout });
1860
2120
  const answer = await new Promise((resolve) => {
1861
2121
  rl.question("Confirm deletion? [y/N] ", resolve);
1862
2122
  });
@@ -1885,7 +2145,7 @@ openclaw.command("sync").description("Read SOUL.md and publish/update a v2.0 cap
1885
2145
  }
1886
2146
  let content;
1887
2147
  try {
1888
- content = readFileSync3(opts.soulPath, "utf-8");
2148
+ content = readFileSync4(opts.soulPath, "utf-8");
1889
2149
  } catch {
1890
2150
  console.error(`Error: cannot read SOUL.md at ${opts.soulPath}`);
1891
2151
  process.exit(1);
@@ -1955,7 +2215,7 @@ openclaw.command("rules").description("Print HEARTBEAT.md rules block (or inject
1955
2215
  }
1956
2216
  });
1957
2217
  program.command("conduct <task>").description("Orchestrate a complex task across the AgentBnB network").option("--plan-only", "Show execution plan without executing").option("--max-budget <credits>", "Maximum credits to spend", "100").option("--json", "Output as JSON").action(async (task, opts) => {
1958
- const { conductAction } = await import("../conduct-QAFZIEY6.js");
2218
+ const { conductAction } = await import("../conduct-YB64OHI6.js");
1959
2219
  const result = await conductAction(task, opts);
1960
2220
  if (opts.json) {
1961
2221
  console.log(JSON.stringify(result, null, 2));
@@ -2065,8 +2325,9 @@ Feedback for skill: ${opts.skill} (${feedbacks.length} entries)
2065
2325
  }
2066
2326
  }
2067
2327
  });
2328
+ 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);
2068
2329
  program.command("mcp-server").description("Start an MCP (Model Context Protocol) server for IDE integration").action(async () => {
2069
- const { startMcpServer } = await import("../server-3G6ZTASA.js");
2330
+ const { startMcpServer } = await import("../server-MHMAYXWZ.js");
2070
2331
  await startMcpServer();
2071
2332
  });
2072
2333
  await program.parseAsync(process.argv);