agentbnb 3.1.0 → 3.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -39,6 +39,8 @@ var CapabilityCardSchema = z.object({
39
39
  * never transmitted beyond the local store.
40
40
  */
41
41
  _internal: z.record(z.unknown()).optional(),
42
+ /** Public gateway URL where this agent accepts requests. Populated on remote publish. */
43
+ gateway_url: z.string().url().optional(),
42
44
  metadata: z.object({
43
45
  apis_used: z.array(z.string()).optional(),
44
46
  avg_latency_ms: z.number().nonnegative().optional(),
@@ -103,6 +105,8 @@ var CapabilityCardV2Schema = z.object({
103
105
  * never transmitted beyond the local store.
104
106
  */
105
107
  _internal: z.record(z.unknown()).optional(),
108
+ /** Public gateway URL where this agent accepts requests. Populated on remote publish. */
109
+ gateway_url: z.string().url().optional(),
106
110
  created_at: z.string().datetime().optional(),
107
111
  updated_at: z.string().datetime().optional()
108
112
  });
@@ -479,6 +483,18 @@ function updateReputation(db, cardId, success, latencyMs) {
479
483
  `);
480
484
  stmt.run(JSON.stringify(updatedCard), now, cardId);
481
485
  }
486
+ function listCards(db, owner) {
487
+ let stmt;
488
+ let rows;
489
+ if (owner !== void 0) {
490
+ stmt = db.prepare("SELECT data FROM capability_cards WHERE owner = ?");
491
+ rows = stmt.all(owner);
492
+ } else {
493
+ stmt = db.prepare("SELECT data FROM capability_cards");
494
+ rows = stmt.all();
495
+ }
496
+ return rows.map((row) => JSON.parse(row.data));
497
+ }
482
498
 
483
499
  // src/registry/matcher.ts
484
500
  function searchCards(db, query, filters = {}) {
@@ -1978,6 +1994,22 @@ import { join as join3 } from "path";
1978
1994
  import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync, existsSync as existsSync2 } from "fs";
1979
1995
  import { homedir } from "os";
1980
1996
  import { join as join2 } from "path";
1997
+ function getConfigDir() {
1998
+ return process.env["AGENTBNB_DIR"] ?? join2(homedir(), ".agentbnb");
1999
+ }
2000
+ function getConfigPath() {
2001
+ return join2(getConfigDir(), "config.json");
2002
+ }
2003
+ function loadConfig() {
2004
+ const configPath = getConfigPath();
2005
+ if (!existsSync2(configPath)) return null;
2006
+ try {
2007
+ const raw = readFileSync2(configPath, "utf-8");
2008
+ return JSON.parse(raw);
2009
+ } catch {
2010
+ return null;
2011
+ }
2012
+ }
1981
2013
 
1982
2014
  // src/autonomy/auto-request.ts
1983
2015
  function minMaxNormalize(values) {
@@ -2507,64 +2539,536 @@ function createSignedEscrowReceipt(db, privateKey, publicKey, opts) {
2507
2539
  return { escrowId, receipt };
2508
2540
  }
2509
2541
 
2510
- // src/relay/types.ts
2542
+ // src/identity/identity.ts
2511
2543
  import { z as z4 } from "zod";
2512
- var RegisterMessageSchema = z4.object({
2513
- type: z4.literal("register"),
2544
+ import { createHash } from "crypto";
2545
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, existsSync as existsSync4, mkdirSync as mkdirSync3 } from "fs";
2546
+ import { join as join4 } from "path";
2547
+ var AgentIdentitySchema = z4.object({
2548
+ /** Deterministic ID derived from public key: sha256(hex).slice(0, 16). */
2549
+ agent_id: z4.string().min(1),
2550
+ /** Human-readable owner name (from config or init). */
2514
2551
  owner: z4.string().min(1),
2515
- token: z4.string().min(1),
2516
- card: z4.record(z4.unknown())
2552
+ /** Hex-encoded Ed25519 public key. */
2553
+ public_key: z4.string().min(1),
2554
+ /** ISO 8601 timestamp of identity creation. */
2555
+ created_at: z4.string().datetime(),
2556
+ /** Optional guarantor info if linked to a human. */
2557
+ guarantor: z4.object({
2558
+ github_login: z4.string().min(1),
2559
+ verified_at: z4.string().datetime()
2560
+ }).optional()
2561
+ });
2562
+ var AgentCertificateSchema = z4.object({
2563
+ identity: AgentIdentitySchema,
2564
+ /** ISO 8601 timestamp of certificate issuance. */
2565
+ issued_at: z4.string().datetime(),
2566
+ /** ISO 8601 timestamp of certificate expiry. */
2567
+ expires_at: z4.string().datetime(),
2568
+ /** Hex-encoded public key of the issuer (same as identity for self-signed). */
2569
+ issuer_public_key: z4.string().min(1),
2570
+ /** Base64url Ed25519 signature over { identity, issued_at, expires_at, issuer_public_key }. */
2571
+ signature: z4.string().min(1)
2572
+ });
2573
+ var IDENTITY_FILENAME = "identity.json";
2574
+ function deriveAgentId(publicKeyHex) {
2575
+ return createHash("sha256").update(publicKeyHex, "hex").digest("hex").slice(0, 16);
2576
+ }
2577
+ function createIdentity(configDir, owner) {
2578
+ if (!existsSync4(configDir)) {
2579
+ mkdirSync3(configDir, { recursive: true });
2580
+ }
2581
+ let keys;
2582
+ try {
2583
+ keys = loadKeyPair(configDir);
2584
+ } catch {
2585
+ keys = generateKeyPair();
2586
+ saveKeyPair(configDir, keys);
2587
+ }
2588
+ const publicKeyHex = keys.publicKey.toString("hex");
2589
+ const agentId = deriveAgentId(publicKeyHex);
2590
+ const identity = {
2591
+ agent_id: agentId,
2592
+ owner,
2593
+ public_key: publicKeyHex,
2594
+ created_at: (/* @__PURE__ */ new Date()).toISOString()
2595
+ };
2596
+ saveIdentity(configDir, identity);
2597
+ return identity;
2598
+ }
2599
+ function loadIdentity(configDir) {
2600
+ const filePath = join4(configDir, IDENTITY_FILENAME);
2601
+ if (!existsSync4(filePath)) return null;
2602
+ try {
2603
+ const raw = readFileSync4(filePath, "utf-8");
2604
+ return AgentIdentitySchema.parse(JSON.parse(raw));
2605
+ } catch {
2606
+ return null;
2607
+ }
2608
+ }
2609
+ function saveIdentity(configDir, identity) {
2610
+ if (!existsSync4(configDir)) {
2611
+ mkdirSync3(configDir, { recursive: true });
2612
+ }
2613
+ const filePath = join4(configDir, IDENTITY_FILENAME);
2614
+ writeFileSync4(filePath, JSON.stringify(identity, null, 2), "utf-8");
2615
+ }
2616
+ function issueAgentCertificate(identity, privateKey) {
2617
+ const issuedAt = (/* @__PURE__ */ new Date()).toISOString();
2618
+ const expiresAt = new Date(Date.now() + 365 * 24 * 60 * 60 * 1e3).toISOString();
2619
+ const payload = {
2620
+ identity,
2621
+ issued_at: issuedAt,
2622
+ expires_at: expiresAt,
2623
+ issuer_public_key: identity.public_key
2624
+ };
2625
+ const signature = signEscrowReceipt(payload, privateKey);
2626
+ return {
2627
+ identity,
2628
+ issued_at: issuedAt,
2629
+ expires_at: expiresAt,
2630
+ issuer_public_key: identity.public_key,
2631
+ signature
2632
+ };
2633
+ }
2634
+ function verifyAgentCertificate(cert) {
2635
+ if (new Date(cert.expires_at) < /* @__PURE__ */ new Date()) {
2636
+ return false;
2637
+ }
2638
+ const publicKeyHex = cert.issuer_public_key;
2639
+ const publicKeyBuf = Buffer.from(publicKeyHex, "hex");
2640
+ const payload = {
2641
+ identity: cert.identity,
2642
+ issued_at: cert.issued_at,
2643
+ expires_at: cert.expires_at,
2644
+ issuer_public_key: cert.issuer_public_key
2645
+ };
2646
+ return verifyEscrowReceipt(payload, cert.signature, publicKeyBuf);
2647
+ }
2648
+ function ensureIdentity(configDir, owner) {
2649
+ const existing = loadIdentity(configDir);
2650
+ if (existing) return existing;
2651
+ return createIdentity(configDir, owner);
2652
+ }
2653
+
2654
+ // src/sdk/consumer.ts
2655
+ var AgentBnBConsumer = class {
2656
+ configDir;
2657
+ identity = null;
2658
+ keys = null;
2659
+ creditDb = null;
2660
+ constructor(opts) {
2661
+ this.configDir = opts?.configDir ?? getConfigDir();
2662
+ }
2663
+ /**
2664
+ * Loads agent identity and keypair from disk.
2665
+ * Creates identity if none exists (uses owner from config.json or generates one).
2666
+ *
2667
+ * @returns The loaded AgentIdentity.
2668
+ * @throws {AgentBnBError} if keypair is missing and cannot be created.
2669
+ */
2670
+ authenticate() {
2671
+ const config = loadConfig();
2672
+ const owner = config?.owner ?? `agent-${Date.now().toString(36)}`;
2673
+ this.identity = ensureIdentity(this.configDir, owner);
2674
+ this.keys = loadKeyPair(this.configDir);
2675
+ return this.identity;
2676
+ }
2677
+ /**
2678
+ * Returns the cached identity. Throws if not yet authenticated.
2679
+ */
2680
+ getIdentity() {
2681
+ if (!this.identity) {
2682
+ throw new AgentBnBError("Not authenticated. Call authenticate() first.", "NOT_AUTHENTICATED");
2683
+ }
2684
+ return this.identity;
2685
+ }
2686
+ /**
2687
+ * Requests a capability from a remote agent with full escrow lifecycle.
2688
+ *
2689
+ * 1. Creates a signed escrow receipt (holds credits locally)
2690
+ * 2. Sends the request to the target gateway
2691
+ * 3. Settles escrow on success, releases on failure
2692
+ *
2693
+ * @param opts - Request options including target, card, credits, and params.
2694
+ * @returns The result from the capability execution.
2695
+ * @throws {AgentBnBError} on insufficient credits, network error, or RPC error.
2696
+ */
2697
+ async request(opts) {
2698
+ const identity = this.getIdentity();
2699
+ if (!this.keys) {
2700
+ throw new AgentBnBError("Keypair not loaded. Call authenticate() first.", "NOT_AUTHENTICATED");
2701
+ }
2702
+ const db = this.getCreditDb();
2703
+ const { escrowId, receipt } = createSignedEscrowReceipt(
2704
+ db,
2705
+ this.keys.privateKey,
2706
+ this.keys.publicKey,
2707
+ {
2708
+ owner: identity.owner,
2709
+ amount: opts.credits,
2710
+ cardId: opts.cardId,
2711
+ skillId: opts.skillId
2712
+ }
2713
+ );
2714
+ try {
2715
+ const result = await requestCapability({
2716
+ gatewayUrl: opts.gatewayUrl,
2717
+ token: opts.token,
2718
+ cardId: opts.cardId,
2719
+ params: opts.params,
2720
+ timeoutMs: opts.timeoutMs,
2721
+ escrowReceipt: receipt
2722
+ });
2723
+ settleRequesterEscrow(db, escrowId);
2724
+ return result;
2725
+ } catch (err) {
2726
+ releaseRequesterEscrow(db, escrowId);
2727
+ throw err;
2728
+ }
2729
+ }
2730
+ /**
2731
+ * Returns the current credit balance for this agent.
2732
+ */
2733
+ getBalance() {
2734
+ const identity = this.getIdentity();
2735
+ const db = this.getCreditDb();
2736
+ return getBalance(db, identity.owner);
2737
+ }
2738
+ /**
2739
+ * Returns basic reputation data from the local credit database.
2740
+ * Note: success_rate is computed from local request history only.
2741
+ */
2742
+ getReputation() {
2743
+ const identity = this.getIdentity();
2744
+ const db = this.getCreditDb();
2745
+ const stmt = db.prepare(`
2746
+ SELECT
2747
+ COUNT(*) as total,
2748
+ SUM(CASE WHEN status = 'settled' THEN 1 ELSE 0 END) as settled
2749
+ FROM credit_escrow
2750
+ WHERE owner = ?
2751
+ `);
2752
+ const row = stmt.get(identity.owner);
2753
+ const total = row?.total ?? 0;
2754
+ const settled = row?.settled ?? 0;
2755
+ return {
2756
+ success_rate: total > 0 ? settled / total : 1,
2757
+ total_requests: total
2758
+ };
2759
+ }
2760
+ /**
2761
+ * Closes the credit database connection. Call when done.
2762
+ */
2763
+ close() {
2764
+ if (this.creditDb) {
2765
+ this.creditDb.close();
2766
+ this.creditDb = null;
2767
+ }
2768
+ }
2769
+ /** Lazily opens and caches the credit database. */
2770
+ getCreditDb() {
2771
+ if (!this.creditDb) {
2772
+ const config = loadConfig();
2773
+ const creditDbPath = config?.credit_db_path ?? `${this.configDir}/credit.db`;
2774
+ this.creditDb = openCreditDb(creditDbPath);
2775
+ }
2776
+ return this.creditDb;
2777
+ }
2778
+ };
2779
+
2780
+ // src/sdk/provider.ts
2781
+ var AgentBnBProvider = class {
2782
+ configDir;
2783
+ identity = null;
2784
+ registryDb = null;
2785
+ creditDb = null;
2786
+ gateway = null;
2787
+ constructor(opts) {
2788
+ this.configDir = opts?.configDir ?? getConfigDir();
2789
+ }
2790
+ /**
2791
+ * Loads agent identity from disk.
2792
+ * Creates identity if none exists.
2793
+ *
2794
+ * @returns The loaded AgentIdentity.
2795
+ */
2796
+ authenticate() {
2797
+ const config = loadConfig();
2798
+ const owner = config?.owner ?? `agent-${Date.now().toString(36)}`;
2799
+ this.identity = ensureIdentity(this.configDir, owner);
2800
+ return this.identity;
2801
+ }
2802
+ /**
2803
+ * Returns the cached identity. Throws if not yet authenticated.
2804
+ */
2805
+ getIdentity() {
2806
+ if (!this.identity) {
2807
+ throw new AgentBnBError("Not authenticated. Call authenticate() first.", "NOT_AUTHENTICATED");
2808
+ }
2809
+ return this.identity;
2810
+ }
2811
+ /**
2812
+ * Starts the gateway server to share capabilities.
2813
+ *
2814
+ * @param opts - Optional port and host configuration.
2815
+ * @returns Context with the gateway server and port.
2816
+ */
2817
+ async startSharing(opts) {
2818
+ this.getIdentity();
2819
+ const config = loadConfig();
2820
+ const port = opts?.port ?? config?.gateway_port ?? 7700;
2821
+ const host = opts?.host ?? "0.0.0.0";
2822
+ const registryDb = this.getRegistryDb();
2823
+ const creditDb = this.getCreditDb();
2824
+ const token = config?.token ?? "";
2825
+ const gateway = createGatewayServer({
2826
+ registryDb,
2827
+ creditDb,
2828
+ tokens: [token],
2829
+ handlerUrl: `http://localhost:${port}`,
2830
+ silent: true
2831
+ });
2832
+ await gateway.listen({ port, host });
2833
+ this.gateway = gateway;
2834
+ return { gateway, port };
2835
+ }
2836
+ /**
2837
+ * Stops the gateway server.
2838
+ */
2839
+ async stopSharing() {
2840
+ if (this.gateway) {
2841
+ await this.gateway.close();
2842
+ this.gateway = null;
2843
+ }
2844
+ }
2845
+ /**
2846
+ * Returns all capability cards owned by this agent.
2847
+ */
2848
+ listCapabilities() {
2849
+ const identity = this.getIdentity();
2850
+ const db = this.getRegistryDb();
2851
+ return listCards(db, identity.owner);
2852
+ }
2853
+ /**
2854
+ * Returns the current credit balance for this agent.
2855
+ */
2856
+ getBalance() {
2857
+ const identity = this.getIdentity();
2858
+ const db = this.getCreditDb();
2859
+ return getBalance(db, identity.owner);
2860
+ }
2861
+ /**
2862
+ * Closes all database connections and stops the gateway. Call when done.
2863
+ */
2864
+ async close() {
2865
+ await this.stopSharing();
2866
+ if (this.registryDb) {
2867
+ this.registryDb.close();
2868
+ this.registryDb = null;
2869
+ }
2870
+ if (this.creditDb) {
2871
+ this.creditDb.close();
2872
+ this.creditDb = null;
2873
+ }
2874
+ }
2875
+ /** Lazily opens and caches the registry database. */
2876
+ getRegistryDb() {
2877
+ if (!this.registryDb) {
2878
+ const config = loadConfig();
2879
+ const dbPath = config?.db_path ?? `${this.configDir}/registry.db`;
2880
+ this.registryDb = openDatabase(dbPath);
2881
+ }
2882
+ return this.registryDb;
2883
+ }
2884
+ /** Lazily opens and caches the credit database. */
2885
+ getCreditDb() {
2886
+ if (!this.creditDb) {
2887
+ const config = loadConfig();
2888
+ const creditDbPath = config?.credit_db_path ?? `${this.configDir}/credit.db`;
2889
+ this.creditDb = openCreditDb(creditDbPath);
2890
+ }
2891
+ return this.creditDb;
2892
+ }
2893
+ };
2894
+
2895
+ // src/identity/guarantor.ts
2896
+ import { z as z5 } from "zod";
2897
+ import { randomUUID as randomUUID9 } from "crypto";
2898
+ var MAX_AGENTS_PER_GUARANTOR = 10;
2899
+ var GUARANTOR_CREDIT_POOL = 50;
2900
+ var GuarantorRecordSchema = z5.object({
2901
+ id: z5.string().uuid(),
2902
+ github_login: z5.string().min(1),
2903
+ agent_count: z5.number().int().nonnegative(),
2904
+ credit_pool: z5.number().int().nonnegative(),
2905
+ created_at: z5.string().datetime()
2906
+ });
2907
+ var GUARANTOR_SCHEMA = `
2908
+ CREATE TABLE IF NOT EXISTS guarantors (
2909
+ id TEXT PRIMARY KEY,
2910
+ github_login TEXT UNIQUE NOT NULL,
2911
+ agent_count INTEGER NOT NULL DEFAULT 0,
2912
+ credit_pool INTEGER NOT NULL DEFAULT ${GUARANTOR_CREDIT_POOL},
2913
+ created_at TEXT NOT NULL
2914
+ );
2915
+
2916
+ CREATE TABLE IF NOT EXISTS agent_guarantors (
2917
+ agent_id TEXT PRIMARY KEY,
2918
+ guarantor_id TEXT NOT NULL,
2919
+ linked_at TEXT NOT NULL,
2920
+ FOREIGN KEY (guarantor_id) REFERENCES guarantors(id)
2921
+ );
2922
+ `;
2923
+ function ensureGuarantorTables(db) {
2924
+ db.exec(GUARANTOR_SCHEMA);
2925
+ }
2926
+ function registerGuarantor(db, githubLogin) {
2927
+ ensureGuarantorTables(db);
2928
+ const existing = db.prepare("SELECT * FROM guarantors WHERE github_login = ?").get(githubLogin);
2929
+ if (existing) {
2930
+ throw new AgentBnBError(
2931
+ `Guarantor already registered: ${githubLogin}`,
2932
+ "GUARANTOR_EXISTS"
2933
+ );
2934
+ }
2935
+ const record = {
2936
+ id: randomUUID9(),
2937
+ github_login: githubLogin,
2938
+ agent_count: 0,
2939
+ credit_pool: GUARANTOR_CREDIT_POOL,
2940
+ created_at: (/* @__PURE__ */ new Date()).toISOString()
2941
+ };
2942
+ db.prepare(
2943
+ "INSERT INTO guarantors (id, github_login, agent_count, credit_pool, created_at) VALUES (?, ?, ?, ?, ?)"
2944
+ ).run(record.id, record.github_login, record.agent_count, record.credit_pool, record.created_at);
2945
+ return record;
2946
+ }
2947
+ function linkAgentToGuarantor(db, agentId, githubLogin) {
2948
+ ensureGuarantorTables(db);
2949
+ const guarantor = db.prepare("SELECT * FROM guarantors WHERE github_login = ?").get(githubLogin);
2950
+ if (!guarantor) {
2951
+ throw new AgentBnBError(
2952
+ `Guarantor not found: ${githubLogin}`,
2953
+ "GUARANTOR_NOT_FOUND"
2954
+ );
2955
+ }
2956
+ if (guarantor["agent_count"] >= MAX_AGENTS_PER_GUARANTOR) {
2957
+ throw new AgentBnBError(
2958
+ `Maximum agents per guarantor reached (${MAX_AGENTS_PER_GUARANTOR})`,
2959
+ "MAX_AGENTS_EXCEEDED"
2960
+ );
2961
+ }
2962
+ const existingLink = db.prepare("SELECT * FROM agent_guarantors WHERE agent_id = ?").get(agentId);
2963
+ if (existingLink) {
2964
+ throw new AgentBnBError(
2965
+ `Agent ${agentId} is already linked to a guarantor`,
2966
+ "AGENT_ALREADY_LINKED"
2967
+ );
2968
+ }
2969
+ db.transaction(() => {
2970
+ db.prepare("INSERT INTO agent_guarantors (agent_id, guarantor_id, linked_at) VALUES (?, ?, ?)").run(
2971
+ agentId,
2972
+ guarantor["id"],
2973
+ (/* @__PURE__ */ new Date()).toISOString()
2974
+ );
2975
+ db.prepare("UPDATE guarantors SET agent_count = agent_count + 1 WHERE id = ?").run(guarantor["id"]);
2976
+ })();
2977
+ return getGuarantor(db, githubLogin);
2978
+ }
2979
+ function getGuarantor(db, githubLogin) {
2980
+ ensureGuarantorTables(db);
2981
+ const row = db.prepare("SELECT * FROM guarantors WHERE github_login = ?").get(githubLogin);
2982
+ if (!row) return null;
2983
+ return {
2984
+ id: row["id"],
2985
+ github_login: row["github_login"],
2986
+ agent_count: row["agent_count"],
2987
+ credit_pool: row["credit_pool"],
2988
+ created_at: row["created_at"]
2989
+ };
2990
+ }
2991
+ function getAgentGuarantor(db, agentId) {
2992
+ ensureGuarantorTables(db);
2993
+ const link = db.prepare(
2994
+ `SELECT g.* FROM guarantors g
2995
+ JOIN agent_guarantors ag ON ag.guarantor_id = g.id
2996
+ WHERE ag.agent_id = ?`
2997
+ ).get(agentId);
2998
+ if (!link) return null;
2999
+ return {
3000
+ id: link["id"],
3001
+ github_login: link["github_login"],
3002
+ agent_count: link["agent_count"],
3003
+ credit_pool: link["credit_pool"],
3004
+ created_at: link["created_at"]
3005
+ };
3006
+ }
3007
+ function initiateGithubAuth() {
3008
+ return {
3009
+ auth_url: "https://github.com/login/oauth/authorize?client_id=PLACEHOLDER&scope=read:user",
3010
+ state: randomUUID9()
3011
+ };
3012
+ }
3013
+
3014
+ // src/relay/types.ts
3015
+ import { z as z6 } from "zod";
3016
+ var RegisterMessageSchema = z6.object({
3017
+ type: z6.literal("register"),
3018
+ owner: z6.string().min(1),
3019
+ token: z6.string().min(1),
3020
+ card: z6.record(z6.unknown())
2517
3021
  // CapabilityCard (validated separately)
2518
3022
  });
2519
- var RegisteredMessageSchema = z4.object({
2520
- type: z4.literal("registered"),
2521
- agent_id: z4.string()
3023
+ var RegisteredMessageSchema = z6.object({
3024
+ type: z6.literal("registered"),
3025
+ agent_id: z6.string()
2522
3026
  });
2523
- var RelayRequestMessageSchema = z4.object({
2524
- type: z4.literal("relay_request"),
2525
- id: z4.string().uuid(),
2526
- target_owner: z4.string().min(1),
2527
- card_id: z4.string(),
2528
- skill_id: z4.string().optional(),
2529
- params: z4.record(z4.unknown()).default({}),
2530
- requester: z4.string().optional(),
2531
- escrow_receipt: z4.record(z4.unknown()).optional()
3027
+ var RelayRequestMessageSchema = z6.object({
3028
+ type: z6.literal("relay_request"),
3029
+ id: z6.string().uuid(),
3030
+ target_owner: z6.string().min(1),
3031
+ card_id: z6.string(),
3032
+ skill_id: z6.string().optional(),
3033
+ params: z6.record(z6.unknown()).default({}),
3034
+ requester: z6.string().optional(),
3035
+ escrow_receipt: z6.record(z6.unknown()).optional()
2532
3036
  });
2533
- var IncomingRequestMessageSchema = z4.object({
2534
- type: z4.literal("incoming_request"),
2535
- id: z4.string().uuid(),
2536
- from_owner: z4.string().min(1),
2537
- card_id: z4.string(),
2538
- skill_id: z4.string().optional(),
2539
- params: z4.record(z4.unknown()).default({}),
2540
- requester: z4.string().optional(),
2541
- escrow_receipt: z4.record(z4.unknown()).optional()
3037
+ var IncomingRequestMessageSchema = z6.object({
3038
+ type: z6.literal("incoming_request"),
3039
+ id: z6.string().uuid(),
3040
+ from_owner: z6.string().min(1),
3041
+ card_id: z6.string(),
3042
+ skill_id: z6.string().optional(),
3043
+ params: z6.record(z6.unknown()).default({}),
3044
+ requester: z6.string().optional(),
3045
+ escrow_receipt: z6.record(z6.unknown()).optional()
2542
3046
  });
2543
- var RelayResponseMessageSchema = z4.object({
2544
- type: z4.literal("relay_response"),
2545
- id: z4.string().uuid(),
2546
- result: z4.unknown().optional(),
2547
- error: z4.object({
2548
- code: z4.number(),
2549
- message: z4.string()
3047
+ var RelayResponseMessageSchema = z6.object({
3048
+ type: z6.literal("relay_response"),
3049
+ id: z6.string().uuid(),
3050
+ result: z6.unknown().optional(),
3051
+ error: z6.object({
3052
+ code: z6.number(),
3053
+ message: z6.string()
2550
3054
  }).optional()
2551
3055
  });
2552
- var ResponseMessageSchema = z4.object({
2553
- type: z4.literal("response"),
2554
- id: z4.string().uuid(),
2555
- result: z4.unknown().optional(),
2556
- error: z4.object({
2557
- code: z4.number(),
2558
- message: z4.string()
3056
+ var ResponseMessageSchema = z6.object({
3057
+ type: z6.literal("response"),
3058
+ id: z6.string().uuid(),
3059
+ result: z6.unknown().optional(),
3060
+ error: z6.object({
3061
+ code: z6.number(),
3062
+ message: z6.string()
2559
3063
  }).optional()
2560
3064
  });
2561
- var ErrorMessageSchema = z4.object({
2562
- type: z4.literal("error"),
2563
- code: z4.string(),
2564
- message: z4.string(),
2565
- request_id: z4.string().optional()
3065
+ var ErrorMessageSchema = z6.object({
3066
+ type: z6.literal("error"),
3067
+ code: z6.string(),
3068
+ message: z6.string(),
3069
+ request_id: z6.string().optional()
2566
3070
  });
2567
- var RelayMessageSchema = z4.discriminatedUnion("type", [
3071
+ var RelayMessageSchema = z6.discriminatedUnion("type", [
2568
3072
  RegisterMessageSchema,
2569
3073
  RegisteredMessageSchema,
2570
3074
  RelayRequestMessageSchema,
@@ -2575,7 +3079,7 @@ var RelayMessageSchema = z4.discriminatedUnion("type", [
2575
3079
  ]);
2576
3080
 
2577
3081
  // src/relay/websocket-relay.ts
2578
- import { randomUUID as randomUUID9 } from "crypto";
3082
+ import { randomUUID as randomUUID10 } from "crypto";
2579
3083
  var RATE_LIMIT_MAX = 60;
2580
3084
  var RATE_LIMIT_WINDOW_MS = 6e4;
2581
3085
  var RELAY_TIMEOUT_MS = 3e4;
@@ -2647,7 +3151,7 @@ function registerWebSocketRelay(server, db) {
2647
3151
  function logAgentJoined(owner, cardName, cardId) {
2648
3152
  try {
2649
3153
  insertRequestLog(db, {
2650
- id: randomUUID9(),
3154
+ id: randomUUID10(),
2651
3155
  card_id: cardId,
2652
3156
  card_name: cardName,
2653
3157
  requester: owner,
@@ -2747,7 +3251,8 @@ function registerWebSocketRelay(server, db) {
2747
3251
  }
2748
3252
  }
2749
3253
  }
2750
- server.get("/ws", { websocket: true }, (socket) => {
3254
+ server.get("/ws", { websocket: true }, (rawSocket, _request) => {
3255
+ const socket = rawSocket;
2751
3256
  let registeredOwner;
2752
3257
  socket.on("message", (raw) => {
2753
3258
  let data;
@@ -2819,7 +3324,7 @@ function registerWebSocketRelay(server, db) {
2819
3324
 
2820
3325
  // src/relay/websocket-client.ts
2821
3326
  import WebSocket from "ws";
2822
- import { randomUUID as randomUUID10 } from "crypto";
3327
+ import { randomUUID as randomUUID11 } from "crypto";
2823
3328
  var RelayClient = class {
2824
3329
  ws = null;
2825
3330
  opts;
@@ -2915,7 +3420,7 @@ var RelayClient = class {
2915
3420
  if (!this.ws || this.ws.readyState !== WebSocket.OPEN || !this.registered) {
2916
3421
  throw new Error("Not connected to registry relay");
2917
3422
  }
2918
- const id = randomUUID10();
3423
+ const id = randomUUID11();
2919
3424
  const timeoutMs = opts.timeoutMs ?? 3e4;
2920
3425
  return new Promise((resolve, reject) => {
2921
3426
  const timeout = setTimeout(() => {
@@ -3085,7 +3590,171 @@ var RelayClient = class {
3085
3590
  }, delay);
3086
3591
  }
3087
3592
  };
3593
+
3594
+ // src/onboarding/index.ts
3595
+ import { randomUUID as randomUUID13 } from "crypto";
3596
+ import { existsSync as existsSync5, readFileSync as readFileSync5 } from "fs";
3597
+ import { join as join5 } from "path";
3598
+
3599
+ // src/cli/onboarding.ts
3600
+ import { randomUUID as randomUUID12 } from "crypto";
3601
+ import { createConnection } from "net";
3602
+ var KNOWN_API_KEYS = [
3603
+ "OPENAI_API_KEY",
3604
+ "ANTHROPIC_API_KEY",
3605
+ "ELEVENLABS_API_KEY",
3606
+ "KLING_API_KEY",
3607
+ "STABILITY_API_KEY",
3608
+ "REPLICATE_API_TOKEN",
3609
+ "GOOGLE_API_KEY",
3610
+ "AZURE_OPENAI_API_KEY",
3611
+ "COHERE_API_KEY",
3612
+ "MISTRAL_API_KEY"
3613
+ ];
3614
+ function detectApiKeys(knownKeys) {
3615
+ return knownKeys.filter((key) => key in process.env);
3616
+ }
3617
+
3618
+ // src/onboarding/capability-templates.ts
3619
+ var API_PATTERNS = [
3620
+ {
3621
+ pattern: /openai|gpt-4|gpt-3|chatgpt|dall-e/i,
3622
+ capability: { key: "openai", name: "OpenAI Text Generation", category: "Text Gen", credits_per_call: 3, tags: ["llm", "text", "generation"] }
3623
+ },
3624
+ {
3625
+ pattern: /elevenlabs|eleven.?labs/i,
3626
+ capability: { key: "elevenlabs", name: "ElevenLabs TTS", category: "TTS", credits_per_call: 5, tags: ["tts", "audio", "voice"] }
3627
+ },
3628
+ {
3629
+ pattern: /anthropic|claude/i,
3630
+ capability: { key: "anthropic", name: "Anthropic Claude", category: "Text Gen", credits_per_call: 3, tags: ["llm", "text", "generation"] }
3631
+ },
3632
+ {
3633
+ pattern: /recraft/i,
3634
+ capability: { key: "recraft", name: "Recraft V4 Image Gen", category: "Image Gen", credits_per_call: 8, tags: ["image", "generation", "design"] }
3635
+ },
3636
+ {
3637
+ pattern: /kling/i,
3638
+ capability: { key: "kling", name: "Kling AI Video Gen", category: "Video Gen", credits_per_call: 10, tags: ["video", "generation"] }
3639
+ },
3640
+ {
3641
+ pattern: /stable.?diffusion|sdxl|comfyui/i,
3642
+ capability: { key: "stable-diffusion", name: "Stable Diffusion Image Gen", category: "Image Gen", credits_per_call: 6, tags: ["image", "generation", "diffusion"] }
3643
+ },
3644
+ {
3645
+ pattern: /whisper|speech.?to.?text|stt/i,
3646
+ capability: { key: "whisper", name: "Whisper Speech-to-Text", category: "STT", credits_per_call: 3, tags: ["stt", "audio", "transcription"] }
3647
+ },
3648
+ {
3649
+ pattern: /puppeteer|playwright|selenium/i,
3650
+ capability: { key: "puppeteer", name: "Web Scraping & Automation", category: "Web Scraping", credits_per_call: 2, tags: ["scraping", "automation", "browser"] }
3651
+ },
3652
+ {
3653
+ pattern: /ffmpeg/i,
3654
+ capability: { key: "ffmpeg", name: "FFmpeg Media Processing", category: "Media Processing", credits_per_call: 3, tags: ["media", "audio", "video", "processing"] }
3655
+ },
3656
+ {
3657
+ pattern: /tesseract|ocr/i,
3658
+ capability: { key: "tesseract", name: "OCR Text Extraction", category: "OCR", credits_per_call: 4, tags: ["ocr", "text", "extraction"] }
3659
+ }
3660
+ ];
3661
+ var INTERACTIVE_TEMPLATES = [
3662
+ { key: "openai", name: "Text Generation (GPT-4o / Claude / Gemini)", category: "Text Gen", credits_per_call: 3, tags: ["llm", "text", "generation"] },
3663
+ { key: "image-gen", name: "Image Generation (DALL-E / Recraft / Stable Diffusion)", category: "Image Gen", credits_per_call: 8, tags: ["image", "generation"] },
3664
+ { key: "tts", name: "TTS / Voice (ElevenLabs / Google TTS)", category: "TTS", credits_per_call: 5, tags: ["tts", "audio", "voice"] },
3665
+ { key: "video-gen", name: "Video Generation (Kling / Runway)", category: "Video Gen", credits_per_call: 10, tags: ["video", "generation"] },
3666
+ { key: "code-review", name: "Code Review / Analysis", category: "Code", credits_per_call: 3, tags: ["code", "review", "analysis"] },
3667
+ { key: "scraping", name: "Web Scraping / Data Extraction", category: "Web Scraping", credits_per_call: 2, tags: ["scraping", "data", "extraction"] },
3668
+ { key: "translation", name: "Translation", category: "Translation", credits_per_call: 3, tags: ["translation", "language", "text"] },
3669
+ { key: "custom", name: "Custom (describe it)", category: "Custom", credits_per_call: 5, tags: ["custom"] }
3670
+ ];
3671
+
3672
+ // src/onboarding/detect-from-docs.ts
3673
+ function detectFromDocs(content) {
3674
+ if (!content || content.trim().length === 0) {
3675
+ return [];
3676
+ }
3677
+ const seen = /* @__PURE__ */ new Set();
3678
+ const results = [];
3679
+ for (const entry of API_PATTERNS) {
3680
+ if (entry.pattern.test(content) && !seen.has(entry.capability.key)) {
3681
+ seen.add(entry.capability.key);
3682
+ results.push({ ...entry.capability });
3683
+ }
3684
+ }
3685
+ return results;
3686
+ }
3687
+
3688
+ // src/onboarding/interactive.ts
3689
+ import { createInterface } from "readline";
3690
+
3691
+ // src/onboarding/index.ts
3692
+ var DOC_FILES = ["SOUL.md", "CLAUDE.md", "AGENTS.md", "README.md"];
3693
+ function detectCapabilities(opts = {}) {
3694
+ const cwd = opts.cwd ?? process.cwd();
3695
+ if (opts.fromFile) {
3696
+ const filePath = opts.fromFile.startsWith("/") ? opts.fromFile : join5(cwd, opts.fromFile);
3697
+ if (existsSync5(filePath)) {
3698
+ const content = readFileSync5(filePath, "utf-8");
3699
+ const capabilities = detectFromDocs(content);
3700
+ if (capabilities.length > 0) {
3701
+ return { source: "docs", capabilities, sourceFile: filePath };
3702
+ }
3703
+ }
3704
+ return { source: "none", capabilities: [] };
3705
+ }
3706
+ for (const fileName of DOC_FILES) {
3707
+ const filePath = join5(cwd, fileName);
3708
+ if (!existsSync5(filePath)) continue;
3709
+ const content = readFileSync5(filePath, "utf-8");
3710
+ if (fileName === "SOUL.md") {
3711
+ return { source: "soul", capabilities: [], soulContent: content, sourceFile: filePath };
3712
+ }
3713
+ const capabilities = detectFromDocs(content);
3714
+ if (capabilities.length > 0) {
3715
+ return { source: "docs", capabilities, sourceFile: filePath };
3716
+ }
3717
+ }
3718
+ const envKeys = detectApiKeys(KNOWN_API_KEYS);
3719
+ if (envKeys.length > 0) {
3720
+ return { source: "env", capabilities: [], envKeys };
3721
+ }
3722
+ return { source: "none", capabilities: [] };
3723
+ }
3724
+ function capabilitiesToV2Card(capabilities, owner, agentName) {
3725
+ const now = (/* @__PURE__ */ new Date()).toISOString();
3726
+ const skills = capabilities.map((cap) => ({
3727
+ id: cap.key,
3728
+ name: cap.name,
3729
+ description: `${cap.name} capability \u2014 ${cap.category}`,
3730
+ level: 1,
3731
+ category: cap.category.toLowerCase().replace(/\s+/g, "_"),
3732
+ inputs: [{ name: "input", type: "text", required: true }],
3733
+ outputs: [{ name: "output", type: "text", required: true }],
3734
+ pricing: { credits_per_call: cap.credits_per_call },
3735
+ availability: { online: true },
3736
+ metadata: {
3737
+ tags: cap.tags
3738
+ }
3739
+ }));
3740
+ const card = {
3741
+ spec_version: "2.0",
3742
+ id: randomUUID13(),
3743
+ owner,
3744
+ agent_name: agentName ?? owner,
3745
+ skills,
3746
+ availability: { online: true },
3747
+ created_at: now,
3748
+ updated_at: now
3749
+ };
3750
+ return CapabilityCardV2Schema.parse(card);
3751
+ }
3088
3752
  export {
3753
+ API_PATTERNS,
3754
+ AgentBnBConsumer,
3755
+ AgentBnBProvider,
3756
+ AgentCertificateSchema,
3757
+ AgentIdentitySchema,
3089
3758
  ApiExecutor,
3090
3759
  ApiSkillConfigSchema,
3091
3760
  BudgetController,
@@ -3096,6 +3765,10 @@ export {
3096
3765
  ConductorMode,
3097
3766
  ConductorSkillConfigSchema,
3098
3767
  EscrowReceiptSchema,
3768
+ GUARANTOR_CREDIT_POOL,
3769
+ GuarantorRecordSchema,
3770
+ INTERACTIVE_TEMPLATES,
3771
+ MAX_AGENTS_PER_GUARANTOR,
3099
3772
  ORCHESTRATION_FEE,
3100
3773
  OpenClawBridge,
3101
3774
  OpenClawSkillConfigSchema,
@@ -3110,19 +3783,31 @@ export {
3110
3783
  applyInputMapping,
3111
3784
  buildAuthHeaders,
3112
3785
  buildConductorCard,
3786
+ capabilitiesToV2Card,
3113
3787
  createGatewayServer,
3788
+ createIdentity,
3114
3789
  createSignedEscrowReceipt,
3115
3790
  createSkillExecutor,
3116
3791
  decompose,
3792
+ deriveAgentId,
3793
+ detectCapabilities,
3794
+ detectFromDocs,
3795
+ ensureIdentity,
3117
3796
  executeCapabilityRequest,
3118
3797
  expandEnvVars,
3119
3798
  extractByPath,
3120
3799
  generateKeyPair,
3800
+ getAgentGuarantor,
3121
3801
  getBalance,
3122
3802
  getCard,
3803
+ getGuarantor,
3804
+ initiateGithubAuth,
3123
3805
  insertCard,
3124
3806
  interpolate,
3125
3807
  interpolateObject,
3808
+ issueAgentCertificate,
3809
+ linkAgentToGuarantor,
3810
+ loadIdentity,
3126
3811
  loadKeyPair,
3127
3812
  matchSubTasks,
3128
3813
  openCreditDb,
@@ -3130,14 +3815,17 @@ export {
3130
3815
  orchestrate,
3131
3816
  parseSkillsFile,
3132
3817
  registerConductorCard,
3818
+ registerGuarantor,
3133
3819
  registerWebSocketRelay,
3134
3820
  releaseRequesterEscrow,
3135
3821
  requestViaRelay,
3136
3822
  resolvePath,
3823
+ saveIdentity,
3137
3824
  saveKeyPair,
3138
3825
  searchCards,
3139
3826
  settleProviderEarning,
3140
3827
  settleRequesterEscrow,
3141
3828
  signEscrowReceipt,
3829
+ verifyAgentCertificate,
3142
3830
  verifyEscrowReceipt
3143
3831
  };