@lightdash/cli 3.135.2 → 3.136.2

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.
@@ -22,6 +22,7 @@ Users describe features by what they see in the Lightdash editor. Translate:
22
22
  | drill down, click into a chart | `drill-down` | app code opt-in |
23
23
  | drill into a viz data point (reusable visualization) | `viz-drill-down` | app code opt-in |
24
24
  | "ask the AI", one-line takeaway, explain this row | `ai-prompt` | app code opt-in |
25
+ | "investigate this", act on a recommendation, agent digs beyond the page | `instruction-investigations` | app code opt-in |
25
26
  | "share this view", URL that restores state | `url-state` | app code opt-in |
26
27
  | "remember my filters", "keep my inputs", shared comments/targets/notes, "who changed this" | `app-state` | app code opt-in — only when the host has it enabled |
27
28
  | Google Sheets export | `gsheet-export` | app code opt-in |
@@ -208,6 +209,17 @@ order, `sortBy` describes result ordering, `totalColumnCount` exposes truncation
208
209
  plain text. `result` is the object `useLightdash` returns (keep a reference
209
210
  to it even when destructuring), never a rebuilt `{ data, columns }`. Hide the control when `available` is false; trigger from a user
210
211
  action. Full contract in `/app/references/ai-analysis.md`.
212
+ - `instruction-investigations`: `useInvestigation()` returns `{ available,
213
+ investigate, status, explanation, partial, error, canContinue,
214
+ continueInAskAi }`; `investigate({ instruction, sources: [{ result, label }] })`
215
+ sends an author-written brief to the AI agent, which starts from those
216
+ loaded results and may run further read-only semantic-layer queries beyond
217
+ the page. One hook instance per control; the explanation is Markdown and
218
+ the run takes up to a couple of minutes, so show a running state. Hide the
219
+ control when `available` is false; trigger from a user action. Use it for
220
+ "investigate why" actions; keep `ai-prompt` for answers over loaded rows
221
+ only. Full contract in "Agent investigations on demand" in
222
+ `/app/references/ai-analysis.md`.
211
223
  - `shared-ai-commentary`: `useSharedAiCommentary({ selectionKey, prompt,
212
224
  sources, focus? })` saves a generated answer in shared app state keyed to
213
225
  the current selection: the first viewer generates, later viewers of the
