@grafana/assistant 0.0.15 → 0.0.17
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 +385 -35
- package/dist/components/OpenAssistantButton.d.ts +30 -0
- package/dist/components/OpenAssistantButton.stories.d.ts +9 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/context/base.d.ts +4 -3
- package/dist/context/chat.d.ts +5 -24
- package/dist/context/component.d.ts +38 -0
- package/dist/context/dashboard.d.ts +0 -1
- package/dist/context/datasource.d.ts +8 -4
- package/dist/context/factory.d.ts +22 -10
- package/dist/context/index.d.ts +1 -0
- package/dist/context/label.d.ts +7 -5
- package/dist/context/page.d.ts +1 -0
- package/dist/context/types.d.ts +10 -9
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -1
- package/dist/sidebar.d.ts +4 -0
- package/package.json +12 -2
package/README.md
CHANGED
|
@@ -36,7 +36,9 @@ function MyComponent() {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
return (
|
|
39
|
-
<button onClick={() => openAssistant({
|
|
39
|
+
<button onClick={() => openAssistant({
|
|
40
|
+
origin: 'grafana/panel-data-analyzer',
|
|
41
|
+
prompt: 'Help me analyze data' })}>
|
|
40
42
|
Open Assistant
|
|
41
43
|
</button>
|
|
42
44
|
);
|
|
@@ -49,10 +51,15 @@ function MyComponent() {
|
|
|
49
51
|
import { openAssistant, closeAssistant } from '@grafana/assistant';
|
|
50
52
|
|
|
51
53
|
// Open the assistant with an initial prompt
|
|
52
|
-
openAssistant({ prompt: 'Show me CPU usage over the last hour' });
|
|
54
|
+
openAssistant({ origin: 'grafana/some-feature', prompt: 'Show me CPU usage over the last hour' });
|
|
55
|
+
|
|
56
|
+
// Open the assistant with initial prompt and autoSend set to false
|
|
57
|
+
openAssistant({ origin: 'grafana-datasources/prometheus/some-feature', prompt: 'Help me analyze data', autoSend: false })
|
|
53
58
|
|
|
54
59
|
// Open the assistant without an initial prompt
|
|
55
|
-
openAssistant({
|
|
60
|
+
openAssistant({
|
|
61
|
+
origin: 'grafana-slo-app/some-page',
|
|
62
|
+
});
|
|
56
63
|
|
|
57
64
|
// Close the assistant
|
|
58
65
|
closeAssistant();
|
|
@@ -61,16 +68,14 @@ closeAssistant();
|
|
|
61
68
|
### Using Context with the Assistant
|
|
62
69
|
|
|
63
70
|
```typescript
|
|
64
|
-
import { openAssistant,
|
|
71
|
+
import { openAssistant, createAssistantContextItem } from '@grafana/assistant';
|
|
65
72
|
|
|
66
73
|
// Create context items to provide additional information to the assistant
|
|
67
|
-
const datasourceContext =
|
|
68
|
-
datasourceName: 'My Prometheus',
|
|
74
|
+
const datasourceContext = createAssistantContextItem('datasource', {
|
|
69
75
|
datasourceUid: 'prometheus-uid',
|
|
70
|
-
datasourceType: 'prometheus'
|
|
71
76
|
});
|
|
72
77
|
|
|
73
|
-
const dashboardContext =
|
|
78
|
+
const dashboardContext = createAssistantContextItem('dashboard', {
|
|
74
79
|
dashboardUid: 'dashboard-uid',
|
|
75
80
|
dashboardTitle: 'System Overview',
|
|
76
81
|
folderUid: 'folder-uid',
|
|
@@ -79,9 +84,26 @@ const dashboardContext = createContext('dashboard', {
|
|
|
79
84
|
|
|
80
85
|
// Open the assistant with initial prompt and context
|
|
81
86
|
openAssistant({
|
|
87
|
+
origin: 'grafana/dashboard-page',
|
|
82
88
|
prompt: 'Analyze the CPU metrics from this dashboard',
|
|
83
89
|
context: [datasourceContext, dashboardContext]
|
|
84
90
|
});
|
|
91
|
+
|
|
92
|
+
// Create hidden context for system instructions (won't show in UI pills)
|
|
93
|
+
const systemInstructions = createAssistantContextItem('structured', {
|
|
94
|
+
hidden: true,
|
|
95
|
+
title: 'System Instructions',
|
|
96
|
+
data: {
|
|
97
|
+
instructions: 'When analyzing metrics, always consider seasonal patterns and anomalies',
|
|
98
|
+
preferences: 'Use clear, technical language and provide actionable insights'
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// Include hidden context with visible context
|
|
103
|
+
openAssistant({
|
|
104
|
+
prompt: 'What are the trends in this data?',
|
|
105
|
+
context: [datasourceContext, systemInstructions]
|
|
106
|
+
});
|
|
85
107
|
```
|
|
86
108
|
|
|
87
109
|
### Providing Page-Specific Context
|
|
@@ -89,10 +111,10 @@ openAssistant({
|
|
|
89
111
|
You can register context items that are automatically included when the assistant is opened on pages matching specific URL patterns. The `providePageContext` function returns a setter function that allows you to update the context dynamically:
|
|
90
112
|
|
|
91
113
|
```typescript
|
|
92
|
-
import { providePageContext,
|
|
114
|
+
import { providePageContext, createAssistantContextItem } from '@grafana/assistant';
|
|
93
115
|
|
|
94
116
|
// Create initial context for dashboard pages
|
|
95
|
-
const dashboardContext =
|
|
117
|
+
const dashboardContext = createAssistantContextItem('structured', {
|
|
96
118
|
data: {
|
|
97
119
|
name: 'Dashboard Context',
|
|
98
120
|
pageType: 'dashboard',
|
|
@@ -107,7 +129,7 @@ const setContext = providePageContext('/d/*', [dashboardContext]);
|
|
|
107
129
|
// Later, dynamically update the context based on user interactions or data changes
|
|
108
130
|
setContext([
|
|
109
131
|
dashboardContext,
|
|
110
|
-
|
|
132
|
+
createAssistantContextItem('structured', {
|
|
111
133
|
data: {
|
|
112
134
|
name: 'Panel Context',
|
|
113
135
|
selectedPanel: 'cpu-usage-panel',
|
|
@@ -118,6 +140,17 @@ setContext([
|
|
|
118
140
|
|
|
119
141
|
// Clean up when no longer needed
|
|
120
142
|
setContext.unregister();
|
|
143
|
+
|
|
144
|
+
// Example: Provide hidden system instructions for explore pages
|
|
145
|
+
providePageContext('/explore', [
|
|
146
|
+
createAssistantContextItem('structured', {
|
|
147
|
+
hidden: true,
|
|
148
|
+
title: 'Additional instructions',
|
|
149
|
+
data: {
|
|
150
|
+
'System Instructions': 'When working with explore queries, always validate the time range and check for data availability. Suggest using recording rules for expensive queries.',
|
|
151
|
+
},
|
|
152
|
+
}),
|
|
153
|
+
]);
|
|
121
154
|
```
|
|
122
155
|
|
|
123
156
|
### Using Page Context in React Components
|
|
@@ -125,10 +158,10 @@ setContext.unregister();
|
|
|
125
158
|
For React components, use the `useProvidePageContext` hook which automatically handles cleanup:
|
|
126
159
|
|
|
127
160
|
```typescript
|
|
128
|
-
import { useProvidePageContext,
|
|
161
|
+
import { useProvidePageContext, createAssistantContextItem } from '@grafana/assistant';
|
|
129
162
|
|
|
130
163
|
function DashboardComponent() {
|
|
131
|
-
const dashboardContext =
|
|
164
|
+
const dashboardContext = createAssistantContextItem('structured', {
|
|
132
165
|
data: {
|
|
133
166
|
name: 'Dashboard Context',
|
|
134
167
|
pageType: 'dashboard'
|
|
@@ -142,7 +175,7 @@ function DashboardComponent() {
|
|
|
142
175
|
const handlePanelSelect = (panelId: string) => {
|
|
143
176
|
setContext([
|
|
144
177
|
dashboardContext,
|
|
145
|
-
|
|
178
|
+
createAssistantContextItem('structured', {
|
|
146
179
|
data: {
|
|
147
180
|
name: 'Panel Context',
|
|
148
181
|
selectedPanel: panelId
|
|
@@ -173,22 +206,20 @@ function MyComponent() {
|
|
|
173
206
|
|
|
174
207
|
### Creating Context Items
|
|
175
208
|
|
|
176
|
-
The `
|
|
209
|
+
The `createAssistantContextItem` function allows you to create structured context items that provide the assistant with additional information about your Grafana resources.
|
|
177
210
|
|
|
178
211
|
```typescript
|
|
179
|
-
import {
|
|
212
|
+
import { createAssistantContextItem } from '@grafana/assistant';
|
|
180
213
|
|
|
181
214
|
// Create a datasource context
|
|
182
|
-
const datasourceContext =
|
|
183
|
-
datasourceName: 'Production Prometheus',
|
|
215
|
+
const datasourceContext = createAssistantContextItem('datasource', {
|
|
184
216
|
datasourceUid: 'prom-123',
|
|
185
|
-
datasourceType: 'prometheus',
|
|
186
217
|
title: 'Main Datasource', // Optional custom title
|
|
187
218
|
icon: 'database' // Optional custom icon
|
|
188
219
|
});
|
|
189
220
|
|
|
190
221
|
// Create a dashboard context
|
|
191
|
-
const dashboardContext =
|
|
222
|
+
const dashboardContext = createAssistantContextItem('dashboard', {
|
|
192
223
|
dashboardUid: 'dash-456',
|
|
193
224
|
dashboardTitle: 'Application Overview',
|
|
194
225
|
folderUid: 'folder-789',
|
|
@@ -196,14 +227,14 @@ const dashboardContext = createContext('dashboard', {
|
|
|
196
227
|
});
|
|
197
228
|
|
|
198
229
|
// Create a label context
|
|
199
|
-
const labelContext =
|
|
230
|
+
const labelContext = createAssistantContextItem('label_name', {
|
|
200
231
|
datasourceUid: 'prom-123',
|
|
201
232
|
datasourceType: 'prometheus',
|
|
202
233
|
labelName: 'service'
|
|
203
234
|
});
|
|
204
235
|
|
|
205
236
|
// Create a label value context
|
|
206
|
-
const labelValueContext =
|
|
237
|
+
const labelValueContext = createAssistantContextItem('label_value', {
|
|
207
238
|
datasourceUid: 'prom-123',
|
|
208
239
|
datasourceType: 'prometheus',
|
|
209
240
|
labelName: 'service',
|
|
@@ -211,13 +242,13 @@ const labelValueContext = createContext('label_value', {
|
|
|
211
242
|
});
|
|
212
243
|
|
|
213
244
|
// Create a folder context
|
|
214
|
-
const folderContext =
|
|
245
|
+
const folderContext = createAssistantContextItem('dashboard_folder', {
|
|
215
246
|
folderUid: 'folder-789',
|
|
216
247
|
folderTitle: 'Production Dashboards'
|
|
217
248
|
});
|
|
218
249
|
|
|
219
250
|
// Create structured data context
|
|
220
|
-
const structuredContext =
|
|
251
|
+
const structuredContext = createAssistantContextItem('structured', {
|
|
221
252
|
data: {
|
|
222
253
|
name: 'Custom Data',
|
|
223
254
|
metrics: ['cpu_usage', 'memory_usage'],
|
|
@@ -226,10 +257,172 @@ const structuredContext = createContext('structured', {
|
|
|
226
257
|
});
|
|
227
258
|
|
|
228
259
|
// Create generic context
|
|
229
|
-
const genericContext =
|
|
260
|
+
const genericContext = createAssistantContextItem('unknown', {
|
|
230
261
|
id: 'my-context',
|
|
231
262
|
text: 'Some additional context information'
|
|
232
263
|
});
|
|
264
|
+
|
|
265
|
+
// Create component context for custom React components
|
|
266
|
+
const componentContext = createAssistantContextItem('component', {
|
|
267
|
+
components: {
|
|
268
|
+
MyCustomComponent: MyCustomComponentImplementation,
|
|
269
|
+
AnotherComponent: AnotherComponentImplementation,
|
|
270
|
+
},
|
|
271
|
+
prompt: `
|
|
272
|
+
- When mentioning specific entities, use the your_app_MyCustomComponent with the syntax: <your_app_MyCustomComponent prop1={'value1'} prop2={'value2'} />
|
|
273
|
+
- Custom components must never be wrapped in code blocks (backticks \` or \`\`\`).
|
|
274
|
+
- Always provide all required props when using custom components.
|
|
275
|
+
`,
|
|
276
|
+
namespace: 'your_app', // Optional: Namespace for your components (defaults to 'components')
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
// Create hidden context (useful for system instructions)
|
|
280
|
+
const hiddenInstructions = createAssistantContextItem('structured', {
|
|
281
|
+
hidden: true, // Won't be shown in UI pills but will be sent to the assistant
|
|
282
|
+
title: 'Page-specific instructions',
|
|
283
|
+
data: {
|
|
284
|
+
instructions: 'Always provide step-by-step explanations',
|
|
285
|
+
context: 'This is a complex system with multiple dependencies'
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### Registering Custom Components for Assistant Usage
|
|
291
|
+
|
|
292
|
+
The `component` context type allows you to register custom React components that the assistant can use in its responses. This is particularly useful for rendering domain-specific UI elements that enhance the user experience.
|
|
293
|
+
|
|
294
|
+
> **⚠️ Important:** Components must be approved by #grafana-assistant before usage. Please reach out to the Grafana Assistant team for review and approval of your custom components before implementing them in production.
|
|
295
|
+
|
|
296
|
+
#### Method 1: Using provideComponents (Recommended)
|
|
297
|
+
|
|
298
|
+
```typescript
|
|
299
|
+
import { provideComponents } from '@grafana/assistant';
|
|
300
|
+
import MyEntityMention from 'components/MyEntityMentionComponent';
|
|
301
|
+
import MyCustomChart from 'components/MyCustomChartComponent';
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Configure the assistant context for your app plugin.
|
|
305
|
+
* This sets up custom components that will be available to the Grafana Assistant
|
|
306
|
+
* when users are on any page matching the provided pattern.
|
|
307
|
+
*/
|
|
308
|
+
export function configureAssistantContext() {
|
|
309
|
+
provideComponents(
|
|
310
|
+
`
|
|
311
|
+
- When mentioning an entity in text, always use the your_app_MyEntityMention component: <your_app_MyEntityMention name={'entity name here'} type={'entity type here'} />
|
|
312
|
+
- For displaying charts, use the your_app_MyCustomChart component: <your_app_MyCustomChart data={chartData} title={'Chart Title'} />
|
|
313
|
+
- Custom components must never be wrapped in code blocks (backticks \` or \`\`\`).
|
|
314
|
+
`,
|
|
315
|
+
'your_app', // namespace
|
|
316
|
+
{
|
|
317
|
+
MyEntityMention,
|
|
318
|
+
MyCustomChart,
|
|
319
|
+
},
|
|
320
|
+
/.*/ // matches all pages
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
#### Method 2: Using createAssistantContextItem with providePageContext
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
import { createAssistantContextItem, providePageContext } from '@grafana/assistant';
|
|
329
|
+
import MyEntityMention from 'components/MyEntityMentionComponent';
|
|
330
|
+
import MyCustomChart from 'components/MyCustomChartComponent';
|
|
331
|
+
|
|
332
|
+
export function configureAssistantContext() {
|
|
333
|
+
providePageContext(/.*/, [
|
|
334
|
+
createAssistantContextItem('component', {
|
|
335
|
+
components: {
|
|
336
|
+
MyEntityMention,
|
|
337
|
+
MyCustomChart,
|
|
338
|
+
},
|
|
339
|
+
prompt: `
|
|
340
|
+
- When mentioning an entity in text, always use the your_app_MyEntityMention component: <your_app_MyEntityMention name={'entity name here'} type={'entity type here'} />
|
|
341
|
+
- For displaying charts, use the your_app_MyCustomChart component: <your_app_MyCustomChart data={chartData} title={'Chart Title'} />
|
|
342
|
+
- Custom components must never be wrapped in code blocks (backticks \` or \`\`\`).
|
|
343
|
+
`,
|
|
344
|
+
namespace: 'your_app', // Optional: defaults to 'components' if not provided
|
|
345
|
+
}),
|
|
346
|
+
]);
|
|
347
|
+
}
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
**Key Points for Component Context:**
|
|
351
|
+
|
|
352
|
+
- **Approval Required**: ⚠️ Components must be approved by #grafana-assistant before usage
|
|
353
|
+
- **Components**: A record of component names to their React component implementations
|
|
354
|
+
- **Prompt**: Instructions for the assistant on how and when to use these components
|
|
355
|
+
- **Namespace**: A unique identifier for your app's components (e.g., 'your_app', 'datasource'). Optional - defaults to 'components' if not provided
|
|
356
|
+
- **Component Usage**: Components are referenced in assistant responses as `<namespace_ComponentName prop={'value'} />` (note the underscore format)
|
|
357
|
+
- **No Code Blocks**: Custom components should never be wrapped in markdown code blocks
|
|
358
|
+
|
|
359
|
+
**Example Component Implementation:**
|
|
360
|
+
```typescript
|
|
361
|
+
interface MyEntityMentionProps {
|
|
362
|
+
name: string;
|
|
363
|
+
type: string;
|
|
364
|
+
env?: string;
|
|
365
|
+
site?: string;
|
|
366
|
+
namespace?: string;
|
|
367
|
+
properties?: string;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
const MyEntityMention: React.FC<MyEntityMentionProps> = ({ name, type, env, site, namespace, properties }) => {
|
|
371
|
+
return (
|
|
372
|
+
<span
|
|
373
|
+
className="entity-mention"
|
|
374
|
+
data-entity-type={type}
|
|
375
|
+
title={`${type}: ${name}`}
|
|
376
|
+
>
|
|
377
|
+
{name}
|
|
378
|
+
</span>
|
|
379
|
+
);
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
export default MyEntityMention;
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### Using Hidden Context for System Instructions
|
|
386
|
+
|
|
387
|
+
The `hidden` parameter allows you to provide context to the assistant without showing it in the UI pills. This is particularly useful for:
|
|
388
|
+
|
|
389
|
+
- **System instructions**: Provide behavioral guidelines specific to certain pages
|
|
390
|
+
- **Metadata**: Include technical details that might confuse users if shown
|
|
391
|
+
- **Contextual rules**: Add page-specific rules without cluttering the interface
|
|
392
|
+
|
|
393
|
+
Example use cases:
|
|
394
|
+
|
|
395
|
+
```typescript
|
|
396
|
+
// Provide exploration-specific guidelines
|
|
397
|
+
providePageContext('/explore', [
|
|
398
|
+
createAssistantContextItem('structured', {
|
|
399
|
+
hidden: true,
|
|
400
|
+
title: 'Explore Page Guidelines',
|
|
401
|
+
data: {
|
|
402
|
+
instructions: [
|
|
403
|
+
'Always validate time ranges before running queries',
|
|
404
|
+
'Suggest using recording rules for expensive queries',
|
|
405
|
+
'Warn about queries that might impact performance'
|
|
406
|
+
],
|
|
407
|
+
queryLimits: {
|
|
408
|
+
maxTimeRange: '24h',
|
|
409
|
+
suggestedSampleInterval: '1m'
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
})
|
|
413
|
+
]);
|
|
414
|
+
|
|
415
|
+
// Add dashboard-specific context
|
|
416
|
+
providePageContext('/d/*', [
|
|
417
|
+
createAssistantContextItem('structured', {
|
|
418
|
+
hidden: true,
|
|
419
|
+
title: 'Dashboard Instructions',
|
|
420
|
+
data: {
|
|
421
|
+
bestPractices: 'Encourage users to use template variables for flexibility',
|
|
422
|
+
performance: 'Suggest panel caching for slow queries'
|
|
423
|
+
}
|
|
424
|
+
})
|
|
425
|
+
]);
|
|
233
426
|
```
|
|
234
427
|
|
|
235
428
|
### Exposing Functions to the Assistant
|
|
@@ -263,6 +456,52 @@ export const getExtensionConfigs = () => [
|
|
|
263
456
|
];
|
|
264
457
|
```
|
|
265
458
|
|
|
459
|
+
### Using the OpenAssistantButton Component
|
|
460
|
+
|
|
461
|
+
The `OpenAssistantButton` is a pre-built Button component that provides an easy way to add assistant functionality to your UI with a single button click. It automatically checks availability and hides itself if the Assistant is not available.
|
|
462
|
+
|
|
463
|
+
```typescript
|
|
464
|
+
import { OpenAssistantButton, createAssistantContextItem } from '@grafana/assistant';
|
|
465
|
+
|
|
466
|
+
function MyDashboard() {
|
|
467
|
+
const dashboardContext = createAssistantContextItem('dashboard', {
|
|
468
|
+
dashboardUid: 'dashboard-123',
|
|
469
|
+
dashboardTitle: 'CPU Metrics Dashboard'
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
return (
|
|
473
|
+
<div>
|
|
474
|
+
<h1>Dashboard</h1>
|
|
475
|
+
|
|
476
|
+
{/* Basic usage */}
|
|
477
|
+
<OpenAssistantButton
|
|
478
|
+
prompt="Help me analyze the CPU usage trends in this dashboard"
|
|
479
|
+
context={[dashboardContext]}
|
|
480
|
+
origin="grafana/dashboard-menu"
|
|
481
|
+
/>
|
|
482
|
+
|
|
483
|
+
{/* Icon-only button */}
|
|
484
|
+
<OpenAssistantButton
|
|
485
|
+
prompt="Show me optimization suggestions"
|
|
486
|
+
iconOnlyButton={true}
|
|
487
|
+
name="Get AI suggestions"
|
|
488
|
+
size="md"
|
|
489
|
+
origin="grafana-datasources/loki/query-editor"
|
|
490
|
+
/>
|
|
491
|
+
|
|
492
|
+
{/* Button without auto-send */}
|
|
493
|
+
<OpenAssistantButton
|
|
494
|
+
prompt="What patterns do you see in the data?"
|
|
495
|
+
autoSend={false}
|
|
496
|
+
name="Ask Assistant"
|
|
497
|
+
size="lg"
|
|
498
|
+
origin="grafana/panel-viewer"
|
|
499
|
+
/>
|
|
500
|
+
</div>
|
|
501
|
+
);
|
|
502
|
+
}
|
|
503
|
+
```
|
|
504
|
+
|
|
266
505
|
## API Reference
|
|
267
506
|
|
|
268
507
|
### React Hooks
|
|
@@ -292,6 +531,47 @@ A React hook for providing page context that automatically cleans up on unmount.
|
|
|
292
531
|
|
|
293
532
|
**Returns:** A setter function to update the context
|
|
294
533
|
|
|
534
|
+
#### `usePageComponents(): Record<string, ComponentImplementation>`
|
|
535
|
+
|
|
536
|
+
A React hook that provides all components available for the current page. This hook automatically updates when the URL changes or when component registrations change.
|
|
537
|
+
|
|
538
|
+
**Returns:** Object containing all components available for the current page, keyed by `namespace_componentName` format.
|
|
539
|
+
|
|
540
|
+
**Example:**
|
|
541
|
+
```typescript
|
|
542
|
+
import { usePageComponents } from '@grafana/assistant';
|
|
543
|
+
|
|
544
|
+
function MyAssistantComponent() {
|
|
545
|
+
const components = usePageComponents();
|
|
546
|
+
|
|
547
|
+
// Access components registered with namespace 'myapp' and component name 'EntityMention'
|
|
548
|
+
const EntityMentionComponent = components['myapp_EntityMention'];
|
|
549
|
+
|
|
550
|
+
return (
|
|
551
|
+
<div>
|
|
552
|
+
Available components: {Object.keys(components).join(', ')}
|
|
553
|
+
</div>
|
|
554
|
+
);
|
|
555
|
+
}
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
### React Components
|
|
559
|
+
|
|
560
|
+
#### `<OpenAssistantButton />`
|
|
561
|
+
|
|
562
|
+
A pre-built React component that renders a button to open the Grafana Assistant with configurable prompt and context.
|
|
563
|
+
|
|
564
|
+
**Parameters:**
|
|
565
|
+
- `prompt: string` - **Required** The initial prompt to display in the assistant
|
|
566
|
+
- `origin: string` - **Required** Origin of the request that opened the assistant. Should be structured using forward slashes with the first part as a namespace. Examples: 'grafana-datasources/prometheus/query-builder', 'grafana-slo-app/slo-editor-overview'
|
|
567
|
+
- `context?: ChatContextItem[]` - Optional context items created with `createAssistantContextItem`
|
|
568
|
+
- `autoSend?: boolean` - Whether to automatically send the initial prompt (defaults to `true`)
|
|
569
|
+
- `title?: string` - Text to display on the button (defaults to `'Analyze with Assistant'`)
|
|
570
|
+
- `size?: 'xs' | 'sm' | 'md' | 'lg'` - Button size (defaults to `'sm'`)
|
|
571
|
+
- `iconOnlyButton?: boolean` - If `true`, renders as an icon-only button with tooltip (defaults to `false`)
|
|
572
|
+
|
|
573
|
+
**Returns:** JSX element or `null` if assistant is not available
|
|
574
|
+
|
|
295
575
|
### Availability Functions
|
|
296
576
|
|
|
297
577
|
#### `isAssistantAvailable(): Observable<boolean>`
|
|
@@ -308,8 +588,10 @@ Opens the Grafana Assistant sidebar.
|
|
|
308
588
|
|
|
309
589
|
**Parameters:**
|
|
310
590
|
- `props: OpenAssistantProps` - Configuration object
|
|
591
|
+
- `origin: string` - Origin of the request that opened the assistant. Should be structured using forward slashes with the first part as a namespace. Examples: 'grafana-datasources/prometheus/query-builder', 'grafana-slo-app/slo-editor-overview'
|
|
311
592
|
- `prompt?: string` - Optional initial prompt to display in the assistant
|
|
312
593
|
- `context?: ChatContextItem[]` - Optional context items to provide additional information to the assistant
|
|
594
|
+
- `autoSend?: boolean` - Optional flag to automatically send the initial prompt
|
|
313
595
|
|
|
314
596
|
#### `closeAssistant(): void`
|
|
315
597
|
|
|
@@ -317,7 +599,7 @@ Closes the Grafana Assistant sidebar.
|
|
|
317
599
|
|
|
318
600
|
### Context Functions
|
|
319
601
|
|
|
320
|
-
#### `
|
|
602
|
+
#### `createAssistantContextItem<T>(type: T, params: ContextTypeParams<T>): ChatContextItem`
|
|
321
603
|
|
|
322
604
|
Creates a context item that can be passed to the assistant to provide additional information.
|
|
323
605
|
|
|
@@ -329,8 +611,10 @@ Creates a context item that can be passed to the assistant to provide additional
|
|
|
329
611
|
- `'label_name'` - Label name context
|
|
330
612
|
- `'label_value'` - Label value context
|
|
331
613
|
- `'structured'` - Custom structured data context
|
|
614
|
+
- `'component'` - Custom React components context
|
|
332
615
|
- `'unknown'` - Generic text context
|
|
333
|
-
- `params` - Parameters specific to the context type (see Context Types section)
|
|
616
|
+
- `params` - Parameters specific to the context type (see Context Types section). All context types support:
|
|
617
|
+
- `hidden?: boolean` - If true, the context item will not be shown in the UI pills but will still be sent to the assistant. This is useful for providing system instructions, behavioral guidelines, or other metadata that shouldn't clutter the user interface.
|
|
334
618
|
|
|
335
619
|
**Returns:** A `ChatContextItem` that can be passed to `openAssistant`
|
|
336
620
|
|
|
@@ -362,6 +646,50 @@ setDashboardContext([...newContext]);
|
|
|
362
646
|
setDashboardContext.unregister();
|
|
363
647
|
```
|
|
364
648
|
|
|
649
|
+
#### `provideComponents(prompt: string, namespace: string, components: Record<string, ComponentImplementation>, urlPattern?: string | RegExp): ((context: ChatContextItem[]) => void) & { unregister: () => void }`
|
|
650
|
+
|
|
651
|
+
A simplified function for providing components to the assistant. This is a convenience wrapper around `providePageContext` specifically for registering components.
|
|
652
|
+
|
|
653
|
+
**Parameters:**
|
|
654
|
+
- `prompt` - Instructions for the assistant on how and when to use these components
|
|
655
|
+
- `namespace` - A unique identifier for your app's components (e.g., 'myapp', 'datasource')
|
|
656
|
+
- `components` - A record of component names to their React component implementations
|
|
657
|
+
- `urlPattern` - Optional URL pattern to match against page URLs (defaults to `/.*/` - matches all pages)
|
|
658
|
+
|
|
659
|
+
**Returns:** A setter function to update the context, with an `unregister` method attached for cleanup
|
|
660
|
+
|
|
661
|
+
**Example:**
|
|
662
|
+
```typescript
|
|
663
|
+
import { provideComponents } from '@grafana/assistant';
|
|
664
|
+
import MyEntityMention from './components/MyEntityMention';
|
|
665
|
+
import MyCustomChart from './components/MyCustomChart';
|
|
666
|
+
|
|
667
|
+
// Register components for all pages
|
|
668
|
+
const setComponents = provideComponents(
|
|
669
|
+
`
|
|
670
|
+
- When mentioning entities, use the myapp_MyEntityMention component: <myapp_MyEntityMention name={'entity-name'} type={'entity-type'} />
|
|
671
|
+
- For charts, use the myapp_MyCustomChart component: <myapp_MyCustomChart data={chartData} title={'Chart Title'} />
|
|
672
|
+
- Custom components must never be wrapped in code blocks.
|
|
673
|
+
`,
|
|
674
|
+
'myapp',
|
|
675
|
+
{
|
|
676
|
+
MyEntityMention,
|
|
677
|
+
MyCustomChart,
|
|
678
|
+
}
|
|
679
|
+
);
|
|
680
|
+
|
|
681
|
+
// Register components only for dashboard pages
|
|
682
|
+
const setDashboardComponents = provideComponents(
|
|
683
|
+
'Use components to enhance dashboard analysis.',
|
|
684
|
+
'dashboard',
|
|
685
|
+
{ MyEntityMention },
|
|
686
|
+
'/d/*'
|
|
687
|
+
);
|
|
688
|
+
|
|
689
|
+
// Cleanup when done
|
|
690
|
+
setComponents.unregister();
|
|
691
|
+
```
|
|
692
|
+
|
|
365
693
|
### Questions System
|
|
366
694
|
|
|
367
695
|
The questions system allows external parties to provide sample prompts with optional context for specific pages. It reuses the existing page context infrastructure but presents a simpler interface focused on questions.
|
|
@@ -382,12 +710,12 @@ Registers questions for specific pages based on URL patterns. Returns a setter f
|
|
|
382
710
|
const setQuestions = provideQuestions("/d/*", [
|
|
383
711
|
{
|
|
384
712
|
prompt: "What metrics are available in this dashboard?",
|
|
385
|
-
context: [], // Optional context items created with `
|
|
713
|
+
context: [], // Optional context items created with `createAssistantContextItem`
|
|
386
714
|
},
|
|
387
715
|
{
|
|
388
716
|
prompt: "How can I optimize the queries in this dashboard?",
|
|
389
717
|
context: [
|
|
390
|
-
|
|
718
|
+
createAssistantContextItem("dashboard", {
|
|
391
719
|
dashboardUid: 'dashboard-uid',
|
|
392
720
|
dashboardTitle: 'System Overview',
|
|
393
721
|
folderUid: 'folder-uid',
|
|
@@ -470,13 +798,15 @@ function AssistantComponent() {
|
|
|
470
798
|
type OpenAssistantProps = {
|
|
471
799
|
prompt?: string;
|
|
472
800
|
context?: ChatContextItem[];
|
|
801
|
+
autoSend?: boolean;
|
|
473
802
|
};
|
|
474
803
|
```
|
|
475
804
|
|
|
476
805
|
Configuration object for opening the assistant.
|
|
477
806
|
|
|
478
807
|
- `prompt` - Optional initial prompt to display
|
|
479
|
-
- `context` - Optional context items to provide
|
|
808
|
+
- `context` - Optional context items to provide
|
|
809
|
+
- `autoSend` - Optional flag to automatically send the initial prompt
|
|
480
810
|
|
|
481
811
|
#### `ChatContextItem`
|
|
482
812
|
|
|
@@ -534,11 +864,10 @@ Represents a registered questions mapping.
|
|
|
534
864
|
|
|
535
865
|
```typescript
|
|
536
866
|
interface CreateDatasourceContextParams {
|
|
537
|
-
datasourceName: string;
|
|
538
867
|
datasourceUid: string;
|
|
539
|
-
datasourceType: string;
|
|
540
868
|
title?: string;
|
|
541
869
|
icon?: IconName;
|
|
870
|
+
hidden?: boolean; // If true, the context item will not be shown in the context pills
|
|
542
871
|
}
|
|
543
872
|
```
|
|
544
873
|
|
|
@@ -552,6 +881,7 @@ interface CreateDashboardContextParams {
|
|
|
552
881
|
folderTitle?: string;
|
|
553
882
|
title?: string;
|
|
554
883
|
icon?: IconName;
|
|
884
|
+
hidden?: boolean; // If true, the context item will not be shown in the context pills
|
|
555
885
|
}
|
|
556
886
|
```
|
|
557
887
|
|
|
@@ -563,6 +893,7 @@ interface CreateFolderContextParams {
|
|
|
563
893
|
folderTitle: string;
|
|
564
894
|
title?: string;
|
|
565
895
|
icon?: IconName;
|
|
896
|
+
hidden?: boolean; // If true, the context item will not be shown in the context pills
|
|
566
897
|
}
|
|
567
898
|
```
|
|
568
899
|
|
|
@@ -575,6 +906,7 @@ interface CreateLabelNameContextParams {
|
|
|
575
906
|
labelName: string;
|
|
576
907
|
title?: string;
|
|
577
908
|
icon?: IconName;
|
|
909
|
+
hidden?: boolean; // If true, the context item will not be shown in the context pills
|
|
578
910
|
}
|
|
579
911
|
```
|
|
580
912
|
|
|
@@ -588,6 +920,7 @@ interface CreateLabelValueContextParams {
|
|
|
588
920
|
labelValue: string;
|
|
589
921
|
title?: string;
|
|
590
922
|
icon?: IconName;
|
|
923
|
+
hidden?: boolean; // If true, the context item will not be shown in the context pills
|
|
591
924
|
}
|
|
592
925
|
```
|
|
593
926
|
|
|
@@ -598,6 +931,20 @@ interface StructuredNodeDataParams {
|
|
|
598
931
|
data: Record<string, any>;
|
|
599
932
|
title?: string;
|
|
600
933
|
icon?: IconName;
|
|
934
|
+
hidden?: boolean; // If true, the context item will not be shown in the context pills
|
|
935
|
+
}
|
|
936
|
+
```
|
|
937
|
+
|
|
938
|
+
#### Component Context Parameters
|
|
939
|
+
|
|
940
|
+
```typescript
|
|
941
|
+
interface CreateComponentContextParams {
|
|
942
|
+
components: Record<string, React.ComponentType<any>>;
|
|
943
|
+
prompt: string;
|
|
944
|
+
namespace?: string; // Optional: defaults to 'components' if not provided
|
|
945
|
+
title?: string;
|
|
946
|
+
icon?: IconName;
|
|
947
|
+
hidden?: boolean; // If true, the context item will not be shown in the context pills
|
|
601
948
|
}
|
|
602
949
|
```
|
|
603
950
|
|
|
@@ -609,6 +956,7 @@ interface NodeDataParams {
|
|
|
609
956
|
text?: string;
|
|
610
957
|
title?: string;
|
|
611
958
|
icon?: IconName;
|
|
959
|
+
hidden?: boolean; // If true, the context item will not be shown in the context pills
|
|
612
960
|
}
|
|
613
961
|
```
|
|
614
962
|
|
|
@@ -689,11 +1037,13 @@ export type LabelNameNodeData;
|
|
|
689
1037
|
export type LabelValueNodeData;
|
|
690
1038
|
export type StructuredNodeData;
|
|
691
1039
|
export type TreeNode;
|
|
1040
|
+
export type ItemDataType;
|
|
692
1041
|
|
|
693
|
-
//
|
|
694
|
-
export
|
|
1042
|
+
// Component types
|
|
1043
|
+
export type ComponentImplementation;
|
|
1044
|
+
export type NamedComponents;
|
|
695
1045
|
```
|
|
696
1046
|
|
|
697
1047
|
## License
|
|
698
1048
|
|
|
699
|
-
Apache-2.0
|
|
1049
|
+
Apache-2.0
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ChatContextItem } from '../context/types';
|
|
3
|
+
import { OpenAssistantProps } from '../sidebar';
|
|
4
|
+
export interface OpenAssistantButtonProps {
|
|
5
|
+
/** Prompt to pass to the openAssistant function. */
|
|
6
|
+
prompt: string;
|
|
7
|
+
/** Origin of the request that opened the assistant. This is used to track the source of the request. Should be a structured string using forward slashes, with the first part as a namespace. Examples: 'grafana-datasources/prometheus/query-builder', 'grafana-slo-app/slo-editor-overview', 'grafana/trace-view-analyzer`. */
|
|
8
|
+
origin: string;
|
|
9
|
+
/** Context to pass to the openAssistant function. Optional, defaults to undefined. Created with `createAssistantContextItem`. */
|
|
10
|
+
context?: ChatContextItem[];
|
|
11
|
+
/** Whether to automatically send the prompt. Optional, defaults to true. */
|
|
12
|
+
autoSend?: boolean;
|
|
13
|
+
/** Text to display on the button. Optional, defaults to 'Analyze with Assistant' */
|
|
14
|
+
title?: string;
|
|
15
|
+
/** Button size, defaults to sm */
|
|
16
|
+
size?: 'xs' | 'sm' | 'md' | 'lg';
|
|
17
|
+
/** If true, the button will be Assistant icon only with name as title. Defaults to false. */
|
|
18
|
+
iconOnlyButton?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A button component that opens the Grafana Assistant with configurable prompt and context.
|
|
22
|
+
*/
|
|
23
|
+
export declare function OpenAssistantButton(props: OpenAssistantButtonProps): React.JSX.Element | null;
|
|
24
|
+
/**
|
|
25
|
+
* Presentational component separated from OpenAssistantButton to avoid hook dependencies in Storybook.
|
|
26
|
+
* It is not exported for users of the package.
|
|
27
|
+
*/
|
|
28
|
+
export declare function OpenAssistantButtonView({ prompt, origin, context, autoSend, title, size, iconOnlyButton, openAssistant, }: OpenAssistantButtonProps & {
|
|
29
|
+
openAssistant: (props: OpenAssistantProps) => void;
|
|
30
|
+
}): React.JSX.Element;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { OpenAssistantButtonView } from './OpenAssistantButton';
|
|
3
|
+
declare const meta: Meta<typeof OpenAssistantButtonView>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<typeof OpenAssistantButtonView>;
|
|
6
|
+
export declare const Default: Story;
|
|
7
|
+
export declare const IconOnly: Story;
|
|
8
|
+
export declare const LargeButton: Story;
|
|
9
|
+
export declare const CustomTitle: Story;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { OpenAssistantButton, type OpenAssistantButtonProps } from './OpenAssistantButton';
|
package/dist/context/base.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { IconName } from '@grafana/ui';
|
|
|
2
2
|
import { type ContextItemData } from './types';
|
|
3
3
|
export interface BaseParams {
|
|
4
4
|
title?: string;
|
|
5
|
+
hidden?: boolean;
|
|
5
6
|
img?: string;
|
|
6
7
|
icon?: IconName;
|
|
7
8
|
}
|
|
@@ -9,9 +10,6 @@ export interface NodeDataParams extends BaseParams {
|
|
|
9
10
|
id: string;
|
|
10
11
|
text?: string;
|
|
11
12
|
}
|
|
12
|
-
export interface StructuredNodeDataParams extends BaseParams {
|
|
13
|
-
data: Record<string, any>;
|
|
14
|
-
}
|
|
15
13
|
export declare class NodeData {
|
|
16
14
|
params: NodeDataParams;
|
|
17
15
|
id: string;
|
|
@@ -19,6 +17,9 @@ export declare class NodeData {
|
|
|
19
17
|
constructor(params: NodeDataParams);
|
|
20
18
|
formatForLLM(codeElementIds?: string[]): ContextItemData;
|
|
21
19
|
}
|
|
20
|
+
export interface StructuredNodeDataParams extends BaseParams {
|
|
21
|
+
data: Record<string, any>;
|
|
22
|
+
}
|
|
22
23
|
export declare class StructuredNodeData {
|
|
23
24
|
params: StructuredNodeDataParams;
|
|
24
25
|
id: string;
|
package/dist/context/chat.d.ts
CHANGED
|
@@ -1,22 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { CreateDatasourceContextParams } from './datasource';
|
|
4
|
-
import { CreateLabelNameContextParams, CreateLabelValueContextParams } from './label';
|
|
5
|
-
import { ChatContextItem, ItemDataType } from './types';
|
|
6
|
-
type ContextTypeMap = {
|
|
7
|
-
[ItemDataType.Datasource]: CreateDatasourceContextParams;
|
|
8
|
-
[ItemDataType.LabelName]: CreateLabelNameContextParams;
|
|
9
|
-
[ItemDataType.LabelValue]: CreateLabelValueContextParams;
|
|
10
|
-
[ItemDataType.Dashboard]: CreateDashboardContextParams;
|
|
11
|
-
[ItemDataType.DashboardFolder]: CreateFolderContextParams;
|
|
12
|
-
[ItemDataType.Structured]: StructuredNodeDataParams;
|
|
13
|
-
[ItemDataType.Unknown]: NodeDataParams;
|
|
14
|
-
};
|
|
15
|
-
/**
|
|
16
|
-
* @deprecated This function is deprecated and will be removed in a future release because it collides with React's context naming.
|
|
17
|
-
* Use createContextItem instead.
|
|
18
|
-
*/
|
|
19
|
-
export declare function createContext<T extends keyof ContextTypeMap>(type: T, params: ContextTypeMap[T]): ChatContextItem;
|
|
1
|
+
import { ContextTypeRegistry } from './factory';
|
|
2
|
+
import { ChatContextItem } from './types';
|
|
20
3
|
/**
|
|
21
4
|
* Creates a new chat context item that can be added to conversations.
|
|
22
5
|
*
|
|
@@ -40,16 +23,14 @@ export declare function createContext<T extends keyof ContextTypeMap>(type: T, p
|
|
|
40
23
|
* // Create a context that will be passed into the function triggering an assistant open
|
|
41
24
|
* openAssistant({
|
|
42
25
|
* ...
|
|
26
|
+
* origin: 'my-feature',
|
|
43
27
|
* context: [
|
|
44
|
-
*
|
|
28
|
+
* createAssistantContextItem('datasource', {
|
|
45
29
|
* datasourceUid: datasource.uid,
|
|
46
|
-
* datasourceName: datasource.name,
|
|
47
|
-
* datasourceType: datasource.type,
|
|
48
30
|
* img: datasource.meta?.info?.logos?.small,
|
|
49
31
|
* }),
|
|
50
32
|
* ],
|
|
51
33
|
* });
|
|
52
34
|
* ```
|
|
53
35
|
*/
|
|
54
|
-
export declare function
|
|
55
|
-
export {};
|
|
36
|
+
export declare function createAssistantContextItem<T extends keyof ContextTypeRegistry>(type: T, params: ContextTypeRegistry[T]['params']): ChatContextItem;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { ComponentType } from 'react';
|
|
2
|
+
import { BaseParams, NodeData } from './base';
|
|
3
|
+
import { type ContextItemData } from './types';
|
|
4
|
+
export type ComponentImplementation = ComponentType<any>;
|
|
5
|
+
export type NamedComponents = Record<string, ComponentImplementation>;
|
|
6
|
+
/**
|
|
7
|
+
* Type used to create a component context item.
|
|
8
|
+
*/
|
|
9
|
+
export interface CreateComponentContextParams extends BaseParams {
|
|
10
|
+
components: Record<string, ComponentType<any>>;
|
|
11
|
+
prompt: string;
|
|
12
|
+
namespace?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare class ComponentNodeData extends NodeData {
|
|
15
|
+
components: Record<string, ComponentType<any>>;
|
|
16
|
+
prompt: string;
|
|
17
|
+
namespace: string;
|
|
18
|
+
constructor(params: CreateComponentContextParams);
|
|
19
|
+
formatForLLM(codeElementIds?: string[]): ContextItemData;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* React hook that provides all components available for the current page.
|
|
23
|
+
* This hook automatically updates when the URL changes or when component registrations change.
|
|
24
|
+
*
|
|
25
|
+
* @returns Object containing all components available for the current page, keyed by namespace.componentName
|
|
26
|
+
*/
|
|
27
|
+
export declare function usePageComponents(): Record<string, ComponentImplementation>;
|
|
28
|
+
/**
|
|
29
|
+
* Provide components to the assistant.
|
|
30
|
+
*
|
|
31
|
+
* @param prompt - The prompt to use for the components.
|
|
32
|
+
* @param namespace - The namespace to use for the components.
|
|
33
|
+
* @param components - The components to provide.
|
|
34
|
+
* @param urlPattern - The URL pattern to match for the components.
|
|
35
|
+
*/
|
|
36
|
+
export declare function provideComponents(prompt: string, namespace: string, components: Record<string, ComponentImplementation>, urlPattern?: string | RegExp): ((context: import("./types").ChatContextItem[]) => void) & {
|
|
37
|
+
unregister: () => void;
|
|
38
|
+
};
|
|
@@ -15,7 +15,6 @@ export declare class DashboardNodeData extends NodeData {
|
|
|
15
15
|
dashboardTitle: string;
|
|
16
16
|
folderUid?: string;
|
|
17
17
|
folderTitle?: string;
|
|
18
|
-
text: string;
|
|
19
18
|
constructor(params: CreateDashboardContextParams);
|
|
20
19
|
formatForLLM(codeElementIds?: string[]): ContextItemData;
|
|
21
20
|
}
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
import { BaseParams, NodeData } from './base';
|
|
2
|
+
import { DatasourceMeta } from './factory';
|
|
2
3
|
import { type ContextItemData } from './types';
|
|
4
|
+
/**
|
|
5
|
+
* Type used to create a datasource context item.
|
|
6
|
+
*
|
|
7
|
+
* All required attributes will be inferred from the datasources uid.
|
|
8
|
+
*/
|
|
3
9
|
export interface CreateDatasourceContextParams extends BaseParams {
|
|
4
|
-
datasourceName: string;
|
|
5
10
|
datasourceUid: string;
|
|
6
|
-
datasourceType: string;
|
|
7
11
|
}
|
|
8
12
|
export declare class DatasourceNodeData extends NodeData {
|
|
9
13
|
datasourceUid: string;
|
|
10
14
|
datasourceType: string;
|
|
11
15
|
datasourceName: string;
|
|
12
|
-
|
|
13
|
-
constructor(params: CreateDatasourceContextParams);
|
|
16
|
+
img?: string;
|
|
17
|
+
constructor(params: CreateDatasourceContextParams & DatasourceMeta);
|
|
14
18
|
formatForLLM(codeElementIds?: string[]): ContextItemData;
|
|
15
19
|
}
|
|
@@ -1,39 +1,51 @@
|
|
|
1
1
|
import { NodeData, NodeDataParams, StructuredNodeData, StructuredNodeDataParams } from './base';
|
|
2
|
+
import { ComponentNodeData, type CreateComponentContextParams } from './component';
|
|
2
3
|
import { DashboardNodeData, FolderNodeData, type CreateDashboardContextParams, type CreateFolderContextParams } from './dashboard';
|
|
3
4
|
import { DatasourceNodeData, type CreateDatasourceContextParams } from './datasource';
|
|
4
5
|
import { LabelNameNodeData, LabelValueNodeData, type CreateLabelNameContextParams, type CreateLabelValueContextParams } from './label';
|
|
5
|
-
|
|
6
|
+
/**
|
|
7
|
+
* registry to handle the type mappings between ItemData type, params and node data
|
|
8
|
+
*/
|
|
9
|
+
export type ContextTypeRegistry = {
|
|
6
10
|
datasource: {
|
|
7
11
|
params: CreateDatasourceContextParams;
|
|
8
|
-
|
|
12
|
+
node: DatasourceNodeData;
|
|
9
13
|
};
|
|
10
14
|
label_name: {
|
|
11
15
|
params: CreateLabelNameContextParams;
|
|
12
|
-
|
|
16
|
+
node: LabelNameNodeData;
|
|
13
17
|
};
|
|
14
18
|
label_value: {
|
|
15
19
|
params: CreateLabelValueContextParams;
|
|
16
|
-
|
|
20
|
+
node: LabelValueNodeData;
|
|
17
21
|
};
|
|
18
22
|
dashboard: {
|
|
19
23
|
params: CreateDashboardContextParams;
|
|
20
|
-
|
|
24
|
+
node: DashboardNodeData;
|
|
21
25
|
};
|
|
22
26
|
dashboard_folder: {
|
|
23
27
|
params: CreateFolderContextParams;
|
|
24
|
-
|
|
28
|
+
node: FolderNodeData;
|
|
25
29
|
};
|
|
26
30
|
structured: {
|
|
27
31
|
params: StructuredNodeDataParams;
|
|
28
|
-
|
|
32
|
+
node: StructuredNodeData;
|
|
33
|
+
};
|
|
34
|
+
component: {
|
|
35
|
+
params: CreateComponentContextParams;
|
|
36
|
+
node: ComponentNodeData;
|
|
29
37
|
};
|
|
30
38
|
unknown: {
|
|
31
39
|
params: NodeDataParams;
|
|
32
|
-
|
|
40
|
+
node: NodeData;
|
|
33
41
|
};
|
|
34
42
|
};
|
|
43
|
+
export type DatasourceMeta = {
|
|
44
|
+
datasourceType: string;
|
|
45
|
+
datasourceName: string;
|
|
46
|
+
img?: string;
|
|
47
|
+
};
|
|
35
48
|
/**
|
|
36
49
|
* Creates context nodes based on type with full type safety using generics
|
|
37
50
|
*/
|
|
38
|
-
export declare function createContextByType<T extends keyof
|
|
39
|
-
export {};
|
|
51
|
+
export declare function createContextByType<T extends keyof ContextTypeRegistry>(type: T, params: ContextTypeRegistry[T]['params']): ContextTypeRegistry[T]['node'];
|
package/dist/context/index.d.ts
CHANGED
package/dist/context/label.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { BaseParams, NodeData } from './base';
|
|
2
|
+
import { DatasourceMeta } from './factory';
|
|
2
3
|
import { type ContextItemData } from './types';
|
|
3
4
|
export interface CreateLabelNameContextParams extends BaseParams {
|
|
4
5
|
datasourceUid: string;
|
|
5
|
-
datasourceType: string;
|
|
6
6
|
labelName: string;
|
|
7
7
|
}
|
|
8
8
|
export interface CreateLabelValueContextParams extends CreateLabelNameContextParams {
|
|
@@ -11,17 +11,19 @@ export interface CreateLabelValueContextParams extends CreateLabelNameContextPar
|
|
|
11
11
|
export declare class LabelNameNodeData extends NodeData {
|
|
12
12
|
datasourceUid: string;
|
|
13
13
|
datasourceType: string;
|
|
14
|
+
datasourceName: string;
|
|
14
15
|
labelName: string;
|
|
15
|
-
|
|
16
|
-
constructor(params: CreateLabelNameContextParams);
|
|
16
|
+
img?: string;
|
|
17
|
+
constructor(params: CreateLabelNameContextParams & DatasourceMeta);
|
|
17
18
|
formatForLLM(codeElementIds?: string[]): ContextItemData;
|
|
18
19
|
}
|
|
19
20
|
export declare class LabelValueNodeData extends NodeData {
|
|
20
21
|
datasourceUid: string;
|
|
21
22
|
datasourceType: string;
|
|
23
|
+
datasourceName: string;
|
|
22
24
|
labelName: string;
|
|
23
25
|
labelValue: string;
|
|
24
|
-
|
|
25
|
-
constructor(params: CreateLabelValueContextParams);
|
|
26
|
+
img?: string;
|
|
27
|
+
constructor(params: CreateLabelValueContextParams & DatasourceMeta);
|
|
26
28
|
formatForLLM(codeElementIds?: string[]): ContextItemData;
|
|
27
29
|
}
|
package/dist/context/page.d.ts
CHANGED
|
@@ -28,4 +28,5 @@ export declare function providePageContext(urlPattern: string | RegExp, initialC
|
|
|
28
28
|
export declare function useProvidePageContext(urlPattern: string | RegExp, initialContext?: ChatContextItem[]): (context: ChatContextItem[]) => void;
|
|
29
29
|
export declare function usePageContext(options?: {
|
|
30
30
|
allowQuestions: boolean;
|
|
31
|
+
allowComponents: boolean;
|
|
31
32
|
}): ChatContextItem[];
|
package/dist/context/types.d.ts
CHANGED
|
@@ -1,19 +1,12 @@
|
|
|
1
1
|
import { IconName } from '@grafana/ui';
|
|
2
|
+
import { ComponentType } from 'react';
|
|
2
3
|
export interface BaseItemData {
|
|
3
4
|
name: string;
|
|
4
5
|
text: string;
|
|
5
6
|
}
|
|
6
7
|
export interface UnknownItemData extends BaseItemData {
|
|
7
8
|
}
|
|
8
|
-
export
|
|
9
|
-
Unknown = "unknown",
|
|
10
|
-
Datasource = "datasource",
|
|
11
|
-
LabelName = "label_name",
|
|
12
|
-
LabelValue = "label_value",
|
|
13
|
-
Dashboard = "dashboard",
|
|
14
|
-
DashboardFolder = "dashboard_folder",
|
|
15
|
-
Structured = "structured"
|
|
16
|
-
}
|
|
9
|
+
export type ItemDataType = 'unknown' | 'datasource' | 'label_name' | 'label_value' | 'dashboard' | 'dashboard_folder' | 'structured' | 'component';
|
|
17
10
|
export interface ContextItemData {
|
|
18
11
|
type: ItemDataType;
|
|
19
12
|
codeElementIds?: string[];
|
|
@@ -33,11 +26,14 @@ export interface TreeNode {
|
|
|
33
26
|
export interface DatasourceItemData extends BaseItemData {
|
|
34
27
|
uid: string;
|
|
35
28
|
type: string;
|
|
29
|
+
img?: string;
|
|
36
30
|
}
|
|
37
31
|
export interface LabelNameItemData extends BaseItemData {
|
|
38
32
|
datasourceUid: string;
|
|
39
33
|
datasourceType: string;
|
|
34
|
+
datasourceName: string;
|
|
40
35
|
labelName: string;
|
|
36
|
+
img?: string;
|
|
41
37
|
}
|
|
42
38
|
export interface LabelValueItemData extends LabelNameItemData {
|
|
43
39
|
labelValue: string;
|
|
@@ -52,6 +48,11 @@ export interface FolderItemData extends BaseItemData {
|
|
|
52
48
|
folderUid: string;
|
|
53
49
|
folderTitle: string;
|
|
54
50
|
}
|
|
51
|
+
export interface ComponentItemData extends BaseItemData {
|
|
52
|
+
components: Record<string, ComponentType<any>>;
|
|
53
|
+
prompt: string;
|
|
54
|
+
namespace: string;
|
|
55
|
+
}
|
|
55
56
|
export interface ChatContextItem {
|
|
56
57
|
node: TreeNode;
|
|
57
58
|
occurrences: string[];
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { createAssistantContextItem, ChatContextItem, ComponentNodeData, DashboardNodeData, DatasourceNodeData, FolderNodeData, ItemDataType, LabelNameNodeData, LabelValueNodeData, StructuredNodeData, TreeNode, providePageContext, useProvidePageContext, PageContextRegistration, usePageContext, provideQuestions, useProvideQuestions, useQuestions, Question, QuestionRegistration, usePageComponents, provideComponents, ComponentImplementation, NamedComponents, } from './context/index';
|
|
2
2
|
export * from './functions';
|
|
3
3
|
export * from './hook';
|
|
4
4
|
export * from './plugin';
|
|
5
5
|
export * from './sidebar';
|
|
6
|
+
export * from './components';
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(()=>{"use strict";var e,t={d:(e,a)=>{for(var n in a)t.o(a,n)&&!t.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:a[n]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},a={};function n(e){let t=5381;for(let a=0;a<e.length;a++)t=(t<<5)+t+e.charCodeAt(a);return(t>>>0).toString(16)}t.r(a),t.d(a,{CALLBACK_EXTENSION_POINT:()=>C,DashboardNodeData:()=>o,DatasourceNodeData:()=>d,FolderNodeData:()=>i,ItemDataType:()=>e,LabelNameNodeData:()=>l,LabelValueNodeData:()=>u,StructuredNodeData:()=>r,closeAssistant:()=>M,createContext:()=>f,createContextItem:()=>h,getExposeAssistantFunctionsConfig:()=>F,isAssistantAvailable:()=>V,newFunctionNamespace:()=>A,openAssistant:()=>k,providePageContext:()=>y,provideQuestions:()=>D,useAssistant:()=>R,usePageContext:()=>N,useProvidePageContext:()=>T,useProvideQuestions:()=>S,useQuestions:()=>I}),function(e){e.Unknown="unknown",e.Datasource="datasource",e.LabelName="label_name",e.LabelValue="label_value",e.Dashboard="dashboard",e.DashboardFolder="dashboard_folder",e.Structured="structured"}(e||(e={}));class s{constructor(e){this.params=e,this.text="",this.id=n(e.id)}formatForLLM(t){var a,n;return{type:e.Unknown,codeElementIds:t,data:{name:null!==(a=this.params.text)&&void 0!==a?a:"",text:null!==(n=this.params.text)&&void 0!==n?n:""}}}}class r{constructor(e){this.params=e,this.id=n(JSON.stringify(e.data))}formatForLLM(t){return{type:e.Structured,codeElementIds:t,data:this.params.data}}}class o extends s{constructor(e){super({...e,id:e.dashboardUid}),this.text="",this.dashboardUid=e.dashboardUid,this.dashboardTitle=e.dashboardTitle,this.folderUid=e.folderUid,this.folderTitle=e.folderTitle,this.text=e.dashboardTitle}formatForLLM(t){return{type:e.Dashboard,codeElementIds:t,data:{name:this.dashboardTitle,dashboardUid:this.dashboardUid,dashboardTitle:this.dashboardTitle,folderUid:this.folderUid,folderTitle:this.folderTitle,text:this.text}}}}class i extends s{constructor(e){super({...e,id:e.folderUid}),this.text="",this.folderUid=e.folderUid,this.folderTitle=e.folderTitle,this.text=e.folderTitle}formatForLLM(t){return{type:e.DashboardFolder,codeElementIds:t,data:{name:this.folderTitle,folderUid:this.folderUid,folderTitle:this.folderTitle,text:this.text}}}}class d extends s{constructor(e){super({...e,id:e.datasourceUid}),this.text="",this.datasourceUid=e.datasourceUid,this.datasourceType=e.datasourceType,this.datasourceName=e.datasourceName,this.text=e.datasourceName}formatForLLM(t){return{type:e.Datasource,codeElementIds:t,data:{name:this.datasourceName,uid:this.datasourceUid,type:this.datasourceType,text:this.text}}}}class l extends s{constructor(e){super({...e,id:`${e.datasourceUid}-${e.labelName}`}),this.text="",this.datasourceUid=e.datasourceUid,this.datasourceType=e.datasourceType,this.labelName=e.labelName,this.text=e.labelName}formatForLLM(t){return{type:e.LabelName,codeElementIds:t,data:{name:this.labelName,datasourceUid:this.datasourceUid,datasourceType:this.datasourceType,labelName:this.labelName,text:this.text}}}}class u extends s{constructor(e){super({...e,id:`${e.datasourceUid}-${e.labelName}-${e.labelValue}`}),this.text="",this.datasourceUid=e.datasourceUid,this.datasourceType=e.datasourceType,this.labelName=e.labelName,this.labelValue=e.labelValue,this.text=e.labelValue}formatForLLM(t){return{type:e.LabelValue,codeElementIds:t,data:{name:this.labelValue,datasourceUid:this.datasourceUid,datasourceType:this.datasourceType,labelName:this.labelName,labelValue:this.labelValue,text:this.text}}}}const c={[e.Datasource]:"database",[e.LabelName]:"database",[e.LabelValue]:"database",[e.Dashboard]:"dashboard",[e.DashboardFolder]:"folder",[e.Unknown]:"circle-mono",[e.Structured]:"gf-grid"};function p(t,a){return t===e.Datasource?a.datasourceName:t===e.LabelName?a.labelName:t===e.LabelValue?a.labelValue:t===e.Dashboard?a.dashboardTitle:t===e.DashboardFolder?a.folderTitle:t===e.Structured?a.data.name:"Given Context"}function f(e,t){var a,n;const f=function(e,t){switch(e){case"datasource":return new d(t);case"label_name":return new l(t);case"label_value":return new u(t);case"dashboard":return new o(t);case"dashboard_folder":return new i(t);case"structured":return new r(t);case"unknown":return new s(t);default:return console.error(`Unknown context type: ${e}`),new s(t)}}(e,t);return{node:{id:f.id,name:null!==(a=t.title)&&void 0!==a?a:p(e,t),img:t.img,icon:null!==(n=t.icon)&&void 0!==n?n:c[e],navigable:!1,selectable:!0,data:f},occurrences:[]}}function h(e,t){return f(e,t)}const m=require("@grafana/runtime"),b=require("react"),v=[],x="grafana-assistant:page-context-sync",g="grafana-assistant:page-context-update",w="grafana-assistant:page-context-remove",E="grafana-assistant:location-changed";let L=!1;function y(e,t){const a=v.findIndex((t=>{return a=t.urlPattern,n=e,"string"==typeof a&&"string"==typeof n?a===n:a instanceof RegExp&&n instanceof RegExp&&a.source===n.source&&a.flags===n.flags;var a,n}));let n;-1!==a?(n=v[a],n.context=[...t]):(n={id:`page-context-${Date.now()}-${Math.random().toString(36).slice(2,11)}`,urlPattern:e,context:[...t]},v.push(n)),window.dispatchEvent(new CustomEvent(g,{detail:n})),window.dispatchEvent(new CustomEvent(x,{detail:{registry:v}}));const s=e=>{const t=v.findIndex((e=>e.id===n.id));-1!==t&&(v[t].context=[...e],window.dispatchEvent(new CustomEvent(g,{detail:v[t]})))};return s.unregister=()=>{const e=v.findIndex((e=>e.id===n.id));-1!==e&&(v.splice(e,1),window.dispatchEvent(new CustomEvent(w,{detail:{id:n.id}})))},s}function T(e,t=[]){const a=(0,b.useRef)(void 0),n=(0,b.useRef)(t);return n.current=t,(0,b.useEffect)((()=>(a.current=y(e,n.current),()=>{var e;null===(e=a.current)||void 0===e||e.unregister()})),[e]),(0,b.useEffect)((()=>{a.current&&a.current(t)}),[t]),(0,b.useCallback)((e=>{var t;null===(t=a.current)||void 0===t||t.call(a,e)}),[])}function N(e={allowQuestions:!1}){const[t,a]=(0,b.useState)([]),n=(0,m.useLocationService)(),s=(0,b.useRef)("");return(0,b.useEffect)((()=>{const e=()=>{const e=function(e,t){if(!e)return[];const a=[];for(const n of t)U(e,n.urlPattern)&&a.push(...n.context);return a}(n.getLocation().pathname,v);a(e)},t=()=>{e()},r=t=>{var a;const s=null===(a=t.detail)||void 0===a?void 0:a.pathname;s&&s===n.getLocation().pathname&&e()},o=n.getLocationObservable().subscribe((t=>{const a=t.pathname;a!==s.current&&(s.current=a,function(e){window.dispatchEvent(new CustomEvent(E,{detail:{pathname:e}}))}(a),e())}));return e(),window.addEventListener(x,t),window.addEventListener(g,t),window.addEventListener(w,t),window.addEventListener(E,r),()=>{o.unsubscribe(),window.removeEventListener(x,t),window.removeEventListener(g,t),window.removeEventListener(w,t),window.removeEventListener(E,r)}}),[n]),e.allowQuestions?t:t.filter((e=>{var t;return"question"!==(null===(t=e.node.data)||void 0===t?void 0:t.type)}))}function U(e,t){if(t instanceof RegExp)return t.test(e);if("string"==typeof t){const a=t.replace(/\*\*/g,"\0DOUBLE_STAR\0").replace(/\*/g,"[^/]*").replace(/\u0000DOUBLE_STAR\u0000/g,".*").replace(/\?/g,".");return new RegExp(`^${a}$`).test(e)}return!1}function D(e,t){const a=e=>e.map(((e,t)=>({node:{id:`question-${t}`,name:e.prompt,navigable:!1,selectable:!0,icon:"question-circle",data:{type:"question",prompt:e.prompt,context:e.context||[]}},occurrences:[]}))),n=y(e,a(t)),s=e=>{n(a(e))};return s.unregister=n.unregister,s}function S(e,t=[]){const a=e=>e.map(((e,t)=>({node:{id:`question-${t}`,name:e.prompt,navigable:!1,selectable:!0,icon:"question-circle",data:{type:"question",prompt:e.prompt,context:e.context||[]}},occurrences:[]}))),n=T(e,a(t));return e=>{n(a(e))}}function I(){const e=N({allowQuestions:!0});return P(e)}L||(window.addEventListener(x,(e=>{var t;const a=null===(t=e.detail)||void 0===t?void 0:t.registry;if(a){const e=new Set(v.map((e=>e.id))),t=a.filter((t=>!e.has(t.id)));v.push(...t)}})),window.addEventListener(g,(e=>{const t=e.detail;if(t){const e=v.findIndex((e=>e.id===t.id));-1!==e?v[e]=t:v.push(t)}})),window.addEventListener(w,(e=>{var t;const a=null===(t=e.detail)||void 0===t?void 0:t.id;if(a){const e=v.findIndex((e=>e.id===a));-1!==e&&v.splice(e,1)}})),L=!0);const P=e=>e.filter((e=>{var t;return"question"===(null===(t=e.node.data)||void 0===t?void 0:t.type)})).map((e=>{var t,a;return{prompt:(null===(t=e.node.data)||void 0===t?void 0:t.prompt)||e.node.name,context:(null===(a=e.node.data)||void 0===a?void 0:a.context)||[]}})),C="grafana-assistant-app/callback/v0-alpha";function A(e,t){return{namespace:e,functions:t}}function F(e){return{title:"callback",targets:[C],fn:()=>e.map((e=>({namespace:e.namespace,functions:e.functions})))}}const O=require("rxjs");function V(){if(!m.getObservablePluginLinks)return(0,O.of)(!1);return(0,m.getObservablePluginLinks)({extensionPointId:"grafana/extension-sidebar/v0-alpha"}).pipe((0,O.map)((e=>e.some((e=>"grafana-assistant-app"===e.pluginId&&"Grafana Assistant"===e.title)))))}const q=require("@grafana/data");class $ extends q.BusEventWithPayload{}$.type="open-extension-sidebar";class _ extends q.BusEventBase{}function k(e){!function(e,t,a){const n=new $({pluginId:"grafana-assistant-app",componentTitle:"Grafana Assistant",props:a});(0,m.getAppEvents)().publish(n)}(0,0,{initialPrompt:e.prompt,initialContext:e.context})}function M(){!function(){const e=new _;(0,m.getAppEvents)().publish(e)}()}function R(){const[e,t]=(0,b.useState)(!1);return(0,b.useEffect)((()=>{const e=V().subscribe((e=>t(e)));return()=>{e.unsubscribe()}}),[]),[e,e?k:void 0,e?M:void 0]}_.type="close-extension-sidebar",module.exports=a})();
|
|
1
|
+
(()=>{"use strict";var e={n:t=>{var n=t&&t.__esModule?()=>t.default:()=>t;return e.d(n,{a:n}),n},d:(t,n)=>{for(var a in n)e.o(n,a)&&!e.o(t,a)&&Object.defineProperty(t,a,{enumerable:!0,get:n[a]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};function n(e){let t=5381;for(let n=0;n<e.length;n++)t=(t<<5)+t+e.charCodeAt(n);return(t>>>0).toString(16)}e.r(t),e.d(t,{CALLBACK_EXTENSION_POINT:()=>I,ComponentNodeData:()=>b,DashboardNodeData:()=>x,DatasourceNodeData:()=>E,FolderNodeData:()=>k,LabelNameNodeData:()=>C,LabelValueNodeData:()=>A,OpenAssistantButton:()=>ut,StructuredNodeData:()=>r,closeAssistant:()=>z,createAssistantContextItem:()=>N,getExposeAssistantFunctionsConfig:()=>P,isAssistantAvailable:()=>j,newFunctionNamespace:()=>O,openAssistant:()=>F,provideComponents:()=>w,providePageContext:()=>h,provideQuestions:()=>L,useAssistant:()=>G,usePageComponents:()=>y,usePageContext:()=>v,useProvidePageContext:()=>m,useProvideQuestions:()=>T,useQuestions:()=>_});class a{constructor(e){this.params=e,this.text="",this.id=n(e.id)}formatForLLM(e){var t,n;return{type:"unknown",codeElementIds:e,data:{name:null!==(t=this.params.text)&&void 0!==t?t:"",text:null!==(n=this.params.text)&&void 0!==n?n:""}}}}class r{constructor(e){this.params=e,this.id=n(JSON.stringify(e.data))}formatForLLM(e){return{type:"structured",codeElementIds:e,data:this.params.data}}}const s=require("@grafana/runtime"),o=require("react");var i=e.n(o);const c=[],u="grafana-assistant:page-context-sync",l="grafana-assistant:page-context-update",d="grafana-assistant:page-context-remove",f="grafana-assistant:location-changed";let p=!1;function h(e,t){const n=c.findIndex((t=>{return n=t.urlPattern,a=e,"string"==typeof n&&"string"==typeof a?n===a:n instanceof RegExp&&a instanceof RegExp&&n.source===a.source&&n.flags===a.flags;var n,a}));let a;-1!==n?(a=c[n],a.context=[...t]):(a={id:`page-context-${Date.now()}-${Math.random().toString(36).slice(2,11)}`,urlPattern:e,context:[...t]},c.push(a)),window.dispatchEvent(new CustomEvent(l,{detail:a})),window.dispatchEvent(new CustomEvent(u,{detail:{registry:c}}));const r=e=>{const t=c.findIndex((e=>e.id===a.id));-1!==t&&(c[t].context=[...e],window.dispatchEvent(new CustomEvent(l,{detail:c[t]})))};return r.unregister=()=>{const e=c.findIndex((e=>e.id===a.id));-1!==e&&(c.splice(e,1),window.dispatchEvent(new CustomEvent(d,{detail:{id:a.id}})))},r}function m(e,t=[]){const n=(0,o.useRef)(void 0),a=(0,o.useRef)(t);return a.current=t,(0,o.useEffect)((()=>(n.current=h(e,a.current),()=>{var e;null===(e=n.current)||void 0===e||e.unregister()})),[e]),(0,o.useEffect)((()=>{n.current&&n.current(t)}),[t]),(0,o.useCallback)((e=>{var t;null===(t=n.current)||void 0===t||t.call(n,e)}),[])}function v(e={allowQuestions:!1,allowComponents:!1}){const[t,n]=(0,o.useState)([]),a=(0,s.useLocationService)(),r=(0,o.useRef)("");(0,o.useEffect)((()=>{const e=()=>{const e=function(e,t){if(!e)return[];const n=[];for(const a of t)g(e,a.urlPattern)&&n.push(...a.context);return n}(a.getLocation().pathname,c);n(e)},t=()=>{e()},s=t=>{var n;const r=null===(n=t.detail)||void 0===n?void 0:n.pathname;r&&r===a.getLocation().pathname&&e()},o=a.getLocationObservable().subscribe((t=>{const n=t.pathname;n!==r.current&&(r.current=n,function(e){window.dispatchEvent(new CustomEvent(f,{detail:{pathname:e}}))}(n),e())}));return e(),window.addEventListener(u,t),window.addEventListener(l,t),window.addEventListener(d,t),window.addEventListener(f,s),()=>{o.unsubscribe(),window.removeEventListener(u,t),window.removeEventListener(l,t),window.removeEventListener(d,t),window.removeEventListener(f,s)}}),[a]);let i=t;return e.allowQuestions||(i=i.filter((e=>{var t;return"question"!==(null===(t=e.node.data)||void 0===t?void 0:t.type)}))),e.allowComponents||(i=i.filter((e=>{var t;return"component"!==(null===(t=e.node.data)||void 0===t?void 0:t.type)}))),i}function g(e,t){if(t instanceof RegExp)return t.test(e);if("string"==typeof t){const n=t.replace(/\*\*/g,"\0DOUBLE_STAR\0").replace(/\*/g,"[^/]*").replace(/\u0000DOUBLE_STAR\u0000/g,".*").replace(/\?/g,".");return new RegExp(`^${n}$`).test(e)}return!1}p||(window.addEventListener(u,(e=>{var t;const n=null===(t=e.detail)||void 0===t?void 0:t.registry;if(n){const e=new Set(c.map((e=>e.id))),t=n.filter((t=>!e.has(t.id)));c.push(...t)}})),window.addEventListener(l,(e=>{const t=e.detail;if(t){const e=c.findIndex((e=>e.id===t.id));-1!==e?c[e]=t:c.push(t)}})),window.addEventListener(d,(e=>{var t;const n=null===(t=e.detail)||void 0===t?void 0:t.id;if(n){const e=c.findIndex((e=>e.id===n));-1!==e&&c.splice(e,1)}})),p=!0);class b extends a{constructor(e){const t=e.namespace||"components";super({...e,id:`${t}-${Object.keys(e.components).join("-")}`}),this.components=e.components,this.prompt=e.prompt,this.namespace=t}formatForLLM(e){return{type:"component",codeElementIds:e,data:{name:`${this.namespace} components`,prompt:this.prompt,namespace:this.namespace}}}}function y(){const e=v({allowComponents:!0,allowQuestions:!1});return(0,o.useMemo)((()=>{const t={};return e.filter((e=>{var t;return null===(t=e.node.data)||void 0===t?void 0:t.components})).forEach((e=>{const n=e.node.data;if(null==n?void 0:n.components){const e=n.namespace||n.name||"components";Object.entries(n.components).forEach((([n,a])=>{t[`${e}_${n}`]=a}))}})),t}),[e])}function w(e,t,n,a=/.*/){return h(a,[N("component",{components:n,prompt:e,namespace:t})])}class x extends a{constructor(e){super({...e,id:e.dashboardUid}),this.dashboardUid=e.dashboardUid,this.dashboardTitle=e.dashboardTitle,this.folderUid=e.folderUid,this.folderTitle=e.folderTitle,this.text=e.dashboardTitle}formatForLLM(e){return{type:"dashboard",codeElementIds:e,data:{name:this.dashboardTitle,dashboardUid:this.dashboardUid,dashboardTitle:this.dashboardTitle,folderUid:this.folderUid,folderTitle:this.folderTitle,text:this.text}}}}class k extends a{constructor(e){super({...e,id:e.folderUid}),this.text="",this.folderUid=e.folderUid,this.folderTitle=e.folderTitle,this.text=e.folderTitle}formatForLLM(e){return{type:"dashboard_folder",codeElementIds:e,data:{name:this.folderTitle,folderUid:this.folderUid,folderTitle:this.folderTitle,text:this.text}}}}class E extends a{constructor(e){super({...e,id:e.datasourceUid}),this.datasourceUid=e.datasourceUid,this.datasourceType=e.datasourceType,this.datasourceName=e.datasourceName,this.img=e.img,this.text=e.datasourceName}formatForLLM(e){return{type:"datasource",codeElementIds:e,data:{name:this.datasourceName,uid:this.datasourceUid,type:this.datasourceType,text:this.text,img:this.img}}}}class C extends a{constructor(e){super({...e,id:`${e.datasourceUid}-${e.labelName}`}),this.datasourceUid=e.datasourceUid,this.datasourceType=e.datasourceType,this.datasourceName=e.datasourceName,this.labelName=e.labelName,this.text=e.labelName,this.img=e.img}formatForLLM(e){return{type:"label_name",codeElementIds:e,data:{name:this.labelName,datasourceUid:this.datasourceUid,datasourceType:this.datasourceType,datasourceName:this.datasourceName,labelName:this.labelName,img:this.img,text:this.text}}}}class A extends a{constructor(e){super({...e,id:`${e.datasourceUid}-${e.labelName}-${e.labelValue}`}),this.datasourceUid=e.datasourceUid,this.datasourceType=e.datasourceType,this.datasourceName=e.datasourceName,this.labelName=e.labelName,this.labelValue=e.labelValue,this.text=e.labelValue,this.img=e.img}formatForLLM(e){return{type:"label_value",codeElementIds:e,data:{name:this.labelValue,datasourceUid:this.datasourceUid,datasourceType:this.datasourceType,datasourceName:this.datasourceName,labelName:this.labelName,labelValue:this.labelValue,text:this.text,img:this.img}}}}function $(e){var t,n,a,r,o;const i=(0,s.getDataSourceSrv)().getInstanceSettings(e);return{datasourceType:null!==(t=null==i?void 0:i.type)&&void 0!==t?t:"unknown",datasourceName:null!==(n=null==i?void 0:i.name)&&void 0!==n?n:e,img:null===(o=null===(r=null===(a=null==i?void 0:i.meta)||void 0===a?void 0:a.info)||void 0===r?void 0:r.logos)||void 0===o?void 0:o.small}}const S={datasource:"database",label_name:"database",label_value:"database",dashboard:"dashboard",dashboard_folder:"folder",unknown:"circle-mono",structured:"gf-grid",component:"gf-grid"};function N(e,t){var n,s,o;const i=function(e,t){switch(e){case"datasource":return new E({...t,...$(t.datasourceUid)});case"label_name":return new C({...t,...$(t.datasourceUid)});case"label_value":return new A({...t,...$(t.datasourceUid)});case"dashboard":return new x(t);case"dashboard_folder":return new k(t);case"structured":return new r(t);case"component":return new b({...t,hidden:!0});case"unknown":return new a(t);default:return console.error(`Unknown context type: ${e}`),new a(t)}}(e,t),c=null!==(n=t.title)&&void 0!==n?n:function(e){var t;return e instanceof r?e.formatForLLM().data.name:null!==(t=e.text)&&void 0!==t?t:"Given Context"}(i),u=null!==(s=t.img)&&void 0!==s?s:function(e){if("img"in e)return e.img}(i);return{node:{id:i.id,name:c,img:u,icon:null!==(o=t.icon)&&void 0!==o?o:S[e],navigable:!1,selectable:!0,data:i},occurrences:[]}}function L(e,t){const n=e=>e.map(((e,t)=>({node:{id:`question-${t}`,name:e.prompt,navigable:!1,selectable:!0,icon:"question-circle",data:{type:"question",prompt:e.prompt,context:e.context||[]}},occurrences:[]}))),a=h(e,n(t)),r=e=>{a(n(e))};return r.unregister=a.unregister,r}function T(e,t=[]){const n=e=>e.map(((e,t)=>({node:{id:`question-${t}`,name:e.prompt,navigable:!1,selectable:!0,icon:"question-circle",data:{type:"question",prompt:e.prompt,context:e.context||[]}},occurrences:[]}))),a=m(e,n(t));return e=>{a(n(e))}}function _(){const e=v({allowQuestions:!0,allowComponents:!1});return U(e)}const U=e=>e.filter((e=>{var t;return"question"===(null===(t=e.node.data)||void 0===t?void 0:t.type)})).map((e=>{var t,n;return{prompt:(null===(t=e.node.data)||void 0===t?void 0:t.prompt)||e.node.name,context:(null===(n=e.node.data)||void 0===n?void 0:n.context)||[]}})),I="grafana-assistant-app/callback/v0-alpha";function O(e,t){return{namespace:e,functions:t}}function P(e){return{title:"callback",targets:[I],fn:()=>e.map((e=>({namespace:e.namespace,functions:e.functions})))}}const R=require("rxjs");function j(){if(!s.getObservablePluginLinks)return(0,R.of)(!1);return(0,s.getObservablePluginLinks)({extensionPointId:"grafana/extension-sidebar/v0-alpha"}).pipe((0,R.map)((e=>e.some((e=>"grafana-assistant-app"===e.pluginId&&"Grafana Assistant"===e.title)))))}const M=require("@grafana/data");class q extends M.BusEventWithPayload{}q.type="open-extension-sidebar";class D extends M.BusEventBase{}function F(e){var t,n;(0,s.reportInteraction)("grafana_assistant_app_opened_sidebar",{from:e.origin,prompt:null!==(t=e.prompt)&&void 0!==t?t:""}),function(e,t,n){const a=new q({pluginId:"grafana-assistant-app",componentTitle:"Grafana Assistant",props:n});(0,s.getAppEvents)().publish(a)}(0,0,{initialPrompt:e.prompt,initialContext:e.context,initialAutoSend:null===(n=e.autoSend)||void 0===n||n})}function z(){!function(){const e=new D;(0,s.getAppEvents)().publish(e)}()}function G(){const[e,t]=(0,o.useState)(!1);return(0,o.useEffect)((()=>{const e=j().subscribe((e=>t(e)));return()=>{e.unsubscribe()}}),[]),[e,e?F:void 0,e?z:void 0]}D.type="close-extension-sidebar";const B=require("@grafana/ui");var V=function(){function e(e){var t=this;this._insertTag=function(e){var n;n=0===t.tags.length?t.insertionPoint?t.insertionPoint.nextSibling:t.prepend?t.container.firstChild:t.before:t.tags[t.tags.length-1].nextSibling,t.container.insertBefore(e,n),t.tags.push(e)},this.isSpeedy=void 0===e.speedy||e.speedy,this.tags=[],this.ctr=0,this.nonce=e.nonce,this.key=e.key,this.container=e.container,this.prepend=e.prepend,this.insertionPoint=e.insertionPoint,this.before=null}var t=e.prototype;return t.hydrate=function(e){e.forEach(this._insertTag)},t.insert=function(e){this.ctr%(this.isSpeedy?65e3:1)==0&&this._insertTag(function(e){var t=document.createElement("style");return t.setAttribute("data-emotion",e.key),void 0!==e.nonce&&t.setAttribute("nonce",e.nonce),t.appendChild(document.createTextNode("")),t.setAttribute("data-s",""),t}(this));var t=this.tags[this.tags.length-1];if(this.isSpeedy){var n=function(e){if(e.sheet)return e.sheet;for(var t=0;t<document.styleSheets.length;t++)if(document.styleSheets[t].ownerNode===e)return document.styleSheets[t]}(t);try{n.insertRule(e,n.cssRules.length)}catch(e){}}else t.appendChild(document.createTextNode(e));this.ctr++},t.flush=function(){this.tags.forEach((function(e){var t;return null==(t=e.parentNode)?void 0:t.removeChild(e)})),this.tags=[],this.ctr=0},e}(),Q=Math.abs,W=String.fromCharCode,H=Object.assign;function J(e){return e.trim()}function K(e,t,n){return e.replace(t,n)}function X(e,t){return e.indexOf(t)}function Z(e,t){return 0|e.charCodeAt(t)}function Y(e,t,n){return e.slice(t,n)}function ee(e){return e.length}function te(e){return e.length}function ne(e,t){return t.push(e),e}var ae=1,re=1,se=0,oe=0,ie=0,ce="";function ue(e,t,n,a,r,s,o){return{value:e,root:t,parent:n,type:a,props:r,children:s,line:ae,column:re,length:o,return:""}}function le(e,t){return H(ue("",null,null,"",null,null,0),e,{length:-e.length},t)}function de(){return ie=oe>0?Z(ce,--oe):0,re--,10===ie&&(re=1,ae--),ie}function fe(){return ie=oe<se?Z(ce,oe++):0,re++,10===ie&&(re=1,ae++),ie}function pe(){return Z(ce,oe)}function he(){return oe}function me(e,t){return Y(ce,e,t)}function ve(e){switch(e){case 0:case 9:case 10:case 13:case 32:return 5;case 33:case 43:case 44:case 47:case 62:case 64:case 126:case 59:case 123:case 125:return 4;case 58:return 3;case 34:case 39:case 40:case 91:return 2;case 41:case 93:return 1}return 0}function ge(e){return ae=re=1,se=ee(ce=e),oe=0,[]}function be(e){return ce="",e}function ye(e){return J(me(oe-1,ke(91===e?e+2:40===e?e+1:e)))}function we(e){for(;(ie=pe())&&ie<33;)fe();return ve(e)>2||ve(ie)>3?"":" "}function xe(e,t){for(;--t&&fe()&&!(ie<48||ie>102||ie>57&&ie<65||ie>70&&ie<97););return me(e,he()+(t<6&&32==pe()&&32==fe()))}function ke(e){for(;fe();)switch(ie){case e:return oe;case 34:case 39:34!==e&&39!==e&&ke(ie);break;case 40:41===e&&ke(e);break;case 92:fe()}return oe}function Ee(e,t){for(;fe()&&e+ie!==57&&(e+ie!==84||47!==pe()););return"/*"+me(t,oe-1)+"*"+W(47===e?e:fe())}function Ce(e){for(;!ve(pe());)fe();return me(e,oe)}var Ae="-ms-",$e="-moz-",Se="-webkit-",Ne="comm",Le="rule",Te="decl",_e="@keyframes";function Ue(e,t){for(var n="",a=te(e),r=0;r<a;r++)n+=t(e[r],r,e,t)||"";return n}function Ie(e,t,n,a){switch(e.type){case"@layer":if(e.children.length)break;case"@import":case Te:return e.return=e.return||e.value;case Ne:return"";case _e:return e.return=e.value+"{"+Ue(e.children,a)+"}";case Le:e.value=e.props.join(",")}return ee(n=Ue(e.children,a))?e.return=e.value+"{"+n+"}":""}function Oe(e){return be(Pe("",null,null,null,[""],e=ge(e),0,[0],e))}function Pe(e,t,n,a,r,s,o,i,c){for(var u=0,l=0,d=o,f=0,p=0,h=0,m=1,v=1,g=1,b=0,y="",w=r,x=s,k=a,E=y;v;)switch(h=b,b=fe()){case 40:if(108!=h&&58==Z(E,d-1)){-1!=X(E+=K(ye(b),"&","&\f"),"&\f")&&(g=-1);break}case 34:case 39:case 91:E+=ye(b);break;case 9:case 10:case 13:case 32:E+=we(h);break;case 92:E+=xe(he()-1,7);continue;case 47:switch(pe()){case 42:case 47:ne(je(Ee(fe(),he()),t,n),c);break;default:E+="/"}break;case 123*m:i[u++]=ee(E)*g;case 125*m:case 59:case 0:switch(b){case 0:case 125:v=0;case 59+l:-1==g&&(E=K(E,/\f/g,"")),p>0&&ee(E)-d&&ne(p>32?Me(E+";",a,n,d-1):Me(K(E," ","")+";",a,n,d-2),c);break;case 59:E+=";";default:if(ne(k=Re(E,t,n,u,l,r,i,y,w=[],x=[],d),s),123===b)if(0===l)Pe(E,t,k,k,w,s,d,i,x);else switch(99===f&&110===Z(E,3)?100:f){case 100:case 108:case 109:case 115:Pe(e,k,k,a&&ne(Re(e,k,k,0,0,r,i,y,r,w=[],d),x),r,x,d,i,a?w:x);break;default:Pe(E,k,k,k,[""],x,0,i,x)}}u=l=p=0,m=g=1,y=E="",d=o;break;case 58:d=1+ee(E),p=h;default:if(m<1)if(123==b)--m;else if(125==b&&0==m++&&125==de())continue;switch(E+=W(b),b*m){case 38:g=l>0?1:(E+="\f",-1);break;case 44:i[u++]=(ee(E)-1)*g,g=1;break;case 64:45===pe()&&(E+=ye(fe())),f=pe(),l=d=ee(y=E+=Ce(he())),b++;break;case 45:45===h&&2==ee(E)&&(m=0)}}return s}function Re(e,t,n,a,r,s,o,i,c,u,l){for(var d=r-1,f=0===r?s:[""],p=te(f),h=0,m=0,v=0;h<a;++h)for(var g=0,b=Y(e,d+1,d=Q(m=o[h])),y=e;g<p;++g)(y=J(m>0?f[g]+" "+b:K(b,/&\f/g,f[g])))&&(c[v++]=y);return ue(e,t,n,0===r?Le:i,c,u,l)}function je(e,t,n){return ue(e,t,n,Ne,W(ie),Y(e,2,-2),0)}function Me(e,t,n,a){return ue(e,t,n,Te,Y(e,0,a),Y(e,a+1,-1),a)}var qe=function(e,t,n){for(var a=0,r=0;a=r,r=pe(),38===a&&12===r&&(t[n]=1),!ve(r);)fe();return me(e,oe)},De=new WeakMap,Fe=function(e){if("rule"===e.type&&e.parent&&!(e.length<1)){for(var t=e.value,n=e.parent,a=e.column===n.column&&e.line===n.line;"rule"!==n.type;)if(!(n=n.parent))return;if((1!==e.props.length||58===t.charCodeAt(0)||De.get(n))&&!a){De.set(e,!0);for(var r=[],s=function(e,t){return be(function(e,t){var n=-1,a=44;do{switch(ve(a)){case 0:38===a&&12===pe()&&(t[n]=1),e[n]+=qe(oe-1,t,n);break;case 2:e[n]+=ye(a);break;case 4:if(44===a){e[++n]=58===pe()?"&\f":"",t[n]=e[n].length;break}default:e[n]+=W(a)}}while(a=fe());return e}(ge(e),t))}(t,r),o=n.props,i=0,c=0;i<s.length;i++)for(var u=0;u<o.length;u++,c++)e.props[c]=r[i]?s[i].replace(/&\f/g,o[u]):o[u]+" "+s[i]}}},ze=function(e){if("decl"===e.type){var t=e.value;108===t.charCodeAt(0)&&98===t.charCodeAt(2)&&(e.return="",e.value="")}};function Ge(e,t){switch(function(e,t){return 45^Z(e,0)?(((t<<2^Z(e,0))<<2^Z(e,1))<<2^Z(e,2))<<2^Z(e,3):0}(e,t)){case 5103:return Se+"print-"+e+e;case 5737:case 4201:case 3177:case 3433:case 1641:case 4457:case 2921:case 5572:case 6356:case 5844:case 3191:case 6645:case 3005:case 6391:case 5879:case 5623:case 6135:case 4599:case 4855:case 4215:case 6389:case 5109:case 5365:case 5621:case 3829:return Se+e+e;case 5349:case 4246:case 4810:case 6968:case 2756:return Se+e+$e+e+Ae+e+e;case 6828:case 4268:return Se+e+Ae+e+e;case 6165:return Se+e+Ae+"flex-"+e+e;case 5187:return Se+e+K(e,/(\w+).+(:[^]+)/,Se+"box-$1$2"+Ae+"flex-$1$2")+e;case 5443:return Se+e+Ae+"flex-item-"+K(e,/flex-|-self/,"")+e;case 4675:return Se+e+Ae+"flex-line-pack"+K(e,/align-content|flex-|-self/,"")+e;case 5548:return Se+e+Ae+K(e,"shrink","negative")+e;case 5292:return Se+e+Ae+K(e,"basis","preferred-size")+e;case 6060:return Se+"box-"+K(e,"-grow","")+Se+e+Ae+K(e,"grow","positive")+e;case 4554:return Se+K(e,/([^-])(transform)/g,"$1"+Se+"$2")+e;case 6187:return K(K(K(e,/(zoom-|grab)/,Se+"$1"),/(image-set)/,Se+"$1"),e,"")+e;case 5495:case 3959:return K(e,/(image-set\([^]*)/,Se+"$1$`$1");case 4968:return K(K(e,/(.+:)(flex-)?(.*)/,Se+"box-pack:$3"+Ae+"flex-pack:$3"),/s.+-b[^;]+/,"justify")+Se+e+e;case 4095:case 3583:case 4068:case 2532:return K(e,/(.+)-inline(.+)/,Se+"$1$2")+e;case 8116:case 7059:case 5753:case 5535:case 5445:case 5701:case 4933:case 4677:case 5533:case 5789:case 5021:case 4765:if(ee(e)-1-t>6)switch(Z(e,t+1)){case 109:if(45!==Z(e,t+4))break;case 102:return K(e,/(.+:)(.+)-([^]+)/,"$1"+Se+"$2-$3$1"+$e+(108==Z(e,t+3)?"$3":"$2-$3"))+e;case 115:return~X(e,"stretch")?Ge(K(e,"stretch","fill-available"),t)+e:e}break;case 4949:if(115!==Z(e,t+1))break;case 6444:switch(Z(e,ee(e)-3-(~X(e,"!important")&&10))){case 107:return K(e,":",":"+Se)+e;case 101:return K(e,/(.+:)([^;!]+)(;|!.+)?/,"$1"+Se+(45===Z(e,14)?"inline-":"")+"box$3$1"+Se+"$2$3$1"+Ae+"$2box$3")+e}break;case 5936:switch(Z(e,t+11)){case 114:return Se+e+Ae+K(e,/[svh]\w+-[tblr]{2}/,"tb")+e;case 108:return Se+e+Ae+K(e,/[svh]\w+-[tblr]{2}/,"tb-rl")+e;case 45:return Se+e+Ae+K(e,/[svh]\w+-[tblr]{2}/,"lr")+e}return Se+e+Ae+e+e}return e}var Be=[function(e,t,n,a){if(e.length>-1&&!e.return)switch(e.type){case Te:e.return=Ge(e.value,e.length);break;case _e:return Ue([le(e,{value:K(e.value,"@","@"+Se)})],a);case Le:if(e.length)return function(e,t){return e.map(t).join("")}(e.props,(function(t){switch(function(e){return(e=/(::plac\w+|:read-\w+)/.exec(e))?e[0]:e}(t)){case":read-only":case":read-write":return Ue([le(e,{props:[K(t,/:(read-\w+)/,":-moz-$1")]})],a);case"::placeholder":return Ue([le(e,{props:[K(t,/:(plac\w+)/,":"+Se+"input-$1")]}),le(e,{props:[K(t,/:(plac\w+)/,":-moz-$1")]}),le(e,{props:[K(t,/:(plac\w+)/,Ae+"input-$1")]})],a)}return""}))}}],Ve={animationIterationCount:1,aspectRatio:1,borderImageOutset:1,borderImageSlice:1,borderImageWidth:1,boxFlex:1,boxFlexGroup:1,boxOrdinalGroup:1,columnCount:1,columns:1,flex:1,flexGrow:1,flexPositive:1,flexShrink:1,flexNegative:1,flexOrder:1,gridRow:1,gridRowEnd:1,gridRowSpan:1,gridRowStart:1,gridColumn:1,gridColumnEnd:1,gridColumnSpan:1,gridColumnStart:1,msGridRow:1,msGridRowSpan:1,msGridColumn:1,msGridColumnSpan:1,fontWeight:1,lineHeight:1,opacity:1,order:1,orphans:1,scale:1,tabSize:1,widows:1,zIndex:1,zoom:1,WebkitLineClamp:1,fillOpacity:1,floodOpacity:1,stopOpacity:1,strokeDasharray:1,strokeDashoffset:1,strokeMiterlimit:1,strokeOpacity:1,strokeWidth:1};function Qe(e){var t=Object.create(null);return function(n){return void 0===t[n]&&(t[n]=e(n)),t[n]}}var We=/[A-Z]|^ms/g,He=/_EMO_([^_]+?)_([^]*?)_EMO_/g,Je=function(e){return 45===e.charCodeAt(1)},Ke=function(e){return null!=e&&"boolean"!=typeof e},Xe=Qe((function(e){return Je(e)?e:e.replace(We,"-$&").toLowerCase()})),Ze=function(e,t){switch(e){case"animation":case"animationName":if("string"==typeof t)return t.replace(He,(function(e,t,n){return et={name:t,styles:n,next:et},t}))}return 1===Ve[e]||Je(e)||"number"!=typeof t||0===t?t:t+"px"};function Ye(e,t,n){if(null==n)return"";var a=n;if(void 0!==a.__emotion_styles)return a;switch(typeof n){case"boolean":return"";case"object":var r=n;if(1===r.anim)return et={name:r.name,styles:r.styles,next:et},r.name;var s=n;if(void 0!==s.styles){var o=s.next;if(void 0!==o)for(;void 0!==o;)et={name:o.name,styles:o.styles,next:et},o=o.next;return s.styles+";"}return function(e,t,n){var a="";if(Array.isArray(n))for(var r=0;r<n.length;r++)a+=Ye(e,t,n[r])+";";else for(var s in n){var o=n[s];if("object"!=typeof o){var i=o;null!=t&&void 0!==t[i]?a+=s+"{"+t[i]+"}":Ke(i)&&(a+=Xe(s)+":"+Ze(s,i)+";")}else if(!Array.isArray(o)||"string"!=typeof o[0]||null!=t&&void 0!==t[o[0]]){var c=Ye(e,t,o);switch(s){case"animation":case"animationName":a+=Xe(s)+":"+c+";";break;default:a+=s+"{"+c+"}"}}else for(var u=0;u<o.length;u++)Ke(o[u])&&(a+=Xe(s)+":"+Ze(s,o[u])+";")}return a}(e,t,n);case"function":if(void 0!==e){var i=et,c=n(e);return et=i,Ye(e,t,c)}}var u=n;if(null==t)return u;var l=t[u];return void 0!==l?l:u}var et,tt=/label:\s*([^\s;{]+)\s*(;|$)/g;function nt(e,t,n){if(1===e.length&&"object"==typeof e[0]&&null!==e[0]&&void 0!==e[0].styles)return e[0];var a=!0,r="";et=void 0;var s=e[0];null==s||void 0===s.raw?(a=!1,r+=Ye(n,t,s)):r+=s[0];for(var o=1;o<e.length;o++)r+=Ye(n,t,e[o]),a&&(r+=s[o]);tt.lastIndex=0;for(var i,c="";null!==(i=tt.exec(r));)c+="-"+i[1];var u=function(e){for(var t,n=0,a=0,r=e.length;r>=4;++a,r-=4)t=1540483477*(65535&(t=255&e.charCodeAt(a)|(255&e.charCodeAt(++a))<<8|(255&e.charCodeAt(++a))<<16|(255&e.charCodeAt(++a))<<24))+(59797*(t>>>16)<<16),n=1540483477*(65535&(t^=t>>>24))+(59797*(t>>>16)<<16)^1540483477*(65535&n)+(59797*(n>>>16)<<16);switch(r){case 3:n^=(255&e.charCodeAt(a+2))<<16;case 2:n^=(255&e.charCodeAt(a+1))<<8;case 1:n=1540483477*(65535&(n^=255&e.charCodeAt(a)))+(59797*(n>>>16)<<16)}return(((n=1540483477*(65535&(n^=n>>>13))+(59797*(n>>>16)<<16))^n>>>15)>>>0).toString(36)}(r)+c;return{name:u,styles:r,next:et}}function at(e,t,n){var a="";return n.split(" ").forEach((function(n){void 0!==e[n]?t.push(e[n]+";"):n&&(a+=n+" ")})),a}function rt(e,t){if(void 0===e.inserted[t.name])return e.insert("",t,e.sheet,!0)}function st(e,t,n){var a=[],r=at(e,a,n);return a.length<2?n:r+t(a)}var ot=function e(t){for(var n="",a=0;a<t.length;a++){var r=t[a];if(null!=r){var s=void 0;switch(typeof r){case"boolean":break;case"object":if(Array.isArray(r))s=e(r);else for(var o in s="",r)r[o]&&o&&(s&&(s+=" "),s+=o);break;default:s=r}s&&(n&&(n+=" "),n+=s)}}return n};var it=function(e){var t=function(e){var t=e.key;if("css"===t){var n=document.querySelectorAll("style[data-emotion]:not([data-s])");Array.prototype.forEach.call(n,(function(e){-1!==e.getAttribute("data-emotion").indexOf(" ")&&(document.head.appendChild(e),e.setAttribute("data-s",""))}))}var a,r,s=e.stylisPlugins||Be,o={},i=[];a=e.container||document.head,Array.prototype.forEach.call(document.querySelectorAll('style[data-emotion^="'+t+' "]'),(function(e){for(var t=e.getAttribute("data-emotion").split(" "),n=1;n<t.length;n++)o[t[n]]=!0;i.push(e)}));var c,u,l,d,f=[Ie,(d=function(e){c.insert(e)},function(e){e.root||(e=e.return)&&d(e)})],p=(u=[Fe,ze].concat(s,f),l=te(u),function(e,t,n,a){for(var r="",s=0;s<l;s++)r+=u[s](e,t,n,a)||"";return r});r=function(e,t,n,a){c=n,Ue(Oe(e?e+"{"+t.styles+"}":t.styles),p),a&&(h.inserted[t.name]=!0)};var h={key:t,sheet:new V({key:t,container:a,nonce:e.nonce,speedy:e.speedy,prepend:e.prepend,insertionPoint:e.insertionPoint}),nonce:e.nonce,inserted:o,registered:{},insert:r};return h.sheet.hydrate(i),h}(e);t.sheet.speedy=function(e){this.isSpeedy=e},t.compat=!0;var n=function(){for(var e=arguments.length,n=new Array(e),a=0;a<e;a++)n[a]=arguments[a];var r=nt(n,t.registered,void 0);return function(e,t){!function(e,t){var n=e.key+"-"+t.name;void 0===e.registered[n]&&(e.registered[n]=t.styles)}(e,t);var n=e.key+"-"+t.name;if(void 0===e.inserted[t.name]){var a=t;do{e.insert(t===a?"."+n:"",a,e.sheet,!0),a=a.next}while(void 0!==a)}}(t,r),t.key+"-"+r.name};return{css:n,cx:function(){for(var e=arguments.length,a=new Array(e),r=0;r<e;r++)a[r]=arguments[r];return st(t.registered,n,ot(a))},injectGlobal:function(){for(var e=arguments.length,n=new Array(e),a=0;a<e;a++)n[a]=arguments[a];var r=nt(n,t.registered);rt(t,r)},keyframes:function(){for(var e=arguments.length,n=new Array(e),a=0;a<e;a++)n[a]=arguments[a];var r=nt(n,t.registered),s="animation-"+r.name;return rt(t,{name:r.name,styles:"@keyframes "+s+"{"+r.styles+"}"}),s},hydrate:function(e){e.forEach((function(e){t.inserted[e]=!0}))},flush:function(){t.registered={},t.inserted={},t.sheet.flush()},sheet:t.sheet,cache:t,getRegisteredStyles:at.bind(null,t.registered),merge:st.bind(null,t.registered,n)}}({key:"css"}),ct=(it.flush,it.hydrate,it.cx,it.merge,it.getRegisteredStyles,it.injectGlobal,it.keyframes,it.css);function ut(e){const[t,n]=G();return t&&n?i().createElement(lt,{...e,openAssistant:n}):null}function lt({prompt:e,origin:t,context:n,autoSend:a=!0,title:r="Analyze with Assistant",size:c="sm",iconOnlyButton:u=!1,openAssistant:l}){const d=(0,B.useStyles2)(dt);return(0,o.useEffect)((()=>{(0,s.reportInteraction)("grafana_assistant_app_open_sidebar_button_displayed",{from:t})}),[t]),i().createElement(i().Fragment,null,u?i().createElement(B.IconButton,{name:"ai-sparkle",onClick:()=>l({prompt:e,context:n,autoSend:a,origin:t}),variant:"secondary",size:c,"aria-label":r,className:d.icon,tooltip:r,"data-testid":"assistant-icon-button"}):i().createElement(B.Button,{icon:"ai-sparkle",onClick:()=>l({prompt:e,context:n,autoSend:a,origin:t}),variant:"secondary",fill:"solid",size:c,title:r,"aria-label":r,className:d.button,"data-testid":"assistant-button"},r))}it.sheet,it.cache;const dt=e=>({button:ct({label:"assistant-button",border:"1px solid transparent",borderImage:"linear-gradient(90deg, rgb(168, 85, 247), rgb(249, 115, 22)) 1"}),icon:ct({label:"assistant-icon",border:"1px solid transparent",backgroundClip:"padding-box",padding:e.spacing(.5),"&:hover":{borderImage:"linear-gradient(90deg, rgb(168, 85, 247), rgb(249, 115, 22)) 1 !important",border:"1px solid transparent",backgroundClip:"padding-box"}})});module.exports=t})();
|
package/dist/sidebar.d.ts
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import { ChatContextItem } from './context/types';
|
|
2
2
|
export type OpenAssistantProps = {
|
|
3
|
+
origin: string;
|
|
3
4
|
prompt?: string;
|
|
4
5
|
context?: ChatContextItem[];
|
|
6
|
+
autoSend?: boolean;
|
|
5
7
|
};
|
|
6
8
|
/**
|
|
7
9
|
* Open the Grafana Assistant sidebar with a given initial prompt.
|
|
8
10
|
*
|
|
9
11
|
* @param props - The props to pass to the assistant.
|
|
12
|
+
* @param props.origin - The origin of the request that opened the assistant. This is used to track the source of the request. Should be a structured string using forward slashes, with the first part as a namespace. Examples: 'grafana-datasources/prometheus/query-builder', 'grafana-slo-app/slo-editor-overview', 'grafana/trace-view-analyzer`.
|
|
10
13
|
* @param props.prompt - The initial prompt to display in the assistant.
|
|
11
14
|
* @param props.context - The initial context to display in the assistant. Created with `createContext`.
|
|
15
|
+
* @param props.autoSend - Whether to automatically send the initial prompt. When true, opens a chat and sends the initial prompt right away. When false, opens chat and updates user message without sending it. Defaults to true.
|
|
12
16
|
*/
|
|
13
17
|
export declare function openAssistant(props: OpenAssistantProps): void;
|
|
14
18
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@grafana/assistant",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.17",
|
|
4
4
|
"description": "Type definitions and helper functions for Grafana Assistant",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -11,7 +11,10 @@
|
|
|
11
11
|
"prebuild": "rm -rf dist",
|
|
12
12
|
"build": "webpack --config webpack.config.cjs --mode production && tsc --emitDeclarationOnly",
|
|
13
13
|
"dev": "webpack --config webpack.config.cjs --mode development",
|
|
14
|
-
"clean": "rm -rf dist"
|
|
14
|
+
"clean": "rm -rf dist",
|
|
15
|
+
"test": "jest",
|
|
16
|
+
"test:watch": "jest --watch --onlyChanged",
|
|
17
|
+
"test:ci": "jest --passWithNoTests --maxWorkers 4"
|
|
15
18
|
},
|
|
16
19
|
"keywords": [
|
|
17
20
|
"grafana",
|
|
@@ -22,6 +25,13 @@
|
|
|
22
25
|
"author": "Grafana Labs",
|
|
23
26
|
"license": "Apache-2.0",
|
|
24
27
|
"devDependencies": {
|
|
28
|
+
"@storybook/react": "^8.6.14",
|
|
29
|
+
"@testing-library/jest-dom": "6.1.4",
|
|
30
|
+
"@testing-library/react": "14.0.0",
|
|
31
|
+
"@types/jest": "^29.5.0",
|
|
32
|
+
"@types/testing-library__jest-dom": "5.14.8",
|
|
33
|
+
"jest": "^29.5.0",
|
|
34
|
+
"jest-environment-jsdom": "^29.5.0",
|
|
25
35
|
"react": "18.3.1",
|
|
26
36
|
"rxjs": "7.8.2",
|
|
27
37
|
"ts-loader": "^9.0.0",
|