Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion src/components/GeneralPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ import ImportAction from './ImportAction';
import NewChatModal from './NewChatModal';
import Prompt from './Prompt';
import ReadinessAlert from './ReadinessAlert';
import QueryBrowserGraph from './QueryBrowserGraph';
import ResponseTools from './ResponseTools';
import WelcomeNotice from './WelcomeNotice';

Expand Down Expand Up @@ -94,7 +95,18 @@ const isURL = (s: string): boolean => {
}
};

const Code = ({ children }: { children?: React.ReactNode }) => {
type CodeProps = {
children?: React.ReactNode;
className?: string;
};

const Code: React.FC<CodeProps> = ({ children, className }) => {
const isPromQL = className?.includes('language-promql');

if (isPromQL && children) {
return <QueryBrowserGraph query={String(children).trim()} />;
}

if (!children || !String(children).includes('\n')) {
return <code>{children}</code>;
}
Expand Down
3 changes: 2 additions & 1 deletion src/components/Prompt.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { FileCodeIcon, FileUploadIcon, InfoCircleIcon, TaskIcon } from '@pattern

import { AttachmentTypes, toOLSAttachment } from '../attachments';
import { getApiUrl } from '../config';
import { LLM_INSTRUCTIONS } from '../llm-instructions';
import { getFetchErrorMessage } from '../error';
import { getRequestInitWithAuthHeader } from '../hooks/useAuth';
import { useBoolean } from '../hooks/useBoolean';
Expand Down Expand Up @@ -498,7 +499,7 @@ const Prompt: React.FC<PromptProps> = ({ scrollIntoView }) => {
conversation_id: conversationID,
// eslint-disable-next-line camelcase
media_type: 'application/json',
query,
query: `${query}\n\n${LLM_INSTRUCTIONS}`,
};

const streamResponse = async () => {
Expand Down
49 changes: 49 additions & 0 deletions src/components/QueryBrowserGraph.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import * as React from 'react';
import { debounce } from 'lodash';
import { QueryBrowser } from '@openshift-console/dynamic-plugin-sdk';
import { Spinner, TextArea } from '@patternfly/react-core';

const QueryBrowserGraph: React.FC<{ query: string }> = ({ query: initialQuery }) => {
const [inputValue, setInputValue] = React.useState('');
const [query, setQuery] = React.useState(initialQuery);

const debouncedSetQuery = React.useMemo(
() =>
debounce((value: string) => {
setQuery(value);
}, 500),
[],
);

const effectiveQuery = inputValue || initialQuery;

React.useEffect(() => {
debouncedSetQuery(effectiveQuery);
}, [debouncedSetQuery, effectiveQuery]);

const onChange = React.useCallback(
(_event: React.ChangeEvent<HTMLTextAreaElement>, value: string) => {
setInputValue(value);
},
[],
);

return (
<>
<React.Suspense fallback={<Spinner size="md" />}>
<QueryBrowser queries={[query]} showStackedControl />
</React.Suspense>
<TextArea
aria-label="PromQL query"
autoResize
className="ols-plugin__query-browser-input"
onChange={onChange}
resizeOrientation="vertical"
rows={3}
value={inputValue || initialQuery}
/>
</>
);
};

export default QueryBrowserGraph;
6 changes: 6 additions & 0 deletions src/components/general-page.css
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,9 @@
max-width: 30rem;
text-align: center;
}

.ols-plugin__query-browser-input {
font-size: var(--pf-t--global--font--size--body--sm);
margin-bottom: var(--pf-t--global--spacer--lg);
margin-top: -25px;
}
13 changes: 13 additions & 0 deletions src/llm-instructions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export const LLM_INSTRUCTIONS = `
## Frontend rendering capabilities

The OpenShift Lightspeed console UI has special rendering capabilities for certain code block types. When appropriate, use these features to provide more helpful and visual responses, but only when they are more helpful than plain text or code examples.

### PromQL line graphs

The frontend can render Prometheus metrics as line graphs. Each \`\`\`promql code block in your response will automatically generate a corresponding line graph.

Only include PromQL when the user is explicitly asking for Prometheus metrics, monitoring data, alerts, or quantitative troubleshooting (for example: CPU/memory usage, rates, latency, error counts, “show me”, “how much”, “query”, or “graph”). For conceptual or definition questions that do not request metrics (for example: “what is a node?”), do not include PromQL.

When you include PromQL, use a \`\`\`promql code block. Each \`\`\`promql code block must contain exactly one PromQL query and must be valid PromQL that can be run as-is.
`.trim();