@alva-ai/toolkit 0.2.0 → 0.3.1
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 +35 -4
- package/dist/browser.global.js +1 -1
- package/dist/browser.global.js.map +1 -1
- package/dist/cli.js +359 -77
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +109 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +57 -2
- package/dist/index.d.ts +57 -2
- package/dist/index.js +109 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -28,9 +28,20 @@ var FsResource = class {
|
|
|
28
28
|
client;
|
|
29
29
|
/** Returns `ArrayBuffer` for binary files, or parsed JSON for time-series virtual paths. */
|
|
30
30
|
async read(params) {
|
|
31
|
-
|
|
31
|
+
const result = await this.client._request("GET", "/api/v1/fs/read", {
|
|
32
32
|
query: { path: params.path, offset: params.offset, size: params.size }
|
|
33
33
|
});
|
|
34
|
+
if (!(result instanceof ArrayBuffer)) return result;
|
|
35
|
+
try {
|
|
36
|
+
const text = new TextDecoder("utf-8", { fatal: true }).decode(result);
|
|
37
|
+
try {
|
|
38
|
+
return JSON.parse(text);
|
|
39
|
+
} catch {
|
|
40
|
+
return text;
|
|
41
|
+
}
|
|
42
|
+
} catch {
|
|
43
|
+
return result;
|
|
44
|
+
}
|
|
34
45
|
}
|
|
35
46
|
/** Write file using JSON body (Mode 2). For text content. */
|
|
36
47
|
async write(params) {
|
|
@@ -338,6 +349,55 @@ var SdkDocsResource = class {
|
|
|
338
349
|
}
|
|
339
350
|
};
|
|
340
351
|
|
|
352
|
+
// src/resources/skills.ts
|
|
353
|
+
var SkillsResource = class {
|
|
354
|
+
constructor(client) {
|
|
355
|
+
this.client = client;
|
|
356
|
+
}
|
|
357
|
+
client;
|
|
358
|
+
async list() {
|
|
359
|
+
const res = await this.client._request("GET", "/api/v1/skills", {
|
|
360
|
+
baseUrl: this.client.arraysBaseUrl,
|
|
361
|
+
noAuth: true
|
|
362
|
+
});
|
|
363
|
+
return { skills: res.data ?? [] };
|
|
364
|
+
}
|
|
365
|
+
async summary(params) {
|
|
366
|
+
const encoded = encodeURIComponent(params.name);
|
|
367
|
+
const res = await this.client._request(
|
|
368
|
+
"GET",
|
|
369
|
+
`/api/v1/skills/${encoded}`,
|
|
370
|
+
{
|
|
371
|
+
baseUrl: this.client.arraysBaseUrl,
|
|
372
|
+
noAuth: true
|
|
373
|
+
}
|
|
374
|
+
);
|
|
375
|
+
const doc = res.data?.[0];
|
|
376
|
+
if (!doc)
|
|
377
|
+
throw new Error(`empty skills summary response for "${params.name}"`);
|
|
378
|
+
return doc;
|
|
379
|
+
}
|
|
380
|
+
async endpoint(params) {
|
|
381
|
+
const encoded = encodeURIComponent(params.name);
|
|
382
|
+
const res = await this.client._request(
|
|
383
|
+
"GET",
|
|
384
|
+
`/api/v1/skills/${encoded}`,
|
|
385
|
+
{
|
|
386
|
+
baseUrl: this.client.arraysBaseUrl,
|
|
387
|
+
noAuth: true,
|
|
388
|
+
query: { endpoint: params.file }
|
|
389
|
+
}
|
|
390
|
+
);
|
|
391
|
+
const doc = res.data?.[0];
|
|
392
|
+
if (!doc) {
|
|
393
|
+
throw new Error(
|
|
394
|
+
`empty skills endpoint response for "${params.name}" file "${params.file}"`
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
return doc;
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
|
|
341
401
|
// src/resources/comments.ts
|
|
342
402
|
var CommentsResource = class {
|
|
343
403
|
constructor(client) {
|
|
@@ -493,11 +553,37 @@ var TradingResource = class {
|
|
|
493
553
|
}
|
|
494
554
|
};
|
|
495
555
|
|
|
556
|
+
// src/resources/arraysJwt.ts
|
|
557
|
+
var ArraysJwtResource = class {
|
|
558
|
+
constructor(client) {
|
|
559
|
+
this.client = client;
|
|
560
|
+
}
|
|
561
|
+
client;
|
|
562
|
+
/** Idempotently sign-or-renew the Arrays JWT server-side. */
|
|
563
|
+
async ensure() {
|
|
564
|
+
this.client._requireAuth();
|
|
565
|
+
return this.client._request(
|
|
566
|
+
"POST",
|
|
567
|
+
"/api/v1/arrays-jwt/ensure"
|
|
568
|
+
);
|
|
569
|
+
}
|
|
570
|
+
/** Report the current Arrays JWT state for the authenticated user. */
|
|
571
|
+
async status() {
|
|
572
|
+
this.client._requireAuth();
|
|
573
|
+
return this.client._request(
|
|
574
|
+
"GET",
|
|
575
|
+
"/api/v1/arrays-jwt/status"
|
|
576
|
+
);
|
|
577
|
+
}
|
|
578
|
+
};
|
|
579
|
+
|
|
496
580
|
// src/client.ts
|
|
497
581
|
var DEFAULT_BASE_URL = "https://api-llm.prd.alva.ai";
|
|
582
|
+
var DEFAULT_ARRAYS_BASE_URL = "https://data-tools.prd.space.id";
|
|
498
583
|
var AlvaClient = class {
|
|
499
584
|
baseUrl;
|
|
500
|
-
|
|
585
|
+
arraysBaseUrl;
|
|
586
|
+
viewer_token;
|
|
501
587
|
apiKey;
|
|
502
588
|
_fs;
|
|
503
589
|
_run;
|
|
@@ -505,14 +591,17 @@ var AlvaClient = class {
|
|
|
505
591
|
_release;
|
|
506
592
|
_secrets;
|
|
507
593
|
_sdk;
|
|
594
|
+
_skills;
|
|
508
595
|
_comments;
|
|
509
596
|
_remix;
|
|
510
597
|
_screenshot;
|
|
511
598
|
_user;
|
|
512
599
|
_trading;
|
|
600
|
+
_arraysJwt;
|
|
513
601
|
constructor(config) {
|
|
514
602
|
this.baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;
|
|
515
|
-
this.
|
|
603
|
+
this.arraysBaseUrl = config.arraysBaseUrl ?? DEFAULT_ARRAYS_BASE_URL;
|
|
604
|
+
this.viewer_token = config.viewer_token;
|
|
516
605
|
this.apiKey = config.apiKey;
|
|
517
606
|
}
|
|
518
607
|
get fs() {
|
|
@@ -533,6 +622,9 @@ var AlvaClient = class {
|
|
|
533
622
|
get sdk() {
|
|
534
623
|
return this._sdk ??= new SdkDocsResource(this);
|
|
535
624
|
}
|
|
625
|
+
get skills() {
|
|
626
|
+
return this._skills ??= new SkillsResource(this);
|
|
627
|
+
}
|
|
536
628
|
get comments() {
|
|
537
629
|
return this._comments ??= new CommentsResource(this);
|
|
538
630
|
}
|
|
@@ -548,17 +640,21 @@ var AlvaClient = class {
|
|
|
548
640
|
get trading() {
|
|
549
641
|
return this._trading ??= new TradingResource(this);
|
|
550
642
|
}
|
|
643
|
+
get arraysJwt() {
|
|
644
|
+
return this._arraysJwt ??= new ArraysJwtResource(this);
|
|
645
|
+
}
|
|
551
646
|
_requireAuth() {
|
|
552
|
-
if (!this.
|
|
647
|
+
if (!this.viewer_token && !this.apiKey) {
|
|
553
648
|
throw new AlvaError(
|
|
554
649
|
"UNAUTHENTICATED",
|
|
555
|
-
"Authentication is required. Pass
|
|
650
|
+
"Authentication is required. Pass viewer_token or apiKey in the constructor.",
|
|
556
651
|
401
|
|
557
652
|
);
|
|
558
653
|
}
|
|
559
654
|
}
|
|
560
655
|
async _request(method, path, options) {
|
|
561
|
-
|
|
656
|
+
const baseUrl = options?.baseUrl ?? this.baseUrl;
|
|
657
|
+
let url = `${baseUrl}${path}`;
|
|
562
658
|
if (options?.query) {
|
|
563
659
|
const params = new URLSearchParams();
|
|
564
660
|
for (const [key, value] of Object.entries(options.query)) {
|
|
@@ -572,10 +668,12 @@ var AlvaClient = class {
|
|
|
572
668
|
}
|
|
573
669
|
}
|
|
574
670
|
const headers = {};
|
|
575
|
-
if (
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
671
|
+
if (!options?.noAuth) {
|
|
672
|
+
if (this.viewer_token) {
|
|
673
|
+
headers["x-Playbook-Viewer"] = this.viewer_token;
|
|
674
|
+
} else if (this.apiKey) {
|
|
675
|
+
headers["X-Alva-Api-Key"] = this.apiKey;
|
|
676
|
+
}
|
|
579
677
|
}
|
|
580
678
|
let fetchBody;
|
|
581
679
|
if (options?.rawBody !== void 0) {
|
|
@@ -691,6 +789,7 @@ async function writeConfig(config, deps, profileName = "default") {
|
|
|
691
789
|
return {
|
|
692
790
|
apiKey: profileData.apiKey,
|
|
693
791
|
baseUrl: profileData.baseUrl,
|
|
792
|
+
arraysBaseUrl: DEFAULT_ARRAYS_BASE_URL,
|
|
694
793
|
profile: profileName
|
|
695
794
|
};
|
|
696
795
|
}
|
|
@@ -710,6 +809,8 @@ function loadConfig(deps) {
|
|
|
710
809
|
const profileName = parseFlag(argv, "--profile") || env.ALVA_PROFILE || "default";
|
|
711
810
|
const baseUrlFlag = parseFlag(argv, "--base-url");
|
|
712
811
|
const baseUrlEnv = env.ALVA_ENDPOINT;
|
|
812
|
+
const arraysBaseUrlFlag = parseFlag(argv, "--arrays-endpoint");
|
|
813
|
+
const arraysBaseUrlEnv = env.ARRAYS_ENDPOINT;
|
|
713
814
|
const apiKeyFlag = parseFlag(argv, "--api-key");
|
|
714
815
|
const apiKeyEnv = env.ALVA_API_KEY;
|
|
715
816
|
let fileProfile = {};
|
|
@@ -731,6 +832,7 @@ function loadConfig(deps) {
|
|
|
731
832
|
return {
|
|
732
833
|
apiKey: apiKeyFlag ?? apiKeyEnv ?? fileProfile.apiKey,
|
|
733
834
|
baseUrl: baseUrlFlag ?? baseUrlEnv ?? fileProfile.baseUrl,
|
|
835
|
+
arraysBaseUrl: arraysBaseUrlFlag ?? arraysBaseUrlEnv ?? DEFAULT_ARRAYS_BASE_URL,
|
|
734
836
|
profile: profileName
|
|
735
837
|
};
|
|
736
838
|
}
|
|
@@ -859,11 +961,48 @@ Waiting for login callback...
|
|
|
859
961
|
});
|
|
860
962
|
}
|
|
861
963
|
|
|
964
|
+
// src/cli/postConfigureHooks.ts
|
|
965
|
+
function defaultStderr(s) {
|
|
966
|
+
process.stderr.write(s);
|
|
967
|
+
}
|
|
968
|
+
function formatTier(t) {
|
|
969
|
+
const stripped = typeof t === "string" && t.startsWith("SUBSCRIPTION_TIER_") ? t.slice("SUBSCRIPTION_TIER_".length) : String(t);
|
|
970
|
+
return stripped.toLowerCase();
|
|
971
|
+
}
|
|
972
|
+
function formatExpiry(expiresAt) {
|
|
973
|
+
return new Date(expiresAt * 1e3).toISOString().slice(0, 10);
|
|
974
|
+
}
|
|
975
|
+
var ensureArraysJwtHook = {
|
|
976
|
+
name: "ensureArraysJwt",
|
|
977
|
+
async run(client) {
|
|
978
|
+
const res = await client.arraysJwt.ensure();
|
|
979
|
+
const date = formatExpiry(res.expires_at);
|
|
980
|
+
const tier = formatTier(res.tier);
|
|
981
|
+
const verb = res.renewed ? "Arrays JWT provisioned" : "Arrays JWT already current";
|
|
982
|
+
process.stderr.write(`${verb} (expires ${date}, tier: ${tier})
|
|
983
|
+
`);
|
|
984
|
+
}
|
|
985
|
+
};
|
|
986
|
+
var POST_CONFIGURE_HOOKS = [ensureArraysJwtHook];
|
|
987
|
+
async function runPostConfigureHooks(client, deps) {
|
|
988
|
+
const hooks = deps?.hooks ?? POST_CONFIGURE_HOOKS;
|
|
989
|
+
const stderr = deps?.stderr ?? defaultStderr;
|
|
990
|
+
for (const hook of hooks) {
|
|
991
|
+
try {
|
|
992
|
+
await hook.run(client);
|
|
993
|
+
} catch (err) {
|
|
994
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
995
|
+
stderr(`warning: post-configure hook "${hook.name}" failed: ${msg}
|
|
996
|
+
`);
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
|
|
862
1001
|
// src/cli/index.ts
|
|
863
1002
|
import * as fs from "fs";
|
|
864
1003
|
import * as os2 from "os";
|
|
865
1004
|
import * as fsPromises2 from "fs/promises";
|
|
866
|
-
var CLI_VERSION = true ? "0.
|
|
1005
|
+
var CLI_VERSION = true ? "0.3.1" : "dev";
|
|
867
1006
|
function isVersionOlderThan(a, b) {
|
|
868
1007
|
const parse = (v) => {
|
|
869
1008
|
if (!v) return null;
|
|
@@ -885,24 +1024,27 @@ var HELP_TEXT = `Usage: alva <command> [options]
|
|
|
885
1024
|
|
|
886
1025
|
Commands:
|
|
887
1026
|
configure Save API key and endpoint to a named profile
|
|
888
|
-
whoami Verify credentials and show current
|
|
889
|
-
user User profile operations
|
|
1027
|
+
whoami Verify credentials and show current identity
|
|
1028
|
+
user User profile operations (me)
|
|
890
1029
|
fs Filesystem operations (read, write, stat, readdir, mkdir, remove, rename, copy, symlink, readlink, chmod, grant, revoke)
|
|
891
1030
|
run Execute code in the Alva runtime
|
|
892
|
-
deploy Cronjob management (create, list, get, update, delete, pause, resume)
|
|
1031
|
+
deploy Cronjob management (create, list, get, update, delete, pause, resume, runs, run-logs)
|
|
893
1032
|
release Feed and playbook releases (feed, playbook-draft, playbook)
|
|
894
1033
|
secrets Secret management (create, list, get, update, delete)
|
|
895
1034
|
sdk SDK documentation (doc, partitions, partition-summary)
|
|
1035
|
+
skills Data-skill documentation from the Arrays backend (list, summary, endpoint)
|
|
896
1036
|
comments Playbook comments (create, pin, unpin)
|
|
897
1037
|
remix Save playbook remix lineage
|
|
898
1038
|
trading Trading operations (accounts, portfolio, orders, subscriptions, equity-history, risk-rules, subscribe, unsubscribe, execute, update-risk-rules)
|
|
899
|
-
auth Authentication (login
|
|
1039
|
+
auth Authentication (login)
|
|
900
1040
|
screenshot Capture a web screenshot as PNG
|
|
1041
|
+
arrays Arrays backend operations (token ensure, token status)
|
|
901
1042
|
|
|
902
1043
|
Global options:
|
|
903
|
-
--api-key <key>
|
|
904
|
-
--base-url <url>
|
|
905
|
-
--profile <name>
|
|
1044
|
+
--api-key <key> API key (overrides env and config file)
|
|
1045
|
+
--base-url <url> API base URL (overrides env and config file)
|
|
1046
|
+
--profile <name> Named profile to use (default: "default")
|
|
1047
|
+
--arrays-endpoint <url> Arrays backend URL (or ARRAYS_ENDPOINT env; default: https://data-tools.prd.space.id)
|
|
906
1048
|
-v, --version Show CLI version
|
|
907
1049
|
--help Show help (use 'alva <command> --help' for command details)
|
|
908
1050
|
|
|
@@ -919,6 +1061,8 @@ var COMMAND_HELP = {
|
|
|
919
1061
|
Save API credentials to ~/.config/alva/config.json (mode 0600).
|
|
920
1062
|
After configuring, subsequent commands use the saved key automatically.
|
|
921
1063
|
Multiple profiles allow switching between environments (production, staging, etc.).
|
|
1064
|
+
Also auto-runs 'alva arrays token ensure' to provision the server-side Arrays JWT
|
|
1065
|
+
(soft-fail: a network/auth failure prints a stderr warning but exit stays 0).
|
|
922
1066
|
|
|
923
1067
|
Required:
|
|
924
1068
|
--api-key <key> Your Alva API key (starts with "alva_")
|
|
@@ -954,6 +1098,9 @@ Verify that your credentials are valid by calling the Alva API. Shows your
|
|
|
954
1098
|
username, subscription tier, and which profile/endpoint is being used.
|
|
955
1099
|
Use this after 'alva configure' to confirm everything works.
|
|
956
1100
|
|
|
1101
|
+
Output also includes _meta.arrays_jwt (exists, expires_at, renewal_needed,
|
|
1102
|
+
tier) when the backend is reachable; the field is omitted on RPC failure.
|
|
1103
|
+
|
|
957
1104
|
Examples:
|
|
958
1105
|
alva whoami
|
|
959
1106
|
alva --profile staging whoami`,
|
|
@@ -987,16 +1134,26 @@ Subcommands:
|
|
|
987
1134
|
grant Grant access permission to a user or group
|
|
988
1135
|
revoke Revoke access permission
|
|
989
1136
|
|
|
990
|
-
|
|
991
|
-
--path
|
|
992
|
-
--
|
|
993
|
-
|
|
994
|
-
--
|
|
995
|
-
--
|
|
1137
|
+
Subcommand flags:
|
|
1138
|
+
read --path (required), [--offset <n>], [--size <n>]
|
|
1139
|
+
write --path (required), --data <text> OR --file <local-path> (one required),
|
|
1140
|
+
[--mkdir-parents | --no-mkdir-parents]
|
|
1141
|
+
stat --path (required)
|
|
1142
|
+
readdir --path (required), [--recursive | --no-recursive]
|
|
1143
|
+
mkdir --path (required)
|
|
1144
|
+
remove --path (required), [--recursive | --no-recursive]
|
|
1145
|
+
rename --old-path (required), --new-path (required)
|
|
1146
|
+
copy --src-path (required), --dst-path (required)
|
|
1147
|
+
symlink --target-path (required), --link-path (required)
|
|
1148
|
+
readlink --path (required)
|
|
1149
|
+
chmod --path (required), --mode <octal> (required)
|
|
1150
|
+
grant --path (required), --subject <s> (required), --permission <p> (required)
|
|
1151
|
+
revoke --path (required), --subject <s> (required), --permission <p> (required)
|
|
996
1152
|
|
|
997
1153
|
Path conventions:
|
|
998
1154
|
~/... Home-relative path (expands to /alva/home/<username>/...)
|
|
999
1155
|
/alva/home/alice/... Absolute path (required for public/unauthenticated reads)
|
|
1156
|
+
Quote tilde paths to prevent shell expansion: --path "~/data" (not --path ~/data).
|
|
1000
1157
|
|
|
1001
1158
|
Time series reads:
|
|
1002
1159
|
Paths under feed data directories support virtual suffixes:
|
|
@@ -1012,21 +1169,23 @@ Grant/revoke subjects:
|
|
|
1012
1169
|
user:<id> Specific user by ID
|
|
1013
1170
|
|
|
1014
1171
|
Examples:
|
|
1015
|
-
alva fs readdir --path ~/
|
|
1016
|
-
alva fs readdir --path ~/data --recursive
|
|
1017
|
-
alva fs read --path ~/data/prices.json
|
|
1018
|
-
alva fs read --path ~/feeds/btc-ema/v1/data/metrics/prices/@last/100
|
|
1172
|
+
alva fs readdir --path "~/"
|
|
1173
|
+
alva fs readdir --path "~/data" --recursive
|
|
1174
|
+
alva fs read --path "~/data/prices.json"
|
|
1175
|
+
alva fs read --path "~/feeds/btc-ema/v1/data/metrics/prices/@last/100"
|
|
1019
1176
|
alva fs read --path /alva/home/alice/feeds/btc-ema/v1/data/metrics/prices/@last/10
|
|
1020
|
-
alva fs write --path ~/hello.txt --data "Hello, world!"
|
|
1021
|
-
alva fs write --path ~/feeds/my-feed/v1/src/index.js --file ./local-script.js --mkdir-parents
|
|
1022
|
-
alva fs stat --path ~/hello.txt
|
|
1023
|
-
alva fs mkdir --path ~/feeds/my-feed/v1/src
|
|
1024
|
-
alva fs remove --path ~/old-folder --recursive
|
|
1025
|
-
alva fs rename --old-path ~/a.txt --new-path ~/b.txt
|
|
1026
|
-
alva fs copy --src-path ~/a.txt --dst-path ~/b.txt
|
|
1027
|
-
alva fs chmod --path ~/script.js --mode 755
|
|
1028
|
-
alva fs grant --path ~/feeds/btc-ema --subject "special:user:*" --permission read
|
|
1029
|
-
alva fs revoke --path ~/feeds/btc-ema --subject "special:user:*" --permission read
|
|
1177
|
+
alva fs write --path "~/hello.txt" --data "Hello, world!"
|
|
1178
|
+
alva fs write --path "~/feeds/my-feed/v1/src/index.js" --file ./local-script.js --mkdir-parents
|
|
1179
|
+
alva fs stat --path "~/hello.txt"
|
|
1180
|
+
alva fs mkdir --path "~/feeds/my-feed/v1/src"
|
|
1181
|
+
alva fs remove --path "~/old-folder" --recursive
|
|
1182
|
+
alva fs rename --old-path "~/a.txt" --new-path "~/b.txt"
|
|
1183
|
+
alva fs copy --src-path "~/a.txt" --dst-path "~/b.txt"
|
|
1184
|
+
alva fs chmod --path "~/script.js" --mode 755
|
|
1185
|
+
alva fs grant --path "~/feeds/btc-ema" --subject "special:user:*" --permission read
|
|
1186
|
+
alva fs revoke --path "~/feeds/btc-ema" --subject "special:user:*" --permission read
|
|
1187
|
+
alva fs symlink --target-path "~/real-file.txt" --link-path "~/my-link.txt"
|
|
1188
|
+
alva fs readlink --path "~/my-link.txt"`,
|
|
1030
1189
|
run: `Usage: alva run [options]
|
|
1031
1190
|
|
|
1032
1191
|
Execute JavaScript code in the Alva V8 runtime. Provide either inline code
|
|
@@ -1067,8 +1226,8 @@ Constraints:
|
|
|
1067
1226
|
Examples:
|
|
1068
1227
|
alva run --code "1 + 2 + 3;"
|
|
1069
1228
|
alva run --code "JSON.stringify(require('env').args);" --args '{"symbol":"BTC"}'
|
|
1070
|
-
alva run --entry-path ~/feeds/my-feed/v1/src/index.js
|
|
1071
|
-
alva run --entry-path ~/tasks/analyze/src/index.js --args '{"symbol":"NVDA","limit":50}'
|
|
1229
|
+
alva run --entry-path "~/feeds/my-feed/v1/src/index.js"
|
|
1230
|
+
alva run --entry-path "~/tasks/analyze/src/index.js" --args '{"symbol":"NVDA","limit":50}'
|
|
1072
1231
|
alva run --local-file ./my-script.js --args '{"symbol":"BTC"}'`,
|
|
1073
1232
|
deploy: `Usage: alva deploy <subcommand> [options]
|
|
1074
1233
|
|
|
@@ -1083,6 +1242,8 @@ Subcommands:
|
|
|
1083
1242
|
delete Delete a cronjob
|
|
1084
1243
|
pause Pause a running cronjob
|
|
1085
1244
|
resume Resume a paused cronjob
|
|
1245
|
+
runs List runs for a cronjob (cursor-paginated)
|
|
1246
|
+
run-logs Get stdout/stderr logs for a single cronjob run
|
|
1086
1247
|
|
|
1087
1248
|
Create flags:
|
|
1088
1249
|
--name <name> Cronjob name (required, 1-63 lowercase alphanumeric/hyphens)
|
|
@@ -1099,6 +1260,15 @@ List flags:
|
|
|
1099
1260
|
Get/Update/Delete/Pause/Resume flags:
|
|
1100
1261
|
--id <id> Cronjob ID (required)
|
|
1101
1262
|
|
|
1263
|
+
Runs flags:
|
|
1264
|
+
--id <id> Cronjob ID (required)
|
|
1265
|
+
--first <n> Max results per page
|
|
1266
|
+
--cursor <cursor> Pagination cursor from previous response
|
|
1267
|
+
|
|
1268
|
+
Run-logs flags:
|
|
1269
|
+
--id <id> Cronjob ID (required)
|
|
1270
|
+
--run-id <id> Run ID (required)
|
|
1271
|
+
|
|
1102
1272
|
Name format: 1-63 lowercase alphanumeric or hyphens, no leading/trailing hyphens.
|
|
1103
1273
|
Valid: btc-ema-update, my-strategy-1
|
|
1104
1274
|
Invalid: BTC EMA, -my-job-, my_job
|
|
@@ -1110,8 +1280,8 @@ Recommended cron schedules:
|
|
|
1110
1280
|
"0 0 * * *" Daily at midnight (end-of-day summaries)
|
|
1111
1281
|
|
|
1112
1282
|
Examples:
|
|
1113
|
-
alva deploy create --name btc-ema --path ~/feeds/btc-ema/v1/src/index.js --cron "0 */4 * * *"
|
|
1114
|
-
alva deploy create --name alert --path ~/feeds/alert/v1/src/index.js --cron "*/5 * * * *" --push-notify --args '{"threshold":100}'
|
|
1283
|
+
alva deploy create --name btc-ema --path "~/feeds/btc-ema/v1/src/index.js" --cron "0 */4 * * *"
|
|
1284
|
+
alva deploy create --name alert --path "~/feeds/alert/v1/src/index.js" --cron "*/5 * * * *" --push-notify --args '{"threshold":100}'
|
|
1115
1285
|
alva deploy list
|
|
1116
1286
|
alva deploy list --limit 10
|
|
1117
1287
|
alva deploy get --id 42
|
|
@@ -1147,7 +1317,7 @@ Playbook-draft flags:
|
|
|
1147
1317
|
--name <name> URL-safe playbook name, unique per user (required)
|
|
1148
1318
|
--display-name <name> Human-readable title, max 40 chars (required)
|
|
1149
1319
|
--feeds <json> JSON array of {feed_id, feed_major?} (required)
|
|
1150
|
-
--changelog <text> Release changelog
|
|
1320
|
+
--changelog <text> Release changelog
|
|
1151
1321
|
--description <text> Playbook description
|
|
1152
1322
|
--trading-symbols <json> JSON array of tickers, e.g. '["BTC","ETH"]' (max 50)
|
|
1153
1323
|
|
|
@@ -1215,20 +1385,37 @@ Flags:
|
|
|
1215
1385
|
--partition <name> Partition name for 'partition-summary' (required)
|
|
1216
1386
|
|
|
1217
1387
|
Key partitions:
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
crypto_technical_metrics MA, RSI, MACD, MVRV, SOPR, NUPL (20 modules)
|
|
1221
|
-
equity_fundamentals Income, balance sheet, PE, ROE (31 modules)
|
|
1222
|
-
equity_estimates_and_targets Analyst targets, consensus estimates
|
|
1223
|
-
equity_ownership_and_flow Insider trades, senator trading, institutions
|
|
1224
|
-
macro_and_economics_data CPI, GDP, Treasury rates, VIX (20 modules)
|
|
1388
|
+
feed_widgets Per-handle/channel rolling subscriptions
|
|
1389
|
+
unified_search Web search and URL scraping tools (X/Grok, Google, Brave, serper, decodo)
|
|
1225
1390
|
technical_indicator_calculation_helpers 50+ pure calculators (RSI, MACD, Bollinger)
|
|
1226
1391
|
|
|
1227
1392
|
Examples:
|
|
1228
1393
|
alva sdk partitions
|
|
1229
|
-
alva sdk partition-summary --partition
|
|
1230
|
-
alva sdk doc --name "@arrays/
|
|
1231
|
-
alva sdk doc --name "@arrays/data/
|
|
1394
|
+
alva sdk partition-summary --partition feed_widgets
|
|
1395
|
+
alva sdk doc --name "@arrays/data/widget-scrap/twitter:v1.0.0"
|
|
1396
|
+
alva sdk doc --name "@arrays/data/search/search-grok-x:v1.0.0"`,
|
|
1397
|
+
skills: `Usage: alva skills <subcommand> [options]
|
|
1398
|
+
|
|
1399
|
+
Browse the Arrays backend's data-skill documentation. These endpoints are
|
|
1400
|
+
public \u2014 no Alva credentials required.
|
|
1401
|
+
|
|
1402
|
+
Subcommands:
|
|
1403
|
+
list List all available data skills
|
|
1404
|
+
summary Get the endpoints table for a skill (requires --name)
|
|
1405
|
+
endpoint Get full documentation for a specific endpoint (requires --name and --file)
|
|
1406
|
+
|
|
1407
|
+
Flags:
|
|
1408
|
+
--name <name> Skill name (required for summary and endpoint)
|
|
1409
|
+
--file <file> Endpoint file name from the "File" column of 'skills summary' (required for endpoint)
|
|
1410
|
+
|
|
1411
|
+
Global override:
|
|
1412
|
+
--arrays-endpoint <url> Arrays backend URL (or ARRAYS_ENDPOINT env)
|
|
1413
|
+
Default: https://data-tools.prd.space.id
|
|
1414
|
+
|
|
1415
|
+
Examples:
|
|
1416
|
+
alva skills list
|
|
1417
|
+
alva skills summary --name <skill>
|
|
1418
|
+
alva skills endpoint --name <skill> --file <endpoint-file>`,
|
|
1232
1419
|
comments: `Usage: alva comments <subcommand> [options]
|
|
1233
1420
|
|
|
1234
1421
|
Manage comments on Alva playbooks. Supports top-level comments and threaded
|
|
@@ -1348,7 +1535,20 @@ Examples:
|
|
|
1348
1535
|
alva trading subscribe --account-id acc_123 --source-username alice --source-feed btc-signals --playbook-id pb_1 --playbook-version v1.0.0
|
|
1349
1536
|
alva trading unsubscribe --subscription-id sub_456
|
|
1350
1537
|
alva trading execute --account-id acc_123 --signal '{"symbol":"BTC","side":"buy","qty":0.1}' --dry-run
|
|
1351
|
-
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
|
|
1538
|
+
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`,
|
|
1539
|
+
arrays: `Usage: alva arrays token <subcommand>
|
|
1540
|
+
|
|
1541
|
+
Manage the Arrays JWT used by sandbox scripts (secret.loadPlaintext('ARRAYS_JWT')).
|
|
1542
|
+
The JWT is stored server-side as a jagent secret; the CLI never receives the
|
|
1543
|
+
token itself. 'alva configure' auto-runs 'token ensure' after saving credentials.
|
|
1544
|
+
|
|
1545
|
+
Subcommands:
|
|
1546
|
+
token ensure Provision or refresh the Arrays JWT (idempotent)
|
|
1547
|
+
token status Show Arrays JWT presence, expiry, tier, and renewal hint
|
|
1548
|
+
|
|
1549
|
+
Examples:
|
|
1550
|
+
alva arrays token ensure
|
|
1551
|
+
alva arrays token status`
|
|
1352
1552
|
};
|
|
1353
1553
|
async function handleConfigure(args, deps) {
|
|
1354
1554
|
const flags = parseFlags2(args.slice(1));
|
|
@@ -1373,6 +1573,15 @@ async function handleConfigure(args, deps) {
|
|
|
1373
1573
|
readFile: (path) => fsPromises2.readFile(path, "utf-8")
|
|
1374
1574
|
};
|
|
1375
1575
|
const result = await writeConfig(configInput, writeDeps, profileName);
|
|
1576
|
+
const client = new AlvaClient(baseUrl ? { apiKey, baseUrl } : { apiKey });
|
|
1577
|
+
const runHooks = writeDeps.runHooks ?? ((c) => runPostConfigureHooks(c));
|
|
1578
|
+
try {
|
|
1579
|
+
await runHooks(client);
|
|
1580
|
+
} catch (err) {
|
|
1581
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1582
|
+
process.stderr?.write?.(`warning: post-configure hooks crashed: ${msg}
|
|
1583
|
+
`);
|
|
1584
|
+
}
|
|
1376
1585
|
return {
|
|
1377
1586
|
status: "configured",
|
|
1378
1587
|
apiKey: result.apiKey,
|
|
@@ -1458,12 +1667,21 @@ async function dispatch(client, args, meta) {
|
|
|
1458
1667
|
const user = await client.user.me();
|
|
1459
1668
|
const record = user;
|
|
1460
1669
|
const version = meta?.cliVersion ?? CLI_VERSION;
|
|
1670
|
+
let arraysJwtStatus;
|
|
1671
|
+
try {
|
|
1672
|
+
arraysJwtStatus = await client.arraysJwt.status();
|
|
1673
|
+
} catch {
|
|
1674
|
+
}
|
|
1675
|
+
const metaBlock = {
|
|
1676
|
+
profile: meta?.profile ?? "default",
|
|
1677
|
+
endpoint: meta?.baseUrl ?? client.baseUrl
|
|
1678
|
+
};
|
|
1679
|
+
if (arraysJwtStatus !== void 0) {
|
|
1680
|
+
metaBlock.arrays_jwt = arraysJwtStatus;
|
|
1681
|
+
}
|
|
1461
1682
|
const result = {
|
|
1462
1683
|
...record,
|
|
1463
|
-
_meta:
|
|
1464
|
-
profile: meta?.profile ?? "default",
|
|
1465
|
-
endpoint: meta?.baseUrl ?? client.baseUrl
|
|
1466
|
-
}
|
|
1684
|
+
_meta: metaBlock
|
|
1467
1685
|
};
|
|
1468
1686
|
const minVersion = record.toolkit_min_version;
|
|
1469
1687
|
if (typeof minVersion === "string" && version && version !== "dev" && isVersionOlderThan(version, minVersion)) {
|
|
@@ -1674,11 +1892,7 @@ async function dispatch(client, args, meta) {
|
|
|
1674
1892
|
requireFlag(flags, "feeds", "release playbook-draft")
|
|
1675
1893
|
),
|
|
1676
1894
|
trading_symbols: flags["trading-symbols"] ? jsonParse(flags["trading-symbols"]) : void 0,
|
|
1677
|
-
changelog:
|
|
1678
|
-
flags,
|
|
1679
|
-
"changelog",
|
|
1680
|
-
"release playbook-draft"
|
|
1681
|
-
)
|
|
1895
|
+
changelog: flags["changelog"]
|
|
1682
1896
|
});
|
|
1683
1897
|
case "playbook":
|
|
1684
1898
|
return client.release.playbook({
|
|
@@ -1748,6 +1962,28 @@ async function dispatch(client, args, meta) {
|
|
|
1748
1962
|
);
|
|
1749
1963
|
}
|
|
1750
1964
|
}
|
|
1965
|
+
case "skills": {
|
|
1966
|
+
if (!subcommand)
|
|
1967
|
+
throw new CliUsageError("Missing subcommand for skills", "skills");
|
|
1968
|
+
switch (subcommand) {
|
|
1969
|
+
case "list":
|
|
1970
|
+
return client.skills.list();
|
|
1971
|
+
case "summary":
|
|
1972
|
+
return client.skills.summary({
|
|
1973
|
+
name: requireFlag(flags, "name", "skills summary")
|
|
1974
|
+
});
|
|
1975
|
+
case "endpoint":
|
|
1976
|
+
return client.skills.endpoint({
|
|
1977
|
+
name: requireFlag(flags, "name", "skills endpoint"),
|
|
1978
|
+
file: requireFlag(flags, "file", "skills endpoint")
|
|
1979
|
+
});
|
|
1980
|
+
default:
|
|
1981
|
+
throw new CliUsageError(
|
|
1982
|
+
`Unknown subcommand: skills ${subcommand}`,
|
|
1983
|
+
"skills"
|
|
1984
|
+
);
|
|
1985
|
+
}
|
|
1986
|
+
}
|
|
1751
1987
|
case "comments": {
|
|
1752
1988
|
if (!subcommand)
|
|
1753
1989
|
throw new CliUsageError("Missing subcommand for comments", "comments");
|
|
@@ -1786,6 +2022,30 @@ async function dispatch(client, args, meta) {
|
|
|
1786
2022
|
},
|
|
1787
2023
|
parents: jsonParse(requireFlag(flags, "parents", "remix"))
|
|
1788
2024
|
});
|
|
2025
|
+
case "arrays": {
|
|
2026
|
+
if (!subcommand || subcommand === "--help" || subcommand === "-h") {
|
|
2027
|
+
return { _help: true, text: COMMAND_HELP.arrays };
|
|
2028
|
+
}
|
|
2029
|
+
if (subcommand === "token") {
|
|
2030
|
+
const leaf = args[2];
|
|
2031
|
+
if (!leaf || leaf === "--help" || leaf === "-h") {
|
|
2032
|
+
return { _help: true, text: COMMAND_HELP.arrays };
|
|
2033
|
+
}
|
|
2034
|
+
switch (leaf) {
|
|
2035
|
+
case "ensure":
|
|
2036
|
+
return client.arraysJwt.ensure();
|
|
2037
|
+
case "status":
|
|
2038
|
+
return client.arraysJwt.status();
|
|
2039
|
+
default:
|
|
2040
|
+
throw new Error(
|
|
2041
|
+
`Unknown subcommand 'arrays token ${leaf}'. Use 'alva arrays --help' for usage.`
|
|
2042
|
+
);
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
2045
|
+
throw new Error(
|
|
2046
|
+
`Unknown subcommand 'arrays ${subcommand}'. Use 'alva arrays --help' for usage.`
|
|
2047
|
+
);
|
|
2048
|
+
}
|
|
1789
2049
|
case "screenshot": {
|
|
1790
2050
|
const outFile = requireFlag(flags, "out", "screenshot");
|
|
1791
2051
|
const result = await client.screenshot.capture({
|
|
@@ -1794,6 +2054,12 @@ async function dispatch(client, args, meta) {
|
|
|
1794
2054
|
xpath: flags["xpath"]
|
|
1795
2055
|
});
|
|
1796
2056
|
const buf = Buffer.from(result);
|
|
2057
|
+
if (buf.length === 0) {
|
|
2058
|
+
throw new CliUsageError(
|
|
2059
|
+
"Screenshot service returned empty response (0 bytes). The service may be overloaded \u2014 retry in a few seconds.",
|
|
2060
|
+
"screenshot"
|
|
2061
|
+
);
|
|
2062
|
+
}
|
|
1797
2063
|
fs.writeFileSync(outFile, buf);
|
|
1798
2064
|
return { written: outFile, bytes: buf.length };
|
|
1799
2065
|
}
|
|
@@ -1917,6 +2183,27 @@ async function dispatch(client, args, meta) {
|
|
|
1917
2183
|
throw new CliUsageError(`Unknown command: '${group}'`);
|
|
1918
2184
|
}
|
|
1919
2185
|
}
|
|
2186
|
+
function stripGlobalFlags(argv) {
|
|
2187
|
+
const GLOBAL_FLAGS = [
|
|
2188
|
+
"--api-key",
|
|
2189
|
+
"--base-url",
|
|
2190
|
+
"--profile",
|
|
2191
|
+
"--arrays-endpoint"
|
|
2192
|
+
];
|
|
2193
|
+
const result = [];
|
|
2194
|
+
for (let i = 0; i < argv.length; i++) {
|
|
2195
|
+
const a = argv[i];
|
|
2196
|
+
if (GLOBAL_FLAGS.includes(a)) {
|
|
2197
|
+
i++;
|
|
2198
|
+
continue;
|
|
2199
|
+
}
|
|
2200
|
+
if (GLOBAL_FLAGS.some((f) => a.startsWith(`${f}=`))) {
|
|
2201
|
+
continue;
|
|
2202
|
+
}
|
|
2203
|
+
result.push(a);
|
|
2204
|
+
}
|
|
2205
|
+
return result;
|
|
2206
|
+
}
|
|
1920
2207
|
async function main() {
|
|
1921
2208
|
try {
|
|
1922
2209
|
const rawArgs = process.argv.slice(2);
|
|
@@ -1959,20 +2246,10 @@ async function main() {
|
|
|
1959
2246
|
});
|
|
1960
2247
|
const client = new AlvaClient({
|
|
1961
2248
|
apiKey: config.apiKey,
|
|
1962
|
-
baseUrl: config.baseUrl
|
|
2249
|
+
baseUrl: config.baseUrl,
|
|
2250
|
+
arraysBaseUrl: config.arraysBaseUrl
|
|
1963
2251
|
});
|
|
1964
|
-
const cleanArgs =
|
|
1965
|
-
for (let i = 0; i < rawArgs.length; i++) {
|
|
1966
|
-
const a = rawArgs[i];
|
|
1967
|
-
if (a === "--api-key" || a === "--base-url" || a === "--profile") {
|
|
1968
|
-
i++;
|
|
1969
|
-
continue;
|
|
1970
|
-
}
|
|
1971
|
-
if (a.startsWith("--api-key=") || a.startsWith("--base-url=") || a.startsWith("--profile=")) {
|
|
1972
|
-
continue;
|
|
1973
|
-
}
|
|
1974
|
-
cleanArgs.push(a);
|
|
1975
|
-
}
|
|
2252
|
+
const cleanArgs = stripGlobalFlags(rawArgs);
|
|
1976
2253
|
const result = await dispatch(client, cleanArgs, {
|
|
1977
2254
|
profile: config.profile,
|
|
1978
2255
|
baseUrl: config.baseUrl,
|
|
@@ -1993,6 +2270,10 @@ async function main() {
|
|
|
1993
2270
|
process.stdout.write(Buffer.from(result));
|
|
1994
2271
|
return;
|
|
1995
2272
|
}
|
|
2273
|
+
if (typeof result === "string") {
|
|
2274
|
+
process.stdout.write(result);
|
|
2275
|
+
return;
|
|
2276
|
+
}
|
|
1996
2277
|
if (result !== void 0) {
|
|
1997
2278
|
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
1998
2279
|
}
|
|
@@ -2030,6 +2311,7 @@ export {
|
|
|
2030
2311
|
CLI_VERSION,
|
|
2031
2312
|
dispatch,
|
|
2032
2313
|
handleConfigure,
|
|
2033
|
-
isVersionOlderThan
|
|
2314
|
+
isVersionOlderThan,
|
|
2315
|
+
stripGlobalFlags
|
|
2034
2316
|
};
|
|
2035
2317
|
//# sourceMappingURL=cli.js.map
|