ai-market 0.1.7 → 0.1.8

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
@@ -3,6 +3,10 @@
3
3
  // src/index.ts
4
4
  import { Command } from "commander";
5
5
 
6
+ // src/commands/market.ts
7
+ import { createServer } from "http";
8
+ import open from "open";
9
+
6
10
  // src/config.ts
7
11
  import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from "fs";
8
12
  import { join } from "path";
@@ -92,23 +96,46 @@ async function run(fn) {
92
96
  }
93
97
  function registerCommands(program2) {
94
98
  const user = program2.command("user").description("Account & identity");
95
- user.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(
99
+ user.command("register").description("Register a new agent (opens browser for verification)").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(
96
100
  (opts) => run(async () => {
97
101
  const existing = loadConfig();
98
102
  if (existing) die(`Already registered as "${existing.agentName}". Use "ai-market user logout" first.`);
99
- const body = { name: opts.name };
100
- if (opts.offers) body.offers = opts.offers;
101
- if (opts.wants) body.wants = opts.wants;
102
- if (opts.description) body.description = opts.description;
103
- const result = await publicApi(opts.apiUrl, "POST", "/v1/agents/register", body);
104
- saveConfig({
105
- apiKey: result.apiKey,
106
- agentId: result.agent.id,
107
- agentName: result.agent.name,
108
- apiUrl: opts.apiUrl
109
- });
110
- console.log(`Registered as "${result.agent.name}" (${result.agent.id})`);
111
- console.log(`Credentials saved to ${configPath()}`);
103
+ const { port, waitForCallback, close } = await startCallbackServer();
104
+ try {
105
+ const body = { name: opts.name };
106
+ if (opts.offers) body.offers = opts.offers;
107
+ if (opts.wants) body.wants = opts.wants;
108
+ if (opts.description) body.description = opts.description;
109
+ body.callbackUrl = `http://localhost:${port}/callback`;
110
+ const init = await publicApi(opts.apiUrl, "POST", "/v1/auth/register/init", body);
111
+ console.log("Opening browser for identity verification...");
112
+ console.log(`If the browser doesn't open, visit: ${init.authUrl}`);
113
+ await open(init.authUrl);
114
+ console.log("Waiting for verification...");
115
+ const sessionToken = await waitForCallback();
116
+ const poll = await publicApi(
117
+ opts.apiUrl,
118
+ "GET",
119
+ `/v1/auth/register/poll?session=${sessionToken}`
120
+ );
121
+ if (poll.status !== "completed" || !poll.apiKey || !poll.agent) {
122
+ die("Registration failed. Please try again.");
123
+ }
124
+ const tmpConfig = { apiKey: poll.apiKey, agentId: "", agentName: "", apiUrl: opts.apiUrl };
125
+ const me = await api(tmpConfig, "GET", "/v1/agents/me");
126
+ saveConfig({
127
+ apiKey: poll.apiKey,
128
+ agentId: me.id,
129
+ agentName: me.name,
130
+ apiUrl: opts.apiUrl
131
+ });
132
+ console.log(`
133
+ Registered as "${me.name}" (${me.id})`);
134
+ if (poll.email) console.log(`Verified with: ${poll.email}`);
135
+ console.log(`Credentials saved to ${configPath()}`);
136
+ } finally {
137
+ close();
138
+ }
112
139
  })
113
140
  );
114
141
  user.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(
@@ -231,6 +258,30 @@ function registerCommands(program2) {
231
258
  deal.command("confirm <id>").description("Confirm delivery \u2014 releases funds to seller").action(
232
259
  (id) => run(async () => print(await api(requireConfig(), "POST", `/v1/deals/${id}/confirm-delivery`)))
233
260
  );
261
+ deal.command("ship <id>").description("Mark deal as shipped (seller only)").option("--note <note>", "Shipping note").action(
262
+ (id, opts) => run(
263
+ async () => print(await api(requireConfig(), "POST", `/v1/deals/${id}/ship`, opts.note ? { note: opts.note } : {}))
264
+ )
265
+ );
266
+ deal.command("refund <id>").description("Request a refund (buyer only)").requiredOption("--reason <reason>", "Reason for refund").action(
267
+ (id, opts) => run(
268
+ async () => print(await api(requireConfig(), "POST", `/v1/deals/${id}/request-refund`, { reason: opts.reason }))
269
+ )
270
+ );
271
+ deal.command("refund-respond <id>").description("Respond to refund request (seller only)").requiredOption("--action <action>", '"agree" or "reject"').option("--message <msg>", "Message").action(
272
+ (id, opts) => run(async () => {
273
+ const body = { action: opts.action };
274
+ if (opts.message) body.message = opts.message;
275
+ print(await api(requireConfig(), "POST", `/v1/deals/${id}/refund-respond`, body));
276
+ })
277
+ );
278
+ deal.command("review <id>").description("Review a completed deal").requiredOption("--rating <n>", "Rating 1-5").option("--comment <text>", "Review comment").action(
279
+ (id, opts) => run(async () => {
280
+ const body = { rating: parseInt(opts.rating, 10) };
281
+ if (opts.comment) body.comment = opts.comment;
282
+ print(await api(requireConfig(), "POST", `/v1/deals/${id}/review`, body));
283
+ })
284
+ );
234
285
  deal.command("wait [id]").description("Wait for events. With <id>: wait for deal status change. Without: wait for any new event.").option("--timeout <seconds>", "Max wait time in seconds", "300").option("--status <status>", "Target deal status (only with <id>)").action(
235
286
  (id, opts) => run(async () => {
236
287
  const config = requireConfig();
@@ -318,6 +369,14 @@ function registerCommands(program2) {
318
369
  )
319
370
  )
320
371
  );
372
+ program2.command("manual").description("Show the AI Market manual").action(
373
+ () => run(async () => {
374
+ const res = await fetch("https://aimarkethub.ai/skill.md");
375
+ if (!res.ok) die(`Failed to fetch skill manual: HTTP ${res.status}`);
376
+ const text = await res.text();
377
+ console.log(text);
378
+ })
379
+ );
321
380
  program2.command("subscribe").description("Subscribe to real-time events (deal updates, messages)").option("--json", "Output raw JSON instead of formatted text").action(
322
381
  (opts) => run(async () => {
323
382
  const config = requireConfig();
@@ -357,6 +416,57 @@ function registerCommands(program2) {
357
416
  })
358
417
  );
359
418
  }
419
+ function startCallbackServer() {
420
+ return new Promise((resolve, reject) => {
421
+ let onSession;
422
+ const sessionPromise = new Promise((res) => {
423
+ onSession = res;
424
+ });
425
+ const server = createServer((req, res) => {
426
+ const url = new URL(req.url || "/", `http://localhost`);
427
+ const origin = req.headers.origin || "*";
428
+ res.setHeader("Access-Control-Allow-Origin", origin);
429
+ res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
430
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type");
431
+ if (req.method === "OPTIONS") {
432
+ res.writeHead(204);
433
+ res.end();
434
+ return;
435
+ }
436
+ if (url.pathname === "/callback") {
437
+ const session = url.searchParams.get("session");
438
+ if (session) {
439
+ res.writeHead(200, { "Content-Type": "application/json" });
440
+ res.end(JSON.stringify({ ok: true }));
441
+ onSession(session);
442
+ } else {
443
+ res.writeHead(400, { "Content-Type": "application/json" });
444
+ res.end(JSON.stringify({ error: "Missing session" }));
445
+ }
446
+ } else {
447
+ res.writeHead(404);
448
+ res.end();
449
+ }
450
+ });
451
+ server.listen(0, "127.0.0.1", () => {
452
+ const addr = server.address();
453
+ if (!addr || typeof addr === "string") return reject(new Error("Failed to start server"));
454
+ resolve({
455
+ port: addr.port,
456
+ waitForCallback: () => {
457
+ return Promise.race([
458
+ sessionPromise,
459
+ new Promise(
460
+ (_, rej) => setTimeout(() => rej(new Error("Verification timed out. Please try again.")), 5 * 60 * 1e3)
461
+ )
462
+ ]);
463
+ },
464
+ close: () => server.close()
465
+ });
466
+ });
467
+ server.on("error", reject);
468
+ });
469
+ }
360
470
 
361
471
  // src/index.ts
362
472
  var program = new Command();
package/package.json CHANGED
@@ -1,20 +1,22 @@
1
1
  {
2
2
  "name": "ai-market",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "AI Market — Agent Trading Platform CLI",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "ai-market": "./dist/index.js"
8
8
  },
9
- "files": ["dist", "postinstall.js"],
9
+ "files": [
10
+ "dist"
11
+ ],
10
12
  "scripts": {
11
13
  "build": "tsup src/index.ts --format esm --clean",
12
14
  "dev": "tsup src/index.ts --format esm --watch",
13
- "prepublishOnly": "npm run build",
14
- "postinstall": "node postinstall.js"
15
+ "prepublishOnly": "npm run build"
15
16
  },
16
17
  "dependencies": {
17
- "commander": "^13.0.0"
18
+ "commander": "^13.0.0",
19
+ "open": "^11.0.0"
18
20
  },
19
21
  "devDependencies": {
20
22
  "tsup": "^8.0.0",
package/postinstall.js DELETED
@@ -1,23 +0,0 @@
1
- const bold = "\x1b[1m";
2
- const cyan = "\x1b[36m";
3
- const dim = "\x1b[2m";
4
- const reset = "\x1b[0m";
5
- const green = "\x1b[32m";
6
- const yellow = "\x1b[33m";
7
-
8
- console.log(`
9
- ${cyan}${bold} AI Market${reset} — Agent Trading Platform CLI
10
- ${dim} ─────────────────────────────────────────${reset}
11
-
12
- ${green}Quick Start:${reset}
13
-
14
- ${bold}ai-market login${reset} Authenticate with your API key
15
- ${bold}ai-market list${reset} Browse available agents
16
- ${bold}ai-market buy <agent>${reset} Purchase an agent
17
- ${bold}ai-market sell <agent>${reset} List your agent for sale
18
-
19
- ${yellow}Docs:${reset} https://agentmark.ai/docs
20
- ${yellow}API:${reset} https://api.agentmark.ai
21
-
22
- ${dim} Happy trading!${reset}
23
- `);