mirror of
https://github.com/TandoorRecipes/recipes.git
synced 2025-12-24 02:39:20 -05:00
basics of AI provider system
This commit is contained in:
18
cookbook/helper/ai_helper.py
Normal file
18
cookbook/helper/ai_helper.py
Normal file
@@ -0,0 +1,18 @@
|
||||
from django.utils import timezone
|
||||
from django.db.models import Sum
|
||||
|
||||
from cookbook.models import AiLog
|
||||
|
||||
|
||||
def get_monthly_token_usage(space):
|
||||
"""
|
||||
returns the number of credits the space has used in the current month
|
||||
"""
|
||||
return AiLog.objects.filter(space=space, credits_from_balance=False, created_at__month=timezone.now().month).aggregate(Sum('credit_cost'))['credit_cost__sum']
|
||||
|
||||
|
||||
def has_monthly_token(space):
|
||||
"""
|
||||
checks if the monthly credit limit has been exceeded
|
||||
"""
|
||||
return get_monthly_token_usage(space) < space.ai_credits_monthly
|
||||
@@ -330,6 +330,21 @@ class CustomRecipePermission(permissions.BasePermission):
|
||||
return ((has_group_permission(request.user, ['guest']) and request.method in SAFE_METHODS)
|
||||
or has_group_permission(request.user, ['user'])) and obj.space == request.space
|
||||
|
||||
class CustomAiProviderPermission(permissions.BasePermission):
|
||||
"""
|
||||
Custom permission class for the AiProvider api endpoint
|
||||
"""
|
||||
message = _('You do not have the required permissions to view this page!')
|
||||
|
||||
def has_permission(self, request, view): # user is either at least a user and the request is safe
|
||||
return (has_group_permission(request.user, ['user']) and request.method in SAFE_METHODS) or (has_group_permission(request.user, ['admin']) or request.user.is_superuser)
|
||||
|
||||
# editing of global providers allowed for superusers, space providers by admins and users can read only access
|
||||
def has_object_permission(self, request, view, obj):
|
||||
return ((obj.space is None and request.user.is_superuser)
|
||||
or (obj.space == request.space and has_group_permission(request.user, ['admin']))
|
||||
or (obj.space == request.space and has_group_permission(request.user, ['user']) and request.method in SAFE_METHODS))
|
||||
|
||||
|
||||
class CustomUserPermission(permissions.BasePermission):
|
||||
"""
|
||||
|
||||
@@ -411,6 +411,8 @@ class AiProvider(models.Model):
|
||||
|
||||
|
||||
class AiLog(models.Model, PermissionModelMixin):
|
||||
F_FILE_IMPORT = 'FILE_IMPORT'
|
||||
|
||||
ai_provider = models.ForeignKey(AiProvider, on_delete=models.SET_NULL, null=True)
|
||||
function = models.CharField(max_length=64)
|
||||
credit_cost = models.DecimalField(max_digits=16, decimal_places=4)
|
||||
|
||||
@@ -24,6 +24,7 @@ from rest_framework.fields import IntegerField
|
||||
|
||||
from cookbook.helper.CustomStorageClass import CachedS3Boto3Storage
|
||||
from cookbook.helper.HelperFunctions import str2bool
|
||||
from cookbook.helper.ai_helper import get_monthly_token_usage
|
||||
from cookbook.helper.image_processing import is_file_type_allowed
|
||||
from cookbook.helper.permission_helper import above_space_limit
|
||||
from cookbook.helper.property_helper import FoodPropertyHelper
|
||||
@@ -36,7 +37,7 @@ from cookbook.models import (Automation, BookmarkletImport, Comment, CookLog, Cu
|
||||
ShareLink, ShoppingListEntry, ShoppingListRecipe, Space,
|
||||
Step, Storage, Supermarket, SupermarketCategory,
|
||||
SupermarketCategoryRelation, Sync, SyncLog, Unit, UnitConversion,
|
||||
UserFile, UserPreference, UserSpace, ViewLog, ConnectorConfig, SearchPreference, SearchFields, AiLog)
|
||||
UserFile, UserPreference, UserSpace, ViewLog, ConnectorConfig, SearchPreference, SearchFields, AiLog, AiProvider)
|
||||
from cookbook.templatetags.custom_tags import markdown
|
||||
from recipes.settings import AWS_ENABLED, MEDIA_URL, EMAIL_HOST
|
||||
|
||||
@@ -353,7 +354,7 @@ class SpaceSerializer(WritableNestedModelSerializer):
|
||||
|
||||
@extend_schema_field(int)
|
||||
def get_ai_monthly_credits_used(self, obj):
|
||||
return AiLog.objects.filter(space=obj, credits_from_balance=False).aggregate(Sum('credit_cost'))['credit_cost__sum']
|
||||
return get_monthly_token_usage(obj)
|
||||
|
||||
@extend_schema_field(float)
|
||||
def get_file_size_mb(self, obj):
|
||||
@@ -402,6 +403,33 @@ class SpacedModelSerializer(serializers.ModelSerializer):
|
||||
return super().create(validated_data)
|
||||
|
||||
|
||||
class AiProviderSerializer(serializers.ModelSerializer):
|
||||
|
||||
def create(self, validated_data):
|
||||
if not self.context['request'].user.is_superuser:
|
||||
validated_data['space'] = self.context['request'].space
|
||||
return super().create(validated_data)
|
||||
|
||||
class Meta:
|
||||
model = AiProvider
|
||||
fields = ('id','name', 'description', 'api_key', 'model_name', 'url', 'space', 'created_at', 'updated_at')
|
||||
read_only_fields = ('created_at', 'updated_at',)
|
||||
|
||||
extra_kwargs = {
|
||||
'api_key': {'write_only': True},
|
||||
}
|
||||
|
||||
|
||||
class AiLogSerializer(serializers.ModelSerializer):
|
||||
ai_provider = AiProviderSerializer(read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = AiLog
|
||||
fields = ('id', 'ai_provider', 'function', 'credit_cost', 'credits_from_balance', 'input_tokens', 'output_tokens', 'start_time', 'end_time', 'created_by', 'created_at',
|
||||
'updated_at')
|
||||
read_only_fields = ('__all__',)
|
||||
|
||||
|
||||
class MealTypeSerializer(SpacedModelSerializer, WritableNestedModelSerializer):
|
||||
|
||||
def create(self, validated_data):
|
||||
@@ -1794,6 +1822,7 @@ class RecipeFromSourceResponseSerializer(serializers.Serializer):
|
||||
|
||||
|
||||
class AiImportSerializer(serializers.Serializer):
|
||||
ai_provider_id = serializers.IntegerField()
|
||||
file = serializers.FileField(allow_null=True)
|
||||
text = serializers.CharField(allow_null=True, allow_blank=True)
|
||||
recipe_id = serializers.CharField(allow_null=True, allow_blank=True)
|
||||
|
||||
@@ -61,6 +61,8 @@ router.register(r'search-preference', api.SearchPreferenceViewSet)
|
||||
router.register(r'user-space', api.UserSpaceViewSet)
|
||||
router.register(r'view-log', api.ViewLogViewSet)
|
||||
router.register(r'access-token', api.AccessTokenViewSet)
|
||||
router.register(r'ai-provider', api.AiProviderViewSet)
|
||||
router.register(r'ai-log', api.AiLogViewSet)
|
||||
|
||||
router.register(r'localization', api.LocalizationViewSet, basename='localization')
|
||||
router.register(r'server-settings', api.ServerSettingsViewSet, basename='server-settings')
|
||||
|
||||
@@ -74,7 +74,7 @@ from cookbook.helper.permission_helper import (CustomIsAdmin, CustomIsOwner, Cus
|
||||
CustomTokenHasScope, CustomUserPermission, IsReadOnlyDRF,
|
||||
above_space_limit,
|
||||
group_required, has_group_permission, is_space_owner,
|
||||
switch_user_active_space
|
||||
switch_user_active_space, CustomAiProviderPermission
|
||||
)
|
||||
from cookbook.helper.recipe_search import RecipeSearch
|
||||
from cookbook.helper.recipe_url_import import clean_dict, get_from_youtube_scraper, get_images_from_soup
|
||||
@@ -85,7 +85,7 @@ from cookbook.models import (Automation, BookmarkletImport, ConnectorConfig, Coo
|
||||
RecipeBookEntry, ShareLink, ShoppingListEntry,
|
||||
ShoppingListRecipe, Space, Step, Storage, Supermarket, SupermarketCategory,
|
||||
SupermarketCategoryRelation, Sync, SyncLog, Unit, UnitConversion,
|
||||
UserFile, UserPreference, UserSpace, ViewLog, RecipeImport, SearchPreference, SearchFields
|
||||
UserFile, UserPreference, UserSpace, ViewLog, RecipeImport, SearchPreference, SearchFields, AiLog, AiProvider
|
||||
)
|
||||
from cookbook.provider.dropbox import Dropbox
|
||||
from cookbook.provider.local import Local
|
||||
@@ -110,7 +110,8 @@ from cookbook.serializer import (AccessTokenSerializer, AutomationSerializer, Au
|
||||
UserSerializer, UserSpaceSerializer, ViewLogSerializer,
|
||||
LocalizationSerializer, ServerSettingsSerializer, RecipeFromSourceResponseSerializer, ShoppingListEntryBulkCreateSerializer, FdcQuerySerializer,
|
||||
AiImportSerializer, ImportOpenDataSerializer, ImportOpenDataMetaDataSerializer, ImportOpenDataResponseSerializer, ExportRequestSerializer,
|
||||
RecipeImportSerializer, ConnectorConfigSerializer, SearchPreferenceSerializer, SearchFieldsSerializer, RecipeBatchUpdateSerializer
|
||||
RecipeImportSerializer, ConnectorConfigSerializer, SearchPreferenceSerializer, SearchFieldsSerializer, RecipeBatchUpdateSerializer,
|
||||
AiProviderSerializer, AiLogSerializer
|
||||
)
|
||||
from cookbook.version_info import TANDOOR_VERSION
|
||||
from cookbook.views.import_export import get_integration
|
||||
@@ -617,6 +618,29 @@ class SearchPreferenceViewSet(LoggingMixin, viewsets.ModelViewSet):
|
||||
return self.queryset.filter(user=self.request.user)
|
||||
|
||||
|
||||
class AiProviderViewSet(LoggingMixin, viewsets.ModelViewSet):
|
||||
queryset = AiProvider.objects
|
||||
serializer_class = AiProviderSerializer
|
||||
permission_classes = [CustomAiProviderPermission & CustomTokenHasReadWriteScope]
|
||||
pagination_class = DefaultPagination
|
||||
|
||||
def get_queryset(self):
|
||||
# read only access to all space and global AiProviders
|
||||
with scopes_disabled():
|
||||
return self.queryset.filter(Q(space=self.request.space) | Q(space__isnull=True))
|
||||
|
||||
|
||||
class AiLogViewSet(LoggingMixin, viewsets.ModelViewSet):
|
||||
queryset = AiLog.objects
|
||||
serializer_class = AiLogSerializer
|
||||
permission_classes = [CustomIsUser & CustomTokenHasReadWriteScope]
|
||||
http_method_names = ['get']
|
||||
pagination_class = DefaultPagination
|
||||
|
||||
def get_queryset(self):
|
||||
return self.queryset.filter(space=self.request.space)
|
||||
|
||||
|
||||
class StorageViewSet(LoggingMixin, viewsets.ModelViewSet):
|
||||
# TODO handle delete protect error and adjust test
|
||||
queryset = Storage.objects
|
||||
@@ -2000,14 +2024,28 @@ class AiImportView(APIView):
|
||||
if serializer.is_valid():
|
||||
# TODO max file size check
|
||||
|
||||
if 'ai_provider_id' not in serializer.validated_data:
|
||||
response = {
|
||||
'error': True,
|
||||
'msg': 'You must select an AI provider to perform your request',
|
||||
}
|
||||
return Response(RecipeFromSourceResponseSerializer(context={'request': request}).to_representation(response), status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
ai_provider = AiProvider.objects.filter(pk=serializer.validated_data['ai_provider_id']).filter(Q(space=request.space) | Q(space__isnull=True)).first()
|
||||
|
||||
def log_ai_request(kwargs, completion_response, start_time, end_time):
|
||||
print(completion_response['usage']['completion_tokens'], completion_response['usage']['prompt_tokens'], start_time, end_time)
|
||||
try:
|
||||
response_cost = kwargs.get("response_cost", 0)
|
||||
print("response_cost", response_cost)
|
||||
except:
|
||||
print('could not get cost')
|
||||
traceback.print_exc()
|
||||
AiLog.objects.create(
|
||||
created_by=request.user,
|
||||
space=request.space,
|
||||
ai_provider=ai_provider,
|
||||
start_time=start_time,
|
||||
end_time=end_time,
|
||||
input_tokens=completion_response['usage']['prompt_tokens'],
|
||||
output_tokens=completion_response['usage']['completion_tokens'],
|
||||
function=AiLog.F_FILE_IMPORT,
|
||||
credit_cost=kwargs.get("response_cost", 0) * 100,
|
||||
credits_from_balance=False, # TODO implement
|
||||
)
|
||||
|
||||
litellm.success_callback = [log_ai_request]
|
||||
|
||||
@@ -2079,7 +2117,9 @@ class AiImportView(APIView):
|
||||
return Response(RecipeFromSourceResponseSerializer(context={'request': request}).to_representation(response), status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
try:
|
||||
ai_response = completion(api_key=AI_API_KEY, model=AI_MODEL_NAME, response_format={"type": "json_object"}, messages=messages, )
|
||||
ai_response = completion(api_key=ai_provider.api_key,
|
||||
model=ai_provider.model_name,
|
||||
response_format={"type": "json_object"}, messages=messages, )
|
||||
except BadRequestError as err:
|
||||
response = {
|
||||
'error': True,
|
||||
|
||||
@@ -126,6 +126,7 @@
|
||||
<v-card-text>
|
||||
Convert the recipe using AI
|
||||
|
||||
<model-select model="AiProvider" v-model="selectedAiProvider"></model-select>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</template>
|
||||
@@ -191,7 +192,7 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import {computed, onBeforeUnmount, onMounted, ref, watch} from 'vue'
|
||||
import {ApiApi, Recipe} from "@/openapi"
|
||||
import {AiProvider, ApiApi, Recipe} from "@/openapi"
|
||||
import NumberScalerDialog from "@/components/inputs/NumberScalerDialog.vue"
|
||||
import StepsOverview from "@/components/display/StepsOverview.vue";
|
||||
import RecipeActivity from "@/components/display/RecipeActivity.vue";
|
||||
@@ -207,6 +208,7 @@ import {useUserPreferenceStore} from "@/stores/UserPreferenceStore.ts";
|
||||
import {ErrorMessageType, useMessageStore} from "@/stores/MessageStore.ts";
|
||||
import {useFileApi} from "@/composables/useFileApi.ts";
|
||||
import PrivateRecipeBadge from "@/components/display/PrivateRecipeBadge.vue";
|
||||
import ModelSelect from "@/components/inputs/ModelSelect.vue";
|
||||
|
||||
const {request, release} = useWakeLock()
|
||||
const {doAiImport, fileApiLoading} = useFileApi()
|
||||
@@ -217,6 +219,8 @@ const recipe = defineModel<Recipe>({required: true})
|
||||
const servings = ref(1)
|
||||
const showFullRecipeName = ref(false)
|
||||
|
||||
const selectedAiProvider = ref<undefined | AiProvider>(undefined)
|
||||
|
||||
/**
|
||||
* factor for multiplying ingredient amounts based on recipe base servings and user selected servings
|
||||
*/
|
||||
@@ -249,7 +253,7 @@ onBeforeUnmount(() => {
|
||||
function aiConvertRecipe() {
|
||||
let api = new ApiApi()
|
||||
|
||||
doAiImport(null, '', recipe.value.id!).then(r => {
|
||||
doAiImport(selectedAiProvider.value.id!,null, '', recipe.value.id!).then(r => {
|
||||
if (r.recipe) {
|
||||
recipe.value.internal = true
|
||||
recipe.value.steps = r.recipe.steps
|
||||
|
||||
99
vue3/src/components/model_editors/AiProviderEditor.vue
Normal file
99
vue3/src/components/model_editors/AiProviderEditor.vue
Normal file
@@ -0,0 +1,99 @@
|
||||
<template>
|
||||
<model-editor-base
|
||||
:loading="loading"
|
||||
:dialog="dialog"
|
||||
@save="saveObject"
|
||||
@delete="deleteObject"
|
||||
@close="emit('close'); editingObjChanged = false"
|
||||
:is-update="isUpdate()"
|
||||
:is-changed="editingObjChanged"
|
||||
:model-class="modelClass"
|
||||
:object-name="editingObjName()">
|
||||
<v-card-text>
|
||||
<v-form :disabled="loading">
|
||||
<v-text-field :label="$t('Name')" v-model="editingObj.name"></v-text-field>
|
||||
<v-textarea :label="$t('Description')" v-model="editingObj.description"></v-textarea>
|
||||
|
||||
<!-- TODO localize -->
|
||||
<v-checkbox :label="$t('Global')" v-model="globalProvider" v-if="useUserPreferenceStore().userSettings.user.isSuperuser"></v-checkbox>
|
||||
|
||||
<v-text-field :label="$t('APIKey')" v-model="editingObj.apiKey"></v-text-field>
|
||||
|
||||
<v-combobox :label="$t('Model')" :items="aiModels" v-model="editingObj.modelName" hide-details>
|
||||
|
||||
</v-combobox>
|
||||
|
||||
<p class="mt-2 mb-2">You can use any model that <a href="https://docs.litellm.ai/docs/providers" target="_blank">LiteLLM supports</a>, the list just contains some
|
||||
of the most
|
||||
commonly used models.</p>
|
||||
|
||||
<v-text-field :label="$t('Url')" v-model="editingObj.url"></v-text-field>
|
||||
|
||||
</v-form>
|
||||
</v-card-text>
|
||||
</model-editor-base>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
import {onMounted, PropType, ref, watch} from "vue";
|
||||
import {AiProvider} from "@/openapi";
|
||||
|
||||
import ModelEditorBase from "@/components/model_editors/ModelEditorBase.vue";
|
||||
import {useModelEditorFunctions} from "@/composables/useModelEditorFunctions";
|
||||
import {useUserPreferenceStore} from "@/stores/UserPreferenceStore.ts";
|
||||
|
||||
|
||||
const props = defineProps({
|
||||
item: {type: {} as PropType<AiProvider>, required: false, default: null},
|
||||
itemId: {type: [Number, String], required: false, default: undefined},
|
||||
itemDefaults: {type: {} as PropType<AiProvider>, required: false, default: {} as AiProvider},
|
||||
dialog: {type: Boolean, default: false}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['create', 'save', 'delete', 'close', 'changedState'])
|
||||
const {setupState, deleteObject, saveObject, isUpdate, editingObjName, loading, editingObj, editingObjChanged, modelClass} = useModelEditorFunctions<AiProvider>('AiProvider', emit)
|
||||
|
||||
/**
|
||||
* watch prop changes and re-initialize editor
|
||||
* required to embed editor directly into pages and be able to change item from the outside
|
||||
*/
|
||||
watch([() => props.item, () => props.itemId], () => {
|
||||
initializeEditor()
|
||||
})
|
||||
|
||||
// object specific data (for selects/display)
|
||||
const aiModels = ref(['gemini/gemini-2.5-pro', 'gemini/gemini-2.5-flash', 'gemini/gemini-2.5-flash-lite', 'gpt-5', 'gpt-5-mini', 'gpt-5-nano'])
|
||||
|
||||
const globalProvider = ref(false)
|
||||
|
||||
watch(() => globalProvider, () => {
|
||||
if(globalProvider.value){
|
||||
editingObj.value.space = undefined
|
||||
} else {
|
||||
editingObj.value.space = useUserPreferenceStore().activeSpace.id!
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
initializeEditor()
|
||||
})
|
||||
|
||||
/**
|
||||
* component specific state setup logic
|
||||
*/
|
||||
function initializeEditor() {
|
||||
setupState(props.item, props.itemId, {
|
||||
itemDefaults: props.itemDefaults
|
||||
}).then(() => {
|
||||
globalProvider.value = editingObj.value.space == undefined
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,7 +1,7 @@
|
||||
import {useDjangoUrls} from "@/composables/useDjangoUrls";
|
||||
import {ref} from "vue";
|
||||
import {getCookie} from "@/utils/cookie";
|
||||
import {RecipeFromSourceResponseFromJSON, RecipeImageFromJSON, ResponseError, UserFile, UserFileFromJSON} from "@/openapi";
|
||||
import {AiProvider, RecipeFromSourceResponseFromJSON, RecipeImageFromJSON, ResponseError, UserFile, UserFileFromJSON} from "@/openapi";
|
||||
|
||||
|
||||
/**
|
||||
@@ -86,7 +86,7 @@ export function useFileApi() {
|
||||
* @param text text to import
|
||||
* @param recipeId id of a recipe to use as import base (for external recipes
|
||||
*/
|
||||
function doAiImport(file: File | null, text: string = '', recipeId: string = '') {
|
||||
function doAiImport(providerId: number, file: File | null, text: string = '', recipeId: string = '') {
|
||||
let formData = new FormData()
|
||||
|
||||
if (file != null) {
|
||||
@@ -96,6 +96,7 @@ export function useFileApi() {
|
||||
}
|
||||
formData.append('text', text)
|
||||
formData.append('recipe_id', recipeId)
|
||||
formData.append('ai_provider_id', providerId)
|
||||
fileApiLoading.value = true
|
||||
|
||||
return fetch(getDjangoUrl(`api/ai-import/`), {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"AI": "AI",
|
||||
"AIImportSubtitle": "Verwende AI um Fotos von Rezepten zu importieren.",
|
||||
"API": "API",
|
||||
"APIKey": "API Schlüssel",
|
||||
"Summary": "Zusammenfassung",
|
||||
"Structured": "Strukturiert",
|
||||
"API_Browser": "API Browser",
|
||||
@@ -307,6 +308,7 @@
|
||||
"Monday": "Montag",
|
||||
"Month": "Monat",
|
||||
"More": "Mehr",
|
||||
"Model": "Modell",
|
||||
"Move": "Verschieben",
|
||||
"MoveCategory": "Verschieben nach: ",
|
||||
"MoveToStep": "Verschieben in Schritt",
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"AI": "AI",
|
||||
"AIImportSubtitle": "Use AI to import images of recipes.",
|
||||
"API": "API",
|
||||
"APIKey": "API key",
|
||||
"API_Browser": "API Browser",
|
||||
"API_Documentation": "API Docs",
|
||||
"AccessTokenHelp": "Access keys for the REST API.",
|
||||
@@ -305,6 +306,7 @@
|
||||
"Monday": "Monday",
|
||||
"Month": "Month",
|
||||
"More": "More",
|
||||
"Model": "Model",
|
||||
"Move": "Move",
|
||||
"MoveCategory": "Move To: ",
|
||||
"MoveToStep": "Move to Step",
|
||||
|
||||
@@ -3,6 +3,8 @@ apis/ApiTokenAuthApi.ts
|
||||
apis/index.ts
|
||||
index.ts
|
||||
models/AccessToken.ts
|
||||
models/AiLog.ts
|
||||
models/AiProvider.ts
|
||||
models/AlignmentEnum.ts
|
||||
models/AuthToken.ts
|
||||
models/AutoMealPlan.ts
|
||||
@@ -57,6 +59,8 @@ models/OpenDataStoreCategory.ts
|
||||
models/OpenDataUnit.ts
|
||||
models/OpenDataUnitTypeEnum.ts
|
||||
models/OpenDataVersion.ts
|
||||
models/PaginatedAiLogList.ts
|
||||
models/PaginatedAiProviderList.ts
|
||||
models/PaginatedAutomationList.ts
|
||||
models/PaginatedBookmarkletImportListList.ts
|
||||
models/PaginatedConnectorConfigList.ts
|
||||
@@ -103,6 +107,7 @@ models/PaginatedUserSpaceList.ts
|
||||
models/PaginatedViewLogList.ts
|
||||
models/ParsedIngredient.ts
|
||||
models/PatchedAccessToken.ts
|
||||
models/PatchedAiProvider.ts
|
||||
models/PatchedAutomation.ts
|
||||
models/PatchedBookmarkletImport.ts
|
||||
models/PatchedConnectorConfig.ts
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
import * as runtime from '../runtime';
|
||||
import type {
|
||||
AccessToken,
|
||||
AiLog,
|
||||
AiProvider,
|
||||
AutoMealPlan,
|
||||
Automation,
|
||||
BookmarkletImport,
|
||||
@@ -49,6 +51,8 @@ import type {
|
||||
OpenDataStore,
|
||||
OpenDataUnit,
|
||||
OpenDataVersion,
|
||||
PaginatedAiLogList,
|
||||
PaginatedAiProviderList,
|
||||
PaginatedAutomationList,
|
||||
PaginatedBookmarkletImportListList,
|
||||
PaginatedConnectorConfigList,
|
||||
@@ -95,6 +99,7 @@ import type {
|
||||
PaginatedViewLogList,
|
||||
ParsedIngredient,
|
||||
PatchedAccessToken,
|
||||
PatchedAiProvider,
|
||||
PatchedAutomation,
|
||||
PatchedBookmarkletImport,
|
||||
PatchedConnectorConfig,
|
||||
@@ -179,6 +184,10 @@ import type {
|
||||
import {
|
||||
AccessTokenFromJSON,
|
||||
AccessTokenToJSON,
|
||||
AiLogFromJSON,
|
||||
AiLogToJSON,
|
||||
AiProviderFromJSON,
|
||||
AiProviderToJSON,
|
||||
AutoMealPlanFromJSON,
|
||||
AutoMealPlanToJSON,
|
||||
AutomationFromJSON,
|
||||
@@ -245,6 +254,10 @@ import {
|
||||
OpenDataUnitToJSON,
|
||||
OpenDataVersionFromJSON,
|
||||
OpenDataVersionToJSON,
|
||||
PaginatedAiLogListFromJSON,
|
||||
PaginatedAiLogListToJSON,
|
||||
PaginatedAiProviderListFromJSON,
|
||||
PaginatedAiProviderListToJSON,
|
||||
PaginatedAutomationListFromJSON,
|
||||
PaginatedAutomationListToJSON,
|
||||
PaginatedBookmarkletImportListListFromJSON,
|
||||
@@ -337,6 +350,8 @@ import {
|
||||
ParsedIngredientToJSON,
|
||||
PatchedAccessTokenFromJSON,
|
||||
PatchedAccessTokenToJSON,
|
||||
PatchedAiProviderFromJSON,
|
||||
PatchedAiProviderToJSON,
|
||||
PatchedAutomationFromJSON,
|
||||
PatchedAutomationToJSON,
|
||||
PatchedBookmarkletImportFromJSON,
|
||||
@@ -527,6 +542,42 @@ export interface ApiAiImportCreateRequest {
|
||||
recipeId: string | null;
|
||||
}
|
||||
|
||||
export interface ApiAiLogListRequest {
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
}
|
||||
|
||||
export interface ApiAiLogRetrieveRequest {
|
||||
id: number;
|
||||
}
|
||||
|
||||
export interface ApiAiProviderCreateRequest {
|
||||
aiProvider: Omit<AiProvider, 'createdAt'|'updatedAt'>;
|
||||
}
|
||||
|
||||
export interface ApiAiProviderDestroyRequest {
|
||||
id: number;
|
||||
}
|
||||
|
||||
export interface ApiAiProviderListRequest {
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
}
|
||||
|
||||
export interface ApiAiProviderPartialUpdateRequest {
|
||||
id: number;
|
||||
patchedAiProvider?: Omit<PatchedAiProvider, 'createdAt'|'updatedAt'>;
|
||||
}
|
||||
|
||||
export interface ApiAiProviderRetrieveRequest {
|
||||
id: number;
|
||||
}
|
||||
|
||||
export interface ApiAiProviderUpdateRequest {
|
||||
id: number;
|
||||
aiProvider: Omit<AiProvider, 'createdAt'|'updatedAt'>;
|
||||
}
|
||||
|
||||
export interface ApiAutoPlanCreateRequest {
|
||||
autoMealPlan: AutoMealPlan;
|
||||
}
|
||||
@@ -1732,7 +1783,7 @@ export interface ApiSpaceListRequest {
|
||||
|
||||
export interface ApiSpacePartialUpdateRequest {
|
||||
id: number;
|
||||
patchedSpace?: Omit<PatchedSpace, 'createdBy'|'createdAt'|'maxRecipes'|'maxFileStorageMb'|'maxUsers'|'allowSharing'|'demo'|'userCount'|'recipeCount'|'fileSizeMb'>;
|
||||
patchedSpace?: Omit<PatchedSpace, 'createdBy'|'createdAt'|'maxRecipes'|'maxFileStorageMb'|'maxUsers'|'allowSharing'|'demo'|'userCount'|'recipeCount'|'fileSizeMb'|'aiCreditsMonthly'|'aiCreditsBalance'|'aiMonthlyCreditsUsed'>;
|
||||
}
|
||||
|
||||
export interface ApiSpaceRetrieveRequest {
|
||||
@@ -2443,6 +2494,319 @@ export class ApiApi extends runtime.BaseAPI {
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* logs request counts to redis cache total/per user/
|
||||
*/
|
||||
async apiAiLogListRaw(requestParameters: ApiAiLogListRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<PaginatedAiLogList>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['page'] != null) {
|
||||
queryParameters['page'] = requestParameters['page'];
|
||||
}
|
||||
|
||||
if (requestParameters['pageSize'] != null) {
|
||||
queryParameters['page_size'] = requestParameters['pageSize'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
if (this.configuration && this.configuration.apiKey) {
|
||||
headerParameters["Authorization"] = await this.configuration.apiKey("Authorization"); // ApiKeyAuth authentication
|
||||
}
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/ai-log/`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => PaginatedAiLogListFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* logs request counts to redis cache total/per user/
|
||||
*/
|
||||
async apiAiLogList(requestParameters: ApiAiLogListRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<PaginatedAiLogList> {
|
||||
const response = await this.apiAiLogListRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* logs request counts to redis cache total/per user/
|
||||
*/
|
||||
async apiAiLogRetrieveRaw(requestParameters: ApiAiLogRetrieveRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<AiLog>> {
|
||||
if (requestParameters['id'] == null) {
|
||||
throw new runtime.RequiredError(
|
||||
'id',
|
||||
'Required parameter "id" was null or undefined when calling apiAiLogRetrieve().'
|
||||
);
|
||||
}
|
||||
|
||||
const queryParameters: any = {};
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
if (this.configuration && this.configuration.apiKey) {
|
||||
headerParameters["Authorization"] = await this.configuration.apiKey("Authorization"); // ApiKeyAuth authentication
|
||||
}
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/ai-log/{id}/`.replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id']))),
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => AiLogFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* logs request counts to redis cache total/per user/
|
||||
*/
|
||||
async apiAiLogRetrieve(requestParameters: ApiAiLogRetrieveRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<AiLog> {
|
||||
const response = await this.apiAiLogRetrieveRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* logs request counts to redis cache total/per user/
|
||||
*/
|
||||
async apiAiProviderCreateRaw(requestParameters: ApiAiProviderCreateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<AiProvider>> {
|
||||
if (requestParameters['aiProvider'] == null) {
|
||||
throw new runtime.RequiredError(
|
||||
'aiProvider',
|
||||
'Required parameter "aiProvider" was null or undefined when calling apiAiProviderCreate().'
|
||||
);
|
||||
}
|
||||
|
||||
const queryParameters: any = {};
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
headerParameters['Content-Type'] = 'application/json';
|
||||
|
||||
if (this.configuration && this.configuration.apiKey) {
|
||||
headerParameters["Authorization"] = await this.configuration.apiKey("Authorization"); // ApiKeyAuth authentication
|
||||
}
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/ai-provider/`,
|
||||
method: 'POST',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
body: AiProviderToJSON(requestParameters['aiProvider']),
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => AiProviderFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* logs request counts to redis cache total/per user/
|
||||
*/
|
||||
async apiAiProviderCreate(requestParameters: ApiAiProviderCreateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<AiProvider> {
|
||||
const response = await this.apiAiProviderCreateRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* logs request counts to redis cache total/per user/
|
||||
*/
|
||||
async apiAiProviderDestroyRaw(requestParameters: ApiAiProviderDestroyRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<void>> {
|
||||
if (requestParameters['id'] == null) {
|
||||
throw new runtime.RequiredError(
|
||||
'id',
|
||||
'Required parameter "id" was null or undefined when calling apiAiProviderDestroy().'
|
||||
);
|
||||
}
|
||||
|
||||
const queryParameters: any = {};
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
if (this.configuration && this.configuration.apiKey) {
|
||||
headerParameters["Authorization"] = await this.configuration.apiKey("Authorization"); // ApiKeyAuth authentication
|
||||
}
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/ai-provider/{id}/`.replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id']))),
|
||||
method: 'DELETE',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.VoidApiResponse(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* logs request counts to redis cache total/per user/
|
||||
*/
|
||||
async apiAiProviderDestroy(requestParameters: ApiAiProviderDestroyRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<void> {
|
||||
await this.apiAiProviderDestroyRaw(requestParameters, initOverrides);
|
||||
}
|
||||
|
||||
/**
|
||||
* logs request counts to redis cache total/per user/
|
||||
*/
|
||||
async apiAiProviderListRaw(requestParameters: ApiAiProviderListRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<PaginatedAiProviderList>> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters['page'] != null) {
|
||||
queryParameters['page'] = requestParameters['page'];
|
||||
}
|
||||
|
||||
if (requestParameters['pageSize'] != null) {
|
||||
queryParameters['page_size'] = requestParameters['pageSize'];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
if (this.configuration && this.configuration.apiKey) {
|
||||
headerParameters["Authorization"] = await this.configuration.apiKey("Authorization"); // ApiKeyAuth authentication
|
||||
}
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/ai-provider/`,
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => PaginatedAiProviderListFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* logs request counts to redis cache total/per user/
|
||||
*/
|
||||
async apiAiProviderList(requestParameters: ApiAiProviderListRequest = {}, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<PaginatedAiProviderList> {
|
||||
const response = await this.apiAiProviderListRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* logs request counts to redis cache total/per user/
|
||||
*/
|
||||
async apiAiProviderPartialUpdateRaw(requestParameters: ApiAiProviderPartialUpdateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<AiProvider>> {
|
||||
if (requestParameters['id'] == null) {
|
||||
throw new runtime.RequiredError(
|
||||
'id',
|
||||
'Required parameter "id" was null or undefined when calling apiAiProviderPartialUpdate().'
|
||||
);
|
||||
}
|
||||
|
||||
const queryParameters: any = {};
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
headerParameters['Content-Type'] = 'application/json';
|
||||
|
||||
if (this.configuration && this.configuration.apiKey) {
|
||||
headerParameters["Authorization"] = await this.configuration.apiKey("Authorization"); // ApiKeyAuth authentication
|
||||
}
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/ai-provider/{id}/`.replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id']))),
|
||||
method: 'PATCH',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
body: PatchedAiProviderToJSON(requestParameters['patchedAiProvider']),
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => AiProviderFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* logs request counts to redis cache total/per user/
|
||||
*/
|
||||
async apiAiProviderPartialUpdate(requestParameters: ApiAiProviderPartialUpdateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<AiProvider> {
|
||||
const response = await this.apiAiProviderPartialUpdateRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* logs request counts to redis cache total/per user/
|
||||
*/
|
||||
async apiAiProviderRetrieveRaw(requestParameters: ApiAiProviderRetrieveRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<AiProvider>> {
|
||||
if (requestParameters['id'] == null) {
|
||||
throw new runtime.RequiredError(
|
||||
'id',
|
||||
'Required parameter "id" was null or undefined when calling apiAiProviderRetrieve().'
|
||||
);
|
||||
}
|
||||
|
||||
const queryParameters: any = {};
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
if (this.configuration && this.configuration.apiKey) {
|
||||
headerParameters["Authorization"] = await this.configuration.apiKey("Authorization"); // ApiKeyAuth authentication
|
||||
}
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/ai-provider/{id}/`.replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id']))),
|
||||
method: 'GET',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => AiProviderFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* logs request counts to redis cache total/per user/
|
||||
*/
|
||||
async apiAiProviderRetrieve(requestParameters: ApiAiProviderRetrieveRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<AiProvider> {
|
||||
const response = await this.apiAiProviderRetrieveRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* logs request counts to redis cache total/per user/
|
||||
*/
|
||||
async apiAiProviderUpdateRaw(requestParameters: ApiAiProviderUpdateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<runtime.ApiResponse<AiProvider>> {
|
||||
if (requestParameters['id'] == null) {
|
||||
throw new runtime.RequiredError(
|
||||
'id',
|
||||
'Required parameter "id" was null or undefined when calling apiAiProviderUpdate().'
|
||||
);
|
||||
}
|
||||
|
||||
if (requestParameters['aiProvider'] == null) {
|
||||
throw new runtime.RequiredError(
|
||||
'aiProvider',
|
||||
'Required parameter "aiProvider" was null or undefined when calling apiAiProviderUpdate().'
|
||||
);
|
||||
}
|
||||
|
||||
const queryParameters: any = {};
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
headerParameters['Content-Type'] = 'application/json';
|
||||
|
||||
if (this.configuration && this.configuration.apiKey) {
|
||||
headerParameters["Authorization"] = await this.configuration.apiKey("Authorization"); // ApiKeyAuth authentication
|
||||
}
|
||||
|
||||
const response = await this.request({
|
||||
path: `/api/ai-provider/{id}/`.replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id']))),
|
||||
method: 'PUT',
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
body: AiProviderToJSON(requestParameters['aiProvider']),
|
||||
}, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => AiProviderFromJSON(jsonValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* logs request counts to redis cache total/per user/
|
||||
*/
|
||||
async apiAiProviderUpdate(requestParameters: ApiAiProviderUpdateRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<AiProvider> {
|
||||
const response = await this.apiAiProviderUpdateRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* logs request counts to redis cache total/per user/
|
||||
*/
|
||||
|
||||
157
vue3/src/openapi/models/AiLog.ts
Normal file
157
vue3/src/openapi/models/AiLog.ts
Normal file
@@ -0,0 +1,157 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Tandoor
|
||||
* Tandoor API Docs
|
||||
*
|
||||
* The version of the OpenAPI document: 0.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
import type { AiProvider } from './AiProvider';
|
||||
import {
|
||||
AiProviderFromJSON,
|
||||
AiProviderFromJSONTyped,
|
||||
AiProviderToJSON,
|
||||
} from './AiProvider';
|
||||
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface AiLog
|
||||
*/
|
||||
export interface AiLog {
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof AiLog
|
||||
*/
|
||||
id?: number;
|
||||
/**
|
||||
*
|
||||
* @type {AiProvider}
|
||||
* @memberof AiLog
|
||||
*/
|
||||
readonly aiProvider: AiProvider;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AiLog
|
||||
*/
|
||||
_function: string;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof AiLog
|
||||
*/
|
||||
creditCost: number;
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof AiLog
|
||||
*/
|
||||
creditsFromBalance?: boolean;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof AiLog
|
||||
*/
|
||||
inputTokens?: number;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof AiLog
|
||||
*/
|
||||
outputTokens?: number;
|
||||
/**
|
||||
*
|
||||
* @type {Date}
|
||||
* @memberof AiLog
|
||||
*/
|
||||
startTime?: Date;
|
||||
/**
|
||||
*
|
||||
* @type {Date}
|
||||
* @memberof AiLog
|
||||
*/
|
||||
endTime?: Date;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof AiLog
|
||||
*/
|
||||
createdBy?: number;
|
||||
/**
|
||||
*
|
||||
* @type {Date}
|
||||
* @memberof AiLog
|
||||
*/
|
||||
readonly createdAt: Date;
|
||||
/**
|
||||
*
|
||||
* @type {Date}
|
||||
* @memberof AiLog
|
||||
*/
|
||||
readonly updatedAt: Date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the AiLog interface.
|
||||
*/
|
||||
export function instanceOfAiLog(value: object): value is AiLog {
|
||||
if (!('aiProvider' in value) || value['aiProvider'] === undefined) return false;
|
||||
if (!('_function' in value) || value['_function'] === undefined) return false;
|
||||
if (!('creditCost' in value) || value['creditCost'] === undefined) return false;
|
||||
if (!('createdAt' in value) || value['createdAt'] === undefined) return false;
|
||||
if (!('updatedAt' in value) || value['updatedAt'] === undefined) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
export function AiLogFromJSON(json: any): AiLog {
|
||||
return AiLogFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function AiLogFromJSONTyped(json: any, ignoreDiscriminator: boolean): AiLog {
|
||||
if (json == null) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
|
||||
'id': json['id'] == null ? undefined : json['id'],
|
||||
'aiProvider': AiProviderFromJSON(json['ai_provider']),
|
||||
'_function': json['function'],
|
||||
'creditCost': json['credit_cost'],
|
||||
'creditsFromBalance': json['credits_from_balance'] == null ? undefined : json['credits_from_balance'],
|
||||
'inputTokens': json['input_tokens'] == null ? undefined : json['input_tokens'],
|
||||
'outputTokens': json['output_tokens'] == null ? undefined : json['output_tokens'],
|
||||
'startTime': json['start_time'] == null ? undefined : (new Date(json['start_time'])),
|
||||
'endTime': json['end_time'] == null ? undefined : (new Date(json['end_time'])),
|
||||
'createdBy': json['created_by'] == null ? undefined : json['created_by'],
|
||||
'createdAt': (new Date(json['created_at'])),
|
||||
'updatedAt': (new Date(json['updated_at'])),
|
||||
};
|
||||
}
|
||||
|
||||
export function AiLogToJSON(value?: Omit<AiLog, 'aiProvider'|'createdAt'|'updatedAt'> | null): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
return {
|
||||
|
||||
'id': value['id'],
|
||||
'function': value['_function'],
|
||||
'credit_cost': value['creditCost'],
|
||||
'credits_from_balance': value['creditsFromBalance'],
|
||||
'input_tokens': value['inputTokens'],
|
||||
'output_tokens': value['outputTokens'],
|
||||
'start_time': value['startTime'] == null ? undefined : ((value['startTime'] as any).toISOString()),
|
||||
'end_time': value['endTime'] == null ? undefined : ((value['endTime'] as any).toISOString()),
|
||||
'created_by': value['createdBy'],
|
||||
};
|
||||
}
|
||||
|
||||
127
vue3/src/openapi/models/AiProvider.ts
Normal file
127
vue3/src/openapi/models/AiProvider.ts
Normal file
@@ -0,0 +1,127 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Tandoor
|
||||
* Tandoor API Docs
|
||||
*
|
||||
* The version of the OpenAPI document: 0.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface AiProvider
|
||||
*/
|
||||
export interface AiProvider {
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof AiProvider
|
||||
*/
|
||||
id?: number;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AiProvider
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AiProvider
|
||||
*/
|
||||
description?: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AiProvider
|
||||
*/
|
||||
apiKey: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AiProvider
|
||||
*/
|
||||
modelName: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AiProvider
|
||||
*/
|
||||
url?: string;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof AiProvider
|
||||
*/
|
||||
space?: number;
|
||||
/**
|
||||
*
|
||||
* @type {Date}
|
||||
* @memberof AiProvider
|
||||
*/
|
||||
readonly createdAt: Date;
|
||||
/**
|
||||
*
|
||||
* @type {Date}
|
||||
* @memberof AiProvider
|
||||
*/
|
||||
readonly updatedAt: Date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the AiProvider interface.
|
||||
*/
|
||||
export function instanceOfAiProvider(value: object): value is AiProvider {
|
||||
if (!('name' in value) || value['name'] === undefined) return false;
|
||||
if (!('apiKey' in value) || value['apiKey'] === undefined) return false;
|
||||
if (!('modelName' in value) || value['modelName'] === undefined) return false;
|
||||
if (!('createdAt' in value) || value['createdAt'] === undefined) return false;
|
||||
if (!('updatedAt' in value) || value['updatedAt'] === undefined) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
export function AiProviderFromJSON(json: any): AiProvider {
|
||||
return AiProviderFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function AiProviderFromJSONTyped(json: any, ignoreDiscriminator: boolean): AiProvider {
|
||||
if (json == null) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
|
||||
'id': json['id'] == null ? undefined : json['id'],
|
||||
'name': json['name'],
|
||||
'description': json['description'] == null ? undefined : json['description'],
|
||||
'apiKey': json['api_key'],
|
||||
'modelName': json['model_name'],
|
||||
'url': json['url'] == null ? undefined : json['url'],
|
||||
'space': json['space'] == null ? undefined : json['space'],
|
||||
'createdAt': (new Date(json['created_at'])),
|
||||
'updatedAt': (new Date(json['updated_at'])),
|
||||
};
|
||||
}
|
||||
|
||||
export function AiProviderToJSON(value?: Omit<AiProvider, 'createdAt'|'updatedAt'> | null): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
return {
|
||||
|
||||
'id': value['id'],
|
||||
'name': value['name'],
|
||||
'description': value['description'],
|
||||
'api_key': value['apiKey'],
|
||||
'model_name': value['modelName'],
|
||||
'url': value['url'],
|
||||
'space': value['space'],
|
||||
};
|
||||
}
|
||||
|
||||
101
vue3/src/openapi/models/PaginatedAiLogList.ts
Normal file
101
vue3/src/openapi/models/PaginatedAiLogList.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Tandoor
|
||||
* Tandoor API Docs
|
||||
*
|
||||
* The version of the OpenAPI document: 0.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
import type { AiLog } from './AiLog';
|
||||
import {
|
||||
AiLogFromJSON,
|
||||
AiLogFromJSONTyped,
|
||||
AiLogToJSON,
|
||||
} from './AiLog';
|
||||
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface PaginatedAiLogList
|
||||
*/
|
||||
export interface PaginatedAiLogList {
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof PaginatedAiLogList
|
||||
*/
|
||||
count: number;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof PaginatedAiLogList
|
||||
*/
|
||||
next?: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof PaginatedAiLogList
|
||||
*/
|
||||
previous?: string;
|
||||
/**
|
||||
*
|
||||
* @type {Array<AiLog>}
|
||||
* @memberof PaginatedAiLogList
|
||||
*/
|
||||
results: Array<AiLog>;
|
||||
/**
|
||||
*
|
||||
* @type {Date}
|
||||
* @memberof PaginatedAiLogList
|
||||
*/
|
||||
timestamp?: Date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the PaginatedAiLogList interface.
|
||||
*/
|
||||
export function instanceOfPaginatedAiLogList(value: object): value is PaginatedAiLogList {
|
||||
if (!('count' in value) || value['count'] === undefined) return false;
|
||||
if (!('results' in value) || value['results'] === undefined) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
export function PaginatedAiLogListFromJSON(json: any): PaginatedAiLogList {
|
||||
return PaginatedAiLogListFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function PaginatedAiLogListFromJSONTyped(json: any, ignoreDiscriminator: boolean): PaginatedAiLogList {
|
||||
if (json == null) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
|
||||
'count': json['count'],
|
||||
'next': json['next'] == null ? undefined : json['next'],
|
||||
'previous': json['previous'] == null ? undefined : json['previous'],
|
||||
'results': ((json['results'] as Array<any>).map(AiLogFromJSON)),
|
||||
'timestamp': json['timestamp'] == null ? undefined : (new Date(json['timestamp'])),
|
||||
};
|
||||
}
|
||||
|
||||
export function PaginatedAiLogListToJSON(value?: PaginatedAiLogList | null): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
return {
|
||||
|
||||
'count': value['count'],
|
||||
'next': value['next'],
|
||||
'previous': value['previous'],
|
||||
'results': ((value['results'] as Array<any>).map(AiLogToJSON)),
|
||||
'timestamp': value['timestamp'] == null ? undefined : ((value['timestamp']).toISOString()),
|
||||
};
|
||||
}
|
||||
|
||||
101
vue3/src/openapi/models/PaginatedAiProviderList.ts
Normal file
101
vue3/src/openapi/models/PaginatedAiProviderList.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Tandoor
|
||||
* Tandoor API Docs
|
||||
*
|
||||
* The version of the OpenAPI document: 0.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
import type { AiProvider } from './AiProvider';
|
||||
import {
|
||||
AiProviderFromJSON,
|
||||
AiProviderFromJSONTyped,
|
||||
AiProviderToJSON,
|
||||
} from './AiProvider';
|
||||
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface PaginatedAiProviderList
|
||||
*/
|
||||
export interface PaginatedAiProviderList {
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof PaginatedAiProviderList
|
||||
*/
|
||||
count: number;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof PaginatedAiProviderList
|
||||
*/
|
||||
next?: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof PaginatedAiProviderList
|
||||
*/
|
||||
previous?: string;
|
||||
/**
|
||||
*
|
||||
* @type {Array<AiProvider>}
|
||||
* @memberof PaginatedAiProviderList
|
||||
*/
|
||||
results: Array<AiProvider>;
|
||||
/**
|
||||
*
|
||||
* @type {Date}
|
||||
* @memberof PaginatedAiProviderList
|
||||
*/
|
||||
timestamp?: Date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the PaginatedAiProviderList interface.
|
||||
*/
|
||||
export function instanceOfPaginatedAiProviderList(value: object): value is PaginatedAiProviderList {
|
||||
if (!('count' in value) || value['count'] === undefined) return false;
|
||||
if (!('results' in value) || value['results'] === undefined) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
export function PaginatedAiProviderListFromJSON(json: any): PaginatedAiProviderList {
|
||||
return PaginatedAiProviderListFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function PaginatedAiProviderListFromJSONTyped(json: any, ignoreDiscriminator: boolean): PaginatedAiProviderList {
|
||||
if (json == null) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
|
||||
'count': json['count'],
|
||||
'next': json['next'] == null ? undefined : json['next'],
|
||||
'previous': json['previous'] == null ? undefined : json['previous'],
|
||||
'results': ((json['results'] as Array<any>).map(AiProviderFromJSON)),
|
||||
'timestamp': json['timestamp'] == null ? undefined : (new Date(json['timestamp'])),
|
||||
};
|
||||
}
|
||||
|
||||
export function PaginatedAiProviderListToJSON(value?: PaginatedAiProviderList | null): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
return {
|
||||
|
||||
'count': value['count'],
|
||||
'next': value['next'],
|
||||
'previous': value['previous'],
|
||||
'results': ((value['results'] as Array<any>).map(AiProviderToJSON)),
|
||||
'timestamp': value['timestamp'] == null ? undefined : ((value['timestamp']).toISOString()),
|
||||
};
|
||||
}
|
||||
|
||||
122
vue3/src/openapi/models/PatchedAiProvider.ts
Normal file
122
vue3/src/openapi/models/PatchedAiProvider.ts
Normal file
@@ -0,0 +1,122 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Tandoor
|
||||
* Tandoor API Docs
|
||||
*
|
||||
* The version of the OpenAPI document: 0.0.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import { mapValues } from '../runtime';
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface PatchedAiProvider
|
||||
*/
|
||||
export interface PatchedAiProvider {
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof PatchedAiProvider
|
||||
*/
|
||||
id?: number;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof PatchedAiProvider
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof PatchedAiProvider
|
||||
*/
|
||||
description?: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof PatchedAiProvider
|
||||
*/
|
||||
apiKey?: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof PatchedAiProvider
|
||||
*/
|
||||
modelName?: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof PatchedAiProvider
|
||||
*/
|
||||
url?: string;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof PatchedAiProvider
|
||||
*/
|
||||
space?: number;
|
||||
/**
|
||||
*
|
||||
* @type {Date}
|
||||
* @memberof PatchedAiProvider
|
||||
*/
|
||||
readonly createdAt?: Date;
|
||||
/**
|
||||
*
|
||||
* @type {Date}
|
||||
* @memberof PatchedAiProvider
|
||||
*/
|
||||
readonly updatedAt?: Date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the PatchedAiProvider interface.
|
||||
*/
|
||||
export function instanceOfPatchedAiProvider(value: object): value is PatchedAiProvider {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function PatchedAiProviderFromJSON(json: any): PatchedAiProvider {
|
||||
return PatchedAiProviderFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function PatchedAiProviderFromJSONTyped(json: any, ignoreDiscriminator: boolean): PatchedAiProvider {
|
||||
if (json == null) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
|
||||
'id': json['id'] == null ? undefined : json['id'],
|
||||
'name': json['name'] == null ? undefined : json['name'],
|
||||
'description': json['description'] == null ? undefined : json['description'],
|
||||
'apiKey': json['api_key'] == null ? undefined : json['api_key'],
|
||||
'modelName': json['model_name'] == null ? undefined : json['model_name'],
|
||||
'url': json['url'] == null ? undefined : json['url'],
|
||||
'space': json['space'] == null ? undefined : json['space'],
|
||||
'createdAt': json['created_at'] == null ? undefined : (new Date(json['created_at'])),
|
||||
'updatedAt': json['updated_at'] == null ? undefined : (new Date(json['updated_at'])),
|
||||
};
|
||||
}
|
||||
|
||||
export function PatchedAiProviderToJSON(value?: Omit<PatchedAiProvider, 'createdAt'|'updatedAt'> | null): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
return {
|
||||
|
||||
'id': value['id'],
|
||||
'name': value['name'],
|
||||
'description': value['description'],
|
||||
'api_key': value['apiKey'],
|
||||
'model_name': value['modelName'],
|
||||
'url': value['url'],
|
||||
'space': value['space'],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -212,6 +212,24 @@ export interface PatchedSpace {
|
||||
* @memberof PatchedSpace
|
||||
*/
|
||||
logoColorSvg?: UserFileView;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof PatchedSpace
|
||||
*/
|
||||
readonly aiCreditsMonthly?: number;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof PatchedSpace
|
||||
*/
|
||||
readonly aiCreditsBalance?: number;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof PatchedSpace
|
||||
*/
|
||||
readonly aiMonthlyCreditsUsed?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -258,10 +276,13 @@ export function PatchedSpaceFromJSONTyped(json: any, ignoreDiscriminator: boolea
|
||||
'logoColor192': json['logo_color_192'] == null ? undefined : UserFileViewFromJSON(json['logo_color_192']),
|
||||
'logoColor512': json['logo_color_512'] == null ? undefined : UserFileViewFromJSON(json['logo_color_512']),
|
||||
'logoColorSvg': json['logo_color_svg'] == null ? undefined : UserFileViewFromJSON(json['logo_color_svg']),
|
||||
'aiCreditsMonthly': json['ai_credits_monthly'] == null ? undefined : json['ai_credits_monthly'],
|
||||
'aiCreditsBalance': json['ai_credits_balance'] == null ? undefined : json['ai_credits_balance'],
|
||||
'aiMonthlyCreditsUsed': json['ai_monthly_credits_used'] == null ? undefined : json['ai_monthly_credits_used'],
|
||||
};
|
||||
}
|
||||
|
||||
export function PatchedSpaceToJSON(value?: Omit<PatchedSpace, 'createdBy'|'createdAt'|'maxRecipes'|'maxFileStorageMb'|'maxUsers'|'allowSharing'|'demo'|'userCount'|'recipeCount'|'fileSizeMb'> | null): any {
|
||||
export function PatchedSpaceToJSON(value?: Omit<PatchedSpace, 'createdBy'|'createdAt'|'maxRecipes'|'maxFileStorageMb'|'maxUsers'|'allowSharing'|'demo'|'userCount'|'recipeCount'|'fileSizeMb'|'aiCreditsMonthly'|'aiCreditsBalance'|'aiMonthlyCreditsUsed'> | null): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -212,6 +212,24 @@ export interface Space {
|
||||
* @memberof Space
|
||||
*/
|
||||
logoColorSvg?: UserFileView;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof Space
|
||||
*/
|
||||
readonly aiCreditsMonthly: number;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof Space
|
||||
*/
|
||||
readonly aiCreditsBalance: number;
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof Space
|
||||
*/
|
||||
readonly aiMonthlyCreditsUsed: number;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -229,6 +247,9 @@ export function instanceOfSpace(value: object): value is Space {
|
||||
if (!('userCount' in value) || value['userCount'] === undefined) return false;
|
||||
if (!('recipeCount' in value) || value['recipeCount'] === undefined) return false;
|
||||
if (!('fileSizeMb' in value) || value['fileSizeMb'] === undefined) return false;
|
||||
if (!('aiCreditsMonthly' in value) || value['aiCreditsMonthly'] === undefined) return false;
|
||||
if (!('aiCreditsBalance' in value) || value['aiCreditsBalance'] === undefined) return false;
|
||||
if (!('aiMonthlyCreditsUsed' in value) || value['aiMonthlyCreditsUsed'] === undefined) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -269,10 +290,13 @@ export function SpaceFromJSONTyped(json: any, ignoreDiscriminator: boolean): Spa
|
||||
'logoColor192': json['logo_color_192'] == null ? undefined : UserFileViewFromJSON(json['logo_color_192']),
|
||||
'logoColor512': json['logo_color_512'] == null ? undefined : UserFileViewFromJSON(json['logo_color_512']),
|
||||
'logoColorSvg': json['logo_color_svg'] == null ? undefined : UserFileViewFromJSON(json['logo_color_svg']),
|
||||
'aiCreditsMonthly': json['ai_credits_monthly'],
|
||||
'aiCreditsBalance': json['ai_credits_balance'],
|
||||
'aiMonthlyCreditsUsed': json['ai_monthly_credits_used'],
|
||||
};
|
||||
}
|
||||
|
||||
export function SpaceToJSON(value?: Omit<Space, 'createdBy'|'createdAt'|'maxRecipes'|'maxFileStorageMb'|'maxUsers'|'allowSharing'|'demo'|'userCount'|'recipeCount'|'fileSizeMb'> | null): any {
|
||||
export function SpaceToJSON(value?: Omit<Space, 'createdBy'|'createdAt'|'maxRecipes'|'maxFileStorageMb'|'maxUsers'|'allowSharing'|'demo'|'userCount'|'recipeCount'|'fileSizeMb'|'aiCreditsMonthly'|'aiCreditsBalance'|'aiMonthlyCreditsUsed'> | null): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
export * from './AccessToken';
|
||||
export * from './AiLog';
|
||||
export * from './AiProvider';
|
||||
export * from './AlignmentEnum';
|
||||
export * from './AuthToken';
|
||||
export * from './AutoMealPlan';
|
||||
@@ -55,6 +57,8 @@ export * from './OpenDataStoreCategory';
|
||||
export * from './OpenDataUnit';
|
||||
export * from './OpenDataUnitTypeEnum';
|
||||
export * from './OpenDataVersion';
|
||||
export * from './PaginatedAiLogList';
|
||||
export * from './PaginatedAiProviderList';
|
||||
export * from './PaginatedAutomationList';
|
||||
export * from './PaginatedBookmarkletImportListList';
|
||||
export * from './PaginatedConnectorConfigList';
|
||||
@@ -101,6 +105,7 @@ export * from './PaginatedUserSpaceList';
|
||||
export * from './PaginatedViewLogList';
|
||||
export * from './ParsedIngredient';
|
||||
export * from './PatchedAccessToken';
|
||||
export * from './PatchedAiProvider';
|
||||
export * from './PatchedAutomation';
|
||||
export * from './PatchedBookmarkletImport';
|
||||
export * from './PatchedConnectorConfig';
|
||||
|
||||
@@ -35,6 +35,16 @@
|
||||
<database-model-col model="MealType"></database-model-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col>
|
||||
<h2>{{ $t('Ai') }}</h2>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row dense>
|
||||
<database-model-col model="AiProvider"></database-model-col>
|
||||
<database-model-col model="AiLog"></database-model-col>
|
||||
</v-row>
|
||||
|
||||
<template v-for="p in TANDOOR_PLUGINS" :key="p.name">
|
||||
<component :is="p.databasePageComponent" v-if="p.databasePageComponent"></component>
|
||||
</template>
|
||||
|
||||
@@ -140,10 +140,18 @@
|
||||
@keydown.enter="loadRecipeFromUrl({url: importUrl})"></v-text-field>
|
||||
|
||||
<div v-if="importType == 'ai'">
|
||||
<v-btn-toggle v-model="aiMode">
|
||||
<v-btn value="file">{{ $t('File') }}</v-btn>
|
||||
<v-btn value="text">{{ $t('Text') }}</v-btn>
|
||||
</v-btn-toggle>
|
||||
<v-row>
|
||||
<v-col md="6">
|
||||
<ModelSelect model="AiProvider" v-model="selectedAiProvider"></ModelSelect>
|
||||
</v-col>
|
||||
<v-col md="6">
|
||||
<v-btn-toggle class="mb-2" border divided v-model="aiMode">
|
||||
<v-btn value="file">{{ $t('File') }}</v-btn>
|
||||
<v-btn value="text">{{ $t('Text') }}</v-btn>
|
||||
</v-btn-toggle>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
|
||||
<v-file-upload v-model="image" v-if="aiMode == 'file'" :loading="loading" clearable>
|
||||
<template #icon>
|
||||
@@ -540,6 +548,7 @@ import {useI18n} from "vue-i18n";
|
||||
import {computed, onMounted, ref} from "vue";
|
||||
import {
|
||||
AccessToken,
|
||||
AiProvider,
|
||||
ApiApi,
|
||||
ImportLog,
|
||||
Recipe,
|
||||
@@ -648,6 +657,7 @@ const appImportDuplicates = ref(false)
|
||||
const appImportLog = ref<null | ImportLog>(null)
|
||||
const image = ref<null | File>(null)
|
||||
const aiMode = ref<'file' | 'text'>('file')
|
||||
const selectedAiProvider = ref<undefined | AiProvider>(undefined)
|
||||
const editAfterImport = ref(false)
|
||||
|
||||
const bookmarkletToken = ref("")
|
||||
@@ -724,12 +734,15 @@ function loadRecipeFromUrl(recipeFromSourceRequest: RecipeFromSource) {
|
||||
*/
|
||||
function loadRecipeFromAiImport() {
|
||||
let request = null
|
||||
|
||||
if(selectedAiProvider.value == undefined) {
|
||||
useMessageStore().addError(ErrorMessageType.CREATE_ERROR, "No AI Provider selected")
|
||||
}
|
||||
|
||||
if (image.value != null && aiMode.value == 'file') {
|
||||
console.log('file import')
|
||||
request = doAiImport(image.value)
|
||||
request = doAiImport(selectedAiProvider.value.id!,image.value)
|
||||
} else if (sourceImportText.value != '' && aiMode.value == 'text') {
|
||||
console.log('text import')
|
||||
request = doAiImport(null, sourceImportText.value)
|
||||
request = doAiImport(selectedAiProvider.value.id!, null, sourceImportText.value)
|
||||
}
|
||||
|
||||
if (request != null) {
|
||||
@@ -811,13 +824,13 @@ function deleteStep(step: SourceImportStep) {
|
||||
}
|
||||
|
||||
function handleMergeAllSteps(): void {
|
||||
if (importResponse.value.recipe && importResponse.value.recipe.steps){
|
||||
if (importResponse.value.recipe && importResponse.value.recipe.steps) {
|
||||
mergeAllSteps(importResponse.value.recipe.steps)
|
||||
}
|
||||
}
|
||||
|
||||
function handleSplitAllSteps(): void {
|
||||
if (importResponse.value.recipe && importResponse.value.recipe.steps){
|
||||
if (importResponse.value.recipe && importResponse.value.recipe.steps) {
|
||||
splitAllSteps(importResponse.value.recipe.steps, '\n')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {
|
||||
AccessToken,
|
||||
AccessToken, AiLog, AiProvider,
|
||||
ApiApi, ApiKeywordMoveUpdateRequest, Automation, type AutomationTypeEnum, ConnectorConfig, CookLog, CustomFilter,
|
||||
Food,
|
||||
Ingredient,
|
||||
@@ -146,6 +146,8 @@ export type EditorSupportedModels =
|
||||
| 'ViewLog'
|
||||
| 'ConnectorConfig'
|
||||
| 'SearchFields'
|
||||
| 'AiProvider'
|
||||
| 'AiLog'
|
||||
|
||||
// used to type methods/parameters in conjunction with configuration type
|
||||
export type EditorSupportedTypes =
|
||||
@@ -180,6 +182,8 @@ export type EditorSupportedTypes =
|
||||
| ViewLog
|
||||
| ConnectorConfig
|
||||
| SearchFields
|
||||
| AiProvider
|
||||
| AiLog
|
||||
|
||||
export const TFood = {
|
||||
name: 'Food',
|
||||
@@ -788,6 +792,53 @@ export const TConnectorConfig = {
|
||||
} as Model
|
||||
registerModel(TConnectorConfig)
|
||||
|
||||
export const TAiProvider = {
|
||||
name: 'AiProvider',
|
||||
localizationKey: 'AiProvider',
|
||||
localizationKeyDescription: 'AiProviderHelp',
|
||||
icon: 'fa-solid fa-wand-magic-sparkles',
|
||||
|
||||
editorComponent: defineAsyncComponent(() => import(`@/components/model_editors/AiProviderEditor.vue`)),
|
||||
|
||||
disableListView: false,
|
||||
toStringKeys: ['name'],
|
||||
isPaginated: true,
|
||||
|
||||
disableCreate: false,
|
||||
disableDelete: false,
|
||||
disableUpdate: false,
|
||||
|
||||
tableHeaders: [
|
||||
{title: 'Name', key: 'name'},
|
||||
|
||||
{title: 'Actions', key: 'action', align: 'end'},
|
||||
]
|
||||
} as Model
|
||||
registerModel(TAiProvider)
|
||||
|
||||
export const TAiLog = {
|
||||
name: 'AiLog',
|
||||
localizationKey: 'AiLog',
|
||||
localizationKeyDescription: 'AiLogHelp',
|
||||
icon: 'fa-solid fa-wand-magic-sparkles',
|
||||
|
||||
disableListView: false,
|
||||
toStringKeys: ['aiProvider.name', 'function', 'created_at'],
|
||||
isPaginated: true,
|
||||
|
||||
disableCreate: true,
|
||||
disableDelete: true,
|
||||
disableUpdate: true,
|
||||
|
||||
tableHeaders: [
|
||||
{title: 'Name', key: 'function'},
|
||||
{title: 'AiProvider', key: 'aiProvider.name',},
|
||||
{title: 'CreatedAt', key: 'createdAt'},
|
||||
{title: 'Actions', key: 'action', align: 'end'},
|
||||
]
|
||||
} as Model
|
||||
registerModel(TAiLog)
|
||||
|
||||
export const TFoodInheritField = {
|
||||
name: 'FoodInheritField',
|
||||
localizationKey: 'FoodInherit',
|
||||
|
||||
Reference in New Issue
Block a user