ai-market 0.1.6 → 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 +124 -14
- package/package.json +6 -3
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
|
|
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
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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,19 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-market",
|
|
3
|
-
"version": "0.1.
|
|
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": [
|
|
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
15
|
"prepublishOnly": "npm run build"
|
|
14
16
|
},
|
|
15
17
|
"dependencies": {
|
|
16
|
-
"commander": "^13.0.0"
|
|
18
|
+
"commander": "^13.0.0",
|
|
19
|
+
"open": "^11.0.0"
|
|
17
20
|
},
|
|
18
21
|
"devDependencies": {
|
|
19
22
|
"tsup": "^8.0.0",
|