Bump @grafana/assistant package (#110507)

* Bump @grafana/assistant package

* Update origin

* Update FlameGraphHeader.tsx

Co-authored-by: Kevin Adam  <16607163+kevelopment@users.noreply.github.com>

* Update LogListContext.tsx

Co-authored-by: Sven Grossmann <sven.grossmann@grafana.com>

* Fix lint

* Update public/app/features/logs/components/panel/LogListContext.tsx

Co-authored-by: Sven Grossmann <sven.grossmann@grafana.com>

---------

Co-authored-by: Kevin Adam <16607163+kevelopment@users.noreply.github.com>
Co-authored-by: Sven Grossmann <sven.grossmann@grafana.com>
This commit is contained in:
Ivana Huckova 2025-09-03 15:30:02 +02:00 committed by GitHub
parent dc16562050
commit 4e28cba1c5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 52 additions and 90 deletions

View File

@ -273,7 +273,7 @@
"@formatjs/intl-durationformat": "^0.7.0",
"@glideapps/glide-data-grid": "^6.0.0",
"@grafana/alerting": "workspace:*",
"@grafana/assistant": "0.0.16",
"@grafana/assistant": "0.0.17",
"@grafana/aws-sdk": "0.7.1",
"@grafana/azure-sdk": "0.0.7",
"@grafana/data": "workspace:*",

View File

@ -83,7 +83,7 @@
"typescript": "5.9.2"
},
"peerDependencies": {
"@grafana/assistant": "^0.0.12",
"@grafana/assistant": "^0.0.17",
"react": "^18.0.0",
"react-dom": "^18.0.0"
}

View File

@ -1,35 +0,0 @@
import { ChatContextItem, useAssistant } from '@grafana/assistant';
import { Button } from '@grafana/ui';
type Props = {
assistantContext: ChatContextItem[];
className?: string;
};
export function AnalyzeFlameGraphButton(props: Props) {
const { assistantContext, className } = props;
const [isAvailable, openAssistant] = useAssistant();
if (!isAvailable || !openAssistant || assistantContext.length === 0) {
return null;
}
return (
<Button
className={className}
onClick={() =>
openAssistant({
origin: 'analyze-flame-graph',
prompt: 'Analyze Flame Graph',
context: assistantContext,
})
}
variant="secondary"
fill="outline"
icon="ai-sparkle"
size="sm"
>
Analyze Flame Graph
</Button>
);
}

View File

