@alva-ai/toolkit 0.7.0-beta.0 → 0.8.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/dist/cli.js CHANGED
@@ -285,7 +285,8 @@ var ReleaseResource = class {
285
285
  description: params.description,
286
286
  feeds: params.feeds,
287
287
  trading_symbols: params.trading_symbols,
288
- template_id: params.template_id
288
+ skill_id: params.skill_id,
289
+ tags: params.tags
289
290
  }
290
291
  });
291
292
  }
@@ -303,6 +304,32 @@ var ReleaseResource = class {
303
304
  }
304
305
  };
305
306
 
307
+ // src/resources/feed.ts
308
+ var FeedResource = class {
309
+ constructor(client) {
310
+ this.client = client;
311
+ }
312
+ client;
313
+ /**
314
+ * Soft-delete a feed and all its active majors. Cascades:
315
+ * - all active feed_majors are soft-deleted in the same transaction
316
+ * - associated producer cronjobs are removed best-effort (the cronjob
317
+ * scavenger reconciles any leftover rows on its next sweep)
318
+ *
319
+ * Auth: caller must own the feed (uid match), enforced by the backend.
320
+ */
321
+ async delete(params) {
322
+ this.client._requireAuth();
323
+ if (!Number.isInteger(params.id) || params.id <= 0) {
324
+ throw new Error("feed id must be a positive integer");
325
+ }
326
+ return this.client._request(
327
+ "DELETE",
328
+ `/api/v1/feed/${encodeURIComponent(String(params.id))}`
329
+ );
330
+ }
331
+ };
332
+
306
333
  // src/resources/secrets.ts
