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.
Files changed (60) hide show
  1. package/README.md +245 -39
  2. package/dist/{card-RSGDCHCV.js → card-REW7BSWW.js} +1 -1
  3. package/dist/{chunk-FLY3WIQR.js → chunk-2HSUPCBT.js} +3 -3
  4. package/dist/{chunk-WGZ5AGOX.js → chunk-3CIMVISQ.js} +24 -1
  5. package/dist/{chunk-NH2FIERR.js → chunk-574W3HHE.js} +1 -1
  6. package/dist/{chunk-WTXRY7R2.js → chunk-APEG4QIN.js} +157 -9
  7. package/dist/chunk-BP3L2TET.js +148 -0
  8. package/dist/{chunk-NLAWT4DT.js → chunk-CWYPTQRQ.js} +7 -7
  9. package/dist/{chunk-UKT6H7YT.js → chunk-DUW6RX6I.js} +5 -2
  10. package/dist/chunk-EAD4A4KG.js +430 -0
  11. package/dist/{chunk-QT7TEVNV.js → chunk-EHSHB7TY.js} +23 -1
  12. package/dist/{chunk-B5FTAGFN.js → chunk-ETGOKDFR.js} +75 -75
  13. package/dist/{chunk-5KFI5X7B.js → chunk-F53QQIM2.js} +1 -1
  14. package/dist/{chunk-MLS6IGGG.js → chunk-FK2MDNTB.js} +117 -117
  15. package/dist/{chunk-EGUOAHCW.js → chunk-GO4FVRVN.js} +15 -13
  16. package/dist/{chunk-CRFCWD6V.js → chunk-J2K5S5MX.js} +136 -173
  17. package/dist/chunk-K5FO42YF.js +1136 -0
  18. package/dist/{chunk-DFBX3BBD.js → chunk-KA2VIEGM.js} +211 -16
  19. package/dist/chunk-NWIQJ2CL.js +108 -0
  20. package/dist/chunk-OCSU2S6W.js +168 -0
  21. package/dist/{chunk-QQFBFV4V.js → chunk-PGDBUUGR.js} +60 -19
  22. package/dist/{chunk-QITOPASZ.js → chunk-PSQHUZ7X.js} +1 -1
  23. package/dist/{chunk-C6KPAFCC.js → chunk-PU7LXOQ3.js} +23 -1
  24. package/dist/{chunk-JOY533UH.js → chunk-TW65F5EU.js} +1 -1
  25. package/dist/{chunk-ZX5623ER.js → chunk-VMH2YS2I.js} +1 -1
  26. package/dist/{chunk-XND2DWTZ.js → chunk-VPQ44XKE.js} +2 -2
  27. package/dist/{chunk-CSATDXZC.js → chunk-Y7T6IMM3.js} +1 -1
  28. package/dist/cli/index.js +755 -379
  29. package/dist/{client-T5MTY3CS.js → client-HRYRJKSA.js} +3 -3
  30. package/dist/{conduct-WU3VEXB6.js → conduct-JNYJCDHQ.js} +14 -13
  31. package/dist/conduct-KJUD2RTB.js +22 -0
  32. package/dist/{conductor-mode-ZMTFZGJP.js → conductor-mode-2VVFMKVE.js} +313 -14
  33. package/dist/conductor-mode-VGUU54QI.js +276 -0
  34. package/dist/execute-I4PKSNJM.js +12 -0
  35. package/dist/execute-MOXSSA3Q.js +15 -0
  36. package/dist/index.d.ts +795 -2
  37. package/dist/index.js +861 -111
  38. package/dist/{process-guard-CC7CNRQJ.js → process-guard-QCCBGILS.js} +1 -1
  39. package/dist/publish-capability-TS6CNR5G.js +12 -0
  40. package/dist/reliability-metrics-QG7WC5QK.js +18 -0
  41. package/dist/{request-VOXBFUOG.js → request-E7TA7COA.js} +19 -18
  42. package/dist/{serve-skill-IH7UAJNR.js → serve-skill-HIOWYKRU.js} +13 -11
  43. package/dist/{server-JVQW2TID.js → server-I63CXFX3.js} +17 -16
  44. package/dist/{service-coordinator-EYRDTHL5.js → service-coordinator-XBNT3SMU.js} +369 -260
  45. package/dist/skill-config-FETXPNVP.js +22 -0
  46. package/dist/skills/agentbnb/bootstrap.js +430 -84
  47. package/dist/websocket-client-5MH6QRJK.js +7 -0
  48. package/dist/{websocket-client-WRN3HO73.js → websocket-client-PFGVTXNE.js} +1 -1
  49. package/openclaw.plugin.json +2 -2
  50. package/package.json +2 -1
  51. package/skills/agentbnb/SKILL.md +35 -0
  52. package/skills/agentbnb/bootstrap.ts +126 -8
  53. package/skills/agentbnb/install.sh +49 -9
  54. package/dist/chunk-EANI2N2V.js +0 -309
  55. package/dist/chunk-EPIWHNB2.js +0 -946
  56. package/dist/conduct-6LKIJJKQ.js +0 -21
  57. package/dist/conductor-mode-Q4IIDY5E.js +0 -123
  58. package/dist/execute-4D4ITQCL.js +0 -10
  59. package/dist/execute-T7Y6RKSW.js +0 -13
  60. 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-B5FTAGFN.js";
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
- updateCard,
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-CRFCWD6V.js";
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-WGZ5AGOX.js";
63
+ } from "../../chunk-3CIMVISQ.js";
62
64
  import {
63
65
  RelayClient,
64
66
  RelayMessageSchema
65
- } from "../../chunk-C6KPAFCC.js";
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
- if (!cmdConfig.allowed_commands.includes(baseCommand)) {
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: "${baseCommand}". Allowed: ${cmdConfig.allowed_commands.join(", ")}`
984
+ error: `Command not allowed: "${commandToCheck}". Allowed: ${effectiveAllowed.join(", ")}`
930
985
  };
931
986
  }
932
987
  }
933
- const interpolatedCommand = safeInterpolateCommand2(cmdConfig.command, { params });
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-ZMTFZGJP.js");
1075
- const { registerConductorCard, CONDUCTOR_OWNER } = await import("../../card-RSGDCHCV.js");
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
- const result = await executeCapabilityRequest({
1260
- registryDb,
1261
- creditDb,
1262
- cardId,
1263
- skillId,
1264
- params,
1265
- requester,
1266
- escrowReceipt: receipt,
1267
- skillExecutor,
1268
- handlerUrl,
1269
- timeoutMs
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: randomUUID(),
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 randomUUID4 } from "crypto";
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 randomUUID3 } from "crypto";
2007
+ import { randomUUID as randomUUID4 } from "crypto";
1889
2008
 
1890
2009
  // src/hub-agent/job-queue.ts
1891
- import { randomUUID as randomUUID2 } from "crypto";
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 = randomUUID2();
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 = randomUUID3();
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: randomUUID4(),
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 randomUUID5 } from "crypto";
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: randomUUID5(),
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: randomUUID5()
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: "P2P Agent Capability Sharing Protocol \u2014 discover, publish, and exchange agent capabilities",
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') THEN 1 ELSE 0 END) as terminal_exec,
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
- 200: { type: "object", properties: { ok: { type: "boolean" }, id: { type: "string" } } },
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({ ok: true, id });
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
- COUNT(*) as total,
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 randomUUID6 } from "crypto";
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-RSGDCHCV.js");
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-WRN3HO73.js");
5440
- const { executeCapabilityRequest: executeCapabilityRequest2 } = await import("../../execute-4D4ITQCL.js");
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: randomUUID6(),
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-RSGDCHCV.js");
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 randomUUID8 } from "crypto";
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 randomUUID7 } from "crypto";
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: randomUUID7()
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:${randomUUID8()}`;
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: randomUUID8(),
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
- process.env["AGENTBNB_DIR"] = configDir;
6490
+ const workspaceDir = resolveWorkspaceDir();
6491
+ process.env["AGENTBNB_DIR"] = workspaceDir;
6149
6492
  process.stderr.write(
6150
- `[agentbnb] AGENTBNB_DIR not set \u2014 auto-configured to ${configDir} for child process isolation.
6493
+ `[agentbnb] AGENTBNB_DIR auto-configured to ${workspaceDir} for workspace isolation.
6151
6494
  `
6152
6495
  );
6153
- } else if (process.env["AGENTBNB_DIR"] !== configDir) {
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") {