@ -11,7 +11,8 @@ import { MIN_WIDTH_TO_SHOW_BOTH_TOPTABLE_AND_FLAMEGRAPH } from './constants';
jest.mock('@grafana/assistant', () => ({
useAssistant: jest.fn(() => [false, null]), // [isAvailable, openAssistant]
createContext: jest.fn(),
createAssistantContextItem: jest.fn(),
OpenAssistantButton: () => <div>OpenAssistantButton</div>,
}));
jest.mock('react-use', () => ({

View File

@ -9,7 +9,8 @@ import { ColorScheme, SelectedView } from './types';
jest.mock('@grafana/assistant', () => ({
useAssistant: jest.fn(() => [false, null]), // [isAvailable, openAssistant]
createContext: jest.fn(),
createAssistantContextItem: jest.fn(),
OpenAssistantButton: () => <div>OpenAssistantButton</div>,
}));
describe('FlameGraphHeader', () => {

View File

@ -3,11 +3,10 @@ import { useEffect, useState } from 'react';
import * as React from 'react';
import { useDebounce, usePrevious } from 'react-use';
import { ChatContextItem } from '@grafana/assistant';
import { ChatContextItem, OpenAssistantButton } from '@grafana/assistant';
import { GrafanaTheme2, SelectableValue } from '@grafana/data';
import { Button, ButtonGroup, Dropdown, Input, Menu, RadioButtonGroup, useStyles2 } from '@grafana/ui';
import { AnalyzeFlameGraphButton } from './AnalyzeFlameGraphButton';
import { byPackageGradient, byValueGradient, diffColorBlindGradient, diffDefaultGradient } from './FlameGraph/colors';
import { CollapsedMap } from './FlameGraph/dataTransform';
import { MIN_WIDTH_TO_SHOW_BOTH_TOPTABLE_AND_FLAMEGRAPH } from './constants';
@ -89,8 +88,10 @@ const FlameGraphHeader = ({
</div>
<div className={styles.rightContainer}>
{assistantContext && (
<AnalyzeFlameGraphButton className={styles.buttonSpacing} assistantContext={assistantContext} />
{!!assistantContext?.length && (
<div className={styles.buttonSpacing}>
<OpenAssistantButton origin="grafana/flame-graph" prompt="Analyze Flame Graph" context={assistantContext} />
</div>
)}
{showResetButton && (
<Button

View File

@ -718,16 +718,20 @@ async function handleOpenAssistant(openAssistant: (props: OpenAssistantProps) =>
const datasource = await getDataSourceSrv().get(log.datasourceUid);
const context = [];
if (datasource) {
context.push(createAssistantContextItem('datasource', { datasourceUid: datasource.uid }));
context.push(
createAssistantContextItem('datasource', {
datasourceUid: datasource.uid,
})
);
}
openAssistant({
origin: 'grafana/explain-log-line',
prompt: `${t('logs.log-line-menu.log-line-explainer', 'Explain log line in a concise way')}:
\`\`\`
${log.entry.replaceAll('`', '\\`')}
\`\`\`
`,
origin: 'explain-log-line',
\`\`\`
${log.entry.replaceAll('`', '\\`')}
\`\`\`
`,
context: [
...context,
createAssistantContextItem('structured', {

View File

@ -39,7 +39,7 @@
"webpack": "5.101.0"
},
"peerDependencies": {
"@grafana/assistant": "^0.0.12",
"@grafana/assistant": "^0.0.17",
"@grafana/runtime": "*"
},
"scripts": {

View File

@ -17,12 +17,14 @@ jest.mock('@grafana/assistant', () => ({
createAssistantContextItem: jest.fn(),
}));
const mockCreateContext = createAssistantContextItem as jest.MockedFunction<typeof createAssistantContextItem>;
const mockCreateAssistantContextItem = createAssistantContextItem as jest.MockedFunction<
typeof createAssistantContextItem
>;
describe('enrichDataFrameWithAssistantContentMapper', () => {
beforeEach(() => {
jest.clearAllMocks();
mockCreateContext.mockImplementation((type, data) => ({
mockCreateAssistantContextItem.mockImplementation((type, data) => ({
type,
data,
node: { id: 'test-id', type: 'test', name: 'test-node', navigable: true },
@ -106,15 +108,15 @@ describe('enrichDataFrameWithAssistantContentMapper', () => {
expect(result.data).toHaveLength(1);
expect(result.data[0].meta?.custom?.assistantContext).toBeDefined();
expect(mockCreateContext).toHaveBeenCalledTimes(2);
expect(mockCreateAssistantContextItem).toHaveBeenCalledTimes(2);
// Verify datasource context
expect(mockCreateContext).toHaveBeenCalledWith('datasource', {
expect(mockCreateAssistantContextItem).toHaveBeenCalledWith('datasource', {
datasourceUid: 'test-uid',
});
// Verify structured context
expect(mockCreateContext).toHaveBeenCalledWith('structured', {
expect(mockCreateAssistantContextItem).toHaveBeenCalledWith('structured', {
title: 'Analyze Flame Graph',
data: {
start: request.range.from.valueOf(),
@ -173,7 +175,7 @@ describe('enrichDataFrameWithAssistantContentMapper', () => {
expect(result.data).toHaveLength(2);
expect(result.data[0].meta?.custom?.assistantContext).toBeDefined();
expect(result.data[1].meta?.custom?.assistantContext).toBeDefined();
expect(mockCreateContext).toHaveBeenCalledTimes(4); // 2 contexts per frame
expect(mockCreateAssistantContextItem).toHaveBeenCalledTimes(4); // 2 contexts per frame
});
});
@ -193,7 +195,7 @@ describe('enrichDataFrameWithAssistantContentMapper', () => {
const result = mapper(response);
expect(result.data[0].meta?.custom?.assistantContext).toBeUndefined();
expect(mockCreateContext).not.toHaveBeenCalled();
expect(mockCreateAssistantContextItem).not.toHaveBeenCalled();
});
});
@ -213,7 +215,7 @@ describe('enrichDataFrameWithAssistantContentMapper', () => {
const result = mapper(response);
expect(result.data[0]).toBe(dataFrame); // Should remain unchanged
expect(mockCreateContext).not.toHaveBeenCalled();
expect(mockCreateAssistantContextItem).not.toHaveBeenCalled();
});
it('should not add context when query has no datasource information', () => {
@ -232,7 +234,7 @@ describe('enrichDataFrameWithAssistantContentMapper', () => {
const result = mapper(response);
expect(result.data[0]).toBe(dataFrame); // Should remain unchanged
expect(mockCreateContext).not.toHaveBeenCalled();
expect(mockCreateAssistantContextItem).not.toHaveBeenCalled();
});
it('should not add context if query has incomplete datasource information', () => {
@ -254,7 +256,7 @@ describe('enrichDataFrameWithAssistantContentMapper', () => {
const result = mapper(response);
expect(result.data[0]).toBe(dataFrame); // Should remain unchanged
expect(mockCreateContext).not.toHaveBeenCalled();
expect(mockCreateAssistantContextItem).not.toHaveBeenCalled();
});
it('should not add context with empty response data', () => {
@ -265,7 +267,7 @@ describe('enrichDataFrameWithAssistantContentMapper', () => {
const result = mapper(response);
expect(result.data).toHaveLength(0);
expect(mockCreateContext).not.toHaveBeenCalled();
expect(mockCreateAssistantContextItem).not.toHaveBeenCalled();
});
it('should handle mixed data frame types', () => {
@ -296,7 +298,7 @@ describe('enrichDataFrameWithAssistantContentMapper', () => {
expect(result.data[0].meta?.custom?.assistantContext).toBeDefined(); // Flamegraph
expect(result.data[1].meta?.custom?.assistantContext).toBeUndefined(); // Table
expect(result.data[2].meta?.custom?.assistantContext).toBeDefined(); // Flamegraph
expect(mockCreateContext).toHaveBeenCalledTimes(4); // 2 contexts for each flamegraph
expect(mockCreateAssistantContextItem).toHaveBeenCalledTimes(4); // 2 contexts for each flamegraph
});
});
@ -321,7 +323,7 @@ describe('enrichDataFrameWithAssistantContentMapper', () => {
const mapper = enrichDataFrameWithAssistantContentMapper(request, 'TestDatasource');
mapper(response);
expect(mockCreateContext).toHaveBeenCalledWith('structured', {
expect(mockCreateAssistantContextItem).toHaveBeenCalledWith('structured', {
title: 'Analyze Flame Graph',
data: {
start: fromTime.valueOf(),

View File

@ -2648,7 +2648,7 @@ __metadata:
typescript: "npm:5.9.2"
webpack: "npm:5.101.0"
peerDependencies:
"@grafana/assistant": ^0.0.12
"@grafana/assistant": ^0.0.17
"@grafana/runtime": "*"
languageName: unknown
linkType: soft
@ -3057,9 +3057,9 @@ __metadata:
languageName: unknown
linkType: soft
"@grafana/assistant@npm:0.0.16":
version: 0.0.16
resolution: "@grafana/assistant@npm:0.0.16"
"@grafana/assistant@npm:0.0.17":
version: 0.0.17
resolution: "@grafana/assistant@npm:0.0.17"
peerDependencies:
"@grafana/data": ">=12.1.0"
"@grafana/runtime": ">=12.1.0"
@ -3067,7 +3067,7 @@ __metadata:
"@grafana/ui": ">=12.1.0"
react: ">=18.0.0"
rxjs: ">=7.0.0"
checksum: 10/8482e09d3e86a865a8cf90908ae1438317b994798b5bf5d1a2369154b786e1ba20f30e208d48bed249c8427f11f87307b338c5307a8cb5143cffb2ef02050847
checksum: 10/0d10a4cb0b1dd1082157f106072b5ea164471b51e0a7ee8b70c48b6d3115d049d36783a04f0b04d6202f2eac01863fa08efd61ecf4d79febfc039966133c1c6a
languageName: node
linkType: hard
@ -3287,7 +3287,7 @@ __metadata:
tslib: "npm:2.8.1"
typescript: "npm:5.9.2"
peerDependencies:
"@grafana/assistant": ^0.0.12
"@grafana/assistant": ^0.0.17
react: ^18.0.0
react-dom: ^18.0.0
languageName: unknown
@ -18300,7 +18300,7 @@ __metadata:
"@formatjs/intl-durationformat": "npm:^0.7.0"
"@glideapps/glide-data-grid": "npm:^6.0.0"
"@grafana/alerting": "workspace:*"
"@grafana/assistant": "npm:0.0.16"
"@grafana/assistant": "npm:0.0.17"
"@grafana/aws-sdk": "npm:0.7.1"
"@grafana/azure-sdk": "npm:0.0.7"
"@grafana/data": "workspace:*"
@ -28782,7 +28782,7 @@ __metadata:
languageName: node
linkType: hard
"safe-buffer@npm:5.2.1, safe-buffer@npm:>=5.1.0, safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.2, safe-buffer@npm:^5.2.1, safe-buffer@npm:~5.2.0":
"safe-buffer@npm:5.2.1, safe-buffer@npm:>=5.1.0, safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.2, safe-buffer@npm:~5.2.0":
version: 5.2.1
resolution: "safe-buffer@npm:5.2.1"
checksum: 10/32872cd0ff68a3ddade7a7617b8f4c2ae8764d8b7d884c651b74457967a9e0e886267d3ecc781220629c44a865167b61c375d2da6c720c840ecd73f45d5d9451
@ -29116,15 +29116,14 @@ __metadata:
linkType: hard
"sha.js@npm:^2.4.11":
version: 2.4.12
resolution: "sha.js@npm:2.4.12"
version: 2.4.11
resolution: "sha.js@npm:2.4.11"
dependencies:
inherits: "npm:^2.0.4"
safe-buffer: "npm:^5.2.1"
to-buffer: "npm:^1.2.0"
inherits: "npm:^2.0.1"
safe-buffer: "npm:^5.0.1"
bin:
sha.js: bin.js
checksum: 10/39c0993592c2ab34eb2daae2199a2a1d502713765aecb611fd97c0c4ab7cd53e902d628e1962aaf384bafd28f55951fef46dcc78799069ce41d74b03aa13b5a7
sha.js: ./bin.js
checksum: 10/d833bfa3e0a67579a6ce6e1bc95571f05246e0a441dd8c76e3057972f2a3e098465687a4369b07e83a0375a88703577f71b5b2e966809e67ebc340dbedb478c7
languageName: node
linkType: hard
@ -31023,17 +31022,6 @@ __metadata:
languageName: node
linkType: hard
"to-buffer@npm:^1.2.0":
version: 1.2.1
resolution: "to-buffer@npm:1.2.1"
dependencies:
isarray: "npm:^2.0.5"
safe-buffer: "npm:^5.2.1"
typed-array-buffer: "npm:^1.0.3"
checksum: 10/f8d03f070b8567d9c949f1b59c8d47c83ed2e59b50b5449258f931df9a1fcb751aa8bb8756a9345adc529b6b1822521157c48e1a7d01779a47185060d7bf96d4
languageName: node
linkType: hard
"to-camel-case@npm:1.0.0":
version: 1.0.0
resolution: "to-camel-case@npm:1.0.0"