@hedge-layer/cli 1.1.0 → 1.3.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 CHANGED
@@ -59,9 +59,6 @@ hl --json brief "crypto regulation 2026" | jq '.markets'
59
59
 
60
60
  # Filter by tags and volume
61
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
62
  ```
66
63
 
67
64
  | Option | Description |
@@ -71,7 +68,6 @@ hl brief "AI regulation in Europe" --no-stream
71
68
  | `--tags <tags>` | Comma-separated focus area tags (e.g. `"geopolitics,energy"`) |
72
69
  | `--min-volume <n>` | Minimum market volume in USD |
73
70
  | `--max-yes-price <n>` | Maximum YES price (0-1) |
74
- | `--no-stream` | Disable streaming — block until complete |
75
71
 
76
72
  ### Research
77
73
 
@@ -81,6 +77,9 @@ AI-powered interactive research sessions. Describe a topic or thesis, and the AI
81
77
  # Start an interactive research session (Q&A)
82
78
  hl research
83
79
 
80
+ # Non-interactive: same Market Brief as `hl brief`, JSON on stdout (blocking `POST /api/brief` with stream off)
81
+ hl research run "US election forecasting"
82
+
84
83
  # List past research sessions
85
84
  hl research list
86
85
  hl research list --status completed
@@ -92,17 +91,7 @@ hl research show <id>
92
91
  hl research delete <id>
93
92
  ```
94
93
 
95
- For non-interactive, single-shot brief generation, use `hl brief` it uses a dedicated API endpoint optimized for programmatic use.
96
-
97
- ### Markets
98
-
99
- Polymarket orderbook tools.
100
-
101
- ```bash
102
- # View orderbook for a specific CLOB token
103
- hl markets orderbook <tokenId>
104
- hl markets orderbook <tokenId> --size 1000
105
- ```
94
+ For a **non-interactive** JSON brief from the shell, use `hl research run` (blocking) or `hl brief` (streams progress on stderr). Both use the same `POST /api/brief` endpoint.
106
95
 
107
96
  ### Profile
108
97
 
@@ -128,30 +117,6 @@ Every command supports `--json` for pipe-friendly output:
128
117
  hl --json research list | jq '.[0].id'
