C2MV's picture
Deploy Open Notebook to HuggingFace Spaces
bd0c393
|
Raw
History Blame Contribute Delete
8.93 kB

Hooks Module

React hooks for API data fetching, state management, and complex workflows (chat, streaming, file handling).

Key Components

  • Query hooks (useNotebookSources, useSource, useSources): TanStack Query wrappers for source data with infinite scroll and refetch strategies
  • Mutation hooks (useCreateSource, useUpdateSource, useDeleteSource, useFileUpload, useRetrySource): Server mutations with toast notifications and cache invalidation
  • Chat hooks (useNotebookChat, useSourceChat): Complex session management, context building, and message streaming
  • Streaming hooks (useAsk): SSE parsing for multi-stage Ask workflows (strategy β†’ answers β†’ final answer)
  • Model/config hooks (useModels, useSettings, useTransformations): Application-level settings and model management
  • Utility hooks (useMediaQuery, useToast, useNavigation, useAuth): UI state and auth checking
  • i18n hook (useTranslation): Thin wrapper around react-i18next with t('section.key') pattern and language switching

Important Patterns

  • TanStack Query integration: All data hooks use useQuery/useMutation with QUERY_KEYS for cache consistency
  • Optimistic updates: Mutations add local state before server response (e.g., notebook chat messages)
  • Cache invalidation: Broad invalidation of query keys on mutations (e.g., ['sources'] catches all source queries)
  • Auto-refetch on return: refetchOnWindowFocus: true on frequently-changing data (sources, notebooks)
  • Manual refetch controls: Hooks return refetch() for parent components to trigger refresh
  • SSE streaming pattern: useAsk manually parses newline-delimited JSON from /api/search/ask; handles incomplete buffers
  • Status polling: useSourceStatus auto-refetches every 2s while status === 'running' | 'queued' | 'new'
  • Context building: useNotebookChat.buildContext() assembles selected sources + notes with token/char counts
  • i18n pattern: useTranslation returns standard react-i18next t function; access translations via t('section.key')

