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