@@ -3,22 +3,46 @@ import {useCallback, useEffect, useRef, useState} from 'react';
33import { addErrorMessage } from 'sentry/actionCreators/indicator' ;
44import { t } from 'sentry/locale' ;
55import { parseQueryKey } from 'sentry/utils/api/apiQueryKey' ;
6+ import { getApiUrl } from 'sentry/utils/api/getApiUrl' ;
67import { fetchMutation , useApiQuery , useQueryClient } from 'sentry/utils/queryClient' ;
78import { useOrganization } from 'sentry/utils/useOrganization' ;
89import type { SeerExplorerResponse } from 'sentry/views/seerExplorer/hooks/useSeerExplorer' ;
910import { makeSeerExplorerQueryKey } from 'sentry/views/seerExplorer/utils' ;
1011
1112import { extractDashboardFromSession , statusIsTerminal } from './createFromSeerUtils' ;
12- import type { Widget } from './types' ;
13+ import type { DashboardDetails , Widget } from './types' ;
1314
1415const POLL_INTERVAL_MS = 500 ;
1516const POST_COMPLETE_POLL_MS = 5000 ;
1617
18+ async function startDashboardEditSession (
19+ orgSlug : string ,
20+ message : string ,
21+ dashboard : Pick < DashboardDetails , 'title' | 'widgets' >
22+ ) : Promise < number > {
23+ const url = getApiUrl ( '/organizations/$organizationIdOrSlug/dashboards/generate/' , {
24+ path : { organizationIdOrSlug : orgSlug } ,
25+ } ) ;
26+ const response = await fetchMutation < { run_id : string } > ( {
27+ url,
28+ method : 'POST' ,
29+ data : {
30+ prompt : message ,
31+ current_dashboard : {
32+ title : dashboard . title ,
33+ widgets : dashboard . widgets ,
34+ } ,
35+ } ,
36+ } ) ;
37+ return Number ( response . run_id ) ;
38+ }
39+
1740interface UseSeerDashboardSessionOptions {
1841 onDashboardUpdate : ( data : { title : string ; widgets : Widget [ ] } ) => void ;
19- seerRunId : number | null ;
42+ dashboard ?: Pick < DashboardDetails , 'title' | 'widgets' > ;
2043 enabled ?: boolean ;
2144 onPostCompletePollEnd ?: ( ) => void ;
45+ seerRunId ?: number | null ;
2246}
2347
2448interface UseSeerDashboardSessionResult {
@@ -34,14 +58,18 @@ interface UseSeerDashboardSessionResult {
3458 * detecting terminal-state transitions, and sending follow-up messages.
3559 */
3660export function useSeerDashboardSession ( {
37- seerRunId,
61+ seerRunId : externalSeerRunId ,
62+ dashboard,
3863 onDashboardUpdate,
3964 enabled = true ,
4065 onPostCompletePollEnd,
4166} : UseSeerDashboardSessionOptions ) : UseSeerDashboardSessionResult {
4267 const organization = useOrganization ( ) ;
4368 const queryClient = useQueryClient ( ) ;
4469
70+ const [ internalRunId , setInternalRunId ] = useState < number | null > ( null ) ;
71+ const seerRunId = externalSeerRunId ?? internalRunId ;
72+
4573 const [ isUpdating , setIsUpdating ] = useState ( false ) ;
4674
4775 const prevSessionStatusRef = useRef < {
@@ -106,26 +134,41 @@ export function useSeerDashboardSession({
106134
107135 const sendFollowUpMessage = useCallback (
108136 async ( message : string ) => {
109- if ( ! seerRunId ) {
137+ if ( ! seerRunId && ! dashboard ) {
110138 return ;
111139 }
112140 setIsUpdating ( true ) ;
113141 completedAtRef . current = null ;
142+ const errorMessage = t ( 'Failed to send message' ) ;
114143 try {
115- const queryKey = makeSeerExplorerQueryKey ( organization . slug , seerRunId ) ;
116- const { url} = parseQueryKey ( queryKey ) ;
117- await fetchMutation ( {
118- url,
119- method : 'POST' ,
120- data : { query : message } ,
121- } ) ;
122- queryClient . invalidateQueries ( { queryKey} ) ;
144+ if ( ! seerRunId && dashboard ) {
145+ // No session exists yet and an initial dashboard is provided, start a new Seer session
146+ const runId = await startDashboardEditSession (
147+ organization . slug ,
148+ message ,
149+ dashboard
150+ ) ;
151+ if ( ! runId ) {
152+ throw new Error ( 'Failed to start dashboard editing session' ) ;
153+ }
154+ setInternalRunId ( runId ) ;
155+ } else {
156+ // A session exists, send the message to the existing session
157+ const queryKey = makeSeerExplorerQueryKey ( organization . slug , seerRunId ) ;
158+ const { url} = parseQueryKey ( queryKey ) ;
159+ await fetchMutation ( {
160+ url,
161+ method : 'POST' ,
162+ data : { query : message } ,
163+ } ) ;
164+ queryClient . invalidateQueries ( { queryKey} ) ;
165+ }
123166 } catch {
124167 setIsUpdating ( false ) ;
125- addErrorMessage ( t ( 'Failed to send message' ) ) ;
168+ addErrorMessage ( errorMessage ) ;
126169 }
127170 } ,
128- [ organization . slug , queryClient , seerRunId ]
171+ [ organization . slug , queryClient , seerRunId , dashboard ]
129172 ) ;
130173
131174 return {
0 commit comments