Key Dependencies

  • @tanstack/react-query: Data fetching and caching
  • sonner: Toast notifications
  • @/lib/api/*: API module exports (sourcesApi, chatApi, searchApi, etc.)
  • @/lib/types/api: TypeScript response types
  • Zustand stores: useAuthStore, modal managers

How to Add New Hooks

  1. Data queries: Create useQuery hook wrapping API call; use QUERY_KEYS.entityName(id) for cache key
  2. Mutations: Create useMutation hook with onSuccess cache invalidation + toast feedback
  3. Complex state: Use useState + callbacks for local state (see useAsk, useNotebookChat)
  4. Return shape: Export object with both state and action functions for composability

Important Quirks & Gotchas

  • Cache invalidation breadth: Invalidating ['sources'] affects ALL source queries; be precise if performance matters
  • Optimistic updates + error handling: useNotebookChat removes optimistic messages on error; ensure cleanup
  • SSE buffer handling: useAsk keeps incomplete lines in buffer between reads; incomplete JSON silently skipped
  • Model override timing: useNotebookChat stores pending model override if no session exists; applied on session creation
  • Pagination cursor: useNotebookSources uses offset-based pagination; nextOffset calculated from page size
  • Status polling race: useSourceStatus may refetch stale data before server catches up; retry logic has 3-attempt limit
  • Keyboard trap in dialogs: Some hooks manage modal state; ensure Dialog/Modal components handle escape key properly
  • Form data handling: useFileUpload and source creation convert JSON fields to strings in FormData
  • useTranslation: Thin wrapper preserving setLanguage with language change events for LanguageLoadingOverlay

Testing Patterns

// Mock API
const mockApi = {
  list: vi.fn().mockResolvedValue([...])
}

// Test hook with QueryClientProvider + wrapper
render(<Component />, { wrapper: QueryClientProvider })

// Assert mutations trigger cache invalidation
await waitFor(() => expect(queryClient.invalidateQueries).toHaveBeenCalled())

Credentials Hooks (use-credentials.ts)

Hooks for managing AI provider credentials with TanStack Query integration, toast notifications, and cache invalidation.

Query Keys

export const CREDENTIAL_QUERY_KEYS = {
  all: ['credentials'] as const,
  status: ['credentials', 'status'] as const,
  envStatus: ['credentials', 'env-status'] as const,
  byProvider: (provider: string) => ['credentials', 'provider', provider] as const,
  detail: (id: string) => ['credentials', id] as const,
}

Query Hooks

Hook Description Returns
useCredentialStatus() Get configuration status of all providers { configured, source, encryption_configured }
useEnvStatus() Get which providers have env vars set { [provider]: boolean }
useCredentials(provider?) List all credentials (optional filter) Credential[]
useCredentialsByProvider(provider) List credentials for a specific provider Credential[]
useCredential(credentialId) Get a specific credential Credential

Mutation Hooks

Hook Description Cache Invalidation
useCreateCredential() Create new credential all, providers
useUpdateCredential() Update credential all, providers
useDeleteCredential() Delete credential all, models, providers
useTestCredential() Test credential connection None (stores result locally)
useDiscoverModels() Discover models for credential None
useRegisterModels() Register discovered models models, all
useMigrateFromEnv() Migrate from env vars status, envStatus, models, providers
useMigrateFromProviderConfig() Migrate from legacy ProviderConfig status, envStatus, models, providers

useTestCredential Details

Returns extended interface with local state management for test results:

const {
  testCredential,        // (credentialId: string) => void
  testCredentialAsync,   // (credentialId: string) => Promise<TestConnectionResult>
  isPending,             // boolean
  testResults,           // Record<string, TestConnectionResult>
  clearResult,           // (credentialId: string) => void
} = useTestCredential()

Cache Invalidation Strategy

All mutation hooks invalidate:

  • CREDENTIAL_QUERY_KEYS.all β€” refreshes all credential queries (cascades to filtered queries)
  • MODEL_QUERY_KEYS.providers β€” refreshes provider list

Delete hook additionally invalidates:

  • MODEL_QUERY_KEYS.models β€” refreshes full model list (linked models may be deleted)

Migration hooks additionally invalidate:

  • CREDENTIAL_QUERY_KEYS.status β€” refreshes configured/source info
  • CREDENTIAL_QUERY_KEYS.envStatus β€” refreshes env var status

Usage Example

import {
  useCredentialStatus,
  useCredentials,
  useCreateCredential,
  useTestCredential,
  useMigrateFromEnv
} from '@/lib/hooks/use-credentials'

function CredentialSettings() {
  const { data: status, isLoading } = useCredentialStatus()
  const { data: credentials } = useCredentials()
  const createCredential = useCreateCredential()
  const { testCredential, testResults, isPending } = useTestCredential()
  const migrateFromEnv = useMigrateFromEnv()

  const handleCreate = () => {
    createCredential.mutate({
      name: 'My OpenAI Key',
      provider: 'openai',
      modalities: ['language', 'embedding'],
      api_key: 'sk-...'
    })
  }

  const handleTest = (credentialId: string) => {
    testCredential(credentialId)
  }

  const handleMigrate = () => {
    migrateFromEnv.mutate()
  }

  return (
    <div>
      {credentials?.map(cred => (
        <div key={cred.id}>
          <span>{cred.name} ({cred.provider})</span>
          <button onClick={() => handleTest(cred.id)} disabled={isPending}>Test</button>
          {testResults[cred.id]?.success && <span>Connected!</span>}
        </div>
      ))}
      <button onClick={handleCreate}>Add Credential</button>
      <button onClick={handleMigrate}>Migrate from .env</button>
    </div>
  )
}

Important Notes

  • Toast notifications: All mutations show success/error toasts automatically
  • i18n integration: Toast messages use translation keys from t('apiKeys.*') and t('common.*')
  • Error handling: Uses getApiErrorKey() utility to extract error messages from API responses
  • Local test results: useTestCredential stores results in local state (not cached in TanStack Query)
  • Migration feedback: Migration hooks show different toasts based on migrated/skipped/error counts