@datarails-ai/dr-cli 1.6.104 → 1.6.106
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 +964 -235
- package/dist/scopes-map.json +21 -1
- package/dist/skills/dr-cli/SKILL.md +14 -5
- package/dist/skills/dr-cli/reference/metrics.md +73 -3
- package/dist/skills/dr-switch-user/SKILL.md +2 -1
- package/package.json +2 -2
package/dist/scopes-map.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 1,
|
|
3
|
-
"cliVersion": "1.6.
|
|
3
|
+
"cliVersion": "1.6.106",
|
|
4
4
|
"_contract": "Resolve a command path through `aliases` (canonical prefix + alias segment -> canonical path) before any lookup. A path listed in `pendingCommands`, or whose first segment is a key of `pending`, is UNDECIDED, not unrestricted: fail closed or skip it, and never read a path's absence from `commands` as 'no requirement'. An entry carrying `denied` is UNAVAILABLE to any AGENT-SCOPED credential — one whose `scopes` claim carries at least one `resource:action` entry; a claim that is absent, empty, capability-only or wholly unparseable is UNRESTRICTED, and this mark does not apply to it — whatever else that entry says: it is not a ceiling and it is not always-available, its `denied.reason` says why and `denied.until` names the ticket that lifts it, and the absence of `requires` on it must NEVER be read as 'no requirement'. Only an entry in `commands` with an empty `requires` means always-available.",
|
|
5
5
|
"commands": {
|
|
6
6
|
"login": {
|
|
@@ -739,6 +739,26 @@
|
|
|
739
739
|
}
|
|
740
740
|
]
|
|
741
741
|
},
|
|
742
|
+
"functions data": {
|
|
743
|
+
"requires": [
|
|
744
|
+
{
|
|
745
|
+
"resource": "tables",
|
|
746
|
+
"action": "read"
|
|
747
|
+
}
|
|
748
|
+
]
|
|
749
|
+
},
|
|
750
|
+
"functions drilldown": {
|
|
751
|
+
"requires": [
|
|
752
|
+
{
|
|
753
|
+
"resource": "tables",
|
|
754
|
+
"action": "read"
|
|
755
|
+
},
|
|
756
|
+
{
|
|
757
|
+
"resource": "dashboards",
|
|
758
|
+
"action": "read"
|
|
759
|
+
}
|
|
760
|
+
]
|
|
761
|
+
},
|
|
742
762
|
"functions delete": {
|
|
743
763
|
"requires": [
|
|
744
764
|
{
|
|
@@ -66,16 +66,21 @@ per server can be logged in at once.
|
|
|
66
66
|
required unless a credential file already names the server; don't run the
|
|
67
67
|
piped form under shell tracing or command logging). Never pass the key as an
|
|
68
68
|
argument or paste it into chat. `dr` exchanges it for a JWT itself, so no
|
|
69
|
-
re-login is ever needed while the key is live
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
re-login is ever needed while the key is live — and `login --api-key` does that
|
|
70
|
+
exchange **at login** and stores the JWT, so `whoami` and the next command work
|
|
71
|
+
right away. Keys come from an operator today (no self-service command yet).
|
|
72
|
+
`login-as` cannot run from an API-key identity.
|
|
72
73
|
- `dr login-as <email> --server US` — impersonate a user, **JWT only, no
|
|
73
74
|
browser**. Needs an operator `login` first; stores a switchable identity you
|
|
74
75
|
then target with `--account <email>`. `--as <operator-email>` picks the
|
|
75
76
|
operator if several are stored; `--user-id <n>` skips the email lookup.
|
|
76
77
|
Refreshes/auto-remints silently — no re-prompt until the operator expires.
|
|
77
78
|
- `dr whoami --server US` — confirm who/where you are. Offline (decodes the local
|
|
78
|
-
JWT, no network)
|
|
79
|
+
JWT, no network) — **except** an API-key credential holding no token its current
|
|
80
|
+
key minted (a key written straight into a session file — e.g. a managed-agent
|
|
81
|
+
session — or a key rotated since its token was stored), which `whoami` exchanges
|
|
82
|
+
once to obtain one and saves, so it works even as the very first command.
|
|
83
|
+
**Always sanity-check after login or a server switch.**
|
|
79
84
|
Shows `Impersonated by:` for a `login-as` identity, and a `Scope:` row for
|
|
80
85
|
every identity (see below).
|
|
81
86
|
- `dr logout --server US` / `dr logout --all`.
|
|
@@ -234,7 +239,11 @@ area's gotchas.
|
|
|
234
239
|
- `metrics suggestions list|refresh` + `metrics dimensions suggestions list|refresh` — AI suggestion agents (list shows suggestions + `last_run` status; `refresh` triggers a run, `--wait [--timeout <s>]` polls to completion). Gated per-org by Unleash flags; a successful `metrics migrate` auto-triggers both agents, so a 409 from `refresh` right after usually means it's already running — check `list`.
|
|
235
240
|
- `metrics suggestions profile` — read-only: profiles every table and returns, per table, the `reporting_axis` (WHICH date column a BASE metric should bucket by, with `chosen_by` naming the rule), `row_grain.reads_as` (`movements` -> time_aggregation SUM, `balances` -> EOP), candidate `measures`, `categoricals`, and the metrics already defined there. Use this BEFORE proposing any metric: `date_field` cannot be read off the payload (no field marks the reporting column) and guessing it produces a silently wrong number that passes validation. `reporting_axis: null` and `reads_as: "unknown"` are real answers - do not substitute a guess. All measure statistics are SAMPLED from storage-ordered windows and named `sampled_*`; there is deliberately no sum/avg. Needs no Unleash flag. ~30s and ~230 requests on a 43-table org.
|
|
236
241
|
- `metrics dimensions suggestions profile` — read-only: profiles every table/field and returns scored candidate dimension groups (value-overlap grouping, existing-dimension dedupe, machine-readable rejection reasons) in ONE call. Use this instead of looping `templates distinct` per field when reasoning about what dimensions an org should have. Needs no Unleash flag. `--json` for the payload, `--out <file>` when only `summary`/`groups` matter, `--suppression <file>` when you already hold the existing-dimension and dismissed lists. Also emits `near_misses` — pairs just under the merge threshold, for you to judge rather than silently dropped.
|
|
237
|
-
- `functions list|get|create|update|delete|set-filters` — a function's **definition
|
|
242
|
+
- `functions list|get|create|update|delete|set-filters` — a function's **definition**.
|
|
243
|
+
- `functions data <id> --filter "F=V1,V2" --date "Reporting Date=2025-01-31" [--agg YTD]` — the
|
|
244
|
+
function's **live value**, computed by the same endpoint the Excel add-in uses for
|
|
245
|
+
`DR.GET`/`DR.YTD`; `functions drilldown <id> … [--out rows.csv]` — the rows behind it.
|
|
246
|
+
`create`/`update --date-field <Date field>` is required for YTD/QTD/MTD to work.
|
|
238
247
|
- _`set-filters <id> --file <json> [--confirm]` is the **only** way to author a
|
|
239
248
|
function's row-level filters (create/update don't touch them). FULL REPLACE —
|
|
240
249
|
an empty array clears all; dimension `values` are a plain list, date filters
|
|
@@ -478,11 +478,10 @@ dr metrics dimensions suggestions profile -s DEV --account support@acme.com --js
|
|
|
478
478
|
51-table org. Read `summary.empty_unverified` as "at least this many
|
|
479
479
|
fields' emptiness is unproven", not as an exact census.
|
|
480
480
|
|
|
481
|
-
## Functions (DR.GET definitions)
|
|
481
|
+
## Functions (DR.GET definitions and values)
|
|
482
482
|
|
|
483
483
|
- `functions list`, `functions get <id>` — `get` returns the **definition**,
|
|
484
|
-
|
|
485
|
-
`DR.GET(...)` through the add-in and are not exposed by this CLI.
|
|
484
|
+
not the value (for the value see `functions data` below).
|
|
486
485
|
- The core row is `id / name / agg / template / value_field`; below it `get`
|
|
487
486
|
prints a **FILTERS** section (one row per persisted filter: `field`, `name`,
|
|
488
487
|
`type`, `excluded`, `values`) and the **default agg date field** when set.
|
|
@@ -492,6 +491,18 @@ dr metrics dimensions suggestions profile -s DEV --account support@acme.com --js
|
|
|
492
491
|
blob (owned by the add-in), shown verbatim as compact JSON — read it there
|
|
493
492
|
rather than asking the customer to re-check the UI.
|
|
494
493
|
- `functions create`, `functions update`, `functions delete` (two-step confirm).
|
|
494
|
+
- `--date-field <id|name>` (create and update) sets the function's **default
|
|
495
|
+
aggregation date field** (must be a Date field of the template) and sends the
|
|
496
|
+
platform's default per-period roll-up config (every period by month, `sum`,
|
|
497
|
+
end-of-period — what UI-created functions carry; a function needing MTD by
|
|
498
|
+
day must be adjusted in the UI). **Without it `DR.YTD`/`QTD`/`MTD`/…
|
|
499
|
+
do not work for the function anywhere** — `functions data --agg YTD` answers
|
|
500
|
+
HTTP 400 `{"DateAgg":[…]}` and the xlsx auto-calculate engine fails outright.
|
|
501
|
+
`create` without it prints a one-line warning on stderr. A later
|
|
502
|
+
`update`/`set-filters` full PUT keeps the date field (verified) — so
|
|
503
|
+
`update --template <id>` on a function that has one is **refused unless
|
|
504
|
+
`--date-field` is passed too** (the old field belongs to the old table, and
|
|
505
|
+
the server checks only its type).
|
|
495
506
|
- `functions set-filters <id> --file <json> [--confirm]` — **the only way to
|
|
496
507
|
author a function's filters** (`create`/`update` don't touch them). **FULL
|
|
497
508
|
REPLACE**: the server deletes every existing filter and recreates from the
|
|
@@ -505,6 +516,65 @@ dr metrics dimensions suggestions profile -s DEV --account support@acme.com --js
|
|
|
505
516
|
`--confirm`; internally a read-modify-write PUT that preserves the core fields
|
|
506
517
|
and calculated-value links.
|
|
507
518
|
|
|
519
|
+
### Live values: `functions data`
|
|
520
|
+
|
|
521
|
+
`functions data <id> [--filter "NAME=V1,V2"]… [--date "NAME=DATE[,DATE]"]… [--agg DEFAULT|YTD|YTG|QTD|QTG|MTD|MTG] [--json]`
|
|
522
|
+
evaluates the function through `PUT /api/functions/<id>/data/v2` — the endpoint
|
|
523
|
+
the Excel add-in calls for `DR.GET` (`--agg DEFAULT`) and `DR.YTD`/… — so the
|
|
524
|
+
number is the one Excel shows, with the function's own filters always applied
|
|
525
|
+
(a `--filter` can only narrow them, never override).
|
|
526
|
+
|
|
527
|
+
- Fields are named (or given by id) and resolved on the function's template;
|
|
528
|
+
the add-in's canonical field name goes on the wire. An unknown field fails
|
|
529
|
+
client-side with the list of valid fields.
|
|
530
|
+
- **Dates.** The endpoint wants **Excel serial numbers** (2025-01-31 = 45688);
|
|
531
|
+
epoch seconds and ISO strings are not rejected server-side, they silently
|
|
532
|
+
return nothing. The CLI converts: on a Date field (via `--date` or `--filter`)
|
|
533
|
+
pass `YYYY-MM-DD`, `M/D/YYYY`, an ISO datetime, a serial, or epoch seconds.
|
|
534
|
+
A bare month (`2025-06`) is **refused** — tables store a specific day
|
|
535
|
+
(usually month-END), so a month's 1st would match nothing (DEFAULT) or stop a
|
|
536
|
+
month short (YTD). Pass the stored day, e.g. `2025-06-30`.
|
|
537
|
+
- Several values on one field return **one row per value combination**; the
|
|
538
|
+
table shows each field's key (serials rendered back as dates) and `VALUE`
|
|
539
|
+
(rounded to 4 decimals for display; `--json` is the server body verbatim).
|
|
540
|
+
- No row at all prints `(no data: nothing matches these filters)` — a real
|
|
541
|
+
answer (unknown value, or the function's own filter excludes it), not an error.
|
|
542
|
+
- Errors: a per-query `error.msg` (e.g. "Field X is not related to function")
|
|
543
|
+
and any non-2xx exit non-zero; an HTTP 400 such as
|
|
544
|
+
`{"DateAgg":["Function N has no default aggregation date field"]}` is shown
|
|
545
|
+
verbatim with the `--date-field` fix. Under `--json` the body is printed first.
|
|
546
|
+
|
|
547
|
+
### Rows behind a value: `functions drilldown`
|
|
548
|
+
|
|
549
|
+
`functions drilldown <id> [--filter …]… [--exclude …]… [--date …]… [--agg …] [--columns a,b] [--limit 20] [--out rows.csv] [--csv] [--json]`
|
|
550
|
+
calls `PUT /api/functions/<id>/drilldown/v4` with the same filters (as the
|
|
551
|
+
add-in's filter objects, field id + type resolved from the template).
|
|
552
|
+
|
|
553
|
+
- Prints `N rows × M columns`, the function's own aggregate over those rows
|
|
554
|
+
(`SUM(Amount) over these rows: …` — equals `functions data` with the same
|
|
555
|
+
filters), then the first `--limit` rows (0 = all) of the filtered fields and
|
|
556
|
+
the value field, or of `--columns`. Date columns arrive as epoch seconds and
|
|
557
|
+
are shown as dates.
|
|
558
|
+
- Above the server's inline cap (≈ tens of thousands of rows) the answer is
|
|
559
|
+
`too_large_data`. Without `--out` that is an error naming the size; narrow
|
|
560
|
+
with more `--filter`s or add `--out`. With `--out <file.csv>` the CLI takes
|
|
561
|
+
the add-in's **CSV export** path automatically (`export_to_csv` → cache-key
|
|
562
|
+
poll → report download, ~15 s for 25k rows × 215 columns, 20 MB); `--csv`
|
|
563
|
+
forces it. An inline answer with `--out` is written as CSV too (schema
|
|
564
|
+
columns, dates as `YYYY-MM-DD`). `--out` raises the command budget to 300 s
|
|
565
|
+
(`--timeout <s>` overrides).
|
|
566
|
+
- `--json` prints the inline body verbatim (rows plus a trailing
|
|
567
|
+
`{fields, empty_fields}` schema object); with `--out`, a JSON summary
|
|
568
|
+
(`source`, `rows`, `columns`, `aggregate`, `report_id`).
|
|
569
|
+
- **Credential scopes:** a scoped credential (API key) needs `tables:read`
|
|
570
|
+
**and `dashboards:read`** for `drilldown`. The CSV export path polls
|
|
571
|
+
`/api/cache/cache_keys_status` and downloads `/api/dashboards/report/<n>`,
|
|
572
|
+
both of which the server scopes to `dashboards`; without it the export fails
|
|
573
|
+
at the first status poll (error 40301) after the server has started the task.
|
|
574
|
+
The CLI declares `dashboards:read` for every drill-down, inline included,
|
|
575
|
+
because scopes are per command, not per flag. `functions data` needs
|
|
576
|
+
`tables:read` only.
|
|
577
|
+
|
|
508
578
|
## Customer-facing docs (KB)
|
|
509
579
|
|
|
510
580
|
Help Center → the **"Semantic Layer"** category. Find current articles with `dr kb search "metric KPI"` (or
|
|
@@ -92,7 +92,8 @@ Run a single Bash call:
|
|
|
92
92
|
dr whoami --server <X> --account <email> 2>&1 || true
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
-
`whoami` is
|
|
95
|
+
`whoami` is offline (decodes the locally-stored JWT, no network), except that an
|
|
96
|
+
API-key identity holding no token its current key minted is exchanged once.
|
|
96
97
|
Classify the output:
|
|
97
98
|
|
|
98
99
|
| Result | Meaning |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@datarails-ai/dr-cli",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.106",
|
|
4
4
|
"description": "Datarails CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"access": "public"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@datarails-ai/dr-appspace-cli": "0.11.
|
|
20
|
+
"@datarails-ai/dr-appspace-cli": "0.11.3",
|
|
21
21
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
22
22
|
"@napi-rs/keyring": "^1.3.0",
|
|
23
23
|
"commander": "^12.1.0",
|