All files / web/src/providers models.tsx

100% Statements 76/76
90.47% Branches 19/21
100% Functions 7/7
100% Lines 76/76

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121      1x 1x 1x 1x                 1x 1x 1x 1x 19x 1x 1x                                   1x           1x 54x 54x     54x 54x 54x 54x 54x 54x 54x 54x 11x 11x 11x 54x 54x     54x 54x 54x 54x 54x 54x 54x 16x 38x 54x 9x 9x 9x 54x 54x   54x 2x 54x   54x 1x 54x   54x 54x 54x 54x 54x 54x 54x   54x 54x 54x 1x 53x 54x 54x 54x   54x 54x 54x 54x   54x   1x 55x 55x 2x 2x 53x 53x  
'use client';
 
import type { Model, ModelQueryParams } from '@shared/types/data/model';
import { useQuery } from '@tanstack/react-query';
import { getModels } from '@web/api/v1/super-agents/models';
import { getSkillModels } from '@web/api/v1/super-agents/skills';
import {
  createContext,
  type ReactNode,
  useCallback,
  useContext,
  useState,
} from 'react';
 
// Query keys for models
export const modelQueryKeys = {
  all: ['models'] as const,
  lists: () => [...modelQueryKeys.all, 'list'] as const,
  list: (params: ModelQueryParams) =>
    [...modelQueryKeys.lists(), params] as const,
  skillModels: (skillId: string) => ['models', 'skill', skillId] as const,
};
 
interface ModelsContextType {
  models: Model[];
  isLoading: boolean;
  error: string | null;
  queryParams: ModelQueryParams | null;
  setQueryParams: (params: ModelQueryParams | null) => void;
  refetch: () => Promise<void>;
 
  // Skill-specific models
  skillModels: Model[];
  isLoadingSkillModels: boolean;
  skillModelsError: string | null;
  setSkillId: (skillId: string | null) => void;
  refetchSkillModels: () => Promise<void>;
}
 
const ModelsContext = createContext<ModelsContextType | undefined>(undefined);
 
interface ModelsProviderProps {
  children: ReactNode;
}
 
export function ModelsProvider({ children }: ModelsProviderProps) {
  const [queryParams, setQueryParams] = useState<ModelQueryParams | null>(null);
  const [skillId, setSkillId] = useState<string | null>(null);
 
  // Fetch all models using React Query
  const {
    data: models = [],
    isLoading,
    error: queryError,
    refetch: refetchQuery,
  } = useQuery({
    queryKey: queryParams ? modelQueryKeys.list(queryParams) : ['models-null'],
    queryFn: () => {
      if (!queryParams) return [];
      return getModels(queryParams);
    },
    enabled: !!queryParams,
  });
 
  // Fetch skill-specific models using React Query
  const {
    data: skillModels = [],
    isLoading: isLoadingSkillModels,
    error: skillModelsQueryError,
    refetch: refetchSkillModelsQuery,
  } = useQuery({
    queryKey: skillId
      ? modelQueryKeys.skillModels(skillId)
      : ['skill-models-null'],
    queryFn: () => {
      if (!skillId) return [];
      return getSkillModels(skillId);
    },
    enabled: !!skillId,
  });
 
  const refetch = useCallback(async () => {
    await refetchQuery();
  }, [refetchQuery]);
 
  const refetchSkillModels = useCallback(async () => {
    await refetchSkillModelsQuery();
  }, [refetchSkillModelsQuery]);
 
  const contextValue: ModelsContextType = {
    models,
    isLoading,
    error: queryError ? (queryError as Error).message : null,
    queryParams,
    setQueryParams,
    refetch,
 
    skillModels,
    isLoadingSkillModels,
    skillModelsError: skillModelsQueryError
      ? (skillModelsQueryError as Error).message
      : null,
    setSkillId,
    refetchSkillModels,
  };
 
  return (
    <ModelsContext.Provider value={contextValue}>
      {children}
    </ModelsContext.Provider>
  );
}
 
export function useModels(): ModelsContextType {
  const context = useContext(ModelsContext);
  if (!context) {
    throw new Error('useModels must be used within a ModelsProvider');
  }
  return context;
}