agentbnb 8.3.2 → 8.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{card-T2XJZA5A.js → card-HYTD2BJQ.js} +1 -1
- package/dist/{chunk-S7DZHKCG.js → chunk-2PP5MQPD.js} +5 -3
- package/dist/{chunk-75OC6E4F.js → chunk-3XPBFF6H.js} +1 -0
- package/dist/{chunk-5AH3CMOX.js → chunk-3YQ73ZM6.js} +1 -1
- package/dist/{chunk-FELGHDCA.js → chunk-6FZ4WYQL.js} +38 -4
- package/dist/{chunk-D242QZCR.js → chunk-6XCN62YU.js} +10 -54
- package/dist/chunk-AZKVGC5T.js +53 -0
- package/dist/{chunk-NHVHLUYS.js → chunk-CFHCG5FE.js} +6 -217
- package/dist/{chunk-5AIYALBX.js → chunk-COA2D7QM.js} +4 -3
- package/dist/chunk-G5WKW3ED.js +41 -0
- package/dist/{chunk-F3KIEVJ2.js → chunk-HU46M4JA.js} +2 -87
- package/dist/{chunk-77KGEDH4.js → chunk-MZSVVG55.js} +2 -41
- package/dist/chunk-PCQEHIGF.js +750 -0
- package/dist/chunk-PIPCGRCR.js +91 -0
- package/dist/{chunk-QFPXZITP.js → chunk-PMRTQ2RL.js} +34 -0
- package/dist/{chunk-7IQE34QK.js → chunk-UF6R2RVN.js} +5 -3
- package/dist/{chunk-IGQNP3ZO.js → chunk-VAAEBCMU.js} +1 -1
- package/dist/chunk-VRPLSK34.js +214 -0
- package/dist/{chunk-BARHNIKG.js → chunk-WK2QSO4E.js} +1 -1
- package/dist/chunk-WPB5LFGI.js +132 -0
- package/dist/chunk-XGOA5J2K.js +173 -0
- package/dist/{chunk-VJ7XBEY6.js → chunk-Z5726VPY.js} +6 -6
- package/dist/cli/index.js +118 -789
- package/dist/conduct-FZPUMPCI.js +25 -0
- package/dist/{conduct-VYYBCPHA.js → conduct-J2NXU6RM.js} +12 -9
- package/dist/{conductor-mode-SBDCRIX6.js → conductor-mode-HNNMWZIH.js} +11 -8
- package/dist/config-IRWLG6IW.js +12 -0
- package/dist/{execute-FZLQGIXB.js → execute-UAD5T3BQ.js} +1 -1
- package/dist/{execute-TEZPQ5WP.js → execute-UP46R7KS.js} +6 -5
- package/dist/index.js +34 -0
- package/dist/openclaw-setup-KA72IIEW.js +296 -0
- package/dist/openclaw-skills-CT673RBL.js +370 -0
- package/dist/{peers-K7FSHPN3.js → peers-F2EWUMVQ.js} +2 -2
- package/dist/{publish-capability-HVYILTPR.js → publish-capability-GNH5FHKG.js} +2 -2
- package/dist/{request-KJNKR27T.js → request-IM3ZLAOA.js} +13 -9
- package/dist/scanner-F5VNV5FP.js +8 -0
- package/dist/{serve-skill-GC6NIQ5T.js → serve-skill-6RKMVDMK.js} +6 -5
- package/dist/{server-6I7GU2OZ.js → server-MH7FTZFN.js} +11 -9
- package/dist/{service-coordinator-LZJCAQSJ.js → service-coordinator-R5LZVM6A.js} +31 -26
- package/dist/skills/agentbnb/bootstrap.js +34 -2
- package/dist/store-4Z446745.js +32 -0
- package/dist/writer-4QJ3U3WE.js +16 -0
- package/package.json +1 -1
- package/skills/agentbnb/bootstrap.ts +45 -2
- package/dist/conduct-4JDMWBQD.js +0 -22
package/dist/cli/index.js
CHANGED
|
@@ -1,39 +1,46 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
generateHeartbeatSection,
|
|
4
|
+
getOpenClawStatus,
|
|
5
|
+
injectHeartbeatSection,
|
|
6
|
+
performInit,
|
|
7
|
+
publishFromSoulV2
|
|
8
|
+
} from "../chunk-PCQEHIGF.js";
|
|
9
|
+
import {
|
|
10
|
+
AutoRequestor,
|
|
11
|
+
requestViaTemporaryRelay
|
|
12
|
+
} from "../chunk-6XCN62YU.js";
|
|
13
|
+
import {
|
|
14
|
+
BudgetManager,
|
|
15
|
+
DEFAULT_BUDGET_CONFIG
|
|
16
|
+
} from "../chunk-AZKVGC5T.js";
|
|
17
|
+
import {
|
|
7
18
|
discoverLocalAgents,
|
|
8
|
-
getPricingStats,
|
|
9
19
|
resolveSelfCli
|
|
10
|
-
} from "../chunk-
|
|
20
|
+
} from "../chunk-VRPLSK34.js";
|
|
11
21
|
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
loadOrRepairIdentity
|
|
15
|
-
} from "../chunk-BARHNIKG.js";
|
|
22
|
+
getPricingStats
|
|
23
|
+
} from "../chunk-CFHCG5FE.js";
|
|
16
24
|
import {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
} from "../chunk-D242QZCR.js";
|
|
25
|
+
createLedger,
|
|
26
|
+
ensureIdentity
|
|
27
|
+
} from "../chunk-WK2QSO4E.js";
|
|
28
|
+
import "../chunk-MZSVVG55.js";
|
|
22
29
|
import {
|
|
23
30
|
DEFAULT_AUTONOMY_CONFIG
|
|
24
|
-
} from "../chunk-
|
|
25
|
-
import "../chunk-
|
|
31
|
+
} from "../chunk-G5WKW3ED.js";
|
|
32
|
+
import "../chunk-2PP5MQPD.js";
|
|
26
33
|
import {
|
|
27
|
-
bootstrapAgent,
|
|
28
34
|
fetchRemoteCards,
|
|
35
|
+
mergeResults
|
|
36
|
+
} from "../chunk-PIPCGRCR.js";
|
|
37
|
+
import {
|
|
29
38
|
filterCards,
|
|
30
39
|
getBalance,
|
|
31
40
|
getTransactions,
|
|
32
|
-
mergeResults,
|
|
33
|
-
migrateOwner,
|
|
34
41
|
openCreditDb,
|
|
35
42
|
searchCards
|
|
36
|
-
} from "../chunk-
|
|
43
|
+
} from "../chunk-HU46M4JA.js";
|
|
37
44
|
import "../chunk-NX27AFPA.js";
|
|
38
45
|
import "../chunk-PQIP7EXY.js";
|
|
39
46
|
import {
|
|
@@ -50,15 +57,13 @@ import {
|
|
|
50
57
|
loadPeers,
|
|
51
58
|
removePeer,
|
|
52
59
|
savePeer
|
|
53
|
-
} from "../chunk-
|
|
60
|
+
} from "../chunk-3YQ73ZM6.js";
|
|
54
61
|
import {
|
|
55
62
|
getConfigDir,
|
|
56
63
|
loadConfig,
|
|
57
64
|
saveConfig
|
|
58
|
-
} from "../chunk-
|
|
59
|
-
import
|
|
60
|
-
parseSoulMd
|
|
61
|
-
} from "../chunk-IGQNP3ZO.js";
|
|
65
|
+
} from "../chunk-3XPBFF6H.js";
|
|
66
|
+
import "../chunk-VAAEBCMU.js";
|
|
62
67
|
import {
|
|
63
68
|
attachCanonicalAgentId,
|
|
64
69
|
deleteCard,
|
|
@@ -66,726 +71,23 @@ import {
|
|
|
66
71
|
insertCard,
|
|
67
72
|
listCards,
|
|
68
73
|
openDatabase
|
|
69
|
-
} from "../chunk-
|
|
74
|
+
} from "../chunk-COA2D7QM.js";
|
|
75
|
+
import "../chunk-WTHMHNKC.js";
|
|
70
76
|
import {
|
|
71
|
-
|
|
72
|
-
lookupAgent,
|
|
73
|
-
lookupAgentByOwner,
|
|
74
|
-
updateAgentRecord
|
|
75
|
-
} from "../chunk-WTHMHNKC.js";
|
|
76
|
-
import {
|
|
77
|
-
AgentBnBError,
|
|
78
|
-
AnyCardSchema,
|
|
79
|
-
CapabilityCardV2Schema
|
|
77
|
+
AnyCardSchema
|
|
80
78
|
} from "../chunk-I7KWA7OB.js";
|
|
81
79
|
|
|
82
80
|
// src/cli/index.ts
|
|
83
81
|
import { Command } from "commander";
|
|
84
|
-
import { readFileSync as
|
|
85
|
-
import { randomUUID as randomUUID3 } from "crypto";
|
|
86
|
-
import { join as join4 } from "path";
|
|
87
|
-
import { networkInterfaces as networkInterfaces2 } from "os";
|
|
88
|
-
import { createInterface as createInterface3 } from "readline";
|
|
89
|
-
|
|
90
|
-
// src/openclaw/soul-sync.ts
|
|
82
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
91
83
|
import { randomUUID } from "crypto";
|
|
92
|
-
var SKILL_META_GLOBAL_RE = /(?:^|\s)-\s*(capability_types|requires(?:_capabilities)?|visibility)\s*:\s*([^-][^]*?)(?=\s+-\s+(?:capability_types|requires(?:_capabilities)?|visibility)\s*:|$)/gi;
|
|
93
|
-
function extractSkillMeta(raw) {
|
|
94
|
-
let capability_types;
|
|
95
|
-
let requires_capabilities;
|
|
96
|
-
let visibility;
|
|
97
|
-
const removedRanges = [];
|
|
98
|
-
SKILL_META_GLOBAL_RE.lastIndex = 0;
|
|
99
|
-
let m;
|
|
100
|
-
while ((m = SKILL_META_GLOBAL_RE.exec(raw)) !== null) {
|
|
101
|
-
const key = m[1].toLowerCase();
|
|
102
|
-
const val = m[2].trim();
|
|
103
|
-
if (key === "capability_types") {
|
|
104
|
-
capability_types = val.split(",").map((v) => v.trim()).filter(Boolean);
|
|
105
|
-
} else if (key === "requires" || key === "requires_capabilities") {
|
|
106
|
-
requires_capabilities = val.split(",").map((v) => v.trim()).filter(Boolean);
|
|
107
|
-
} else if (key === "visibility") {
|
|
108
|
-
const vis = val.toLowerCase();
|
|
109
|
-
if (vis === "public" || vis === "private") {
|
|
110
|
-
visibility = vis;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
removedRanges.push({ start: m.index, end: m.index + m[0].length });
|
|
114
|
-
}
|
|
115
|
-
let description = raw;
|
|
116
|
-
for (const { start, end } of removedRanges.slice().reverse()) {
|
|
117
|
-
description = description.slice(0, start) + description.slice(end);
|
|
118
|
-
}
|
|
119
|
-
description = description.trim();
|
|
120
|
-
return { description, capability_types, requires_capabilities, visibility };
|
|
121
|
-
}
|
|
122
|
-
function parseSoulMdV2(content) {
|
|
123
|
-
const parsed = parseSoulMd(content);
|
|
124
|
-
const skills = parsed.capabilities.map((cap) => {
|
|
125
|
-
const sanitizedId = cap.name.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "");
|
|
126
|
-
const id = sanitizedId.length > 0 ? sanitizedId : randomUUID();
|
|
127
|
-
const { description: cleanDesc, capability_types, requires_capabilities, visibility } = extractSkillMeta(cap.description);
|
|
128
|
-
const finalDescription = (cleanDesc || cap.name).slice(0, 500);
|
|
129
|
-
const skill = {
|
|
130
|
-
id,
|
|
131
|
-
name: cap.name,
|
|
132
|
-
description: finalDescription,
|
|
133
|
-
level: 2,
|
|
134
|
-
inputs: [
|
|
135
|
-
{
|
|
136
|
-
name: "input",
|
|
137
|
-
type: "text",
|
|
138
|
-
description: "Input for the skill",
|
|
139
|
-
required: true
|
|
140
|
-
}
|
|
141
|
-
],
|
|
142
|
-
outputs: [
|
|
143
|
-
{
|
|
144
|
-
name: "output",
|
|
145
|
-
type: "text",
|
|
146
|
-
description: "Output from the skill",
|
|
147
|
-
required: true
|
|
148
|
-
}
|
|
149
|
-
],
|
|
150
|
-
pricing: { credits_per_call: cap.pricing !== void 0 ? cap.pricing : 10 },
|
|
151
|
-
availability: { online: true }
|
|
152
|
-
};
|
|
153
|
-
if (capability_types !== void 0) skill.capability_types = capability_types;
|
|
154
|
-
if (requires_capabilities !== void 0) skill.requires_capabilities = requires_capabilities;
|
|
155
|
-
if (visibility !== void 0) skill.visibility = visibility;
|
|
156
|
-
return skill;
|
|
157
|
-
});
|
|
158
|
-
return {
|
|
159
|
-
agentName: parsed.name || "Unknown Agent",
|
|
160
|
-
description: parsed.description,
|
|
161
|
-
skills
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
function publishFromSoulV2(db, soulContent, owner, sharedSkills) {
|
|
165
|
-
const { agentName, skills: allSkills } = parseSoulMdV2(soulContent);
|
|
166
|
-
const skills = allSkills.filter((skill) => {
|
|
167
|
-
if (sharedSkills && sharedSkills.length > 0) {
|
|
168
|
-
return sharedSkills.includes(skill.id);
|
|
169
|
-
}
|
|
170
|
-
return skill.visibility !== "private";
|
|
171
|
-
});
|
|
172
|
-
if (skills.length === 0) {
|
|
173
|
-
throw new AgentBnBError("SOUL.md has no H2 sections", "VALIDATION_ERROR");
|
|
174
|
-
}
|
|
175
|
-
const existingCards = listCards(db, owner);
|
|
176
|
-
const existingV2 = existingCards.find(
|
|
177
|
-
(c) => c.spec_version === "2.0"
|
|
178
|
-
);
|
|
179
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
180
|
-
const cardId = existingV2?.id ?? randomUUID();
|
|
181
|
-
const card = {
|
|
182
|
-
spec_version: "2.0",
|
|
183
|
-
id: cardId,
|
|
184
|
-
owner,
|
|
185
|
-
agent_name: agentName,
|
|
186
|
-
skills,
|
|
187
|
-
availability: { online: true },
|
|
188
|
-
created_at: existingV2?.created_at ?? now,
|
|
189
|
-
updated_at: now
|
|
190
|
-
};
|
|
191
|
-
const storedCard = attachCanonicalAgentId(db, card);
|
|
192
|
-
CapabilityCardV2Schema.parse(storedCard);
|
|
193
|
-
if (existingV2) {
|
|
194
|
-
db.prepare(
|
|
195
|
-
"UPDATE capability_cards SET data = ?, updated_at = ? WHERE id = ?"
|
|
196
|
-
).run(JSON.stringify(storedCard), now, cardId);
|
|
197
|
-
} else {
|
|
198
|
-
db.prepare(
|
|
199
|
-
"INSERT INTO capability_cards (id, owner, data, created_at, updated_at) VALUES (?, ?, ?, ?, ?)"
|
|
200
|
-
).run(cardId, storedCard.owner, JSON.stringify(storedCard), now, now);
|
|
201
|
-
}
|
|
202
|
-
return storedCard;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// src/openclaw/heartbeat-writer.ts
|
|
206
|
-
import { readFileSync, writeFileSync, existsSync } from "fs";
|
|
207
|
-
var HEARTBEAT_MARKER_START = "<!-- agentbnb:start -->";
|
|
208
|
-
var HEARTBEAT_MARKER_END = "<!-- agentbnb:end -->";
|
|
209
|
-
function generateHeartbeatSection(autonomy, budget) {
|
|
210
|
-
const t1 = autonomy.tier1_max_credits;
|
|
211
|
-
const t2 = autonomy.tier2_max_credits;
|
|
212
|
-
const reserve = budget.reserve_credits;
|
|
213
|
-
return [
|
|
214
|
-
HEARTBEAT_MARKER_START,
|
|
215
|
-
"## AgentBnB Protocol",
|
|
216
|
-
"",
|
|
217
|
-
"You are a participant in the AgentBnB capability sharing network.",
|
|
218
|
-
"",
|
|
219
|
-
"### Sharing Rules",
|
|
220
|
-
"- When your idle_rate exceeds 70%, automatically share idle capabilities",
|
|
221
|
-
"- Accept incoming requests that match your published Capability Card",
|
|
222
|
-
"- Track credit earnings and report to owner weekly",
|
|
223
|
-
"",
|
|
224
|
-
"### Requesting Rules",
|
|
225
|
-
"- When you encounter a task you cannot complete with local skills:",
|
|
226
|
-
" 1. Query AgentBnB network for matching capabilities",
|
|
227
|
-
" 2. If found and credit sufficient, automatically request",
|
|
228
|
-
" 3. Integrate result into your current workflow",
|
|
229
|
-
"- Budget limits:",
|
|
230
|
-
` - < ${t1} credits: auto-execute, no notification`,
|
|
231
|
-
` - ${t1}-${t2} credits: execute, notify owner after`,
|
|
232
|
-
` - > ${t2} credits: ask owner before executing`,
|
|
233
|
-
"",
|
|
234
|
-
"### Credit Management",
|
|
235
|
-
`- Maintain minimum balance of ${reserve} credits (reserve for emergencies)`,
|
|
236
|
-
`- If balance drops below ${reserve}, increase sharing priority`,
|
|
237
|
-
"- If balance exceeds 500, notify owner of surplus",
|
|
238
|
-
HEARTBEAT_MARKER_END
|
|
239
|
-
].join("\n");
|
|
240
|
-
}
|
|
241
|
-
function injectHeartbeatSection(heartbeatPath, section) {
|
|
242
|
-
if (!existsSync(heartbeatPath)) {
|
|
243
|
-
writeFileSync(heartbeatPath, section + "\n", "utf-8");
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
|
-
let content = readFileSync(heartbeatPath, "utf-8");
|
|
247
|
-
const startIdx = content.indexOf(HEARTBEAT_MARKER_START);
|
|
248
|
-
const endIdx = content.indexOf(HEARTBEAT_MARKER_END);
|
|
249
|
-
if (startIdx !== -1 && endIdx !== -1) {
|
|
250
|
-
content = content.slice(0, startIdx) + section + content.slice(endIdx + HEARTBEAT_MARKER_END.length);
|
|
251
|
-
} else {
|
|
252
|
-
content = content + "\n" + section + "\n";
|
|
253
|
-
}
|
|
254
|
-
writeFileSync(heartbeatPath, content, "utf-8");
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// src/openclaw/skill.ts
|
|
258
|
-
function getOpenClawStatus(config, db, creditDb) {
|
|
259
|
-
const autonomy = config.autonomy ?? DEFAULT_AUTONOMY_CONFIG;
|
|
260
|
-
const budget = config.budget ?? DEFAULT_BUDGET_CONFIG;
|
|
261
|
-
const balance = getBalance(creditDb, config.owner);
|
|
262
|
-
const allCards = listCards(db, config.owner);
|
|
263
|
-
const skills = [];
|
|
264
|
-
for (const card of allCards) {
|
|
265
|
-
const anyCard = card;
|
|
266
|
-
if (anyCard.spec_version !== "2.0" || !Array.isArray(anyCard.skills)) continue;
|
|
267
|
-
for (const skill of anyCard.skills) {
|
|
268
|
-
const internal = skill["_internal"] ?? {};
|
|
269
|
-
const idleRate = typeof internal["idle_rate"] === "number" ? internal["idle_rate"] : null;
|
|
270
|
-
const availability = skill["availability"];
|
|
271
|
-
const online = availability?.online ?? false;
|
|
272
|
-
skills.push({
|
|
273
|
-
id: String(skill["id"] ?? ""),
|
|
274
|
-
name: String(skill["name"] ?? ""),
|
|
275
|
-
idle_rate: idleRate,
|
|
276
|
-
online
|
|
277
|
-
});
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
return {
|
|
281
|
-
installed: true,
|
|
282
|
-
owner: config.owner,
|
|
283
|
-
gateway_url: config.gateway_url,
|
|
284
|
-
tier: autonomy,
|
|
285
|
-
balance,
|
|
286
|
-
reserve: budget.reserve_credits,
|
|
287
|
-
skills
|
|
288
|
-
};
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
// src/cli/init-action.ts
|
|
292
|
-
import { randomBytes } from "crypto";
|
|
293
84
|
import { join as join2 } from "path";
|
|
294
85
|
import { networkInterfaces } from "os";
|
|
295
|
-
|
|
296
|
-
// src/onboarding/index.ts
|
|
297
|
-
import { randomUUID as randomUUID2 } from "crypto";
|
|
298
|
-
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
299
|
-
import { join } from "path";
|
|
300
|
-
|
|
301
|
-
// src/onboarding/capability-templates.ts
|
|
302
|
-
var API_PATTERNS = [
|
|
303
|
-
{
|
|
304
|
-
pattern: /openai|gpt-4|gpt-3|chatgpt|dall-e/i,
|
|
305
|
-
capability: { key: "openai", name: "OpenAI Text Generation", category: "Text Gen", credits_per_call: 3, tags: ["llm", "text", "generation"] }
|
|
306
|
-
},
|
|
307
|
-
{
|
|
308
|
-
pattern: /elevenlabs|eleven.?labs/i,
|
|
309
|
-
capability: { key: "elevenlabs", name: "ElevenLabs TTS", category: "TTS", credits_per_call: 5, tags: ["tts", "audio", "voice"] }
|
|
310
|
-
},
|
|
311
|
-
{
|
|
312
|
-
pattern: /anthropic|claude/i,
|
|
313
|
-
capability: { key: "anthropic", name: "Anthropic Claude", category: "Text Gen", credits_per_call: 3, tags: ["llm", "text", "generation"] }
|
|
314
|
-
},
|
|
315
|
-
{
|
|
316
|
-
pattern: /recraft/i,
|
|
317
|
-
capability: { key: "recraft", name: "Recraft V4 Image Gen", category: "Image Gen", credits_per_call: 8, tags: ["image", "generation", "design"] }
|
|
318
|
-
},
|
|
319
|
-
{
|
|
320
|
-
pattern: /kling/i,
|
|
321
|
-
capability: { key: "kling", name: "Kling AI Video Gen", category: "Video Gen", credits_per_call: 10, tags: ["video", "generation"] }
|
|
322
|
-
},
|
|
323
|
-
{
|
|
324
|
-
pattern: /stable.?diffusion|sdxl|comfyui/i,
|
|
325
|
-
capability: { key: "stable-diffusion", name: "Stable Diffusion Image Gen", category: "Image Gen", credits_per_call: 6, tags: ["image", "generation", "diffusion"] }
|
|
326
|
-
},
|
|
327
|
-
{
|
|
328
|
-
pattern: /whisper|speech.?to.?text|stt/i,
|
|
329
|
-
capability: { key: "whisper", name: "Whisper Speech-to-Text", category: "STT", credits_per_call: 3, tags: ["stt", "audio", "transcription"] }
|
|
330
|
-
},
|
|
331
|
-
{
|
|
332
|
-
pattern: /puppeteer|playwright|selenium/i,
|
|
333
|
-
capability: { key: "puppeteer", name: "Web Scraping & Automation", category: "Web Scraping", credits_per_call: 2, tags: ["scraping", "automation", "browser"] }
|
|
334
|
-
},
|
|
335
|
-
{
|
|
336
|
-
pattern: /ffmpeg/i,
|
|
337
|
-
capability: { key: "ffmpeg", name: "FFmpeg Media Processing", category: "Media Processing", credits_per_call: 3, tags: ["media", "audio", "video", "processing"] }
|
|
338
|
-
},
|
|
339
|
-
{
|
|
340
|
-
pattern: /tesseract|ocr/i,
|
|
341
|
-
capability: { key: "tesseract", name: "OCR Text Extraction", category: "OCR", credits_per_call: 4, tags: ["ocr", "text", "extraction"] }
|
|
342
|
-
}
|
|
343
|
-
];
|
|
344
|
-
var INTERACTIVE_TEMPLATES = [
|
|
345
|
-
{ key: "openai", name: "Text Generation (GPT-4o / Claude / Gemini)", category: "Text Gen", credits_per_call: 3, tags: ["llm", "text", "generation"] },
|
|
346
|
-
{ key: "image-gen", name: "Image Generation (DALL-E / Recraft / Stable Diffusion)", category: "Image Gen", credits_per_call: 8, tags: ["image", "generation"] },
|
|
347
|
-
{ key: "tts", name: "TTS / Voice (ElevenLabs / Google TTS)", category: "TTS", credits_per_call: 5, tags: ["tts", "audio", "voice"] },
|
|
348
|
-
{ key: "video-gen", name: "Video Generation (Kling / Runway)", category: "Video Gen", credits_per_call: 10, tags: ["video", "generation"] },
|
|
349
|
-
{ key: "code-review", name: "Code Review / Analysis", category: "Code", credits_per_call: 3, tags: ["code", "review", "analysis"] },
|
|
350
|
-
{ key: "scraping", name: "Web Scraping / Data Extraction", category: "Web Scraping", credits_per_call: 2, tags: ["scraping", "data", "extraction"] },
|
|
351
|
-
{ key: "translation", name: "Translation", category: "Translation", credits_per_call: 3, tags: ["translation", "language", "text"] },
|
|
352
|
-
{ key: "custom", name: "Custom (describe it)", category: "Custom", credits_per_call: 5, tags: ["custom"] }
|
|
353
|
-
];
|
|
354
|
-
|
|
355
|
-
// src/onboarding/detect-from-docs.ts
|
|
356
|
-
function detectFromDocs(content) {
|
|
357
|
-
if (!content || content.trim().length === 0) {
|
|
358
|
-
return [];
|
|
359
|
-
}
|
|
360
|
-
const seen = /* @__PURE__ */ new Set();
|
|
361
|
-
const results = [];
|
|
362
|
-
for (const entry of API_PATTERNS) {
|
|
363
|
-
if (entry.pattern.test(content) && !seen.has(entry.capability.key)) {
|
|
364
|
-
seen.add(entry.capability.key);
|
|
365
|
-
results.push({ ...entry.capability });
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
return results;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
// src/onboarding/interactive.ts
|
|
372
86
|
import { createInterface } from "readline";
|
|
373
|
-
async function interactiveTemplateMenu() {
|
|
374
|
-
console.log("\nNo capabilities auto-detected.\n");
|
|
375
|
-
console.log("What can your agent do? Pick from templates:\n");
|
|
376
|
-
for (let i = 0; i < INTERACTIVE_TEMPLATES.length; i++) {
|
|
377
|
-
console.log(` ${i + 1}. ${INTERACTIVE_TEMPLATES[i].name}`);
|
|
378
|
-
}
|
|
379
|
-
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
380
|
-
const answer = await new Promise((resolve) => {
|
|
381
|
-
rl.question("\nSelect [1-8, comma-separated]: ", (ans) => {
|
|
382
|
-
rl.close();
|
|
383
|
-
resolve(ans);
|
|
384
|
-
});
|
|
385
|
-
});
|
|
386
|
-
return parseSelection(answer);
|
|
387
|
-
}
|
|
388
|
-
function parseSelection(input) {
|
|
389
|
-
if (!input || input.trim().length === 0) {
|
|
390
|
-
return [];
|
|
391
|
-
}
|
|
392
|
-
const selected = [];
|
|
393
|
-
const seen = /* @__PURE__ */ new Set();
|
|
394
|
-
const parts = input.split(",").map((s) => s.trim());
|
|
395
|
-
for (const part of parts) {
|
|
396
|
-
const num = parseInt(part, 10);
|
|
397
|
-
if (isNaN(num) || num < 1 || num > INTERACTIVE_TEMPLATES.length) {
|
|
398
|
-
continue;
|
|
399
|
-
}
|
|
400
|
-
const template = INTERACTIVE_TEMPLATES[num - 1];
|
|
401
|
-
if (!seen.has(template.key)) {
|
|
402
|
-
seen.add(template.key);
|
|
403
|
-
selected.push({ ...template });
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
return selected;
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
// src/onboarding/index.ts
|
|
410
|
-
var DOC_FILES = ["SOUL.md", "CLAUDE.md", "AGENTS.md", "README.md"];
|
|
411
|
-
function detectCapabilities(opts = {}) {
|
|
412
|
-
const cwd = opts.cwd ?? process.cwd();
|
|
413
|
-
if (opts.fromFile) {
|
|
414
|
-
const filePath = opts.fromFile.startsWith("/") ? opts.fromFile : join(cwd, opts.fromFile);
|
|
415
|
-
if (existsSync2(filePath)) {
|
|
416
|
-
const content = readFileSync2(filePath, "utf-8");
|
|
417
|
-
const capabilities = detectFromDocs(content);
|
|
418
|
-
if (capabilities.length > 0) {
|
|
419
|
-
return { source: "docs", capabilities, sourceFile: filePath };
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
return { source: "none", capabilities: [] };
|
|
423
|
-
}
|
|
424
|
-
for (const fileName of DOC_FILES) {
|
|
425
|
-
const filePath = join(cwd, fileName);
|
|
426
|
-
if (!existsSync2(filePath)) continue;
|
|
427
|
-
const content = readFileSync2(filePath, "utf-8");
|
|
428
|
-
if (fileName === "SOUL.md") {
|
|
429
|
-
return { source: "soul", capabilities: [], soulContent: content, sourceFile: filePath };
|
|
430
|
-
}
|
|
431
|
-
const capabilities = detectFromDocs(content);
|
|
432
|
-
if (capabilities.length > 0) {
|
|
433
|
-
return { source: "docs", capabilities, sourceFile: filePath };
|
|
434
|
-
}
|
|
435
|
-
}
|
|
436
|
-
const envKeys = detectApiKeys(KNOWN_API_KEYS);
|
|
437
|
-
if (envKeys.length > 0) {
|
|
438
|
-
return { source: "env", capabilities: [], envKeys };
|
|
439
|
-
}
|
|
440
|
-
return { source: "none", capabilities: [] };
|
|
441
|
-
}
|
|
442
|
-
function capabilitiesToV2Card(capabilities, owner, agentName) {
|
|
443
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
444
|
-
const skills = capabilities.map((cap) => ({
|
|
445
|
-
id: cap.key,
|
|
446
|
-
name: cap.name,
|
|
447
|
-
description: `${cap.name} capability \u2014 ${cap.category}`,
|
|
448
|
-
level: 1,
|
|
449
|
-
category: cap.category.toLowerCase().replace(/\s+/g, "_"),
|
|
450
|
-
inputs: [{ name: "input", type: "text", required: true }],
|
|
451
|
-
outputs: [{ name: "output", type: "text", required: true }],
|
|
452
|
-
pricing: { credits_per_call: cap.credits_per_call },
|
|
453
|
-
availability: { online: true },
|
|
454
|
-
metadata: {
|
|
455
|
-
tags: cap.tags
|
|
456
|
-
}
|
|
457
|
-
}));
|
|
458
|
-
const card = {
|
|
459
|
-
spec_version: "2.0",
|
|
460
|
-
id: randomUUID2(),
|
|
461
|
-
owner,
|
|
462
|
-
agent_name: agentName ?? owner,
|
|
463
|
-
skills,
|
|
464
|
-
availability: { online: true },
|
|
465
|
-
created_at: now,
|
|
466
|
-
updated_at: now
|
|
467
|
-
};
|
|
468
|
-
return CapabilityCardV2Schema.parse(card);
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
// src/cli/init-action.ts
|
|
472
|
-
import { createInterface as createInterface2 } from "readline";
|
|
473
|
-
async function confirm(question) {
|
|
474
|
-
const rl = createInterface2({ input: process.stdin, output: process.stdout });
|
|
475
|
-
try {
|
|
476
|
-
return await new Promise((resolve) => {
|
|
477
|
-
rl.question(question, (answer) => {
|
|
478
|
-
resolve(answer.trim().toLowerCase() === "y");
|
|
479
|
-
});
|
|
480
|
-
});
|
|
481
|
-
} finally {
|
|
482
|
-
rl.close();
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
function getLanIp() {
|
|
486
|
-
const nets = networkInterfaces();
|
|
487
|
-
for (const ifaces of Object.values(nets)) {
|
|
488
|
-
for (const iface of ifaces ?? []) {
|
|
489
|
-
if (iface.family === "IPv4" && !iface.internal) return iface.address;
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
return "localhost";
|
|
493
|
-
}
|
|
494
|
-
function loadIdentityAuth(owner) {
|
|
495
|
-
const configDir = getConfigDir();
|
|
496
|
-
const { identity, keys } = loadOrRepairIdentity(configDir, owner);
|
|
497
|
-
return {
|
|
498
|
-
agentId: identity.agent_id,
|
|
499
|
-
publicKey: identity.public_key,
|
|
500
|
-
privateKey: keys.privateKey
|
|
501
|
-
};
|
|
502
|
-
}
|
|
503
|
-
function syncAgentRecord(db, identity, owner, displayName) {
|
|
504
|
-
const existingAgent = lookupAgent(db, identity.agent_id) ?? lookupAgentByOwner(db, owner);
|
|
505
|
-
if (!existingAgent) {
|
|
506
|
-
createAgentRecord(db, {
|
|
507
|
-
agent_id: identity.agent_id,
|
|
508
|
-
display_name: displayName,
|
|
509
|
-
public_key: identity.public_key,
|
|
510
|
-
legacy_owner: owner
|
|
511
|
-
});
|
|
512
|
-
return;
|
|
513
|
-
}
|
|
514
|
-
const updates = {};
|
|
515
|
-
if (existingAgent.display_name !== displayName) {
|
|
516
|
-
updates.display_name = displayName;
|
|
517
|
-
}
|
|
518
|
-
if (existingAgent.legacy_owner !== owner) {
|
|
519
|
-
updates.legacy_owner = owner;
|
|
520
|
-
}
|
|
521
|
-
if (Object.keys(updates).length > 0) {
|
|
522
|
-
updateAgentRecord(db, existingAgent.agent_id, updates);
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
async function performInit(opts) {
|
|
526
|
-
const configDir = getConfigDir();
|
|
527
|
-
const dbPath = join2(configDir, "registry.db");
|
|
528
|
-
const creditDbPath = join2(configDir, "credit.db");
|
|
529
|
-
const port = parseInt(opts.port, 10);
|
|
530
|
-
const ip = opts.host ?? getLanIp();
|
|
531
|
-
const yesMode = opts.yes ?? opts.nonInteractive ?? false;
|
|
532
|
-
const existingConfig = loadConfig();
|
|
533
|
-
const owner = opts.agentId ?? opts.owner ?? existingConfig?.owner ?? `agent-${randomBytes(4).toString("hex")}`;
|
|
534
|
-
const config = {
|
|
535
|
-
...existingConfig,
|
|
536
|
-
owner,
|
|
537
|
-
gateway_url: `http://${ip}:${port}`,
|
|
538
|
-
gateway_port: port,
|
|
539
|
-
db_path: dbPath,
|
|
540
|
-
credit_db_path: creditDbPath,
|
|
541
|
-
token: existingConfig?.token ?? randomBytes(32).toString("hex"),
|
|
542
|
-
api_key: existingConfig?.api_key ?? randomBytes(32).toString("hex"),
|
|
543
|
-
...existingConfig?.registry ? { registry: existingConfig.registry } : yesMode ? { registry: "https://agentbnb.fly.dev" } : {}
|
|
544
|
-
};
|
|
545
|
-
saveConfig(config);
|
|
546
|
-
const identityMaterial = loadOrRepairIdentity(configDir, owner);
|
|
547
|
-
const identity = identityMaterial.identity;
|
|
548
|
-
const keypairStatus = identityMaterial.status === "generated" ? "generated" : "existing";
|
|
549
|
-
const creditDb = openCreditDb(creditDbPath);
|
|
550
|
-
const registryDb = openDatabase(dbPath);
|
|
551
|
-
syncAgentRecord(creditDb, identity, owner, config.display_name ?? owner);
|
|
552
|
-
syncAgentRecord(registryDb, identity, owner, config.display_name ?? owner);
|
|
553
|
-
if (existingConfig?.owner && existingConfig.owner !== owner) {
|
|
554
|
-
migrateOwner(creditDb, existingConfig.owner, owner);
|
|
555
|
-
const rows = registryDb.prepare("SELECT id, owner, data FROM capability_cards WHERE owner = ?").all(existingConfig.owner);
|
|
556
|
-
for (const row of rows) {
|
|
557
|
-
try {
|
|
558
|
-
const card = JSON.parse(row.data);
|
|
559
|
-
const updatedCard = attachCanonicalAgentId(registryDb, {
|
|
560
|
-
...card,
|
|
561
|
-
owner
|
|
562
|
-
});
|
|
563
|
-
registryDb.prepare("UPDATE capability_cards SET owner = ?, data = ? WHERE id = ?").run(owner, JSON.stringify(updatedCard), row.id);
|
|
564
|
-
} catch {
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
if (!opts.json && rows.length > 0) {
|
|
568
|
-
console.log(`Migrated ${rows.length} card(s) \u2192 ${owner}`);
|
|
569
|
-
}
|
|
570
|
-
const allOwners = creditDb.prepare("SELECT owner FROM credit_balances WHERE owner != ?").all(owner);
|
|
571
|
-
for (const { owner: oldOwner } of allOwners) {
|
|
572
|
-
migrateOwner(creditDb, oldOwner, owner);
|
|
573
|
-
}
|
|
574
|
-
if (existingConfig.registry) {
|
|
575
|
-
try {
|
|
576
|
-
const renameAuth = loadIdentityAuth(owner);
|
|
577
|
-
const renameLedger = createLedger({
|
|
578
|
-
registryUrl: existingConfig.registry,
|
|
579
|
-
ownerPublicKey: renameAuth.publicKey,
|
|
580
|
-
privateKey: renameAuth.privateKey
|
|
581
|
-
});
|
|
582
|
-
await renameLedger.rename(existingConfig.owner, owner);
|
|
583
|
-
if (!opts.json) {
|
|
584
|
-
console.log(`Migrated Registry credits: ${existingConfig.owner} \u2192 ${owner}`);
|
|
585
|
-
}
|
|
586
|
-
} catch (err) {
|
|
587
|
-
if (!opts.json) {
|
|
588
|
-
console.warn(`Warning: could not migrate Registry credits: ${err.message}`);
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
}
|
|
592
|
-
if (!opts.json) {
|
|
593
|
-
console.log(`Migrated local credits: ${existingConfig.owner} \u2192 ${owner}`);
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
if (!config.agent_id || config.agent_id !== identity.agent_id) {
|
|
597
|
-
config.agent_id = identity.agent_id;
|
|
598
|
-
saveConfig(config);
|
|
599
|
-
}
|
|
600
|
-
bootstrapAgent(creditDb, identity.agent_id, 100);
|
|
601
|
-
registryDb.close();
|
|
602
|
-
creditDb.close();
|
|
603
|
-
let registryBalance;
|
|
604
|
-
if (config.registry) {
|
|
605
|
-
try {
|
|
606
|
-
const identityAuth = loadIdentityAuth(owner);
|
|
607
|
-
const ledger = createLedger({
|
|
608
|
-
registryUrl: config.registry,
|
|
609
|
-
ownerPublicKey: identityAuth.publicKey,
|
|
610
|
-
privateKey: identityAuth.privateKey
|
|
611
|
-
});
|
|
612
|
-
await ledger.grant(owner, 50);
|
|
613
|
-
registryBalance = await ledger.getBalance(owner);
|
|
614
|
-
} catch (err) {
|
|
615
|
-
console.warn(`Warning: could not connect to Registry for credit grant: ${err.message}`);
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
const skipDetect = opts.detect === false;
|
|
619
|
-
const publishedCards = [];
|
|
620
|
-
let detectedSource = "none";
|
|
621
|
-
if (!skipDetect) {
|
|
622
|
-
if (!opts.json) {
|
|
623
|
-
console.log("\nDetecting capabilities...");
|
|
624
|
-
}
|
|
625
|
-
const result = detectCapabilities({ fromFile: opts.from, cwd: process.cwd() });
|
|
626
|
-
detectedSource = result.source;
|
|
627
|
-
if (result.source === "soul") {
|
|
628
|
-
if (!opts.json) {
|
|
629
|
-
console.log(` Found SOUL.md \u2014 extracting capabilities...`);
|
|
630
|
-
}
|
|
631
|
-
const db = openDatabase(dbPath);
|
|
632
|
-
try {
|
|
633
|
-
const card = publishFromSoulV2(db, result.soulContent, owner);
|
|
634
|
-
publishedCards.push({ id: card.id, name: card.agent_name });
|
|
635
|
-
if (!opts.json) {
|
|
636
|
-
console.log(` Published v2.0 card: ${card.agent_name} (${card.skills.length} skills)`);
|
|
637
|
-
}
|
|
638
|
-
} finally {
|
|
639
|
-
db.close();
|
|
640
|
-
}
|
|
641
|
-
} else if (result.source === "docs") {
|
|
642
|
-
if (!opts.json) {
|
|
643
|
-
console.log(` Found ${result.sourceFile ?? "docs"} \u2014 detected ${result.capabilities.length} capabilities:`);
|
|
644
|
-
for (const cap of result.capabilities) {
|
|
645
|
-
console.log(` ${cap.name} (${cap.category}, cr ${cap.credits_per_call}/call)`);
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
const card = capabilitiesToV2Card(result.capabilities, owner);
|
|
649
|
-
if (yesMode) {
|
|
650
|
-
const db = openDatabase(dbPath);
|
|
651
|
-
try {
|
|
652
|
-
const storedCard = attachCanonicalAgentId(db, card);
|
|
653
|
-
db.prepare(
|
|
654
|
-
`INSERT OR REPLACE INTO capability_cards (id, owner, data, created_at, updated_at)
|
|
655
|
-
VALUES (?, ?, ?, ?, ?)`
|
|
656
|
-
).run(
|
|
657
|
-
storedCard.id,
|
|
658
|
-
storedCard.owner,
|
|
659
|
-
JSON.stringify(storedCard),
|
|
660
|
-
storedCard.created_at,
|
|
661
|
-
storedCard.updated_at
|
|
662
|
-
);
|
|
663
|
-
publishedCards.push({ id: storedCard.id, name: storedCard.agent_name });
|
|
664
|
-
if (!opts.json) {
|
|
665
|
-
console.log(` Published v2.0 card: ${storedCard.agent_name} (${storedCard.skills.length} skills)`);
|
|
666
|
-
}
|
|
667
|
-
} finally {
|
|
668
|
-
db.close();
|
|
669
|
-
}
|
|
670
|
-
} else if (process.stdout.isTTY) {
|
|
671
|
-
const yes = await confirm(`
|
|
672
|
-
Publish these ${card.skills.length} capabilities? [y/N] `);
|
|
673
|
-
if (yes) {
|
|
674
|
-
const db = openDatabase(dbPath);
|
|
675
|
-
try {
|
|
676
|
-
const storedCard = attachCanonicalAgentId(db, card);
|
|
677
|
-
db.prepare(
|
|
678
|
-
`INSERT OR REPLACE INTO capability_cards (id, owner, data, created_at, updated_at)
|
|
679
|
-
VALUES (?, ?, ?, ?, ?)`
|
|
680
|
-
).run(
|
|
681
|
-
storedCard.id,
|
|
682
|
-
storedCard.owner,
|
|
683
|
-
JSON.stringify(storedCard),
|
|
684
|
-
storedCard.created_at,
|
|
685
|
-
storedCard.updated_at
|
|
686
|
-
);
|
|
687
|
-
publishedCards.push({ id: storedCard.id, name: storedCard.agent_name });
|
|
688
|
-
console.log(` Published v2.0 card: ${storedCard.agent_name} (${storedCard.skills.length} skills)`);
|
|
689
|
-
} finally {
|
|
690
|
-
db.close();
|
|
691
|
-
}
|
|
692
|
-
} else {
|
|
693
|
-
console.log(" Skipped publishing.");
|
|
694
|
-
}
|
|
695
|
-
} else {
|
|
696
|
-
if (!opts.json) {
|
|
697
|
-
console.log(" Non-interactive environment. Re-run with --yes to auto-publish.");
|
|
698
|
-
}
|
|
699
|
-
}
|
|
700
|
-
} else if (result.source === "env") {
|
|
701
|
-
const detectedKeys = result.envKeys ?? [];
|
|
702
|
-
if (!opts.json) {
|
|
703
|
-
console.log(` Detected ${detectedKeys.length} API key${detectedKeys.length > 1 ? "s" : ""}: ${detectedKeys.join(", ")}`);
|
|
704
|
-
}
|
|
705
|
-
const detectedPorts = await detectOpenPorts([7700, 7701, 8080, 3e3, 8e3, 11434]);
|
|
706
|
-
if (detectedPorts.length > 0 && !opts.json) {
|
|
707
|
-
console.log(` Found services on ports: ${detectedPorts.join(", ")}`);
|
|
708
|
-
}
|
|
709
|
-
const drafts = detectedKeys.map((key) => buildDraftCard(key, owner)).filter((card) => card !== null);
|
|
710
|
-
if (yesMode) {
|
|
711
|
-
const db = openDatabase(dbPath);
|
|
712
|
-
try {
|
|
713
|
-
for (const card of drafts) {
|
|
714
|
-
insertCard(db, card);
|
|
715
|
-
publishedCards.push({ id: card.id, name: card.name });
|
|
716
|
-
if (!opts.json) {
|
|
717
|
-
console.log(` Published: ${card.name} (${card.id})`);
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
} finally {
|
|
721
|
-
db.close();
|
|
722
|
-
}
|
|
723
|
-
} else if (process.stdout.isTTY) {
|
|
724
|
-
const db = openDatabase(dbPath);
|
|
725
|
-
try {
|
|
726
|
-
for (const card of drafts) {
|
|
727
|
-
const yes = await confirm(`Publish "${card.name}"? [y/N] `);
|
|
728
|
-
if (yes) {
|
|
729
|
-
insertCard(db, card);
|
|
730
|
-
publishedCards.push({ id: card.id, name: card.name });
|
|
731
|
-
console.log(` Published: ${card.name} (${card.id})`);
|
|
732
|
-
} else {
|
|
733
|
-
console.log(` Skipped: ${card.name}`);
|
|
734
|
-
}
|
|
735
|
-
}
|
|
736
|
-
} finally {
|
|
737
|
-
db.close();
|
|
738
|
-
}
|
|
739
|
-
} else {
|
|
740
|
-
if (!opts.json) {
|
|
741
|
-
console.log(" Non-interactive environment. Re-run with --yes to auto-publish.");
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
} else {
|
|
745
|
-
if (process.stdout.isTTY && !yesMode && !opts.json) {
|
|
746
|
-
const selected = await interactiveTemplateMenu();
|
|
747
|
-
if (selected.length > 0) {
|
|
748
|
-
const card = capabilitiesToV2Card(selected, owner);
|
|
749
|
-
const db = openDatabase(dbPath);
|
|
750
|
-
try {
|
|
751
|
-
const storedCard = attachCanonicalAgentId(db, card);
|
|
752
|
-
db.prepare(
|
|
753
|
-
`INSERT OR REPLACE INTO capability_cards (id, owner, data, created_at, updated_at)
|
|
754
|
-
VALUES (?, ?, ?, ?, ?)`
|
|
755
|
-
).run(
|
|
756
|
-
storedCard.id,
|
|
757
|
-
storedCard.owner,
|
|
758
|
-
JSON.stringify(storedCard),
|
|
759
|
-
storedCard.created_at,
|
|
760
|
-
storedCard.updated_at
|
|
761
|
-
);
|
|
762
|
-
publishedCards.push({ id: storedCard.id, name: storedCard.agent_name });
|
|
763
|
-
console.log(`
|
|
764
|
-
Published v2.0 card: ${storedCard.agent_name} (${storedCard.skills.length} skills)`);
|
|
765
|
-
} finally {
|
|
766
|
-
db.close();
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
} else if (!opts.json) {
|
|
770
|
-
console.log(" No capabilities detected. You can manually publish with `agentbnb publish`.");
|
|
771
|
-
}
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
return {
|
|
775
|
-
config,
|
|
776
|
-
owner,
|
|
777
|
-
configDir,
|
|
778
|
-
publishedCards,
|
|
779
|
-
registryBalance,
|
|
780
|
-
identity: { agent_id: identity.agent_id },
|
|
781
|
-
keypairStatus,
|
|
782
|
-
detectedSource
|
|
783
|
-
};
|
|
784
|
-
}
|
|
785
87
|
|
|
786
88
|
// src/cli/quickstart.ts
|
|
787
|
-
import { existsSync
|
|
788
|
-
import { join
|
|
89
|
+
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
90
|
+
import { join } from "path";
|
|
789
91
|
import { homedir } from "os";
|
|
790
92
|
var SKILLS_YAML_TEMPLATE = `skills:
|
|
791
93
|
# General-purpose AI task execution via Claude Code CLI
|
|
@@ -828,22 +130,22 @@ var SKILLS_YAML_TEMPLATE = `skills:
|
|
|
828
130
|
credits_per_call: 2
|
|
829
131
|
`;
|
|
830
132
|
function generateSkillsYaml(configDir) {
|
|
831
|
-
const skillsPath =
|
|
832
|
-
if (
|
|
833
|
-
const content =
|
|
133
|
+
const skillsPath = join(configDir, "skills.yaml");
|
|
134
|
+
if (existsSync(skillsPath)) {
|
|
135
|
+
const content = readFileSync(skillsPath, "utf-8");
|
|
834
136
|
const matches = content.match(/^\s+-\s+id:/gm);
|
|
835
137
|
return { generated: false, path: skillsPath, skillCount: matches?.length ?? 0 };
|
|
836
138
|
}
|
|
837
|
-
|
|
139
|
+
writeFileSync(skillsPath, SKILLS_YAML_TEMPLATE, "utf-8");
|
|
838
140
|
return { generated: true, path: skillsPath, skillCount: 3 };
|
|
839
141
|
}
|
|
840
142
|
function registerMcpWithClaudeCode() {
|
|
841
|
-
const claudeDir =
|
|
842
|
-
const claudeJsonPath =
|
|
843
|
-
const legacySettingsPath =
|
|
844
|
-
const useLegacy = !
|
|
143
|
+
const claudeDir = join(homedir(), ".claude");
|
|
144
|
+
const claudeJsonPath = join(homedir(), ".claude.json");
|
|
145
|
+
const legacySettingsPath = join(claudeDir, "settings.json");
|
|
146
|
+
const useLegacy = !existsSync(claudeJsonPath) && existsSync(legacySettingsPath);
|
|
845
147
|
const targetPath = useLegacy ? legacySettingsPath : claudeJsonPath;
|
|
846
|
-
if (!
|
|
148
|
+
if (!existsSync(claudeJsonPath) && !existsSync(claudeDir)) {
|
|
847
149
|
return {
|
|
848
150
|
registered: false,
|
|
849
151
|
reason: "Claude Code not detected. Add MCP manually: claude mcp add agentbnb -- agentbnb mcp-server"
|
|
@@ -857,12 +159,12 @@ function registerMcpWithClaudeCode() {
|
|
|
857
159
|
return { registered: false, path: targetPath, reason: `MCP registration skipped: ${reason}` };
|
|
858
160
|
}
|
|
859
161
|
let settings = {};
|
|
860
|
-
if (
|
|
162
|
+
if (existsSync(targetPath)) {
|
|
861
163
|
try {
|
|
862
|
-
settings = JSON.parse(
|
|
164
|
+
settings = JSON.parse(readFileSync(targetPath, "utf-8"));
|
|
863
165
|
} catch {
|
|
864
166
|
try {
|
|
865
|
-
|
|
167
|
+
writeFileSync(`${targetPath}.bak`, readFileSync(targetPath, "utf-8"), "utf-8");
|
|
866
168
|
} catch {
|
|
867
169
|
}
|
|
868
170
|
settings = {};
|
|
@@ -882,7 +184,7 @@ function registerMcpWithClaudeCode() {
|
|
|
882
184
|
env: {}
|
|
883
185
|
};
|
|
884
186
|
settings.mcpServers = mcpServers;
|
|
885
|
-
|
|
187
|
+
writeFileSync(targetPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
|
|
886
188
|
return { registered: true, path: targetPath };
|
|
887
189
|
}
|
|
888
190
|
async function runQuickstart(opts) {
|
|
@@ -898,14 +200,14 @@ async function runQuickstart(opts) {
|
|
|
898
200
|
json: false
|
|
899
201
|
// We handle output ourselves
|
|
900
202
|
});
|
|
901
|
-
const
|
|
203
|
+
const skills2 = generateSkillsYaml(initResult.configDir);
|
|
902
204
|
if (!jsonMode) {
|
|
903
|
-
if (
|
|
205
|
+
if (skills2.generated) {
|
|
904
206
|
console.log(`
|
|
905
|
-
Generated skills.yaml with ${
|
|
207
|
+
Generated skills.yaml with ${skills2.skillCount} Claude Code skills`);
|
|
906
208
|
} else {
|
|
907
209
|
console.log(`
|
|
908
|
-
Skills: ${
|
|
210
|
+
Skills: ${skills2.skillCount} skill(s) in ${skills2.path}`);
|
|
909
211
|
}
|
|
910
212
|
}
|
|
911
213
|
let mcpResult = { registered: false, reason: "skipped" };
|
|
@@ -925,12 +227,12 @@ Skills: ${skills.skillCount} skill(s) in ${skills.path}`);
|
|
|
925
227
|
if (!skipServe) {
|
|
926
228
|
try {
|
|
927
229
|
const { ProcessGuard } = await import("../process-guard-TNSUNHSR.js");
|
|
928
|
-
const { ServiceCoordinator } = await import("../service-coordinator-
|
|
929
|
-
const guard = new ProcessGuard(
|
|
230
|
+
const { ServiceCoordinator } = await import("../service-coordinator-R5LZVM6A.js");
|
|
231
|
+
const guard = new ProcessGuard(join(initResult.configDir, ".pid"));
|
|
930
232
|
const coordinator = new ServiceCoordinator(initResult.config, guard);
|
|
931
233
|
const result = await coordinator.ensureRunning({
|
|
932
234
|
port: initResult.config.gateway_port,
|
|
933
|
-
skillsYamlPath:
|
|
235
|
+
skillsYamlPath: join(initResult.configDir, "skills.yaml"),
|
|
934
236
|
registryUrl: initResult.config.registry,
|
|
935
237
|
relay: true
|
|
936
238
|
});
|
|
@@ -963,7 +265,7 @@ Skills: ${skills.skillCount} skill(s) in ${skills.path}`);
|
|
|
963
265
|
gateway_url: initResult.config.gateway_url,
|
|
964
266
|
registry: initResult.config.registry,
|
|
965
267
|
credits: initResult.registryBalance ?? 100,
|
|
966
|
-
skills: { count:
|
|
268
|
+
skills: { count: skills2.skillCount, generated: skills2.generated, path: skills2.path },
|
|
967
269
|
mcp: mcpResult,
|
|
968
270
|
daemon: daemonStatus,
|
|
969
271
|
published_cards: initResult.publishedCards
|
|
@@ -974,7 +276,7 @@ Skills: ${skills.skillCount} skill(s) in ${skills.path}`);
|
|
|
974
276
|
console.log(` Gateway: ${initResult.config.gateway_url}`);
|
|
975
277
|
console.log(` Credits: ${initResult.registryBalance ?? 100}`);
|
|
976
278
|
console.log(` Registry: ${initResult.config.registry ?? "not configured"}`);
|
|
977
|
-
console.log(` Skills: ${
|
|
279
|
+
console.log(` Skills: ${skills2.skillCount} loaded`);
|
|
978
280
|
console.log(` MCP: ${mcpResult.registered ? "registered" : mcpResult.reason}`);
|
|
979
281
|
console.log(` Daemon: ${daemonStatus.running ? `running${daemonStatus.pid ? ` (pid ${daemonStatus.pid})` : ""}` : `not running \u2014 ${daemonStatus.reason}`}`);
|
|
980
282
|
console.log("");
|
|
@@ -987,8 +289,8 @@ Skills: ${skills.skillCount} skill(s) in ${skills.path}`);
|
|
|
987
289
|
}
|
|
988
290
|
|
|
989
291
|
// src/cli/index.ts
|
|
990
|
-
var VERSION = true ? "8.
|
|
991
|
-
function
|
|
292
|
+
var VERSION = true ? "8.4.1" : "0.0.0-dev";
|
|
293
|
+
function loadIdentityAuth(owner) {
|
|
992
294
|
const configDir = getConfigDir();
|
|
993
295
|
let keys;
|
|
994
296
|
try {
|
|
@@ -1012,14 +314,14 @@ function buildTimeoutHintFromCard(card, skillId) {
|
|
|
1012
314
|
expected_duration_ms: parsePositiveNumber(card["expected_duration_ms"]),
|
|
1013
315
|
hard_timeout_ms: parsePositiveNumber(card["hard_timeout_ms"])
|
|
1014
316
|
};
|
|
1015
|
-
const
|
|
1016
|
-
if (!Array.isArray(
|
|
317
|
+
const skills2 = card["skills"];
|
|
318
|
+
if (!Array.isArray(skills2)) {
|
|
1017
319
|
return cardHint.expected_duration_ms !== void 0 || cardHint.hard_timeout_ms !== void 0 ? cardHint : void 0;
|
|
1018
320
|
}
|
|
1019
|
-
const selected = skillId ?
|
|
321
|
+
const selected = skillId ? skills2.find((candidate) => {
|
|
1020
322
|
if (!candidate || typeof candidate !== "object") return false;
|
|
1021
323
|
return candidate["id"] === skillId;
|
|
1022
|
-
}) :
|
|
324
|
+
}) : skills2[0];
|
|
1023
325
|
if (!selected || typeof selected !== "object") {
|
|
1024
326
|
return cardHint.expected_duration_ms !== void 0 || cardHint.hard_timeout_ms !== void 0 ? cardHint : void 0;
|
|
1025
327
|
}
|
|
@@ -1030,8 +332,8 @@ function buildTimeoutHintFromCard(card, skillId) {
|
|
|
1030
332
|
};
|
|
1031
333
|
return hint.expected_duration_ms !== void 0 || hint.hard_timeout_ms !== void 0 ? hint : void 0;
|
|
1032
334
|
}
|
|
1033
|
-
function
|
|
1034
|
-
const nets =
|
|
335
|
+
function getLanIp() {
|
|
336
|
+
const nets = networkInterfaces();
|
|
1035
337
|
for (const ifaces of Object.values(nets)) {
|
|
1036
338
|
for (const iface of ifaces ?? []) {
|
|
1037
339
|
if (iface.family === "IPv4" && !iface.internal) return iface.address;
|
|
@@ -1062,7 +364,7 @@ program.command("init").description("Initialize AgentBnB config and create agent
|
|
|
1062
364
|
}
|
|
1063
365
|
console.log(JSON.stringify(jsonOutput, null, 2));
|
|
1064
366
|
} else {
|
|
1065
|
-
const ip = opts.host ??
|
|
367
|
+
const ip = opts.host ?? getLanIp();
|
|
1066
368
|
const port = parseInt(opts.port, 10);
|
|
1067
369
|
console.log(`AgentBnB initialized.`);
|
|
1068
370
|
console.log(` Owner: ${result.owner}`);
|
|
@@ -1086,7 +388,7 @@ program.command("publish <card.json>").description("Publish a Capability Card to
|
|
|
1086
388
|
}
|
|
1087
389
|
let raw;
|
|
1088
390
|
try {
|
|
1089
|
-
raw =
|
|
391
|
+
raw = readFileSync2(cardPath, "utf-8");
|
|
1090
392
|
} catch {
|
|
1091
393
|
console.error(`Error: cannot read file: ${cardPath}`);
|
|
1092
394
|
process.exit(1);
|
|
@@ -1201,11 +503,11 @@ program.command("publish-skills").description("Publish capabilities from skills.
|
|
|
1201
503
|
process.exit(1);
|
|
1202
504
|
}
|
|
1203
505
|
const { parseSkillsFile } = await import("../skill-config-5O2VR546.js");
|
|
1204
|
-
const { skillConfigToSkill } = await import("../publish-capability-
|
|
506
|
+
const { skillConfigToSkill } = await import("../publish-capability-GNH5FHKG.js");
|
|
1205
507
|
const skillsPath = typeof opts.fromSkills === "string" ? opts.fromSkills : "./skills.yaml";
|
|
1206
508
|
let yamlContent;
|
|
1207
509
|
try {
|
|
1208
|
-
yamlContent =
|
|
510
|
+
yamlContent = readFileSync2(skillsPath, "utf-8");
|
|
1209
511
|
} catch {
|
|
1210
512
|
console.error(`Error: cannot read skills.yaml at ${skillsPath}`);
|
|
1211
513
|
process.exit(1);
|
|
@@ -1225,15 +527,15 @@ program.command("publish-skills").description("Publish capabilities from skills.
|
|
|
1225
527
|
console.log("No public skills to publish (all skills have visibility: private or no skills found).");
|
|
1226
528
|
return;
|
|
1227
529
|
}
|
|
1228
|
-
const
|
|
530
|
+
const skills2 = publicSkillConfigs.map((sc) => skillConfigToSkill(sc));
|
|
1229
531
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1230
532
|
const card = {
|
|
1231
533
|
spec_version: "2.0",
|
|
1232
|
-
id:
|
|
534
|
+
id: randomUUID(),
|
|
1233
535
|
owner: config.owner,
|
|
1234
536
|
agent_id: config.agent_id,
|
|
1235
537
|
agent_name: config.owner,
|
|
1236
|
-
skills,
|
|
538
|
+
skills: skills2,
|
|
1237
539
|
availability: { online: true },
|
|
1238
540
|
created_at: now,
|
|
1239
541
|
updated_at: now
|
|
@@ -1247,8 +549,8 @@ program.command("publish-skills").description("Publish capabilities from skills.
|
|
|
1247
549
|
} finally {
|
|
1248
550
|
db.close();
|
|
1249
551
|
}
|
|
1250
|
-
console.log(`Published ${
|
|
1251
|
-
for (const skill of
|
|
552
|
+
console.log(`Published ${skills2.length} skill(s) to local registry`);
|
|
553
|
+
for (const skill of skills2) {
|
|
1252
554
|
console.log(` - ${skill.id}: ${skill.name} (${skill.pricing.credits_per_call} cr/call)`);
|
|
1253
555
|
}
|
|
1254
556
|
});
|
|
@@ -1454,7 +756,7 @@ program.command("request [card-id]").description("Request a capability from anot
|
|
|
1454
756
|
}
|
|
1455
757
|
let batchPayload;
|
|
1456
758
|
try {
|
|
1457
|
-
const raw =
|
|
759
|
+
const raw = readFileSync2(opts.batch, "utf-8");
|
|
1458
760
|
batchPayload = JSON.parse(raw);
|
|
1459
761
|
} catch (err) {
|
|
1460
762
|
console.error(`Error: could not read batch file: ${err.message}`);
|
|
@@ -1515,8 +817,8 @@ Batch Results (${res.results.length} items):`);
|
|
|
1515
817
|
process.exit(1);
|
|
1516
818
|
}
|
|
1517
819
|
}
|
|
1518
|
-
const registryDb = openDatabase(
|
|
1519
|
-
const creditDb = openCreditDb(
|
|
820
|
+
const registryDb = openDatabase(join2(getConfigDir(), "registry.db"));
|
|
821
|
+
const creditDb = openCreditDb(join2(getConfigDir(), "credit.db"));
|
|
1520
822
|
registryDb.pragma("busy_timeout = 5000");
|
|
1521
823
|
creditDb.pragma("busy_timeout = 5000");
|
|
1522
824
|
try {
|
|
@@ -1566,7 +868,7 @@ Batch Results (${res.results.length} items):`);
|
|
|
1566
868
|
let targetOwner;
|
|
1567
869
|
let targetAgentId;
|
|
1568
870
|
let timeoutHint;
|
|
1569
|
-
const identityAuth =
|
|
871
|
+
const identityAuth = loadIdentityAuth(config.owner);
|
|
1570
872
|
if (opts.peer) {
|
|
1571
873
|
const peer = findPeer(opts.peer);
|
|
1572
874
|
if (!peer) {
|
|
@@ -1712,7 +1014,7 @@ program.command("status").description("Show credit balance and recent transactio
|
|
|
1712
1014
|
let transactions;
|
|
1713
1015
|
let heldEscrows;
|
|
1714
1016
|
if (config.registry) {
|
|
1715
|
-
const statusIdentityAuth =
|
|
1017
|
+
const statusIdentityAuth = loadIdentityAuth(config.owner);
|
|
1716
1018
|
const statusLedger = createLedger({
|
|
1717
1019
|
registryUrl: config.registry,
|
|
1718
1020
|
ownerPublicKey: statusIdentityAuth.publicKey,
|
|
@@ -1770,14 +1072,14 @@ program.command("serve").description("Start the AgentBnB gateway server").option
|
|
|
1770
1072
|
process.exit(1);
|
|
1771
1073
|
}
|
|
1772
1074
|
const { ProcessGuard } = await import("../process-guard-TNSUNHSR.js");
|
|
1773
|
-
const { ServiceCoordinator } = await import("../service-coordinator-
|
|
1075
|
+
const { ServiceCoordinator } = await import("../service-coordinator-R5LZVM6A.js");
|
|
1774
1076
|
const port = opts.port ? parseInt(opts.port, 10) : config.gateway_port;
|
|
1775
1077
|
const registryPort = parseInt(opts.registryPort, 10);
|
|
1776
1078
|
if (!Number.isFinite(port) || !Number.isFinite(registryPort)) {
|
|
1777
1079
|
console.error("Error: --port and --registry-port must be valid numbers.");
|
|
1778
1080
|
process.exit(1);
|
|
1779
1081
|
}
|
|
1780
|
-
const guard = new ProcessGuard(
|
|
1082
|
+
const guard = new ProcessGuard(join2(getConfigDir(), ".pid"));
|
|
1781
1083
|
const coordinator = new ServiceCoordinator(config, guard);
|
|
1782
1084
|
try {
|
|
1783
1085
|
await coordinator.ensureRunning({
|
|
@@ -1989,8 +1291,8 @@ configCmd.command("get <key>").description("Get a configuration value").action((
|
|
|
1989
1291
|
return;
|
|
1990
1292
|
}
|
|
1991
1293
|
if (key === "shared-skills") {
|
|
1992
|
-
const
|
|
1993
|
-
console.log(
|
|
1294
|
+
const skills2 = config.shared_skills ?? [];
|
|
1295
|
+
console.log(skills2.length > 0 ? skills2.join(", ") : "(all skills published)");
|
|
1994
1296
|
return;
|
|
1995
1297
|
}
|
|
1996
1298
|
const value = config[key];
|
|
@@ -2015,8 +1317,8 @@ cardsCmd.command("list").description("List all published capability cards in the
|
|
|
2015
1317
|
const v2 = card;
|
|
2016
1318
|
const name = String(v2["agent_name"] ?? v2["name"] ?? "(unnamed)");
|
|
2017
1319
|
const owner = String(v2["owner"] ?? "");
|
|
2018
|
-
const
|
|
2019
|
-
const skillsLabel =
|
|
1320
|
+
const skills2 = Array.isArray(v2["skills"]) ? v2["skills"].length : 0;
|
|
1321
|
+
const skillsLabel = skills2 > 0 ? ` (${skills2} skill${skills2 !== 1 ? "s" : ""})` : "";
|
|
2020
1322
|
console.log(` ${card.id} ${name} owner: ${owner}${skillsLabel}`);
|
|
2021
1323
|
}
|
|
2022
1324
|
} finally {
|
|
@@ -2045,7 +1347,7 @@ cardsCmd.command("delete <card-id>").description("Delete a published capability
|
|
|
2045
1347
|
console.log(` Skills: ${skillCount}`);
|
|
2046
1348
|
console.log(` ID: ${card.id}`);
|
|
2047
1349
|
if (!opts.force && process.stdin.isTTY) {
|
|
2048
|
-
const rl =
|
|
1350
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
2049
1351
|
const answer = await new Promise((resolve) => {
|
|
2050
1352
|
rl.question("Confirm deletion? [y/N] ", resolve);
|
|
2051
1353
|
});
|
|
@@ -2074,7 +1376,7 @@ openclaw.command("sync").description("Read SOUL.md and publish/update a v2.0 cap
|
|
|
2074
1376
|
}
|
|
2075
1377
|
let content;
|
|
2076
1378
|
try {
|
|
2077
|
-
content =
|
|
1379
|
+
content = readFileSync2(opts.soulPath, "utf-8");
|
|
2078
1380
|
} catch {
|
|
2079
1381
|
console.error(`Error: cannot read SOUL.md at ${opts.soulPath}`);
|
|
2080
1382
|
process.exit(1);
|
|
@@ -2143,8 +1445,35 @@ openclaw.command("rules").description("Print HEARTBEAT.md rules block (or inject
|
|
|
2143
1445
|
console.log(section);
|
|
2144
1446
|
}
|
|
2145
1447
|
});
|
|
1448
|
+
openclaw.command("setup").description("Interactive onboarding: connect an OpenClaw agent to AgentBnB").option("--agent <name>", "Agent name to set up (skip interactive selection)").option("--soul-path <path>", "Override SOUL.md path").option("-y, --yes", "Skip confirmation prompts").action(async (opts) => {
|
|
1449
|
+
const { runOpenClawSetup } = await import("../openclaw-setup-KA72IIEW.js");
|
|
1450
|
+
await runOpenClawSetup(opts);
|
|
1451
|
+
});
|
|
1452
|
+
var skills = openclaw.command("skills").description("Manage shared skills on AgentBnB");
|
|
1453
|
+
skills.command("list").description("List all shared skills with stats").action(async () => {
|
|
1454
|
+
const { skillsList } = await import("../openclaw-skills-CT673RBL.js");
|
|
1455
|
+
await skillsList({});
|
|
1456
|
+
});
|
|
1457
|
+
skills.command("add").description("Add a skill to share (interactive or --manual)").option("--manual", "Non-interactive: use flags instead of prompts").option("--name <id>", "Skill ID").option("--type <type>", "Skill type (command|openclaw)").option("--price <n>", "Credits per call", parseFloat).option("--description <text>", "Skill description").action(
|
|
1458
|
+
async (opts) => {
|
|
1459
|
+
const { skillsAdd } = await import("../openclaw-skills-CT673RBL.js");
|
|
1460
|
+
await skillsAdd(opts);
|
|
1461
|
+
}
|
|
1462
|
+
);
|
|
1463
|
+
skills.command("remove <skillId>").description("Remove a skill from AgentBnB").action(async (skillId) => {
|
|
1464
|
+
const { skillsRemove } = await import("../openclaw-skills-CT673RBL.js");
|
|
1465
|
+
await skillsRemove(skillId);
|
|
1466
|
+
});
|
|
1467
|
+
skills.command("price <skillId> <price>").description("Update skill price").action(async (skillId, price) => {
|
|
1468
|
+
const { skillsPrice } = await import("../openclaw-skills-CT673RBL.js");
|
|
1469
|
+
await skillsPrice(skillId, parseFloat(price));
|
|
1470
|
+
});
|
|
1471
|
+
skills.command("stats").description("Revenue and performance report").option("--days <n>", "Days to look back", parseInt, 7).action(async (opts) => {
|
|
1472
|
+
const { skillsStats } = await import("../openclaw-skills-CT673RBL.js");
|
|
1473
|
+
await skillsStats(opts);
|
|
1474
|
+
});
|
|
2146
1475
|
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) => {
|
|
2147
|
-
const { conductAction } = await import("../conduct-
|
|
1476
|
+
const { conductAction } = await import("../conduct-FZPUMPCI.js");
|
|
2148
1477
|
const result = await conductAction(task, opts);
|
|
2149
1478
|
if (opts.json) {
|
|
2150
1479
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -2256,7 +1585,7 @@ Feedback for skill: ${opts.skill} (${feedbacks.length} entries)
|
|
|
2256
1585
|
});
|
|
2257
1586
|
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);
|
|
2258
1587
|
program.command("mcp-server").description("Start an MCP (Model Context Protocol) server for IDE integration").action(async () => {
|
|
2259
|
-
const { startMcpServer } = await import("../server-
|
|
1588
|
+
const { startMcpServer } = await import("../server-MH7FTZFN.js");
|
|
2260
1589
|
await startMcpServer();
|
|
2261
1590
|
});
|
|
2262
1591
|
await program.parseAsync(process.argv);
|