@@ -234,6 +234,59 @@ function RevenueTakeaway() {
234
234
  - Trigger `ask` from a user action, or at most once per loaded view. Never on a timer, never per row. Prompts are rate limited per viewer.
235
235
  - Prompts are capped at 2000 characters; write them as instructions to an analyst, and name the audience and the length you want.
236
236
 
237
+ ## Agent investigations on demand (`useInvestigation`)
238
+
239
+ > Use this when the user wants a button or pill that sends a written instruction to the AI **agent** so it can dig into the question using other data in Lightdash — "investigate what drove this", "act on this recommendation", "analyse the drivers" — with the findings shown inside the app. `useAiPrompt` only sees rows the app already loaded; `useInvestigation` runs the same agent as an anomaly Investigate, which can query other explores (read-only) to test drivers.
240
+
241
+ ```tsx
242
+ import { useInvestigation, useLightdash } from '@lightdash/query-sdk';
243
+
244
+ function DriverPill({ recommendation }: { recommendation: string }) {
245
+ // Keep the hook result itself: `sources` needs the object useLightdash
246
+ // returns, not a rebuilt { data, columns, ... }.
247
+ const revenue = useLightdash(revenueByMonth);
248
+ const investigation = useInvestigation();
249
+
250
+ if (!investigation.available || revenue.loading) return null;
251
+
252
+ return (
253
+ <div>
254
+ <button
255
+ disabled={investigation.status === 'running'}
256
+ onClick={() =>
257
+ investigation.investigate({
258
+ instruction: recommendation,
259
+ sources: [{ result: revenue, label: 'Revenue by month' }],
260
+ })
261
+ }
262
+ >
263
+ {investigation.status === 'running'
264
+ ? 'Investigating…'
265
+ : 'Investigate'}
266
+ </button>
267
+ {investigation.explanation && (
268
+ <Markdown>{investigation.explanation}</Markdown>
269
+ )}
270
+ {investigation.partial && (
271
+ <p>Stopped at the query budget; findings may be incomplete.</p>
272
+ )}
273
+ {investigation.error && <p role="alert">{investigation.error}</p>}
274
+ {investigation.canContinue && (
275
+ <button onClick={investigation.continueInAskAi}>
276
+ Continue in Ask AI
277
+ </button>
278
+ )}
279
+ </div>
280
+ );
281
+ }
282
+ ```
283
+
284
+ - One `useInvestigation()` per control; a re-run replaces that control's result. Several pills mean several hook instances.
285
+ - `sources` work exactly as in `useAiPrompt`: pass the object `useLightdash` returns, with an optional `label` the agent sees as the section title. The agent starts from these rows and may run further read-only semantic-layer queries under the viewer's own access.
286
+ - The run takes up to a couple of minutes and the explanation is **Markdown** (the anomaly `InvestigationCard`'s rendering is a good model). Show a clear running state.
287
+ - `available` is false outside a Lightdash host, when the organisation has AI off for data apps, on hosts that predate the capability, or while the viewer has no agent to run with. Hide the control; do not fall back to `useAiPrompt` silently for "investigate" asks — tell the user the host can't run investigations.
288
+ - Trigger `investigate` only from a viewer's click; runs share the organisation's investigation rate limits and daily caps. Instructions are capped at 2000 characters; write them as a brief to an analyst.
289
+
237
290
  ## Saved commentary shared between viewers (`useSharedAiCommentary`)
238
291
 
239
292
  > Use this when the user wants generated commentary to be **saved** — "save the summary for the team", "everyone should see the same commentary", "let people edit the AI text", "keep the narrative with this view". It needs BOTH AI analysis and saved app state available (see the prompt's availability lines); without either, fall back to `useAiPrompt` (no saving) or plain `useSharedAppState` (no generation).
@@ -781,7 +781,7 @@ For any external HTTP API call, read `/app/references/external-apis.md` and use
781
781
 
782
782
  ### AI analysis — executive summary and anomalies
783
783
 
784
- When the user asks for AI analysis, an executive summary, "what changed and why", anomaly callouts, or any AI-generated insight about the data on the page, read `/app/references/ai-analysis.md` and build its **Default build** with the shipped components in `src/components/insights/` (`InsightsSummary`, `InsightMarker` / `insightCellProps`, `InvestigateMenuItem`, `InvestigationCard`): summary block at the top, markers on every query-bound chart, Investigate in every point menu, the investigation card under the chart. A short ask gets the whole set; only a narrower ask ("just a summary") gets a subset. Never rewrite those components. Lightdash runs the analysis over the queries the app already loaded and pushes the result in; the app renders it and never sends rows or keys. The components render nothing when the host has no analysis to offer. For an author-written question over loaded results (a takeaway under a chart, "explain this row"), use `useAiPrompt` from the same reference. When the user wants the summaries written a certain way (language, currency, domain vocabulary), pass it via the `instructions` prop on `InsightsSummary` — see "Author instructions" in the same reference. When the user wants the analysis to run as soon as the app loads, set the `analyseOnLoad` prop on `InsightsSummary` — see "Analyse on load" in the same reference; never set it unasked. When the user wants generated commentary **saved and shared** — "save the summary for the team", "everyone sees the same commentary", "let people edit the AI text" — and the prompt says saved app state is available, use `useSharedAiCommentary` from the same reference ("Saved commentary shared between viewers") instead of `useAiPrompt`; it keys the text to the current selection so later viewers read and edit the saved version instead of regenerating.
784
+ When the user asks for AI analysis, an executive summary, "what changed and why", anomaly callouts, or any AI-generated insight about the data on the page, read `/app/references/ai-analysis.md` and build its **Default build** with the shipped components in `src/components/insights/` (`InsightsSummary`, `InsightMarker` / `insightCellProps`, `InvestigateMenuItem`, `InvestigationCard`): summary block at the top, markers on every query-bound chart, Investigate in every point menu, the investigation card under the chart. A short ask gets the whole set; only a narrower ask ("just a summary") gets a subset. Never rewrite those components. Lightdash runs the analysis over the queries the app already loaded and pushes the result in; the app renders it and never sends rows or keys. The components render nothing when the host has no analysis to offer. For an author-written question over loaded results (a takeaway under a chart, "explain this row"), use `useAiPrompt` from the same reference. For a button that sends an author-written brief to the AI agent so it can investigate using data beyond the page ("investigate what drove this", "act on this recommendation"), use `useInvestigation` from the same reference ("Agent investigations on demand"); `useAiPrompt` cannot look at other explores. When the user wants the summaries written a certain way (language, currency, domain vocabulary), pass it via the `instructions` prop on `InsightsSummary` — see "Author instructions" in the same reference. When the user wants the analysis to run as soon as the app loads, set the `analyseOnLoad` prop on `InsightsSummary` — see "Analyse on load" in the same reference; never set it unasked. When the user wants generated commentary **saved and shared** — "save the summary for the team", "everyone sees the same commentary", "let people edit the AI text" — and the prompt says saved app state is available, use `useSharedAiCommentary` from the same reference ("Saved commentary shared between viewers") instead of `useAiPrompt`; it keys the text to the current selection so later viewers read and edit the saved version instead of regenerating.
785
785
 
786
786
  ## Visual Design
787
787
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightdash/cli",
3
- "version": "3.135.2",
3
+ "version": "3.136.2",
4
4
  "description": "Lightdash CLI tool",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -22,8 +22,8 @@
22
22
  "@actions/core": "1.11.1",
23
23
  "@aws-sdk/credential-providers": "3.995.0",
24
24
  "@casl/ability": "6.8.0",
25
- "@lightdash/common": "3.135.2",
26
- "@lightdash/warehouses": "3.135.2",
25
+ "@lightdash/common": "3.136.2",
26
+ "@lightdash/warehouses": "3.136.2",
27
27
  "@sidvind/better-ajv-errors": "7.0.0",
28
28
  "@types/columnify": "1.5.1",
29
29
  "ajv": "8.18.0",