@alva-ai/toolkit 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -228,7 +228,8 @@ var ReleaseResource = class {
228
228
  display_name: params.display_name,
229
229
  description: params.description,
230
230
  feeds: params.feeds,
231
- trading_symbols: params.trading_symbols
231
+ trading_symbols: params.trading_symbols,
232
+ changelog: params.changelog
232
233
  }
233
234
  });
234
235
  }
@@ -390,10 +391,88 @@ var UserResource = class {
390
391
  }
391
392
  };
392
393
 
394
+ // src/resources/trading.ts
395
+ var TradingResource = class {
396
+ constructor(client) {
397
+ this.client = client;
398
+ }
399
+ client;
400
+ async accounts() {
401
+ this.client._requireAuth();
402
+ return this.client._request("GET", "/api/v1/trading/accounts");
403
+ }
404
+ async portfolio(accountId) {
405
+ this.client._requireAuth();
406
+ return this.client._request("GET", "/api/v1/trading/portfolio", {
407
+ query: { accountId }
408
+ });
409
+ }
410
+ async orders(params) {
411
+ this.client._requireAuth();
412
+ return this.client._request("GET", "/api/v1/trading/orders", {
413
+ query: {
414
+ accountId: params.accountId,
415
+ source: params.source,
416
+ since: params.since,
417
+ limit: params.limit
418
+ }
419
+ });
420
+ }
421
+ async subscriptions(accountId) {
422
+ this.client._requireAuth();
423
+ return this.client._request("GET", "/api/v1/trading/subscriptions", {
424
+ query: { accountId }
425
+ });
426
+ }
427
+ async equityHistory(params) {
428
+ this.client._requireAuth();
429
+ return this.client._request("GET", "/api/v1/trading/equity-history", {
430
+ query: {
431
+ accountId: params.accountId,
432
+ timeframe: params.timeframe,
433
+ sinceMs: params.sinceMs,
434
+ untilMs: params.untilMs
435
+ }
436
+ });
437
+ }
438
+ async riskRules() {
439
+ this.client._requireAuth();
440
+ return this.client._request(
441
+ "GET",
442
+ "/api/v1/trading/risk-rules"
443
+ );
444
+ }
445
+ async subscribe(params) {
446
+ this.client._requireAuth();
447
+ return this.client._request("POST", "/api/v1/trading/subscribe", {
448
+ body: params
449
+ });
450
+ }
451
+ async unsubscribe(subscriptionId) {
452
+ this.client._requireAuth();
453
+ return this.client._request("POST", "/api/v1/trading/unsubscribe", {
454
+ body: { subscriptionId }
455
+ });
456
+ }
457
+ async execute(params) {
458
+ this.client._requireAuth();
459
+ return this.client._request("POST", "/api/v1/trading/execute", {
460
+ body: params
461
+ });
462
+ }
463
+ async updateRiskRules(rules) {
464
+ this.client._requireAuth();
465
+ return this.client._request("PUT", "/api/v1/trading/risk-rules", {
466
+ body: rules
467
+ });
468
+ }
469
+ };
470
+
393
471
  // src/client.ts
394
472
  var DEFAULT_BASE_URL = "https://api-llm.prd.alva.ai";
