source dump of claude code
at main 105 lines 3.5 kB view raw
1import { useCallback, useRef, useState } from 'react' 2import type { FeedbackSurveyResponse } from '../components/FeedbackSurvey/utils.js' 3import { 4 type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, 5 type AnalyticsMetadata_I_VERIFIED_THIS_IS_PII_TAGGED, 6 logEvent, 7} from '../services/analytics/index.js' 8import { useAppState, useSetAppState } from '../state/AppState.js' 9import type { Message } from '../types/message.js' 10import type { SkillUpdate } from '../utils/hooks/skillImprovement.js' 11import { applySkillImprovement } from '../utils/hooks/skillImprovement.js' 12import { createSystemMessage } from '../utils/messages.js' 13 14type SkillImprovementSuggestion = { 15 skillName: string 16 updates: SkillUpdate[] 17} 18 19type SetMessages = (fn: (prev: Message[]) => Message[]) => void 20 21export function useSkillImprovementSurvey(setMessages: SetMessages): { 22 isOpen: boolean 23 suggestion: SkillImprovementSuggestion | null 24 handleSelect: (selected: FeedbackSurveyResponse) => void 25} { 26 const suggestion = useAppState(s => s.skillImprovement.suggestion) 27 const setAppState = useSetAppState() 28 const [isOpen, setIsOpen] = useState(false) 29 const lastSuggestionRef = useRef(suggestion) 30 const loggedAppearanceRef = useRef(false) 31 32 // Track the suggestion for display even after clearing AppState 33 if (suggestion) { 34 lastSuggestionRef.current = suggestion 35 } 36 37 // Open when a new suggestion arrives 38 if (suggestion && !isOpen) { 39 setIsOpen(true) 40 if (!loggedAppearanceRef.current) { 41 loggedAppearanceRef.current = true 42 logEvent('tengu_skill_improvement_survey', { 43 event_type: 44 'appeared' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, 45 // _PROTO_skill_name routes to the privileged skill_name BQ column. 46 // Unredacted names don't go in additional_metadata. 47 _PROTO_skill_name: (suggestion.skillName ?? 48 'unknown') as AnalyticsMetadata_I_VERIFIED_THIS_IS_PII_TAGGED, 49 }) 50 } 51 } 52 53 const handleSelect = useCallback( 54 (selected: FeedbackSurveyResponse) => { 55 const current = lastSuggestionRef.current 56 if (!current) return 57 58 const applied = selected !== 'dismissed' 59 60 logEvent('tengu_skill_improvement_survey', { 61 event_type: 62 'responded' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, 63 response: (applied 64 ? 'applied' 65 : 'dismissed') as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, 66 // _PROTO_skill_name routes to the privileged skill_name BQ column. 67 // Unredacted names don't go in additional_metadata. 68 _PROTO_skill_name: 69 current.skillName as AnalyticsMetadata_I_VERIFIED_THIS_IS_PII_TAGGED, 70 }) 71 72 if (applied) { 73 void applySkillImprovement(current.skillName, current.updates).then( 74 () => { 75 setMessages(prev => [ 76 ...prev, 77 createSystemMessage( 78 `Skill "${current.skillName}" updated with improvements.`, 79 'suggestion', 80 ), 81 ]) 82 }, 83 ) 84 } 85 86 // Close and clear 87 setIsOpen(false) 88 loggedAppearanceRef.current = false 89 setAppState(prev => { 90 if (!prev.skillImprovement.suggestion) return prev 91 return { 92 ...prev, 93 skillImprovement: { suggestion: null }, 94 } 95 }) 96 }, 97 [setAppState, setMessages], 98 ) 99 100 return { 101 isOpen, 102 suggestion: lastSuggestionRef.current, 103 handleSelect, 104 } 105}