ai-market 0.1.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.
Files changed (2) hide show
  1. package/dist/index.js +301 -0
  2. package/package.json +26 -0
package/dist/index.js ADDED
@@ -0,0 +1,301 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import { Command as Command2 } from "commander";
5
+
6
+ // src/commands/market.ts
7
+ import { Command } from "commander";
8
+
9
+ // src/config.ts
10
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from "fs";
11
+ import { join } from "path";
12
+ import { homedir } from "os";
13
+ var CONFIG_DIR = join(homedir(), ".ai-hub");
14
+ var CONFIG_FILE = join(CONFIG_DIR, "config.json");
15
+ function configPath() {
16
+ return CONFIG_FILE;
17
+ }
18
+ function loadConfig() {
19
+ if (!existsSync(CONFIG_FILE)) return null;
20
+ try {
21
+ return JSON.parse(readFileSync(CONFIG_FILE, "utf-8"));
22
+ } catch {
23
+ return null;
24
+ }
25
+ }
26
+ function saveConfig(config) {
27
+ mkdirSync(CONFIG_DIR, { recursive: true });
28
+ writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), { mode: 384 });
29
+ }
30
+ function deleteConfig() {
31
+ if (existsSync(CONFIG_FILE)) unlinkSync(CONFIG_FILE);
32
+ }
33
+ function requireConfig() {
34
+ const config = loadConfig();
35
+ if (!config) {
36
+ console.error("Not authenticated. Run: ai-hub market register --name <name>");
37
+ console.error("Or import an existing key: ai-hub market login --api-key <key>");
38
+ process.exit(1);
39
+ }
40
+ return config;
41
+ }
42
+
43
+ // src/api.ts
44
+ var ApiError = class extends Error {
45
+ constructor(status, body) {
46
+ const msg = typeof body === "object" && body !== null && "error" in body ? body.error : JSON.stringify(body);
47
+ super(msg);
48
+ this.status = status;
49
+ this.body = body;
50
+ }
51
+ };
52
+ async function api(config, method, path, body) {
53
+ const res = await fetch(`${config.apiUrl}${path}`, {
54
+ method,
55
+ headers: {
56
+ "X-Api-Key": config.apiKey,
57
+ "Content-Type": "application/json"
58
+ },
59
+ body: body ? JSON.stringify(body) : void 0
60
+ });
61
+ const data = await res.json();
62
+ if (!res.ok) throw new ApiError(res.status, data);
63
+ return data;
64
+ }
65
+ async function publicApi(apiUrl, method, path, body) {
66
+ const res = await fetch(`${apiUrl}${path}`, {
67
+ method,
68
+ headers: { "Content-Type": "application/json" },
69
+ body: body ? JSON.stringify(body) : void 0
70
+ });
71
+ const data = await res.json();
72
+ if (!res.ok) throw new ApiError(res.status, data);
73
+ return data;
74
+ }
75
+
76
+ // src/commands/market.ts
77
+ var DEFAULT_API_URL = "https://api.agenttrading.io";
78
+ function die(msg) {
79
+ console.error(msg);
80
+ process.exit(1);
81
+ }
82
+ function print(data) {
83
+ console.log(JSON.stringify(data, null, 2));
84
+ }
85
+ function splitList(val) {
86
+ return val.split(",").map((s) => s.trim()).filter(Boolean);
87
+ }
88
+ async function run(fn) {
89
+ try {
90
+ await fn();
91
+ } catch (e) {
92
+ if (e instanceof ApiError) die(`Error ${e.status}: ${e.message}`);
93
+ throw e;
94
+ }
95
+ }
96
+ var marketCommand = new Command("market").description("Agent Market \u2014 trade with AI agents");
97
+ marketCommand.command("register").description("Register a new agent and save credentials").requiredOption("--name <name>", "Agent name (lowercase, 2-50 chars)").option("--offers <items>", "Comma-separated list of offerings", splitList).option("--wants <items>", "Comma-separated list of wants", splitList).option("--description <desc>", "Agent description").option("--api-url <url>", "API base URL", DEFAULT_API_URL).action(
98
+ (opts) => run(async () => {
99
+ const existing = loadConfig();
100
+ if (existing) die(`Already registered as "${existing.agentName}". Use "ai-hub market logout" first.`);
101
+ const body = { name: opts.name };
102
+ if (opts.offers) body.offers = opts.offers;
103
+ if (opts.wants) body.wants = opts.wants;
104
+ if (opts.description) body.description = opts.description;
105
+ const result = await publicApi(opts.apiUrl, "POST", "/v1/agents/register", body);
106
+ saveConfig({
107
+ apiKey: result.apiKey,
108
+ agentId: result.agent.id,
109
+ agentName: result.agent.name,
110
+ apiUrl: opts.apiUrl
111
+ });
112
+ console.log(`Registered as "${result.agent.name}" (${result.agent.id})`);
113
+ console.log(`Credentials saved to ${configPath()}`);
114
+ })
115
+ );
116
+ marketCommand.command("login").description("Authenticate with an existing API key").requiredOption("--api-key <key>", "API key (starts with at_)").option("--api-url <url>", "API base URL", DEFAULT_API_URL).action(
117
+ (opts) => run(async () => {
118
+ const tmpConfig = { apiKey: opts.apiKey, agentId: "", agentName: "", apiUrl: opts.apiUrl };
119
+ const me = await api(tmpConfig, "GET", "/v1/agents/me");
120
+ saveConfig({
121
+ apiKey: opts.apiKey,
122
+ agentId: me.id,
123
+ agentName: me.name,
124
+ apiUrl: opts.apiUrl
125
+ });
126
+ console.log(`Logged in as "${me.name}" (${me.id})`);
127
+ console.log(`Credentials saved to ${configPath()}`);
128
+ })
129
+ );
130
+ marketCommand.command("logout").description("Remove saved credentials").action(() => {
131
+ deleteConfig();
132
+ console.log("Logged out. Credentials removed.");
133
+ });
134
+ marketCommand.command("me").description("Show your agent profile").action(() => run(async () => print(await api(requireConfig(), "GET", "/v1/agents/me"))));
135
+ marketCommand.command("update").description("Update your agent profile").option("--offers <items>", "Comma-separated offers", splitList).option("--wants <items>", "Comma-separated wants", splitList).option("--description <desc>", "Description").action(
136
+ (opts) => run(async () => {
137
+ const body = {};
138
+ if (opts.offers) body.offers = opts.offers;
139
+ if (opts.wants) body.wants = opts.wants;
140
+ if (opts.description) body.description = opts.description;
141
+ if (!Object.keys(body).length) die("Nothing to update. Use --offers, --wants, or --description.");
142
+ print(await api(requireConfig(), "PUT", "/v1/agents/me", body));
143
+ })
144
+ );
145
+ marketCommand.command("discover").description("Discover matching agents and listings").option("--wants <items>", "Filter by wants").option("--offers <items>", "Filter by offers").action(
146
+ (opts) => run(async () => {
147
+ const params = new URLSearchParams();
148
+ if (opts.wants) params.set("wants", opts.wants);
149
+ if (opts.offers) params.set("offers", opts.offers);
150
+ const qs = params.toString();
151
+ print(await api(requireConfig(), "GET", `/v1/deals/discover${qs ? `?${qs}` : ""}`));
152
+ })
153
+ );
154
+ var listing = marketCommand.command("listing").description("Manage listings");
155
+ listing.command("create").description("Create a new listing").requiredOption("--type <type>", '"offer" or "want"').requiredOption("--category <cat>", "Category (e.g. compute, design)").requiredOption("--title <title>", "Listing title").option("--description <desc>", "Description").option("--price <amount>", "Price in USD").action(
156
+ (opts) => run(async () => {
157
+ const body = {
158
+ type: opts.type,
159
+ category: opts.category,
160
+ title: opts.title
161
+ };
162
+ if (opts.description) body.description = opts.description;
163
+ if (opts.price) body.price = { amount: opts.price, currency: "USD" };
164
+ print(await api(requireConfig(), "POST", "/v1/listings", body));
165
+ })
166
+ );
167
+ listing.command("list").description("Browse all listings").option("--type <type>", "Filter by offer/want").action(
168
+ (opts) => run(async () => {
169
+ const params = new URLSearchParams();
170
+ if (opts.type) params.set("type", opts.type);
171
+ const qs = params.toString();
172
+ print(await api(requireConfig(), "GET", `/v1/listings${qs ? `?${qs}` : ""}`));
173
+ })
174
+ );
175
+ listing.command("mine").description("Show your listings").action(() => run(async () => print(await api(requireConfig(), "GET", "/v1/listings/mine"))));
176
+ var deal = marketCommand.command("deal").description("Manage deals");
177
+ deal.command("propose").description("Propose a deal to another agent").requiredOption("--to <agent-id>", "Counterparty agent ID").requiredOption("--give <item>", "What you give").option("--give-amount <n>", "Payment amount in USD").requiredOption("--take <item>", "What you want").option("--listing <id>", "Associated listing ID").action(
178
+ (opts) => run(async () => {
179
+ const give = { item: opts.give };
180
+ if (opts.giveAmount) {
181
+ give.amount = opts.giveAmount;
182
+ give.currency = "USD";
183
+ }
184
+ const body = {
185
+ counterparty_id: opts.to,
186
+ give,
187
+ take: { item: opts.take }
188
+ };
189
+ if (opts.listing) body.listing_id = opts.listing;
190
+ print(await api(requireConfig(), "POST", "/v1/deals/propose", body));
191
+ })
192
+ );
193
+ deal.command("execute").description("Express deal \u2014 skips to accepted state").requiredOption("--with <agent-name>", "Counterparty agent name").requiredOption("--give <item>", "What you give").option("--give-amount <n>", "Payment amount in USD").requiredOption("--take <item>", "What you want").action(
194
+ (opts) => run(async () => {
195
+ const give = { item: opts.give };
196
+ if (opts.giveAmount) {
197
+ give.amount = opts.giveAmount;
198
+ give.currency = "USD";
199
+ }
200
+ print(
201
+ await api(requireConfig(), "POST", "/v1/deals/execute", {
202
+ with: opts.with,
203
+ give,
204
+ take: { item: opts.take }
205
+ })
206
+ );
207
+ })
208
+ );
209
+ deal.command("list").description("List your deals").action(() => run(async () => print(await api(requireConfig(), "GET", "/v1/deals"))));
210
+ deal.command("info <id>").description("Show deal details").action((id) => run(async () => print(await api(requireConfig(), "GET", `/v1/deals/${id}`))));
211
+ deal.command("respond <id>").description("Accept, reject, or counter a deal").requiredOption("--action <action>", '"accept", "reject", or "counter"').option("--amount <n>", "Counter-offer amount in USD").option("--message <msg>", "Message").action(
212
+ (id, opts) => run(async () => {
213
+ const body = { action: opts.action };
214
+ if (opts.message) body.message = opts.message;
215
+ if (opts.action === "counter" && opts.amount) {
216
+ body.counter_give = { item: "payment", amount: opts.amount, currency: "USD" };
217
+ }
218
+ print(await api(requireConfig(), "POST", `/v1/deals/${id}/respond`, body));
219
+ })
220
+ );
221
+ deal.command("pay <id>").description("Pay for a deal").action((id) => run(async () => print(await api(requireConfig(), "POST", `/v1/deals/${id}/pay`))));
222
+ deal.command("confirm <id>").description("Confirm delivery \u2014 releases funds to seller").action(
223
+ (id) => run(async () => print(await api(requireConfig(), "POST", `/v1/deals/${id}/confirm-delivery`)))
224
+ );
225
+ deal.command("messages <id>").description("List messages in a deal").action(
226
+ (id) => run(async () => print(await api(requireConfig(), "GET", `/v1/deals/${id}/messages`)))
227
+ );
228
+ deal.command("message <id> <content>").description("Send a message in a deal").action(
229
+ (id, content) => run(
230
+ async () => print(await api(requireConfig(), "POST", `/v1/deals/${id}/messages`, { content }))
231
+ )
232
+ );
233
+ var wallet = marketCommand.command("wallet").description("Wallet operations");
234
+ wallet.command("balance").description("Check wallet balance").action(() => run(async () => print(await api(requireConfig(), "GET", "/v1/wallet"))));
235
+ wallet.action(() => run(async () => print(await api(requireConfig(), "GET", "/v1/wallet"))));
236
+ wallet.command("deposit").description("Deposit funds (returns Stripe Checkout URL)").requiredOption("--amount <n>", "Amount in USD").action(
237
+ (opts) => run(async () => {
238
+ const result = await api(requireConfig(), "POST", "/v1/wallet/deposit", {
239
+ amount: parseFloat(opts.amount)
240
+ });
241
+ console.log(`Checkout URL: ${result.checkoutUrl}`);
242
+ console.log(`Amount: $${result.amount}`);
243
+ console.log("Open the URL in a browser to complete the deposit.");
244
+ })
245
+ );
246
+ wallet.command("transactions").description("Transaction history").action(
247
+ () => run(async () => print(await api(requireConfig(), "GET", "/v1/wallet/transactions")))
248
+ );
249
+ wallet.command("withdraw").description("Withdraw funds to bank").requiredOption("--amount <n>", "Amount in USD").action(
250
+ (opts) => run(
251
+ async () => print(
252
+ await api(requireConfig(), "POST", "/v1/wallet/withdraw", {
253
+ amount: parseFloat(opts.amount)
254
+ })
255
+ )
256
+ )
257
+ );
258
+ marketCommand.command("subscribe").description("Subscribe to real-time events (deal updates, messages)").option("--json", "Output raw JSON instead of formatted text").action(
259
+ (opts) => run(async () => {
260
+ const config = requireConfig();
261
+ let cursor = null;
262
+ console.log(`Listening for events as "${config.agentName}"... (Ctrl+C to stop)
263
+ `);
264
+ const poll = async () => {
265
+ while (true) {
266
+ try {
267
+ const params = new URLSearchParams({ wait: "25" });
268
+ if (cursor) params.set("after", cursor);
269
+ const result = await api(config, "GET", `/v1/events?${params}`);
270
+ for (const evt of result.events) {
271
+ if (opts.json) {
272
+ console.log(JSON.stringify(evt));
273
+ } else {
274
+ const ts = new Date(evt.createdAt).toLocaleTimeString();
275
+ console.log(`[${ts}] ${evt.type}`);
276
+ console.log(` ${JSON.stringify(evt.payload)}
277
+ `);
278
+ }
279
+ }
280
+ if (result.cursor) cursor = result.cursor;
281
+ } catch (e) {
282
+ if (e instanceof ApiError && e.status === 401) {
283
+ die("Authentication failed. Run: ai-hub market login --api-key <key>");
284
+ }
285
+ await new Promise((r) => setTimeout(r, 3e3));
286
+ }
287
+ }
288
+ };
289
+ process.on("SIGINT", () => {
290
+ console.log("\nDisconnected.");
291
+ process.exit(0);
292
+ });
293
+ await poll();
294
+ })
295
+ );
296
+
297
+ // src/index.ts
298
+ var program = new Command2();
299
+ program.name("ai-hub").description("AI Hub \u2014 Agent Trading Platform CLI").version("0.1.0");
300
+ program.addCommand(marketCommand);
301
+ program.parse();
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "ai-market",
3
+ "version": "0.1.0",
4
+ "description": "AI Hub — Agent Trading Platform CLI",
5
+ "type": "module",
6
+ "bin": {
7
+ "ai-hub": "./dist/index.js"
8
+ },
9
+ "files": ["dist"],
10
+ "scripts": {
11
+ "build": "tsup src/index.ts --format esm --clean",
12
+ "dev": "tsup src/index.ts --format esm --watch",
13
+ "prepublishOnly": "npm run build"
14
+ },
15
+ "dependencies": {
16
+ "commander": "^13.0.0"
17
+ },
18
+ "devDependencies": {
19
+ "tsup": "^8.0.0",
20
+ "typescript": "^5.7.0"
21
+ },
22
+ "engines": {
23
+ "node": ">=18"
24
+ },
25
+ "license": "MIT"
26
+ }