395
473
  var AlvaClient = class {
396
474
  baseUrl;
475
+ token;
397
476
  apiKey;
398
477
  _fs;
399
478
  _run;
@@ -405,8 +484,10 @@ var AlvaClient = class {
405
484
  _remix;
406
485
  _screenshot;
407
486
  _user;
487
+ _trading;
408
488
  constructor(config) {
409
489
  this.baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;
490
+ this.token = config.token;
410
491
  this.apiKey = config.apiKey;
411
492
  }
412
493
  get fs() {
@@ -439,11 +520,14 @@ var AlvaClient = class {
439
520
  get user() {
440
521
  return this._user ??= new UserResource(this);
441
522
  }
523
+ get trading() {
524
+ return this._trading ??= new TradingResource(this);
525
+ }
442
526
  _requireAuth() {
443
- if (!this.apiKey) {
527
+ if (!this.token && !this.apiKey) {
444
528
  throw new AlvaError(
445
529
  "UNAUTHENTICATED",
446
- "API key is required for this operation. Pass apiKey in the constructor.",
530
+ "Authentication is required. Pass token or apiKey in the constructor.",
447
531
  401
448
532
  );
449
533
  }
@@ -463,7 +547,9 @@ var AlvaClient = class {
463
547
  }
464
548
  }
465
549
  const headers = {};
466
- if (this.apiKey) {
550
+ if (this.token) {
551
+ headers.Authorization = `${this.token}`;
552
+ } else if (this.apiKey) {
467
553
  headers["X-Alva-Api-Key"] = this.apiKey;
468
554
  }
469
555
  let fetchBody;
@@ -628,6 +714,24 @@ function loadConfig(deps) {
628
714
  import * as fs from "fs";
629
715
  import * as os from "os";
630
716
  import * as fsPromises from "fs/promises";
717
+ var CLI_VERSION = true ? "0.1.4" : "dev";
718
+ function isVersionOlderThan(a, b) {
719
+ const parse = (v) => {
720
+ if (!v) return null;
721
+ const parts = v.split(".").map(Number);
722
+ if (parts.some(isNaN)) return null;
723
+ while (parts.length < 3) parts.push(0);
724
+ return parts;
725
+ };
726
+ const pa = parse(a);
727
+ const pb = parse(b);
728
+ if (!pa || !pb) return false;
729
+ for (let i = 0; i < 3; i++) {
730
+ if (pa[i] < pb[i]) return true;
731
+ if (pa[i] > pb[i]) return false;
732
+ }
733
+ return false;
734
+ }
631
735
  var HELP_TEXT = `Usage: alva <command> [options]
632
736
 
633
737
  Commands:
@@ -642,12 +746,14 @@ Commands:
642
746
  sdk SDK documentation (doc, partitions, partition-summary)
643
747
  comments Playbook comments (create, pin, unpin)
644
748
  remix Save playbook remix lineage
749
+ trading Trading operations (accounts, portfolio, orders, subscriptions, equity-history, risk-rules, subscribe, unsubscribe, execute, update-risk-rules)
645
750
  screenshot Capture a web screenshot as PNG
646
751
 
647
752
  Global options:
648
753
  --api-key <key> API key (overrides env and config file)
649
754
  --base-url <url> API base URL (overrides env and config file)
650
755
  --profile <name> Named profile to use (default: "default")
756
+ -v, --version Show CLI version
651
757
  --help Show help (use 'alva <command> --help' for command details)
652
758
 
653
759
  Config resolution: --api-key flag > ALVA_API_KEY env > profile in ~/.config/alva/config.json
@@ -727,7 +833,8 @@ Common flags:
727
833
  --path <path> File or directory path (required for most subcommands)
728
834
  --recursive Enable recursive operation (readdir, remove)
729
835
  --no-recursive Disable recursive operation
730
- --mkdir-parents Create parent directories on write
836
+ --mkdir-parents Create parent directories on write (default for write)
837
+ --no-mkdir-parents Disable automatic parent directory creation on write
731
838
 
732
839
  Path conventions:
733
840
  ~/... Home-relative path (expands to /alva/home/<username>/...)
@@ -876,6 +983,7 @@ Playbook-draft flags:
876
983
  --name <name> URL-safe playbook name, unique per user (required)
877
984
  --display-name <name> Human-readable title, max 40 chars (required)
878
985
  --feeds <json> JSON array of {feed_id, feed_major?} (required)
986
+ --changelog <text> Release changelog (required)
879
987
  --description <text> Playbook description
880
988
  --trading-symbols <json> JSON array of tickers, e.g. '["BTC","ETH"]' (max 50)
881
989
 
@@ -894,7 +1002,7 @@ Display name conventions:
894
1002
  Examples:
895
1003
  alva release feed --name btc-ema --version 1.0.0 --cronjob-id 42
896
1004
  alva release feed --name nvda-insiders --version 1.0.0 --cronjob-id 43 --description "NVDA insider trading activity"
897
- alva release playbook-draft --name btc-dashboard --display-name "BTC Trend Dashboard" --feeds '[{"feed_id":100}]' --trading-symbols '["BTC"]'
1005
+ alva release playbook-draft --name btc-dashboard --display-name "BTC Trend Dashboard" --feeds '[{"feed_id":100}]' --changelog "Initial release" --trading-symbols '["BTC"]'
898
1006
  alva release playbook --name btc-dashboard --version v1.0.0 --feeds '[{"feed_id":100}]' --changelog "Initial release"`,
899
1007
  secrets: `Usage: alva secrets <subcommand> [options]
900
1008
 
@@ -1010,7 +1118,73 @@ Optional:
1010
1118
 
1011
1119
  Examples:
1012
1120
  alva screenshot --url /playbook/alice/btc-dashboard --out dashboard.png
1013
- alva screenshot --url /playbook/alice/btc-dashboard --out chart.png --selector ".chart-container"`
1121
+ alva screenshot --url /playbook/alice/btc-dashboard --out chart.png --selector ".chart-container"`,
1122
+ trading: `Usage: alva trading <subcommand> [options]
1123
+
1124
+ Manage trading accounts, portfolios, orders, subscriptions, and risk rules.
1125
+
1126
+ Subcommands:
1127
+ accounts List all trading accounts
1128
+ portfolio Get portfolio for an account
1129
+ orders List orders for an account
1130
+ subscriptions List subscriptions for an account
1131
+ equity-history Get equity history for an account
1132
+ risk-rules Show risk rules
1133
+ subscribe Subscribe an account to a source feed
1134
+ unsubscribe Unsubscribe by subscription ID
1135
+ execute Execute a signal on an account
1136
+ update-risk-rules Update risk rules
1137
+
1138
+ Portfolio/Orders/Subscriptions/Equity-history flags:
1139
+ --account-id <id> Trading account ID (required)
1140
+
1141
+ Orders optional flags:
1142
+ --limit <n> Max results
1143
+ --source <source> Filter by source
1144
+ --since <timestamp> Filter orders since timestamp
1145
+
1146
+ Equity-history optional flags:
1147
+ --timeframe <tf> Timeframe (e.g. "1d", "1h")
1148
+ --since-ms <ms> Start timestamp in ms
1149
+ --until-ms <ms> End timestamp in ms
1150
+
1151
+ Subscribe flags:
1152
+ --account-id <id> Account ID (required)
1153
+ --source-username <user> Source username (required)
1154
+ --source-feed <feed> Source feed (required)
1155
+ --playbook-id <id> Playbook ID (required)
1156
+ --playbook-version <ver> Playbook version (required)
1157
+ --execute-latest Execute latest signal on subscribe
1158
+
1159
+ Unsubscribe flags:
1160
+ --subscription-id <id> Subscription ID (required)
1161
+
1162
+ Execute flags:
1163
+ --account-id <id> Account ID (required)
1164
+ --signal <json> Signal JSON (required)
1165
+ --dry-run Dry run mode
1166
+ --source-username <user> Source username (optional)
1167
+ --source-feed <feed> Source feed (optional)
1168
+
1169
+ Update-risk-rules flags:
1170
+ --max-single-order-value <n> Max single order value (required)
1171
+ --max-single-order-enabled <bool> Max single order enabled (required)
1172
+ --max-daily-turnover-value <n> Max daily turnover value (required)
1173
+ --max-daily-turnover-enabled <bool> Max daily turnover enabled (required)
1174
+ --max-daily-orders-value <n> Max daily orders value (required)
1175
+ --max-daily-orders-enabled <bool> Max daily orders enabled (required)
1176
+
1177
+ Examples:
1178
+ alva trading accounts
1179
+ alva trading portfolio --account-id acc_123
1180
+ alva trading orders --account-id acc_123 --limit 10
1181
+ alva trading subscriptions --account-id acc_123
1182
+ alva trading equity-history --account-id acc_123 --timeframe 1d
1183
+ alva trading risk-rules
1184
+ alva trading subscribe --account-id acc_123 --source-username alice --source-feed btc-signals --playbook-id pb_1 --playbook-version v1.0.0
1185
+ alva trading unsubscribe --subscription-id sub_456
1186
+ alva trading execute --account-id acc_123 --signal '{"symbol":"BTC","side":"buy","qty":0.1}' --dry-run
1187
+ alva trading update-risk-rules --max-single-order-value 10000 --max-single-order-enabled true --max-daily-turnover-value 50000 --max-daily-turnover-enabled true --max-daily-orders-value 100 --max-daily-orders-enabled true`
1014
1188
  };
1015
1189
  async function handleConfigure(args, deps) {
1016
1190
  const flags = parseFlags(args.slice(1));
@@ -1048,7 +1222,9 @@ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
1048
1222
  "recursive",
1049
1223
  "mkdir-parents",
1050
1224
  "push-notify",
1051
- "help"
1225
+ "help",
1226
+ "execute-latest",
1227
+ "dry-run"
1052
1228
  ]);
1053
1229
  function parseFlags(argv) {
1054
1230
  const flags = {};
@@ -1115,13 +1291,20 @@ async function dispatch(client, args, meta) {
1115
1291
  }
1116
1292
  if (group === "whoami") {
1117
1293
  const user = await client.user.me();
1118
- return {
1119
- ...user,
1294
+ const record = user;
1295
+ const version = meta?.cliVersion ?? CLI_VERSION;
1296
+ const result = {
1297
+ ...record,
1120
1298
  _meta: {
1121
1299
  profile: meta?.profile ?? "default",
1122
1300
  endpoint: meta?.baseUrl ?? client.baseUrl
1123
1301
  }
1124
1302
  };
1303
+ const minVersion = record.toolkit_min_version;
1304
+ if (typeof minVersion === "string" && version && version !== "dev" && isVersionOlderThan(version, minVersion)) {
1305
+ result._warning = `Warning: your toolkit version (${version}) is older than the minimum recommended version (${minVersion}). Please upgrade: npm install -g @alva-ai/toolkit`;
1306
+ }
1307
+ return result;
1125
1308
  }
1126
1309
  const subcommand = args[1];
1127
1310
  const flags = parseFlags(
@@ -1153,13 +1336,13 @@ async function dispatch(client, args, meta) {
1153
1336
  return client.fs.rawWrite({
1154
1337
  path: requireFlag(flags, "path", "fs write"),
1155
1338
  body: fileData,
1156
- mkdir_parents: boolFlag(flags["mkdir-parents"])
1339
+ mkdir_parents: boolFlag(flags["mkdir-parents"]) ?? true
1157
1340
  });
1158
1341
  }
1159
1342
  return client.fs.write({
1160
1343
  path: requireFlag(flags, "path", "fs write"),
1161
1344
  data: requireFlag(flags, "data", "fs write"),
1162
- mkdir_parents: boolFlag(flags["mkdir-parents"])
1345
+ mkdir_parents: boolFlag(flags["mkdir-parents"]) ?? true
1163
1346
  });
1164
1347
  case "stat":
1165
1348
  return client.fs.stat({
@@ -1293,7 +1476,12 @@ async function dispatch(client, args, meta) {
1293
1476
  feeds: jsonParse(
1294
1477
  requireFlag(flags, "feeds", "release playbook-draft")
1295
1478
  ),
1296
- trading_symbols: flags["trading-symbols"] ? jsonParse(flags["trading-symbols"]) : void 0
1479
+ trading_symbols: flags["trading-symbols"] ? jsonParse(flags["trading-symbols"]) : void 0,
1480
+ changelog: requireFlag(
1481
+ flags,
1482
+ "changelog",
1483
+ "release playbook-draft"
1484
+ )
1297
1485
  });
1298
1486
  case "playbook":
1299
1487
  return client.release.playbook({
@@ -1397,6 +1585,111 @@ async function dispatch(client, args, meta) {
1397
1585
  fs.writeFileSync(outFile, buf);
1398
1586
  return { written: outFile, bytes: buf.length };
1399
1587
  }
1588
+ case "trading": {
1589
+ if (!subcommand) throw new Error("Missing subcommand for trading");
1590
+ switch (subcommand) {
1591
+ case "accounts":
1592
+ return client.trading.accounts();
1593
+ case "portfolio":
1594
+ return client.trading.portfolio(
1595
+ requireFlag(flags, "account-id", "trading portfolio")
1596
+ );
1597
+ case "orders":
1598
+ return client.trading.orders({
1599
+ accountId: requireFlag(flags, "account-id", "trading orders"),
1600
+ source: flags["source"],
1601
+ since: num(flags["since"]),
1602
+ limit: num(flags["limit"])
1603
+ });
1604
+ case "subscriptions":
1605
+ return client.trading.subscriptions(
1606
+ requireFlag(flags, "account-id", "trading subscriptions")
1607
+ );
1608
+ case "equity-history":
1609
+ return client.trading.equityHistory({
1610
+ accountId: requireFlag(
1611
+ flags,
1612
+ "account-id",
1613
+ "trading equity-history"
1614
+ ),
1615
+ timeframe: flags["timeframe"],
1616
+ sinceMs: num(flags["since-ms"]),
1617
+ untilMs: num(flags["until-ms"])
1618
+ });
1619
+ case "risk-rules":
1620
+ return client.trading.riskRules();
1621
+ case "subscribe":
1622
+ return client.trading.subscribe({
1623
+ accountId: requireFlag(flags, "account-id", "trading subscribe"),
1624
+ sourceUsername: requireFlag(
1625
+ flags,
1626
+ "source-username",
1627
+ "trading subscribe"
1628
+ ),
1629
+ sourceFeed: requireFlag(flags, "source-feed", "trading subscribe"),
1630
+ playbookId: requireFlag(flags, "playbook-id", "trading subscribe"),
1631
+ playbookVersion: requireFlag(
1632
+ flags,
1633
+ "playbook-version",
1634
+ "trading subscribe"
1635
+ ),
1636
+ executeLatest: boolFlag(flags["execute-latest"])
1637
+ });
1638
+ case "unsubscribe":
1639
+ return client.trading.unsubscribe(
1640
+ requireFlag(flags, "subscription-id", "trading unsubscribe")
1641
+ );
1642
+ case "execute":
1643
+ return client.trading.execute({
1644
+ accountId: requireFlag(flags, "account-id", "trading execute"),
1645
+ signalJson: requireFlag(flags, "signal", "trading execute"),
1646
+ dryRun: boolFlag(flags["dry-run"]) ?? false,
1647
+ sourceUsername: flags["source-username"],
1648
+ sourceFeed: flags["source-feed"]
1649
+ });
1650
+ case "update-risk-rules":
1651
+ return client.trading.updateRiskRules({
1652
+ maxSingleOrder: {
1653
+ value: requireNumericFlag(
1654
+ flags,
1655
+ "max-single-order-value",
1656
+ "trading update-risk-rules"
1657
+ ),
1658
+ enabled: requireFlag(
1659
+ flags,
1660
+ "max-single-order-enabled",
1661
+ "trading update-risk-rules"
1662
+ ) === "true"
1663
+ },
1664
+ maxDailyTurnover: {
1665
+ value: requireNumericFlag(
1666
+ flags,
1667
+ "max-daily-turnover-value",
1668
+ "trading update-risk-rules"
1669
+ ),
1670
+ enabled: requireFlag(
1671
+ flags,
1672
+ "max-daily-turnover-enabled",
1673
+ "trading update-risk-rules"
1674
+ ) === "true"
1675
+ },
1676
+ maxDailyOrders: {
1677
+ value: requireNumericFlag(
1678
+ flags,
1679
+ "max-daily-orders-value",
1680
+ "trading update-risk-rules"
1681
+ ),
1682
+ enabled: requireFlag(
1683
+ flags,
1684
+ "max-daily-orders-enabled",
1685
+ "trading update-risk-rules"
1686
+ ) === "true"
1687
+ }
1688
+ });
1689
+ default:
1690
+ throw new Error(`Unknown subcommand: trading ${subcommand}`);
1691
+ }
1692
+ }
1400
1693
  default:
1401
1694
  throw new Error(
1402
1695
  `Unknown command: '${group}'. Run 'alva --help' to see available commands.`
@@ -1406,6 +1699,11 @@ async function dispatch(client, args, meta) {
1406
1699
  async function main() {
1407
1700
  try {
1408
1701
  const rawArgs = process.argv.slice(2);
1702
+ if (rawArgs[0] === "-v" || rawArgs[0] === "--version") {
1703
+ process.stdout.write(`alva version ${CLI_VERSION}
1704
+ `);
1705
+ return;
1706
+ }
1409
1707
  if (rawArgs[0] === "configure") {
1410
1708
  if (rawArgs[1] === "--help" || rawArgs[1] === "-h") {
1411
1709
  process.stdout.write(COMMAND_HELP["configure"] + "\n");
@@ -1439,8 +1737,15 @@ async function main() {
1439
1737
  }
1440
1738
  const result = await dispatch(client, cleanArgs, {
1441
1739
  profile: config.profile,
1442
- baseUrl: config.baseUrl
1740
+ baseUrl: config.baseUrl,
1741
+ cliVersion: CLI_VERSION
1443
1742
  });
1743
+ if (result && typeof result === "object" && "_warning" in result) {
1744
+ process.stderr.write(
1745
+ result._warning + "\n"
1746
+ );
1747
+ delete result._warning;
1748
+ }
1444
1749
  if (result && typeof result === "object" && "_help" in result) {
1445
1750
  const helpResult = result;
1446
1751
  process.stdout.write(helpResult.text + "\n");
@@ -1467,7 +1772,9 @@ if (isDirectRun) {
1467
1772
  main();
1468
1773
  }
1469
1774
  export {
1775
+ CLI_VERSION,
1470
1776
  dispatch,
1471
- handleConfigure
1777
+ handleConfigure,
1778
+ isVersionOlderThan
1472
1779
  };
1473
1780
  //# sourceMappingURL=cli.js.map