307
334
  var SecretsResource = class {
308
335
  constructor(client) {
@@ -1864,16 +1891,16 @@ var PushSubscriptionsResource = class {
1864
1891
  );
1865
1892
  }
1866
1893
  /**
1867
- * List the caller's personal push subscriptions across all targets
1868
- * (playbook + feed). Defaults to currently-active rows only; pass
1869
- * `include_history=true` to also return previously-unsubscribed rows.
1894
+ * List the caller's currently active personal push subscriptions.
1895
+ * Results are cursor-paginated.
1870
1896
  */
1871
1897
  async list(params = {}) {
1872
1898
  this.client._requireAuth();
1873
1899
  const query = {};
1874
- if (params.include_history !== void 0) {
1875
- query.include_history = String(params.include_history);
1900
+ if (params.first !== void 0 && params.first > 0) {
1901
+ query.first = String(params.first);
1876
1902
  }
1903
+ if (params.cursor) query.cursor = params.cursor;
1877
1904
  return this.client._request("GET", "/api/v1/me/push-subscriptions", {
1878
1905
  query
1879
1906
  });
@@ -1955,6 +1982,7 @@ var AlvaClient = class {
1955
1982
  _run;
1956
1983
  _deploy;
1957
1984
  _release;
1985
+ _feed;
1958
1986
  _secrets;
1959
1987
  _sdk;
1960
1988
  _dataSkills;
@@ -1986,6 +2014,9 @@ var AlvaClient = class {
1986
2014
  get release() {
1987
2015
  return this._release ??= new ReleaseResource(this);
1988
2016
  }
2017
+ get feed() {
2018
+ return this._feed ??= new FeedResource(this);
2019
+ }
1989
2020
  get secrets() {
1990
2021
  return this._secrets ??= new SecretsResource(this);
1991
2022
  }
@@ -2432,12 +2463,12 @@ function formatEndpointMetadataTable(endpoints) {
2432
2463
  const key = ["method", "path", "file", "tier", "access"][i];
2433
2464
  return Math.max(h.length, ...rows.map((r) => String(r[key]).length));
2434
2465
  });
2435
- const pad2 = (s, w) => s + " ".repeat(Math.max(0, w - s.length));
2466
+ const pad = (s, w) => s + " ".repeat(Math.max(0, w - s.length));
2436
2467
  const lines = [
2437
- headers.map((h, i) => pad2(h, widths[i])).join(" "),
2468
+ headers.map((h, i) => pad(h, widths[i])).join(" "),
2438
2469
  widths.map((w) => "-".repeat(w)).join(" "),
2439
2470
  ...rows.map(
2440
- (r) => [r.method, r.path, r.file, r.tier, r.access].map((v, i) => pad2(String(v), widths[i])).join(" ")
2471
+ (r) => [r.method, r.path, r.file, r.tier, r.access].map((v, i) => pad(String(v), widths[i])).join(" ")
2441
2472
  )
2442
2473
  ];
2443
2474
  return lines.join("\n");
@@ -2488,28 +2519,17 @@ function formatSkillEndpoint(doc) {
2488
2519
  }
2489
2520
 
2490
2521
  // src/cli/playbookSkillsFormat.ts
2491
- function pad(s, w) {
2492
- return s + " ".repeat(Math.max(0, w - s.length));
2493
- }
2494
2522
  function formatPlaybookSkillsList(result) {
2495
2523
  const skills = result.skills ?? [];
2496
2524
  if (skills.length === 0) return "No playbook skills found.\n";
2497
- const rows = skills.map((s) => ({
2498
- id: `${s.username}/${s.name}`,
2499
- description: s.description ?? "",
2500
- tags: (s.tags ?? []).join(","),
2501
- updated_at: s.updated_at ?? ""
2502
- }));
2503
- const headers = ["USERNAME/NAME", "DESCRIPTION", "TAGS", "UPDATED_AT"];
2504
- const keys = ["id", "description", "tags", "updated_at"];
2505
- const widths = headers.map(
2506
- (h, i) => Math.max(h.length, ...rows.map((r) => r[keys[i]].length))
2507
- );
2508
- const lines = [
2509
- headers.map((h, i) => pad(h, widths[i])).join(" "),
2510
- widths.map((w) => "-".repeat(w)).join(" "),
2511
- ...rows.map((r) => keys.map((k, i) => pad(r[k], widths[i])).join(" "))
2512
- ];
2525
+ const lines = [];
2526
+ for (const s of skills) {
2527
+ lines.push(`\u2022 ${s.username}/${s.name}`);
2528
+ if (s.description) lines.push(` ${s.description}`);
2529
+ const tags = (s.tags ?? []).join(", ");
2530
+ if (tags) lines.push(` tags: ${tags}`);
2531
+ if (s.updated_at) lines.push(` updated: ${s.updated_at}`);
2532
+ }
2513
2533
  return lines.join("\n") + "\n";
2514
2534
  }
2515
2535
  function formatPlaybookSkillsTags(result) {
@@ -2544,7 +2564,7 @@ function formatPlaybookSkillFile(file) {
2544
2564
  import * as fs from "fs";
2545
2565
  import * as os2 from "os";
2546
2566
  import * as fsPromises2 from "fs/promises";
2547
- var CLI_VERSION = true ? "0.7.0-beta.0" : "dev";
2567
+ var CLI_VERSION = true ? "0.8.0" : "dev";
2548
2568
  function isVersionOlderThan(a, b) {
2549
2569
  const parse = (v) => {
2550
2570
  if (!v) return null;
@@ -2572,11 +2592,13 @@ Commands:
2572
2592
  run Execute code in the Alva runtime
2573
2593
  deploy Cronjob management (create, list, get, update, delete, pause, resume, runs, run-logs)
2574
2594
  release Feed and playbook releases (feed, playbook-draft, playbook)
2595
+ feed Feed lifecycle management (delete)
2575
2596
  secrets Secret management (create, list, get, update, delete)
2576
2597
  sdk SDK documentation (doc, partitions, partition-summary)
2577
2598
  skillhub Playbook skills (list, tags, get, file)
2578
2599
  data-skills Data-skill documentation from the Arrays backend (list, summary, endpoint)
2579
2600
  comments Playbook comments (create, pin, unpin)
2601
+ notification-history Notification delivery history (list-playbook, list-feed)
2580
2602
  push-subscriptions Personal push opt-in (subscribe-playbook, unsubscribe-playbook, subscribe-feed, unsubscribe-feed, list)
2581
2603
  channel Channel group operations (group-subscriptions context, list, subscribe, unsubscribe)
2582
2604
  remix Save playbook remix lineage
@@ -2849,6 +2871,24 @@ Build-time verify (fire once, then poll until your run completes):
2849
2871
  STATUS=$(echo "$ROW" | jq -r .status)
2850
2872
  [ "$STATUS" = completed ] || alva deploy run-logs --id 42 \\
2851
2873
  --run-id "$(echo "$ROW" | jq -r .id)"`,
2874
+ feed: `Usage: alva feed <subcommand> [options]
2875
+
2876
+ Feed lifecycle management. Currently exposes a single subcommand:
2877
+
2878
+ Subcommands:
2879
+ delete Soft-delete a feed and all its active majors
2880
+
2881
+ Delete flags:
2882
+ --id <feed_id> Numeric feed id (required, positive integer)
2883
+
2884
+ Notes:
2885
+ - Cascades to all active feed_majors in the same DB transaction.
2886
+ - Producer cronjobs are removed best-effort; the cronjob scavenger
2887
+ reconciles any leftover rows on its next sweep.
2888
+ - Auth: caller must own the feed (uid match), enforced by the backend.
2889
+
2890
+ Examples:
2891
+ alva feed delete --id 42`,
2852
2892
  release: `Usage: alva release <subcommand> [options]
2853
2893
 
2854
2894
  Publish feeds and playbooks to the Alva platform. The typical workflow:
@@ -2878,8 +2918,12 @@ Playbook-draft flags:
2878
2918
  --feeds <json> JSON array of {feed_id, feed_major?} (required)
2879
2919
  --description <text> Playbook description
2880
2920
  --trading-symbols <json> JSON array of tickers, e.g. '["BTC","ETH"]' (max 50)
2881
- --template-id <id> Source-template reference "username/name", e.g.
2882
- "alva/screener". Persisted set-once on first draft.
2921
+ --skill-id <id> Source-skill reference "username/name", e.g.
2922
+ "alva/screener". Discover skills via
2923
+ "alva skillhub list". Persisted set-once on first draft.
2924
+ --tags <json> JSON array of discovery tags, e.g. '["btc","macro"]'
2925
+ (max 10, each up to 32 chars). First draft merges
2926
+ with skill tags; re-draft replaces the tag set.
2883
2927
 
2884
2928
  Playbook flags:
2885
2929
  --name <name> Playbook name, must already exist as draft (required)
@@ -2902,7 +2946,8 @@ Examples:
2902
2946
  alva release feed --name btc-ema --version 1.0.0 --cronjob-id 42
2903
2947
  alva release feed --name nvda-insiders --version 1.0.0 --cronjob-id 43 --description "NVDA insider trading activity"
2904
2948
  alva release playbook-draft --name btc-dashboard --display-name "BTC Trend Dashboard" --feeds '[{"feed_id":100}]' --trading-symbols '["BTC"]'
2905
- alva release playbook-draft --name btc-dashboard --display-name "BTC Trend Dashboard" --feeds '[{"feed_id":100}]' --template-id alva/screener
2949
+ alva release playbook-draft --name btc-dashboard --display-name "BTC Trend Dashboard" --feeds '[{"feed_id":100}]' --skill-id alva/screener
2950
+ alva release playbook-draft --name btc-dashboard --display-name "BTC Trend Dashboard" --feeds '[{"feed_id":100}]' --tags '["btc","macro"]'
2906
2951
  alva release playbook --name btc-dashboard --version v1.0.0 --feeds '[{"feed_id":100}]' --changelog "Initial release" --readme-url "/alva/home/<username>/playbooks/btc-dashboard/README.md"`,
2907
2952
  secrets: `Usage: alva secrets <subcommand> [options]
2908
2953
 
@@ -2958,7 +3003,7 @@ Key partitions:
2958
3003
  Examples:
2959
3004
  alva sdk partitions
2960
3005
  alva sdk partition-summary --partition feed_widgets
2961
- alva sdk doc --name "@arrays/data/widget-scrap/twitter:v1.0.0"
3006
+ alva sdk doc --name "@arrays/data/widget-scrap/news:v1.0.0"
2962
3007
  alva sdk doc --name "@arrays/data/search/search-grok-x:v1.0.0"`,
2963
3008
  "data-skills": `Usage: alva data-skills <subcommand> [args]
2964
3009
 
@@ -3038,12 +3083,33 @@ Examples:
3038
3083
  alva comments create --username alice --name btc-dashboard --content "Thanks!" --parent-id 5
3039
3084
  alva comments pin --comment-id 12
3040
3085
  alva comments unpin --comment-id 12`,
3086
+ "notification-history": `Usage: alva notification-history <subcommand> [options]
3087
+
3088
+ Read the caller's delivered notification history scoped to a playbook or feed.
3089
+ This is an audit/history surface, not a subscription toggle.
3090
+
3091
+ Subcommands:
3092
+ list-playbook List notification history for a playbook
3093
+ list-feed List notification history for a feed
3094
+
3095
+ Common flags:
3096
+ --username <user> Owner's username (required)
3097
+ --name <name> URL-safe playbook or feed name (required)
3098
+ --channel <name> Optional delivery channel filter (telegram, web, ...)
3099
+ --status <status> Optional status filter (sent, failed, filtered)
3100
+ --since <seconds> Optional Unix seconds lower bound
3101
+ --first <n> Optional page size (default 50, max 200 server-side)
3102
+ --cursor <token> Optional cursor from the previous page
3103
+
3104
+ Examples:
3105
+ alva notification-history list-playbook --username alice --name btc-dashboard --first 5
3106
+ alva notification-history list-feed --username alice --name btc-ema --status sent`,
3041
3107
  "push-subscriptions": `Usage: alva push-subscriptions <subcommand> [options]
3042
3108
 
3043
3109
  Personal opt-in for DM/web push notifications. Independent of social
3044
3110
  follow: subscribing does not start following, unsubscribing does not
3045
- unfollow. Following a playbook elsewhere will compound-subscribe
3046
- automatically.
3111
+ unfollow. Following a playbook elsewhere does not create or revive a
3112
+ push subscription.
3047
3113
 
3048
3114
  Subcommands:
3049
3115
  subscribe-playbook Opt into push for a playbook (any of its feeds)
@@ -3057,13 +3123,14 @@ Subscribe/unsubscribe flags (playbook + feed):
3057
3123
  --name <name> URL-safe playbook or feed name (required)
3058
3124
 
3059
3125
  List flags:
3060
- --include-history Also return rows previously unsubscribed (default: false)
3126
+ --first <n> Optional page size
3127
+ --cursor <token> Optional cursor from the previous page
3061
3128
 
3062
3129
  Examples:
3063
3130
  alva push-subscriptions subscribe-playbook --username alice --name btc-dashboard
3064
3131
  alva push-subscriptions subscribe-feed --username alice --name btc-ema-cross
3065
3132
  alva push-subscriptions unsubscribe-feed --username alice --name btc-ema-cross
3066
- alva push-subscriptions list --include-history`,
3133
+ alva push-subscriptions list --first 20`,
3067
3134
  channel: `Usage: alva channel group-subscriptions <subcommand> [options]
3068
3135
 
3069
3136
  Manage push notifications delivered into the external group chat attached
@@ -3544,6 +3611,21 @@ async function dispatch(client, args, meta) {
3544
3611
  );
3545
3612
  }
3546
3613
  }
3614
+ case "feed": {
3615
+ if (!subcommand)
3616
+ throw new CliUsageError("Missing subcommand for feed", "feed");
3617
+ switch (subcommand) {
3618
+ case "delete":
3619
+ return client.feed.delete({
3620
+ id: requireNumericFlag(flags, "id", "feed delete")
3621
+ });
3622
+ default:
3623
+ throw new CliUsageError(
3624
+ `Unknown subcommand: feed ${subcommand}`,
3625
+ "feed"
3626
+ );
3627
+ }
3628
+ }
3547
3629
  case "release": {
3548
3630
  if (!subcommand)
3549
3631
  throw new CliUsageError("Missing subcommand for release", "release");
@@ -3570,7 +3652,8 @@ async function dispatch(client, args, meta) {
3570
3652
  requireFlag(flags, "feeds", "release playbook-draft")
3571
3653
  ),
3572
3654
  trading_symbols: flags["trading-symbols"] ? jsonParse(flags["trading-symbols"]) : void 0,
3573
- template_id: flags["template-id"]
3655
+ skill_id: flags["skill-id"],
3656
+ tags: flags["tags"] ? jsonParse(flags["tags"]) : void 0
3574
3657
  });
3575
3658
  case "playbook":
3576
3659
  return client.release.playbook({
@@ -3771,6 +3854,37 @@ async function dispatch(client, args, meta) {
3771
3854
  );
3772
3855
  }
3773
3856
  }
3857
+ case "notification-history": {
3858
+ if (!subcommand)
3859
+ throw new CliUsageError(
3860
+ "Missing subcommand for notification-history",
3861
+ "notification-history"
3862
+ );
3863
+ const params = {
3864
+ username: requireFlag(
3865
+ flags,
3866
+ "username",
3867
+ `notification-history ${subcommand}`
3868
+ ),
3869
+ name: requireFlag(flags, "name", `notification-history ${subcommand}`),
3870
+ channel: flags["channel"],
3871
+ status: flags["status"],
3872
+ since_time: num(flags["since"]),
3873
+ first: num(flags["first"]),
3874
+ cursor: flags["cursor"]
3875
+ };
3876
+ switch (subcommand) {
3877
+ case "list-playbook":
3878
+ return client.notifications.listPlaybook(params);
3879
+ case "list-feed":
3880
+ return client.notifications.listFeed(params);
3881
+ default:
3882
+ throw new CliUsageError(
3883
+ `Unknown subcommand: notification-history ${subcommand}`,
3884
+ "notification-history"
3885
+ );
3886
+ }
3887
+ }
3774
3888
  case "push-subscriptions": {
3775
3889
  if (!subcommand)
3776
3890
  throw new CliUsageError(
@@ -3832,7 +3946,8 @@ async function dispatch(client, args, meta) {
3832
3946
  });
3833
3947
  case "list":
3834
3948
  return client.pushSubscriptions.list({
3835
- include_history: flags["include-history"] !== void 0
3949
+ first: num(flags["first"]),
3950
+ cursor: flags["cursor"]
3836
3951
  });
3837
3952
  default:
3838
3953
  throw new CliUsageError(