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
|
@@ -1,6 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
executeCapabilityBatch,
|
|
3
|
+
executeCapabilityRequest
|
|
4
|
+
} from "./chunk-PGDBUUGR.js";
|
|
1
5
|
import {
|
|
2
6
|
StructuredFeedbackSchema
|
|
3
7
|
} from "./chunk-AUBHR7HH.js";
|
|
8
|
+
import {
|
|
9
|
+
RelayMessageSchema
|
|
10
|
+
} from "./chunk-EHSHB7TY.js";
|
|
4
11
|
import {
|
|
5
12
|
KNOWN_API_KEYS,
|
|
6
13
|
announceGateway,
|
|
@@ -8,17 +15,19 @@ import {
|
|
|
8
15
|
detectApiKeys,
|
|
9
16
|
getPricingStats,
|
|
10
17
|
stopAnnouncement
|
|
11
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-FK2MDNTB.js";
|
|
12
19
|
import {
|
|
13
20
|
deriveAgentId
|
|
14
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-PSQHUZ7X.js";
|
|
22
|
+
import "./chunk-DUW6RX6I.js";
|
|
15
23
|
import {
|
|
16
24
|
createLedger,
|
|
17
25
|
identityAuthPlugin
|
|
18
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-2HSUPCBT.js";
|
|
19
27
|
import {
|
|
20
|
-
|
|
21
|
-
|
|
28
|
+
ApiSkillConfigSchema,
|
|
29
|
+
parseSkillsFile
|
|
30
|
+
} from "./chunk-OCSU2S6W.js";
|
|
22
31
|
import {
|
|
23
32
|
interpolateObject
|
|
24
33
|
} from "./chunk-3MJT4PZG.js";
|
|
@@ -28,58 +37,55 @@ import {
|
|
|
28
37
|
insertAuditEvent,
|
|
29
38
|
listPendingRequests,
|
|
30
39
|
resolvePendingRequest
|
|
31
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-Y7T6IMM3.js";
|
|
32
41
|
import {
|
|
33
42
|
buildReputationMap,
|
|
34
43
|
computeReputation,
|
|
35
44
|
filterCards,
|
|
36
45
|
searchCards
|
|
37
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-574W3HHE.js";
|
|
47
|
+
import {
|
|
48
|
+
bootstrapAgent,
|
|
49
|
+
getBalance,
|
|
50
|
+
getTransactions,
|
|
51
|
+
holdEscrow,
|
|
52
|
+
migrateOwner,
|
|
53
|
+
openCreditDb,
|
|
54
|
+
releaseEscrow,
|
|
55
|
+
settleEscrow
|
|
56
|
+
} from "./chunk-J2K5S5MX.js";
|
|
57
|
+
import "./chunk-NWIQJ2CL.js";
|
|
58
|
+
import {
|
|
59
|
+
generateKeyPair,
|
|
60
|
+
verifyEscrowReceipt
|
|
61
|
+
} from "./chunk-F53QQIM2.js";
|
|
38
62
|
import {
|
|
39
63
|
getConfigDir
|
|
40
64
|
} from "./chunk-75OC6E4F.js";
|
|
41
|
-
import {
|
|
42
|
-
executeCapabilityBatch,
|
|
43
|
-
executeCapabilityRequest
|
|
44
|
-
} from "./chunk-QQFBFV4V.js";
|
|
45
|
-
import "./chunk-UKT6H7YT.js";
|
|
46
65
|
import {
|
|
47
66
|
getActivityFeed,
|
|
48
67
|
getCard,
|
|
68
|
+
getCardsBySkillCapability,
|
|
49
69
|
getEvolutionHistory,
|
|
70
|
+
getFeedbackForProvider,
|
|
71
|
+
getFeedbackForSkill,
|
|
50
72
|
getLatestEvolution,
|
|
51
73
|
getRequestLog,
|
|
52
74
|
getSkillRequestCount,
|
|
53
75
|
insertCard,
|
|
54
76
|
insertEvolution,
|
|
77
|
+
insertFeedback,
|
|
55
78
|
insertRequestLog,
|
|
56
79
|
listCards,
|
|
57
80
|
openDatabase,
|
|
58
81
|
updateCard,
|
|
59
82
|
updateSkillAvailability,
|
|
60
83
|
updateSkillIdleRate
|
|
61
|
-
} from "./chunk-
|
|
62
|
-
import {
|
|
63
|
-
bootstrapAgent,
|
|
64
|
-
getBalance,
|
|
65
|
-
getFeedbackForProvider,
|
|
66
|
-
getFeedbackForSkill,
|
|
67
|
-
getTransactions,
|
|
68
|
-
holdEscrow,
|
|
69
|
-
insertFeedback,
|
|
70
|
-
migrateOwner,
|
|
71
|
-
openCreditDb,
|
|
72
|
-
releaseEscrow,
|
|
73
|
-
settleEscrow
|
|
74
|
-
} from "./chunk-EANI2N2V.js";
|
|
75
|
-
import {
|
|
76
|
-
generateKeyPair,
|
|
77
|
-
verifyEscrowReceipt
|
|
78
|
-
} from "./chunk-5KFI5X7B.js";
|
|
84
|
+
} from "./chunk-KA2VIEGM.js";
|
|
79
85
|
import {
|
|
80
86
|
AgentBnBError,
|
|
81
87
|
AnyCardSchema
|
|
82
|
-
} from "./chunk-
|
|
88
|
+
} from "./chunk-3CIMVISQ.js";
|
|
83
89
|
|
|
84
90
|
// src/runtime/agent-runtime.ts
|
|
85
91
|
import { readFileSync, existsSync } from "fs";
|
|
@@ -88,13 +94,16 @@ import { readFileSync, existsSync } from "fs";
|
|
|
88
94
|
var SkillExecutor = class {
|
|
89
95
|
skillMap;
|
|
90
96
|
modeMap;
|
|
97
|
+
concurrencyGuard;
|
|
91
98
|
/**
|
|
92
99
|
* @param configs - Parsed SkillConfig array (from parseSkillsFile).
|
|
93
100
|
* @param modes - Map from skill type string to its executor implementation.
|
|
101
|
+
* @param concurrencyGuard - Optional ConcurrencyGuard to enforce max_concurrent limits.
|
|
94
102
|
*/
|
|
95
|
-
constructor(configs, modes) {
|
|
103
|
+
constructor(configs, modes, concurrencyGuard) {
|
|
96
104
|
this.skillMap = new Map(configs.map((c) => [c.id, c]));
|
|
97
105
|
this.modeMap = modes;
|
|
106
|
+
this.concurrencyGuard = concurrencyGuard;
|
|
98
107
|
}
|
|
99
108
|
/**
|
|
100
109
|
* Execute a skill by ID with the given input parameters.
|
|
@@ -127,6 +136,18 @@ var SkillExecutor = class {
|
|
|
127
136
|
latency_ms: Date.now() - startTime
|
|
128
137
|
};
|
|
129
138
|
}
|
|
139
|
+
const maxConcurrent = config.capacity?.max_concurrent ?? Infinity;
|
|
140
|
+
if (this.concurrencyGuard && maxConcurrent !== Infinity) {
|
|
141
|
+
if (!this.concurrencyGuard.canAccept(skillId, maxConcurrent)) {
|
|
142
|
+
return {
|
|
143
|
+
success: false,
|
|
144
|
+
error: `Skill ${skillId} at capacity (${maxConcurrent} concurrent max)`,
|
|
145
|
+
latency_ms: Date.now() - startTime,
|
|
146
|
+
failure_reason: "overload"
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
this.concurrencyGuard.acquire(skillId);
|
|
150
|
+
}
|
|
130
151
|
try {
|
|
131
152
|
const modeResult = await mode.execute(config, params, onProgress);
|
|
132
153
|
return {
|
|
@@ -140,6 +161,10 @@ var SkillExecutor = class {
|
|
|
140
161
|
error: message,
|
|
141
162
|
latency_ms: Date.now() - startTime
|
|
142
163
|
};
|
|
164
|
+
} finally {
|
|
165
|
+
if (this.concurrencyGuard && maxConcurrent !== Infinity) {
|
|
166
|
+
this.concurrencyGuard.release(skillId);
|
|
167
|
+
}
|
|
143
168
|
}
|
|
144
169
|
}
|
|
145
170
|
/**
|
|
@@ -160,137 +185,8 @@ var SkillExecutor = class {
|
|
|
160
185
|
return this.skillMap.get(skillId);
|
|
161
186
|
}
|
|
162
187
|
};
|
|
163
|
-
function createSkillExecutor(configs, modes) {
|
|
164
|
-
return new SkillExecutor(configs, modes);
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// src/skills/skill-config.ts
|
|
168
|
-
import { z } from "zod";
|
|
169
|
-
import yaml from "js-yaml";
|
|
170
|
-
var PricingSchema = z.object({
|
|
171
|
-
credits_per_call: z.number().nonnegative(),
|
|
172
|
-
credits_per_minute: z.number().nonnegative().optional(),
|
|
173
|
-
free_tier: z.number().nonnegative().optional()
|
|
174
|
-
});
|
|
175
|
-
var ApiAuthSchema = z.discriminatedUnion("type", [
|
|
176
|
-
z.object({
|
|
177
|
-
type: z.literal("bearer"),
|
|
178
|
-
token: z.string()
|
|
179
|
-
}),
|
|
180
|
-
z.object({
|
|
181
|
-
type: z.literal("apikey"),
|
|
182
|
-
header: z.string().default("X-API-Key"),
|
|
183
|
-
key: z.string()
|
|
184
|
-
}),
|
|
185
|
-
z.object({
|
|
186
|
-
type: z.literal("basic"),
|
|
187
|
-
username: z.string(),
|
|
188
|
-
password: z.string()
|
|
189
|
-
})
|
|
190
|
-
]);
|
|
191
|
-
var ApiSkillConfigSchema = z.object({
|
|
192
|
-
id: z.string().min(1),
|
|
193
|
-
type: z.literal("api"),
|
|
194
|
-
name: z.string().min(1),
|
|
195
|
-
endpoint: z.string().min(1),
|
|
196
|
-
method: z.enum(["GET", "POST", "PUT", "DELETE"]),
|
|
197
|
-
auth: ApiAuthSchema.optional(),
|
|
198
|
-
input_mapping: z.record(z.string()).default({}),
|
|
199
|
-
output_mapping: z.record(z.string()).default({}),
|
|
200
|
-
pricing: PricingSchema,
|
|
201
|
-
timeout_ms: z.number().positive().default(3e4),
|
|
202
|
-
retries: z.number().nonnegative().int().default(0),
|
|
203
|
-
provider: z.string().optional()
|
|
204
|
-
});
|
|
205
|
-
var PipelineStepSchema = z.union([
|
|
206
|
-
z.object({
|
|
207
|
-
skill_id: z.string().min(1),
|
|
208
|
-
input_mapping: z.record(z.string()).default({})
|
|
209
|
-
}),
|
|
210
|
-
z.object({
|
|
211
|
-
command: z.string().min(1),
|
|
212
|
-
input_mapping: z.record(z.string()).default({})
|
|
213
|
-
})
|
|
214
|
-
]);
|
|
215
|
-
var PipelineSkillConfigSchema = z.object({
|
|
216
|
-
id: z.string().min(1),
|
|
217
|
-
type: z.literal("pipeline"),
|
|
218
|
-
name: z.string().min(1),
|
|
219
|
-
steps: z.array(PipelineStepSchema).min(1),
|
|
220
|
-
pricing: PricingSchema,
|
|
221
|
-
timeout_ms: z.number().positive().optional()
|
|
222
|
-
});
|
|
223
|
-
var OpenClawSkillConfigSchema = z.object({
|
|
224
|
-
id: z.string().min(1),
|
|
225
|
-
type: z.literal("openclaw"),
|
|
226
|
-
name: z.string().min(1),
|
|
227
|
-
agent_name: z.string().min(1),
|
|
228
|
-
channel: z.enum(["telegram", "webhook", "process"]),
|
|
229
|
-
pricing: PricingSchema,
|
|
230
|
-
timeout_ms: z.number().positive().optional()
|
|
231
|
-
});
|
|
232
|
-
var CommandSkillConfigSchema = z.object({
|
|
233
|
-
id: z.string().min(1),
|
|
234
|
-
type: z.literal("command"),
|
|
235
|
-
name: z.string().min(1),
|
|
236
|
-
command: z.string().min(1),
|
|
237
|
-
output_type: z.enum(["json", "text", "file"]),
|
|
238
|
-
allowed_commands: z.array(z.string()).optional(),
|
|
239
|
-
working_dir: z.string().optional(),
|
|
240
|
-
timeout_ms: z.number().positive().default(3e4),
|
|
241
|
-
pricing: PricingSchema
|
|
242
|
-
});
|
|
243
|
-
var ConductorSkillConfigSchema = z.object({
|
|
244
|
-
id: z.string().min(1),
|
|
245
|
-
type: z.literal("conductor"),
|
|
246
|
-
name: z.string().min(1),
|
|
247
|
-
conductor_skill: z.enum(["orchestrate", "plan"]),
|
|
248
|
-
pricing: PricingSchema,
|
|
249
|
-
timeout_ms: z.number().positive().optional()
|
|
250
|
-
});
|
|
251
|
-
var SkillConfigSchema = z.discriminatedUnion("type", [
|
|
252
|
-
ApiSkillConfigSchema,
|
|
253
|
-
PipelineSkillConfigSchema,
|
|
254
|
-
OpenClawSkillConfigSchema,
|
|
255
|
-
CommandSkillConfigSchema,
|
|
256
|
-
ConductorSkillConfigSchema
|
|
257
|
-
]);
|
|
258
|
-
var SkillsFileSchema = z.object({
|
|
259
|
-
skills: z.array(SkillConfigSchema)
|
|
260
|
-
});
|
|
261
|
-
function expandEnvVars(value) {
|
|
262
|
-
return value.replace(/\$\{([^}]+)\}/g, (_match, varName) => {
|
|
263
|
-
if (/[.a-z]/.test(varName)) {
|
|
264
|
-
return _match;
|
|
265
|
-
}
|
|
266
|
-
const envValue = process.env[varName];
|
|
267
|
-
if (envValue === void 0) {
|
|
268
|
-
throw new Error(`Environment variable "${varName}" is not defined`);
|
|
269
|
-
}
|
|
270
|
-
return envValue;
|
|
271
|
-
});
|
|
272
|
-
}
|
|
273
|
-
function expandEnvVarsDeep(value) {
|
|
274
|
-
if (typeof value === "string") {
|
|
275
|
-
return expandEnvVars(value);
|
|
276
|
-
}
|
|
277
|
-
if (Array.isArray(value)) {
|
|
278
|
-
return value.map(expandEnvVarsDeep);
|
|
279
|
-
}
|
|
280
|
-
if (value !== null && typeof value === "object") {
|
|
281
|
-
const result = {};
|
|
282
|
-
for (const [k, v] of Object.entries(value)) {
|
|
283
|
-
result[k] = expandEnvVarsDeep(v);
|
|
284
|
-
}
|
|
285
|
-
return result;
|
|
286
|
-
}
|
|
287
|
-
return value;
|
|
288
|
-
}
|
|
289
|
-
function parseSkillsFile(yamlContent) {
|
|
290
|
-
const raw = yaml.load(yamlContent);
|
|
291
|
-
const expanded = expandEnvVarsDeep(raw);
|
|
292
|
-
const result = SkillsFileSchema.parse(expanded);
|
|
293
|
-
return result.skills;
|
|
188
|
+
function createSkillExecutor(configs, modes, concurrencyGuard) {
|
|
189
|
+
return new SkillExecutor(configs, modes, concurrencyGuard);
|
|
294
190
|
}
|
|
295
191
|
|
|
296
192
|
// src/skills/api-executor.ts
|
|
@@ -766,14 +662,32 @@ var CommandExecutor = class {
|
|
|
766
662
|
const cmdConfig = config;
|
|
767
663
|
const baseCommand = cmdConfig.command.trim().split(/\s+/)[0] ?? "";
|
|
768
664
|
if (cmdConfig.allowed_commands && cmdConfig.allowed_commands.length > 0) {
|
|
769
|
-
|
|
665
|
+
const effectiveAllowed = cmdConfig.claude_code ? [.../* @__PURE__ */ new Set([...cmdConfig.allowed_commands, "claude"])] : cmdConfig.allowed_commands;
|
|
666
|
+
const commandToCheck = cmdConfig.claude_code ? "claude" : baseCommand;
|
|
667
|
+
if (!effectiveAllowed.includes(commandToCheck)) {
|
|
770
668
|
return {
|
|
771
669
|
success: false,
|
|
772
|
-
error: `Command not allowed: "${
|
|
670
|
+
error: `Command not allowed: "${commandToCheck}". Allowed: ${effectiveAllowed.join(", ")}`
|
|
773
671
|
};
|
|
774
672
|
}
|
|
775
673
|
}
|
|
776
|
-
|
|
674
|
+
let interpolatedCommand;
|
|
675
|
+
if (cmdConfig.claude_code) {
|
|
676
|
+
const parts = ["claude", "--print"];
|
|
677
|
+
if (cmdConfig.claude_code.auto_mode) {
|
|
678
|
+
parts.push("--dangerously-skip-permissions");
|
|
679
|
+
}
|
|
680
|
+
if (cmdConfig.claude_code.model) {
|
|
681
|
+
parts.push("--model", cmdConfig.claude_code.model);
|
|
682
|
+
}
|
|
683
|
+
if (cmdConfig.claude_code.system_prompt) {
|
|
684
|
+
parts.push("-p", shellEscape2(cmdConfig.claude_code.system_prompt));
|
|
685
|
+
}
|
|
686
|
+
const interpolatedPrompt = safeInterpolateCommand2(cmdConfig.command, { params });
|
|
687
|
+
interpolatedCommand = parts.join(" ") + " " + interpolatedPrompt;
|
|
688
|
+
} else {
|
|
689
|
+
interpolatedCommand = safeInterpolateCommand2(cmdConfig.command, { params });
|
|
690
|
+
}
|
|
777
691
|
const timeout = cmdConfig.timeout_ms ?? 3e4;
|
|
778
692
|
const cwd = cmdConfig.working_dir ?? process.cwd();
|
|
779
693
|
let stdout;
|
|
@@ -914,8 +828,8 @@ var AgentRuntime = class {
|
|
|
914
828
|
}
|
|
915
829
|
const modes = /* @__PURE__ */ new Map();
|
|
916
830
|
if (this.conductorEnabled) {
|
|
917
|
-
const { ConductorMode } = await import("./conductor-mode-
|
|
918
|
-
const { registerConductorCard, CONDUCTOR_OWNER } = await import("./card-
|
|
831
|
+
const { ConductorMode } = await import("./conductor-mode-VGUU54QI.js");
|
|
832
|
+
const { registerConductorCard, CONDUCTOR_OWNER } = await import("./card-REW7BSWW.js");
|
|
919
833
|
const { loadPeers } = await import("./peers-K7FSHPN3.js");
|
|
920
834
|
registerConductorCard(this.registryDb);
|
|
921
835
|
const resolveAgentUrl = (owner) => {
|
|
@@ -1021,6 +935,7 @@ var AgentRuntime = class {
|
|
|
1021
935
|
|
|
1022
936
|
// src/gateway/server.ts
|
|
1023
937
|
import Fastify from "fastify";
|
|
938
|
+
import { randomUUID } from "crypto";
|
|
1024
939
|
var VERSION = "0.0.1";
|
|
1025
940
|
function createGatewayServer(opts) {
|
|
1026
941
|
const {
|
|
@@ -1034,6 +949,8 @@ function createGatewayServer(opts) {
|
|
|
1034
949
|
} = opts;
|
|
1035
950
|
const fastify = Fastify({ logger: !silent });
|
|
1036
951
|
const tokenSet = new Set(tokens);
|
|
952
|
+
const inFlight = /* @__PURE__ */ new Map();
|
|
953
|
+
const OVERLOAD_RETRY_MS = 5e3;
|
|
1037
954
|
fastify.addHook("onRequest", async (request) => {
|
|
1038
955
|
if (request.method === "GET" && request.url === "/health") return;
|
|
1039
956
|
const auth = request.headers.authorization;
|
|
@@ -1099,18 +1016,63 @@ function createGatewayServer(opts) {
|
|
|
1099
1016
|
}
|
|
1100
1017
|
const requester = params.requester ?? "unknown";
|
|
1101
1018
|
const receipt = params.escrow_receipt;
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1019
|
+
if (skillExecutor && skillId && typeof skillExecutor.getSkillConfig === "function") {
|
|
1020
|
+
const skillConfig = skillExecutor.getSkillConfig(skillId);
|
|
1021
|
+
const maxConcurrent = skillConfig?.capacity?.max_concurrent;
|
|
1022
|
+
if (maxConcurrent !== void 0) {
|
|
1023
|
+
const current = inFlight.get(skillId) ?? 0;
|
|
1024
|
+
if (current >= maxConcurrent) {
|
|
1025
|
+
try {
|
|
1026
|
+
insertRequestLog(registryDb, {
|
|
1027
|
+
id: randomUUID(),
|
|
1028
|
+
card_id: cardId,
|
|
1029
|
+
card_name: "<overload>",
|
|
1030
|
+
requester,
|
|
1031
|
+
status: "failure",
|
|
1032
|
+
latency_ms: 0,
|
|
1033
|
+
credits_charged: 0,
|
|
1034
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1035
|
+
skill_id: skillId,
|
|
1036
|
+
failure_reason: "overload"
|
|
1037
|
+
});
|
|
1038
|
+
} catch {
|
|
1039
|
+
}
|
|
1040
|
+
return reply.status(200).send({
|
|
1041
|
+
jsonrpc: "2.0",
|
|
1042
|
+
id,
|
|
1043
|
+
error: {
|
|
1044
|
+
code: -32e3,
|
|
1045
|
+
message: "overload",
|
|
1046
|
+
data: { error: "overload", retry_after_ms: OVERLOAD_RETRY_MS }
|
|
1047
|
+
}
|
|
1048
|
+
});
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
const trackKey = skillId ?? cardId;
|
|
1053
|
+
inFlight.set(trackKey, (inFlight.get(trackKey) ?? 0) + 1);
|
|
1054
|
+
let result;
|
|
1055
|
+
try {
|
|
1056
|
+
result = await executeCapabilityRequest({
|
|
1057
|
+
registryDb,
|
|
1058
|
+
creditDb,
|
|
1059
|
+
cardId,
|
|
1060
|
+
skillId,
|
|
1061
|
+
params,
|
|
1062
|
+
requester,
|
|
1063
|
+
escrowReceipt: receipt,
|
|
1064
|
+
skillExecutor,
|
|
1065
|
+
handlerUrl,
|
|
1066
|
+
timeoutMs
|
|
1067
|
+
});
|
|
1068
|
+
} finally {
|
|
1069
|
+
const next = (inFlight.get(trackKey) ?? 1) - 1;
|
|
1070
|
+
if (next <= 0) {
|
|
1071
|
+
inFlight.delete(trackKey);
|
|
1072
|
+
} else {
|
|
1073
|
+
inFlight.set(trackKey, next);
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1114
1076
|
if (result.success) {
|
|
1115
1077
|
return reply.send({ jsonrpc: "2.0", id, result: result.result });
|
|
1116
1078
|
} else {
|
|
@@ -1130,10 +1092,10 @@ import fastifyWebsocket from "@fastify/websocket";
|
|
|
1130
1092
|
import { join, dirname } from "path";
|
|
1131
1093
|
import { fileURLToPath } from "url";
|
|
1132
1094
|
import { existsSync as existsSync2 } from "fs";
|
|
1133
|
-
import { z as
|
|
1095
|
+
import { z as z4 } from "zod";
|
|
1134
1096
|
|
|
1135
1097
|
// src/relay/websocket-relay.ts
|
|
1136
|
-
import { randomUUID as
|
|
1098
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
1137
1099
|
|
|
1138
1100
|
// src/relay/relay-credit.ts
|
|
1139
1101
|
function lookupCardPrice(registryDb, cardId, skillId) {
|
|
@@ -1191,10 +1153,10 @@ function releaseForRelay(creditDb, escrowId) {
|
|
|
1191
1153
|
}
|
|
1192
1154
|
|
|
1193
1155
|
// src/hub-agent/relay-bridge.ts
|
|
1194
|
-
import { randomUUID as
|
|
1156
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
1195
1157
|
|
|
1196
1158
|
// src/hub-agent/job-queue.ts
|
|
1197
|
-
import { randomUUID } from "crypto";
|
|
1159
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
1198
1160
|
function initJobQueue(db) {
|
|
1199
1161
|
db.exec(`
|
|
1200
1162
|
CREATE TABLE IF NOT EXISTS hub_agent_jobs (
|
|
@@ -1213,7 +1175,7 @@ function initJobQueue(db) {
|
|
|
1213
1175
|
`);
|
|
1214
1176
|
}
|
|
1215
1177
|
function insertJob(db, input) {
|
|
1216
|
-
const id =
|
|
1178
|
+
const id = randomUUID2();
|
|
1217
1179
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1218
1180
|
const paramsJson = JSON.stringify(input.params);
|
|
1219
1181
|
db.prepare(`
|
|
@@ -1425,7 +1387,7 @@ function createRelayBridge(opts) {
|
|
|
1425
1387
|
updateJobStatus(registryDb, job.id, "dispatched");
|
|
1426
1388
|
const agent = getHubAgent(registryDb, job.hub_agent_id);
|
|
1427
1389
|
const cardId = agent ? agent.agent_id.padEnd(32, "0").replace(/^(.{8})(.{4})(.{4})(.{4})(.{12}).*$/, "$1-$2-$3-$4-$5") : job.hub_agent_id;
|
|
1428
|
-
const requestId =
|
|
1390
|
+
const requestId = randomUUID3();
|
|
1429
1391
|
let params = {};
|
|
1430
1392
|
try {
|
|
1431
1393
|
params = JSON.parse(job.params);
|
|
@@ -1495,6 +1457,7 @@ function registerWebSocketRelay(server, db, creditDb) {
|
|
|
1495
1457
|
const connections = /* @__PURE__ */ new Map();
|
|
1496
1458
|
const pendingRequests = /* @__PURE__ */ new Map();
|
|
1497
1459
|
const rateLimits = /* @__PURE__ */ new Map();
|
|
1460
|
+
const agentCapacities = /* @__PURE__ */ new Map();
|
|
1498
1461
|
let onAgentOnlineCallback;
|
|
1499
1462
|
function checkRateLimit(owner) {
|
|
1500
1463
|
const now = Date.now();
|
|
@@ -1571,7 +1534,7 @@ function registerWebSocketRelay(server, db, creditDb) {
|
|
|
1571
1534
|
function logAgentJoined(owner, cardName, cardId) {
|
|
1572
1535
|
try {
|
|
1573
1536
|
insertRequestLog(db, {
|
|
1574
|
-
id:
|
|
1537
|
+
id: randomUUID4(),
|
|
1575
1538
|
card_id: cardId,
|
|
1576
1539
|
card_name: cardName,
|
|
1577
1540
|
requester: owner,
|
|
@@ -1798,6 +1761,7 @@ function registerWebSocketRelay(server, db, creditDb) {
|
|
|
1798
1761
|
if (!owner) return;
|
|
1799
1762
|
connections.delete(owner);
|
|
1800
1763
|
rateLimits.delete(owner);
|
|
1764
|
+
agentCapacities.delete(owner);
|
|
1801
1765
|
markOwnerOffline(owner);
|
|
1802
1766
|
for (const [reqId, pending] of pendingRequests) {
|
|
1803
1767
|
if (pending.targetOwner === owner) {
|
|
@@ -1831,6 +1795,9 @@ function registerWebSocketRelay(server, db, creditDb) {
|
|
|
1831
1795
|
}
|
|
1832
1796
|
}
|
|
1833
1797
|
}
|
|
1798
|
+
function handleHeartbeat(msg) {
|
|
1799
|
+
agentCapacities.set(msg.owner, msg.capacity);
|
|
1800
|
+
}
|
|
1834
1801
|
void server.register(async (app) => {
|
|
1835
1802
|
app.get("/ws", { websocket: true }, (rawSocket, _request) => {
|
|
1836
1803
|
const socket = rawSocket;
|
|
@@ -1876,15 +1843,23 @@ function registerWebSocketRelay(server, db, creditDb) {
|
|
|
1876
1843
|
case "relay_progress":
|
|
1877
1844
|
handleRelayProgress(msg);
|
|
1878
1845
|
break;
|
|
1846
|
+
case "heartbeat":
|
|
1847
|
+
handleHeartbeat(msg);
|
|
1848
|
+
break;
|
|
1879
1849
|
default:
|
|
1880
1850
|
break;
|
|
1881
1851
|
}
|
|
1882
1852
|
})();
|
|
1883
1853
|
});
|
|
1854
|
+
const pingInterval = setInterval(() => {
|
|
1855
|
+
if (socket.readyState === 1) socket.ping();
|
|
1856
|
+
}, 3e4);
|
|
1884
1857
|
socket.on("close", () => {
|
|
1858
|
+
clearInterval(pingInterval);
|
|
1885
1859
|
handleDisconnect(registeredOwner);
|
|
1886
1860
|
});
|
|
1887
1861
|
socket.on("error", () => {
|
|
1862
|
+
clearInterval(pingInterval);
|
|
1888
1863
|
handleDisconnect(registeredOwner);
|
|
1889
1864
|
});
|
|
1890
1865
|
});
|
|
@@ -1905,6 +1880,7 @@ function registerWebSocketRelay(server, db, creditDb) {
|
|
|
1905
1880
|
}
|
|
1906
1881
|
pendingRequests.clear();
|
|
1907
1882
|
rateLimits.clear();
|
|
1883
|
+
agentCapacities.clear();
|
|
1908
1884
|
},
|
|
1909
1885
|
setOnAgentOnline: (cb) => {
|
|
1910
1886
|
onAgentOnlineCallback = cb;
|
|
@@ -1913,21 +1889,23 @@ function registerWebSocketRelay(server, db, creditDb) {
|
|
|
1913
1889
|
getPendingRequests: () => pendingRequests,
|
|
1914
1890
|
sendMessage: (ws, msg) => {
|
|
1915
1891
|
sendMessage(ws, msg);
|
|
1916
|
-
}
|
|
1892
|
+
},
|
|
1893
|
+
getAgentCapacity: (owner) => agentCapacities.get(owner),
|
|
1894
|
+
getAllCapacities: () => new Map(agentCapacities)
|
|
1917
1895
|
};
|
|
1918
1896
|
}
|
|
1919
1897
|
|
|
1920
1898
|
// src/identity/guarantor.ts
|
|
1921
|
-
import { z
|
|
1922
|
-
import { randomUUID as
|
|
1899
|
+
import { z } from "zod";
|
|
1900
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
1923
1901
|
var MAX_AGENTS_PER_GUARANTOR = 10;
|
|
1924
1902
|
var GUARANTOR_CREDIT_POOL = 50;
|
|
1925
|
-
var GuarantorRecordSchema =
|
|
1926
|
-
id:
|
|
1927
|
-
github_login:
|
|
1928
|
-
agent_count:
|
|
1929
|
-
credit_pool:
|
|
1930
|
-
created_at:
|
|
1903
|
+
var GuarantorRecordSchema = z.object({
|
|
1904
|
+
id: z.string().uuid(),
|
|
1905
|
+
github_login: z.string().min(1),
|
|
1906
|
+
agent_count: z.number().int().nonnegative(),
|
|
1907
|
+
credit_pool: z.number().int().nonnegative(),
|
|
1908
|
+
created_at: z.string().datetime()
|
|
1931
1909
|
});
|
|
1932
1910
|
var GUARANTOR_SCHEMA = `
|
|
1933
1911
|
CREATE TABLE IF NOT EXISTS guarantors (
|
|
@@ -1958,7 +1936,7 @@ function registerGuarantor(db, githubLogin) {
|
|
|
1958
1936
|
);
|
|
1959
1937
|
}
|
|
1960
1938
|
const record = {
|
|
1961
|
-
id:
|
|
1939
|
+
id: randomUUID5(),
|
|
1962
1940
|
github_login: githubLogin,
|
|
1963
1941
|
agent_count: 0,
|
|
1964
1942
|
credit_pool: GUARANTOR_CREDIT_POOL,
|
|
@@ -2032,7 +2010,7 @@ function getAgentGuarantor(db, agentId) {
|
|
|
2032
2010
|
function initiateGithubAuth() {
|
|
2033
2011
|
return {
|
|
2034
2012
|
auth_url: "https://github.com/login/oauth/authorize?client_id=PLACEHOLDER&scope=read:user",
|
|
2035
|
-
state:
|
|
2013
|
+
state: randomUUID5()
|
|
2036
2014
|
};
|
|
2037
2015
|
}
|
|
2038
2016
|
|
|
@@ -2459,38 +2437,38 @@ var HubAgentExecutor = class {
|
|
|
2459
2437
|
};
|
|
2460
2438
|
|
|
2461
2439
|
// src/hub-agent/types.ts
|
|
2462
|
-
import { z as
|
|
2463
|
-
var SkillRouteSchema =
|
|
2464
|
-
|
|
2465
|
-
skill_id:
|
|
2466
|
-
mode:
|
|
2440
|
+
import { z as z2 } from "zod";
|
|
2441
|
+
var SkillRouteSchema = z2.discriminatedUnion("mode", [
|
|
2442
|
+
z2.object({
|
|
2443
|
+
skill_id: z2.string().min(1),
|
|
2444
|
+
mode: z2.literal("direct_api"),
|
|
2467
2445
|
config: ApiSkillConfigSchema
|
|
2468
2446
|
}),
|
|
2469
|
-
|
|
2470
|
-
skill_id:
|
|
2471
|
-
mode:
|
|
2472
|
-
config:
|
|
2447
|
+
z2.object({
|
|
2448
|
+
skill_id: z2.string().min(1),
|
|
2449
|
+
mode: z2.literal("relay"),
|
|
2450
|
+
config: z2.object({ relay_owner: z2.string().min(1) })
|
|
2473
2451
|
}),
|
|
2474
|
-
|
|
2475
|
-
skill_id:
|
|
2476
|
-
mode:
|
|
2477
|
-
config:
|
|
2452
|
+
z2.object({
|
|
2453
|
+
skill_id: z2.string().min(1),
|
|
2454
|
+
mode: z2.literal("queue"),
|
|
2455
|
+
config: z2.object({ relay_owner: z2.string().min(1) }).passthrough()
|
|
2478
2456
|
})
|
|
2479
2457
|
]);
|
|
2480
|
-
var HubAgentSchema =
|
|
2481
|
-
agent_id:
|
|
2482
|
-
name:
|
|
2483
|
-
owner_public_key:
|
|
2484
|
-
public_key:
|
|
2485
|
-
skill_routes:
|
|
2486
|
-
status:
|
|
2487
|
-
created_at:
|
|
2488
|
-
updated_at:
|
|
2458
|
+
var HubAgentSchema = z2.object({
|
|
2459
|
+
agent_id: z2.string().min(1),
|
|
2460
|
+
name: z2.string().min(1),
|
|
2461
|
+
owner_public_key: z2.string().min(1),
|
|
2462
|
+
public_key: z2.string().min(1),
|
|
2463
|
+
skill_routes: z2.array(SkillRouteSchema),
|
|
2464
|
+
status: z2.enum(["active", "paused"]),
|
|
2465
|
+
created_at: z2.string(),
|
|
2466
|
+
updated_at: z2.string()
|
|
2489
2467
|
});
|
|
2490
|
-
var CreateAgentRequestSchema =
|
|
2491
|
-
name:
|
|
2492
|
-
skill_routes:
|
|
2493
|
-
secrets:
|
|
2468
|
+
var CreateAgentRequestSchema = z2.object({
|
|
2469
|
+
name: z2.string().min(1),
|
|
2470
|
+
skill_routes: z2.array(SkillRouteSchema),
|
|
2471
|
+
secrets: z2.record(z2.string()).optional()
|
|
2494
2472
|
});
|
|
2495
2473
|
|
|
2496
2474
|
// src/hub-agent/routes.ts
|
|
@@ -3037,28 +3015,28 @@ var feedbackPlugin = async (fastify, opts) => {
|
|
|
3037
3015
|
var api_default = feedbackPlugin;
|
|
3038
3016
|
|
|
3039
3017
|
// src/evolution/schema.ts
|
|
3040
|
-
import { z as
|
|
3041
|
-
var CoreMemoryEntrySchema =
|
|
3042
|
-
category:
|
|
3043
|
-
importance:
|
|
3044
|
-
content:
|
|
3045
|
-
scope:
|
|
3018
|
+
import { z as z3 } from "zod";
|
|
3019
|
+
var CoreMemoryEntrySchema = z3.object({
|
|
3020
|
+
category: z3.string(),
|
|
3021
|
+
importance: z3.number().min(0).max(1),
|
|
3022
|
+
content: z3.string(),
|
|
3023
|
+
scope: z3.string().optional()
|
|
3046
3024
|
});
|
|
3047
|
-
var TemplateEvolutionSchema =
|
|
3025
|
+
var TemplateEvolutionSchema = z3.object({
|
|
3048
3026
|
/** e.g. "genesis-template" */
|
|
3049
|
-
template_name:
|
|
3027
|
+
template_name: z3.string().min(1),
|
|
3050
3028
|
/** Semantic version string, e.g. "1.2.3" */
|
|
3051
|
-
template_version:
|
|
3029
|
+
template_version: z3.string().regex(/^\d+\.\d+\.\d+$/, "Must be a valid semver string (e.g. 1.2.3)"),
|
|
3052
3030
|
/** Identifier of the agent publishing this evolution */
|
|
3053
|
-
publisher_agent:
|
|
3031
|
+
publisher_agent: z3.string().min(1),
|
|
3054
3032
|
/** Human-readable description of what changed in this evolution */
|
|
3055
|
-
changelog:
|
|
3033
|
+
changelog: z3.string().max(1e3),
|
|
3056
3034
|
/** Snapshot of the agent's core memory at the time of evolution (max 50 entries) */
|
|
3057
|
-
core_memory_snapshot:
|
|
3035
|
+
core_memory_snapshot: z3.array(CoreMemoryEntrySchema).max(50),
|
|
3058
3036
|
/** Delta in fitness score from before evolution (range -1 to 1) */
|
|
3059
|
-
fitness_improvement:
|
|
3037
|
+
fitness_improvement: z3.number().min(-1).max(1),
|
|
3060
3038
|
/** ISO 8601 datetime string */
|
|
3061
|
-
timestamp:
|
|
3039
|
+
timestamp: z3.string().datetime()
|
|
3062
3040
|
});
|
|
3063
3041
|
|
|
3064
3042
|
// src/evolution/api.ts
|
|
@@ -3184,7 +3162,7 @@ function createRegistryServer(opts) {
|
|
|
3184
3162
|
openapi: "3.0.3",
|
|
3185
3163
|
info: {
|
|
3186
3164
|
title: "AgentBnB Registry API",
|
|
3187
|
-
description: "
|
|
3165
|
+
description: "Where AI agents hire AI agents \u2014 discover, publish, and coordinate agent capabilities",
|
|
3188
3166
|
version: "3.1.6"
|
|
3189
3167
|
},
|
|
3190
3168
|
servers: [{ url: "/", description: "Registry server" }],
|
|
@@ -3216,7 +3194,7 @@ function createRegistryServer(opts) {
|
|
|
3216
3194
|
});
|
|
3217
3195
|
void server.register(cors, {
|
|
3218
3196
|
origin: true,
|
|
3219
|
-
methods: ["GET", "POST", "PATCH", "OPTIONS"],
|
|
3197
|
+
methods: ["GET", "POST", "PATCH", "DELETE", "OPTIONS"],
|
|
3220
3198
|
allowedHeaders: ["Content-Type", "Authorization", "X-Agent-PublicKey", "X-Agent-Signature", "X-Agent-Timestamp"]
|
|
3221
3199
|
});
|
|
3222
3200
|
void server.register(fastifyWebsocket);
|
|
@@ -3295,6 +3273,7 @@ function createRegistryServer(opts) {
|
|
|
3295
3273
|
min_success_rate: { type: "number", description: "Minimum success rate (0-1)" },
|
|
3296
3274
|
max_latency_ms: { type: "number", description: "Maximum average latency in ms" },
|
|
3297
3275
|
min_reputation: { type: "number", description: "Minimum reputation score (0-1) based on peer feedback" },
|
|
3276
|
+
capability_type: { type: "string", description: "Filter cards whose skills declare this capability_type (e.g. tts, code_gen)" },
|
|
3298
3277
|
sort: { type: "string", enum: ["popular", "rated", "success_rate", "cheapest", "newest", "latency", "reputation_desc", "reputation_asc"], description: "Sort order" },
|
|
3299
3278
|
limit: { type: "integer", default: 20, description: "Max items per page (max 100)" },
|
|
3300
3279
|
offset: { type: "integer", default: 0, description: "Pagination offset" }
|
|
@@ -3321,6 +3300,7 @@ function createRegistryServer(opts) {
|
|
|
3321
3300
|
const onlineRaw = query.online;
|
|
3322
3301
|
const online = onlineRaw === "true" ? true : onlineRaw === "false" ? false : void 0;
|
|
3323
3302
|
const tag = query.tag?.trim();
|
|
3303
|
+
const capabilityType = query.capability_type?.trim() || void 0;
|
|
3324
3304
|
const minSuccessRate = query.min_success_rate !== void 0 ? parseFloat(query.min_success_rate) : void 0;
|
|
3325
3305
|
const maxLatencyMs = query.max_latency_ms !== void 0 ? parseFloat(query.max_latency_ms) : void 0;
|
|
3326
3306
|
const minReputation = query.min_reputation !== void 0 ? parseFloat(query.min_reputation) : void 0;
|
|
@@ -3336,6 +3316,12 @@ function createRegistryServer(opts) {
|
|
|
3336
3316
|
cards = filterCards(db, { level, online, min_reputation: minReputation });
|
|
3337
3317
|
}
|
|
3338
3318
|
cards = cards.filter((c) => !c.owner.includes(":req:"));
|
|
3319
|
+
if (capabilityType !== void 0) {
|
|
3320
|
+
const capTypeIds = new Set(
|
|
3321
|
+
getCardsBySkillCapability(db, capabilityType).map((c) => c.id)
|
|
3322
|
+
);
|
|
3323
|
+
cards = cards.filter((c) => capTypeIds.has(c.id));
|
|
3324
|
+
}
|
|
3339
3325
|
if (tag !== void 0 && tag.length > 0) {
|
|
3340
3326
|
cards = cards.filter((c) => {
|
|
3341
3327
|
const rootTags = c.metadata?.tags ?? [];
|
|
@@ -3371,7 +3357,9 @@ function createRegistryServer(opts) {
|
|
|
3371
3357
|
const trustStmt = db.prepare(`
|
|
3372
3358
|
SELECT cc.owner,
|
|
3373
3359
|
COUNT(rl.id) as total_exec,
|
|
3374
|
-
SUM(CASE WHEN rl.status IN ('success','failure','timeout','refunded')
|
|
3360
|
+
SUM(CASE WHEN rl.status IN ('success','failure','timeout','refunded')
|
|
3361
|
+
AND (rl.failure_reason IS NULL OR rl.failure_reason IN ('bad_execution','auth_error'))
|
|
3362
|
+
THEN 1 ELSE 0 END) as terminal_exec,
|
|
3375
3363
|
SUM(CASE WHEN rl.status = 'success' THEN 1 ELSE 0 END) as success_exec,
|
|
3376
3364
|
AVG(CASE WHEN rl.status = 'success' THEN rl.latency_ms END) as avg_latency
|
|
3377
3365
|
FROM capability_cards cc
|
|
@@ -3605,21 +3593,32 @@ function createRegistryServer(opts) {
|
|
|
3605
3593
|
api.delete("/cards/:id", {
|
|
3606
3594
|
schema: {
|
|
3607
3595
|
tags: ["cards"],
|
|
3608
|
-
summary: "Delete a capability card",
|
|
3596
|
+
summary: "Delete a capability card (requires Bearer auth)",
|
|
3597
|
+
security: [{ bearerAuth: [] }],
|
|
3609
3598
|
params: { type: "object", properties: { id: { type: "string" } }, required: ["id"] },
|
|
3610
3599
|
response: {
|
|
3611
|
-
|
|
3600
|
+
204: { type: "null", description: "Card deleted successfully" },
|
|
3601
|
+
401: { type: "object", properties: { error: { type: "string" } } },
|
|
3602
|
+
403: { type: "object", properties: { error: { type: "string" } } },
|
|
3612
3603
|
404: { type: "object", properties: { error: { type: "string" } } }
|
|
3613
3604
|
}
|
|
3614
3605
|
}
|
|
3615
3606
|
}, async (request, reply) => {
|
|
3607
|
+
const auth = request.headers.authorization;
|
|
3608
|
+
const token = auth?.startsWith("Bearer ") ? auth.slice(7).trim() : null;
|
|
3609
|
+
if (!token || !opts.ownerApiKey || token !== opts.ownerApiKey) {
|
|
3610
|
+
return reply.code(401).send({ error: "Unauthorized" });
|
|
3611
|
+
}
|
|
3616
3612
|
const { id } = request.params;
|
|
3617
3613
|
const card = getCard(db, id);
|
|
3618
3614
|
if (!card) {
|
|
3619
3615
|
return reply.code(404).send({ error: "Not found" });
|
|
3620
3616
|
}
|
|
3617
|
+
if (opts.ownerName && card.owner !== opts.ownerName) {
|
|
3618
|
+
return reply.code(403).send({ error: "Forbidden" });
|
|
3619
|
+
}
|
|
3621
3620
|
db.prepare("DELETE FROM capability_cards WHERE id = ?").run(id);
|
|
3622
|
-
return reply.send(
|
|
3621
|
+
return reply.code(204).send();
|
|
3623
3622
|
});
|
|
3624
3623
|
api.get("/api/agents", {
|
|
3625
3624
|
schema: {
|
|
@@ -3704,7 +3703,8 @@ function createRegistryServer(opts) {
|
|
|
3704
3703
|
const lastActive = lastActiveRow?.last_req ?? memberRow?.latest ?? joinedAt;
|
|
3705
3704
|
const metricsStmt = db.prepare(`
|
|
3706
3705
|
SELECT
|
|
3707
|
-
|
|
3706
|
+
SUM(CASE WHEN rl.failure_reason IS NULL OR rl.failure_reason IN ('bad_execution','auth_error')
|
|
3707
|
+
THEN 1 ELSE 0 END) as total,
|
|
3708
3708
|
SUM(CASE WHEN rl.status = 'success' THEN 1 ELSE 0 END) as successes,
|
|
3709
3709
|
AVG(CASE WHEN rl.status = 'success' THEN rl.latency_ms END) as avg_latency,
|
|
3710
3710
|
COUNT(DISTINCT rl.requester) as unique_requesters,
|
|
@@ -4032,16 +4032,16 @@ function createRegistryServer(opts) {
|
|
|
4032
4032
|
const gptActions = convertToGptActions(openapiSpec, serverUrl);
|
|
4033
4033
|
return reply.send(gptActions);
|
|
4034
4034
|
});
|
|
4035
|
-
const BatchRequestBodySchema =
|
|
4036
|
-
requests:
|
|
4037
|
-
|
|
4038
|
-
skill_id:
|
|
4039
|
-
params:
|
|
4040
|
-
max_credits:
|
|
4035
|
+
const BatchRequestBodySchema = z4.object({
|
|
4036
|
+
requests: z4.array(
|
|
4037
|
+
z4.object({
|
|
4038
|
+
skill_id: z4.string().min(1),
|
|
4039
|
+
params: z4.record(z4.unknown()).default({}),
|
|
4040
|
+
max_credits: z4.number().positive()
|
|
4041
4041
|
})
|
|
4042
4042
|
).min(1),
|
|
4043
|
-
strategy:
|
|
4044
|
-
total_budget:
|
|
4043
|
+
strategy: z4.enum(["parallel", "sequential", "best_effort"]),
|
|
4044
|
+
total_budget: z4.number().positive()
|
|
4045
4045
|
});
|
|
4046
4046
|
api.post("/api/request/batch", {
|
|
4047
4047
|
schema: {
|
|
@@ -4297,6 +4297,110 @@ function createRegistryServer(opts) {
|
|
|
4297
4297
|
});
|
|
4298
4298
|
});
|
|
4299
4299
|
}
|
|
4300
|
+
api.get("/api/providers/:owner/reliability", {
|
|
4301
|
+
schema: {
|
|
4302
|
+
tags: ["agents"],
|
|
4303
|
+
summary: "Get provider reliability metrics",
|
|
4304
|
+
params: { type: "object", properties: { owner: { type: "string" } }, required: ["owner"] },
|
|
4305
|
+
response: {
|
|
4306
|
+
200: {
|
|
4307
|
+
type: "object",
|
|
4308
|
+
properties: {
|
|
4309
|
+
current_streak: { type: "integer" },
|
|
4310
|
+
longest_streak: { type: "integer" },
|
|
4311
|
+
total_hires: { type: "integer" },
|
|
4312
|
+
repeat_hires: { type: "integer" },
|
|
4313
|
+
repeat_hire_rate: { type: "number" },
|
|
4314
|
+
avg_feedback_score: { type: "number" },
|
|
4315
|
+
availability_rate: { type: "number" }
|
|
4316
|
+
}
|
|
4317
|
+
},
|
|
4318
|
+
404: { type: "object", properties: { error: { type: "string" } } }
|
|
4319
|
+
}
|
|
4320
|
+
}
|
|
4321
|
+
}, async (request, reply) => {
|
|
4322
|
+
const { owner } = request.params;
|
|
4323
|
+
if (!opts.creditDb) {
|
|
4324
|
+
return reply.code(404).send({ error: "Credit system not enabled" });
|
|
4325
|
+
}
|
|
4326
|
+
const { getReliabilityMetrics } = await import("./reliability-metrics-QG7WC5QK.js");
|
|
4327
|
+
const metrics = getReliabilityMetrics(opts.creditDb, owner);
|
|
4328
|
+
if (!metrics) {
|
|
4329
|
+
return reply.code(404).send({ error: "No reliability data for this provider" });
|
|
4330
|
+
}
|
|
4331
|
+
return reply.send(metrics);
|
|
4332
|
+
});
|
|
4333
|
+
api.get("/api/fleet/:owner", {
|
|
4334
|
+
schema: {
|
|
4335
|
+
tags: ["agents"],
|
|
4336
|
+
summary: "Agent fleet overview for an owner",
|
|
4337
|
+
params: { type: "object", properties: { owner: { type: "string" } }, required: ["owner"] },
|
|
4338
|
+
response: {
|
|
4339
|
+
200: { type: "object", properties: { agents: { type: "array" } } }
|
|
4340
|
+
}
|
|
4341
|
+
}
|
|
4342
|
+
}, async (request, reply) => {
|
|
4343
|
+
const { owner } = request.params;
|
|
4344
|
+
const rows = db.prepare(
|
|
4345
|
+
"SELECT id, data FROM capability_cards WHERE owner = ?"
|
|
4346
|
+
).all(owner);
|
|
4347
|
+
const agents = [];
|
|
4348
|
+
for (const row of rows) {
|
|
4349
|
+
try {
|
|
4350
|
+
const card = JSON.parse(row.data);
|
|
4351
|
+
let earnings = 0;
|
|
4352
|
+
let spend = 0;
|
|
4353
|
+
if (opts.creditDb) {
|
|
4354
|
+
const earningRow = opts.creditDb.prepare(
|
|
4355
|
+
"SELECT COALESCE(SUM(amount), 0) as total FROM credit_transactions WHERE owner = ? AND reason = 'settlement' AND amount > 0"
|
|
4356
|
+
).get(owner);
|
|
4357
|
+
earnings = earningRow.total;
|
|
4358
|
+
const spendRow = opts.creditDb.prepare(
|
|
4359
|
+
"SELECT COALESCE(SUM(ABS(amount)), 0) as total FROM credit_transactions WHERE owner = ? AND reason = 'escrow_hold'"
|
|
4360
|
+
).get(owner);
|
|
4361
|
+
spend = spendRow.total;
|
|
4362
|
+
}
|
|
4363
|
+
const successCount = db.prepare(
|
|
4364
|
+
"SELECT COUNT(*) as cnt FROM request_log WHERE card_id = ? AND status = 'success' AND (action_type IS NULL OR action_type = 'auto_share')"
|
|
4365
|
+
).get(row.id).cnt;
|
|
4366
|
+
const failureCount = db.prepare(
|
|
4367
|
+
"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')"
|
|
4368
|
+
).get(row.id).cnt;
|
|
4369
|
+
const totalExec = successCount + failureCount;
|
|
4370
|
+
const successRate = totalExec > 0 ? successCount / totalExec : 0;
|
|
4371
|
+
let failureBreakdown = {};
|
|
4372
|
+
try {
|
|
4373
|
+
const failureRows = db.prepare(
|
|
4374
|
+
"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"
|
|
4375
|
+
).all(row.id);
|
|
4376
|
+
for (const fr of failureRows) {
|
|
4377
|
+
failureBreakdown[fr.failure_reason] = fr.cnt;
|
|
4378
|
+
}
|
|
4379
|
+
} catch {
|
|
4380
|
+
}
|
|
4381
|
+
let reliability = null;
|
|
4382
|
+
if (opts.creditDb) {
|
|
4383
|
+
const { getReliabilityMetrics } = await import("./reliability-metrics-QG7WC5QK.js");
|
|
4384
|
+
reliability = getReliabilityMetrics(opts.creditDb, owner);
|
|
4385
|
+
}
|
|
4386
|
+
agents.push({
|
|
4387
|
+
id: row.id,
|
|
4388
|
+
name: card.name ?? card.agent_name ?? owner,
|
|
4389
|
+
online: card.availability?.online ?? false,
|
|
4390
|
+
current_load: 0,
|
|
4391
|
+
// Will be populated from relay heartbeat data in future
|
|
4392
|
+
success_rate: successRate,
|
|
4393
|
+
total_executions: totalExec,
|
|
4394
|
+
earnings,
|
|
4395
|
+
spend,
|
|
4396
|
+
failure_breakdown: failureBreakdown,
|
|
4397
|
+
reliability
|
|
4398
|
+
});
|
|
4399
|
+
} catch {
|
|
4400
|
+
}
|
|
4401
|
+
}
|
|
4402
|
+
return reply.send({ agents });
|
|
4403
|
+
});
|
|
4300
4404
|
});
|
|
4301
4405
|
return { server, relayState };
|
|
4302
4406
|
}
|
|
@@ -4400,7 +4504,7 @@ import { createRequire } from "module";
|
|
|
4400
4504
|
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
|
|
4401
4505
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
4402
4506
|
import { dirname as dirname2, join as join2, resolve } from "path";
|
|
4403
|
-
import { randomUUID as
|
|
4507
|
+
import { randomUUID as randomUUID6 } from "crypto";
|
|
4404
4508
|
var ServiceCoordinator = class {
|
|
4405
4509
|
config;
|
|
4406
4510
|
guard;
|
|
@@ -4541,7 +4645,7 @@ var ServiceCoordinator = class {
|
|
|
4541
4645
|
console.log("Conductor mode enabled \u2014 orchestrate/plan skills available via gateway");
|
|
4542
4646
|
}
|
|
4543
4647
|
if (opts.conductorEnabled && this.config.conductor?.public) {
|
|
4544
|
-
const { buildConductorCard } = await import("./card-
|
|
4648
|
+
const { buildConductorCard } = await import("./card-REW7BSWW.js");
|
|
4545
4649
|
const conductorCard = buildConductorCard(this.config.owner);
|
|
4546
4650
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
4547
4651
|
const existing = this.runtime.registryDb.prepare("SELECT id FROM capability_cards WHERE id = ?").get(conductorCard.id);
|
|
@@ -4598,11 +4702,11 @@ var ServiceCoordinator = class {
|
|
|
4598
4702
|
}
|
|
4599
4703
|
}
|
|
4600
4704
|
if (opts.registryUrl && opts.relay) {
|
|
4601
|
-
const { RelayClient } = await import("./websocket-client-
|
|
4602
|
-
const { executeCapabilityRequest: executeCapabilityRequest2 } = await import("./execute-
|
|
4705
|
+
const { RelayClient } = await import("./websocket-client-5MH6QRJK.js");
|
|
4706
|
+
const { executeCapabilityRequest: executeCapabilityRequest2 } = await import("./execute-MOXSSA3Q.js");
|
|
4603
4707
|
const cards = listCards(this.runtime.registryDb, this.config.owner);
|
|
4604
4708
|
const card = cards[0] ?? {
|
|
4605
|
-
id:
|
|
4709
|
+
id: randomUUID6(),
|
|
4606
4710
|
owner: this.config.owner,
|
|
4607
4711
|
name: this.config.owner,
|
|
4608
4712
|
description: "Agent registered via CLI",
|
|
@@ -4615,7 +4719,7 @@ var ServiceCoordinator = class {
|
|
|
4615
4719
|
};
|
|
4616
4720
|
const additionalCards = [];
|
|
4617
4721
|
if (this.config.conductor?.public) {
|
|
4618
|
-
const { buildConductorCard } = await import("./card-
|
|
4722
|
+
const { buildConductorCard } = await import("./card-REW7BSWW.js");
|
|
4619
4723
|
additionalCards.push(
|
|
4620
4724
|
buildConductorCard(this.config.owner)
|
|
4621
4725
|
);
|
|
@@ -4865,7 +4969,6 @@ var ServiceCoordinator = class {
|
|
|
4865
4969
|
})();
|
|
4866
4970
|
};
|
|
4867
4971
|
};
|
|
4868
|
-
var require2 = createRequire(import.meta.url);
|
|
4869
4972
|
function loadPersistedRuntime(configDir) {
|
|
4870
4973
|
const runtimePath = join2(configDir, "runtime.json");
|
|
4871
4974
|
if (!existsSync3(runtimePath)) return null;
|
|
@@ -4893,6 +4996,12 @@ function resolveNodeExecutable(runtime) {
|
|
|
4893
4996
|
return process.execPath;
|
|
4894
4997
|
}
|
|
4895
4998
|
function resolveCliLaunchArgs(serveArgs) {
|
|
4999
|
+
const require2 = createRequire(import.meta.url);
|
|
5000
|
+
try {
|
|
5001
|
+
const distCli2 = require2.resolve("agentbnb/dist/cli/index.js");
|
|
5002
|
+
return [distCli2, "serve", ...serveArgs];
|
|
5003
|
+
} catch {
|
|
5004
|
+
}
|
|
4896
5005
|
const projectRoot = resolve(dirname2(fileURLToPath2(import.meta.url)), "..", "..");
|
|
4897
5006
|
const distCli = join2(projectRoot, "dist", "cli", "index.js");
|
|
4898
5007
|
if (existsSync3(distCli)) {
|