129
118
  ```
130
119
 
131
- ## Development
132
-
133
- ```bash
134
- git clone https://github.com/hedge-layer/hedge-layer-cli.git
135
- cd hedge-layer-cli
136
- npm install
137
- npm run build # Build with tsup
138
- npm run dev # Watch mode
139
-
140
- # Test against local dev server
141
- node dist/index.mjs --api-url http://localhost:3000 research list
142
- ```
143
-
144
- ## Publishing
145
-
146
- Releases are automated via GitHub Actions. To publish a new version:
147
-
148
- ```bash
149
- npm version patch # or minor / major
150
- git push --tags
151
- ```
152
-
153
- The workflow builds and publishes to npm when a version tag (`v*`) is pushed. Authentication uses npm's OIDC trusted publishers — no secrets required.
154
-
155
120
  ## Changelog
156
121
 
157
122
  See [CHANGELOG.md](CHANGELOG.md) for release history.
package/dist/index.mjs CHANGED
@@ -106,6 +106,39 @@ var ApiClient = class {
106
106
  }
107
107
  return res.json();
108
108
  }
109
+ /**
110
+ * POST /api/brief with stream: false — returns the Market Brief JSON body
111
+ * plus optional telemetry from response headers.
112
+ */
113
+ async postBriefSync(query) {
114
+ const path = "/api/brief";
115
+ this.log("POST", path);
116
+ const res = await fetch(`${this.baseUrl}${path}`, {
117
+ method: "POST",
118
+ headers: this.headers(),
119
+ body: JSON.stringify({ query, stream: false })
120
+ });
121
+ this.log("POST", path, res.status);
122
+ const text = await res.text();
123
+ if (!res.ok) {
124
+ throw new ApiError(res.status, text);
125
+ }
126
+ let brief;
127
+ try {
128
+ brief = JSON.parse(text);
129
+ } catch {
130
+ throw new ApiError(res.status, text || "Invalid JSON from /api/brief");
131
+ }
132
+ const dur = res.headers.get("X-Duration-Ms");
133
+ const steps = res.headers.get("X-Steps-Completed");
134
+ const tools = res.headers.get("X-Tools-Used");
135
+ return {
136
+ brief,
137
+ durationMs: dur != null ? Number(dur) : null,
138
+ stepsCompleted: steps != null ? Number(steps) : null,
139
+ toolsUsed: tools ? tools.split(",").filter(Boolean) : []
140
+ };
141
+ }
109
142
  async patch(path, body) {
110
143
  this.log("PATCH", path);
111
144
  const res = await fetch(`${this.baseUrl}${path}`, {
@@ -234,6 +267,12 @@ function bold(text) {
234
267
  function currency(n) {
235
268
  return "$" + n.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
236
269
  }
270
+ function compactCurrency(n) {
271
+ if (!n || isNaN(n)) return "$0";
272
+ if (n >= 1e6) return `$${(n / 1e6).toFixed(1)}M`;
273
+ if (n >= 1e3) return `$${(n / 1e3).toFixed(1)}K`;
274
+ return `$${n.toFixed(0)}`;
275
+ }
237
276
  function percent(n) {
238
277
  return (n * 100).toFixed(1) + "%";
239
278
  }
@@ -342,6 +381,7 @@ async function parseStream(body, callbacks = {}) {
342
381
  const toolCalls = [];
343
382
  const activeToolCalls = /* @__PURE__ */ new Map();
344
383
  let marketBrief = null;
384
+ let feedResult = null;
345
385
  while (true) {
346
386
  const { done, value } = await reader.read();
347
387
  if (!done) {
@@ -405,6 +445,9 @@ async function parseStream(body, callbacks = {}) {
405
445
  if (active.name === "buildMarketBrief" && isMarketBrief(msg.output)) {
406
446
  marketBrief = msg.output;
407
447
  }
448
+ if (active.name === "getFeed" && isFeedResult(msg.output)) {
449
+ feedResult = msg.output;
450
+ }
408
451
  activeToolCalls.delete(id);
409
452
  }
410
453
  break;
@@ -416,11 +459,14 @@ async function parseStream(body, callbacks = {}) {
416
459
  }
417
460
  if (done) break;
418
461
  }
419
- return { assistantText, toolCalls, marketBrief };
462
+ return { assistantText, toolCalls, marketBrief, feedResult };
420
463
  }
421
464
  function isMarketBrief(val) {
422
465
  return val !== null && typeof val === "object" && "title" in val && "markets" in val;
423
466
  }
467
+ function isFeedResult(val) {
468
+ return val !== null && typeof val === "object" && "markets" in val && "sortedBy" in val;
469
+ }
424
470
  async function parseNdjsonStream(body, callbacks = {}) {
425
471
  const decoder = new TextDecoder();
426
472
  const reader = body.getReader();
@@ -469,7 +515,7 @@ async function parseNdjsonStream(body, callbacks = {}) {
469
515
 
470
516
  // src/commands/brief.ts
471
517
  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) => {
518
+ 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).action(async (query, cmdOpts) => {
473
519
  const globalOpts = program2.opts();
474
520
  const client = new ApiClient(globalOpts);
475
521
  requireAuth(client);
@@ -479,13 +525,9 @@ function registerBriefCommands(program2) {
479
525
  ...cmdOpts.location && { location: cmdOpts.location },
480
526
  ...cmdOpts.timeHorizon && { timeHorizon: cmdOpts.timeHorizon },
481
527
  ...filters && { filters },
482
- stream: cmdOpts.stream !== false
528
+ stream: true
483
529
  };
484
- if (body.stream) {
485
- await runStreaming(client, body, globalOpts);
486
- } else {
487
- await runBlocking(client, body, globalOpts);
488
- }
530
+ await runStreaming(client, body, globalOpts);
489
531
  });
490
532
  }
491
533
  function buildFilters(opts) {
@@ -522,17 +564,6 @@ async function runStreaming(client, body, globalOpts) {
522
564
  `));
