Filemedium importancesource

useSkillImprovementSurvey.ts

hooks/useSkillImprovementSurvey.ts

No strong subsystem tag
106
Lines
3528
Bytes
1
Exports
8
Imports
10
Keywords

What this is

This page documents one file from the repository and includes its full source so you can read it without leaving the docs site.

Beginner explanation

This file is one piece of the larger system. Its name, directory, imports, and exports show where it fits. Start by reading the exports and related files first.

How it is used

Start from the exports list and related files. Those are the easiest clues for where this file fits into the system.

Expert explanation

Architecturally, this file intersects with general runtime concerns. It contains 106 lines, 8 detected imports, and 1 detected exports.

Important relationships

Detected exports

  • useSkillImprovementSurvey

Keywords

suggestioncurrentprevskillimprovementskillnamesetmessagesutilsanalyticsmetadata_i_verified_this_is_not_code_or_filepathsmessageisopen

Detected imports

  • react
  • ../components/FeedbackSurvey/utils.js
  • ../services/analytics/index.js
  • ../state/AppState.js
  • ../types/message.js
  • ../utils/hooks/skillImprovement.js
  • ../utils/hooks/skillImprovement.js
  • ../utils/messages.js

Source notes

This page embeds the full file contents. Small or leaf files are still indexed honestly instead of being over-explained.

Open parent directory

Full source

import { useCallback, useRef, useState } from 'react'
import type { FeedbackSurveyResponse } from '../components/FeedbackSurvey/utils.js'
import {
  type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
  type AnalyticsMetadata_I_VERIFIED_THIS_IS_PII_TAGGED,
  logEvent,
} from '../services/analytics/index.js'
import { useAppState, useSetAppState } from '../state/AppState.js'
import type { Message } from '../types/message.js'
import type { SkillUpdate } from '../utils/hooks/skillImprovement.js'
import { applySkillImprovement } from '../utils/hooks/skillImprovement.js'
import { createSystemMessage } from '../utils/messages.js'

type SkillImprovementSuggestion = {
  skillName: string
  updates: SkillUpdate[]
}

type SetMessages = (fn: (prev: Message[]) => Message[]) => void

export function useSkillImprovementSurvey(setMessages: SetMessages): {
  isOpen: boolean
  suggestion: SkillImprovementSuggestion | null
  handleSelect: (selected: FeedbackSurveyResponse) => void
} {
  const suggestion = useAppState(s => s.skillImprovement.suggestion)
  const setAppState = useSetAppState()
  const [isOpen, setIsOpen] = useState(false)
  const lastSuggestionRef = useRef(suggestion)
  const loggedAppearanceRef = useRef(false)

  // Track the suggestion for display even after clearing AppState
  if (suggestion) {
    lastSuggestionRef.current = suggestion
  }

  // Open when a new suggestion arrives
  if (suggestion && !isOpen) {
    setIsOpen(true)
    if (!loggedAppearanceRef.current) {
      loggedAppearanceRef.current = true
      logEvent('tengu_skill_improvement_survey', {
        event_type:
          'appeared' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
        // _PROTO_skill_name routes to the privileged skill_name BQ column.
        // Unredacted names don't go in additional_metadata.
        _PROTO_skill_name: (suggestion.skillName ??
          'unknown') as AnalyticsMetadata_I_VERIFIED_THIS_IS_PII_TAGGED,
      })
    }
  }

  const handleSelect = useCallback(
    (selected: FeedbackSurveyResponse) => {
      const current = lastSuggestionRef.current
      if (!current) return

      const applied = selected !== 'dismissed'

      logEvent('tengu_skill_improvement_survey', {
        event_type:
          'responded' as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
        response: (applied
          ? 'applied'
          : 'dismissed') as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
        // _PROTO_skill_name routes to the privileged skill_name BQ column.
        // Unredacted names don't go in additional_metadata.
        _PROTO_skill_name:
          current.skillName as AnalyticsMetadata_I_VERIFIED_THIS_IS_PII_TAGGED,
      })

      if (applied) {
        void applySkillImprovement(current.skillName, current.updates).then(
          () => {
            setMessages(prev => [
              ...prev,
              createSystemMessage(
                `Skill "${current.skillName}" updated with improvements.`,
                'suggestion',
              ),
            ])
          },
        )
      }

      // Close and clear
      setIsOpen(false)
      loggedAppearanceRef.current = false
      setAppState(prev => {
        if (!prev.skillImprovement.suggestion) return prev
        return {
          ...prev,
          skillImprovement: { suggestion: null },
        }
      })
    },
    [setAppState, setMessages],
  )

  return {
    isOpen,
    suggestion: lastSuggestionRef.current,
    handleSelect,
  }
}