@hedge-layer/cli 1.0.0 → 1.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.
- package/README.md +36 -3
- package/dist/index.mjs +287 -98
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -20,7 +20,10 @@ Requires Node.js 22 or later.
|
|
|
20
20
|
# 2. Authenticate the CLI
|
|
21
21
|
hl auth login
|
|
22
22
|
|
|
23
|
-
# 3.
|
|
23
|
+
# 3. Generate a Market Brief
|
|
24
|
+
hl brief "US China trade war tariffs"
|
|
25
|
+
|
|
26
|
+
# 4. Or start an interactive research session
|
|
24
27
|
hl research
|
|
25
28
|
```
|
|
26
29
|
|
|
@@ -42,12 +45,40 @@ hl --token hl_abc123... research list
|
|
|
42
45
|
|
|
43
46
|
## Commands
|
|
44
47
|
|
|
48
|
+
### Brief
|
|
49
|
+
|
|
50
|
+
Generate a Market Brief directly from a topic — no Q&A, no interactive session. The AI researches current events, discovers relevant prediction markets, and synthesizes a structured brief with causal reasoning and coverage gaps.
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# Generate a brief (streams progress to stderr, brief to stdout)
|
|
54
|
+
hl brief "US China trade war tariffs"
|
|
55
|
+
hl brief "hurricane season impact on Florida" --location "US Southeast" --time-horizon "6 months"
|
|
56
|
+
|
|
57
|
+
# Pipe the brief as JSON
|
|
58
|
+
hl --json brief "crypto regulation 2026" | jq '.markets'
|
|
59
|
+
|
|
60
|
+
# Filter by tags and volume
|
|
61
|
+
hl brief "energy policy" --tags "geopolitics,energy" --min-volume 10000
|
|
62
|
+
|
|
63
|
+
# Disable streaming (block until complete)
|
|
64
|
+
hl brief "AI regulation in Europe" --no-stream
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
| Option | Description |
|
|
68
|
+
|--------|-------------|
|
|
69
|
+
| `-l, --location <loc>` | Geographic context (e.g. `"Middle East"`, `"US"`) |
|
|
70
|
+
| `-t, --time-horizon <h>` | Time frame (e.g. `"3 months"`, `"2026"`) |
|
|
71
|
+
| `--tags <tags>` | Comma-separated focus area tags (e.g. `"geopolitics,energy"`) |
|
|
72
|
+
| `--min-volume <n>` | Minimum market volume in USD |
|
|
73
|
+
| `--max-yes-price <n>` | Maximum YES price (0-1) |
|
|
74
|
+
| `--no-stream` | Disable streaming — block until complete |
|
|
75
|
+
|
|
45
76
|
### Research
|
|
46
77
|
|
|
47
|
-
AI-powered
|
|
78
|
+
AI-powered interactive research sessions. Describe a topic or thesis, and the AI researches current events, discovers relevant prediction markets, and synthesizes a structured Market Brief through a multi-turn conversation.
|
|
48
79
|
|
|
49
80
|
```bash
|
|
50
|
-
# Start an interactive research session
|
|
81
|
+
# Start an interactive research session (Q&A)
|
|
51
82
|
hl research
|
|
52
83
|
|
|
53
84
|
# List past research sessions
|
|
@@ -61,6 +92,8 @@ hl research show <id>
|
|
|
61
92
|
hl research delete <id>
|
|
62
93
|
```
|
|
63
94
|
|
|
95
|
+
For non-interactive, single-shot brief generation, use `hl brief` — it uses a dedicated API endpoint optimized for programmatic use.
|
|
96
|
+
|
|
64
97
|
### Markets
|
|
65
98
|
|
|
66
99
|
Polymarket orderbook tools.
|
package/dist/index.mjs
CHANGED
|
@@ -149,6 +149,23 @@ var ApiClient = class {
|
|
|
149
149
|
}
|
|
150
150
|
return res.body;
|
|
151
151
|
}
|
|
152
|
+
async streamNdjson(path, body) {
|
|
153
|
+
this.log("POST (ndjson)", path);
|
|
154
|
+
const res = await fetch(`${this.baseUrl}${path}`, {
|
|
155
|
+
method: "POST",
|
|
156
|
+
headers: this.headers({ Accept: "application/x-ndjson" }),
|
|
157
|
+
body: JSON.stringify(body)
|
|
158
|
+
});
|
|
159
|
+
this.log("POST (ndjson)", path, res.status);
|
|
160
|
+
if (!res.ok) {
|
|
161
|
+
const text = await res.text();
|
|
162
|
+
throw new ApiError(res.status, text);
|
|
163
|
+
}
|
|
164
|
+
if (!res.body) {
|
|
165
|
+
throw new ApiError(0, "No response body for stream");
|
|
166
|
+
}
|
|
167
|
+
return res.body;
|
|
168
|
+
}
|
|
152
169
|
};
|
|
153
170
|
var ApiError = class extends Error {
|
|
154
171
|
constructor(status, body) {
|
|
@@ -313,82 +330,8 @@ function registerAuthCommands(program2) {
|
|
|
313
330
|
});
|
|
314
331
|
}
|
|
315
332
|
|
|
316
|
-
// src/commands/
|
|
333
|
+
// src/commands/brief.ts
|
|
317
334
|
import chalk2 from "chalk";
|
|
318
|
-
function registerMarketCommands(program2) {
|
|
319
|
-
const markets = program2.command("markets").description("Polymarket orderbook tools");
|
|
320
|
-
markets.command("orderbook <tokenId>").description("Show orderbook spread and depth for a CLOB token").option("-s, --size <n>", "Size for slippage calculation").action(async (tokenId, cmdOpts) => {
|
|
321
|
-
const globalOpts = program2.opts();
|
|
322
|
-
const client = new ApiClient(globalOpts);
|
|
323
|
-
const params = { tokenId };
|
|
324
|
-
if (cmdOpts.size) params.size = cmdOpts.size;
|
|
325
|
-
const data = await client.get("/api/orderbook", params);
|
|
326
|
-
if (globalOpts.json) {
|
|
327
|
-
json(data);
|
|
328
|
-
return;
|
|
329
|
-
}
|
|
330
|
-
heading("Orderbook");
|
|
331
|
-
if (data.spread) {
|
|
332
|
-
table([
|
|
333
|
-
["Best Bid", data.spread.bid.toFixed(4)],
|
|
334
|
-
["Best Ask", data.spread.ask.toFixed(4)],
|
|
335
|
-
["Spread", percent(data.spread.spread)],
|
|
336
|
-
["Ask Depth", currency(data.askDepth)]
|
|
337
|
-
]);
|
|
338
|
-
} else {
|
|
339
|
-
warn("No spread data available (empty orderbook)");
|
|
340
|
-
}
|
|
341
|
-
if (data.slippage) {
|
|
342
|
-
process.stdout.write("\n");
|
|
343
|
-
table([
|
|
344
|
-
["Avg Fill Price", data.slippage.avgPrice.toFixed(4)],
|
|
345
|
-
["Worst Price", data.slippage.worstPrice.toFixed(4)],
|
|
346
|
-
["Slippage", percent(data.slippage.slippage)],
|
|
347
|
-
["Fillable Size", currency(data.slippage.fillableSize)]
|
|
348
|
-
]);
|
|
349
|
-
}
|
|
350
|
-
if (data.book.asks.length > 0) {
|
|
351
|
-
process.stdout.write("\n" + chalk2.dim(" Top 5 asks:") + "\n");
|
|
352
|
-
const askRows = data.book.asks.slice(0, 5).map((l) => [l.price, l.size]);
|
|
353
|
-
table(askRows, ["Price", "Size"]);
|
|
354
|
-
}
|
|
355
|
-
if (data.book.bids.length > 0) {
|
|
356
|
-
process.stdout.write("\n" + chalk2.dim(" Top 5 bids:") + "\n");
|
|
357
|
-
const bidRows = data.book.bids.slice(0, 5).map((l) => [l.price, l.size]);
|
|
358
|
-
table(bidRows, ["Price", "Size"]);
|
|
359
|
-
}
|
|
360
|
-
});
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
// src/commands/profile.ts
|
|
364
|
-
function registerProfileCommand(program2) {
|
|
365
|
-
program2.command("profile").description("Show your user profile").action(async () => {
|
|
366
|
-
const globalOpts = program2.opts();
|
|
367
|
-
const client = new ApiClient(globalOpts);
|
|
368
|
-
requireAuth(client);
|
|
369
|
-
const profile = await client.get("/api/profile");
|
|
370
|
-
if (globalOpts.json) {
|
|
371
|
-
json(profile);
|
|
372
|
-
return;
|
|
373
|
-
}
|
|
374
|
-
heading("Profile");
|
|
375
|
-
table([
|
|
376
|
-
["Handle", bold(profile.handle || "(none)")],
|
|
377
|
-
["User ID", profile.user_id],
|
|
378
|
-
["Created", new Date(profile.created_at).toLocaleDateString()]
|
|
379
|
-
]);
|
|
380
|
-
});
|
|
381
|
-
}
|
|
382
|
-
function requireAuth(client) {
|
|
383
|
-
if (!client.isAuthenticated) {
|
|
384
|
-
error("Not logged in. Run " + bold("hl auth login") + " first.");
|
|
385
|
-
process.exit(1);
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
// src/commands/research.ts
|
|
390
|
-
import readline2 from "readline/promises";
|
|
391
|
-
import chalk3 from "chalk";
|
|
392
335
|
|
|
393
336
|
// src/stream.ts
|
|
394
337
|
async function parseStream(body, callbacks = {}) {
|
|
@@ -478,18 +421,244 @@ async function parseStream(body, callbacks = {}) {
|
|
|
478
421
|
function isMarketBrief(val) {
|
|
479
422
|
return val !== null && typeof val === "object" && "title" in val && "markets" in val;
|
|
480
423
|
}
|
|
424
|
+
async function parseNdjsonStream(body, callbacks = {}) {
|
|
425
|
+
const decoder = new TextDecoder();
|
|
426
|
+
const reader = body.getReader();
|
|
427
|
+
let buffer = "";
|
|
428
|
+
let brief = null;
|
|
429
|
+
let error2 = null;
|
|
430
|
+
while (true) {
|
|
431
|
+
const { done, value } = await reader.read();
|
|
432
|
+
if (!done) {
|
|
433
|
+
buffer += decoder.decode(value, { stream: true });
|
|
434
|
+
}
|
|
435
|
+
const lines = buffer.split("\n");
|
|
436
|
+
buffer = done ? "" : lines.pop() ?? "";
|
|
437
|
+
for (const line of lines) {
|
|
438
|
+
const trimmed = line.trim();
|
|
439
|
+
if (!trimmed) continue;
|
|
440
|
+
let msg;
|
|
441
|
+
try {
|
|
442
|
+
msg = JSON.parse(trimmed);
|
|
443
|
+
} catch {
|
|
444
|
+
continue;
|
|
445
|
+
}
|
|
446
|
+
const type = msg.type;
|
|
447
|
+
switch (type) {
|
|
448
|
+
case "progress": {
|
|
449
|
+
callbacks.onProgress?.(msg.step, msg.message);
|
|
450
|
+
break;
|
|
451
|
+
}
|
|
452
|
+
case "brief": {
|
|
453
|
+
brief = msg.data;
|
|
454
|
+
break;
|
|
455
|
+
}
|
|
456
|
+
case "error": {
|
|
457
|
+
error2 = {
|
|
458
|
+
code: msg.code,
|
|
459
|
+
message: msg.message
|
|
460
|
+
};
|
|
461
|
+
break;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
if (done) break;
|
|
466
|
+
}
|
|
467
|
+
return { brief, error: error2 };
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// src/commands/brief.ts
|
|
471
|
+
function registerBriefCommands(program2) {
|
|
472
|
+
program2.command("brief <query>").description("Generate a Market Brief for a topic (non-interactive)").option("-l, --location <location>", "Geographic context (e.g. 'Middle East', 'US')").option("-t, --time-horizon <horizon>", "Time frame (e.g. '3 months', '2026')").option("--tags <tags>", "Comma-separated focus area tags (e.g. 'geopolitics,energy')").option("--min-volume <n>", "Minimum market volume in USD", parseFloat).option("--max-yes-price <n>", "Maximum YES price (0-1)", parseFloat).option("--no-stream", "Disable streaming \u2014 block until complete").action(async (query, cmdOpts) => {
|
|
473
|
+
const globalOpts = program2.opts();
|
|
474
|
+
const client = new ApiClient(globalOpts);
|
|
475
|
+
requireAuth(client);
|
|
476
|
+
const filters = buildFilters(cmdOpts);
|
|
477
|
+
const body = {
|
|
478
|
+
query,
|
|
479
|
+
...cmdOpts.location && { location: cmdOpts.location },
|
|
480
|
+
...cmdOpts.timeHorizon && { timeHorizon: cmdOpts.timeHorizon },
|
|
481
|
+
...filters && { filters },
|
|
482
|
+
stream: cmdOpts.stream !== false
|
|
483
|
+
};
|
|
484
|
+
if (body.stream) {
|
|
485
|
+
await runStreaming(client, body, globalOpts);
|
|
486
|
+
} else {
|
|
487
|
+
await runBlocking(client, body, globalOpts);
|
|
488
|
+
}
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
function buildFilters(opts) {
|
|
492
|
+
const tags = opts.tags?.split(",").map((t) => t.trim()).filter(Boolean);
|
|
493
|
+
const hasFilters = opts.minVolume != null || opts.maxYesPrice != null || tags && tags.length > 0;
|
|
494
|
+
if (!hasFilters) return void 0;
|
|
495
|
+
return {
|
|
496
|
+
...opts.minVolume != null && { minVolume: opts.minVolume },
|
|
497
|
+
...opts.maxYesPrice != null && { maxYesPrice: opts.maxYesPrice },
|
|
498
|
+
...tags && tags.length > 0 && { tags }
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
async function runStreaming(client, body, globalOpts) {
|
|
502
|
+
const startTime = Date.now();
|
|
503
|
+
process.stderr.write(chalk2.dim(` Generating brief for "${truncate(body.query, 50)}"...
|
|
504
|
+
`));
|
|
505
|
+
const stream = await client.streamNdjson("/api/brief", body);
|
|
506
|
+
const result = await parseNdjsonStream(stream, {
|
|
507
|
+
onProgress: (step, message) => {
|
|
508
|
+
process.stderr.write(chalk2.dim(` [${step}] `) + message + "\n");
|
|
509
|
+
}
|
|
510
|
+
});
|
|
511
|
+
const elapsed = ((Date.now() - startTime) / 1e3).toFixed(1);
|
|
512
|
+
if (result.error) {
|
|
513
|
+
error(`Brief failed (${result.error.code}): ${result.error.message}`);
|
|
514
|
+
process.exit(1);
|
|
515
|
+
}
|
|
516
|
+
if (!result.brief) {
|
|
517
|
+
error("No Market Brief was produced.");
|
|
518
|
+
process.exit(1);
|
|
519
|
+
}
|
|
520
|
+
process.stderr.write(chalk2.dim(` Done (${elapsed}s)
|
|
521
|
+
|
|
522
|
+
`));
|
|
523
|
+
displayBrief(result.brief, globalOpts);
|
|
524
|
+
}
|
|
525
|
+
async function runBlocking(client, body, globalOpts) {
|
|
526
|
+
const startTime = Date.now();
|
|
527
|
+
process.stderr.write(chalk2.dim(` Generating brief for "${truncate(body.query, 50)}"...
|
|
528
|
+
`));
|
|
529
|
+
const brief = await client.post("/api/brief", body);
|
|
530
|
+
const elapsed = ((Date.now() - startTime) / 1e3).toFixed(1);
|
|
531
|
+
process.stderr.write(chalk2.dim(` Done (${elapsed}s)
|
|
532
|
+
|
|
533
|
+
`));
|
|
534
|
+
displayBrief(brief, globalOpts);
|
|
535
|
+
}
|
|
536
|
+
function displayBrief(brief, globalOpts) {
|
|
537
|
+
if (globalOpts.json) {
|
|
538
|
+
json(brief);
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
541
|
+
heading("Market Brief");
|
|
542
|
+
process.stdout.write(" " + chalk2.bold(brief.title) + "\n\n");
|
|
543
|
+
process.stdout.write(" " + chalk2.italic(brief.thesis) + "\n");
|
|
544
|
+
if (brief.markets.length > 0) {
|
|
545
|
+
process.stdout.write("\n" + chalk2.bold(" Markets") + "\n\n");
|
|
546
|
+
const rows = brief.markets.map((m) => {
|
|
547
|
+
const prob = percent(m.yesPrice);
|
|
548
|
+
const signals = m.signals.length > 0 ? m.signals.join(", ") : "\u2014";
|
|
549
|
+
const liq = m.liquidity ? currency(m.liquidity) : "\u2014";
|
|
550
|
+
return [truncate(m.question, 40), prob, signals, liq];
|
|
551
|
+
});
|
|
552
|
+
table(rows, ["Market", "Prob", "Signals", "Liq"]);
|
|
553
|
+
process.stdout.write("\n");
|
|
554
|
+
for (const m of brief.markets) {
|
|
555
|
+
process.stdout.write(" " + chalk2.dim("\u25B8 ") + truncate(m.question, 50) + "\n");
|
|
556
|
+
process.stdout.write(" " + chalk2.dim("Causal link: ") + m.causalLink + "\n");
|
|
557
|
+
process.stdout.write(" " + chalk2.dim("Polymarket: ") + m.polymarketUrl + "\n");
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
if (brief.gaps.length > 0) {
|
|
561
|
+
process.stdout.write("\n" + chalk2.bold(" Coverage Gaps") + "\n\n");
|
|
562
|
+
for (const gap of brief.gaps) {
|
|
563
|
+
process.stdout.write(" " + chalk2.yellow("\u25B8") + " " + gap + "\n");
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
const marketCount = brief.marketCount ?? brief.markets.length;
|
|
567
|
+
process.stdout.write("\n " + chalk2.dim(`${marketCount} markets \xB7 ${brief.gaps.length} coverage gaps`) + "\n");
|
|
568
|
+
}
|
|
569
|
+
function requireAuth(client) {
|
|
570
|
+
if (!client.isAuthenticated) {
|
|
571
|
+
error("Not logged in. Run " + bold("hl auth login") + " first.");
|
|
572
|
+
process.exit(1);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
// src/commands/markets.ts
|
|
577
|
+
import chalk3 from "chalk";
|
|
578
|
+
function registerMarketCommands(program2) {
|
|
579
|
+
const markets = program2.command("markets").description("Polymarket orderbook tools");
|
|
580
|
+
markets.command("orderbook <tokenId>").description("Show orderbook spread and depth for a CLOB token").option("-s, --size <n>", "Size for slippage calculation").action(async (tokenId, cmdOpts) => {
|
|
581
|
+
const globalOpts = program2.opts();
|
|
582
|
+
const client = new ApiClient(globalOpts);
|
|
583
|
+
const params = { tokenId };
|
|
584
|
+
if (cmdOpts.size) params.size = cmdOpts.size;
|
|
585
|
+
const data = await client.get("/api/orderbook", params);
|
|
586
|
+
if (globalOpts.json) {
|
|
587
|
+
json(data);
|
|
588
|
+
return;
|
|
589
|
+
}
|
|
590
|
+
heading("Orderbook");
|
|
591
|
+
if (data.spread) {
|
|
592
|
+
table([
|
|
593
|
+
["Best Bid", data.spread.bid.toFixed(4)],
|
|
594
|
+
["Best Ask", data.spread.ask.toFixed(4)],
|
|
595
|
+
["Spread", percent(data.spread.spread)],
|
|
596
|
+
["Ask Depth", currency(data.askDepth)]
|
|
597
|
+
]);
|
|
598
|
+
} else {
|
|
599
|
+
warn("No spread data available (empty orderbook)");
|
|
600
|
+
}
|
|
601
|
+
if (data.slippage) {
|
|
602
|
+
process.stdout.write("\n");
|
|
603
|
+
table([
|
|
604
|
+
["Avg Fill Price", data.slippage.avgPrice.toFixed(4)],
|
|
605
|
+
["Worst Price", data.slippage.worstPrice.toFixed(4)],
|
|
606
|
+
["Slippage", percent(data.slippage.slippage)],
|
|
607
|
+
["Fillable Size", currency(data.slippage.fillableSize)]
|
|
608
|
+
]);
|
|
609
|
+
}
|
|
610
|
+
if (data.book.asks.length > 0) {
|
|
611
|
+
process.stdout.write("\n" + chalk3.dim(" Top 5 asks:") + "\n");
|
|
612
|
+
const askRows = data.book.asks.slice(0, 5).map((l) => [l.price, l.size]);
|
|
613
|
+
table(askRows, ["Price", "Size"]);
|
|
614
|
+
}
|
|
615
|
+
if (data.book.bids.length > 0) {
|
|
616
|
+
process.stdout.write("\n" + chalk3.dim(" Top 5 bids:") + "\n");
|
|
617
|
+
const bidRows = data.book.bids.slice(0, 5).map((l) => [l.price, l.size]);
|
|
618
|
+
table(bidRows, ["Price", "Size"]);
|
|
619
|
+
}
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
// src/commands/profile.ts
|
|
624
|
+
function registerProfileCommand(program2) {
|
|
625
|
+
program2.command("profile").description("Show your user profile").action(async () => {
|
|
626
|
+
const globalOpts = program2.opts();
|
|
627
|
+
const client = new ApiClient(globalOpts);
|
|
628
|
+
requireAuth2(client);
|
|
629
|
+
const profile = await client.get("/api/profile");
|
|
630
|
+
if (globalOpts.json) {
|
|
631
|
+
json(profile);
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
heading("Profile");
|
|
635
|
+
table([
|
|
636
|
+
["Handle", bold(profile.handle || "(none)")],
|
|
637
|
+
["User ID", profile.user_id],
|
|
638
|
+
["Created", new Date(profile.created_at).toLocaleDateString()]
|
|
639
|
+
]);
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
function requireAuth2(client) {
|
|
643
|
+
if (!client.isAuthenticated) {
|
|
644
|
+
error("Not logged in. Run " + bold("hl auth login") + " first.");
|
|
645
|
+
process.exit(1);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
481
648
|
|
|
482
649
|
// src/commands/research.ts
|
|
650
|
+
import readline2 from "readline/promises";
|
|
651
|
+
import chalk4 from "chalk";
|
|
483
652
|
function registerResearchCommands(program2) {
|
|
484
653
|
const research = program2.command("research").description("AI-powered market research");
|
|
485
654
|
research.command("start", { isDefault: true }).description("Start an interactive market research session").action(async () => {
|
|
486
655
|
const globalOpts = program2.opts();
|
|
487
656
|
const client = new ApiClient(globalOpts);
|
|
488
|
-
|
|
657
|
+
requireAuth3(client);
|
|
489
658
|
const { id } = await client.post("/api/assessments");
|
|
490
659
|
heading("Market Research");
|
|
491
660
|
process.stderr.write(
|
|
492
|
-
|
|
661
|
+
chalk4.dim(" Describe a topic or thesis to explore. Type /quit to exit.\n\n")
|
|
493
662
|
);
|
|
494
663
|
let msgCounter = 0;
|
|
495
664
|
const uiMsg = (role, content) => ({
|
|
@@ -502,11 +671,11 @@ function registerResearchCommands(program2) {
|
|
|
502
671
|
const rl = readline2.createInterface({ input: process.stdin, output: process.stderr });
|
|
503
672
|
try {
|
|
504
673
|
while (true) {
|
|
505
|
-
const userInput = await rl.question(
|
|
674
|
+
const userInput = await rl.question(chalk4.cyan("You: "));
|
|
506
675
|
if (!userInput.trim()) continue;
|
|
507
676
|
if (userInput.trim() === "/quit") break;
|
|
508
677
|
messages.push(uiMsg("user", userInput));
|
|
509
|
-
process.stderr.write(
|
|
678
|
+
process.stderr.write(chalk4.dim("\nAssistant: "));
|
|
510
679
|
try {
|
|
511
680
|
const body = await client.stream("/api/chat", {
|
|
512
681
|
messages,
|
|
@@ -515,13 +684,13 @@ function registerResearchCommands(program2) {
|
|
|
515
684
|
const result = await parseStream(body, {
|
|
516
685
|
onText: (text) => process.stderr.write(text),
|
|
517
686
|
onToolCall: (name) => {
|
|
518
|
-
process.stderr.write(
|
|
687
|
+
process.stderr.write(chalk4.dim(`
|
|
519
688
|
[tool: ${name}]
|
|
520
689
|
`));
|
|
521
690
|
},
|
|
522
691
|
onToolResult: (name, toolResult) => {
|
|
523
692
|
if (globalOpts.verbose) {
|
|
524
|
-
process.stderr.write(
|
|
693
|
+
process.stderr.write(chalk4.dim(` [result: ${name}] ${JSON.stringify(toolResult).slice(0, 200)}
|
|
525
694
|
`));
|
|
526
695
|
}
|
|
527
696
|
}
|
|
@@ -543,10 +712,29 @@ function registerResearchCommands(program2) {
|
|
|
543
712
|
rl.close();
|
|
544
713
|
}
|
|
545
714
|
});
|
|
715
|
+
research.command("run <query>").description("Run research on a topic and return the final brief as JSON").action(async (query) => {
|
|
716
|
+
const globalOpts = program2.opts();
|
|
717
|
+
const client = new ApiClient(globalOpts);
|
|
718
|
+
requireAuth3(client);
|
|
719
|
+
process.stderr.write(chalk4.dim(` Researching "${truncate(query, 60)}"...
|
|
720
|
+
`));
|
|
721
|
+
const startTime = Date.now();
|
|
722
|
+
const result = await client.post("/api/research", { query });
|
|
723
|
+
const elapsed = ((Date.now() - startTime) / 1e3).toFixed(1);
|
|
724
|
+
process.stderr.write(chalk4.dim(` Done (${elapsed}s)
|
|
725
|
+
|
|
726
|
+
`));
|
|
727
|
+
if (result.brief) {
|
|
728
|
+
json(result.brief);
|
|
729
|
+
} else {
|
|
730
|
+
process.stderr.write(chalk4.yellow("No market brief was produced.\n"));
|
|
731
|
+
json(result);
|
|
732
|
+
}
|
|
733
|
+
});
|
|
546
734
|
research.command("list").description("List past research sessions").option("-s, --status <status>", "Filter by status").action(async (cmdOpts) => {
|
|
547
735
|
const globalOpts = program2.opts();
|
|
548
736
|
const client = new ApiClient(globalOpts);
|
|
549
|
-
|
|
737
|
+
requireAuth3(client);
|
|
550
738
|
const params = { list: "true" };
|
|
551
739
|
if (cmdOpts.status) params.status = cmdOpts.status;
|
|
552
740
|
const data = await client.get("/api/assessments", params);
|
|
@@ -570,7 +758,7 @@ function registerResearchCommands(program2) {
|
|
|
570
758
|
research.command("show <id>").description("Show research session details").action(async (id) => {
|
|
571
759
|
const globalOpts = program2.opts();
|
|
572
760
|
const client = new ApiClient(globalOpts);
|
|
573
|
-
|
|
761
|
+
requireAuth3(client);
|
|
574
762
|
const assessment = await client.get(`/api/assessments/${id}`);
|
|
575
763
|
if (globalOpts.json) {
|
|
576
764
|
json(assessment);
|
|
@@ -589,12 +777,12 @@ function registerResearchCommands(program2) {
|
|
|
589
777
|
research.command("delete <id>").description("Delete a research session").action(async (id) => {
|
|
590
778
|
const globalOpts = program2.opts();
|
|
591
779
|
const client = new ApiClient(globalOpts);
|
|
592
|
-
|
|
780
|
+
requireAuth3(client);
|
|
593
781
|
await client.delete(`/api/assessments/${id}`);
|
|
594
782
|
success("Research session deleted.");
|
|
595
783
|
});
|
|
596
784
|
}
|
|
597
|
-
function
|
|
785
|
+
function requireAuth3(client) {
|
|
598
786
|
if (!client.isAuthenticated) {
|
|
599
787
|
error("Not logged in. Run " + bold("hl auth login") + " first.");
|
|
600
788
|
process.exit(1);
|
|
@@ -603,11 +791,11 @@ function requireAuth2(client) {
|
|
|
603
791
|
function formatStatus(status) {
|
|
604
792
|
switch (status) {
|
|
605
793
|
case "completed":
|
|
606
|
-
return
|
|
794
|
+
return chalk4.green(status);
|
|
607
795
|
case "in_progress":
|
|
608
|
-
return
|
|
796
|
+
return chalk4.yellow(status);
|
|
609
797
|
case "abandoned":
|
|
610
|
-
return
|
|
798
|
+
return chalk4.red(status);
|
|
611
799
|
default:
|
|
612
800
|
return status;
|
|
613
801
|
}
|
|
@@ -618,10 +806,10 @@ function displayMarketBrief(brief, globalOpts) {
|
|
|
618
806
|
return;
|
|
619
807
|
}
|
|
620
808
|
heading("Market Brief");
|
|
621
|
-
process.stdout.write(" " +
|
|
622
|
-
process.stdout.write(" " +
|
|
809
|
+
process.stdout.write(" " + chalk4.bold(brief.title) + "\n\n");
|
|
810
|
+
process.stdout.write(" " + chalk4.italic(brief.thesis) + "\n");
|
|
623
811
|
if (brief.markets.length > 0) {
|
|
624
|
-
process.stdout.write("\n" +
|
|
812
|
+
process.stdout.write("\n" + chalk4.bold(" Markets") + "\n\n");
|
|
625
813
|
const rows = brief.markets.map((m) => {
|
|
626
814
|
const prob = percent(m.yesPrice);
|
|
627
815
|
const signals = m.signals.length > 0 ? m.signals.join(", ") : "\u2014";
|
|
@@ -631,24 +819,25 @@ function displayMarketBrief(brief, globalOpts) {
|
|
|
631
819
|
table(rows, ["Market", "Prob", "Signals", "Liq"]);
|
|
632
820
|
process.stdout.write("\n");
|
|
633
821
|
for (const m of brief.markets) {
|
|
634
|
-
process.stdout.write(" " +
|
|
635
|
-
process.stdout.write(" " +
|
|
636
|
-
process.stdout.write(" " +
|
|
822
|
+
process.stdout.write(" " + chalk4.dim("\u25B8 ") + truncate(m.question, 50) + "\n");
|
|
823
|
+
process.stdout.write(" " + chalk4.dim("Causal link: ") + m.causalLink + "\n");
|
|
824
|
+
process.stdout.write(" " + chalk4.dim("Polymarket: ") + m.polymarketUrl + "\n");
|
|
637
825
|
}
|
|
638
826
|
}
|
|
639
827
|
if (brief.gaps.length > 0) {
|
|
640
|
-
process.stdout.write("\n" +
|
|
828
|
+
process.stdout.write("\n" + chalk4.bold(" Coverage Gaps") + "\n\n");
|
|
641
829
|
for (const gap of brief.gaps) {
|
|
642
|
-
process.stdout.write(" " +
|
|
830
|
+
process.stdout.write(" " + chalk4.yellow("\u25B8") + " " + gap + "\n");
|
|
643
831
|
}
|
|
644
832
|
}
|
|
645
|
-
process.stdout.write("\n " +
|
|
833
|
+
process.stdout.write("\n " + chalk4.dim(`${brief.marketCount} markets \xB7 ${brief.gaps.length} coverage gaps`) + "\n");
|
|
646
834
|
}
|
|
647
835
|
|
|
648
836
|
// src/index.ts
|
|
649
837
|
var program = new Command();
|
|
650
|
-
program.name("hl").description("Hedge Layer CLI \u2014 prediction market intelligence from the terminal").version("1.
|
|
838
|
+
program.name("hl").description("Hedge Layer CLI \u2014 prediction market intelligence from the terminal").version("1.1.0").option("--json", "Output as JSON (machine-readable)").option("--api-url <url>", "Override API base URL").option("--token <token>", "Override stored API token").option("--verbose", "Show HTTP request details").option("--no-color", "Disable colored output");
|
|
651
839
|
registerAuthCommands(program);
|
|
840
|
+
registerBriefCommands(program);
|
|
652
841
|
registerMarketCommands(program);
|
|
653
842
|
registerProfileCommand(program);
|
|
654
843
|
registerResearchCommands(program);
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/commands/auth.ts","../src/config.ts","../src/client.ts","../src/output.ts","../src/commands/markets.ts","../src/commands/profile.ts","../src/commands/research.ts","../src/stream.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { registerAuthCommands } from \"./commands/auth.js\";\nimport { registerMarketCommands } from \"./commands/markets.js\";\nimport { registerProfileCommand } from \"./commands/profile.js\";\nimport { registerResearchCommands } from \"./commands/research.js\";\nimport * as out from \"./output.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"hl\")\n .description(\"Hedge Layer CLI — prediction market intelligence from the terminal\")\n .version(__VERSION__)\n .option(\"--json\", \"Output as JSON (machine-readable)\")\n .option(\"--api-url <url>\", \"Override API base URL\")\n .option(\"--token <token>\", \"Override stored API token\")\n .option(\"--verbose\", \"Show HTTP request details\")\n .option(\"--no-color\", \"Disable colored output\");\n\nregisterAuthCommands(program);\nregisterMarketCommands(program);\nregisterProfileCommand(program);\nregisterResearchCommands(program);\n\nprogram.hook(\"preAction\", (_thisCommand, actionCommand) => {\n const opts = program.opts();\n if (opts.color === false) {\n process.env.FORCE_COLOR = \"0\";\n }\n if (opts.verbose) {\n const cmdName = actionCommand.name();\n process.stderr.write(out.dim(`[verbose] Running: hl ${cmdName}\\n`));\n }\n});\n\nasync function main() {\n try {\n await program.parseAsync(process.argv);\n } catch (e) {\n if (e instanceof Error && e.message.includes(\"API error\")) {\n out.error(e.message);\n } else {\n out.error(`Unexpected error: ${e instanceof Error ? e.message : String(e)}`);\n if (program.opts().verbose) {\n console.error(e);\n }\n }\n process.exit(1);\n }\n}\n\nmain();\n","import { Command } from \"commander\";\nimport readline from \"node:readline/promises\";\nimport { loadConfig, saveConfig, clearConfig, configPath, DEFAULT_API_URL } from \"../config.js\";\nimport { ApiClient } from \"../client.js\";\nimport type { UserProfile, GlobalOptions } from \"../types.js\";\nimport * as out from \"../output.js\";\n\nexport function registerAuthCommands(program: Command): void {\n const auth = program.command(\"auth\").description(\"Manage API authentication\");\n\n auth\n .command(\"login\")\n .description(\"Authenticate with a Hedge Layer API token\")\n .option(\"--api-url <url>\", \"API base URL\", DEFAULT_API_URL)\n .action(async (cmdOpts: { apiUrl?: string }) => {\n const globalOpts = program.opts<GlobalOptions>();\n\n const rl = readline.createInterface({ input: process.stdin, output: process.stderr });\n try {\n out.heading(\"Hedge Layer CLI — Login\");\n process.stderr.write(\n `Create an API token at ${out.bold(\"https://hedgelayer.ai/settings\")} → API Tokens\\n\\n`,\n );\n\n const token = (await rl.question(\"Paste your API token: \")).trim();\n\n if (!token.startsWith(\"hl_\") || token.length !== 43) {\n out.error('Invalid token format. Tokens start with \"hl_\" and are 43 characters.');\n process.exit(1);\n }\n\n const apiUrl = globalOpts.apiUrl ?? cmdOpts.apiUrl ?? DEFAULT_API_URL;\n const client = new ApiClient({ token, apiUrl });\n\n process.stderr.write(\"\\nValidating token...\");\n let profile: UserProfile;\n try {\n profile = await client.get<UserProfile>(\"/api/profile\");\n } catch {\n process.stderr.write(\"\\n\");\n out.error(\"Token validation failed. Check your token and try again.\");\n process.exit(1);\n }\n process.stderr.write(\" done\\n\\n\");\n\n saveConfig({ api_url: apiUrl, token });\n\n out.success(`Logged in as ${out.bold(profile.handle || profile.user_id)}`);\n process.stderr.write(` Config saved to ${out.dim(configPath())}\\n`);\n } finally {\n rl.close();\n }\n });\n\n auth\n .command(\"status\")\n .description(\"Show current authentication status\")\n .action(async () => {\n const globalOpts = program.opts<GlobalOptions>();\n const config = loadConfig();\n const token = globalOpts.token ?? config.token;\n\n if (!token) {\n out.warn(\"Not logged in. Run \" + out.bold(\"hl auth login\") + \" to authenticate.\");\n process.exit(1);\n }\n\n const client = new ApiClient(globalOpts);\n\n try {\n const profile = await client.get<UserProfile>(\"/api/profile\");\n if (globalOpts.json) {\n out.json({\n authenticated: true,\n handle: profile.handle,\n user_id: profile.user_id,\n api_url: client.apiUrl,\n });\n } else {\n out.heading(\"Auth Status\");\n out.table(\n [\n [\"Handle\", out.bold(profile.handle || \"(none)\")],\n [\"User ID\", profile.user_id],\n [\"API URL\", client.apiUrl],\n [\"Config\", configPath()],\n ],\n );\n }\n } catch {\n out.error(\"Token is invalid or expired. Run \" + out.bold(\"hl auth login\") + \" to re-authenticate.\");\n process.exit(1);\n }\n });\n\n auth\n .command(\"logout\")\n .description(\"Remove stored API token\")\n .action(() => {\n clearConfig();\n out.success(\"Logged out. Token removed from \" + out.dim(configPath()));\n });\n}\n","import { readFileSync, writeFileSync, mkdirSync, existsSync, unlinkSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\n\nconst CONFIG_DIR = join(homedir(), \".hedgelayer\");\nconst CONFIG_FILE = join(CONFIG_DIR, \"config.json\");\n\nexport const DEFAULT_API_URL = \"https://hedgelayer.ai\";\n\nexport interface Config {\n api_url: string;\n token: string | null;\n}\n\nfunction defaultConfig(): Config {\n return { api_url: DEFAULT_API_URL, token: null };\n}\n\nexport function loadConfig(): Config {\n try {\n if (!existsSync(CONFIG_FILE)) return defaultConfig();\n const raw = readFileSync(CONFIG_FILE, \"utf-8\");\n const parsed = JSON.parse(raw);\n return {\n api_url: parsed.api_url ?? DEFAULT_API_URL,\n token: parsed.token ?? null,\n };\n } catch {\n return defaultConfig();\n }\n}\n\nexport function saveConfig(config: Config): void {\n mkdirSync(CONFIG_DIR, { recursive: true });\n writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2) + \"\\n\", \"utf-8\");\n}\n\nexport function clearConfig(): void {\n try {\n if (existsSync(CONFIG_FILE)) unlinkSync(CONFIG_FILE);\n } catch {\n // ignore\n }\n}\n\nexport function configPath(): string {\n return CONFIG_FILE;\n}\n","import type { GlobalOptions } from \"./types.js\";\nimport { loadConfig, DEFAULT_API_URL } from \"./config.js\";\n\nexport class ApiClient {\n private baseUrl: string;\n private token: string | null;\n private verbose: boolean;\n\n constructor(opts: GlobalOptions = {}) {\n const config = loadConfig();\n this.baseUrl = (opts.apiUrl ?? config.api_url ?? DEFAULT_API_URL).replace(/\\/$/, \"\");\n this.token = opts.token ?? config.token ?? null;\n this.verbose = opts.verbose ?? false;\n }\n\n get isAuthenticated(): boolean {\n return this.token !== null;\n }\n\n get apiUrl(): string {\n return this.baseUrl;\n }\n\n private headers(extra: Record<string, string> = {}): Record<string, string> {\n const h: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...extra,\n };\n if (this.token) {\n h[\"Authorization\"] = `Bearer ${this.token}`;\n }\n return h;\n }\n\n private log(method: string, path: string, status?: number): void {\n if (!this.verbose) return;\n const statusStr = status ? ` → ${status}` : \"\";\n process.stderr.write(`[verbose] ${method} ${this.baseUrl}${path}${statusStr}\\n`);\n }\n\n async get<T>(path: string, params?: Record<string, string>): Promise<T> {\n const url = new URL(path, this.baseUrl);\n if (params) {\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined && v !== \"\") url.searchParams.set(k, v);\n }\n }\n\n this.log(\"GET\", `${url.pathname}${url.search}`);\n const res = await fetch(url.toString(), { headers: this.headers() });\n this.log(\"GET\", `${url.pathname}${url.search}`, res.status);\n\n if (!res.ok) {\n const body = await res.text();\n throw new ApiError(res.status, body);\n }\n return res.json() as Promise<T>;\n }\n\n async post<T>(path: string, body?: unknown): Promise<T> {\n this.log(\"POST\", path);\n const res = await fetch(`${this.baseUrl}${path}`, {\n method: \"POST\",\n headers: this.headers(),\n body: body !== undefined ? JSON.stringify(body) : undefined,\n });\n this.log(\"POST\", path, res.status);\n\n if (!res.ok) {\n const text = await res.text();\n throw new ApiError(res.status, text);\n }\n return res.json() as Promise<T>;\n }\n\n async patch<T>(path: string, body: unknown): Promise<T> {\n this.log(\"PATCH\", path);\n const res = await fetch(`${this.baseUrl}${path}`, {\n method: \"PATCH\",\n headers: this.headers(),\n body: JSON.stringify(body),\n });\n this.log(\"PATCH\", path, res.status);\n\n if (!res.ok) {\n const text = await res.text();\n throw new ApiError(res.status, text);\n }\n return res.json() as Promise<T>;\n }\n\n async delete(path: string): Promise<void> {\n this.log(\"DELETE\", path);\n const res = await fetch(`${this.baseUrl}${path}`, {\n method: \"DELETE\",\n headers: this.headers(),\n });\n this.log(\"DELETE\", path, res.status);\n\n if (!res.ok) {\n const text = await res.text();\n throw new ApiError(res.status, text);\n }\n }\n\n async stream(path: string, body: unknown): Promise<ReadableStream<Uint8Array>> {\n this.log(\"POST (stream)\", path);\n const res = await fetch(`${this.baseUrl}${path}`, {\n method: \"POST\",\n headers: this.headers({ Accept: \"text/event-stream\" }),\n body: JSON.stringify(body),\n });\n this.log(\"POST (stream)\", path, res.status);\n\n if (!res.ok) {\n const text = await res.text();\n throw new ApiError(res.status, text);\n }\n if (!res.body) {\n throw new ApiError(0, \"No response body for stream\");\n }\n return res.body;\n }\n}\n\nexport class ApiError extends Error {\n constructor(\n public status: number,\n public body: string,\n ) {\n let msg: string;\n try {\n const parsed = JSON.parse(body);\n msg = parsed.error ?? parsed.message ?? body;\n } catch {\n msg = body;\n }\n super(`API error ${status}: ${msg}`);\n this.name = \"ApiError\";\n }\n}\n","import chalk from \"chalk\";\n\nexport function json(data: unknown): void {\n process.stdout.write(JSON.stringify(data, null, 2) + \"\\n\");\n}\n\nexport function table(rows: string[][], headers?: string[]): void {\n const allRows = headers ? [headers, ...rows] : rows;\n const colWidths: number[] = [];\n for (const row of allRows) {\n for (let i = 0; i < row.length; i++) {\n colWidths[i] = Math.max(colWidths[i] ?? 0, stripAnsi(row[i]).length);\n }\n }\n\n for (let r = 0; r < allRows.length; r++) {\n const row = allRows[r];\n const padded = row.map((cell, i) => {\n const bare = stripAnsi(cell);\n const pad = colWidths[i] - bare.length;\n return cell + \" \".repeat(Math.max(0, pad));\n });\n process.stdout.write(\" \" + padded.join(\" \") + \"\\n\");\n\n if (r === 0 && headers) {\n const sep = colWidths.map((w) => \"─\".repeat(w)).join(\"──\");\n process.stdout.write(\" \" + sep + \"\\n\");\n }\n }\n}\n\nfunction stripAnsi(str: string): string {\n // eslint-disable-next-line no-control-regex\n return str.replace(/\\x1b\\[[0-9;]*m/g, \"\");\n}\n\nexport function heading(text: string): void {\n process.stdout.write(\"\\n\" + chalk.bold(text) + \"\\n\\n\");\n}\n\nexport function success(text: string): void {\n process.stdout.write(chalk.green(\"✓\") + \" \" + text + \"\\n\");\n}\n\nexport function warn(text: string): void {\n process.stdout.write(chalk.yellow(\"⚠\") + \" \" + text + \"\\n\");\n}\n\nexport function error(text: string): void {\n process.stderr.write(chalk.red(\"✗\") + \" \" + text + \"\\n\");\n}\n\nexport function dim(text: string): string {\n return chalk.dim(text);\n}\n\nexport function bold(text: string): string {\n return chalk.bold(text);\n}\n\nexport function currency(n: number): string {\n return \"$\" + n.toLocaleString(\"en-US\", { minimumFractionDigits: 2, maximumFractionDigits: 2 });\n}\n\nexport function percent(n: number): string {\n return (n * 100).toFixed(1) + \"%\";\n}\n\nexport function truncate(str: string, max: number): string {\n if (str.length <= max) return str;\n return str.slice(0, max - 1) + \"…\";\n}\n\nexport function relativeTime(date: string): string {\n const diff = Date.now() - new Date(date).getTime();\n const mins = Math.floor(diff / 60_000);\n if (mins < 1) return \"just now\";\n if (mins < 60) return `${mins}m ago`;\n const hours = Math.floor(mins / 60);\n if (hours < 24) return `${hours}h ago`;\n const days = Math.floor(hours / 24);\n return `${days}d ago`;\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { ApiClient } from \"../client.js\";\nimport type { Orderbook, SlippageResult, GlobalOptions } from \"../types.js\";\nimport * as out from \"../output.js\";\n\nexport function registerMarketCommands(program: Command): void {\n const markets = program.command(\"markets\").description(\"Polymarket orderbook tools\");\n\n markets\n .command(\"orderbook <tokenId>\")\n .description(\"Show orderbook spread and depth for a CLOB token\")\n .option(\"-s, --size <n>\", \"Size for slippage calculation\")\n .action(async (tokenId: string, cmdOpts: { size?: string }) => {\n const globalOpts = program.opts<GlobalOptions>();\n const client = new ApiClient(globalOpts);\n\n const params: Record<string, string> = { tokenId };\n if (cmdOpts.size) params.size = cmdOpts.size;\n\n const data = await client.get<{\n book: Orderbook;\n spread: { bid: number; ask: number; spread: number } | null;\n askDepth: number;\n slippage: SlippageResult | null;\n }>(\"/api/orderbook\", params);\n\n if (globalOpts.json) {\n out.json(data);\n return;\n }\n\n out.heading(\"Orderbook\");\n\n if (data.spread) {\n out.table([\n [\"Best Bid\", data.spread.bid.toFixed(4)],\n [\"Best Ask\", data.spread.ask.toFixed(4)],\n [\"Spread\", out.percent(data.spread.spread)],\n [\"Ask Depth\", out.currency(data.askDepth)],\n ]);\n } else {\n out.warn(\"No spread data available (empty orderbook)\");\n }\n\n if (data.slippage) {\n process.stdout.write(\"\\n\");\n out.table([\n [\"Avg Fill Price\", data.slippage.avgPrice.toFixed(4)],\n [\"Worst Price\", data.slippage.worstPrice.toFixed(4)],\n [\"Slippage\", out.percent(data.slippage.slippage)],\n [\"Fillable Size\", out.currency(data.slippage.fillableSize)],\n ]);\n }\n\n if (data.book.asks.length > 0) {\n process.stdout.write(\"\\n\" + chalk.dim(\" Top 5 asks:\") + \"\\n\");\n const askRows = data.book.asks.slice(0, 5).map((l) => [l.price, l.size]);\n out.table(askRows, [\"Price\", \"Size\"]);\n }\n\n if (data.book.bids.length > 0) {\n process.stdout.write(\"\\n\" + chalk.dim(\" Top 5 bids:\") + \"\\n\");\n const bidRows = data.book.bids.slice(0, 5).map((l) => [l.price, l.size]);\n out.table(bidRows, [\"Price\", \"Size\"]);\n }\n });\n}\n\n","import { Command } from \"commander\";\nimport { ApiClient } from \"../client.js\";\nimport type { UserProfile, GlobalOptions } from \"../types.js\";\nimport * as out from \"../output.js\";\n\nexport function registerProfileCommand(program: Command): void {\n program\n .command(\"profile\")\n .description(\"Show your user profile\")\n .action(async () => {\n const globalOpts = program.opts<GlobalOptions>();\n const client = new ApiClient(globalOpts);\n requireAuth(client);\n\n const profile = await client.get<UserProfile>(\"/api/profile\");\n\n if (globalOpts.json) {\n out.json(profile);\n return;\n }\n\n out.heading(\"Profile\");\n out.table([\n [\"Handle\", out.bold(profile.handle || \"(none)\")],\n [\"User ID\", profile.user_id],\n [\"Created\", new Date(profile.created_at).toLocaleDateString()],\n ]);\n });\n}\n\nfunction requireAuth(client: ApiClient): void {\n if (!client.isAuthenticated) {\n out.error(\"Not logged in. Run \" + out.bold(\"hl auth login\") + \" first.\");\n process.exit(1);\n }\n}\n","import { Command } from \"commander\";\nimport readline from \"node:readline/promises\";\nimport chalk from \"chalk\";\nimport { ApiClient } from \"../client.js\";\nimport { parseStream } from \"../stream.js\";\nimport type { Assessment, MarketBrief, GlobalOptions } from \"../types.js\";\nimport * as out from \"../output.js\";\n\nexport function registerResearchCommands(program: Command): void {\n const research = program.command(\"research\").description(\"AI-powered market research\");\n\n research\n .command(\"start\", { isDefault: true })\n .description(\"Start an interactive market research session\")\n .action(async () => {\n const globalOpts = program.opts<GlobalOptions>();\n const client = new ApiClient(globalOpts);\n requireAuth(client);\n\n const { id } = await client.post<{ id: string }>(\"/api/assessments\");\n\n out.heading(\"Market Research\");\n process.stderr.write(\n chalk.dim(\" Describe a topic or thesis to explore. Type /quit to exit.\\n\\n\"),\n );\n\n let msgCounter = 0;\n const uiMsg = (role: string, content: string) => ({\n id: `msg-${++msgCounter}`,\n role,\n content,\n parts: [{ type: \"text\" as const, text: content }],\n });\n\n const messages: ReturnType<typeof uiMsg>[] = [];\n const rl = readline.createInterface({ input: process.stdin, output: process.stderr });\n\n try {\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const userInput = await rl.question(chalk.cyan(\"You: \"));\n if (!userInput.trim()) continue;\n if (userInput.trim() === \"/quit\") break;\n\n messages.push(uiMsg(\"user\", userInput));\n\n process.stderr.write(chalk.dim(\"\\nAssistant: \"));\n\n try {\n const body = await client.stream(\"/api/chat\", {\n messages,\n assessmentId: id,\n });\n\n const result = await parseStream(body, {\n onText: (text) => process.stderr.write(text),\n onToolCall: (name) => {\n process.stderr.write(chalk.dim(`\\n [tool: ${name}]\\n`));\n },\n onToolResult: (name, toolResult) => {\n if (globalOpts.verbose) {\n process.stderr.write(chalk.dim(` [result: ${name}] ${JSON.stringify(toolResult).slice(0, 200)}\\n`));\n }\n },\n });\n\n process.stderr.write(\"\\n\\n\");\n\n if (result.assistantText) {\n messages.push(uiMsg(\"assistant\", result.assistantText));\n }\n\n if (result.marketBrief) {\n displayMarketBrief(result.marketBrief as unknown as MarketBrief, globalOpts);\n break;\n }\n } catch (e) {\n process.stderr.write(\"\\n\");\n out.error(`Chat error: ${e instanceof Error ? e.message : String(e)}`);\n }\n }\n } finally {\n rl.close();\n }\n });\n\n research\n .command(\"list\")\n .description(\"List past research sessions\")\n .option(\"-s, --status <status>\", \"Filter by status\")\n .action(async (cmdOpts: { status?: string }) => {\n const globalOpts = program.opts<GlobalOptions>();\n const client = new ApiClient(globalOpts);\n requireAuth(client);\n\n const params: Record<string, string> = { list: \"true\" };\n if (cmdOpts.status) params.status = cmdOpts.status;\n\n const data = await client.get<{ assessments: Assessment[] }>(\"/api/assessments\", params);\n\n if (globalOpts.json) {\n out.json(data.assessments);\n return;\n }\n\n if (data.assessments.length === 0) {\n out.warn(\"No research sessions found.\");\n return;\n }\n\n out.heading(`Research Sessions (${data.assessments.length})`);\n\n const rows = data.assessments.map((a) => {\n const status = formatStatus(a.status);\n const brief = a.market_brief?.title ?? \"—\";\n const markets = a.market_brief ? String(a.market_brief.marketCount) : \"—\";\n return [a.id.slice(0, 8), status, out.truncate(brief, 30), markets, out.relativeTime(a.created_at)];\n });\n\n out.table(rows, [\"ID\", \"Status\", \"Brief\", \"Markets\", \"Created\"]);\n });\n\n research\n .command(\"show <id>\")\n .description(\"Show research session details\")\n .action(async (id: string) => {\n const globalOpts = program.opts<GlobalOptions>();\n const client = new ApiClient(globalOpts);\n requireAuth(client);\n\n const assessment = await client.get<Assessment>(`/api/assessments/${id}`);\n\n if (globalOpts.json) {\n out.json(assessment);\n return;\n }\n\n out.heading(\"Research Session \" + out.dim(assessment.id.slice(0, 8)));\n\n out.table([\n [\"Status\", formatStatus(assessment.status)],\n [\"Created\", new Date(assessment.created_at).toLocaleString()],\n [\"Updated\", new Date(assessment.updated_at).toLocaleString()],\n ]);\n\n if (assessment.market_brief) {\n displayMarketBrief(assessment.market_brief, globalOpts);\n }\n });\n\n research\n .command(\"delete <id>\")\n .description(\"Delete a research session\")\n .action(async (id: string) => {\n const globalOpts = program.opts<GlobalOptions>();\n const client = new ApiClient(globalOpts);\n requireAuth(client);\n\n await client.delete(`/api/assessments/${id}`);\n out.success(\"Research session deleted.\");\n });\n}\n\nfunction requireAuth(client: ApiClient): void {\n if (!client.isAuthenticated) {\n out.error(\"Not logged in. Run \" + out.bold(\"hl auth login\") + \" first.\");\n process.exit(1);\n }\n}\n\nfunction formatStatus(status: string): string {\n switch (status) {\n case \"completed\":\n return chalk.green(status);\n case \"in_progress\":\n return chalk.yellow(status);\n case \"abandoned\":\n return chalk.red(status);\n default:\n return status;\n }\n}\n\nfunction displayMarketBrief(brief: MarketBrief, globalOpts: GlobalOptions): void {\n if (globalOpts.json) {\n out.json(brief);\n return;\n }\n\n out.heading(\"Market Brief\");\n\n process.stdout.write(\" \" + chalk.bold(brief.title) + \"\\n\\n\");\n process.stdout.write(\" \" + chalk.italic(brief.thesis) + \"\\n\");\n\n if (brief.markets.length > 0) {\n process.stdout.write(\"\\n\" + chalk.bold(\" Markets\") + \"\\n\\n\");\n const rows = brief.markets.map((m) => {\n const prob = out.percent(m.yesPrice);\n const signals = m.signals.length > 0 ? m.signals.join(\", \") : \"—\";\n const liq = m.liquidity ? out.currency(m.liquidity) : \"—\";\n return [out.truncate(m.question, 40), prob, signals, liq];\n });\n out.table(rows, [\"Market\", \"Prob\", \"Signals\", \"Liq\"]);\n\n process.stdout.write(\"\\n\");\n for (const m of brief.markets) {\n process.stdout.write(\" \" + chalk.dim(\"▸ \") + out.truncate(m.question, 50) + \"\\n\");\n process.stdout.write(\" \" + chalk.dim(\"Causal link: \") + m.causalLink + \"\\n\");\n process.stdout.write(\" \" + chalk.dim(\"Polymarket: \") + m.polymarketUrl + \"\\n\");\n }\n }\n\n if (brief.gaps.length > 0) {\n process.stdout.write(\"\\n\" + chalk.bold(\" Coverage Gaps\") + \"\\n\\n\");\n for (const gap of brief.gaps) {\n process.stdout.write(\" \" + chalk.yellow(\"▸\") + \" \" + gap + \"\\n\");\n }\n }\n\n process.stdout.write(\"\\n \" + chalk.dim(`${brief.marketCount} markets · ${brief.gaps.length} coverage gaps`) + \"\\n\");\n}\n","/**\n * Parses the Vercel AI SDK UI Message Stream protocol (SSE format).\n *\n * The server sends Server-Sent Events where each `data:` line contains\n * a JSON object with a `type` field:\n * text-delta: { type, id, delta }\n * tool-input-start: { type, toolCallId, toolName }\n * tool-input-delta: { type, toolCallId, inputTextDelta }\n * tool-input-available: { type, toolCallId, toolName, input }\n * tool-output-available:{ type, toolCallId, output }\n * error: { type, errorText }\n * [DONE]: stream termination sentinel\n */\n\nexport interface StreamCallbacks {\n onText?: (text: string) => void;\n onToolCall?: (name: string, args: unknown) => void;\n onToolResult?: (name: string, result: unknown) => void;\n}\n\nexport interface StreamResult {\n assistantText: string;\n toolCalls: Array<{ name: string; args: unknown }>;\n marketBrief: Record<string, unknown> | null;\n}\n\nexport async function parseStream(\n body: ReadableStream<Uint8Array>,\n callbacks: StreamCallbacks = {},\n): Promise<StreamResult> {\n const decoder = new TextDecoder();\n const reader = body.getReader();\n\n let buffer = \"\";\n let assistantText = \"\";\n const toolCalls: Array<{ name: string; args: unknown }> = [];\n const activeToolCalls = new Map<string, { name: string; argStr: string }>();\n let marketBrief: Record<string, unknown> | null = null;\n\n while (true) {\n const { done, value } = await reader.read();\n if (!done) {\n buffer += decoder.decode(value, { stream: true });\n }\n\n const lines = buffer.split(\"\\n\");\n buffer = done ? \"\" : (lines.pop() ?? \"\");\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith(\":\")) continue;\n\n if (!trimmed.startsWith(\"data:\")) continue;\n const payload = trimmed.slice(5).trim();\n\n if (payload === \"[DONE]\") continue;\n\n let msg: Record<string, unknown>;\n try {\n msg = JSON.parse(payload);\n } catch {\n continue;\n }\n\n const type = msg.type as string;\n\n switch (type) {\n case \"text-delta\": {\n const delta = msg.delta as string;\n if (delta) {\n assistantText += delta;\n callbacks.onText?.(delta);\n }\n break;\n }\n\n case \"tool-input-start\": {\n const id = msg.toolCallId as string;\n const name = msg.toolName as string;\n if (id && name) {\n activeToolCalls.set(id, { name, argStr: \"\" });\n }\n break;\n }\n\n case \"tool-input-delta\": {\n const id = msg.toolCallId as string;\n const active = activeToolCalls.get(id);\n if (active) {\n active.argStr += msg.inputTextDelta as string;\n }\n break;\n }\n\n case \"tool-input-available\": {\n const id = msg.toolCallId as string;\n const active = activeToolCalls.get(id);\n if (active) {\n const args = msg.input ?? active.argStr;\n toolCalls.push({ name: active.name, args });\n callbacks.onToolCall?.(active.name, args);\n }\n break;\n }\n\n case \"tool-output-available\": {\n const id = msg.toolCallId as string;\n const active = activeToolCalls.get(id);\n if (active) {\n callbacks.onToolResult?.(active.name, msg.output);\n if (active.name === \"buildMarketBrief\" && isMarketBrief(msg.output)) {\n marketBrief = msg.output as Record<string, unknown>;\n }\n activeToolCalls.delete(id);\n }\n break;\n }\n\n case \"error\": {\n throw new Error((msg.errorText as string) ?? \"Unknown stream error\");\n }\n }\n }\n\n if (done) break;\n }\n\n return { assistantText, toolCalls, marketBrief };\n}\n\nfunction isMarketBrief(val: unknown): boolean {\n return (\n val !== null &&\n typeof val === \"object\" &&\n \"title\" in (val as Record<string, unknown>) &&\n \"markets\" in (val as Record<string, unknown>)\n );\n}\n"],"mappings":";;;AAAA,SAAS,eAAe;;;ACCxB,OAAO,cAAc;;;ACDrB,SAAS,cAAc,eAAe,WAAW,YAAY,kBAAkB;AAC/E,SAAS,YAAY;AACrB,SAAS,eAAe;AAExB,IAAM,aAAa,KAAK,QAAQ,GAAG,aAAa;AAChD,IAAM,cAAc,KAAK,YAAY,aAAa;AAE3C,IAAM,kBAAkB;AAO/B,SAAS,gBAAwB;AAC/B,SAAO,EAAE,SAAS,iBAAiB,OAAO,KAAK;AACjD;AAEO,SAAS,aAAqB;AACnC,MAAI;AACF,QAAI,CAAC,WAAW,WAAW,EAAG,QAAO,cAAc;AACnD,UAAM,MAAM,aAAa,aAAa,OAAO;AAC7C,UAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,WAAO;AAAA,MACL,SAAS,OAAO,WAAW;AAAA,MAC3B,OAAO,OAAO,SAAS;AAAA,IACzB;AAAA,EACF,QAAQ;AACN,WAAO,cAAc;AAAA,EACvB;AACF;AAEO,SAAS,WAAW,QAAsB;AAC/C,YAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AACzC,gBAAc,aAAa,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,MAAM,OAAO;AAC5E;AAEO,SAAS,cAAoB;AAClC,MAAI;AACF,QAAI,WAAW,WAAW,EAAG,YAAW,WAAW;AAAA,EACrD,QAAQ;AAAA,EAER;AACF;AAEO,SAAS,aAAqB;AACnC,SAAO;AACT;;;AC5CO,IAAM,YAAN,MAAgB;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,OAAsB,CAAC,GAAG;AACpC,UAAM,SAAS,WAAW;AAC1B,SAAK,WAAW,KAAK,UAAU,OAAO,WAAW,iBAAiB,QAAQ,OAAO,EAAE;AACnF,SAAK,QAAQ,KAAK,SAAS,OAAO,SAAS;AAC3C,SAAK,UAAU,KAAK,WAAW;AAAA,EACjC;AAAA,EAEA,IAAI,kBAA2B;AAC7B,WAAO,KAAK,UAAU;AAAA,EACxB;AAAA,EAEA,IAAI,SAAiB;AACnB,WAAO,KAAK;AAAA,EACd;AAAA,EAEQ,QAAQ,QAAgC,CAAC,GAA2B;AAC1E,UAAM,IAA4B;AAAA,MAChC,gBAAgB;AAAA,MAChB,GAAG;AAAA,IACL;AACA,QAAI,KAAK,OAAO;AACd,QAAE,eAAe,IAAI,UAAU,KAAK,KAAK;AAAA,IAC3C;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,IAAI,QAAgB,MAAc,QAAuB;AAC/D,QAAI,CAAC,KAAK,QAAS;AACnB,UAAM,YAAY,SAAS,WAAM,MAAM,KAAK;AAC5C,YAAQ,OAAO,MAAM,aAAa,MAAM,IAAI,KAAK,OAAO,GAAG,IAAI,GAAG,SAAS;AAAA,CAAI;AAAA,EACjF;AAAA,EAEA,MAAM,IAAO,MAAc,QAA6C;AACtE,UAAM,MAAM,IAAI,IAAI,MAAM,KAAK,OAAO;AACtC,QAAI,QAAQ;AACV,iBAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,MAAM,GAAG;AAC3C,YAAI,MAAM,UAAa,MAAM,GAAI,KAAI,aAAa,IAAI,GAAG,CAAC;AAAA,MAC5D;AAAA,IACF;AAEA,SAAK,IAAI,OAAO,GAAG,IAAI,QAAQ,GAAG,IAAI,MAAM,EAAE;AAC9C,UAAM,MAAM,MAAM,MAAM,IAAI,SAAS,GAAG,EAAE,SAAS,KAAK,QAAQ,EAAE,CAAC;AACnE,SAAK,IAAI,OAAO,GAAG,IAAI,QAAQ,GAAG,IAAI,MAAM,IAAI,IAAI,MAAM;AAE1D,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,YAAM,IAAI,SAAS,IAAI,QAAQ,IAAI;AAAA,IACrC;AACA,WAAO,IAAI,KAAK;AAAA,EAClB;AAAA,EAEA,MAAM,KAAQ,MAAc,MAA4B;AACtD,SAAK,IAAI,QAAQ,IAAI;AACrB,UAAM,MAAM,MAAM,MAAM,GAAG,KAAK,OAAO,GAAG,IAAI,IAAI;AAAA,MAChD,QAAQ;AAAA,MACR,SAAS,KAAK,QAAQ;AAAA,MACtB,MAAM,SAAS,SAAY,KAAK,UAAU,IAAI,IAAI;AAAA,IACpD,CAAC;AACD,SAAK,IAAI,QAAQ,MAAM,IAAI,MAAM;AAEjC,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,YAAM,IAAI,SAAS,IAAI,QAAQ,IAAI;AAAA,IACrC;AACA,WAAO,IAAI,KAAK;AAAA,EAClB;AAAA,EAEA,MAAM,MAAS,MAAc,MAA2B;AACtD,SAAK,IAAI,SAAS,IAAI;AACtB,UAAM,MAAM,MAAM,MAAM,GAAG,KAAK,OAAO,GAAG,IAAI,IAAI;AAAA,MAChD,QAAQ;AAAA,MACR,SAAS,KAAK,QAAQ;AAAA,MACtB,MAAM,KAAK,UAAU,IAAI;AAAA,IAC3B,CAAC;AACD,SAAK,IAAI,SAAS,MAAM,IAAI,MAAM;AAElC,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,YAAM,IAAI,SAAS,IAAI,QAAQ,IAAI;AAAA,IACrC;AACA,WAAO,IAAI,KAAK;AAAA,EAClB;AAAA,EAEA,MAAM,OAAO,MAA6B;AACxC,SAAK,IAAI,UAAU,IAAI;AACvB,UAAM,MAAM,MAAM,MAAM,GAAG,KAAK,OAAO,GAAG,IAAI,IAAI;AAAA,MAChD,QAAQ;AAAA,MACR,SAAS,KAAK,QAAQ;AAAA,IACxB,CAAC;AACD,SAAK,IAAI,UAAU,MAAM,IAAI,MAAM;AAEnC,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,YAAM,IAAI,SAAS,IAAI,QAAQ,IAAI;AAAA,IACrC;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,MAAc,MAAoD;AAC7E,SAAK,IAAI,iBAAiB,IAAI;AAC9B,UAAM,MAAM,MAAM,MAAM,GAAG,KAAK,OAAO,GAAG,IAAI,IAAI;AAAA,MAChD,QAAQ;AAAA,MACR,SAAS,KAAK,QAAQ,EAAE,QAAQ,oBAAoB,CAAC;AAAA,MACrD,MAAM,KAAK,UAAU,IAAI;AAAA,IAC3B,CAAC;AACD,SAAK,IAAI,iBAAiB,MAAM,IAAI,MAAM;AAE1C,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,YAAM,IAAI,SAAS,IAAI,QAAQ,IAAI;AAAA,IACrC;AACA,QAAI,CAAC,IAAI,MAAM;AACb,YAAM,IAAI,SAAS,GAAG,6BAA6B;AAAA,IACrD;AACA,WAAO,IAAI;AAAA,EACb;AACF;AAEO,IAAM,WAAN,cAAuB,MAAM;AAAA,EAClC,YACS,QACA,MACP;AACA,QAAI;AACJ,QAAI;AACF,YAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,YAAM,OAAO,SAAS,OAAO,WAAW;AAAA,IAC1C,QAAQ;AACN,YAAM;AAAA,IACR;AACA,UAAM,aAAa,MAAM,KAAK,GAAG,EAAE;AAV5B;AACA;AAUP,SAAK,OAAO;AAAA,EACd;AACF;;;AC5IA,OAAO,WAAW;AAEX,SAAS,KAAK,MAAqB;AACxC,UAAQ,OAAO,MAAM,KAAK,UAAU,MAAM,MAAM,CAAC,IAAI,IAAI;AAC3D;AAEO,SAAS,MAAM,MAAkB,SAA0B;AAChE,QAAM,UAAU,UAAU,CAAC,SAAS,GAAG,IAAI,IAAI;AAC/C,QAAM,YAAsB,CAAC;AAC7B,aAAW,OAAO,SAAS;AACzB,aAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,gBAAU,CAAC,IAAI,KAAK,IAAI,UAAU,CAAC,KAAK,GAAG,UAAU,IAAI,CAAC,CAAC,EAAE,MAAM;AAAA,IACrE;AAAA,EACF;AAEA,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,UAAM,MAAM,QAAQ,CAAC;AACrB,UAAM,SAAS,IAAI,IAAI,CAAC,MAAM,MAAM;AAClC,YAAM,OAAO,UAAU,IAAI;AAC3B,YAAM,MAAM,UAAU,CAAC,IAAI,KAAK;AAChC,aAAO,OAAO,IAAI,OAAO,KAAK,IAAI,GAAG,GAAG,CAAC;AAAA,IAC3C,CAAC;AACD,YAAQ,OAAO,MAAM,OAAO,OAAO,KAAK,IAAI,IAAI,IAAI;AAEpD,QAAI,MAAM,KAAK,SAAS;AACtB,YAAM,MAAM,UAAU,IAAI,CAAC,MAAM,SAAI,OAAO,CAAC,CAAC,EAAE,KAAK,cAAI;AACzD,cAAQ,OAAO,MAAM,OAAO,MAAM,IAAI;AAAA,IACxC;AAAA,EACF;AACF;AAEA,SAAS,UAAU,KAAqB;AAEtC,SAAO,IAAI,QAAQ,mBAAmB,EAAE;AAC1C;AAEO,SAAS,QAAQ,MAAoB;AAC1C,UAAQ,OAAO,MAAM,OAAO,MAAM,KAAK,IAAI,IAAI,MAAM;AACvD;AAEO,SAAS,QAAQ,MAAoB;AAC1C,UAAQ,OAAO,MAAM,MAAM,MAAM,QAAG,IAAI,MAAM,OAAO,IAAI;AAC3D;AAEO,SAAS,KAAK,MAAoB;AACvC,UAAQ,OAAO,MAAM,MAAM,OAAO,QAAG,IAAI,MAAM,OAAO,IAAI;AAC5D;AAEO,SAAS,MAAM,MAAoB;AACxC,UAAQ,OAAO,MAAM,MAAM,IAAI,QAAG,IAAI,MAAM,OAAO,IAAI;AACzD;AAEO,SAAS,IAAI,MAAsB;AACxC,SAAO,MAAM,IAAI,IAAI;AACvB;AAEO,SAAS,KAAK,MAAsB;AACzC,SAAO,MAAM,KAAK,IAAI;AACxB;AAEO,SAAS,SAAS,GAAmB;AAC1C,SAAO,MAAM,EAAE,eAAe,SAAS,EAAE,uBAAuB,GAAG,uBAAuB,EAAE,CAAC;AAC/F;AAEO,SAAS,QAAQ,GAAmB;AACzC,UAAQ,IAAI,KAAK,QAAQ,CAAC,IAAI;AAChC;AAEO,SAAS,SAAS,KAAa,KAAqB;AACzD,MAAI,IAAI,UAAU,IAAK,QAAO;AAC9B,SAAO,IAAI,MAAM,GAAG,MAAM,CAAC,IAAI;AACjC;AAEO,SAAS,aAAa,MAAsB;AACjD,QAAM,OAAO,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,EAAE,QAAQ;AACjD,QAAM,OAAO,KAAK,MAAM,OAAO,GAAM;AACrC,MAAI,OAAO,EAAG,QAAO;AACrB,MAAI,OAAO,GAAI,QAAO,GAAG,IAAI;AAC7B,QAAM,QAAQ,KAAK,MAAM,OAAO,EAAE;AAClC,MAAI,QAAQ,GAAI,QAAO,GAAG,KAAK;AAC/B,QAAM,OAAO,KAAK,MAAM,QAAQ,EAAE;AAClC,SAAO,GAAG,IAAI;AAChB;;;AH3EO,SAAS,qBAAqBA,UAAwB;AAC3D,QAAM,OAAOA,SAAQ,QAAQ,MAAM,EAAE,YAAY,2BAA2B;AAE5E,OACG,QAAQ,OAAO,EACf,YAAY,2CAA2C,EACvD,OAAO,mBAAmB,gBAAgB,eAAe,EACzD,OAAO,OAAO,YAAiC;AAC9C,UAAM,aAAaA,SAAQ,KAAoB;AAE/C,UAAM,KAAK,SAAS,gBAAgB,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,CAAC;AACpF,QAAI;AACF,MAAI,QAAQ,8BAAyB;AACrC,cAAQ,OAAO;AAAA,QACb,0BAA8B,KAAK,gCAAgC,CAAC;AAAA;AAAA;AAAA,MACtE;AAEA,YAAM,SAAS,MAAM,GAAG,SAAS,wBAAwB,GAAG,KAAK;AAEjE,UAAI,CAAC,MAAM,WAAW,KAAK,KAAK,MAAM,WAAW,IAAI;AACnD,QAAI,MAAM,sEAAsE;AAChF,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAEA,YAAM,SAAS,WAAW,UAAU,QAAQ,UAAU;AACtD,YAAM,SAAS,IAAI,UAAU,EAAE,OAAO,OAAO,CAAC;AAE9C,cAAQ,OAAO,MAAM,uBAAuB;AAC5C,UAAI;AACJ,UAAI;AACF,kBAAU,MAAM,OAAO,IAAiB,cAAc;AAAA,MACxD,QAAQ;AACN,gBAAQ,OAAO,MAAM,IAAI;AACzB,QAAI,MAAM,0DAA0D;AACpE,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA,cAAQ,OAAO,MAAM,WAAW;AAEhC,iBAAW,EAAE,SAAS,QAAQ,MAAM,CAAC;AAErC,MAAI,QAAQ,gBAAoB,KAAK,QAAQ,UAAU,QAAQ,OAAO,CAAC,EAAE;AACzE,cAAQ,OAAO,MAAM,qBAAyB,IAAI,WAAW,CAAC,CAAC;AAAA,CAAI;AAAA,IACrE,UAAE;AACA,SAAG,MAAM;AAAA,IACX;AAAA,EACF,CAAC;AAEH,OACG,QAAQ,QAAQ,EAChB,YAAY,oCAAoC,EAChD,OAAO,YAAY;AAClB,UAAM,aAAaA,SAAQ,KAAoB;AAC/C,UAAM,SAAS,WAAW;AAC1B,UAAM,QAAQ,WAAW,SAAS,OAAO;AAEzC,QAAI,CAAC,OAAO;AACV,MAAI,KAAK,wBAA4B,KAAK,eAAe,IAAI,mBAAmB;AAChF,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,UAAM,SAAS,IAAI,UAAU,UAAU;AAEvC,QAAI;AACF,YAAM,UAAU,MAAM,OAAO,IAAiB,cAAc;AAC5D,UAAI,WAAW,MAAM;AACnB,QAAI,KAAK;AAAA,UACP,eAAe;AAAA,UACf,QAAQ,QAAQ;AAAA,UAChB,SAAS,QAAQ;AAAA,UACjB,SAAS,OAAO;AAAA,QAClB,CAAC;AAAA,MACH,OAAO;AACL,QAAI,QAAQ,aAAa;AACzB,QAAI;AAAA,UACF;AAAA,YACE,CAAC,UAAc,KAAK,QAAQ,UAAU,QAAQ,CAAC;AAAA,YAC/C,CAAC,WAAW,QAAQ,OAAO;AAAA,YAC3B,CAAC,WAAW,OAAO,MAAM;AAAA,YACzB,CAAC,UAAU,WAAW,CAAC;AAAA,UACzB;AAAA,QACF;AAAA,MACF;AAAA,IACF,QAAQ;AACN,MAAI,MAAM,sCAA0C,KAAK,eAAe,IAAI,sBAAsB;AAClG,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF,CAAC;AAEH,OACG,QAAQ,QAAQ,EAChB,YAAY,yBAAyB,EACrC,OAAO,MAAM;AACZ,gBAAY;AACZ,IAAI,QAAQ,oCAAwC,IAAI,WAAW,CAAC,CAAC;AAAA,EACvE,CAAC;AACL;;;AIrGA,OAAOC,YAAW;AAKX,SAAS,uBAAuBC,UAAwB;AAC7D,QAAM,UAAUA,SAAQ,QAAQ,SAAS,EAAE,YAAY,4BAA4B;AAEnF,UACG,QAAQ,qBAAqB,EAC7B,YAAY,kDAAkD,EAC9D,OAAO,kBAAkB,+BAA+B,EACxD,OAAO,OAAO,SAAiB,YAA+B;AAC7D,UAAM,aAAaA,SAAQ,KAAoB;AAC/C,UAAM,SAAS,IAAI,UAAU,UAAU;AAEvC,UAAM,SAAiC,EAAE,QAAQ;AACjD,QAAI,QAAQ,KAAM,QAAO,OAAO,QAAQ;AAExC,UAAM,OAAO,MAAM,OAAO,IAKvB,kBAAkB,MAAM;AAE3B,QAAI,WAAW,MAAM;AACnB,MAAI,KAAK,IAAI;AACb;AAAA,IACF;AAEA,IAAI,QAAQ,WAAW;AAEvB,QAAI,KAAK,QAAQ;AACf,MAAI,MAAM;AAAA,QACR,CAAC,YAAY,KAAK,OAAO,IAAI,QAAQ,CAAC,CAAC;AAAA,QACvC,CAAC,YAAY,KAAK,OAAO,IAAI,QAAQ,CAAC,CAAC;AAAA,QACvC,CAAC,UAAc,QAAQ,KAAK,OAAO,MAAM,CAAC;AAAA,QAC1C,CAAC,aAAiB,SAAS,KAAK,QAAQ,CAAC;AAAA,MAC3C,CAAC;AAAA,IACH,OAAO;AACL,MAAI,KAAK,4CAA4C;AAAA,IACvD;AAEA,QAAI,KAAK,UAAU;AACjB,cAAQ,OAAO,MAAM,IAAI;AACzB,MAAI,MAAM;AAAA,QACR,CAAC,kBAAkB,KAAK,SAAS,SAAS,QAAQ,CAAC,CAAC;AAAA,QACpD,CAAC,eAAe,KAAK,SAAS,WAAW,QAAQ,CAAC,CAAC;AAAA,QACnD,CAAC,YAAgB,QAAQ,KAAK,SAAS,QAAQ,CAAC;AAAA,QAChD,CAAC,iBAAqB,SAAS,KAAK,SAAS,YAAY,CAAC;AAAA,MAC5D,CAAC;AAAA,IACH;AAEA,QAAI,KAAK,KAAK,KAAK,SAAS,GAAG;AAC7B,cAAQ,OAAO,MAAM,OAAOC,OAAM,IAAI,eAAe,IAAI,IAAI;AAC7D,YAAM,UAAU,KAAK,KAAK,KAAK,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC;AACvE,MAAI,MAAM,SAAS,CAAC,SAAS,MAAM,CAAC;AAAA,IACtC;AAEA,QAAI,KAAK,KAAK,KAAK,SAAS,GAAG;AAC7B,cAAQ,OAAO,MAAM,OAAOA,OAAM,IAAI,eAAe,IAAI,IAAI;AAC7D,YAAM,UAAU,KAAK,KAAK,KAAK,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC;AACvE,MAAI,MAAM,SAAS,CAAC,SAAS,MAAM,CAAC;AAAA,IACtC;AAAA,EACF,CAAC;AACL;;;AC9DO,SAAS,uBAAuBC,UAAwB;AAC7D,EAAAA,SACG,QAAQ,SAAS,EACjB,YAAY,wBAAwB,EACpC,OAAO,YAAY;AAClB,UAAM,aAAaA,SAAQ,KAAoB;AAC/C,UAAM,SAAS,IAAI,UAAU,UAAU;AACvC,gBAAY,MAAM;AAElB,UAAM,UAAU,MAAM,OAAO,IAAiB,cAAc;AAE5D,QAAI,WAAW,MAAM;AACnB,MAAI,KAAK,OAAO;AAChB;AAAA,IACF;AAEA,IAAI,QAAQ,SAAS;AACrB,IAAI,MAAM;AAAA,MACR,CAAC,UAAc,KAAK,QAAQ,UAAU,QAAQ,CAAC;AAAA,MAC/C,CAAC,WAAW,QAAQ,OAAO;AAAA,MAC3B,CAAC,WAAW,IAAI,KAAK,QAAQ,UAAU,EAAE,mBAAmB,CAAC;AAAA,IAC/D,CAAC;AAAA,EACH,CAAC;AACL;AAEA,SAAS,YAAY,QAAyB;AAC5C,MAAI,CAAC,OAAO,iBAAiB;AAC3B,IAAI,MAAM,wBAA4B,KAAK,eAAe,IAAI,SAAS;AACvE,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;;;AClCA,OAAOC,eAAc;AACrB,OAAOC,YAAW;;;ACwBlB,eAAsB,YACpB,MACA,YAA6B,CAAC,GACP;AACvB,QAAM,UAAU,IAAI,YAAY;AAChC,QAAM,SAAS,KAAK,UAAU;AAE9B,MAAI,SAAS;AACb,MAAI,gBAAgB;AACpB,QAAM,YAAoD,CAAC;AAC3D,QAAM,kBAAkB,oBAAI,IAA8C;AAC1E,MAAI,cAA8C;AAElD,SAAO,MAAM;AACX,UAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,QAAI,CAAC,MAAM;AACT,gBAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AAAA,IAClD;AAEA,UAAM,QAAQ,OAAO,MAAM,IAAI;AAC/B,aAAS,OAAO,KAAM,MAAM,IAAI,KAAK;AAErC,eAAW,QAAQ,OAAO;AACxB,YAAM,UAAU,KAAK,KAAK;AAC1B,UAAI,CAAC,WAAW,QAAQ,WAAW,GAAG,EAAG;AAEzC,UAAI,CAAC,QAAQ,WAAW,OAAO,EAAG;AAClC,YAAM,UAAU,QAAQ,MAAM,CAAC,EAAE,KAAK;AAEtC,UAAI,YAAY,SAAU;AAE1B,UAAI;AACJ,UAAI;AACF,cAAM,KAAK,MAAM,OAAO;AAAA,MAC1B,QAAQ;AACN;AAAA,MACF;AAEA,YAAM,OAAO,IAAI;AAEjB,cAAQ,MAAM;AAAA,QACZ,KAAK,cAAc;AACjB,gBAAM,QAAQ,IAAI;AAClB,cAAI,OAAO;AACT,6BAAiB;AACjB,sBAAU,SAAS,KAAK;AAAA,UAC1B;AACA;AAAA,QACF;AAAA,QAEA,KAAK,oBAAoB;AACvB,gBAAM,KAAK,IAAI;AACf,gBAAM,OAAO,IAAI;AACjB,cAAI,MAAM,MAAM;AACd,4BAAgB,IAAI,IAAI,EAAE,MAAM,QAAQ,GAAG,CAAC;AAAA,UAC9C;AACA;AAAA,QACF;AAAA,QAEA,KAAK,oBAAoB;AACvB,gBAAM,KAAK,IAAI;AACf,gBAAM,SAAS,gBAAgB,IAAI,EAAE;AACrC,cAAI,QAAQ;AACV,mBAAO,UAAU,IAAI;AAAA,UACvB;AACA;AAAA,QACF;AAAA,QAEA,KAAK,wBAAwB;AAC3B,gBAAM,KAAK,IAAI;AACf,gBAAM,SAAS,gBAAgB,IAAI,EAAE;AACrC,cAAI,QAAQ;AACV,kBAAM,OAAO,IAAI,SAAS,OAAO;AACjC,sBAAU,KAAK,EAAE,MAAM,OAAO,MAAM,KAAK,CAAC;AAC1C,sBAAU,aAAa,OAAO,MAAM,IAAI;AAAA,UAC1C;AACA;AAAA,QACF;AAAA,QAEA,KAAK,yBAAyB;AAC5B,gBAAM,KAAK,IAAI;AACf,gBAAM,SAAS,gBAAgB,IAAI,EAAE;AACrC,cAAI,QAAQ;AACV,sBAAU,eAAe,OAAO,MAAM,IAAI,MAAM;AAChD,gBAAI,OAAO,SAAS,sBAAsB,cAAc,IAAI,MAAM,GAAG;AACnE,4BAAc,IAAI;AAAA,YACpB;AACA,4BAAgB,OAAO,EAAE;AAAA,UAC3B;AACA;AAAA,QACF;AAAA,QAEA,KAAK,SAAS;AACZ,gBAAM,IAAI,MAAO,IAAI,aAAwB,sBAAsB;AAAA,QACrE;AAAA,MACF;AAAA,IACF;AAEA,QAAI,KAAM;AAAA,EACZ;AAEA,SAAO,EAAE,eAAe,WAAW,YAAY;AACjD;AAEA,SAAS,cAAc,KAAuB;AAC5C,SACE,QAAQ,QACR,OAAO,QAAQ,YACf,WAAY,OACZ,aAAc;AAElB;;;ADjIO,SAAS,yBAAyBC,UAAwB;AAC/D,QAAM,WAAWA,SAAQ,QAAQ,UAAU,EAAE,YAAY,4BAA4B;AAErF,WACG,QAAQ,SAAS,EAAE,WAAW,KAAK,CAAC,EACpC,YAAY,8CAA8C,EAC1D,OAAO,YAAY;AAClB,UAAM,aAAaA,SAAQ,KAAoB;AAC/C,UAAM,SAAS,IAAI,UAAU,UAAU;AACvC,IAAAC,aAAY,MAAM;AAElB,UAAM,EAAE,GAAG,IAAI,MAAM,OAAO,KAAqB,kBAAkB;AAEnE,IAAI,QAAQ,iBAAiB;AAC7B,YAAQ,OAAO;AAAA,MACbC,OAAM,IAAI,kEAAkE;AAAA,IAC9E;AAEA,QAAI,aAAa;AACjB,UAAM,QAAQ,CAAC,MAAc,aAAqB;AAAA,MAChD,IAAI,OAAO,EAAE,UAAU;AAAA,MACvB;AAAA,MACA;AAAA,MACA,OAAO,CAAC,EAAE,MAAM,QAAiB,MAAM,QAAQ,CAAC;AAAA,IAClD;AAEA,UAAM,WAAuC,CAAC;AAC9C,UAAM,KAAKC,UAAS,gBAAgB,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,CAAC;AAEpF,QAAI;AAEF,aAAO,MAAM;AACX,cAAM,YAAY,MAAM,GAAG,SAASD,OAAM,KAAK,OAAO,CAAC;AACvD,YAAI,CAAC,UAAU,KAAK,EAAG;AACvB,YAAI,UAAU,KAAK,MAAM,QAAS;AAElC,iBAAS,KAAK,MAAM,QAAQ,SAAS,CAAC;AAEtC,gBAAQ,OAAO,MAAMA,OAAM,IAAI,eAAe,CAAC;AAE/C,YAAI;AACF,gBAAM,OAAO,MAAM,OAAO,OAAO,aAAa;AAAA,YAC5C;AAAA,YACA,cAAc;AAAA,UAChB,CAAC;AAED,gBAAM,SAAS,MAAM,YAAY,MAAM;AAAA,YACrC,QAAQ,CAAC,SAAS,QAAQ,OAAO,MAAM,IAAI;AAAA,YAC3C,YAAY,CAAC,SAAS;AACpB,sBAAQ,OAAO,MAAMA,OAAM,IAAI;AAAA,WAAc,IAAI;AAAA,CAAK,CAAC;AAAA,YACzD;AAAA,YACA,cAAc,CAAC,MAAM,eAAe;AAClC,kBAAI,WAAW,SAAS;AACtB,wBAAQ,OAAO,MAAMA,OAAM,IAAI,cAAc,IAAI,KAAK,KAAK,UAAU,UAAU,EAAE,MAAM,GAAG,GAAG,CAAC;AAAA,CAAI,CAAC;AAAA,cACrG;AAAA,YACF;AAAA,UACF,CAAC;AAED,kBAAQ,OAAO,MAAM,MAAM;AAE3B,cAAI,OAAO,eAAe;AACxB,qBAAS,KAAK,MAAM,aAAa,OAAO,aAAa,CAAC;AAAA,UACxD;AAEA,cAAI,OAAO,aAAa;AACtB,+BAAmB,OAAO,aAAuC,UAAU;AAC3E;AAAA,UACF;AAAA,QACF,SAAS,GAAG;AACV,kBAAQ,OAAO,MAAM,IAAI;AACzB,UAAI,MAAM,eAAe,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC,EAAE;AAAA,QACvE;AAAA,MACF;AAAA,IACF,UAAE;AACA,SAAG,MAAM;AAAA,IACX;AAAA,EACF,CAAC;AAEH,WACG,QAAQ,MAAM,EACd,YAAY,6BAA6B,EACzC,OAAO,yBAAyB,kBAAkB,EAClD,OAAO,OAAO,YAAiC;AAC9C,UAAM,aAAaF,SAAQ,KAAoB;AAC/C,UAAM,SAAS,IAAI,UAAU,UAAU;AACvC,IAAAC,aAAY,MAAM;AAElB,UAAM,SAAiC,EAAE,MAAM,OAAO;AACtD,QAAI,QAAQ,OAAQ,QAAO,SAAS,QAAQ;AAE5C,UAAM,OAAO,MAAM,OAAO,IAAmC,oBAAoB,MAAM;AAEvF,QAAI,WAAW,MAAM;AACnB,MAAI,KAAK,KAAK,WAAW;AACzB;AAAA,IACF;AAEA,QAAI,KAAK,YAAY,WAAW,GAAG;AACjC,MAAI,KAAK,6BAA6B;AACtC;AAAA,IACF;AAEA,IAAI,QAAQ,sBAAsB,KAAK,YAAY,MAAM,GAAG;AAE5D,UAAM,OAAO,KAAK,YAAY,IAAI,CAAC,MAAM;AACvC,YAAM,SAAS,aAAa,EAAE,MAAM;AACpC,YAAM,QAAQ,EAAE,cAAc,SAAS;AACvC,YAAM,UAAU,EAAE,eAAe,OAAO,EAAE,aAAa,WAAW,IAAI;AACtE,aAAO,CAAC,EAAE,GAAG,MAAM,GAAG,CAAC,GAAG,QAAY,SAAS,OAAO,EAAE,GAAG,SAAa,aAAa,EAAE,UAAU,CAAC;AAAA,IACpG,CAAC;AAED,IAAI,MAAM,MAAM,CAAC,MAAM,UAAU,SAAS,WAAW,SAAS,CAAC;AAAA,EACjE,CAAC;AAEH,WACG,QAAQ,WAAW,EACnB,YAAY,+BAA+B,EAC3C,OAAO,OAAO,OAAe;AAC5B,UAAM,aAAaD,SAAQ,KAAoB;AAC/C,UAAM,SAAS,IAAI,UAAU,UAAU;AACvC,IAAAC,aAAY,MAAM;AAElB,UAAM,aAAa,MAAM,OAAO,IAAgB,oBAAoB,EAAE,EAAE;AAExE,QAAI,WAAW,MAAM;AACnB,MAAI,KAAK,UAAU;AACnB;AAAA,IACF;AAEA,IAAI,QAAQ,sBAA0B,IAAI,WAAW,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC;AAEpE,IAAI,MAAM;AAAA,MACR,CAAC,UAAU,aAAa,WAAW,MAAM,CAAC;AAAA,MAC1C,CAAC,WAAW,IAAI,KAAK,WAAW,UAAU,EAAE,eAAe,CAAC;AAAA,MAC5D,CAAC,WAAW,IAAI,KAAK,WAAW,UAAU,EAAE,eAAe,CAAC;AAAA,IAC9D,CAAC;AAED,QAAI,WAAW,cAAc;AAC3B,yBAAmB,WAAW,cAAc,UAAU;AAAA,IACxD;AAAA,EACF,CAAC;AAEH,WACG,QAAQ,aAAa,EACrB,YAAY,2BAA2B,EACvC,OAAO,OAAO,OAAe;AAC5B,UAAM,aAAaD,SAAQ,KAAoB;AAC/C,UAAM,SAAS,IAAI,UAAU,UAAU;AACvC,IAAAC,aAAY,MAAM;AAElB,UAAM,OAAO,OAAO,oBAAoB,EAAE,EAAE;AAC5C,IAAI,QAAQ,2BAA2B;AAAA,EACzC,CAAC;AACL;AAEA,SAASA,aAAY,QAAyB;AAC5C,MAAI,CAAC,OAAO,iBAAiB;AAC3B,IAAI,MAAM,wBAA4B,KAAK,eAAe,IAAI,SAAS;AACvE,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAEA,SAAS,aAAa,QAAwB;AAC5C,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAOC,OAAM,MAAM,MAAM;AAAA,IAC3B,KAAK;AACH,aAAOA,OAAM,OAAO,MAAM;AAAA,IAC5B,KAAK;AACH,aAAOA,OAAM,IAAI,MAAM;AAAA,IACzB;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,mBAAmB,OAAoB,YAAiC;AAC/E,MAAI,WAAW,MAAM;AACnB,IAAI,KAAK,KAAK;AACd;AAAA,EACF;AAEA,EAAI,QAAQ,cAAc;AAE1B,UAAQ,OAAO,MAAM,OAAOA,OAAM,KAAK,MAAM,KAAK,IAAI,MAAM;AAC5D,UAAQ,OAAO,MAAM,OAAOA,OAAM,OAAO,MAAM,MAAM,IAAI,IAAI;AAE7D,MAAI,MAAM,QAAQ,SAAS,GAAG;AAC5B,YAAQ,OAAO,MAAM,OAAOA,OAAM,KAAK,WAAW,IAAI,MAAM;AAC5D,UAAM,OAAO,MAAM,QAAQ,IAAI,CAAC,MAAM;AACpC,YAAM,OAAW,QAAQ,EAAE,QAAQ;AACnC,YAAM,UAAU,EAAE,QAAQ,SAAS,IAAI,EAAE,QAAQ,KAAK,IAAI,IAAI;AAC9D,YAAM,MAAM,EAAE,YAAgB,SAAS,EAAE,SAAS,IAAI;AACtD,aAAO,CAAK,SAAS,EAAE,UAAU,EAAE,GAAG,MAAM,SAAS,GAAG;AAAA,IAC1D,CAAC;AACD,IAAI,MAAM,MAAM,CAAC,UAAU,QAAQ,WAAW,KAAK,CAAC;AAEpD,YAAQ,OAAO,MAAM,IAAI;AACzB,eAAW,KAAK,MAAM,SAAS;AAC7B,cAAQ,OAAO,MAAM,OAAOA,OAAM,IAAI,SAAI,IAAQ,SAAS,EAAE,UAAU,EAAE,IAAI,IAAI;AACjF,cAAQ,OAAO,MAAM,SAASA,OAAM,IAAI,eAAe,IAAI,EAAE,aAAa,IAAI;AAC9E,cAAQ,OAAO,MAAM,SAASA,OAAM,IAAI,cAAc,IAAI,EAAE,gBAAgB,IAAI;AAAA,IAClF;AAAA,EACF;AAEA,MAAI,MAAM,KAAK,SAAS,GAAG;AACzB,YAAQ,OAAO,MAAM,OAAOA,OAAM,KAAK,iBAAiB,IAAI,MAAM;AAClE,eAAW,OAAO,MAAM,MAAM;AAC5B,cAAQ,OAAO,MAAM,OAAOA,OAAM,OAAO,QAAG,IAAI,MAAM,MAAM,IAAI;AAAA,IAClE;AAAA,EACF;AAEA,UAAQ,OAAO,MAAM,SAASA,OAAM,IAAI,GAAG,MAAM,WAAW,iBAAc,MAAM,KAAK,MAAM,gBAAgB,IAAI,IAAI;AACrH;;;APrNA,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACG,KAAK,IAAI,EACT,YAAY,yEAAoE,EAChF,QAAQ,OAAW,EACnB,OAAO,UAAU,mCAAmC,EACpD,OAAO,mBAAmB,uBAAuB,EACjD,OAAO,mBAAmB,2BAA2B,EACrD,OAAO,aAAa,2BAA2B,EAC/C,OAAO,cAAc,wBAAwB;AAEhD,qBAAqB,OAAO;AAC5B,uBAAuB,OAAO;AAC9B,uBAAuB,OAAO;AAC9B,yBAAyB,OAAO;AAEhC,QAAQ,KAAK,aAAa,CAAC,cAAc,kBAAkB;AACzD,QAAM,OAAO,QAAQ,KAAK;AAC1B,MAAI,KAAK,UAAU,OAAO;AACxB,YAAQ,IAAI,cAAc;AAAA,EAC5B;AACA,MAAI,KAAK,SAAS;AAChB,UAAM,UAAU,cAAc,KAAK;AACnC,YAAQ,OAAO,MAAU,IAAI,yBAAyB,OAAO;AAAA,CAAI,CAAC;AAAA,EACpE;AACF,CAAC;AAED,eAAe,OAAO;AACpB,MAAI;AACF,UAAM,QAAQ,WAAW,QAAQ,IAAI;AAAA,EACvC,SAAS,GAAG;AACV,QAAI,aAAa,SAAS,EAAE,QAAQ,SAAS,WAAW,GAAG;AACzD,MAAI,MAAM,EAAE,OAAO;AAAA,IACrB,OAAO;AACL,MAAI,MAAM,qBAAqB,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC,EAAE;AAC3E,UAAI,QAAQ,KAAK,EAAE,SAAS;AAC1B,gBAAQ,MAAM,CAAC;AAAA,MACjB;AAAA,IACF;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAEA,KAAK;","names":["program","chalk","program","chalk","program","readline","chalk","program","requireAuth","chalk","readline"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/commands/auth.ts","../src/config.ts","../src/client.ts","../src/output.ts","../src/commands/brief.ts","../src/stream.ts","../src/commands/markets.ts","../src/commands/profile.ts","../src/commands/research.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { registerAuthCommands } from \"./commands/auth.js\";\nimport { registerBriefCommands } from \"./commands/brief.js\";\nimport { registerMarketCommands } from \"./commands/markets.js\";\nimport { registerProfileCommand } from \"./commands/profile.js\";\nimport { registerResearchCommands } from \"./commands/research.js\";\nimport * as out from \"./output.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"hl\")\n .description(\"Hedge Layer CLI — prediction market intelligence from the terminal\")\n .version(__VERSION__)\n .option(\"--json\", \"Output as JSON (machine-readable)\")\n .option(\"--api-url <url>\", \"Override API base URL\")\n .option(\"--token <token>\", \"Override stored API token\")\n .option(\"--verbose\", \"Show HTTP request details\")\n .option(\"--no-color\", \"Disable colored output\");\n\nregisterAuthCommands(program);\nregisterBriefCommands(program);\nregisterMarketCommands(program);\nregisterProfileCommand(program);\nregisterResearchCommands(program);\n\nprogram.hook(\"preAction\", (_thisCommand, actionCommand) => {\n const opts = program.opts();\n if (opts.color === false) {\n process.env.FORCE_COLOR = \"0\";\n }\n if (opts.verbose) {\n const cmdName = actionCommand.name();\n process.stderr.write(out.dim(`[verbose] Running: hl ${cmdName}\\n`));\n }\n});\n\nasync function main() {\n try {\n await program.parseAsync(process.argv);\n } catch (e) {\n if (e instanceof Error && e.message.includes(\"API error\")) {\n out.error(e.message);\n } else {\n out.error(`Unexpected error: ${e instanceof Error ? e.message : String(e)}`);\n if (program.opts().verbose) {\n console.error(e);\n }\n }\n process.exit(1);\n }\n}\n\nmain();\n","import { Command } from \"commander\";\nimport readline from \"node:readline/promises\";\nimport { loadConfig, saveConfig, clearConfig, configPath, DEFAULT_API_URL } from \"../config.js\";\nimport { ApiClient } from \"../client.js\";\nimport type { UserProfile, GlobalOptions } from \"../types.js\";\nimport * as out from \"../output.js\";\n\nexport function registerAuthCommands(program: Command): void {\n const auth = program.command(\"auth\").description(\"Manage API authentication\");\n\n auth\n .command(\"login\")\n .description(\"Authenticate with a Hedge Layer API token\")\n .option(\"--api-url <url>\", \"API base URL\", DEFAULT_API_URL)\n .action(async (cmdOpts: { apiUrl?: string }) => {\n const globalOpts = program.opts<GlobalOptions>();\n\n const rl = readline.createInterface({ input: process.stdin, output: process.stderr });\n try {\n out.heading(\"Hedge Layer CLI — Login\");\n process.stderr.write(\n `Create an API token at ${out.bold(\"https://hedgelayer.ai/settings\")} → API Tokens\\n\\n`,\n );\n\n const token = (await rl.question(\"Paste your API token: \")).trim();\n\n if (!token.startsWith(\"hl_\") || token.length !== 43) {\n out.error('Invalid token format. Tokens start with \"hl_\" and are 43 characters.');\n process.exit(1);\n }\n\n const apiUrl = globalOpts.apiUrl ?? cmdOpts.apiUrl ?? DEFAULT_API_URL;\n const client = new ApiClient({ token, apiUrl });\n\n process.stderr.write(\"\\nValidating token...\");\n let profile: UserProfile;\n try {\n profile = await client.get<UserProfile>(\"/api/profile\");\n } catch {\n process.stderr.write(\"\\n\");\n out.error(\"Token validation failed. Check your token and try again.\");\n process.exit(1);\n }\n process.stderr.write(\" done\\n\\n\");\n\n saveConfig({ api_url: apiUrl, token });\n\n out.success(`Logged in as ${out.bold(profile.handle || profile.user_id)}`);\n process.stderr.write(` Config saved to ${out.dim(configPath())}\\n`);\n } finally {\n rl.close();\n }\n });\n\n auth\n .command(\"status\")\n .description(\"Show current authentication status\")\n .action(async () => {\n const globalOpts = program.opts<GlobalOptions>();\n const config = loadConfig();\n const token = globalOpts.token ?? config.token;\n\n if (!token) {\n out.warn(\"Not logged in. Run \" + out.bold(\"hl auth login\") + \" to authenticate.\");\n process.exit(1);\n }\n\n const client = new ApiClient(globalOpts);\n\n try {\n const profile = await client.get<UserProfile>(\"/api/profile\");\n if (globalOpts.json) {\n out.json({\n authenticated: true,\n handle: profile.handle,\n user_id: profile.user_id,\n api_url: client.apiUrl,\n });\n } else {\n out.heading(\"Auth Status\");\n out.table(\n [\n [\"Handle\", out.bold(profile.handle || \"(none)\")],\n [\"User ID\", profile.user_id],\n [\"API URL\", client.apiUrl],\n [\"Config\", configPath()],\n ],\n );\n }\n } catch {\n out.error(\"Token is invalid or expired. Run \" + out.bold(\"hl auth login\") + \" to re-authenticate.\");\n process.exit(1);\n }\n });\n\n auth\n .command(\"logout\")\n .description(\"Remove stored API token\")\n .action(() => {\n clearConfig();\n out.success(\"Logged out. Token removed from \" + out.dim(configPath()));\n });\n}\n","import { readFileSync, writeFileSync, mkdirSync, existsSync, unlinkSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\n\nconst CONFIG_DIR = join(homedir(), \".hedgelayer\");\nconst CONFIG_FILE = join(CONFIG_DIR, \"config.json\");\n\nexport const DEFAULT_API_URL = \"https://hedgelayer.ai\";\n\nexport interface Config {\n api_url: string;\n token: string | null;\n}\n\nfunction defaultConfig(): Config {\n return { api_url: DEFAULT_API_URL, token: null };\n}\n\nexport function loadConfig(): Config {\n try {\n if (!existsSync(CONFIG_FILE)) return defaultConfig();\n const raw = readFileSync(CONFIG_FILE, \"utf-8\");\n const parsed = JSON.parse(raw);\n return {\n api_url: parsed.api_url ?? DEFAULT_API_URL,\n token: parsed.token ?? null,\n };\n } catch {\n return defaultConfig();\n }\n}\n\nexport function saveConfig(config: Config): void {\n mkdirSync(CONFIG_DIR, { recursive: true });\n writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2) + \"\\n\", \"utf-8\");\n}\n\nexport function clearConfig(): void {\n try {\n if (existsSync(CONFIG_FILE)) unlinkSync(CONFIG_FILE);\n } catch {\n // ignore\n }\n}\n\nexport function configPath(): string {\n return CONFIG_FILE;\n}\n","import type { GlobalOptions } from \"./types.js\";\nimport { loadConfig, DEFAULT_API_URL } from \"./config.js\";\n\nexport class ApiClient {\n private baseUrl: string;\n private token: string | null;\n private verbose: boolean;\n\n constructor(opts: GlobalOptions = {}) {\n const config = loadConfig();\n this.baseUrl = (opts.apiUrl ?? config.api_url ?? DEFAULT_API_URL).replace(/\\/$/, \"\");\n this.token = opts.token ?? config.token ?? null;\n this.verbose = opts.verbose ?? false;\n }\n\n get isAuthenticated(): boolean {\n return this.token !== null;\n }\n\n get apiUrl(): string {\n return this.baseUrl;\n }\n\n private headers(extra: Record<string, string> = {}): Record<string, string> {\n const h: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...extra,\n };\n if (this.token) {\n h[\"Authorization\"] = `Bearer ${this.token}`;\n }\n return h;\n }\n\n private log(method: string, path: string, status?: number): void {\n if (!this.verbose) return;\n const statusStr = status ? ` → ${status}` : \"\";\n process.stderr.write(`[verbose] ${method} ${this.baseUrl}${path}${statusStr}\\n`);\n }\n\n async get<T>(path: string, params?: Record<string, string>): Promise<T> {\n const url = new URL(path, this.baseUrl);\n if (params) {\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined && v !== \"\") url.searchParams.set(k, v);\n }\n }\n\n this.log(\"GET\", `${url.pathname}${url.search}`);\n const res = await fetch(url.toString(), { headers: this.headers() });\n this.log(\"GET\", `${url.pathname}${url.search}`, res.status);\n\n if (!res.ok) {\n const body = await res.text();\n throw new ApiError(res.status, body);\n }\n return res.json() as Promise<T>;\n }\n\n async post<T>(path: string, body?: unknown): Promise<T> {\n this.log(\"POST\", path);\n const res = await fetch(`${this.baseUrl}${path}`, {\n method: \"POST\",\n headers: this.headers(),\n body: body !== undefined ? JSON.stringify(body) : undefined,\n });\n this.log(\"POST\", path, res.status);\n\n if (!res.ok) {\n const text = await res.text();\n throw new ApiError(res.status, text);\n }\n return res.json() as Promise<T>;\n }\n\n async patch<T>(path: string, body: unknown): Promise<T> {\n this.log(\"PATCH\", path);\n const res = await fetch(`${this.baseUrl}${path}`, {\n method: \"PATCH\",\n headers: this.headers(),\n body: JSON.stringify(body),\n });\n this.log(\"PATCH\", path, res.status);\n\n if (!res.ok) {\n const text = await res.text();\n throw new ApiError(res.status, text);\n }\n return res.json() as Promise<T>;\n }\n\n async delete(path: string): Promise<void> {\n this.log(\"DELETE\", path);\n const res = await fetch(`${this.baseUrl}${path}`, {\n method: \"DELETE\",\n headers: this.headers(),\n });\n this.log(\"DELETE\", path, res.status);\n\n if (!res.ok) {\n const text = await res.text();\n throw new ApiError(res.status, text);\n }\n }\n\n async stream(path: string, body: unknown): Promise<ReadableStream<Uint8Array>> {\n this.log(\"POST (stream)\", path);\n const res = await fetch(`${this.baseUrl}${path}`, {\n method: \"POST\",\n headers: this.headers({ Accept: \"text/event-stream\" }),\n body: JSON.stringify(body),\n });\n this.log(\"POST (stream)\", path, res.status);\n\n if (!res.ok) {\n const text = await res.text();\n throw new ApiError(res.status, text);\n }\n if (!res.body) {\n throw new ApiError(0, \"No response body for stream\");\n }\n return res.body;\n }\n\n async streamNdjson(path: string, body: unknown): Promise<ReadableStream<Uint8Array>> {\n this.log(\"POST (ndjson)\", path);\n const res = await fetch(`${this.baseUrl}${path}`, {\n method: \"POST\",\n headers: this.headers({ Accept: \"application/x-ndjson\" }),\n body: JSON.stringify(body),\n });\n this.log(\"POST (ndjson)\", path, res.status);\n\n if (!res.ok) {\n const text = await res.text();\n throw new ApiError(res.status, text);\n }\n if (!res.body) {\n throw new ApiError(0, \"No response body for stream\");\n }\n return res.body;\n }\n}\n\nexport class ApiError extends Error {\n constructor(\n public status: number,\n public body: string,\n ) {\n let msg: string;\n try {\n const parsed = JSON.parse(body);\n msg = parsed.error ?? parsed.message ?? body;\n } catch {\n msg = body;\n }\n super(`API error ${status}: ${msg}`);\n this.name = \"ApiError\";\n }\n}\n","import chalk from \"chalk\";\n\nexport function json(data: unknown): void {\n process.stdout.write(JSON.stringify(data, null, 2) + \"\\n\");\n}\n\nexport function table(rows: string[][], headers?: string[]): void {\n const allRows = headers ? [headers, ...rows] : rows;\n const colWidths: number[] = [];\n for (const row of allRows) {\n for (let i = 0; i < row.length; i++) {\n colWidths[i] = Math.max(colWidths[i] ?? 0, stripAnsi(row[i]).length);\n }\n }\n\n for (let r = 0; r < allRows.length; r++) {\n const row = allRows[r];\n const padded = row.map((cell, i) => {\n const bare = stripAnsi(cell);\n const pad = colWidths[i] - bare.length;\n return cell + \" \".repeat(Math.max(0, pad));\n });\n process.stdout.write(\" \" + padded.join(\" \") + \"\\n\");\n\n if (r === 0 && headers) {\n const sep = colWidths.map((w) => \"─\".repeat(w)).join(\"──\");\n process.stdout.write(\" \" + sep + \"\\n\");\n }\n }\n}\n\nfunction stripAnsi(str: string): string {\n // eslint-disable-next-line no-control-regex\n return str.replace(/\\x1b\\[[0-9;]*m/g, \"\");\n}\n\nexport function heading(text: string): void {\n process.stdout.write(\"\\n\" + chalk.bold(text) + \"\\n\\n\");\n}\n\nexport function success(text: string): void {\n process.stdout.write(chalk.green(\"✓\") + \" \" + text + \"\\n\");\n}\n\nexport function warn(text: string): void {\n process.stdout.write(chalk.yellow(\"⚠\") + \" \" + text + \"\\n\");\n}\n\nexport function error(text: string): void {\n process.stderr.write(chalk.red(\"✗\") + \" \" + text + \"\\n\");\n}\n\nexport function dim(text: string): string {\n return chalk.dim(text);\n}\n\nexport function bold(text: string): string {\n return chalk.bold(text);\n}\n\nexport function currency(n: number): string {\n return \"$\" + n.toLocaleString(\"en-US\", { minimumFractionDigits: 2, maximumFractionDigits: 2 });\n}\n\nexport function percent(n: number): string {\n return (n * 100).toFixed(1) + \"%\";\n}\n\nexport function truncate(str: string, max: number): string {\n if (str.length <= max) return str;\n return str.slice(0, max - 1) + \"…\";\n}\n\nexport function relativeTime(date: string): string {\n const diff = Date.now() - new Date(date).getTime();\n const mins = Math.floor(diff / 60_000);\n if (mins < 1) return \"just now\";\n if (mins < 60) return `${mins}m ago`;\n const hours = Math.floor(mins / 60);\n if (hours < 24) return `${hours}h ago`;\n const days = Math.floor(hours / 24);\n return `${days}d ago`;\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { ApiClient } from \"../client.js\";\nimport { parseNdjsonStream } from \"../stream.js\";\nimport type { MarketBrief, BriefRequest, BriefRequestFilters, GlobalOptions } from \"../types.js\";\nimport * as out from \"../output.js\";\n\nexport function registerBriefCommands(program: Command): void {\n program\n .command(\"brief <query>\")\n .description(\"Generate a Market Brief for a topic (non-interactive)\")\n .option(\"-l, --location <location>\", \"Geographic context (e.g. 'Middle East', 'US')\")\n .option(\"-t, --time-horizon <horizon>\", \"Time frame (e.g. '3 months', '2026')\")\n .option(\"--tags <tags>\", \"Comma-separated focus area tags (e.g. 'geopolitics,energy')\")\n .option(\"--min-volume <n>\", \"Minimum market volume in USD\", parseFloat)\n .option(\"--max-yes-price <n>\", \"Maximum YES price (0-1)\", parseFloat)\n .option(\"--no-stream\", \"Disable streaming — block until complete\")\n .action(async (query: string, cmdOpts: BriefCmdOpts) => {\n const globalOpts = program.opts<GlobalOptions>();\n const client = new ApiClient(globalOpts);\n requireAuth(client);\n\n const filters = buildFilters(cmdOpts);\n const body: BriefRequest = {\n query,\n ...(cmdOpts.location && { location: cmdOpts.location }),\n ...(cmdOpts.timeHorizon && { timeHorizon: cmdOpts.timeHorizon }),\n ...(filters && { filters }),\n stream: cmdOpts.stream !== false,\n };\n\n if (body.stream) {\n await runStreaming(client, body, globalOpts);\n } else {\n await runBlocking(client, body, globalOpts);\n }\n });\n}\n\n// ---------------------------------------------------------------------------\n// Command option types\n// ---------------------------------------------------------------------------\n\ninterface BriefCmdOpts {\n location?: string;\n timeHorizon?: string;\n tags?: string;\n minVolume?: number;\n maxYesPrice?: number;\n stream?: boolean;\n}\n\nfunction buildFilters(opts: BriefCmdOpts): BriefRequestFilters | undefined {\n const tags = opts.tags?.split(\",\").map((t) => t.trim()).filter(Boolean);\n const hasFilters = opts.minVolume != null || opts.maxYesPrice != null || (tags && tags.length > 0);\n if (!hasFilters) return undefined;\n return {\n ...(opts.minVolume != null && { minVolume: opts.minVolume }),\n ...(opts.maxYesPrice != null && { maxYesPrice: opts.maxYesPrice }),\n ...(tags && tags.length > 0 && { tags }),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Streaming mode (default)\n// ---------------------------------------------------------------------------\n\nasync function runStreaming(client: ApiClient, body: BriefRequest, globalOpts: GlobalOptions): Promise<void> {\n const startTime = Date.now();\n process.stderr.write(chalk.dim(` Generating brief for \"${out.truncate(body.query, 50)}\"...\\n`));\n\n const stream = await client.streamNdjson(\"/api/brief\", body);\n const result = await parseNdjsonStream(stream, {\n onProgress: (step, message) => {\n process.stderr.write(chalk.dim(` [${step}] `) + message + \"\\n\");\n },\n });\n\n const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);\n\n if (result.error) {\n out.error(`Brief failed (${result.error.code}): ${result.error.message}`);\n process.exit(1);\n }\n\n if (!result.brief) {\n out.error(\"No Market Brief was produced.\");\n process.exit(1);\n }\n\n process.stderr.write(chalk.dim(` Done (${elapsed}s)\\n\\n`));\n displayBrief(result.brief as unknown as MarketBrief, globalOpts);\n}\n\n// ---------------------------------------------------------------------------\n// Blocking mode (--no-stream)\n// ---------------------------------------------------------------------------\n\nasync function runBlocking(client: ApiClient, body: BriefRequest, globalOpts: GlobalOptions): Promise<void> {\n const startTime = Date.now();\n process.stderr.write(chalk.dim(` Generating brief for \"${out.truncate(body.query, 50)}\"...\\n`));\n\n const brief = await client.post<MarketBrief>(\"/api/brief\", body);\n\n const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);\n process.stderr.write(chalk.dim(` Done (${elapsed}s)\\n\\n`));\n\n displayBrief(brief, globalOpts);\n}\n\n// ---------------------------------------------------------------------------\n// Display\n// ---------------------------------------------------------------------------\n\nfunction displayBrief(brief: MarketBrief, globalOpts: GlobalOptions): void {\n if (globalOpts.json) {\n out.json(brief);\n return;\n }\n\n out.heading(\"Market Brief\");\n\n process.stdout.write(\" \" + chalk.bold(brief.title) + \"\\n\\n\");\n process.stdout.write(\" \" + chalk.italic(brief.thesis) + \"\\n\");\n\n if (brief.markets.length > 0) {\n process.stdout.write(\"\\n\" + chalk.bold(\" Markets\") + \"\\n\\n\");\n const rows = brief.markets.map((m) => {\n const prob = out.percent(m.yesPrice);\n const signals = m.signals.length > 0 ? m.signals.join(\", \") : \"—\";\n const liq = m.liquidity ? out.currency(m.liquidity) : \"—\";\n return [out.truncate(m.question, 40), prob, signals, liq];\n });\n out.table(rows, [\"Market\", \"Prob\", \"Signals\", \"Liq\"]);\n\n process.stdout.write(\"\\n\");\n for (const m of brief.markets) {\n process.stdout.write(\" \" + chalk.dim(\"▸ \") + out.truncate(m.question, 50) + \"\\n\");\n process.stdout.write(\" \" + chalk.dim(\"Causal link: \") + m.causalLink + \"\\n\");\n process.stdout.write(\" \" + chalk.dim(\"Polymarket: \") + m.polymarketUrl + \"\\n\");\n }\n }\n\n if (brief.gaps.length > 0) {\n process.stdout.write(\"\\n\" + chalk.bold(\" Coverage Gaps\") + \"\\n\\n\");\n for (const gap of brief.gaps) {\n process.stdout.write(\" \" + chalk.yellow(\"▸\") + \" \" + gap + \"\\n\");\n }\n }\n\n const marketCount = brief.marketCount ?? brief.markets.length;\n process.stdout.write(\"\\n \" + chalk.dim(`${marketCount} markets · ${brief.gaps.length} coverage gaps`) + \"\\n\");\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction requireAuth(client: ApiClient): void {\n if (!client.isAuthenticated) {\n out.error(\"Not logged in. Run \" + out.bold(\"hl auth login\") + \" first.\");\n process.exit(1);\n }\n}\n","/**\n * Parses the Vercel AI SDK UI Message Stream protocol (SSE format).\n *\n * The server sends Server-Sent Events where each `data:` line contains\n * a JSON object with a `type` field:\n * text-delta: { type, id, delta }\n * tool-input-start: { type, toolCallId, toolName }\n * tool-input-delta: { type, toolCallId, inputTextDelta }\n * tool-input-available: { type, toolCallId, toolName, input }\n * tool-output-available:{ type, toolCallId, output }\n * error: { type, errorText }\n * [DONE]: stream termination sentinel\n */\n\nexport interface StreamCallbacks {\n onText?: (text: string) => void;\n onToolCall?: (name: string, args: unknown) => void;\n onToolResult?: (name: string, result: unknown) => void;\n}\n\nexport interface StreamResult {\n assistantText: string;\n toolCalls: Array<{ name: string; args: unknown }>;\n marketBrief: Record<string, unknown> | null;\n}\n\nexport async function parseStream(\n body: ReadableStream<Uint8Array>,\n callbacks: StreamCallbacks = {},\n): Promise<StreamResult> {\n const decoder = new TextDecoder();\n const reader = body.getReader();\n\n let buffer = \"\";\n let assistantText = \"\";\n const toolCalls: Array<{ name: string; args: unknown }> = [];\n const activeToolCalls = new Map<string, { name: string; argStr: string }>();\n let marketBrief: Record<string, unknown> | null = null;\n\n while (true) {\n const { done, value } = await reader.read();\n if (!done) {\n buffer += decoder.decode(value, { stream: true });\n }\n\n const lines = buffer.split(\"\\n\");\n buffer = done ? \"\" : (lines.pop() ?? \"\");\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith(\":\")) continue;\n\n if (!trimmed.startsWith(\"data:\")) continue;\n const payload = trimmed.slice(5).trim();\n\n if (payload === \"[DONE]\") continue;\n\n let msg: Record<string, unknown>;\n try {\n msg = JSON.parse(payload);\n } catch {\n continue;\n }\n\n const type = msg.type as string;\n\n switch (type) {\n case \"text-delta\": {\n const delta = msg.delta as string;\n if (delta) {\n assistantText += delta;\n callbacks.onText?.(delta);\n }\n break;\n }\n\n case \"tool-input-start\": {\n const id = msg.toolCallId as string;\n const name = msg.toolName as string;\n if (id && name) {\n activeToolCalls.set(id, { name, argStr: \"\" });\n }\n break;\n }\n\n case \"tool-input-delta\": {\n const id = msg.toolCallId as string;\n const active = activeToolCalls.get(id);\n if (active) {\n active.argStr += msg.inputTextDelta as string;\n }\n break;\n }\n\n case \"tool-input-available\": {\n const id = msg.toolCallId as string;\n const active = activeToolCalls.get(id);\n if (active) {\n const args = msg.input ?? active.argStr;\n toolCalls.push({ name: active.name, args });\n callbacks.onToolCall?.(active.name, args);\n }\n break;\n }\n\n case \"tool-output-available\": {\n const id = msg.toolCallId as string;\n const active = activeToolCalls.get(id);\n if (active) {\n callbacks.onToolResult?.(active.name, msg.output);\n if (active.name === \"buildMarketBrief\" && isMarketBrief(msg.output)) {\n marketBrief = msg.output as Record<string, unknown>;\n }\n activeToolCalls.delete(id);\n }\n break;\n }\n\n case \"error\": {\n throw new Error((msg.errorText as string) ?? \"Unknown stream error\");\n }\n }\n }\n\n if (done) break;\n }\n\n return { assistantText, toolCalls, marketBrief };\n}\n\nfunction isMarketBrief(val: unknown): boolean {\n return (\n val !== null &&\n typeof val === \"object\" &&\n \"title\" in (val as Record<string, unknown>) &&\n \"markets\" in (val as Record<string, unknown>)\n );\n}\n\n// ---------------------------------------------------------------------------\n// NDJSON stream parser (for POST /api/brief)\n// ---------------------------------------------------------------------------\n\nexport interface NdjsonCallbacks {\n onProgress?: (step: string, message: string) => void;\n}\n\nexport interface NdjsonBriefResult {\n brief: Record<string, unknown> | null;\n error: { code: string; message: string } | null;\n}\n\n/**\n * Parses an NDJSON stream from the /api/brief endpoint.\n *\n * Each line is a JSON object with a `type` field:\n * progress: { type, step, message }\n * brief: { type, data: MarketBrief }\n * error: { type, code, message }\n */\nexport async function parseNdjsonStream(\n body: ReadableStream<Uint8Array>,\n callbacks: NdjsonCallbacks = {},\n): Promise<NdjsonBriefResult> {\n const decoder = new TextDecoder();\n const reader = body.getReader();\n\n let buffer = \"\";\n let brief: Record<string, unknown> | null = null;\n let error: { code: string; message: string } | null = null;\n\n while (true) {\n const { done, value } = await reader.read();\n if (!done) {\n buffer += decoder.decode(value, { stream: true });\n }\n\n const lines = buffer.split(\"\\n\");\n buffer = done ? \"\" : (lines.pop() ?? \"\");\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n\n let msg: Record<string, unknown>;\n try {\n msg = JSON.parse(trimmed);\n } catch {\n continue;\n }\n\n const type = msg.type as string;\n\n switch (type) {\n case \"progress\": {\n callbacks.onProgress?.(msg.step as string, msg.message as string);\n break;\n }\n case \"brief\": {\n brief = msg.data as Record<string, unknown>;\n break;\n }\n case \"error\": {\n error = {\n code: msg.code as string,\n message: msg.message as string,\n };\n break;\n }\n }\n }\n\n if (done) break;\n }\n\n return { brief, error };\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { ApiClient } from \"../client.js\";\nimport type { Orderbook, SlippageResult, GlobalOptions } from \"../types.js\";\nimport * as out from \"../output.js\";\n\nexport function registerMarketCommands(program: Command): void {\n const markets = program.command(\"markets\").description(\"Polymarket orderbook tools\");\n\n markets\n .command(\"orderbook <tokenId>\")\n .description(\"Show orderbook spread and depth for a CLOB token\")\n .option(\"-s, --size <n>\", \"Size for slippage calculation\")\n .action(async (tokenId: string, cmdOpts: { size?: string }) => {\n const globalOpts = program.opts<GlobalOptions>();\n const client = new ApiClient(globalOpts);\n\n const params: Record<string, string> = { tokenId };\n if (cmdOpts.size) params.size = cmdOpts.size;\n\n const data = await client.get<{\n book: Orderbook;\n spread: { bid: number; ask: number; spread: number } | null;\n askDepth: number;\n slippage: SlippageResult | null;\n }>(\"/api/orderbook\", params);\n\n if (globalOpts.json) {\n out.json(data);\n return;\n }\n\n out.heading(\"Orderbook\");\n\n if (data.spread) {\n out.table([\n [\"Best Bid\", data.spread.bid.toFixed(4)],\n [\"Best Ask\", data.spread.ask.toFixed(4)],\n [\"Spread\", out.percent(data.spread.spread)],\n [\"Ask Depth\", out.currency(data.askDepth)],\n ]);\n } else {\n out.warn(\"No spread data available (empty orderbook)\");\n }\n\n if (data.slippage) {\n process.stdout.write(\"\\n\");\n out.table([\n [\"Avg Fill Price\", data.slippage.avgPrice.toFixed(4)],\n [\"Worst Price\", data.slippage.worstPrice.toFixed(4)],\n [\"Slippage\", out.percent(data.slippage.slippage)],\n [\"Fillable Size\", out.currency(data.slippage.fillableSize)],\n ]);\n }\n\n if (data.book.asks.length > 0) {\n process.stdout.write(\"\\n\" + chalk.dim(\" Top 5 asks:\") + \"\\n\");\n const askRows = data.book.asks.slice(0, 5).map((l) => [l.price, l.size]);\n out.table(askRows, [\"Price\", \"Size\"]);\n }\n\n if (data.book.bids.length > 0) {\n process.stdout.write(\"\\n\" + chalk.dim(\" Top 5 bids:\") + \"\\n\");\n const bidRows = data.book.bids.slice(0, 5).map((l) => [l.price, l.size]);\n out.table(bidRows, [\"Price\", \"Size\"]);\n }\n });\n}\n\n","import { Command } from \"commander\";\nimport { ApiClient } from \"../client.js\";\nimport type { UserProfile, GlobalOptions } from \"../types.js\";\nimport * as out from \"../output.js\";\n\nexport function registerProfileCommand(program: Command): void {\n program\n .command(\"profile\")\n .description(\"Show your user profile\")\n .action(async () => {\n const globalOpts = program.opts<GlobalOptions>();\n const client = new ApiClient(globalOpts);\n requireAuth(client);\n\n const profile = await client.get<UserProfile>(\"/api/profile\");\n\n if (globalOpts.json) {\n out.json(profile);\n return;\n }\n\n out.heading(\"Profile\");\n out.table([\n [\"Handle\", out.bold(profile.handle || \"(none)\")],\n [\"User ID\", profile.user_id],\n [\"Created\", new Date(profile.created_at).toLocaleDateString()],\n ]);\n });\n}\n\nfunction requireAuth(client: ApiClient): void {\n if (!client.isAuthenticated) {\n out.error(\"Not logged in. Run \" + out.bold(\"hl auth login\") + \" first.\");\n process.exit(1);\n }\n}\n","import { Command } from \"commander\";\nimport readline from \"node:readline/promises\";\nimport chalk from \"chalk\";\nimport { ApiClient } from \"../client.js\";\nimport { parseStream } from \"../stream.js\";\nimport type { Assessment, MarketBrief, GlobalOptions, ResearchResponse } from \"../types.js\";\nimport * as out from \"../output.js\";\n\nexport function registerResearchCommands(program: Command): void {\n const research = program.command(\"research\").description(\"AI-powered market research\");\n\n research\n .command(\"start\", { isDefault: true })\n .description(\"Start an interactive market research session\")\n .action(async () => {\n const globalOpts = program.opts<GlobalOptions>();\n const client = new ApiClient(globalOpts);\n requireAuth(client);\n\n const { id } = await client.post<{ id: string }>(\"/api/assessments\");\n\n out.heading(\"Market Research\");\n process.stderr.write(\n chalk.dim(\" Describe a topic or thesis to explore. Type /quit to exit.\\n\\n\"),\n );\n\n let msgCounter = 0;\n const uiMsg = (role: string, content: string) => ({\n id: `msg-${++msgCounter}`,\n role,\n content,\n parts: [{ type: \"text\" as const, text: content }],\n });\n\n const messages: ReturnType<typeof uiMsg>[] = [];\n const rl = readline.createInterface({ input: process.stdin, output: process.stderr });\n\n try {\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const userInput = await rl.question(chalk.cyan(\"You: \"));\n if (!userInput.trim()) continue;\n if (userInput.trim() === \"/quit\") break;\n\n messages.push(uiMsg(\"user\", userInput));\n\n process.stderr.write(chalk.dim(\"\\nAssistant: \"));\n\n try {\n const body = await client.stream(\"/api/chat\", {\n messages,\n assessmentId: id,\n });\n\n const result = await parseStream(body, {\n onText: (text) => process.stderr.write(text),\n onToolCall: (name) => {\n process.stderr.write(chalk.dim(`\\n [tool: ${name}]\\n`));\n },\n onToolResult: (name, toolResult) => {\n if (globalOpts.verbose) {\n process.stderr.write(chalk.dim(` [result: ${name}] ${JSON.stringify(toolResult).slice(0, 200)}\\n`));\n }\n },\n });\n\n process.stderr.write(\"\\n\\n\");\n\n if (result.assistantText) {\n messages.push(uiMsg(\"assistant\", result.assistantText));\n }\n\n if (result.marketBrief) {\n displayMarketBrief(result.marketBrief as unknown as MarketBrief, globalOpts);\n break;\n }\n } catch (e) {\n process.stderr.write(\"\\n\");\n out.error(`Chat error: ${e instanceof Error ? e.message : String(e)}`);\n }\n }\n } finally {\n rl.close();\n }\n });\n\n research\n .command(\"run <query>\")\n .description(\"Run research on a topic and return the final brief as JSON\")\n .action(async (query: string) => {\n const globalOpts = program.opts<GlobalOptions>();\n const client = new ApiClient(globalOpts);\n requireAuth(client);\n\n process.stderr.write(chalk.dim(` Researching \"${out.truncate(query, 60)}\"...\\n`));\n const startTime = Date.now();\n\n const result = await client.post<ResearchResponse>(\"/api/research\", { query });\n\n const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);\n process.stderr.write(chalk.dim(` Done (${elapsed}s)\\n\\n`));\n\n if (result.brief) {\n out.json(result.brief);\n } else {\n process.stderr.write(chalk.yellow(\"No market brief was produced.\\n\"));\n out.json(result);\n }\n });\n\n research\n .command(\"list\")\n .description(\"List past research sessions\")\n .option(\"-s, --status <status>\", \"Filter by status\")\n .action(async (cmdOpts: { status?: string }) => {\n const globalOpts = program.opts<GlobalOptions>();\n const client = new ApiClient(globalOpts);\n requireAuth(client);\n\n const params: Record<string, string> = { list: \"true\" };\n if (cmdOpts.status) params.status = cmdOpts.status;\n\n const data = await client.get<{ assessments: Assessment[] }>(\"/api/assessments\", params);\n\n if (globalOpts.json) {\n out.json(data.assessments);\n return;\n }\n\n if (data.assessments.length === 0) {\n out.warn(\"No research sessions found.\");\n return;\n }\n\n out.heading(`Research Sessions (${data.assessments.length})`);\n\n const rows = data.assessments.map((a) => {\n const status = formatStatus(a.status);\n const brief = a.market_brief?.title ?? \"—\";\n const markets = a.market_brief ? String(a.market_brief.marketCount) : \"—\";\n return [a.id.slice(0, 8), status, out.truncate(brief, 30), markets, out.relativeTime(a.created_at)];\n });\n\n out.table(rows, [\"ID\", \"Status\", \"Brief\", \"Markets\", \"Created\"]);\n });\n\n research\n .command(\"show <id>\")\n .description(\"Show research session details\")\n .action(async (id: string) => {\n const globalOpts = program.opts<GlobalOptions>();\n const client = new ApiClient(globalOpts);\n requireAuth(client);\n\n const assessment = await client.get<Assessment>(`/api/assessments/${id}`);\n\n if (globalOpts.json) {\n out.json(assessment);\n return;\n }\n\n out.heading(\"Research Session \" + out.dim(assessment.id.slice(0, 8)));\n\n out.table([\n [\"Status\", formatStatus(assessment.status)],\n [\"Created\", new Date(assessment.created_at).toLocaleString()],\n [\"Updated\", new Date(assessment.updated_at).toLocaleString()],\n ]);\n\n if (assessment.market_brief) {\n displayMarketBrief(assessment.market_brief, globalOpts);\n }\n });\n\n research\n .command(\"delete <id>\")\n .description(\"Delete a research session\")\n .action(async (id: string) => {\n const globalOpts = program.opts<GlobalOptions>();\n const client = new ApiClient(globalOpts);\n requireAuth(client);\n\n await client.delete(`/api/assessments/${id}`);\n out.success(\"Research session deleted.\");\n });\n}\n\nfunction requireAuth(client: ApiClient): void {\n if (!client.isAuthenticated) {\n out.error(\"Not logged in. Run \" + out.bold(\"hl auth login\") + \" first.\");\n process.exit(1);\n }\n}\n\nfunction formatStatus(status: string): string {\n switch (status) {\n case \"completed\":\n return chalk.green(status);\n case \"in_progress\":\n return chalk.yellow(status);\n case \"abandoned\":\n return chalk.red(status);\n default:\n return status;\n }\n}\n\nfunction displayMarketBrief(brief: MarketBrief, globalOpts: GlobalOptions): void {\n if (globalOpts.json) {\n out.json(brief);\n return;\n }\n\n out.heading(\"Market Brief\");\n\n process.stdout.write(\" \" + chalk.bold(brief.title) + \"\\n\\n\");\n process.stdout.write(\" \" + chalk.italic(brief.thesis) + \"\\n\");\n\n if (brief.markets.length > 0) {\n process.stdout.write(\"\\n\" + chalk.bold(\" Markets\") + \"\\n\\n\");\n const rows = brief.markets.map((m) => {\n const prob = out.percent(m.yesPrice);\n const signals = m.signals.length > 0 ? m.signals.join(\", \") : \"—\";\n const liq = m.liquidity ? out.currency(m.liquidity) : \"—\";\n return [out.truncate(m.question, 40), prob, signals, liq];\n });\n out.table(rows, [\"Market\", \"Prob\", \"Signals\", \"Liq\"]);\n\n process.stdout.write(\"\\n\");\n for (const m of brief.markets) {\n process.stdout.write(\" \" + chalk.dim(\"▸ \") + out.truncate(m.question, 50) + \"\\n\");\n process.stdout.write(\" \" + chalk.dim(\"Causal link: \") + m.causalLink + \"\\n\");\n process.stdout.write(\" \" + chalk.dim(\"Polymarket: \") + m.polymarketUrl + \"\\n\");\n }\n }\n\n if (brief.gaps.length > 0) {\n process.stdout.write(\"\\n\" + chalk.bold(\" Coverage Gaps\") + \"\\n\\n\");\n for (const gap of brief.gaps) {\n process.stdout.write(\" \" + chalk.yellow(\"▸\") + \" \" + gap + \"\\n\");\n }\n }\n\n process.stdout.write(\"\\n \" + chalk.dim(`${brief.marketCount} markets · ${brief.gaps.length} coverage gaps`) + \"\\n\");\n}\n"],"mappings":"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","names":["program","chalk","error","program","chalk","chalk","program","chalk","program","requireAuth","readline","chalk","program","requireAuth","chalk","readline"]}
|