agentbnb 7.0.0 → 8.2.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.
- package/dist/{conductor-mode-2GSLHVN6.js → chunk-P4LOYSLA.js} +624 -260
- package/dist/cli/index.js +15 -5
- package/dist/conductor-mode-TFCVCQHU.js +266 -0
- package/dist/{server-MHMAYXWZ.js → server-LMY2A3GT.js} +2 -4
- package/dist/skills/agentbnb/bootstrap.js +775 -28
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/skills/agentbnb/bootstrap.test.ts +94 -5
- package/skills/agentbnb/bootstrap.ts +139 -17
- package/skills/agentbnb/openclaw-tools.test.ts +328 -0
- package/skills/agentbnb/openclaw-tools.ts +297 -0
- package/dist/chunk-B2VJTKO5.js +0 -393
package/dist/cli/index.js
CHANGED
|
@@ -84,7 +84,6 @@ import {
|
|
|
84
84
|
// src/cli/index.ts
|
|
85
85
|
import { Command } from "commander";
|
|
86
86
|
import { readFileSync as readFileSync4 } from "fs";
|
|
87
|
-
import { createRequire } from "module";
|
|
88
87
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
89
88
|
import { join as join4 } from "path";
|
|
90
89
|
import { networkInterfaces as networkInterfaces2 } from "os";
|
|
@@ -868,6 +867,18 @@ function registerMcpWithClaudeCode() {
|
|
|
868
867
|
const resolved = execSync("which agentbnb", { encoding: "utf-8" }).trim();
|
|
869
868
|
if (resolved) agentbnbCommand = resolved;
|
|
870
869
|
} catch {
|
|
870
|
+
try {
|
|
871
|
+
const scriptPath = process.argv[1];
|
|
872
|
+
if (scriptPath && existsSync3(scriptPath)) {
|
|
873
|
+
agentbnbCommand = scriptPath;
|
|
874
|
+
}
|
|
875
|
+
} catch {
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
if (agentbnbCommand === "agentbnb") {
|
|
879
|
+
console.warn(
|
|
880
|
+
"Warning: Could not resolve absolute path to agentbnb binary.\n Claude Code MCP may not work. Install globally first:\n npm install -g agentbnb"
|
|
881
|
+
);
|
|
871
882
|
}
|
|
872
883
|
let settings = {};
|
|
873
884
|
if (existsSync3(settingsPath)) {
|
|
@@ -995,8 +1006,7 @@ Skills: ${skills.skillCount} skill(s) in ${skills.path}`);
|
|
|
995
1006
|
}
|
|
996
1007
|
|
|
997
1008
|
// src/cli/index.ts
|
|
998
|
-
var
|
|
999
|
-
var pkg = require2("../../package.json");
|
|
1009
|
+
var VERSION = "8.2.0";
|
|
1000
1010
|
function loadIdentityAuth2(owner) {
|
|
1001
1011
|
const configDir = getConfigDir();
|
|
1002
1012
|
let keys;
|
|
@@ -1023,7 +1033,7 @@ function getLanIp2() {
|
|
|
1023
1033
|
return "localhost";
|
|
1024
1034
|
}
|
|
1025
1035
|
var program = new Command();
|
|
1026
|
-
program.name("agentbnb").description("P2P Agent Capability Sharing Protocol \u2014 Airbnb for AI agent pipelines").version(
|
|
1036
|
+
program.name("agentbnb").description("P2P Agent Capability Sharing Protocol \u2014 Airbnb for AI agent pipelines").version(VERSION);
|
|
1027
1037
|
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
1038
|
const result = await performInit(opts);
|
|
1029
1039
|
if (opts.json) {
|
|
@@ -2327,7 +2337,7 @@ Feedback for skill: ${opts.skill} (${feedbacks.length} entries)
|
|
|
2327
2337
|
});
|
|
2328
2338
|
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);
|
|
2329
2339
|
program.command("mcp-server").description("Start an MCP (Model Context Protocol) server for IDE integration").action(async () => {
|
|
2330
|
-
const { startMcpServer } = await import("../server-
|
|
2340
|
+
const { startMcpServer } = await import("../server-LMY2A3GT.js");
|
|
2331
2341
|
await startMcpServer();
|
|
2332
2342
|
});
|
|
2333
2343
|
await program.parseAsync(process.argv);
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BudgetController,
|
|
3
|
+
BudgetManager,
|
|
4
|
+
decompose,
|
|
5
|
+
matchSubTasks,
|
|
6
|
+
orchestrate,
|
|
7
|
+
requestCapability,
|
|
8
|
+
validateAndNormalizeSubtasks
|
|
9
|
+
} from "./chunk-P4LOYSLA.js";
|
|
10
|
+
import "./chunk-HLUEOLSZ.js";
|
|
11
|
+
import {
|
|
12
|
+
getCardsByCapabilityType,
|
|
13
|
+
getCardsBySkillCapability
|
|
14
|
+
} from "./chunk-7EF3HYVZ.js";
|
|
15
|
+
import "./chunk-NWIQJ2CL.js";
|
|
16
|
+
import "./chunk-IVOYM3WG.js";
|
|
17
|
+
import "./chunk-WVY2W7AA.js";
|
|
18
|
+
|
|
19
|
+
// src/conductor/team-formation.ts
|
|
20
|
+
import { randomUUID } from "crypto";
|
|
21
|
+
function selectByStrategy(matches, strategy) {
|
|
22
|
+
if (matches.length === 0) return void 0;
|
|
23
|
+
if (strategy === "balanced") {
|
|
24
|
+
return matches[0];
|
|
25
|
+
}
|
|
26
|
+
if (strategy === "quality_optimized") {
|
|
27
|
+
return matches.reduce((best, m) => m.score > best.score ? m : best, matches[0]);
|
|
28
|
+
}
|
|
29
|
+
return matches.reduce((best, m) => {
|
|
30
|
+
if (m.credits < best.credits) return m;
|
|
31
|
+
if (m.credits === best.credits && m.score > best.score) return m;
|
|
32
|
+
return best;
|
|
33
|
+
}, matches[0]);
|
|
34
|
+
}
|
|
35
|
+
async function formTeam(opts) {
|
|
36
|
+
const { subtasks, strategy, db, conductorOwner, registryUrl } = opts;
|
|
37
|
+
const team_id = randomUUID();
|
|
38
|
+
if (subtasks.length === 0) {
|
|
39
|
+
return { team_id, strategy, matched: [], unrouted: [] };
|
|
40
|
+
}
|
|
41
|
+
const matched = [];
|
|
42
|
+
const unrouted = [];
|
|
43
|
+
for (const subtask of subtasks) {
|
|
44
|
+
const skillCards = getCardsBySkillCapability(db, subtask.required_capability).filter((c) => c.owner !== conductorOwner);
|
|
45
|
+
if (skillCards.length > 0) {
|
|
46
|
+
const candidates = skillCards.map((card) => {
|
|
47
|
+
const skills = card.skills ?? [];
|
|
48
|
+
const matchingSkill = skills.find(
|
|
49
|
+
(s) => s.capability_type === subtask.required_capability || (s.capability_types ?? []).includes(subtask.required_capability)
|
|
50
|
+
);
|
|
51
|
+
return {
|
|
52
|
+
subtask_id: subtask.id,
|
|
53
|
+
selected_agent: card.owner,
|
|
54
|
+
selected_skill: matchingSkill?.id ?? "",
|
|
55
|
+
selected_card_id: card.id,
|
|
56
|
+
score: 1,
|
|
57
|
+
credits: matchingSkill?.pricing.credits_per_call ?? 0,
|
|
58
|
+
alternatives: []
|
|
59
|
+
};
|
|
60
|
+
});
|
|
61
|
+
const selected2 = selectByStrategy(candidates, strategy);
|
|
62
|
+
matched.push({
|
|
63
|
+
subtask,
|
|
64
|
+
capability_type: subtask.required_capability,
|
|
65
|
+
agent: selected2.selected_agent,
|
|
66
|
+
skill: selected2.selected_skill,
|
|
67
|
+
card_id: selected2.selected_card_id,
|
|
68
|
+
credits: selected2.credits,
|
|
69
|
+
score: selected2.score
|
|
70
|
+
});
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const matchResults = await matchSubTasks({
|
|
74
|
+
db,
|
|
75
|
+
subtasks: [subtask],
|
|
76
|
+
conductorOwner,
|
|
77
|
+
registryUrl
|
|
78
|
+
});
|
|
79
|
+
const m = matchResults[0];
|
|
80
|
+
if (!m || m.selected_agent === "") {
|
|
81
|
+
unrouted.push(subtask);
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
const allCandidates = [
|
|
85
|
+
m,
|
|
86
|
+
...m.alternatives.map((alt) => ({
|
|
87
|
+
subtask_id: m.subtask_id,
|
|
88
|
+
selected_agent: alt.agent,
|
|
89
|
+
selected_skill: alt.skill,
|
|
90
|
+
score: alt.score,
|
|
91
|
+
credits: alt.credits,
|
|
92
|
+
alternatives: []
|
|
93
|
+
}))
|
|
94
|
+
];
|
|
95
|
+
const selected = selectByStrategy(allCandidates, strategy);
|
|
96
|
+
matched.push({
|
|
97
|
+
subtask,
|
|
98
|
+
capability_type: subtask.required_capability,
|
|
99
|
+
agent: selected.selected_agent,
|
|
100
|
+
skill: selected.selected_skill,
|
|
101
|
+
card_id: selected === m ? m.selected_card_id : void 0,
|
|
102
|
+
credits: selected.credits,
|
|
103
|
+
score: selected.score
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
return { team_id, strategy, matched, unrouted };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// src/conductor/conductor-mode.ts
|
|
110
|
+
var ConductorMode = class {
|
|
111
|
+
db;
|
|
112
|
+
creditDb;
|
|
113
|
+
conductorOwner;
|
|
114
|
+
gatewayToken;
|
|
115
|
+
resolveAgentUrl;
|
|
116
|
+
maxBudget;
|
|
117
|
+
constructor(opts) {
|
|
118
|
+
this.db = opts.db;
|
|
119
|
+
this.creditDb = opts.creditDb;
|
|
120
|
+
this.conductorOwner = opts.conductorOwner;
|
|
121
|
+
this.gatewayToken = opts.gatewayToken;
|
|
122
|
+
this.resolveAgentUrl = opts.resolveAgentUrl;
|
|
123
|
+
this.maxBudget = opts.maxBudget ?? 100;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Execute a conductor skill with the given config and params.
|
|
127
|
+
*
|
|
128
|
+
* @param config - SkillConfig with type 'conductor' and conductor_skill field.
|
|
129
|
+
* @param params - Must include `task` string.
|
|
130
|
+
* @returns Execution result without latency_ms (added by SkillExecutor).
|
|
131
|
+
*/
|
|
132
|
+
async execute(config, params, onProgress) {
|
|
133
|
+
const conductorSkill = config.conductor_skill;
|
|
134
|
+
if (conductorSkill !== "orchestrate" && conductorSkill !== "plan") {
|
|
135
|
+
return {
|
|
136
|
+
success: false,
|
|
137
|
+
error: `Unknown conductor skill: "${conductorSkill}"`
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
const task = params.task;
|
|
141
|
+
if (typeof task !== "string" || task.length === 0) {
|
|
142
|
+
return {
|
|
143
|
+
success: false,
|
|
144
|
+
error: 'Missing or empty "task" parameter'
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
const orchestrationDepth = typeof params.orchestration_depth === "number" ? params.orchestration_depth : 0;
|
|
148
|
+
const decompositionDepth = typeof params.decomposition_depth === "number" ? params.decomposition_depth : 0;
|
|
149
|
+
if (orchestrationDepth >= 2) {
|
|
150
|
+
return {
|
|
151
|
+
success: false,
|
|
152
|
+
error: "orchestration_depth limit exceeded: max 1 nested orchestration"
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
let subtasks = [];
|
|
156
|
+
if (decompositionDepth === 0) {
|
|
157
|
+
const allDecomposers = getCardsByCapabilityType(this.db, "task_decomposition");
|
|
158
|
+
const externalDecomposers = allDecomposers.filter((c) => c.owner !== this.conductorOwner);
|
|
159
|
+
if (externalDecomposers.length > 0) {
|
|
160
|
+
const provider = externalDecomposers[0];
|
|
161
|
+
try {
|
|
162
|
+
const providerUrl = this.resolveAgentUrl(provider.owner);
|
|
163
|
+
const response = await requestCapability({
|
|
164
|
+
gatewayUrl: providerUrl.url,
|
|
165
|
+
token: this.gatewayToken,
|
|
166
|
+
cardId: provider.id,
|
|
167
|
+
params: {
|
|
168
|
+
task,
|
|
169
|
+
decomposition_depth: decompositionDepth + 1,
|
|
170
|
+
orchestration_depth: orchestrationDepth + 1
|
|
171
|
+
},
|
|
172
|
+
timeoutMs: 3e4
|
|
173
|
+
});
|
|
174
|
+
if (Array.isArray(response)) {
|
|
175
|
+
const validation = validateAndNormalizeSubtasks(response, {
|
|
176
|
+
max_credits: this.maxBudget
|
|
177
|
+
});
|
|
178
|
+
if (validation.errors.length === 0) {
|
|
179
|
+
subtasks = validation.valid;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
} catch {
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
if (subtasks.length === 0) {
|
|
187
|
+
subtasks = decompose(task);
|
|
188
|
+
}
|
|
189
|
+
if (subtasks.length === 0) {
|
|
190
|
+
return {
|
|
191
|
+
success: false,
|
|
192
|
+
error: "No template matches task"
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
onProgress?.({ step: 1, total: 5, message: `Decomposed into ${subtasks.length} sub-tasks` });
|
|
196
|
+
const matchResults = await matchSubTasks({
|
|
197
|
+
db: this.db,
|
|
198
|
+
subtasks,
|
|
199
|
+
conductorOwner: this.conductorOwner
|
|
200
|
+
});
|
|
201
|
+
onProgress?.({ step: 2, total: 5, message: `Matched ${matchResults.length} sub-tasks to agents` });
|
|
202
|
+
let team;
|
|
203
|
+
if (conductorSkill === "orchestrate") {
|
|
204
|
+
const strategy = typeof params.formation_strategy === "string" && ["cost_optimized", "quality_optimized", "balanced"].includes(params.formation_strategy) ? params.formation_strategy : "balanced";
|
|
205
|
+
team = await formTeam({
|
|
206
|
+
subtasks,
|
|
207
|
+
strategy,
|
|
208
|
+
db: this.db,
|
|
209
|
+
conductorOwner: this.conductorOwner
|
|
210
|
+
});
|
|
211
|
+
onProgress?.({ step: 2, total: 5, message: `Formed team: ${team.matched.length} members, ${team.unrouted.length} unrouted` });
|
|
212
|
+
}
|
|
213
|
+
const budgetManager = new BudgetManager(this.creditDb, this.conductorOwner);
|
|
214
|
+
const budgetController = new BudgetController(budgetManager, this.maxBudget);
|
|
215
|
+
const executionBudget = budgetController.calculateBudget(matchResults);
|
|
216
|
+
if (!budgetController.canExecute(executionBudget)) {
|
|
217
|
+
return {
|
|
218
|
+
success: false,
|
|
219
|
+
error: `Budget exceeded: estimated ${executionBudget.estimated_total} cr, max ${this.maxBudget} cr`
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
onProgress?.({ step: 3, total: 5, message: `Budget approved: ${executionBudget.estimated_total} cr` });
|
|
223
|
+
if (conductorSkill === "plan") {
|
|
224
|
+
return {
|
|
225
|
+
success: true,
|
|
226
|
+
result: {
|
|
227
|
+
subtasks,
|
|
228
|
+
matches: matchResults,
|
|
229
|
+
budget: executionBudget,
|
|
230
|
+
team
|
|
231
|
+
// undefined when no role hints
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
const matchMap = new Map(
|
|
236
|
+
matchResults.map((m) => [m.subtask_id, m])
|
|
237
|
+
);
|
|
238
|
+
const orchResult = await orchestrate({
|
|
239
|
+
subtasks,
|
|
240
|
+
matches: matchMap,
|
|
241
|
+
gatewayToken: this.gatewayToken,
|
|
242
|
+
resolveAgentUrl: this.resolveAgentUrl,
|
|
243
|
+
maxBudget: this.maxBudget,
|
|
244
|
+
team
|
|
245
|
+
});
|
|
246
|
+
onProgress?.({ step: 4, total: 5, message: "Pipeline execution complete" });
|
|
247
|
+
const resultObj = {};
|
|
248
|
+
for (const [key, value] of orchResult.results) {
|
|
249
|
+
resultObj[key] = value;
|
|
250
|
+
}
|
|
251
|
+
return {
|
|
252
|
+
success: orchResult.success,
|
|
253
|
+
result: {
|
|
254
|
+
plan: subtasks,
|
|
255
|
+
execution: resultObj,
|
|
256
|
+
total_credits: orchResult.total_credits,
|
|
257
|
+
latency_ms: orchResult.latency_ms,
|
|
258
|
+
errors: orchResult.errors
|
|
259
|
+
},
|
|
260
|
+
error: orchResult.success ? void 0 : orchResult.errors?.join("; ")
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
export {
|
|
265
|
+
ConductorMode
|
|
266
|
+
};
|
|
@@ -32,7 +32,6 @@ import {
|
|
|
32
32
|
} from "./chunk-WVY2W7AA.js";
|
|
33
33
|
|
|
34
34
|
// src/mcp/server.ts
|
|
35
|
-
import { createRequire } from "module";
|
|
36
35
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
37
36
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
38
37
|
|
|
@@ -254,8 +253,7 @@ function registerPublishTool(server, ctx) {
|
|
|
254
253
|
}
|
|
255
254
|
|
|
256
255
|
// src/mcp/server.ts
|
|
257
|
-
var
|
|
258
|
-
var pkg = require2("../../package.json");
|
|
256
|
+
var VERSION = "8.2.0";
|
|
259
257
|
async function startMcpServer() {
|
|
260
258
|
const config = loadConfig();
|
|
261
259
|
if (!config) {
|
|
@@ -266,7 +264,7 @@ async function startMcpServer() {
|
|
|
266
264
|
const identity = ensureIdentity(configDir, config.owner);
|
|
267
265
|
const server = new McpServer({
|
|
268
266
|
name: "agentbnb",
|
|
269
|
-
version:
|
|
267
|
+
version: VERSION
|
|
270
268
|
});
|
|
271
269
|
const ctx = {
|
|
272
270
|
configDir,
|