agentbnb 5.1.11 → 7.0.0-beta.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/README.md +245 -39
- package/dist/{card-RSGDCHCV.js → card-REW7BSWW.js} +1 -1
- package/dist/{chunk-FLY3WIQR.js → chunk-2HSUPCBT.js} +3 -3
- package/dist/{chunk-WGZ5AGOX.js → chunk-3CIMVISQ.js} +24 -1
- package/dist/{chunk-NH2FIERR.js → chunk-574W3HHE.js} +1 -1
- package/dist/{chunk-WTXRY7R2.js → chunk-APEG4QIN.js} +157 -9
- package/dist/chunk-BP3L2TET.js +148 -0
- package/dist/{chunk-NLAWT4DT.js → chunk-CWYPTQRQ.js} +7 -7
- package/dist/{chunk-UKT6H7YT.js → chunk-DUW6RX6I.js} +5 -2
- package/dist/chunk-EAD4A4KG.js +430 -0
- package/dist/{chunk-QT7TEVNV.js → chunk-EHSHB7TY.js} +23 -1
- package/dist/{chunk-B5FTAGFN.js → chunk-ETGOKDFR.js} +75 -75
- package/dist/{chunk-5KFI5X7B.js → chunk-F53QQIM2.js} +1 -1
- package/dist/{chunk-MLS6IGGG.js → chunk-FK2MDNTB.js} +117 -117
- package/dist/{chunk-EGUOAHCW.js → chunk-GO4FVRVN.js} +15 -13
- package/dist/{chunk-CRFCWD6V.js → chunk-J2K5S5MX.js} +136 -173
- package/dist/chunk-K5FO42YF.js +1136 -0
- package/dist/{chunk-DFBX3BBD.js → chunk-KA2VIEGM.js} +211 -16
- package/dist/chunk-NWIQJ2CL.js +108 -0
- package/dist/chunk-OCSU2S6W.js +168 -0
- package/dist/{chunk-QQFBFV4V.js → chunk-PGDBUUGR.js} +60 -19
- package/dist/{chunk-QITOPASZ.js → chunk-PSQHUZ7X.js} +1 -1
- package/dist/{chunk-C6KPAFCC.js → chunk-PU7LXOQ3.js} +23 -1
- package/dist/{chunk-JOY533UH.js → chunk-TW65F5EU.js} +1 -1
- package/dist/{chunk-ZX5623ER.js → chunk-VMH2YS2I.js} +1 -1
- package/dist/{chunk-XND2DWTZ.js → chunk-VPQ44XKE.js} +2 -2
- package/dist/{chunk-CSATDXZC.js → chunk-Y7T6IMM3.js} +1 -1
- package/dist/cli/index.js +755 -379
- package/dist/{client-T5MTY3CS.js → client-HRYRJKSA.js} +3 -3
- package/dist/{conduct-WU3VEXB6.js → conduct-JNYJCDHQ.js} +14 -13
- package/dist/conduct-KJUD2RTB.js +22 -0
- package/dist/{conductor-mode-ZMTFZGJP.js → conductor-mode-2VVFMKVE.js} +313 -14
- package/dist/conductor-mode-VGUU54QI.js +276 -0
- package/dist/execute-I4PKSNJM.js +12 -0
- package/dist/execute-MOXSSA3Q.js +15 -0
- package/dist/index.d.ts +795 -2
- package/dist/index.js +861 -111
- package/dist/{process-guard-CC7CNRQJ.js → process-guard-QCCBGILS.js} +1 -1
- package/dist/publish-capability-TS6CNR5G.js +12 -0
- package/dist/reliability-metrics-QG7WC5QK.js +18 -0
- package/dist/{request-VOXBFUOG.js → request-E7TA7COA.js} +19 -18
- package/dist/{serve-skill-IH7UAJNR.js → serve-skill-HIOWYKRU.js} +13 -11
- package/dist/{server-JVQW2TID.js → server-I63CXFX3.js} +17 -16
- package/dist/{service-coordinator-EYRDTHL5.js → service-coordinator-XBNT3SMU.js} +369 -260
- package/dist/skill-config-FETXPNVP.js +22 -0
- package/dist/skills/agentbnb/bootstrap.js +430 -84
- package/dist/websocket-client-5MH6QRJK.js +7 -0
- package/dist/{websocket-client-WRN3HO73.js → websocket-client-PFGVTXNE.js} +1 -1
- package/openclaw.plugin.json +2 -2
- package/package.json +2 -1
- package/skills/agentbnb/SKILL.md +35 -0
- package/skills/agentbnb/bootstrap.ts +126 -8
- package/skills/agentbnb/install.sh +49 -9
- package/dist/chunk-EANI2N2V.js +0 -309
- package/dist/chunk-EPIWHNB2.js +0 -946
- package/dist/conduct-6LKIJJKQ.js +0 -21
- package/dist/conductor-mode-Q4IIDY5E.js +0 -123
- package/dist/execute-4D4ITQCL.js +0 -10
- package/dist/execute-T7Y6RKSW.js +0 -13
- package/dist/websocket-client-6IIDGXKB.js +0 -7
|
@@ -12,61 +12,67 @@ import {
|
|
|
12
12
|
requestViaRelay,
|
|
13
13
|
resolvePendingRequest,
|
|
14
14
|
searchCards
|
|
15
|
-
} from "../../chunk-
|
|
16
|
-
import {
|
|
17
|
-
getConfigDir,
|
|
18
|
-
loadConfig
|
|
19
|
-
} from "../../chunk-IVOYM3WG.js";
|
|
15
|
+
} from "../../chunk-ETGOKDFR.js";
|
|
20
16
|
import {
|
|
21
17
|
executeCapabilityBatch,
|
|
22
18
|
executeCapabilityRequest,
|
|
23
|
-
getActivityFeed,
|
|
24
|
-
getCard,
|
|
25
|
-
getEvolutionHistory,
|
|
26
|
-
getLatestEvolution,
|
|
27
|
-
getRequestLog,
|
|
28
|
-
getSkillRequestCount,
|
|
29
|
-
insertCard,
|
|
30
|
-
insertEvolution,
|
|
31
|
-
insertRequestLog,
|
|
32
|
-
listCards,
|
|
33
|
-
openDatabase,
|
|
34
19
|
releaseRequesterEscrow,
|
|
35
|
-
settleRequesterEscrow
|
|
36
|
-
|
|
37
|
-
updateSkillAvailability,
|
|
38
|
-
updateSkillIdleRate
|
|
39
|
-
} from "../../chunk-EPIWHNB2.js";
|
|
20
|
+
settleRequesterEscrow
|
|
21
|
+
} from "../../chunk-EAD4A4KG.js";
|
|
40
22
|
import {
|
|
41
23
|
bootstrapAgent,
|
|
42
24
|
generateKeyPair,
|
|
25
|
+
getActivityFeed,
|
|
43
26
|
getBalance,
|
|
27
|
+
getCard,
|
|
28
|
+
getCardsBySkillCapability,
|
|
29
|
+
getEvolutionHistory,
|
|
44
30
|
getFeedbackForProvider,
|
|
45
31
|
getFeedbackForSkill,
|
|
32
|
+
getLatestEvolution,
|
|
33
|
+
getRequestLog,
|
|
34
|
+
getSkillRequestCount,
|
|
46
35
|
getTransactions,
|
|
47
36
|
holdEscrow,
|
|
37
|
+
insertCard,
|
|
38
|
+
insertEvolution,
|
|
48
39
|
insertFeedback,
|
|
40
|
+
insertRequestLog,
|
|
41
|
+
listCards,
|
|
49
42
|
loadKeyPair,
|
|
50
43
|
migrateOwner,
|
|
51
44
|
openCreditDb,
|
|
45
|
+
openDatabase,
|
|
52
46
|
releaseEscrow,
|
|
53
47
|
saveKeyPair,
|
|
54
48
|
settleEscrow,
|
|
55
49
|
signEscrowReceipt,
|
|
50
|
+
updateCard,
|
|
51
|
+
updateSkillAvailability,
|
|
52
|
+
updateSkillIdleRate,
|
|
56
53
|
verifyEscrowReceipt
|
|
57
|
-
} from "../../chunk-
|
|
54
|
+
} from "../../chunk-K5FO42YF.js";
|
|
55
|
+
import "../../chunk-NWIQJ2CL.js";
|
|
56
|
+
import {
|
|
57
|
+
getConfigDir,
|
|
58
|
+
loadConfig
|
|
59
|
+
} from "../../chunk-IVOYM3WG.js";
|
|
58
60
|
import {
|
|
59
61
|
AgentBnBError,
|
|
60
62
|
AnyCardSchema
|
|
61
|
-
} from "../../chunk-
|
|
63
|
+
} from "../../chunk-3CIMVISQ.js";
|
|
62
64
|
import {
|
|
63
65
|
RelayClient,
|
|
64
66
|
RelayMessageSchema
|
|
65
|
-
} from "../../chunk-
|
|
67
|
+
} from "../../chunk-PU7LXOQ3.js";
|
|
66
68
|
|
|
67
69
|
// skills/agentbnb/bootstrap.ts
|
|
68
70
|
import { join as join5 } from "path";
|
|
71
|
+
import { dirname as dirname4, basename } from "path";
|
|
72
|
+
import { existsSync as existsSync6 } from "fs";
|
|
73
|
+
import { homedir as homedir2 } from "os";
|
|
69
74
|
import { spawnSync } from "child_process";
|
|
75
|
+
import { randomUUID as randomUUID10 } from "crypto";
|
|
70
76
|
|
|
71
77
|
// src/runtime/process-guard.ts
|
|
72
78
|
import { dirname, join } from "path";
|
|
@@ -245,13 +251,16 @@ import { readFileSync as readFileSync2, existsSync as existsSync2 } from "fs";
|
|
|
245
251
|
var SkillExecutor = class {
|
|
246
252
|
skillMap;
|
|
247
253
|
modeMap;
|
|
254
|
+
concurrencyGuard;
|
|
248
255
|
/**
|
|
249
256
|
* @param configs - Parsed SkillConfig array (from parseSkillsFile).
|
|
250
257
|
* @param modes - Map from skill type string to its executor implementation.
|
|
258
|
+
* @param concurrencyGuard - Optional ConcurrencyGuard to enforce max_concurrent limits.
|
|
251
259
|
*/
|
|
252
|
-
constructor(configs, modes) {
|
|
260
|
+
constructor(configs, modes, concurrencyGuard) {
|
|
253
261
|
this.skillMap = new Map(configs.map((c) => [c.id, c]));
|
|
254
262
|
this.modeMap = modes;
|
|
263
|
+
this.concurrencyGuard = concurrencyGuard;
|
|
255
264
|
}
|
|
256
265
|
/**
|
|
257
266
|
* Execute a skill by ID with the given input parameters.
|
|
@@ -284,6 +293,18 @@ var SkillExecutor = class {
|
|
|
284
293
|
latency_ms: Date.now() - startTime
|
|
285
294
|
};
|
|
286
295
|
}
|
|
296
|
+
const maxConcurrent = config.capacity?.max_concurrent ?? Infinity;
|
|
297
|
+
if (this.concurrencyGuard && maxConcurrent !== Infinity) {
|
|
298
|
+
if (!this.concurrencyGuard.canAccept(skillId, maxConcurrent)) {
|
|
299
|
+
return {
|
|
300
|
+
success: false,
|
|
301
|
+
error: `Skill ${skillId} at capacity (${maxConcurrent} concurrent max)`,
|
|
302
|
+
latency_ms: Date.now() - startTime,
|
|
303
|
+
failure_reason: "overload"
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
this.concurrencyGuard.acquire(skillId);
|
|
307
|
+
}
|
|
287
308
|
try {
|
|
288
309
|
const modeResult = await mode.execute(config, params, onProgress);
|
|
289
310
|
return {
|
|
@@ -297,6 +318,10 @@ var SkillExecutor = class {
|
|
|
297
318
|
error: message,
|
|
298
319
|
latency_ms: Date.now() - startTime
|
|
299
320
|
};
|
|
321
|
+
} finally {
|
|
322
|
+
if (this.concurrencyGuard && maxConcurrent !== Infinity) {
|
|
323
|
+
this.concurrencyGuard.release(skillId);
|
|
324
|
+
}
|
|
300
325
|
}
|
|
301
326
|
}
|
|
302
327
|
/**
|
|
@@ -317,13 +342,16 @@ var SkillExecutor = class {
|
|
|
317
342
|
return this.skillMap.get(skillId);
|
|
318
343
|
}
|
|
319
344
|
};
|
|
320
|
-
function createSkillExecutor(configs, modes) {
|
|
321
|
-
return new SkillExecutor(configs, modes);
|
|
345
|
+
function createSkillExecutor(configs, modes, concurrencyGuard) {
|
|
346
|
+
return new SkillExecutor(configs, modes, concurrencyGuard);
|
|
322
347
|
}
|
|
323
348
|
|
|
324
349
|
// src/skills/skill-config.ts
|
|
325
350
|
import { z } from "zod";
|
|
326
351
|
import yaml from "js-yaml";
|
|
352
|
+
var CapacitySchema = z.object({
|
|
353
|
+
max_concurrent: z.number().positive().int().optional()
|
|
354
|
+
}).optional();
|
|
327
355
|
var PricingSchema = z.object({
|
|
328
356
|
credits_per_call: z.number().nonnegative(),
|
|
329
357
|
credits_per_minute: z.number().nonnegative().optional(),
|
|
@@ -345,6 +373,12 @@ var ApiAuthSchema = z.discriminatedUnion("type", [
|
|
|
345
373
|
password: z.string()
|
|
346
374
|
})
|
|
347
375
|
]);
|
|
376
|
+
var CapabilityDeclarationSchema = {
|
|
377
|
+
description: z.string().optional(),
|
|
378
|
+
capability_types: z.array(z.string()).optional(),
|
|
379
|
+
requires_capabilities: z.array(z.string()).optional(),
|
|
380
|
+
visibility: z.enum(["public", "private"]).optional()
|
|
381
|
+
};
|
|
348
382
|
var ApiSkillConfigSchema = z.object({
|
|
349
383
|
id: z.string().min(1),
|
|
350
384
|
type: z.literal("api"),
|
|
@@ -357,7 +391,9 @@ var ApiSkillConfigSchema = z.object({
|
|
|
357
391
|
pricing: PricingSchema,
|
|
358
392
|
timeout_ms: z.number().positive().default(3e4),
|
|
359
393
|
retries: z.number().nonnegative().int().default(0),
|
|
360
|
-
provider: z.string().optional()
|
|
394
|
+
provider: z.string().optional(),
|
|
395
|
+
capacity: CapacitySchema,
|
|
396
|
+
...CapabilityDeclarationSchema
|
|
361
397
|
});
|
|
362
398
|
var PipelineStepSchema = z.union([
|
|
363
399
|
z.object({
|
|
@@ -375,7 +411,9 @@ var PipelineSkillConfigSchema = z.object({
|
|
|
375
411
|
name: z.string().min(1),
|
|
376
412
|
steps: z.array(PipelineStepSchema).min(1),
|
|
377
413
|
pricing: PricingSchema,
|
|
378
|
-
timeout_ms: z.number().positive().optional()
|
|
414
|
+
timeout_ms: z.number().positive().optional(),
|
|
415
|
+
capacity: CapacitySchema,
|
|
416
|
+
...CapabilityDeclarationSchema
|
|
379
417
|
});
|
|
380
418
|
var OpenClawSkillConfigSchema = z.object({
|
|
381
419
|
id: z.string().min(1),
|
|
@@ -384,7 +422,17 @@ var OpenClawSkillConfigSchema = z.object({
|
|
|
384
422
|
agent_name: z.string().min(1),
|
|
385
423
|
channel: z.enum(["telegram", "webhook", "process"]),
|
|
386
424
|
pricing: PricingSchema,
|
|
387
|
-
timeout_ms: z.number().positive().optional()
|
|
425
|
+
timeout_ms: z.number().positive().optional(),
|
|
426
|
+
capacity: CapacitySchema,
|
|
427
|
+
...CapabilityDeclarationSchema
|
|
428
|
+
});
|
|
429
|
+
var ClaudeCodeConfigSchema = z.object({
|
|
430
|
+
/** Optional system prompt passed via `-p` flag. */
|
|
431
|
+
system_prompt: z.string().optional(),
|
|
432
|
+
/** Model to use (e.g. 'claude-opus-4-6', 'claude-sonnet-4-6'). */
|
|
433
|
+
model: z.string().optional(),
|
|
434
|
+
/** When true, passes `--dangerously-skip-permissions` to claude CLI. */
|
|
435
|
+
auto_mode: z.boolean().default(false)
|
|
388
436
|
});
|
|
389
437
|
var CommandSkillConfigSchema = z.object({
|
|
390
438
|
id: z.string().min(1),
|
|
@@ -394,8 +442,11 @@ var CommandSkillConfigSchema = z.object({
|
|
|
394
442
|
output_type: z.enum(["json", "text", "file"]),
|
|
395
443
|
allowed_commands: z.array(z.string()).optional(),
|
|
396
444
|
working_dir: z.string().optional(),
|
|
445
|
+
claude_code: ClaudeCodeConfigSchema.optional(),
|
|
397
446
|
timeout_ms: z.number().positive().default(3e4),
|
|
398
|
-
pricing: PricingSchema
|
|
447
|
+
pricing: PricingSchema,
|
|
448
|
+
capacity: CapacitySchema,
|
|
449
|
+
...CapabilityDeclarationSchema
|
|
399
450
|
});
|
|
400
451
|
var ConductorSkillConfigSchema = z.object({
|
|
401
452
|
id: z.string().min(1),
|
|
@@ -403,7 +454,9 @@ var ConductorSkillConfigSchema = z.object({
|
|
|
403
454
|
name: z.string().min(1),
|
|
404
455
|
conductor_skill: z.enum(["orchestrate", "plan"]),
|
|
405
456
|
pricing: PricingSchema,
|
|
406
|
-
timeout_ms: z.number().positive().optional()
|
|
457
|
+
timeout_ms: z.number().positive().optional(),
|
|
458
|
+
capacity: CapacitySchema,
|
|
459
|
+
...CapabilityDeclarationSchema
|
|
407
460
|
});
|
|
408
461
|
var SkillConfigSchema = z.discriminatedUnion("type", [
|
|
409
462
|
ApiSkillConfigSchema,
|
|
@@ -923,14 +976,32 @@ var CommandExecutor = class {
|
|
|
923
976
|
const cmdConfig = config;
|
|
924
977
|
const baseCommand = cmdConfig.command.trim().split(/\s+/)[0] ?? "";
|
|
925
978
|
if (cmdConfig.allowed_commands && cmdConfig.allowed_commands.length > 0) {
|
|
926
|
-
|
|
979
|
+
const effectiveAllowed = cmdConfig.claude_code ? [.../* @__PURE__ */ new Set([...cmdConfig.allowed_commands, "claude"])] : cmdConfig.allowed_commands;
|
|
980
|
+
const commandToCheck = cmdConfig.claude_code ? "claude" : baseCommand;
|
|
981
|
+
if (!effectiveAllowed.includes(commandToCheck)) {
|
|
927
982
|
return {
|
|
928
983
|
success: false,
|
|
929
|
-
error: `Command not allowed: "${
|
|
984
|
+
error: `Command not allowed: "${commandToCheck}". Allowed: ${effectiveAllowed.join(", ")}`
|
|
930
985
|
};
|
|
931
986
|
}
|
|
932
987
|
}
|
|
933
|
-
|
|
988
|
+
let interpolatedCommand;
|
|
989
|
+
if (cmdConfig.claude_code) {
|
|
990
|
+
const parts = ["claude", "--print"];
|
|
991
|
+
if (cmdConfig.claude_code.auto_mode) {
|
|
992
|
+
parts.push("--dangerously-skip-permissions");
|
|
993
|
+
}
|
|
994
|
+
if (cmdConfig.claude_code.model) {
|
|
995
|
+
parts.push("--model", cmdConfig.claude_code.model);
|
|
996
|
+
}
|
|
997
|
+
if (cmdConfig.claude_code.system_prompt) {
|
|
998
|
+
parts.push("-p", shellEscape2(cmdConfig.claude_code.system_prompt));
|
|
999
|
+
}
|
|
1000
|
+
const interpolatedPrompt = safeInterpolateCommand2(cmdConfig.command, { params });
|
|
1001
|
+
interpolatedCommand = parts.join(" ") + " " + interpolatedPrompt;
|
|
1002
|
+
} else {
|
|
1003
|
+
interpolatedCommand = safeInterpolateCommand2(cmdConfig.command, { params });
|
|
1004
|
+
}
|
|
934
1005
|
const timeout = cmdConfig.timeout_ms ?? 3e4;
|
|
935
1006
|
const cwd = cmdConfig.working_dir ?? process.cwd();
|
|
936
1007
|
let stdout;
|
|
@@ -1071,8 +1142,8 @@ var AgentRuntime = class {
|
|
|
1071
1142
|
}
|
|
1072
1143
|
const modes = /* @__PURE__ */ new Map();
|
|
1073
1144
|
if (this.conductorEnabled) {
|
|
1074
|
-
const { ConductorMode } = await import("../../conductor-mode-
|
|
1075
|
-
const { registerConductorCard, CONDUCTOR_OWNER } = await import("../../card-
|
|
1145
|
+
const { ConductorMode } = await import("../../conductor-mode-2VVFMKVE.js");
|
|
1146
|
+
const { registerConductorCard, CONDUCTOR_OWNER } = await import("../../card-REW7BSWW.js");
|
|
1076
1147
|
const { loadPeers } = await import("../../peers-CJ7T4RJO.js");
|
|
1077
1148
|
registerConductorCard(this.registryDb);
|
|
1078
1149
|
const resolveAgentUrl = (owner) => {
|
|
@@ -1178,6 +1249,7 @@ var AgentRuntime = class {
|
|
|
1178
1249
|
|
|
1179
1250
|
// src/gateway/server.ts
|
|
1180
1251
|
import Fastify from "fastify";
|
|
1252
|
+
import { randomUUID } from "crypto";
|
|
1181
1253
|
var VERSION = "0.0.1";
|
|
1182
1254
|
function createGatewayServer(opts) {
|
|
1183
1255
|
const {
|
|
@@ -1191,6 +1263,8 @@ function createGatewayServer(opts) {
|
|
|
1191
1263
|
} = opts;
|
|
1192
1264
|
const fastify = Fastify({ logger: !silent });
|
|
1193
1265
|
const tokenSet = new Set(tokens);
|
|
1266
|
+
const inFlight = /* @__PURE__ */ new Map();
|
|
1267
|
+
const OVERLOAD_RETRY_MS = 5e3;
|
|
1194
1268
|
fastify.addHook("onRequest", async (request) => {
|
|
1195
1269
|
if (request.method === "GET" && request.url === "/health") return;
|
|
1196
1270
|
const auth = request.headers.authorization;
|
|
@@ -1256,18 +1330,63 @@ function createGatewayServer(opts) {
|
|
|
1256
1330
|
}
|
|
1257
1331
|
const requester = params.requester ?? "unknown";
|
|
1258
1332
|
const receipt = params.escrow_receipt;
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1333
|
+
if (skillExecutor && skillId && typeof skillExecutor.getSkillConfig === "function") {
|
|
1334
|
+
const skillConfig = skillExecutor.getSkillConfig(skillId);
|
|
1335
|
+
const maxConcurrent = skillConfig?.capacity?.max_concurrent;
|
|
1336
|
+
if (maxConcurrent !== void 0) {
|
|
1337
|
+
const current = inFlight.get(skillId) ?? 0;
|
|
1338
|
+
if (current >= maxConcurrent) {
|
|
1339
|
+
try {
|
|
1340
|
+
insertRequestLog(registryDb, {
|
|
1341
|
+
id: randomUUID(),
|
|
1342
|
+
card_id: cardId,
|
|
1343
|
+
card_name: "<overload>",
|
|
1344
|
+
requester,
|
|
1345
|
+
status: "failure",
|
|
1346
|
+
latency_ms: 0,
|
|
1347
|
+
credits_charged: 0,
|
|
1348
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1349
|
+
skill_id: skillId,
|
|
1350
|
+
failure_reason: "overload"
|
|
1351
|
+
});
|
|
1352
|
+
} catch {
|
|
1353
|
+
}
|
|
1354
|
+
return reply.status(200).send({
|
|
1355
|
+
jsonrpc: "2.0",
|
|
1356
|
+
id,
|
|
1357
|
+
error: {
|
|
1358
|
+
code: -32e3,
|
|
1359
|
+
message: "overload",
|
|
1360
|
+
data: { error: "overload", retry_after_ms: OVERLOAD_RETRY_MS }
|
|
1361
|
+
}
|
|
1362
|
+
});
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
const trackKey = skillId ?? cardId;
|
|
1367
|
+
inFlight.set(trackKey, (inFlight.get(trackKey) ?? 0) + 1);
|
|
1368
|
+
let result;
|
|
1369
|
+
try {
|
|
1370
|
+
result = await executeCapabilityRequest({
|
|
1371
|
+
registryDb,
|
|
1372
|
+
creditDb,
|
|
1373
|
+
cardId,
|
|
1374
|
+
skillId,
|
|
1375
|
+
params,
|
|
1376
|
+
requester,
|
|
1377
|
+
escrowReceipt: receipt,
|
|
1378
|
+
skillExecutor,
|
|
1379
|
+
handlerUrl,
|
|
1380
|
+
timeoutMs
|
|
1381
|
+
});
|
|
1382
|
+
} finally {
|
|
1383
|
+
const next = (inFlight.get(trackKey) ?? 1) - 1;
|
|
1384
|
+
if (next <= 0) {
|
|
1385
|
+
inFlight.delete(trackKey);
|
|
1386
|
+
} else {
|
|
1387
|
+
inFlight.set(trackKey, next);
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1271
1390
|
if (result.success) {
|
|
1272
1391
|
return reply.send({ jsonrpc: "2.0", id, result: result.result });
|
|
1273
1392
|
} else {
|
|
@@ -1682,7 +1801,7 @@ function createLedger(opts) {
|
|
|
1682
1801
|
}
|
|
1683
1802
|
|
|
1684
1803
|
// src/cli/onboarding.ts
|
|
1685
|
-
import { randomUUID } from "crypto";
|
|
1804
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
1686
1805
|
import { createConnection } from "net";
|
|
1687
1806
|
var KNOWN_API_KEYS = [
|
|
1688
1807
|
"OPENAI_API_KEY",
|
|
@@ -1807,7 +1926,7 @@ function buildDraftCard(apiKey, owner) {
|
|
|
1807
1926
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1808
1927
|
return {
|
|
1809
1928
|
spec_version: "1.0",
|
|
1810
|
-
id:
|
|
1929
|
+
id: randomUUID2(),
|
|
1811
1930
|
owner,
|
|
1812
1931
|
name: template.name,
|
|
1813
1932
|
description: template.description,
|
|
@@ -1827,7 +1946,7 @@ function buildDraftCard(apiKey, owner) {
|
|
|
1827
1946
|
}
|
|
1828
1947
|
|
|
1829
1948
|
// src/relay/websocket-relay.ts
|
|
1830
|
-
import { randomUUID as
|
|
1949
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
1831
1950
|
|
|
1832
1951
|
// src/relay/relay-credit.ts
|
|
1833
1952
|
function lookupCardPrice(registryDb, cardId, skillId) {
|
|
@@ -1885,10 +2004,10 @@ function releaseForRelay(creditDb, escrowId) {
|
|
|
1885
2004
|
}
|
|
1886
2005
|
|
|
1887
2006
|
// src/hub-agent/relay-bridge.ts
|
|
1888
|
-
import { randomUUID as
|
|
2007
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
1889
2008
|
|
|
1890
2009
|
// src/hub-agent/job-queue.ts
|
|
1891
|
-
import { randomUUID as
|
|
2010
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
1892
2011
|
function initJobQueue(db) {
|
|
1893
2012
|
db.exec(`
|
|
1894
2013
|
CREATE TABLE IF NOT EXISTS hub_agent_jobs (
|
|
@@ -1907,7 +2026,7 @@ function initJobQueue(db) {
|
|
|
1907
2026
|
`);
|
|
1908
2027
|
}
|
|
1909
2028
|
function insertJob(db, input) {
|
|
1910
|
-
const id =
|
|
2029
|
+
const id = randomUUID3();
|
|
1911
2030
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1912
2031
|
const paramsJson = JSON.stringify(input.params);
|
|
1913
2032
|
db.prepare(`
|
|
@@ -2205,7 +2324,7 @@ function createRelayBridge(opts) {
|
|
|
2205
2324
|
updateJobStatus(registryDb, job.id, "dispatched");
|
|
2206
2325
|
const agent = getHubAgent(registryDb, job.hub_agent_id);
|
|
2207
2326
|
const cardId = agent ? agent.agent_id.padEnd(32, "0").replace(/^(.{8})(.{4})(.{4})(.{4})(.{12}).*$/, "$1-$2-$3-$4-$5") : job.hub_agent_id;
|
|
2208
|
-
const requestId =
|
|
2327
|
+
const requestId = randomUUID4();
|
|
2209
2328
|
let params = {};
|
|
2210
2329
|
try {
|
|
2211
2330
|
params = JSON.parse(job.params);
|
|
@@ -2275,6 +2394,7 @@ function registerWebSocketRelay(server, db, creditDb) {
|
|
|
2275
2394
|
const connections = /* @__PURE__ */ new Map();
|
|
2276
2395
|
const pendingRequests = /* @__PURE__ */ new Map();
|
|
2277
2396
|
const rateLimits = /* @__PURE__ */ new Map();
|
|
2397
|
+
const agentCapacities = /* @__PURE__ */ new Map();
|
|
2278
2398
|
let onAgentOnlineCallback;
|
|
2279
2399
|
function checkRateLimit(owner) {
|
|
2280
2400
|
const now = Date.now();
|
|
@@ -2351,7 +2471,7 @@ function registerWebSocketRelay(server, db, creditDb) {
|
|
|
2351
2471
|
function logAgentJoined(owner, cardName, cardId) {
|
|
2352
2472
|
try {
|
|
2353
2473
|
insertRequestLog(db, {
|
|
2354
|
-
id:
|
|
2474
|
+
id: randomUUID5(),
|
|
2355
2475
|
card_id: cardId,
|
|
2356
2476
|
card_name: cardName,
|
|
2357
2477
|
requester: owner,
|
|
@@ -2578,6 +2698,7 @@ function registerWebSocketRelay(server, db, creditDb) {
|
|
|
2578
2698
|
if (!owner) return;
|
|
2579
2699
|
connections.delete(owner);
|
|
2580
2700
|
rateLimits.delete(owner);
|
|
2701
|
+
agentCapacities.delete(owner);
|
|
2581
2702
|
markOwnerOffline(owner);
|
|
2582
2703
|
for (const [reqId, pending] of pendingRequests) {
|
|
2583
2704
|
if (pending.targetOwner === owner) {
|
|
@@ -2611,6 +2732,9 @@ function registerWebSocketRelay(server, db, creditDb) {
|
|
|
2611
2732
|
}
|
|
2612
2733
|
}
|
|
2613
2734
|
}
|
|
2735
|
+
function handleHeartbeat(msg) {
|
|
2736
|
+
agentCapacities.set(msg.owner, msg.capacity);
|
|
2737
|
+
}
|
|
2614
2738
|
void server.register(async (app) => {
|
|
2615
2739
|
app.get("/ws", { websocket: true }, (rawSocket, _request) => {
|
|
2616
2740
|
const socket = rawSocket;
|
|
@@ -2656,15 +2780,23 @@ function registerWebSocketRelay(server, db, creditDb) {
|
|
|
2656
2780
|
case "relay_progress":
|
|
2657
2781
|
handleRelayProgress(msg);
|
|
2658
2782
|
break;
|
|
2783
|
+
case "heartbeat":
|
|
2784
|
+
handleHeartbeat(msg);
|
|
2785
|
+
break;
|
|
2659
2786
|
default:
|
|
2660
2787
|
break;
|
|
2661
2788
|
}
|
|
2662
2789
|
})();
|
|
2663
2790
|
});
|
|
2791
|
+
const pingInterval = setInterval(() => {
|
|
2792
|
+
if (socket.readyState === 1) socket.ping();
|
|
2793
|
+
}, 3e4);
|
|
2664
2794
|
socket.on("close", () => {
|
|
2795
|
+
clearInterval(pingInterval);
|
|
2665
2796
|
handleDisconnect(registeredOwner);
|
|
2666
2797
|
});
|
|
2667
2798
|
socket.on("error", () => {
|
|
2799
|
+
clearInterval(pingInterval);
|
|
2668
2800
|
handleDisconnect(registeredOwner);
|
|
2669
2801
|
});
|
|
2670
2802
|
});
|
|
@@ -2685,6 +2817,7 @@ function registerWebSocketRelay(server, db, creditDb) {
|
|
|
2685
2817
|
}
|
|
2686
2818
|
pendingRequests.clear();
|
|
2687
2819
|
rateLimits.clear();
|
|
2820
|
+
agentCapacities.clear();
|
|
2688
2821
|
},
|
|
2689
2822
|
setOnAgentOnline: (cb) => {
|
|
2690
2823
|
onAgentOnlineCallback = cb;
|
|
@@ -2693,13 +2826,15 @@ function registerWebSocketRelay(server, db, creditDb) {
|
|
|
2693
2826
|
getPendingRequests: () => pendingRequests,
|
|
2694
2827
|
sendMessage: (ws, msg) => {
|
|
2695
2828
|
sendMessage(ws, msg);
|
|
2696
|
-
}
|
|
2829
|
+
},
|
|
2830
|
+
getAgentCapacity: (owner) => agentCapacities.get(owner),
|
|
2831
|
+
getAllCapacities: () => new Map(agentCapacities)
|
|
2697
2832
|
};
|
|
2698
2833
|
}
|
|
2699
2834
|
|
|
2700
2835
|
// src/identity/guarantor.ts
|
|
2701
2836
|
import { z as z3 } from "zod";
|
|
2702
|
-
import { randomUUID as
|
|
2837
|
+
import { randomUUID as randomUUID6 } from "crypto";
|
|
2703
2838
|
var MAX_AGENTS_PER_GUARANTOR = 10;
|
|
2704
2839
|
var GUARANTOR_CREDIT_POOL = 50;
|
|
2705
2840
|
var GuarantorRecordSchema = z3.object({
|
|
@@ -2738,7 +2873,7 @@ function registerGuarantor(db, githubLogin) {
|
|
|
2738
2873
|
);
|
|
2739
2874
|
}
|
|
2740
2875
|
const record = {
|
|
2741
|
-
id:
|
|
2876
|
+
id: randomUUID6(),
|
|
2742
2877
|
github_login: githubLogin,
|
|
2743
2878
|
agent_count: 0,
|
|
2744
2879
|
credit_pool: GUARANTOR_CREDIT_POOL,
|
|
@@ -2812,7 +2947,7 @@ function getAgentGuarantor(db, agentId) {
|
|
|
2812
2947
|
function initiateGithubAuth() {
|
|
2813
2948
|
return {
|
|
2814
2949
|
auth_url: "https://github.com/login/oauth/authorize?client_id=PLACEHOLDER&scope=read:user",
|
|
2815
|
-
state:
|
|
2950
|
+
state: randomUUID6()
|
|
2816
2951
|
};
|
|
2817
2952
|
}
|
|
2818
2953
|
|
|
@@ -3985,7 +4120,7 @@ function createRegistryServer(opts) {
|
|
|
3985
4120
|
openapi: "3.0.3",
|
|
3986
4121
|
info: {
|
|
3987
4122
|
title: "AgentBnB Registry API",
|
|
3988
|
-
description: "
|
|
4123
|
+
description: "Where AI agents hire AI agents \u2014 discover, publish, and coordinate agent capabilities",
|
|
3989
4124
|
version: "3.1.6"
|
|
3990
4125
|
},
|
|
3991
4126
|
servers: [{ url: "/", description: "Registry server" }],
|
|
@@ -4017,7 +4152,7 @@ function createRegistryServer(opts) {
|
|
|
4017
4152
|
});
|
|
4018
4153
|
void server.register(cors, {
|
|
4019
4154
|
origin: true,
|
|
4020
|
-
methods: ["GET", "POST", "PATCH", "OPTIONS"],
|
|
4155
|
+
methods: ["GET", "POST", "PATCH", "DELETE", "OPTIONS"],
|
|
4021
4156
|
allowedHeaders: ["Content-Type", "Authorization", "X-Agent-PublicKey", "X-Agent-Signature", "X-Agent-Timestamp"]
|
|
4022
4157
|
});
|
|
4023
4158
|
void server.register(fastifyWebsocket);
|
|
@@ -4096,6 +4231,7 @@ function createRegistryServer(opts) {
|
|
|
4096
4231
|
min_success_rate: { type: "number", description: "Minimum success rate (0-1)" },
|
|
4097
4232
|
max_latency_ms: { type: "number", description: "Maximum average latency in ms" },
|
|
4098
4233
|
min_reputation: { type: "number", description: "Minimum reputation score (0-1) based on peer feedback" },
|
|
4234
|
+
capability_type: { type: "string", description: "Filter cards whose skills declare this capability_type (e.g. tts, code_gen)" },
|
|
4099
4235
|
sort: { type: "string", enum: ["popular", "rated", "success_rate", "cheapest", "newest", "latency", "reputation_desc", "reputation_asc"], description: "Sort order" },
|
|
4100
4236
|
limit: { type: "integer", default: 20, description: "Max items per page (max 100)" },
|
|
4101
4237
|
offset: { type: "integer", default: 0, description: "Pagination offset" }
|
|
@@ -4122,6 +4258,7 @@ function createRegistryServer(opts) {
|
|
|
4122
4258
|
const onlineRaw = query.online;
|
|
4123
4259
|
const online = onlineRaw === "true" ? true : onlineRaw === "false" ? false : void 0;
|
|
4124
4260
|
const tag = query.tag?.trim();
|
|
4261
|
+
const capabilityType = query.capability_type?.trim() || void 0;
|
|
4125
4262
|
const minSuccessRate = query.min_success_rate !== void 0 ? parseFloat(query.min_success_rate) : void 0;
|
|
4126
4263
|
const maxLatencyMs = query.max_latency_ms !== void 0 ? parseFloat(query.max_latency_ms) : void 0;
|
|
4127
4264
|
const minReputation = query.min_reputation !== void 0 ? parseFloat(query.min_reputation) : void 0;
|
|
@@ -4137,6 +4274,12 @@ function createRegistryServer(opts) {
|
|
|
4137
4274
|
cards = filterCards(db, { level, online, min_reputation: minReputation });
|
|
4138
4275
|
}
|
|
4139
4276
|
cards = cards.filter((c) => !c.owner.includes(":req:"));
|
|
4277
|
+
if (capabilityType !== void 0) {
|
|
4278
|
+
const capTypeIds = new Set(
|
|
4279
|
+
getCardsBySkillCapability(db, capabilityType).map((c) => c.id)
|
|
4280
|
+
);
|
|
4281
|
+
cards = cards.filter((c) => capTypeIds.has(c.id));
|
|
4282
|
+
}
|
|
4140
4283
|
if (tag !== void 0 && tag.length > 0) {
|
|
4141
4284
|
cards = cards.filter((c) => {
|
|
4142
4285
|
const rootTags = c.metadata?.tags ?? [];
|
|
@@ -4172,7 +4315,9 @@ function createRegistryServer(opts) {
|
|
|
4172
4315
|
const trustStmt = db.prepare(`
|
|
4173
4316
|
SELECT cc.owner,
|
|
4174
4317
|
COUNT(rl.id) as total_exec,
|
|
4175
|
-
SUM(CASE WHEN rl.status IN ('success','failure','timeout','refunded')
|
|
4318
|
+
SUM(CASE WHEN rl.status IN ('success','failure','timeout','refunded')
|
|
4319
|
+
AND (rl.failure_reason IS NULL OR rl.failure_reason IN ('bad_execution','auth_error'))
|
|
4320
|
+
THEN 1 ELSE 0 END) as terminal_exec,
|
|
4176
4321
|
SUM(CASE WHEN rl.status = 'success' THEN 1 ELSE 0 END) as success_exec,
|
|
4177
4322
|
AVG(CASE WHEN rl.status = 'success' THEN rl.latency_ms END) as avg_latency
|
|
4178
4323
|
FROM capability_cards cc
|
|
@@ -4406,21 +4551,32 @@ function createRegistryServer(opts) {
|
|
|
4406
4551
|
api.delete("/cards/:id", {
|
|
4407
4552
|
schema: {
|
|
4408
4553
|
tags: ["cards"],
|
|
4409
|
-
summary: "Delete a capability card",
|
|
4554
|
+
summary: "Delete a capability card (requires Bearer auth)",
|
|
4555
|
+
security: [{ bearerAuth: [] }],
|
|
4410
4556
|
params: { type: "object", properties: { id: { type: "string" } }, required: ["id"] },
|
|
4411
4557
|
response: {
|
|
4412
|
-
|
|
4558
|
+
204: { type: "null", description: "Card deleted successfully" },
|
|
4559
|
+
401: { type: "object", properties: { error: { type: "string" } } },
|
|
4560
|
+
403: { type: "object", properties: { error: { type: "string" } } },
|
|
4413
4561
|
404: { type: "object", properties: { error: { type: "string" } } }
|
|
4414
4562
|
}
|
|
4415
4563
|
}
|
|
4416
4564
|
}, async (request, reply) => {
|
|
4565
|
+
const auth = request.headers.authorization;
|
|
4566
|
+
const token = auth?.startsWith("Bearer ") ? auth.slice(7).trim() : null;
|
|
4567
|
+
if (!token || !opts.ownerApiKey || token !== opts.ownerApiKey) {
|
|
4568
|
+
return reply.code(401).send({ error: "Unauthorized" });
|
|
4569
|
+
}
|
|
4417
4570
|
const { id } = request.params;
|
|
4418
4571
|
const card = getCard(db, id);
|
|
4419
4572
|
if (!card) {
|
|
4420
4573
|
return reply.code(404).send({ error: "Not found" });
|
|
4421
4574
|
}
|
|
4575
|
+
if (opts.ownerName && card.owner !== opts.ownerName) {
|
|
4576
|
+
return reply.code(403).send({ error: "Forbidden" });
|
|
4577
|
+
}
|
|
4422
4578
|
db.prepare("DELETE FROM capability_cards WHERE id = ?").run(id);
|
|
4423
|
-
return reply.send(
|
|
4579
|
+
return reply.code(204).send();
|
|
4424
4580
|
});
|
|
4425
4581
|
api.get("/api/agents", {
|
|
4426
4582
|
schema: {
|
|
@@ -4505,7 +4661,8 @@ function createRegistryServer(opts) {
|
|
|
4505
4661
|
const lastActive = lastActiveRow?.last_req ?? memberRow?.latest ?? joinedAt;
|
|
4506
4662
|
const metricsStmt = db.prepare(`
|
|
4507
4663
|
SELECT
|
|
4508
|
-
|
|
4664
|
+
SUM(CASE WHEN rl.failure_reason IS NULL OR rl.failure_reason IN ('bad_execution','auth_error')
|
|
4665
|
+
THEN 1 ELSE 0 END) as total,
|
|
4509
4666
|
SUM(CASE WHEN rl.status = 'success' THEN 1 ELSE 0 END) as successes,
|
|
4510
4667
|
AVG(CASE WHEN rl.status = 'success' THEN rl.latency_ms END) as avg_latency,
|
|
4511
4668
|
COUNT(DISTINCT rl.requester) as unique_requesters,
|
|
@@ -5098,6 +5255,110 @@ function createRegistryServer(opts) {
|
|
|
5098
5255
|
});
|
|
5099
5256
|
});
|
|
5100
5257
|
}
|
|
5258
|
+
api.get("/api/providers/:owner/reliability", {
|
|
5259
|
+
schema: {
|
|
5260
|
+
tags: ["agents"],
|
|
5261
|
+
summary: "Get provider reliability metrics",
|
|
5262
|
+
params: { type: "object", properties: { owner: { type: "string" } }, required: ["owner"] },
|
|
5263
|
+
response: {
|
|
5264
|
+
200: {
|
|
5265
|
+
type: "object",
|
|
5266
|
+
properties: {
|
|
5267
|
+
current_streak: { type: "integer" },
|
|
5268
|
+
longest_streak: { type: "integer" },
|
|
5269
|
+
total_hires: { type: "integer" },
|
|
5270
|
+
repeat_hires: { type: "integer" },
|
|
5271
|
+
repeat_hire_rate: { type: "number" },
|
|
5272
|
+
avg_feedback_score: { type: "number" },
|
|
5273
|
+
availability_rate: { type: "number" }
|
|
5274
|
+
}
|
|
5275
|
+
},
|
|
5276
|
+
404: { type: "object", properties: { error: { type: "string" } } }
|
|
5277
|
+
}
|
|
5278
|
+
}
|
|
5279
|
+
}, async (request, reply) => {
|
|
5280
|
+
const { owner } = request.params;
|
|
5281
|
+
if (!opts.creditDb) {
|
|
5282
|
+
return reply.code(404).send({ error: "Credit system not enabled" });
|
|
5283
|
+
}
|
|
5284
|
+
const { getReliabilityMetrics } = await import("../../reliability-metrics-QG7WC5QK.js");
|
|
5285
|
+
const metrics = getReliabilityMetrics(opts.creditDb, owner);
|
|
5286
|
+
if (!metrics) {
|
|
5287
|
+
return reply.code(404).send({ error: "No reliability data for this provider" });
|
|
5288
|
+
}
|
|
5289
|
+
return reply.send(metrics);
|
|
5290
|
+
});
|
|
5291
|
+
api.get("/api/fleet/:owner", {
|
|
5292
|
+
schema: {
|
|
5293
|
+
tags: ["agents"],
|
|
5294
|
+
summary: "Agent fleet overview for an owner",
|
|
5295
|
+
params: { type: "object", properties: { owner: { type: "string" } }, required: ["owner"] },
|
|
5296
|
+
response: {
|
|
5297
|
+
200: { type: "object", properties: { agents: { type: "array" } } }
|
|
5298
|
+
}
|
|
5299
|
+
}
|
|
5300
|
+
}, async (request, reply) => {
|
|
5301
|
+
const { owner } = request.params;
|
|
5302
|
+
const rows = db.prepare(
|
|
5303
|
+
"SELECT id, data FROM capability_cards WHERE owner = ?"
|
|
5304
|
+
).all(owner);
|
|
5305
|
+
const agents = [];
|
|
5306
|
+
for (const row of rows) {
|
|
5307
|
+
try {
|
|
5308
|
+
const card = JSON.parse(row.data);
|
|
5309
|
+
let earnings = 0;
|
|
5310
|
+
let spend = 0;
|
|
5311
|
+
if (opts.creditDb) {
|
|
5312
|
+
const earningRow = opts.creditDb.prepare(
|
|
5313
|
+
"SELECT COALESCE(SUM(amount), 0) as total FROM credit_transactions WHERE owner = ? AND reason = 'settlement' AND amount > 0"
|
|
5314
|
+
).get(owner);
|
|
5315
|
+
earnings = earningRow.total;
|
|
5316
|
+
const spendRow = opts.creditDb.prepare(
|
|
5317
|
+
"SELECT COALESCE(SUM(ABS(amount)), 0) as total FROM credit_transactions WHERE owner = ? AND reason = 'escrow_hold'"
|
|
5318
|
+
).get(owner);
|
|
5319
|
+
spend = spendRow.total;
|
|
5320
|
+
}
|
|
5321
|
+
const successCount = db.prepare(
|
|
5322
|
+
"SELECT COUNT(*) as cnt FROM request_log WHERE card_id = ? AND status = 'success' AND (action_type IS NULL OR action_type = 'auto_share')"
|
|
5323
|
+
).get(row.id).cnt;
|
|
5324
|
+
const failureCount = db.prepare(
|
|
5325
|
+
"SELECT COUNT(*) as cnt FROM request_log WHERE card_id = ? AND status IN ('failure', 'timeout', 'refunded') AND (action_type IS NULL OR action_type = 'auto_share')"
|
|
5326
|
+
).get(row.id).cnt;
|
|
5327
|
+
const totalExec = successCount + failureCount;
|
|
5328
|
+
const successRate = totalExec > 0 ? successCount / totalExec : 0;
|
|
5329
|
+
let failureBreakdown = {};
|
|
5330
|
+
try {
|
|
5331
|
+
const failureRows = db.prepare(
|
|
5332
|
+
"SELECT failure_reason, COUNT(*) as cnt FROM request_log WHERE card_id = ? AND status IN ('failure', 'timeout', 'refunded') AND failure_reason IS NOT NULL GROUP BY failure_reason"
|
|
5333
|
+
).all(row.id);
|
|
5334
|
+
for (const fr of failureRows) {
|
|
5335
|
+
failureBreakdown[fr.failure_reason] = fr.cnt;
|
|
5336
|
+
}
|
|
5337
|
+
} catch {
|
|
5338
|
+
}
|
|
5339
|
+
let reliability = null;
|
|
5340
|
+
if (opts.creditDb) {
|
|
5341
|
+
const { getReliabilityMetrics } = await import("../../reliability-metrics-QG7WC5QK.js");
|
|
5342
|
+
reliability = getReliabilityMetrics(opts.creditDb, owner);
|
|
5343
|
+
}
|
|
5344
|
+
agents.push({
|
|
5345
|
+
id: row.id,
|
|
5346
|
+
name: card.name ?? card.agent_name ?? owner,
|
|
5347
|
+
online: card.availability?.online ?? false,
|
|
5348
|
+
current_load: 0,
|
|
5349
|
+
// Will be populated from relay heartbeat data in future
|
|
5350
|
+
success_rate: successRate,
|
|
5351
|
+
total_executions: totalExec,
|
|
5352
|
+
earnings,
|
|
5353
|
+
spend,
|
|
5354
|
+
failure_breakdown: failureBreakdown,
|
|
5355
|
+
reliability
|
|
5356
|
+
});
|
|
5357
|
+
} catch {
|
|
5358
|
+
}
|
|
5359
|
+
}
|
|
5360
|
+
return reply.send({ agents });
|
|
5361
|
+
});
|
|
5101
5362
|
});
|
|
5102
5363
|
return { server, relayState };
|
|
5103
5364
|
}
|
|
@@ -5238,7 +5499,7 @@ import { createRequire } from "module";
|
|
|
5238
5499
|
import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
|
|
5239
5500
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
5240
5501
|
import { dirname as dirname3, join as join4, resolve } from "path";
|
|
5241
|
-
import { randomUUID as
|
|
5502
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
5242
5503
|
var ServiceCoordinator = class {
|
|
5243
5504
|
config;
|
|
5244
5505
|
guard;
|
|
@@ -5379,7 +5640,7 @@ var ServiceCoordinator = class {
|
|
|
5379
5640
|
console.log("Conductor mode enabled \u2014 orchestrate/plan skills available via gateway");
|
|
5380
5641
|
}
|
|
5381
5642
|
if (opts.conductorEnabled && this.config.conductor?.public) {
|
|
5382
|
-
const { buildConductorCard } = await import("../../card-
|
|
5643
|
+
const { buildConductorCard } = await import("../../card-REW7BSWW.js");
|
|
5383
5644
|
const conductorCard = buildConductorCard(this.config.owner);
|
|
5384
5645
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
5385
5646
|
const existing = this.runtime.registryDb.prepare("SELECT id FROM capability_cards WHERE id = ?").get(conductorCard.id);
|
|
@@ -5436,11 +5697,11 @@ var ServiceCoordinator = class {
|
|
|
5436
5697
|
}
|
|
5437
5698
|
}
|
|
5438
5699
|
if (opts.registryUrl && opts.relay) {
|
|
5439
|
-
const { RelayClient: RelayClient2 } = await import("../../websocket-client-
|
|
5440
|
-
const { executeCapabilityRequest: executeCapabilityRequest2 } = await import("../../execute-
|
|
5700
|
+
const { RelayClient: RelayClient2 } = await import("../../websocket-client-PFGVTXNE.js");
|
|
5701
|
+
const { executeCapabilityRequest: executeCapabilityRequest2 } = await import("../../execute-I4PKSNJM.js");
|
|
5441
5702
|
const cards = listCards(this.runtime.registryDb, this.config.owner);
|
|
5442
5703
|
const card = cards[0] ?? {
|
|
5443
|
-
id:
|
|
5704
|
+
id: randomUUID7(),
|
|
5444
5705
|
owner: this.config.owner,
|
|
5445
5706
|
name: this.config.owner,
|
|
5446
5707
|
description: "Agent registered via CLI",
|
|
@@ -5453,7 +5714,7 @@ var ServiceCoordinator = class {
|
|
|
5453
5714
|
};
|
|
5454
5715
|
const additionalCards = [];
|
|
5455
5716
|
if (this.config.conductor?.public) {
|
|
5456
|
-
const { buildConductorCard } = await import("../../card-
|
|
5717
|
+
const { buildConductorCard } = await import("../../card-REW7BSWW.js");
|
|
5457
5718
|
additionalCards.push(
|
|
5458
5719
|
buildConductorCard(this.config.owner)
|
|
5459
5720
|
);
|
|
@@ -5703,7 +5964,6 @@ var ServiceCoordinator = class {
|
|
|
5703
5964
|
})();
|
|
5704
5965
|
};
|
|
5705
5966
|
};
|
|
5706
|
-
var require2 = createRequire(import.meta.url);
|
|
5707
5967
|
function loadPersistedRuntime(configDir) {
|
|
5708
5968
|
const runtimePath = join4(configDir, "runtime.json");
|
|
5709
5969
|
if (!existsSync5(runtimePath)) return null;
|
|
@@ -5731,6 +5991,12 @@ function resolveNodeExecutable(runtime) {
|
|
|
5731
5991
|
return process.execPath;
|
|
5732
5992
|
}
|
|
5733
5993
|
function resolveCliLaunchArgs(serveArgs) {
|
|
5994
|
+
const require2 = createRequire(import.meta.url);
|
|
5995
|
+
try {
|
|
5996
|
+
const distCli2 = require2.resolve("agentbnb/dist/cli/index.js");
|
|
5997
|
+
return [distCli2, "serve", ...serveArgs];
|
|
5998
|
+
} catch {
|
|
5999
|
+
}
|
|
5734
6000
|
const projectRoot = resolve(dirname3(fileURLToPath2(import.meta.url)), "..", "..");
|
|
5735
6001
|
const distCli = join4(projectRoot, "dist", "cli", "index.js");
|
|
5736
6002
|
if (existsSync5(distCli)) {
|
|
@@ -5761,11 +6027,11 @@ function sleep2(ms) {
|
|
|
5761
6027
|
}
|
|
5762
6028
|
|
|
5763
6029
|
// src/app/agentbnb-service.ts
|
|
5764
|
-
import { randomUUID as
|
|
6030
|
+
import { randomUUID as randomUUID9 } from "crypto";
|
|
5765
6031
|
|
|
5766
6032
|
// src/credit/escrow-receipt.ts
|
|
5767
6033
|
import { z as z8 } from "zod";
|
|
5768
|
-
import { randomUUID as
|
|
6034
|
+
import { randomUUID as randomUUID8 } from "crypto";
|
|
5769
6035
|
var EscrowReceiptSchema = z8.object({
|
|
5770
6036
|
requester_owner: z8.string().min(1),
|
|
5771
6037
|
requester_public_key: z8.string().min(1),
|
|
@@ -5785,7 +6051,7 @@ function createSignedEscrowReceipt(db, privateKey, publicKey, opts) {
|
|
|
5785
6051
|
card_id: opts.cardId,
|
|
5786
6052
|
...opts.skillId ? { skill_id: opts.skillId } : {},
|
|
5787
6053
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5788
|
-
nonce:
|
|
6054
|
+
nonce: randomUUID8()
|
|
5789
6055
|
};
|
|
5790
6056
|
const signature = signEscrowReceipt(receiptData, privateKey);
|
|
5791
6057
|
const receipt = {
|
|
@@ -6027,13 +6293,13 @@ var AgentBnBService = class {
|
|
|
6027
6293
|
if (!this.config.registry) {
|
|
6028
6294
|
throw new AgentBnBError("Registry is required for relay fallback.", "RELAY_NOT_AVAILABLE");
|
|
6029
6295
|
}
|
|
6030
|
-
const requesterId = `${this.config.owner}:req:${
|
|
6296
|
+
const requesterId = `${this.config.owner}:req:${randomUUID9()}`;
|
|
6031
6297
|
const tempRelay = new RelayClient({
|
|
6032
6298
|
registryUrl: this.config.registry,
|
|
6033
6299
|
owner: requesterId,
|
|
6034
6300
|
token: this.config.token,
|
|
6035
6301
|
card: {
|
|
6036
|
-
id:
|
|
6302
|
+
id: randomUUID9(),
|
|
6037
6303
|
owner: requesterId,
|
|
6038
6304
|
name: requesterId,
|
|
6039
6305
|
description: "Requester",
|
|
@@ -6142,15 +6408,94 @@ function isNetworkError(err) {
|
|
|
6142
6408
|
}
|
|
6143
6409
|
|
|
6144
6410
|
// skills/agentbnb/bootstrap.ts
|
|
6411
|
+
function findSoulMd(startDir) {
|
|
6412
|
+
let dir = startDir;
|
|
6413
|
+
while (true) {
|
|
6414
|
+
const candidate = join5(dir, "SOUL.md");
|
|
6415
|
+
if (existsSync6(candidate)) return candidate;
|
|
6416
|
+
const parent = dirname4(dir);
|
|
6417
|
+
if (parent === dir) return null;
|
|
6418
|
+
dir = parent;
|
|
6419
|
+
}
|
|
6420
|
+
}
|
|
6421
|
+
function resolveWorkspaceDir() {
|
|
6422
|
+
const soulPath = findSoulMd(process.cwd());
|
|
6423
|
+
if (soulPath) {
|
|
6424
|
+
const workspaceName = basename(dirname4(soulPath));
|
|
6425
|
+
return join5(homedir2(), ".agentbnb", workspaceName);
|
|
6426
|
+
}
|
|
6427
|
+
return join5(homedir2(), ".agentbnb");
|
|
6428
|
+
}
|
|
6429
|
+
function registerDecomposerCard(configDir, owner) {
|
|
6430
|
+
try {
|
|
6431
|
+
const db = openDatabase(join5(configDir, "registry.db"));
|
|
6432
|
+
const existing = db.prepare(
|
|
6433
|
+
"SELECT id FROM capability_cards WHERE owner = ? AND json_extract(data, '$.capability_type') = ?"
|
|
6434
|
+
).get(owner, "task_decomposition");
|
|
6435
|
+
if (existing) return;
|
|
6436
|
+
const cardId = randomUUID10();
|
|
6437
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
6438
|
+
const card = {
|
|
6439
|
+
spec_version: "2.0",
|
|
6440
|
+
id: cardId,
|
|
6441
|
+
owner,
|
|
6442
|
+
agent_name: `${owner}-decomposer`,
|
|
6443
|
+
capability_type: "task_decomposition",
|
|
6444
|
+
skills: [
|
|
6445
|
+
{
|
|
6446
|
+
id: "task-decomposition",
|
|
6447
|
+
name: "Task Decomposition",
|
|
6448
|
+
description: "Decomposes natural-language tasks into executable sub-task DAGs using the AgentBnB Rule Engine.",
|
|
6449
|
+
level: 1,
|
|
6450
|
+
category: "task_decomposition",
|
|
6451
|
+
inputs: [
|
|
6452
|
+
{
|
|
6453
|
+
name: "task",
|
|
6454
|
+
type: "text",
|
|
6455
|
+
description: "Natural language task description",
|
|
6456
|
+
required: true
|
|
6457
|
+
}
|
|
6458
|
+
],
|
|
6459
|
+
outputs: [
|
|
6460
|
+
{
|
|
6461
|
+
name: "subtasks",
|
|
6462
|
+
type: "json",
|
|
6463
|
+
description: "Array of SubTask objects with id, role, description, dependencies",
|
|
6464
|
+
required: true
|
|
6465
|
+
}
|
|
6466
|
+
],
|
|
6467
|
+
pricing: { credits_per_call: 1 }
|
|
6468
|
+
}
|
|
6469
|
+
],
|
|
6470
|
+
availability: { online: true },
|
|
6471
|
+
created_at: now,
|
|
6472
|
+
updated_at: now
|
|
6473
|
+
};
|
|
6474
|
+
db.prepare(
|
|
6475
|
+
"INSERT INTO capability_cards (id, owner, data, created_at, updated_at) VALUES (?, ?, ?, ?, ?)"
|
|
6476
|
+
).run(cardId, owner, JSON.stringify(card), now, now);
|
|
6477
|
+
process.stderr.write(
|
|
6478
|
+
`[agentbnb] registered task_decomposition card: ${cardId} (owner=${owner})
|
|
6479
|
+
`
|
|
6480
|
+
);
|
|
6481
|
+
} catch (err) {
|
|
6482
|
+
process.stderr.write(
|
|
6483
|
+
`[agentbnb] WARNING: failed to register task_decomposition card: ${String(err)}
|
|
6484
|
+
`
|
|
6485
|
+
);
|
|
6486
|
+
}
|
|
6487
|
+
}
|
|
6145
6488
|
async function activate(config = {}) {
|
|
6146
|
-
const configDir = getConfigDir();
|
|
6147
6489
|
if (!process.env["AGENTBNB_DIR"]) {
|
|
6148
|
-
|
|
6490
|
+
const workspaceDir = resolveWorkspaceDir();
|
|
6491
|
+
process.env["AGENTBNB_DIR"] = workspaceDir;
|
|
6149
6492
|
process.stderr.write(
|
|
6150
|
-
`[agentbnb] AGENTBNB_DIR
|
|
6493
|
+
`[agentbnb] AGENTBNB_DIR auto-configured to ${workspaceDir} for workspace isolation.
|
|
6151
6494
|
`
|
|
6152
6495
|
);
|
|
6153
|
-
}
|
|
6496
|
+
}
|
|
6497
|
+
const configDir = getConfigDir();
|
|
6498
|
+
if (process.env["AGENTBNB_DIR"] !== configDir) {
|
|
6154
6499
|
process.stderr.write(
|
|
6155
6500
|
`[agentbnb] WARNING: AGENTBNB_DIR (${process.env["AGENTBNB_DIR"]}) differs from resolved configDir (${configDir}).
|
|
6156
6501
|
`
|
|
@@ -6185,6 +6530,7 @@ async function activate(config = {}) {
|
|
|
6185
6530
|
relay: config.relay
|
|
6186
6531
|
};
|
|
6187
6532
|
const startDisposition = await service.ensureRunning(opts);
|
|
6533
|
+
registerDecomposerCard(configDir, agentConfig.owner);
|
|
6188
6534
|
const status = await service.getNodeStatus();
|
|
6189
6535
|
const onSigterm = () => {
|
|
6190
6536
|
if (startDisposition === "started") {
|