523
565
  displayBrief(result.brief, globalOpts);
524
566
  }
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
567
  function displayBrief(brief, globalOpts) {
537
568
  if (globalOpts.json) {
538
569
  json(brief);
@@ -573,53 +604,6 @@ function requireAuth(client) {
573
604
  }
574
605
  }
575
606
 
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
607
  // src/commands/profile.ts
624
608
  function registerProfileCommand(program2) {
625
609
  program2.command("profile").description("Show your user profile").action(async () => {
@@ -648,7 +632,7 @@ function requireAuth2(client) {
648
632
 
649
633
  // src/commands/research.ts
650
634
  import readline2 from "readline/promises";
651
- import chalk4 from "chalk";
635
+ import chalk3 from "chalk";
652
636
  function registerResearchCommands(program2) {
653
637
  const research = program2.command("research").description("AI-powered market research");
654
638
  research.command("start", { isDefault: true }).description("Start an interactive market research session").action(async () => {
@@ -658,7 +642,7 @@ function registerResearchCommands(program2) {
658
642
  const { id } = await client.post("/api/assessments");
659
643
  heading("Market Research");
660
644
  process.stderr.write(
661
- chalk4.dim(" Describe a topic or thesis to explore. Type /quit to exit.\n\n")
645
+ chalk3.dim(" Describe a topic or thesis to explore. Type /quit to exit.\n\n")
662
646
  );
663
647
  let msgCounter = 0;
664
648
  const uiMsg = (role, content) => ({
@@ -668,14 +652,16 @@ function registerResearchCommands(program2) {
668
652
  parts: [{ type: "text", text: content }]
669
653
  });
670
654
  const messages = [];
655
+ let firstMessageTs = null;
671
656
  const rl = readline2.createInterface({ input: process.stdin, output: process.stderr });
672
657
  try {
673
658
  while (true) {
674
- const userInput = await rl.question(chalk4.cyan("You: "));
659
+ const userInput = await rl.question(chalk3.cyan("You: "));
675
660
  if (!userInput.trim()) continue;
676
661
  if (userInput.trim() === "/quit") break;
662
+ if (firstMessageTs === null) firstMessageTs = Date.now();
677
663
  messages.push(uiMsg("user", userInput));
678
- process.stderr.write(chalk4.dim("\nAssistant: "));
664
+ process.stderr.write(chalk3.dim("\nAssistant: "));
679
665
  try {
680
666
  const body = await client.stream("/api/chat", {
681
667
  messages,
@@ -684,13 +670,13 @@ function registerResearchCommands(program2) {
684
670
  const result = await parseStream(body, {
685
671
  onText: (text) => process.stderr.write(text),
686
672
  onToolCall: (name) => {
687
- process.stderr.write(chalk4.dim(`
673
+ process.stderr.write(chalk3.dim(`
688
674
  [tool: ${name}]
689
675
  `));
690
676
  },
691
677
  onToolResult: (name, toolResult) => {
692
678
  if (globalOpts.verbose) {
693
- process.stderr.write(chalk4.dim(` [result: ${name}] ${JSON.stringify(toolResult).slice(0, 200)}
679
+ process.stderr.write(chalk3.dim(` [result: ${name}] ${JSON.stringify(toolResult).slice(0, 200)}
694
680
  `));
695
681
  }
696
682
  }
@@ -699,6 +685,16 @@ function registerResearchCommands(program2) {
699
685
  if (result.assistantText) {
700
686
  messages.push(uiMsg("assistant", result.assistantText));
701
687
  }
688
+ try {
689
+ await persistAssessment(client, id, messages, result.marketBrief, firstMessageTs);
690
+ } catch (persistErr) {
691
+ warn(
692
+ `Could not save session: ${persistErr instanceof Error ? persistErr.message : String(persistErr)}`
693
+ );
694
+ }
695
+ if (result.feedResult) {
696
+ displayFeedResult(result.feedResult, globalOpts);
697
+ }
702
698
  if (result.marketBrief) {
703
699
  displayMarketBrief(result.marketBrief, globalOpts);
704
700
  break;
@@ -712,23 +708,34 @@ function registerResearchCommands(program2) {
712
708
  rl.close();
713
709
  }
714
710
  });
715
- research.command("run <query>").description("Run research on a topic and return the final brief as JSON").action(async (query) => {
711
+ research.command("run <query>").description("Run research on a topic and return the final Market Brief as JSON (via /api/brief)").action(async (query) => {
716
712
  const globalOpts = program2.opts();
717
713
  const client = new ApiClient(globalOpts);
718
714
  requireAuth3(client);
719
- process.stderr.write(chalk4.dim(` Researching "${truncate(query, 60)}"...
715
+ process.stderr.write(chalk3.dim(` Researching "${truncate(query, 60)}"...
720
716
  `));
721
717
  const startTime = Date.now();
722
- const result = await client.post("/api/research", { query });
718
+ const { brief, durationMs, stepsCompleted, toolsUsed } = await client.postBriefSync(query);
723
719
  const elapsed = ((Date.now() - startTime) / 1e3).toFixed(1);
724
- process.stderr.write(chalk4.dim(` Done (${elapsed}s)
720
+ process.stderr.write(chalk3.dim(` Done (${elapsed}s)
725
721
 
726
722
  `));
727
- if (result.brief) {
728
- json(result.brief);
723
+ const looksLikeBrief = brief && typeof brief === "object" && Array.isArray(brief.markets) && typeof brief.title === "string";
724
+ if (looksLikeBrief) {
725
+ json(brief);
729
726
  } else {
730
- process.stderr.write(chalk4.yellow("No market brief was produced.\n"));
731
- json(result);
727
+ process.stderr.write(chalk3.yellow("No market brief was produced.\n"));
728
+ json({
729
+ brief: null,
730
+ text: null,
731
+ metadata: {
732
+ model: "",
733
+ stepsUsed: stepsCompleted ?? 0,
734
+ toolsUsed,
735
+ durationMs: durationMs ?? Date.now() - startTime
736
+ },
737
+ raw: brief
738
+ });
732
739
  }
733
740
  });
734
741
  research.command("list").description("List past research sessions").option("-s, --status <status>", "Filter by status").action(async (cmdOpts) => {
@@ -788,28 +795,117 @@ function requireAuth3(client) {
788
795
  process.exit(1);
789
796
  }
790
797
  }
798
+ function buildAssessmentPatch(messages, marketBrief, firstMessageTs) {
799
+ const patch = { messages };
800
+ const meta = {
801
+ timeToBriefMs: null,
802
+ searchQueries: [],
803
+ searchResultCounts: [],
804
+ coverageHit: false,
805
+ completedAt: null
806
+ };
807
+ if (marketBrief && typeof marketBrief === "object" && Array.isArray(marketBrief.markets)) {
808
+ const markets = marketBrief.markets;
809
+ patch.market_brief = marketBrief;
810
+ patch.status = "completed";
811
+ meta.timeToBriefMs = firstMessageTs != null ? Date.now() - firstMessageTs : null;
812
+ meta.coverageHit = markets.length > 0;
813
+ meta.completedAt = (/* @__PURE__ */ new Date()).toISOString();
814
+ }
815
+ patch.metadata = meta;
816
+ return patch;
817
+ }
818
+ async function persistAssessment(client, assessmentId, messages, marketBrief, firstMessageTs) {
819
+ await client.patch(`/api/assessments/${assessmentId}`, buildAssessmentPatch(messages, marketBrief, firstMessageTs));
820
+ }
791
821
  function formatStatus(status) {
792
822
  switch (status) {
793
823
  case "completed":
794
- return chalk4.green(status);
824
+ return chalk3.green(status);
795
825
  case "in_progress":
796
- return chalk4.yellow(status);
826
+ return chalk3.yellow(status);
797
827
  case "abandoned":
798
- return chalk4.red(status);
828
+ return chalk3.red(status);
799
829
  default:
800
830
  return status;
801
831
  }
802
832
  }
833
+ var SORT_LABELS = {
834
+ score: "attention score",
835
+ volume: "24h volume",
836
+ liquidity: "liquidity",
837
+ movement: "price movement",
838
+ spread: "spread tightness",
839
+ recency: "recency",
840
+ extremity: "uncertainty",
841
+ rewards: "rewards"
842
+ };
843
+ function displayFeedResult(feed, globalOpts) {
844
+ if (globalOpts.json) {
845
+ json(feed);
846
+ return;
847
+ }
848
+ const sortLabel = SORT_LABELS[feed.sortedBy] ?? feed.sortedBy;
849
+ heading(`Market Feed \u2014 ${feed.marketsReturned} markets by ${sortLabel}`);
850
+ process.stdout.write(
851
+ chalk3.dim(` ${feed.totalScanned.toLocaleString()} scanned \xB7 ${feed.totalAfterFilter.toLocaleString()} after filters
852
+
853
+ `)
854
+ );
855
+ if (feed.markets.length === 0) {
856
+ warn("No markets matched the criteria.");
857
+ return;
858
+ }
859
+ const rows = feed.markets.map((m) => {
860
+ const prob = percent(m.yesPrice);
861
+ const change = m.oneDayPriceChange;
862
+ const changeStr = change > 0 ? chalk3.green(`+${(change * 100).toFixed(1)}%`) : change < 0 ? chalk3.red(`${(change * 100).toFixed(1)}%`) : chalk3.dim("0.0%");
863
+ return [
864
+ String(m.rank),
865
+ truncate(m.question, 42),
866
+ prob,
867
+ String(Math.round(m.score)),
868
+ compactCurrency(m.volume24h),
869
+ compactCurrency(m.liquidity),
870
+ changeStr
871
+ ];
872
+ });
873
+ table(rows, ["#", "Market", "Prob", "Score", "24h Vol", "Liq", "Chg"]);
874
+ process.stdout.write("\n");
875
+ for (const m of feed.markets.slice(0, 5)) {
876
+ const url = m.polymarketUrl;
877
+ process.stdout.write(" " + chalk3.dim("\u25B8 ") + truncate(m.question, 55) + "\n");
878
+ process.stdout.write(" " + chalk3.dim("Score: ") + scoreBar(m.score) + " ");
879
+ process.stdout.write(chalk3.dim("Spread: ") + m.spread.toFixed(3) + " ");
880
+ if (m.rewardsDailyRate > 0) {
881
+ process.stdout.write(chalk3.dim("Rewards: ") + `$${m.rewardsDailyRate.toFixed(2)}/day`);
882
+ }
883
+ process.stdout.write("\n");
884
+ process.stdout.write(" " + chalk3.dim("Polymarket: ") + url + "\n");
885
+ }
886
+ if (feed.markets.length > 5) {
887
+ process.stdout.write(chalk3.dim(`
888
+ \u2026 and ${feed.markets.length - 5} more
889
+ `));
890
+ }
891
+ }
892
+ function scoreBar(score) {
893
+ const width = 15;
894
+ const filled = Math.round(score / 100 * width);
895
+ const empty = width - filled;
896
+ const color = score >= 70 ? chalk3.green : score >= 45 ? chalk3.yellow : chalk3.dim;
897
+ return color("\u2588".repeat(filled)) + chalk3.dim("\u2591".repeat(empty)) + ` ${Math.round(score)}`;
898
+ }
803
899
  function displayMarketBrief(brief, globalOpts) {
804
900
  if (globalOpts.json) {
805
901
  json(brief);
806
902
  return;
807
903
  }
808
904
  heading("Market Brief");
809
- process.stdout.write(" " + chalk4.bold(brief.title) + "\n\n");
810
- process.stdout.write(" " + chalk4.italic(brief.thesis) + "\n");
905
+ process.stdout.write(" " + chalk3.bold(brief.title) + "\n\n");
906
+ process.stdout.write(" " + chalk3.italic(brief.thesis) + "\n");
811
907
  if (brief.markets.length > 0) {
812
- process.stdout.write("\n" + chalk4.bold(" Markets") + "\n\n");
908
+ process.stdout.write("\n" + chalk3.bold(" Markets") + "\n\n");
813
909
  const rows = brief.markets.map((m) => {
814
910
  const prob = percent(m.yesPrice);
815
911
  const signals = m.signals.length > 0 ? m.signals.join(", ") : "\u2014";
@@ -819,26 +915,25 @@ function displayMarketBrief(brief, globalOpts) {
819
915
  table(rows, ["Market", "Prob", "Signals", "Liq"]);
820
916
  process.stdout.write("\n");
821
917
  for (const m of brief.markets) {
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");
918
+ process.stdout.write(" " + chalk3.dim("\u25B8 ") + truncate(m.question, 50) + "\n");
919
+ process.stdout.write(" " + chalk3.dim("Causal link: ") + m.causalLink + "\n");
920
+ process.stdout.write(" " + chalk3.dim("Polymarket: ") + m.polymarketUrl + "\n");
825
921
  }
826
922
  }
827
923
  if (brief.gaps.length > 0) {
828
- process.stdout.write("\n" + chalk4.bold(" Coverage Gaps") + "\n\n");
924
+ process.stdout.write("\n" + chalk3.bold(" Coverage Gaps") + "\n\n");
829
925
  for (const gap of brief.gaps) {
830
- process.stdout.write(" " + chalk4.yellow("\u25B8") + " " + gap + "\n");
926
+ process.stdout.write(" " + chalk3.yellow("\u25B8") + " " + gap + "\n");
831
927
  }
832
928
  }
833
- process.stdout.write("\n " + chalk4.dim(`${brief.marketCount} markets \xB7 ${brief.gaps.length} coverage gaps`) + "\n");
929
+ process.stdout.write("\n " + chalk3.dim(`${brief.marketCount} markets \xB7 ${brief.gaps.length} coverage gaps`) + "\n");
834
930
  }
835
931
 
836
932
  // src/index.ts
837
933
  var program = new Command();
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");
934
+ program.name("hl").description("Hedge Layer CLI \u2014 prediction market intelligence from the terminal").version("1.3.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");
839
935
  registerAuthCommands(program);
840
936
  registerBriefCommands(program);
841
- registerMarketCommands(program);
842
937
  registerProfileCommand(program);
843
938
  registerResearchCommands(program);
844
939
  program.hook("preAction", (_thisCommand, actionCommand) => {
@@ -1 +1 @@
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"]}
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/profile.ts","../src/commands/research.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { registerAuthCommands } from \"./commands/auth.js\";\nimport { registerBriefCommands } from \"./commands/brief.js\";\n\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);\n\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 /**\n * POST /api/brief with stream: false — returns the Market Brief JSON body\n * plus optional telemetry from response headers.\n */\n async postBriefSync(query: string): Promise<{\n brief: Record<string, unknown>;\n durationMs: number | null;\n stepsCompleted: number | null;\n toolsUsed: string[];\n }> {\n const path = \"/api/brief\";\n this.log(\"POST\", path);\n const res = await fetch(`${this.baseUrl}${path}`, {\n method: \"POST\",\n headers: this.headers(),\n body: JSON.stringify({ query, stream: false }),\n });\n this.log(\"POST\", path, res.status);\n\n const text = await res.text();\n if (!res.ok) {\n throw new ApiError(res.status, text);\n }\n\n let brief: Record<string, unknown>;\n try {\n brief = JSON.parse(text) as Record<string, unknown>;\n } catch {\n throw new ApiError(res.status, text || \"Invalid JSON from /api/brief\");\n }\n\n const dur = res.headers.get(\"X-Duration-Ms\");\n const steps = res.headers.get(\"X-Steps-Completed\");\n const tools = res.headers.get(\"X-Tools-Used\");\n\n return {\n brief,\n durationMs: dur != null ? Number(dur) : null,\n stepsCompleted: steps != null ? Number(steps) : null,\n toolsUsed: tools ? tools.split(\",\").filter(Boolean) : [],\n };\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 compactCurrency(n: number): string {\n if (!n || isNaN(n)) return \"$0\";\n if (n >= 1_000_000) return `$${(n / 1_000_000).toFixed(1)}M`;\n if (n >= 1_000) return `$${(n / 1_000).toFixed(1)}K`;\n return `$${n.toFixed(0)}`;\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 .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: true,\n };\n\n await runStreaming(client, body, globalOpts);\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}\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// 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 feedResult: 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 let feedResult: 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 if (active.name === \"getFeed\" && isFeedResult(msg.output)) {\n feedResult = 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, feedResult };\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\nfunction isFeedResult(val: unknown): boolean {\n return (\n val !== null &&\n typeof val === \"object\" &&\n \"markets\" in (val as Record<string, unknown>) &&\n \"sortedBy\" 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 { 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, FeedResult, FeedResultMarket, 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 let firstMessageTs: number | null = null;\n const rl = readline.createInterface({ input: process.stdin, output: process.stderr });\n\n try {\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 if (firstMessageTs === null) firstMessageTs = Date.now();\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 try {\n await persistAssessment(client, id, messages, result.marketBrief, firstMessageTs);\n } catch (persistErr) {\n out.warn(\n `Could not save session: ${persistErr instanceof Error ? persistErr.message : String(persistErr)}`,\n );\n }\n\n if (result.feedResult) {\n displayFeedResult(result.feedResult as unknown as FeedResult, globalOpts);\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 Market Brief as JSON (via /api/brief)\")\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 { brief, durationMs, stepsCompleted, toolsUsed } = await client.postBriefSync(query);\n\n const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);\n process.stderr.write(chalk.dim(` Done (${elapsed}s)\\n\\n`));\n\n const looksLikeBrief =\n brief &&\n typeof brief === \"object\" &&\n Array.isArray((brief as { markets?: unknown }).markets) &&\n typeof (brief as { title?: unknown }).title === \"string\";\n\n if (looksLikeBrief) {\n out.json(brief as unknown as MarketBrief);\n } else {\n process.stderr.write(chalk.yellow(\"No market brief was produced.\\n\"));\n out.json({\n brief: null,\n text: null,\n metadata: {\n model: \"\",\n stepsUsed: stepsCompleted ?? 0,\n toolsUsed,\n durationMs: durationMs ?? Date.now() - startTime,\n },\n raw: brief,\n });\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\n/** Mirrors web ChatInterface assessment PATCH (simplified metadata without tool-part extraction). */\nfunction buildAssessmentPatch(\n messages: unknown[],\n marketBrief: Record<string, unknown> | null,\n firstMessageTs: number | null,\n): Record<string, unknown> {\n const patch: Record<string, unknown> = { messages };\n const meta: Record<string, unknown> = {\n timeToBriefMs: null,\n searchQueries: [],\n searchResultCounts: [],\n coverageHit: false,\n completedAt: null,\n };\n\n if (\n marketBrief &&\n typeof marketBrief === \"object\" &&\n Array.isArray((marketBrief as { markets?: unknown }).markets)\n ) {\n const markets = (marketBrief as { markets: unknown[] }).markets;\n patch.market_brief = marketBrief;\n patch.status = \"completed\";\n meta.timeToBriefMs = firstMessageTs != null ? Date.now() - firstMessageTs : null;\n meta.coverageHit = markets.length > 0;\n meta.completedAt = new Date().toISOString();\n }\n\n patch.metadata = meta;\n return patch;\n}\n\nasync function persistAssessment(\n client: ApiClient,\n assessmentId: string,\n messages: unknown[],\n marketBrief: Record<string, unknown> | null,\n firstMessageTs: number | null,\n): Promise<void> {\n await client.patch(`/api/assessments/${assessmentId}`, buildAssessmentPatch(messages, marketBrief, firstMessageTs));\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\nconst SORT_LABELS: Record<string, string> = {\n score: \"attention score\",\n volume: \"24h volume\",\n liquidity: \"liquidity\",\n movement: \"price movement\",\n spread: \"spread tightness\",\n recency: \"recency\",\n extremity: \"uncertainty\",\n rewards: \"rewards\",\n};\n\nfunction displayFeedResult(feed: FeedResult, globalOpts: GlobalOptions): void {\n if (globalOpts.json) {\n out.json(feed);\n return;\n }\n\n const sortLabel = SORT_LABELS[feed.sortedBy] ?? feed.sortedBy;\n out.heading(`Market Feed — ${feed.marketsReturned} markets by ${sortLabel}`);\n process.stdout.write(\n chalk.dim(` ${feed.totalScanned.toLocaleString()} scanned · ${feed.totalAfterFilter.toLocaleString()} after filters\\n\\n`),\n );\n\n if (feed.markets.length === 0) {\n out.warn(\"No markets matched the criteria.\");\n return;\n }\n\n const rows = feed.markets.map((m: FeedResultMarket) => {\n const prob = out.percent(m.yesPrice);\n const change = m.oneDayPriceChange;\n const changeStr = change > 0\n ? chalk.green(`+${(change * 100).toFixed(1)}%`)\n : change < 0\n ? chalk.red(`${(change * 100).toFixed(1)}%`)\n : chalk.dim(\"0.0%\");\n return [\n String(m.rank),\n out.truncate(m.question, 42),\n prob,\n String(Math.round(m.score)),\n out.compactCurrency(m.volume24h),\n out.compactCurrency(m.liquidity),\n changeStr,\n ];\n });\n\n out.table(rows, [\"#\", \"Market\", \"Prob\", \"Score\", \"24h Vol\", \"Liq\", \"Chg\"]);\n\n process.stdout.write(\"\\n\");\n for (const m of feed.markets.slice(0, 5)) {\n const url = m.polymarketUrl;\n process.stdout.write(\" \" + chalk.dim(\"▸ \") + out.truncate(m.question, 55) + \"\\n\");\n process.stdout.write(\" \" + chalk.dim(\"Score: \") + scoreBar(m.score) + \" \");\n process.stdout.write(chalk.dim(\"Spread: \") + m.spread.toFixed(3) + \" \");\n if (m.rewardsDailyRate > 0) {\n process.stdout.write(chalk.dim(\"Rewards: \") + `$${m.rewardsDailyRate.toFixed(2)}/day`);\n }\n process.stdout.write(\"\\n\");\n process.stdout.write(\" \" + chalk.dim(\"Polymarket: \") + url + \"\\n\");\n }\n\n if (feed.markets.length > 5) {\n process.stdout.write(chalk.dim(`\\n … and ${feed.markets.length - 5} more\\n`));\n }\n}\n\nfunction scoreBar(score: number): string {\n const width = 15;\n const filled = Math.round((score / 100) * width);\n const empty = width - filled;\n const color = score >= 70 ? chalk.green : score >= 45 ? chalk.yellow : chalk.dim;\n return color(\"█\".repeat(filled)) + chalk.dim(\"░\".repeat(empty)) + ` ${Math.round(score)}`;\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","program","requireAuth","readline","chalk","program","requireAuth","chalk","readline"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hedge-layer/cli",
3
- "version": "1.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "CLI for Hedge Layer — prediction market intelligence from the terminal",
5
5
  "type": "module",
6
6
  "bin": {
@@ -42,6 +42,7 @@
42
42
  },
43
43
  "devDependencies": {
44
44
  "@eslint/js": "^10.0.1",
45
+ "@types/node": "^25.5.2",
45
46
  "eslint": "^10.0.3",
46
47
  "tsup": "^8.4.0",
47
48
  "typescript": "^5.7.0",