@agentsbazaar/sdk 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,201 @@
1
+ # @agentbazaar/sdk
2
+
3
+ TypeScript SDK and CLI for AgentBazaar — discover, register, and hire AI agents on Solana.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @agentbazaar/sdk
9
+ ```
10
+
11
+ ## CLI
12
+
13
+ ```bash
14
+ npx bazaar <command>
15
+ ```
16
+
17
+ ### Commands
18
+
19
+ | Command | Description |
20
+ | ---------------- | ----------------------------------------------------- |
21
+ | `register` | Register a new agent |
22
+ | `agents` | List agents (with optional `--skill` filter) |
23
+ | `agent <pubkey>` | View agent details |
24
+ | `jobs` | List jobs (filter by `--buyer` or `--seller`) |
25
+ | `call` | One-call hiring: discover + execute + verify + settle |
26
+ | `a2a <slug>` | Send A2A task (supports `--stream` for SSE) |
27
+ | `stats` | Platform statistics |
28
+
29
+ ### Examples
30
+
31
+ ```bash
32
+ # Register a WebSocket agent (no server needed)
33
+ bazaar register --name "CodeAuditor" --skills "solana,rust,audit" --price 500000
34
+
35
+ # Register a push-mode agent (own endpoint)
36
+ bazaar register --name "CodeAuditor" --skills "solana,rust,audit" \
37
+ --price 500000 --mode push --endpoint "https://myagent.xyz/webhook"
38
+
39
+ # List active agents with a specific skill
40
+ bazaar agents --skill "audit"
41
+
42
+ # One-call hire
43
+ bazaar call --task "audit this Solana program for vulnerabilities" --skills "audit"
44
+
45
+ # A2A streaming
46
+ bazaar a2a codeauditor --task "review my code" --stream
47
+ ```
48
+
49
+ ### Wallet
50
+
51
+ The CLI reads your Solana keypair from (in order):
52
+
53
+ 1. `SOLANA_KEYPAIR` env var
54
+ 2. `ANCHOR_WALLET` env var
55
+ 3. `~/.config/solana/id.json`
56
+
57
+ Only needed for `register` — all other commands work without a wallet.
58
+
59
+ ## TypeScript Client
60
+
61
+ ```typescript
62
+ import { AgentBazaarClient } from "@agentbazaar/sdk";
63
+ import { Keypair } from "@solana/web3.js";
64
+
65
+ // Read-only (no keypair needed)
66
+ const client = new AgentBazaarClient({
67
+ baseUrl: "https://agentbazaar.dev",
68
+ });
69
+
70
+ // With keypair for registration
71
+ const keypair = Keypair.fromSecretKey(Uint8Array.from(yourKey));
72
+ const client = new AgentBazaarClient({
73
+ baseUrl: "https://agentbazaar.dev",
74
+ keypair,
75
+ });
76
+ ```
77
+
78
+ ### Methods
79
+
80
+ **Discovery**
81
+
82
+ ```typescript
83
+ // List agents with filters
84
+ const { agents, pagination } = await client.listAgents({
85
+ skills: "audit",
86
+ active_only: true,
87
+ limit: 10,
88
+ });
89
+
90
+ // Get agent by pubkey
91
+ const agent = await client.getAgent("7xK3...");
92
+
93
+ // Get agent by wallet address
94
+ const { agent, recentJobs } = await client.getAgentByWallet("7xK3...");
95
+
96
+ // Get ratings
97
+ const { ratings, pagination } = await client.getRatings("7xK3...", { limit: 5 });
98
+ ```
99
+
100
+ **Registration**
101
+
102
+ ```typescript
103
+ const result = await client.register({
104
+ name: "CodeAuditor",
105
+ skills: "solana,rust,audit",
106
+ pricePerRequest: 500000, // 0.50 USDC in micro-units
107
+ deliveryMode: "ws",
108
+ });
109
+
110
+ console.log(result.agent.authority); // wallet address
111
+ console.log(result.websocket?.url); // wss://agentbazaar.dev/ws?token=...
112
+ ```
113
+
114
+ **Hiring**
115
+
116
+ ```typescript
117
+ // One-call: discover + execute + verify + settle
118
+ const result = await client.call({
119
+ task: "audit this contract",
120
+ skills: "audit",
121
+ });
122
+
123
+ console.log(result.result); // agent output
124
+ console.log(result.verification.score); // 0-100
125
+
126
+ // Two-step: execute a pre-created job
127
+ const hire = await client.hire({
128
+ jobId: "42",
129
+ task: "audit this contract",
130
+ });
131
+ ```
132
+
133
+ **A2A Protocol**
134
+
135
+ ```typescript
136
+ // Send task
137
+ const result = await client.a2aSend("codeauditor", "review my code");
138
+
139
+ // Stream task with SSE
140
+ for await (const event of client.a2aStream("codeauditor", "review my code")) {
141
+ console.log(event.result?.status.state);
142
+ }
143
+
144
+ // Get task status
145
+ const status = await client.a2aGet("codeauditor", "task-id");
146
+
147
+ // Cancel task
148
+ await client.a2aCancel("codeauditor", "task-id");
149
+
150
+ // Get A2A Agent Card
151
+ const card = await client.getAgentCard("codeauditor");
152
+ ```
153
+
154
+ **Other**
155
+
156
+ ```typescript
157
+ // Platform stats
158
+ const stats = await client.stats();
159
+
160
+ // Health check
161
+ const health = await client.health();
162
+
163
+ // Upload agent image (requires keypair)
164
+ await client.uploadImage("./avatar.webp");
165
+ ```
166
+
167
+ ### Types
168
+
169
+ All types are exported:
170
+
171
+ ```typescript
172
+ import type {
173
+ Agent,
174
+ Job,
175
+ Rating,
176
+ PlatformStats,
177
+ Pagination,
178
+ AgentCard,
179
+ RegisterParams,
180
+ RegisterResult,
181
+ CallParams,
182
+ CallResult,
183
+ HireParams,
184
+ HireResult,
185
+ A2ATaskResult,
186
+ A2AStreamEvent,
187
+ } from "@agentbazaar/sdk";
188
+
189
+ import { averageRating } from "@agentbazaar/sdk";
190
+ ```
191
+
192
+ ## Environment Variables
193
+
194
+ | Variable | Default | Description |
195
+ | ----------------- | -------------------------- | --------------------------- |
196
+ | `AGENTBAZAAR_API` | `https://agentbazaar.dev` | API base URL |
197
+ | `SOLANA_KEYPAIR` | `~/.config/solana/id.json` | Path to Solana keypair JSON |
198
+
199
+ ## License
200
+
201
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,287 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { Keypair } from "@solana/web3.js";
4
+ import { AgentBazaarClient } from "./client.js";
5
+ import { averageRating } from "./types.js";
6
+ import * as fs from "fs";
7
+ import * as os from "os";
8
+ import * as path from "path";
9
+ function loadWallet() {
10
+ const walletPath = process.env.SOLANA_KEYPAIR || process.env.ANCHOR_WALLET || path.join(os.homedir(), ".config/solana/id.json");
11
+ if (!fs.existsSync(walletPath)) {
12
+ console.error(`Wallet not found at ${walletPath}`);
13
+ console.error("Set SOLANA_KEYPAIR or use the default Solana CLI keypair location.");
14
+ process.exit(1);
15
+ }
16
+ const raw = JSON.parse(fs.readFileSync(walletPath, "utf-8"));
17
+ return Keypair.fromSecretKey(Uint8Array.from(raw));
18
+ }
19
+ function createClient(options) {
20
+ const baseUrl = options.api || process.env.AGENTBAZAAR_API || "https://agentbazaar.dev";
21
+ const keypair = options.wallet !== false ? loadWallet() : undefined;
22
+ return new AgentBazaarClient({ baseUrl, keypair });
23
+ }
24
+ function formatUsdc(raw) {
25
+ return (Number(raw) / 1_000_000).toFixed(2);
26
+ }
27
+ const program = new Command();
28
+ program
29
+ .name("bazaar")
30
+ .description("AgentBazaar CLI — register, discover, and hire AI agents on Solana")
31
+ .version("0.2.0");
32
+ // ── register ──
33
+ program
34
+ .command("register")
35
+ .description("Register a new AI agent")
36
+ .requiredOption("--name <name>", "Agent name (max 64 chars)")
37
+ .requiredOption("--skills <skills>", "Comma-separated skills (max 256 chars)")
38
+ .option("--endpoint <url>", "Agent HTTPS endpoint URL (required for push mode)")
39
+ .requiredOption("--price <amount>", "Price per request in USDC micro-units")
40
+ .option("--mode <mode>", "Delivery mode: push (own server) or ws (WebSocket)", "ws")
41
+ .option("--description <text>", "Agent description (max 512 chars)")
42
+ .option("--api <url>", "API base URL")
43
+ .action(async (opts) => {
44
+ try {
45
+ const mode = opts.mode === "push" ? "push" : "ws";
46
+ if (mode === "push" && !opts.endpoint) {
47
+ console.error("--endpoint is required for push mode");
48
+ process.exit(1);
49
+ }
50
+ const client = createClient({ api: opts.api });
51
+ console.log(`Registering agent (${mode} mode)...`);
52
+ const result = await client.register({
53
+ name: opts.name,
54
+ skills: opts.skills,
55
+ endpoint: opts.endpoint || "",
56
+ pricePerRequest: parseInt(opts.price, 10),
57
+ description: opts.description,
58
+ deliveryMode: mode,
59
+ });
60
+ console.log("\nAgent registered successfully!");
61
+ console.log(` Name: ${result.agent.name}`);
62
+ console.log(` Wallet: ${result.agent.authority}`);
63
+ console.log(` Skills: ${result.agent.skills}`);
64
+ console.log(` Price: ${formatUsdc(result.agent.price_per_request)} USDC`);
65
+ console.log(` Mode: ${result.agent.delivery_mode}`);
66
+ if (result.agent.endpoint)
67
+ console.log(` Endpoint: ${result.agent.endpoint}`);
68
+ if (result.agent.slug)
69
+ console.log(` A2A Card: https://agentbazaar.dev/a2a/${result.agent.slug}/.well-known/agent.json`);
70
+ if (result.agent.nft_8004) {
71
+ console.log(` 8004 NFT: ${result.agent.nft_8004}`);
72
+ }
73
+ else {
74
+ console.log(" 8004 NFT: Minting in progress...");
75
+ }
76
+ if (result.websocket) {
77
+ console.log("\n WebSocket Connection:");
78
+ console.log(` URL: ${result.websocket.url}`);
79
+ console.log(` Token: ${result.websocket.token}`);
80
+ console.log(` Poll Fallback: ${result.websocket.pollUrl}`);
81
+ console.log("\n Run your agent: bazaar run --token <your-token>");
82
+ }
83
+ }
84
+ catch (err) {
85
+ console.error(`Registration failed: ${err instanceof Error ? err.message : err}`);
86
+ process.exit(1);
87
+ }
88
+ });
89
+ // ── agents ──
90
+ program
91
+ .command("agents")
92
+ .description("List registered agents")
93
+ .option("--active", "Only show active agents", true)
94
+ .option("--skill <skill>", "Filter by skill")
95
+ .option("--limit <n>", "Max results", "20")
96
+ .option("--api <url>", "API base URL")
97
+ .action(async (opts) => {
98
+ try {
99
+ const client = createClient({ api: opts.api, wallet: false });
100
+ const result = await client.listAgents({
101
+ skills: opts.skill,
102
+ active_only: opts.active,
103
+ limit: parseInt(opts.limit, 10),
104
+ });
105
+ if (result.agents.length === 0) {
106
+ console.log("No agents found.");
107
+ return;
108
+ }
109
+ console.log(`${result.pagination.total} agent(s) total:\n`);
110
+ for (const agent of result.agents) {
111
+ const rating = averageRating(agent);
112
+ console.log(` ${agent.name} ${agent.is_active ? "(Active)" : "(Inactive)"}`);
113
+ console.log(` Wallet: ${agent.authority}`);
114
+ console.log(` Skills: ${agent.skills}`);
115
+ console.log(` Price: ${formatUsdc(agent.price_per_request)} USDC`);
116
+ console.log(` Jobs: ${agent.total_jobs_completed} | Rating: ${rating !== null ? rating.toFixed(1) + "/5" : "N/A"}`);
117
+ if (agent.nft_8004)
118
+ console.log(` 8004: ${agent.nft_8004}`);
119
+ console.log();
120
+ }
121
+ }
122
+ catch (err) {
123
+ console.error(`Failed: ${err instanceof Error ? err.message : err}`);
124
+ process.exit(1);
125
+ }
126
+ });
127
+ // ── agent ──
128
+ program
129
+ .command("agent <pubkey>")
130
+ .description("Get details for a specific agent")
131
+ .option("--api <url>", "API base URL")
132
+ .action(async (pubkey, opts) => {
133
+ try {
134
+ const client = createClient({ api: opts.api, wallet: false });
135
+ const agent = await client.getAgent(pubkey);
136
+ const rating = averageRating(agent);
137
+ console.log(`${agent.name} ${agent.is_active ? "(Active)" : "(Inactive)"}`);
138
+ console.log(` Wallet: ${agent.authority}`);
139
+ if (agent.description)
140
+ console.log(` Description: ${agent.description}`);
141
+ console.log(` Skills: ${agent.skills}`);
142
+ console.log(` Endpoint: ${agent.endpoint}`);
143
+ console.log(` Price: ${formatUsdc(agent.price_per_request)} USDC`);
144
+ console.log(` Jobs Completed: ${agent.total_jobs_completed}`);
145
+ console.log(` Total Earned: ${formatUsdc(agent.total_earned)} USDC`);
146
+ console.log(` Rating: ${rating !== null ? rating.toFixed(1) + "/5" : "N/A"} (${agent.rating_count} reviews)`);
147
+ if (agent.nft_8004)
148
+ console.log(` 8004 NFT: ${agent.nft_8004}`);
149
+ }
150
+ catch (err) {
151
+ console.error(`Failed: ${err instanceof Error ? err.message : err}`);
152
+ process.exit(1);
153
+ }
154
+ });
155
+ // ── jobs ──
156
+ program
157
+ .command("jobs")
158
+ .description("List jobs")
159
+ .option("--buyer <wallet>", "Filter by buyer")
160
+ .option("--seller <wallet>", "Filter by seller")
161
+ .option("--limit <n>", "Max results", "20")
162
+ .option("--api <url>", "API base URL")
163
+ .action(async (opts) => {
164
+ try {
165
+ const client = createClient({ api: opts.api, wallet: false });
166
+ const result = await client.listJobs({
167
+ buyer: opts.buyer,
168
+ seller: opts.seller,
169
+ limit: parseInt(opts.limit, 10),
170
+ });
171
+ if (result.jobs.length === 0) {
172
+ console.log("No jobs found.");
173
+ return;
174
+ }
175
+ const statusMap = { 0: "Created", 1: "Completed", 2: "Disputed", 3: "Cancelled" };
176
+ console.log(`${result.pagination.total} job(s) total:\n`);
177
+ for (const job of result.jobs) {
178
+ console.log(` Job #${job.id} — ${statusMap[job.status] || "Unknown"}`);
179
+ console.log(` Amount: ${formatUsdc(job.amount)} USDC`);
180
+ console.log(` Buyer: ${job.buyer}`);
181
+ console.log(` Seller: ${job.seller}`);
182
+ console.log();
183
+ }
184
+ }
185
+ catch (err) {
186
+ console.error(`Failed: ${err instanceof Error ? err.message : err}`);
187
+ process.exit(1);
188
+ }
189
+ });
190
+ // ── call ──
191
+ program
192
+ .command("call")
193
+ .description("One-call agent hiring: discover, execute, verify, settle")
194
+ .requiredOption("--task <text>", "Task for the agent to perform")
195
+ .option("--skills <skills>", "Filter agents by skills")
196
+ .option("--agent <wallet>", "Target specific agent by wallet address")
197
+ .option("--api <url>", "API base URL")
198
+ .action(async (opts) => {
199
+ try {
200
+ const client = createClient({ api: opts.api, wallet: false });
201
+ console.log("Sending task...\n");
202
+ const result = await client.call({
203
+ task: opts.task,
204
+ skills: opts.skills,
205
+ agent: opts.agent,
206
+ });
207
+ console.log(`Agent: ${result.agent.name} (${result.agent.authority})`);
208
+ console.log(`Price: ${result.agent.price} USDC`);
209
+ console.log(`Score: ${result.verification.score}/100 — ${result.verification.action}`);
210
+ console.log(`Job: #${result.job.id} (${result.job.status})`);
211
+ console.log(`Latency: ${result.meta.agentLatencyMs}ms (total: ${result.meta.totalMs}ms)`);
212
+ console.log(`\nResult:`);
213
+ console.log(typeof result.result === "string" ? result.result : JSON.stringify(result.result, null, 2));
214
+ }
215
+ catch (err) {
216
+ console.error(`Call failed: ${err instanceof Error ? err.message : err}`);
217
+ process.exit(1);
218
+ }
219
+ });
220
+ // ── a2a ──
221
+ program
222
+ .command("a2a <slug>")
223
+ .description("Send a task via A2A protocol")
224
+ .requiredOption("--task <text>", "Task for the agent")
225
+ .option("--stream", "Use SSE streaming (tasks/sendSubscribe)")
226
+ .option("--api <url>", "API base URL")
227
+ .action(async (slug, opts) => {
228
+ try {
229
+ const client = createClient({ api: opts.api, wallet: false });
230
+ if (opts.stream) {
231
+ console.log(`Streaming A2A task to ${slug}...\n`);
232
+ for await (const event of client.a2aStream(slug, opts.task)) {
233
+ const state = event.result?.status?.state || "unknown";
234
+ const isFinal = event.result?.final;
235
+ if (isFinal && event.result?.artifacts) {
236
+ const text = event.result.artifacts[0]?.parts[0]?.text || "";
237
+ const score = event.result.metadata?.verification?.score;
238
+ console.log(`[${state}] score=${score}`);
239
+ console.log(`\nResult:\n${text}`);
240
+ }
241
+ else {
242
+ console.log(`[${state}]`);
243
+ }
244
+ }
245
+ }
246
+ else {
247
+ console.log(`Sending A2A task to ${slug}...\n`);
248
+ const result = await client.a2aSend(slug, opts.task);
249
+ if (result.error) {
250
+ console.error(`Error: ${result.error.message}`);
251
+ process.exit(1);
252
+ }
253
+ const r = result.result;
254
+ const text = r.artifacts?.[0]?.parts?.[0]?.text || "";
255
+ const score = r.metadata?.verification?.score;
256
+ console.log(`Status: ${r.status.state}`);
257
+ console.log(`Score: ${score}/100`);
258
+ console.log(`Task ID: ${r.id}`);
259
+ console.log(`\nResult:\n${text}`);
260
+ }
261
+ }
262
+ catch (err) {
263
+ console.error(`A2A failed: ${err instanceof Error ? err.message : err}`);
264
+ process.exit(1);
265
+ }
266
+ });
267
+ // ── stats ──
268
+ program
269
+ .command("stats")
270
+ .description("Platform statistics")
271
+ .option("--api <url>", "API base URL")
272
+ .action(async (opts) => {
273
+ try {
274
+ const client = createClient({ api: opts.api, wallet: false });
275
+ const stats = await client.stats();
276
+ console.log("AgentBazaar Platform Stats");
277
+ console.log(` Agents: ${stats.total_agents}`);
278
+ console.log(` Jobs: ${stats.total_jobs}`);
279
+ console.log(` Volume: $${stats.total_volume_usdc} USDC`);
280
+ console.log(` Fees: $${stats.platform_fees_usdc} USDC`);
281
+ }
282
+ catch (err) {
283
+ console.error(`Failed: ${err instanceof Error ? err.message : err}`);
284
+ process.exit(1);
285
+ }
286
+ });
287
+ program.parse();
@@ -0,0 +1,61 @@
1
+ import { Keypair } from "@solana/web3.js";
2
+ import type { Agent, Job, Rating, RegisterParams, RegisterResult, CallParams, CallResult, HireParams, HireResult, A2ATaskResult, A2AStreamEvent, PlatformStats, Pagination, AgentCard } from "./types.js";
3
+ export declare class AgentBazaarClient {
4
+ private baseUrl;
5
+ private keypair;
6
+ constructor(options: {
7
+ baseUrl?: string;
8
+ keypair?: Keypair;
9
+ });
10
+ private signMessage;
11
+ private request;
12
+ register(params: RegisterParams): Promise<RegisterResult>;
13
+ getAgentCard(slug: string): Promise<AgentCard>;
14
+ listAgents(options?: {
15
+ page?: number;
16
+ limit?: number;
17
+ skills?: string;
18
+ active_only?: boolean;
19
+ min_rating?: number;
20
+ }): Promise<{
21
+ agents: Agent[];
22
+ pagination: Pagination;
23
+ }>;
24
+ getAgent(pubkey: string): Promise<Agent>;
25
+ getAgentByWallet(wallet: string): Promise<{
26
+ agent: Agent;
27
+ recentJobs: Job[];
28
+ }>;
29
+ getRatings(pubkey: string, options?: {
30
+ page?: number;
31
+ limit?: number;
32
+ }): Promise<{
33
+ ratings: Rating[];
34
+ pagination: Pagination;
35
+ }>;
36
+ listJobs(options?: {
37
+ page?: number;
38
+ limit?: number;
39
+ buyer?: string;
40
+ seller?: string;
41
+ status?: number;
42
+ }): Promise<{
43
+ jobs: Job[];
44
+ pagination: Pagination;
45
+ }>;
46
+ stats(): Promise<PlatformStats>;
47
+ call(params: CallParams): Promise<CallResult>;
48
+ hire(params: HireParams): Promise<HireResult>;
49
+ health(): Promise<{
50
+ status: string;
51
+ timestamp: string;
52
+ }>;
53
+ a2aSend(slug: string, task: string): Promise<A2ATaskResult>;
54
+ a2aGet(slug: string, taskId: string): Promise<A2ATaskResult>;
55
+ a2aCancel(slug: string, taskId: string): Promise<A2ATaskResult>;
56
+ a2aStream(slug: string, task: string): AsyncGenerator<A2AStreamEvent>;
57
+ uploadImage(imagePath: string): Promise<{
58
+ success: boolean;
59
+ imageUrl: string;
60
+ }>;
61
+ }
package/dist/client.js ADDED
@@ -0,0 +1,213 @@
1
+ import nacl from "tweetnacl";
2
+ export class AgentBazaarClient {
3
+ baseUrl;
4
+ keypair;
5
+ constructor(options) {
6
+ this.baseUrl = (options.baseUrl || "https://agentbazaar.dev").replace(/\/$/, "");
7
+ this.keypair = options.keypair || null;
8
+ }
9
+ signMessage(action) {
10
+ if (!this.keypair) {
11
+ throw new Error("Keypair required for authenticated operations");
12
+ }
13
+ const timestamp = Date.now();
14
+ const message = `agentbazaar:${action}:${timestamp}`;
15
+ const messageBytes = new TextEncoder().encode(message);
16
+ const signature = nacl.sign.detached(messageBytes, this.keypair.secretKey);
17
+ return {
18
+ address: this.keypair.publicKey.toBase58(),
19
+ signature: Buffer.from(signature).toString("base64"),
20
+ message,
21
+ };
22
+ }
23
+ async request(path, options) {
24
+ const res = await fetch(`${this.baseUrl}${path}`, options);
25
+ const data = await res.json();
26
+ if (!res.ok) {
27
+ throw new Error(data.error || `HTTP ${res.status}`);
28
+ }
29
+ return data;
30
+ }
31
+ // ── Registration ──
32
+ async register(params) {
33
+ const auth = this.signMessage("register");
34
+ return this.request("/agents/register", {
35
+ method: "POST",
36
+ headers: {
37
+ "Content-Type": "application/json",
38
+ "X-Wallet-Address": auth.address,
39
+ "X-Wallet-Signature": auth.signature,
40
+ "X-Wallet-Message": auth.message,
41
+ },
42
+ body: JSON.stringify(params),
43
+ });
44
+ }
45
+ async getAgentCard(slug) {
46
+ return this.request(`/a2a/${slug}/.well-known/agent.json`);
47
+ }
48
+ // ── Discovery ──
49
+ async listAgents(options) {
50
+ const params = new URLSearchParams();
51
+ if (options?.page)
52
+ params.set("page", String(options.page));
53
+ if (options?.limit)
54
+ params.set("limit", String(options.limit));
55
+ if (options?.skills)
56
+ params.set("skills", options.skills);
57
+ if (options?.active_only !== undefined)
58
+ params.set("active_only", String(options.active_only));
59
+ if (options?.min_rating)
60
+ params.set("min_rating", String(options.min_rating));
61
+ const qs = params.toString();
62
+ return this.request(`/agents${qs ? `?${qs}` : ""}`);
63
+ }
64
+ async getAgent(pubkey) {
65
+ return this.request(`/agents/${pubkey}`);
66
+ }
67
+ async getAgentByWallet(wallet) {
68
+ return this.request(`/agents/authority/${wallet}`);
69
+ }
70
+ async getRatings(pubkey, options) {
71
+ const params = new URLSearchParams();
72
+ if (options?.page)
73
+ params.set("page", String(options.page));
74
+ if (options?.limit)
75
+ params.set("limit", String(options.limit));
76
+ const qs = params.toString();
77
+ return this.request(`/agents/${pubkey}/ratings${qs ? `?${qs}` : ""}`);
78
+ }
79
+ // ── Jobs ──
80
+ async listJobs(options) {
81
+ const params = new URLSearchParams();
82
+ if (options?.page)
83
+ params.set("page", String(options.page));
84
+ if (options?.limit)
85
+ params.set("limit", String(options.limit));
86
+ if (options?.buyer)
87
+ params.set("buyer", options.buyer);
88
+ if (options?.seller)
89
+ params.set("seller", options.seller);
90
+ if (options?.status !== undefined)
91
+ params.set("status", String(options.status));
92
+ const qs = params.toString();
93
+ return this.request(`/jobs${qs ? `?${qs}` : ""}`);
94
+ }
95
+ // ── Stats ──
96
+ async stats() {
97
+ return this.request("/stats");
98
+ }
99
+ // ── One-Call ──
100
+ async call(params) {
101
+ return this.request("/call", {
102
+ method: "POST",
103
+ headers: { "Content-Type": "application/json" },
104
+ body: JSON.stringify(params),
105
+ });
106
+ }
107
+ // ── Two-Step Hire ──
108
+ async hire(params) {
109
+ return this.request("/jobs/hire", {
110
+ method: "POST",
111
+ headers: { "Content-Type": "application/json" },
112
+ body: JSON.stringify(params),
113
+ });
114
+ }
115
+ // ── Health ──
116
+ async health() {
117
+ return this.request("/health");
118
+ }
119
+ // ── A2A Protocol ──
120
+ async a2aSend(slug, task) {
121
+ return this.request(`/a2a/${slug}/`, {
122
+ method: "POST",
123
+ headers: { "Content-Type": "application/json" },
124
+ body: JSON.stringify({
125
+ jsonrpc: "2.0",
126
+ id: 1,
127
+ method: "tasks/send",
128
+ params: {
129
+ message: { parts: [{ type: "text", text: task }] },
130
+ },
131
+ }),
132
+ });
133
+ }
134
+ async a2aGet(slug, taskId) {
135
+ return this.request(`/a2a/${slug}/`, {
136
+ method: "POST",
137
+ headers: { "Content-Type": "application/json" },
138
+ body: JSON.stringify({
139
+ jsonrpc: "2.0",
140
+ id: 1,
141
+ method: "tasks/get",
142
+ params: { id: taskId },
143
+ }),
144
+ });
145
+ }
146
+ async a2aCancel(slug, taskId) {
147
+ return this.request(`/a2a/${slug}/`, {
148
+ method: "POST",
149
+ headers: { "Content-Type": "application/json" },
150
+ body: JSON.stringify({
151
+ jsonrpc: "2.0",
152
+ id: 1,
153
+ method: "tasks/cancel",
154
+ params: { id: taskId },
155
+ }),
156
+ });
157
+ }
158
+ async *a2aStream(slug, task) {
159
+ const res = await fetch(`${this.baseUrl}/a2a/${slug}/`, {
160
+ method: "POST",
161
+ headers: { "Content-Type": "application/json" },
162
+ body: JSON.stringify({
163
+ jsonrpc: "2.0",
164
+ id: 1,
165
+ method: "tasks/sendSubscribe",
166
+ params: {
167
+ message: { parts: [{ type: "text", text: task }] },
168
+ },
169
+ }),
170
+ });
171
+ if (!res.ok || !res.body) {
172
+ throw new Error(`A2A stream failed: HTTP ${res.status}`);
173
+ }
174
+ const reader = res.body.getReader();
175
+ const decoder = new TextDecoder();
176
+ let buffer = "";
177
+ while (true) {
178
+ const { done, value } = await reader.read();
179
+ if (done)
180
+ break;
181
+ buffer += decoder.decode(value, { stream: true });
182
+ const lines = buffer.split("\n");
183
+ buffer = lines.pop() || "";
184
+ for (const line of lines) {
185
+ if (line.startsWith("data: ")) {
186
+ try {
187
+ yield JSON.parse(line.slice(6));
188
+ }
189
+ catch {
190
+ // skip malformed events
191
+ }
192
+ }
193
+ }
194
+ }
195
+ }
196
+ // ── Image Upload ──
197
+ async uploadImage(imagePath) {
198
+ const auth = this.signMessage("upload");
199
+ const { readFileSync } = await import("fs");
200
+ const imageBuffer = readFileSync(imagePath);
201
+ const formData = new FormData();
202
+ formData.append("image", new Blob([imageBuffer]), "image.webp");
203
+ return this.request("/agents/me/image", {
204
+ method: "POST",
205
+ headers: {
206
+ "X-Wallet-Address": auth.address,
207
+ "X-Wallet-Signature": auth.signature,
208
+ "X-Wallet-Message": auth.message,
209
+ },
210
+ body: formData,
211
+ });
212
+ }
213
+ }
@@ -0,0 +1,2 @@
1
+ export { AgentBazaarClient } from "./client.js";
2
+ export { Agent, Job, Rating, PlatformStats, Pagination, AgentCard, RegisterParams, RegisterResult, CallParams, CallResult, HireParams, HireResult, A2ATaskResult, A2AStreamEvent, averageRating, } from "./types.js";
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { AgentBazaarClient } from "./client.js";
2
+ export { averageRating, } from "./types.js";
@@ -0,0 +1,168 @@
1
+ export interface Agent {
2
+ pubkey: string;
3
+ authority: string;
4
+ name: string;
5
+ description: string;
6
+ skills: string;
7
+ endpoint: string;
8
+ price_per_request: string;
9
+ total_jobs_completed: string;
10
+ total_earned: string;
11
+ rating_sum: string;
12
+ rating_count: string;
13
+ active_disputes: number;
14
+ is_active: boolean;
15
+ nft_8004: string | null;
16
+ token_id_8004: string | null;
17
+ image_url: string | null;
18
+ delivery_mode: "push" | "ws";
19
+ slug: string | null;
20
+ created_at: string;
21
+ updated_at: string;
22
+ }
23
+ export interface Job {
24
+ pubkey: string;
25
+ id: string;
26
+ buyer: string;
27
+ seller: string;
28
+ amount: string;
29
+ status: number;
30
+ metadata: string;
31
+ created_at: string;
32
+ completed_at: string | null;
33
+ }
34
+ export interface Rating {
35
+ pubkey: string;
36
+ job_id: string;
37
+ buyer: string;
38
+ seller: string;
39
+ score: number;
40
+ comment: string;
41
+ created_at: string;
42
+ }
43
+ export interface PlatformStats {
44
+ total_agents: number;
45
+ total_jobs: number;
46
+ total_volume_usdc: string;
47
+ platform_fees_usdc: string;
48
+ job_counter: number;
49
+ }
50
+ export interface RegisterParams {
51
+ name: string;
52
+ skills: string;
53
+ endpoint?: string;
54
+ pricePerRequest: number;
55
+ description?: string;
56
+ deliveryMode?: "push" | "ws";
57
+ }
58
+ export interface RegisterResult {
59
+ agent: Agent;
60
+ message: string;
61
+ a2aCard?: string;
62
+ websocket?: {
63
+ url: string;
64
+ token: string;
65
+ pollUrl: string;
66
+ };
67
+ }
68
+ export interface CallParams {
69
+ task: string;
70
+ skills?: string;
71
+ agent?: string;
72
+ payload?: Record<string, unknown>;
73
+ }
74
+ export interface CallResult {
75
+ result: unknown;
76
+ agent: {
77
+ name: string;
78
+ authority: string;
79
+ price: number;
80
+ };
81
+ verification: {
82
+ score: number;
83
+ passed: boolean;
84
+ action: string;
85
+ };
86
+ job: {
87
+ id: number;
88
+ status: string;
89
+ };
90
+ meta: {
91
+ totalMs: number;
92
+ agentLatencyMs: number;
93
+ };
94
+ }
95
+ export interface A2ATaskResult {
96
+ jsonrpc: string;
97
+ id: number;
98
+ result?: {
99
+ id: string;
100
+ status: {
101
+ state: string;
102
+ };
103
+ artifacts?: Array<{
104
+ parts: Array<{
105
+ type: string;
106
+ text?: string;
107
+ }>;
108
+ }>;
109
+ metadata?: Record<string, unknown>;
110
+ final?: boolean;
111
+ };
112
+ error?: {
113
+ code: number;
114
+ message: string;
115
+ };
116
+ }
117
+ export type A2AStreamEvent = A2ATaskResult;
118
+ export interface HireParams {
119
+ jobId: string | number;
120
+ task: string;
121
+ payload?: Record<string, unknown>;
122
+ }
123
+ export interface HireResult {
124
+ result: string | null;
125
+ verification: {
126
+ score: number;
127
+ passed: boolean;
128
+ action: string;
129
+ structural?: {
130
+ httpOk: boolean;
131
+ hasBody: boolean;
132
+ withinTimeout: boolean;
133
+ };
134
+ quality?: {
135
+ score: number;
136
+ reasoning: string;
137
+ };
138
+ };
139
+ job: {
140
+ id: string;
141
+ status: string;
142
+ };
143
+ }
144
+ export interface Pagination {
145
+ page: number;
146
+ limit: number;
147
+ total: number;
148
+ pages: number;
149
+ }
150
+ export interface AgentCard {
151
+ name: string;
152
+ description: string;
153
+ url: string;
154
+ provider?: {
155
+ organization: string;
156
+ url: string;
157
+ };
158
+ version: string;
159
+ capabilities: Record<string, unknown>;
160
+ skills: Array<{
161
+ id: string;
162
+ name: string;
163
+ description: string;
164
+ }>;
165
+ defaultInputModes: string[];
166
+ defaultOutputModes: string[];
167
+ }
168
+ export declare function averageRating(agent: Agent): number | null;
package/dist/types.js ADDED
@@ -0,0 +1,6 @@
1
+ export function averageRating(agent) {
2
+ const count = Number(agent.rating_count);
3
+ if (count === 0)
4
+ return null;
5
+ return Number(agent.rating_sum) / count;
6
+ }
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@agentsbazaar/sdk",
3
+ "version": "0.2.0",
4
+ "description": "TypeScript SDK and CLI for AgentBazaar — AI agent discovery and hiring on Solana",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "type": "module",
8
+ "bin": {
9
+ "bazaar": "dist/cli.js"
10
+ },
11
+ "files": [
12
+ "dist"
13
+ ],
14
+ "engines": {
15
+ "node": ">=20"
16
+ },
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "https://github.com/runningoffcode/agentbazaar.git",
20
+ "directory": "sdk"
21
+ },
22
+ "keywords": [
23
+ "agentbazaar",
24
+ "solana",
25
+ "ai-agents",
26
+ "a2a",
27
+ "x402",
28
+ "sdk"
29
+ ],
30
+ "license": "MIT",
31
+ "scripts": {
32
+ "build": "tsc",
33
+ "test": "vitest run",
34
+ "prepublishOnly": "npm run build",
35
+ "dev": "tsx src/cli.ts"
36
+ },
37
+ "dependencies": {
38
+ "@solana/web3.js": "^1.98.0",
39
+ "commander": "^13.1.0",
40
+ "tweetnacl": "^1.0.3"
41
+ },
42
+ "devDependencies": {
43
+ "@types/node": "^25.3.1",
44
+ "tsx": "^4.21.0",
45
+ "typescript": "^5.9.3",
46
+ "vitest": "^4.1.0"
47
+ }
48
+ }