@alva-ai/toolkit 0.2.1 → 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 +28 -0
- package/dist/browser.global.js +1 -1
- package/dist/browser.global.js.map +1 -1
- package/dist/cli.js +304 -45
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +105 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +55 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.js +105 -7
- 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,10 +553,36 @@ 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;
|
|
585
|
+
arraysBaseUrl;
|
|
500
586
|
viewer_token;
|
|
501
587
|
apiKey;
|
|
502
588
|
_fs;
|
|
@@ -505,13 +591,16 @@ 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;
|
|
603
|
+
this.arraysBaseUrl = config.arraysBaseUrl ?? DEFAULT_ARRAYS_BASE_URL;
|
|
515
604
|
this.viewer_token = config.viewer_token;
|
|
516
605
|
this.apiKey = config.apiKey;
|
|
517
606
|
}
|
|
@@ -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,6 +640,9 @@ 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
647
|
if (!this.viewer_token && !this.apiKey) {
|
|
553
648
|
throw new AlvaError(
|
|
@@ -558,7 +653,8 @@ var AlvaClient = class {
|
|
|
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;
|
|
@@ -893,16 +1032,19 @@ Commands:
|
|
|
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
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`,
|
|
@@ -1170,7 +1317,7 @@ Playbook-draft flags:
|
|
|
1170
1317
|
--name <name> URL-safe playbook name, unique per user (required)
|
|
1171
1318
|
--display-name <name> Human-readable title, max 40 chars (required)
|
|
1172
1319
|
--feeds <json> JSON array of {feed_id, feed_major?} (required)
|
|
1173
|
-
--changelog <text> Release changelog
|
|
1320
|
+
--changelog <text> Release changelog
|
|
1174
1321
|
--description <text> Playbook description
|
|
1175
1322
|
--trading-symbols <json> JSON array of tickers, e.g. '["BTC","ETH"]' (max 50)
|
|
1176
1323
|
|
|
@@ -1238,20 +1385,37 @@ Flags:
|
|
|
1238
1385
|
--partition <name> Partition name for 'partition-summary' (required)
|
|
1239
1386
|
|
|
1240
1387
|
Key partitions:
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
crypto_technical_metrics MA, RSI, MACD, MVRV, SOPR, NUPL (20 modules)
|
|
1244
|
-
equity_fundamentals Income, balance sheet, PE, ROE (31 modules)
|
|
1245
|
-
equity_estimates_and_targets Analyst targets, consensus estimates
|
|
1246
|
-
equity_ownership_and_flow Insider trades, senator trading, institutions
|
|
1247
|
-
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)
|
|
1248
1390
|
technical_indicator_calculation_helpers 50+ pure calculators (RSI, MACD, Bollinger)
|
|
1249
1391
|
|
|
1250
1392
|
Examples:
|
|
1251
1393
|
alva sdk partitions
|
|
1252
|
-
alva sdk partition-summary --partition
|
|
1253
|
-
alva sdk doc --name "@arrays/
|
|
1254
|
-
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>`,
|
|
1255
1419
|
comments: `Usage: alva comments <subcommand> [options]
|
|
1256
1420
|
|
|
1257
1421
|
Manage comments on Alva playbooks. Supports top-level comments and threaded
|
|
@@ -1371,7 +1535,20 @@ Examples:
|
|
|
1371
1535
|
alva trading subscribe --account-id acc_123 --source-username alice --source-feed btc-signals --playbook-id pb_1 --playbook-version v1.0.0
|
|
1372
1536
|
alva trading unsubscribe --subscription-id sub_456
|
|
1373
1537
|
alva trading execute --account-id acc_123 --signal '{"symbol":"BTC","side":"buy","qty":0.1}' --dry-run
|
|
1374
|
-
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`
|
|
1375
1552
|
};
|
|
1376
1553
|
async function handleConfigure(args, deps) {
|
|
1377
1554
|
const flags = parseFlags2(args.slice(1));
|
|
@@ -1396,6 +1573,15 @@ async function handleConfigure(args, deps) {
|
|
|
1396
1573
|
readFile: (path) => fsPromises2.readFile(path, "utf-8")
|
|
1397
1574
|
};
|
|
1398
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
|
+
}
|
|
1399
1585
|
return {
|
|
1400
1586
|
status: "configured",
|
|
1401
1587
|
apiKey: result.apiKey,
|
|
@@ -1481,12 +1667,21 @@ async function dispatch(client, args, meta) {
|
|
|
1481
1667
|
const user = await client.user.me();
|
|
1482
1668
|
const record = user;
|
|
1483
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
|
+
}
|
|
1484
1682
|
const result = {
|
|
1485
1683
|
...record,
|
|
1486
|
-
_meta:
|
|
1487
|
-
profile: meta?.profile ?? "default",
|
|
1488
|
-
endpoint: meta?.baseUrl ?? client.baseUrl
|
|
1489
|
-
}
|
|
1684
|
+
_meta: metaBlock
|
|
1490
1685
|
};
|
|
1491
1686
|
const minVersion = record.toolkit_min_version;
|
|
1492
1687
|
if (typeof minVersion === "string" && version && version !== "dev" && isVersionOlderThan(version, minVersion)) {
|
|
@@ -1697,11 +1892,7 @@ async function dispatch(client, args, meta) {
|
|
|
1697
1892
|
requireFlag(flags, "feeds", "release playbook-draft")
|
|
1698
1893
|
),
|
|
1699
1894
|
trading_symbols: flags["trading-symbols"] ? jsonParse(flags["trading-symbols"]) : void 0,
|
|
1700
|
-
changelog:
|
|
1701
|
-
flags,
|
|
1702
|
-
"changelog",
|
|
1703
|
-
"release playbook-draft"
|
|
1704
|
-
)
|
|
1895
|
+
changelog: flags["changelog"]
|
|
1705
1896
|
});
|
|
1706
1897
|
case "playbook":
|
|
1707
1898
|
return client.release.playbook({
|
|
@@ -1771,6 +1962,28 @@ async function dispatch(client, args, meta) {
|
|
|
1771
1962
|
);
|
|
1772
1963
|
}
|
|
1773
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
|
+
}
|
|
1774
1987
|
case "comments": {
|
|
1775
1988
|
if (!subcommand)
|
|
1776
1989
|
throw new CliUsageError("Missing subcommand for comments", "comments");
|
|
@@ -1809,6 +2022,30 @@ async function dispatch(client, args, meta) {
|
|
|
1809
2022
|
},
|
|
1810
2023
|
parents: jsonParse(requireFlag(flags, "parents", "remix"))
|
|
1811
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
|
+
}
|
|
1812
2049
|
case "screenshot": {
|
|
1813
2050
|
const outFile = requireFlag(flags, "out", "screenshot");
|
|
1814
2051
|
const result = await client.screenshot.capture({
|
|
@@ -1817,6 +2054,12 @@ async function dispatch(client, args, meta) {
|
|
|
1817
2054
|
xpath: flags["xpath"]
|
|
1818
2055
|
});
|
|
1819
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
|
+
}
|
|
1820
2063
|
fs.writeFileSync(outFile, buf);
|
|
1821
2064
|
return { written: outFile, bytes: buf.length };
|
|
1822
2065
|
}
|
|
@@ -1940,6 +2183,27 @@ async function dispatch(client, args, meta) {
|
|
|
1940
2183
|
throw new CliUsageError(`Unknown command: '${group}'`);
|
|
1941
2184
|
}
|
|
1942
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
|
+
}
|
|
1943
2207
|
async function main() {
|
|
1944
2208
|
try {
|
|
1945
2209
|
const rawArgs = process.argv.slice(2);
|
|
@@ -1982,20 +2246,10 @@ async function main() {
|
|
|
1982
2246
|
});
|
|
1983
2247
|
const client = new AlvaClient({
|
|
1984
2248
|
apiKey: config.apiKey,
|
|
1985
|
-
baseUrl: config.baseUrl
|
|
2249
|
+
baseUrl: config.baseUrl,
|
|
2250
|
+
arraysBaseUrl: config.arraysBaseUrl
|
|
1986
2251
|
});
|
|
1987
|
-
const cleanArgs =
|
|
1988
|
-
for (let i = 0; i < rawArgs.length; i++) {
|
|
1989
|
-
const a = rawArgs[i];
|
|
1990
|
-
if (a === "--api-key" || a === "--base-url" || a === "--profile") {
|
|
1991
|
-
i++;
|
|
1992
|
-
continue;
|
|
1993
|
-
}
|
|
1994
|
-
if (a.startsWith("--api-key=") || a.startsWith("--base-url=") || a.startsWith("--profile=")) {
|
|
1995
|
-
continue;
|
|
1996
|
-
}
|
|
1997
|
-
cleanArgs.push(a);
|
|
1998
|
-
}
|
|
2252
|
+
const cleanArgs = stripGlobalFlags(rawArgs);
|
|
1999
2253
|
const result = await dispatch(client, cleanArgs, {
|
|
2000
2254
|
profile: config.profile,
|
|
2001
2255
|
baseUrl: config.baseUrl,
|
|
@@ -2016,6 +2270,10 @@ async function main() {
|
|
|
2016
2270
|
process.stdout.write(Buffer.from(result));
|
|
2017
2271
|
return;
|
|
2018
2272
|
}
|
|
2273
|
+
if (typeof result === "string") {
|
|
2274
|
+
process.stdout.write(result);
|
|
2275
|
+
return;
|
|
2276
|
+
}
|
|
2019
2277
|
if (result !== void 0) {
|
|
2020
2278
|
process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
2021
2279
|
}
|
|
@@ -2053,6 +2311,7 @@ export {
|
|
|
2053
2311
|
CLI_VERSION,
|
|
2054
2312
|
dispatch,
|
|
2055
2313
|
handleConfigure,
|
|
2056
|
-
isVersionOlderThan
|
|
2314
|
+
isVersionOlderThan,
|
|
2315
|
+
stripGlobalFlags
|
|
2057
2316
|
};
|
|
2058
2317
|
//# sourceMappingURL=cli.js.map
|