Skip to content

Commit

Permalink
Begin implementing tool calling (#1645)
Browse files Browse the repository at this point in the history
Co-authored-by: Jake Laderman <[email protected]>
  • Loading branch information
michaeljguarino and jsladerman authored Dec 3, 2024
1 parent 530e337 commit d05fc9f
Show file tree
Hide file tree
Showing 38 changed files with 795 additions and 70 deletions.
18 changes: 11 additions & 7 deletions assets/src/components/ai/AIPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const AIPanel = forwardRef(
subheader,
footer,
children,
secondaryButton,
...props
}: {
open: boolean
Expand All @@ -31,6 +32,7 @@ const AIPanel = forwardRef(
subheader: string
footer?: ReactNode
children: ReactNode
secondaryButton?: ReactNode
} & CardProps,
ref: Ref<HTMLDivElement>
) => {
Expand Down Expand Up @@ -108,13 +110,15 @@ const AIPanel = forwardRef(
},
}}
>
<Button
onClick={onClose}
secondary={!!footer}
floating={!!footer}
>
Got it, thanks!
</Button>
{secondaryButton || (
<Button
onClick={onClose}
secondary={!!footer}
floating={!!footer}
>
Got it, thanks!
</Button>
)}
{footer && footer}
</div>
)}
Expand Down
99 changes: 90 additions & 9 deletions assets/src/components/ai/chatbot/AISuggestFix.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
import { Markdown } from '@pluralsh/design-system'
import { Button, Markdown, PrOpenIcon, Toast } from '@pluralsh/design-system'
import {
Dispatch,
ReactNode,
SetStateAction,
useCallback,
useEffect,
useRef,
useState,
} from 'react'
import { useTheme } from 'styled-components'
import {
AiDelta,
AiInsightFragment,
AiRole,
ChatMessage,
useAiChatStreamSubscription,
useAiFixPrMutation,
useAiSuggestedFixLazyQuery,
} from '../../../generated/graphql.ts'
import { GqlError } from '../../utils/Alert.tsx'
import LoadingIndicator from '../../utils/LoadingIndicator.tsx'
import AIPanel from '../AIPanel.tsx'
import { AISuggestFixButton } from './AISuggestFixButton.tsx'
import { ChatWithAIButton, insightMessage } from './ChatbotButton.tsx'
import { useDeploymentSettings } from 'components/contexts/DeploymentSettingsContext.tsx'

interface AISuggestFixProps {
insight: Nullable<AiInsightFragment>
Expand Down Expand Up @@ -73,7 +77,71 @@ export function Loading({
)
}

function FixPr({
insightId,
fix,
}: {
insightId: string
fix: string
}): ReactNode {
const [mutation, { data, loading, error }] = useAiFixPrMutation({
variables: { insightId, messages: [{ role: AiRole.User, content: fix }] },
})
const theme = useTheme()

// TEMP FIX, implement permanent solution in DS
const successToastRef = useRef<HTMLDivElement>(null)
const errorToastRef = useRef<HTMLDivElement>(null)
useEffect(() => {
if (successToastRef.current) successToastRef.current.style.zIndex = '10000'
if (errorToastRef.current) errorToastRef.current.style.zIndex = '10000'
}, [data?.aiFixPr])

return (
<>
{data?.aiFixPr && (
<Toast
ref={successToastRef}
severity="info"
position="top-right"
margin="large"
heading="PR Created!"
>
<a
href={data?.aiFixPr?.url}
target="_blank"
rel="noreferrer"
style={{ textDecoration: 'none', cursor: 'pointer' }}
color={theme.colors['action-link-inline']}
>
{data?.aiFixPr?.url}
</a>
</Toast>
)}
{error && (
<Toast
ref={errorToastRef}
severity="danger"
position="top-right"
margin="large"
heading="PR Creation Failed"
>
{error.message}
</Toast>
)}
<Button
startIcon={<PrOpenIcon />}
onClick={mutation}
loading={loading}
>
Open PR
</Button>
</>
)
}

function AISuggestFix({ insight }: AISuggestFixProps): ReactNode {
const settings = useDeploymentSettings()
const ref = useRef<HTMLDivElement>(null)
const [streaming, setStreaming] = useState<boolean>(false)
const scrollToBottom = useCallback(() => {
Expand All @@ -99,6 +167,18 @@ function AISuggestFix({ insight }: AISuggestFixProps): ReactNode {
return null
}

const tools = !!settings.ai?.toolsEnabled
const chatButton = (
<ChatWithAIButton
secondary={tools}
insightId={insight?.id}
messages={[
insightMessage(insight),
fixMessage(data?.aiSuggestedFix || ''),
]}
/>
)

return (
<div
css={{
Expand All @@ -114,15 +194,16 @@ function AISuggestFix({ insight }: AISuggestFixProps): ReactNode {
showClosePanel={!!data?.aiSuggestedFix}
header="Suggest a fix"
subheader="Get a suggested fix based on the insight. AI is prone to mistakes, always test changes before application."
secondaryButton={tools ? chatButton : null}
footer={
<ChatWithAIButton
primary
insightId={insight?.id}
messages={[
insightMessage(insight),
fixMessage(data?.aiSuggestedFix || ''),
]}
/>
tools && insight && data?.aiSuggestedFix ? (
<FixPr
insightId={insight.id}
fix={data.aiSuggestedFix}
/>
) : (
chatButton
)
}
>
{data?.aiSuggestedFix && <Markdown text={data?.aiSuggestedFix} />}
Expand Down
2 changes: 1 addition & 1 deletion assets/src/generated/graphql-kubernetes.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable */
/* prettier-ignore */
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
Expand Down
2 changes: 1 addition & 1 deletion assets/src/generated/graphql-plural.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable */
/* prettier-ignore */
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
Expand Down
78 changes: 72 additions & 6 deletions assets/src/generated/graphql.ts

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions assets/src/graph/ai.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,12 @@ mutation DeleteChatThread($id: ID!) {
}
}

mutation AiFixPr($insightId: ID!, $messages: [ChatMessage]) {
aiFixPr(insightId: $insightId, messages: $messages) {
...PullRequest
}
}

subscription AIChatStream($threadId: ID, $insightId: ID, $scopeId: String) {
aiStream(threadId: $threadId, insightId: $insightId, scopeId: $scopeId) {
seq
Expand Down
1 change: 1 addition & 0 deletions assets/src/graph/cdGlobalSettings.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ fragment AiSettings on AiSettings {
location
}
enabled
toolsEnabled
provider
}

Expand Down
46 changes: 30 additions & 16 deletions go/client/models_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions lib/console.ex
Original file line number Diff line number Diff line change
Expand Up @@ -310,5 +310,7 @@ defmodule Console do

def jitter(seconds), do: :rand.uniform(seconds * 2) - seconds

def priv_file!(name), do: Path.join([:code.priv_dir(:console), name]) |> File.read!()

def storage, do: Console.Storage.Git
end
Loading

0 comments on commit d05fc9f

Please sign in to comment.