@datarails-ai/dr-cli 1.6.105 → 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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 1,
3
- "cliVersion": "1.6.105",
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
  {
@@ -239,7 +239,11 @@ area's gotchas.
239
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`.
240
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.
241
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.
242
- - `functions list|get|create|update|delete|set-filters` — a function's **definition** only.
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.
243
247
  - _`set-filters <id> --file <json> [--confirm]` is the **only** way to author a
244
248
  function's row-level filters (create/update don't touch them). FULL REPLACE —
245
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
- **not** the live value. Live function values are computed in Excel via
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datarails-ai/dr-cli",
3
- "version": "1.6.105",
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.2",
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",