From 22d7418a7803c15a9e885673b15300253118ebbb Mon Sep 17 00:00:00 2001 From: Rachid Flih Date: Thu, 21 Nov 2024 17:51:19 -0300 Subject: [PATCH] fix: Killed RAG feature --- apps/webapp/Dockerfile.slim | 61 + apps/webapp/next.config.mjs | 8 +- .../app/(Dashboard)/configuration/page.tsx | 5 - .../RAGSettings/RAGItemDisplay.tsx | 297 ---- .../Configuration/RAGSettings/RAGItemList.tsx | 40 - .../Configuration/RAGSettings/RAGLayout.tsx | 79 -- .../RAGSettings/RAGSettingsPage.tsx | 31 - .../Configuration/RAGSettings/useRagItem.tsx | 18 - .../Configuration/RAGSettings/utils.ts | 17 - .../api/src/@core/@core-services/module.ts | 6 +- .../unification/ingest-data.service.ts | 3 - packages/api/src/@core/core.module.ts | 3 - .../@core/rag/chunking/chunking.service.ts | 80 -- .../api/src/@core/rag/document.processor.ts | 73 - .../embedding.credentials.service.ts | 58 - .../@core/rag/embedding/embedding.service.ts | 117 -- .../src/@core/rag/loader/loader.service.ts | 104 -- packages/api/src/@core/rag/rag.controller.ts | 78 - packages/api/src/@core/rag/rag.dto.ts | 65 - packages/api/src/@core/rag/rag.module.ts | 63 - packages/api/src/@core/rag/rag.service.ts | 56 - packages/api/src/@core/rag/types/index.ts | 11 - .../rag/vecdb/chromadb/chromadb.service.ts | 55 - .../@core/rag/vecdb/milvus/milvus.service.ts | 116 -- .../rag/vecdb/pinecone/pinecone.service.ts | 75 - .../@core/rag/vecdb/qdrant/qdrant.service.ts | 121 -- .../vecdb/turbopuffer/turbopuffer.service.ts | 48 - .../rag/vecdb/vecdb.credentials.service.ts | 92 -- .../api/src/@core/rag/vecdb/vecdb.service.ts | 122 -- .../rag/vecdb/weaviate/weaviate.service.ts | 98 -- packages/api/src/@core/s3/constants.ts | 1 - packages/api/src/@core/s3/s3.service.ts | 336 ----- packages/api/swagger/swagger-spec.yaml | 1251 ++++++++--------- 33 files changed, 688 insertions(+), 2900 deletions(-) create mode 100644 apps/webapp/Dockerfile.slim delete mode 100644 apps/webapp/src/components/Configuration/RAGSettings/RAGItemDisplay.tsx delete mode 100644 apps/webapp/src/components/Configuration/RAGSettings/RAGItemList.tsx delete mode 100644 apps/webapp/src/components/Configuration/RAGSettings/RAGLayout.tsx delete mode 100644 apps/webapp/src/components/Configuration/RAGSettings/RAGSettingsPage.tsx delete mode 100644 apps/webapp/src/components/Configuration/RAGSettings/useRagItem.tsx delete mode 100644 apps/webapp/src/components/Configuration/RAGSettings/utils.ts delete mode 100644 packages/api/src/@core/rag/chunking/chunking.service.ts delete mode 100644 packages/api/src/@core/rag/document.processor.ts delete mode 100644 packages/api/src/@core/rag/embedding/embedding.credentials.service.ts delete mode 100644 packages/api/src/@core/rag/embedding/embedding.service.ts delete mode 100644 packages/api/src/@core/rag/loader/loader.service.ts delete mode 100644 packages/api/src/@core/rag/rag.controller.ts delete mode 100644 packages/api/src/@core/rag/rag.dto.ts delete mode 100644 packages/api/src/@core/rag/rag.module.ts delete mode 100644 packages/api/src/@core/rag/rag.service.ts delete mode 100644 packages/api/src/@core/rag/types/index.ts delete mode 100644 packages/api/src/@core/rag/vecdb/chromadb/chromadb.service.ts delete mode 100644 packages/api/src/@core/rag/vecdb/milvus/milvus.service.ts delete mode 100644 packages/api/src/@core/rag/vecdb/pinecone/pinecone.service.ts delete mode 100644 packages/api/src/@core/rag/vecdb/qdrant/qdrant.service.ts delete mode 100644 packages/api/src/@core/rag/vecdb/turbopuffer/turbopuffer.service.ts delete mode 100644 packages/api/src/@core/rag/vecdb/vecdb.credentials.service.ts delete mode 100644 packages/api/src/@core/rag/vecdb/vecdb.service.ts delete mode 100644 packages/api/src/@core/rag/vecdb/weaviate/weaviate.service.ts delete mode 100644 packages/api/src/@core/s3/constants.ts delete mode 100644 packages/api/src/@core/s3/s3.service.ts diff --git a/apps/webapp/Dockerfile.slim b/apps/webapp/Dockerfile.slim new file mode 100644 index 000000000..e3dc2a480 --- /dev/null +++ b/apps/webapp/Dockerfile.slim @@ -0,0 +1,61 @@ +FROM node:20-alpine AS base +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" +RUN apk add --no-cache libc6-compat && \ + corepack enable + +WORKDIR /app + +# Install Turbo +RUN pnpm add -g turbo@1.13.4 + +# Copy necessary files for turbo prune +COPY . . + +# Prune the workspace +RUN turbo prune --scope=webapp --docker + +# Installer stage +FROM base AS installer +WORKDIR /app + +# Copy pruned files +COPY --from=base /app/out/json/ . +COPY --from=base /app/out/pnpm-lock.yaml ./pnpm-lock.yaml +COPY --from=base /app/out/full/ . + +# Install dependencies +RUN pnpm install --shamefully-hoist + +# Build shared package first +RUN cd packages/shared && pnpm run build + +# Build the webapp +RUN pnpm run build --filter=webapp... + +# Runner stage +FROM node:20-alpine AS runner +WORKDIR /app + +# Don't run production as root +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs + +# Copy necessary files +COPY --from=installer /app/apps/webapp/.next/standalone ./ +COPY --from=installer /app/apps/webapp/.next/static ./apps/webapp/.next/static +COPY --from=installer /app/apps/webapp/public ./apps/webapp/public + +# Copy package.json files +COPY --from=installer /app/apps/webapp/package.json ./package.json + +# Install only production dependencies + +USER nextjs + +ENV NODE_ENV=production +ENV PORT=8090 + +EXPOSE 8090 + +CMD ["node", "server.js"] \ No newline at end of file diff --git a/apps/webapp/next.config.mjs b/apps/webapp/next.config.mjs index 0050161f4..2f4162c91 100644 --- a/apps/webapp/next.config.mjs +++ b/apps/webapp/next.config.mjs @@ -1,6 +1,12 @@ /** @type {import('next').NextConfig} */ +import path from 'path'; +import { fileURLToPath } from 'url'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + const nextConfig = { output: 'standalone', + outputFileTracingRoot: path.join(__dirname, '../../'), async redirects() { return [ { @@ -12,4 +18,4 @@ const nextConfig = { } }; -export default nextConfig; +export default nextConfig; \ No newline at end of file diff --git a/apps/webapp/src/app/(Dashboard)/configuration/page.tsx b/apps/webapp/src/app/(Dashboard)/configuration/page.tsx index 106c1d1e6..66aac6bae 100644 --- a/apps/webapp/src/app/(Dashboard)/configuration/page.tsx +++ b/apps/webapp/src/app/(Dashboard)/configuration/page.tsx @@ -39,7 +39,6 @@ import useUpdatePullFrequency from "@/hooks/create/useCreatePullFrequency"; import { toast } from "sonner"; import { useQueryClient } from "@tanstack/react-query"; import { Loader2 } from "lucide-react"; -import RAGSettingsPage from "@/components/Configuration/RAGSettings/RAGSettingsPage"; const frequencyOptions = [ { label: '5 min', value: 300 }, @@ -185,7 +184,6 @@ export default function Page() { Sync Frequency - RAG Settings Manage Catalog Widget @@ -360,9 +358,6 @@ export default function Page() { - - - diff --git a/apps/webapp/src/components/Configuration/RAGSettings/RAGItemDisplay.tsx b/apps/webapp/src/components/Configuration/RAGSettings/RAGItemDisplay.tsx deleted file mode 100644 index 8e7e7711c..000000000 --- a/apps/webapp/src/components/Configuration/RAGSettings/RAGItemDisplay.tsx +++ /dev/null @@ -1,297 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import { useForm } from "react-hook-form"; -import { zodResolver } from "@hookform/resolvers/zod"; -import { useQueryClient } from "@tanstack/react-query"; -import { usePostHog } from 'posthog-js/react'; -import { toast } from "sonner"; -import * as z from "zod"; -import { Button } from "@/components/ui/button"; -import { Separator } from "@/components/ui/separator"; -import { Switch } from "@/components/ui/switch"; -import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; -import { Input } from "@/components/ui/input"; -import config from "@/lib/config"; -import useProjectStore from "@/state/projectStore"; -import useConnectionStrategies from "@/hooks/get/useConnectionStrategies"; -import useCreateConnectionStrategy from "@/hooks/create/useCreateConnectionStrategy"; -import useUpdateConnectionStrategy from "@/hooks/update/useUpdateConnectionStrategy"; -import useConnectionStrategyAuthCredentials from "@/hooks/get/useConnectionStrategyAuthCredentials"; -import { vectorDatabases, embeddingModels, TabType } from './utils'; - -const formSchema = z.object({ - apiKey: z.string().optional(), - baseUrl: z.string().optional(), - url: z.string().optional(), - indexName: z.string().optional(), - embeddingApiKey: z.string().optional(), - collectionName: z.string().optional(), - className: z.string().optional(), -}); - -interface ItemDisplayProps { - item?: typeof vectorDatabases[number] | typeof embeddingModels[number]; - type: string; -} - -export function RAGItemDisplay({ item, type }: ItemDisplayProps) { - const [isActive, setIsActive] = useState(false); - const { idProject } = useProjectStore(); - const queryClient = useQueryClient(); - const posthog = usePostHog(); - - const { data: connectionStrategies } = useConnectionStrategies(); - const { createCsPromise } = useCreateConnectionStrategy(); - const { updateCsPromise } = useUpdateConnectionStrategy(); - const { mutateAsync: fetchCredentials } = useConnectionStrategyAuthCredentials(); - - const form = useForm>({ - resolver: zodResolver(formSchema), - defaultValues: { - apiKey: "", baseUrl: "", url: "", indexName: "", embeddingApiKey: "", - }, - }); - - const currentStrategy = connectionStrategies?.find( - (cs) => cs.type === `${type}.${item?.name.toLowerCase()}` - ); - - useEffect(() => { - if (currentStrategy) { - fetchCredentials({ type: currentStrategy.type, attributes: getAttributesForItem(item?.name) }, { - onSuccess(data) { - setFormValuesFromCredentials(item?.name ?? '', data); - setIsActive(currentStrategy.status === true); - } - }); - } else { - form.reset(); - setIsActive(false); - } - }, [connectionStrategies, item]); - - function onSubmit(values: z.infer) { - const attributes = getAttributesForItem(item?.name); - const attributeValues = attributes.map(attr => values[attr as keyof typeof values]).filter((value): value is string => value !== undefined); - - const promise = currentStrategy - ? updateCsPromise({ - id_cs: currentStrategy.id_connection_strategy, - updateToggle: false, - status: isActive, - attributes, - values: attributeValues, - }) - : createCsPromise({ - type: `${type}.${item?.name.toLowerCase()}`, - attributes, - values: attributeValues, - status: false, - }); - - toast.promise(promise, { - loading: 'Saving changes...', - success: (data: any) => { - queryClient.setQueryData( - ['connection-strategies'], - (oldData = []) => { - if (currentStrategy) { - return oldData.map(cs => - cs.id_connection_strategy === data.id_connection_strategy - ? { ...data, status: isActive } // Ensure status matches isActive - : cs - ); - } else { - return [...oldData, { ...data, status: false }]; // New strategy is inactive - } - } - ); - setIsActive(data.status); - return "Changes saved successfully"; - }, - error: (err: any) => err.message || 'An error occurred', - }); - - posthog?.capture(`RAG_${type}_${currentStrategy ? 'updated' : 'created'}`, { - id_project: idProject, - item_name: item?.name, - mode: config.DISTRIBUTION - }); - } - - const handleActiveChange = (checked: boolean) => { - if (currentStrategy) { - const updatePromises = []; - - // Update current strategy - updatePromises.push( - toast.promise( - updateCsPromise({ - id_cs: currentStrategy.id_connection_strategy, - updateToggle: true, - status: checked - }), - { - loading: `${checked ? 'Activating' : 'Deactivating'} ${item?.name}...`, - success: (data: any) => { - queryClient.setQueryData(['connection-strategies'], (oldData = []) => - oldData.map(cs => cs.id_connection_strategy === data.id_connection_strategy ? data : cs) - ); - setIsActive(checked); - return `${item?.name} ${checked ? 'activated' : 'deactivated'} successfully`; - }, - error: (err: any) => err.message || 'An error occurred', - } - ) - ); - - if (checked) { - // Deactivate other items of the same type - connectionStrategies?.forEach(cs => { - if (cs.type.startsWith(`${type}.`) && cs.type !== `${type}.${item?.name.toLowerCase()}` && cs.status) { - updatePromises.push( - toast.promise( - updateCsPromise({ - id_cs: cs.id_connection_strategy, - updateToggle: true, - status: false - }), - { - loading: `Deactivating ${cs.type.split('.')[1]}...`, - success: (data: any) => { - queryClient.setQueryData(['connection-strategies'], (oldData = []) => - oldData.map(strategy => strategy.id_connection_strategy === data.id_connection_strategy ? data : strategy) - ); - return `${cs.type.split('.')[1]} deactivated successfully`; - }, - error: (err: any) => err.message || 'An error occurred', - } - ) - ); - } - }); - } - - // Wait for all updates to complete - Promise.all(updatePromises).then(() => { - queryClient.invalidateQueries({ queryKey: ['connection-strategies'] }); - }); - } - }; - - const getAttributesForItem = (itemName?: string): string[] => { - switch (itemName?.toLowerCase()) { - case 'turbopuffer': - return ['apiKey']; - case 'pinecone': - return ['apiKey', 'indexName']; - case 'qdrant': - return ['apiKey', 'baseUrl', 'collectionName']; - case 'chromadb': - return ['url', 'collectionName']; - case 'weaviate': - return ['apiKey', 'url', 'className']; - case 'openai_ada_small_1536': - case 'openai_ada_large_3072': - case 'openai_ada_002': - case 'cohere_multilingual_v3': - return ['embeddingApiKey']; - default: - return []; - } - }; - - const setFormValuesFromCredentials = (itemName: string, data: string[]) => { - switch (itemName?.toLowerCase()) { - case 'turbopuffer': - form.setValue("apiKey", data[0]); - break; - case 'pinecone': - form.setValue("apiKey", data[0]); - form.setValue("indexName", data[1]); - break; - case 'qdrant': - form.setValue("apiKey", data[0]); - form.setValue("baseUrl", data[1]); - form.setValue("collectionName", data[1]); - break; - case 'chromadb': - form.setValue("url", data[0]); - form.setValue("collectionName", data[1]); - break; - case 'weaviate': - form.setValue("apiKey", data[0]); - form.setValue("url", data[1]); - form.setValue("className", data[1]); - break; - case 'openai_ada_small_1536': - case 'openai_ada_large_3072': - case 'openai_ada_002': - case 'cohere_multilingual_v3': - form.setValue("embeddingApiKey", data[0]); - break; - } - }; - - const renderInputs = () => { - const attributes = getAttributesForItem(item?.name); - return attributes.map((attr) => ( - } - render={({ field }) => ( - - {attr} - - - - - - )} - /> - )); - }; - - return ( -
- - {item ? ( -
-
-
- {item.name} -
-
{item.name}
-
{item.description}
-
- -
-
-
-
- -
-
- - {renderInputs()} - -
- -
-
- ) : ( -
- No item selected -
- )} -
- ); -} \ No newline at end of file diff --git a/apps/webapp/src/components/Configuration/RAGSettings/RAGItemList.tsx b/apps/webapp/src/components/Configuration/RAGSettings/RAGItemList.tsx deleted file mode 100644 index cf0e1b17d..000000000 --- a/apps/webapp/src/components/Configuration/RAGSettings/RAGItemList.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import * as React from "react" -import { cn } from "@/lib/utils" -import { Button } from "@/components/ui/button" -import { ScrollArea } from "@/components/ui/scroll-area" -import { vectorDatabases, embeddingModels } from "./utils" -import { useRagItem } from "./useRagItem" - -interface RAGItemListProps { - items: (typeof vectorDatabases[number] | typeof embeddingModels[number])[]; - type: string; -} - -export function RAGItemList({ items, type }: RAGItemListProps) { - const [ragItem, setRagItem] = useRagItem() - - return ( - -
- {items.map((item) => ( - - ))} -
-
- ) -} \ No newline at end of file diff --git a/apps/webapp/src/components/Configuration/RAGSettings/RAGLayout.tsx b/apps/webapp/src/components/Configuration/RAGSettings/RAGLayout.tsx deleted file mode 100644 index 5dc141338..000000000 --- a/apps/webapp/src/components/Configuration/RAGSettings/RAGLayout.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import { Input } from "@/components/ui/input" -import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "@/components/ui/resizable" -import { Separator } from "@/components/ui/separator" -import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs" -import { TooltipProvider } from "@/components/ui/tooltip" -import { Search } from "lucide-react" -import * as React from "react" -import { RAGItemDisplay } from "./RAGItemDisplay" -import { RAGItemList } from "./RAGItemList" -import { embeddingModels, vectorDatabases } from "./utils" -import { useRagItem } from "./useRagItem" - -interface Props { - items: (typeof vectorDatabases[number] | typeof embeddingModels[number])[]; - defaultLayout: number[] | undefined - onSearchChange: (query: string) => void - activeTab: string; - setActiveTab: (tab: string) => void -} - -export function RAGLayout({ - items, - defaultLayout = [265, 440, 655], - onSearchChange, - activeTab, - setActiveTab -}: Props) { - const [ragItem, setRagItem] = useRagItem() - const handleSearchChange = (event: React.ChangeEvent) => { - onSearchChange(event.target.value) - } - - return ( - - { - document.cookie = `react-resizable-panels:layout=${JSON.stringify( - sizes - )}` - }} - className="h-full max-h-[800px] items-stretch" - > - - setActiveTab(value as "vectorDatabase" | "embeddingModel")}> -
-

RAG Settings

-

Configure your vector databases and embedding models for Retrieval-Augmented Generation.

-
- - - Vector Databases - Embedding Models - -
-
-
- - -
-
-
- -
-
- - - item.name === ragItem.selected)} - type={activeTab} - /> - -
-
- ) -} \ No newline at end of file diff --git a/apps/webapp/src/components/Configuration/RAGSettings/RAGSettingsPage.tsx b/apps/webapp/src/components/Configuration/RAGSettings/RAGSettingsPage.tsx deleted file mode 100644 index d71e53aae..000000000 --- a/apps/webapp/src/components/Configuration/RAGSettings/RAGSettingsPage.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import * as React from "react" -import { RAGLayout } from "./RAGLayout"; -import { embeddingModels, TabType, vectorDatabases } from "./utils"; - -export default function RAGSettingsPage() { - const [searchQuery, setSearchQuery] = React.useState("") - const [activeTab, setActiveTab] = React.useState("vectorDatabase") - const defaultLayout = undefined - - const handleSearchChange = (query: string) => { - setSearchQuery(query) - } - - const items = activeTab === "vectorDatabase" ? vectorDatabases : embeddingModels - const filteredItems = items.filter((item) => { - const matchesSearch = item.name.toLowerCase().includes(searchQuery.toLowerCase()) || item.description?.toLowerCase().includes(searchQuery.toLowerCase()) - return matchesSearch - }) - - return ( -
- -
- ) -} \ No newline at end of file diff --git a/apps/webapp/src/components/Configuration/RAGSettings/useRagItem.tsx b/apps/webapp/src/components/Configuration/RAGSettings/useRagItem.tsx deleted file mode 100644 index 9d20bddbf..000000000 --- a/apps/webapp/src/components/Configuration/RAGSettings/useRagItem.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { atom, useAtom } from "jotai" -import { vectorDatabases, embeddingModels } from "./utils" - -type ItemType = "vectorDatabase" | "embeddingModel" - -type Config = { - selected: string - type: string -} - -const configAtom = atom({ - selected: vectorDatabases[0].name, - type: "vectorDatabase" -}) - -export function useRagItem() { - return useAtom(configAtom) -} \ No newline at end of file diff --git a/apps/webapp/src/components/Configuration/RAGSettings/utils.ts b/apps/webapp/src/components/Configuration/RAGSettings/utils.ts deleted file mode 100644 index 770da4909..000000000 --- a/apps/webapp/src/components/Configuration/RAGSettings/utils.ts +++ /dev/null @@ -1,17 +0,0 @@ -export const vectorDatabases = [ - { name: "Pinecone", logoPath: "/rag/pinecone.png", description: "Pinecone vector database" }, - { name: "Qdrant", logoPath: "/rag/qdrant.png", description: "Qdrant vector database" }, - { name: "Weaviate", logoPath: "/rag/weaviate.webp", description: "Weaviate vector database" }, - { name: "Chromadb", logoPath: "/rag/chroma.webp", description: "ChromaDB vector database" }, - { name: "Turbopuffer", logoPath: "/rag/turbopuffer.png", description: "TurboPuffer vector database" }, -]; - -export const embeddingModels = [ - { name: "OPENAI_ADA_SMALL_1536", logoPath: "/rag/openai.png", description: "OpenAI - text-embedding-3-small" }, - { name: "OPENAI_ADA_LARGE_3072", logoPath: "/rag/openai.png", description: "OpenAI - text-embedding-3-large" }, - { name: "OPENAI_ADA_002", logoPath: "/rag/openai.png", description: "OpenAI - text-embedding-ada-002" }, - { name: "COHERE_MULTILINGUAL_V3", logoPath: "/rag/cohere.jpeg", description: "Cohere - embed-multilingual-v3.0" }, -]; - -export type TabType = "vectorDatabase" | "embeddingModel"; - \ No newline at end of file diff --git a/packages/api/src/@core/@core-services/module.ts b/packages/api/src/@core/@core-services/module.ts index 4381224d8..0854eceec 100644 --- a/packages/api/src/@core/@core-services/module.ts +++ b/packages/api/src/@core/@core-services/module.ts @@ -1,4 +1,3 @@ -import { RagModule } from '@@core/rag/rag.module'; import { Global, Module } from '@nestjs/common'; import { ConnectionUtils } from '../connections/@utils/index'; import { FieldMappingService } from './../field-mapping/field-mapping.service'; @@ -12,11 +11,10 @@ import { MappersRegistry } from './registries/mappers.registry'; import { UnificationRegistry } from './registries/unification.registry'; import { RetryModule } from './request-retry/module'; import { CoreUnification } from './unification/core-unification.service'; -import { RagService } from '@@core/rag/rag.service'; @Global() @Module({ - imports: [BullQueueModule, RetryModule, RagModule], + imports: [BullQueueModule, RetryModule], providers: [ PrismaService, MappersRegistry, @@ -28,7 +26,6 @@ import { RagService } from '@@core/rag/rag.service'; LoggerService, ConnectionUtils, FieldMappingService, - RagService, ], exports: [ PrismaService, @@ -43,7 +40,6 @@ import { RagService } from '@@core/rag/rag.service'; FieldMappingService, BullQueueModule, RetryModule, - RagService, ], }) export class CoreSharedModule {} diff --git a/packages/api/src/@core/@core-services/unification/ingest-data.service.ts b/packages/api/src/@core/@core-services/unification/ingest-data.service.ts index 353f5718c..685ccd487 100644 --- a/packages/api/src/@core/@core-services/unification/ingest-data.service.ts +++ b/packages/api/src/@core/@core-services/unification/ingest-data.service.ts @@ -14,8 +14,6 @@ import { ConnectionUtils } from '@@core/connections/@utils'; import { IBaseObjectService, SyncParam } from '@@core/utils/types/interface'; import { FieldMappingService } from '@@core/field-mapping/field-mapping.service'; import { LoggerService } from '../logger/logger.service'; -import { RagService } from '@@core/rag/rag.service'; -import { FileInfo } from '@@core/rag/types'; import { fs_files as FileStorageFile } from '@prisma/client'; @Injectable() @@ -28,7 +26,6 @@ export class IngestDataService { private connectionUtils: ConnectionUtils, private logger: LoggerService, private fieldMappingService: FieldMappingService, - private ragService: RagService, ) {} async syncForLinkedUser( diff --git a/packages/api/src/@core/core.module.ts b/packages/api/src/@core/core.module.ts index bb7310259..fb78e6842 100644 --- a/packages/api/src/@core/core.module.ts +++ b/packages/api/src/@core/core.module.ts @@ -16,7 +16,6 @@ import { PassthroughModule } from './passthrough/passthrough.module'; import { ProjectConnectorsModule } from './project-connectors/project-connectors.module'; import { ProjectsModule } from './projects/projects.module'; import { SyncModule } from './sync/sync.module'; -import { RagModule } from './rag/rag.module'; @Module({ imports: [ @@ -36,7 +35,6 @@ import { RagModule } from './rag/rag.module'; SyncModule, ProjectConnectorsModule, BullQueueModule, - RagModule, ], exports: [ AuthModule, @@ -56,7 +54,6 @@ import { RagModule } from './rag/rag.module'; ProjectConnectorsModule, IngestDataService, BullQueueModule, - RagModule, ], providers: [IngestDataService], }) diff --git a/packages/api/src/@core/rag/chunking/chunking.service.ts b/packages/api/src/@core/rag/chunking/chunking.service.ts deleted file mode 100644 index dc45670bb..000000000 --- a/packages/api/src/@core/rag/chunking/chunking.service.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { RecursiveCharacterTextSplitter } from '@langchain/textsplitters'; -import { Document } from '@langchain/core/documents'; - -@Injectable() -export class DocumentSplitterService { - async chunkDocument( - documents: Document[], - fileType: string, - chunkSize = 1000, - chunkOverlap = 200, - ): Promise { - const chunkedDocuments: Document[] = []; - - for (const document of documents) { - let chunks: Document[]; - - if (fileType === 'json' || fileType === 'csv') { - chunks = await this.chunkJSON(document, chunkSize); - } else { - chunks = await this.chunkText(document, chunkSize, chunkOverlap); - } - - chunkedDocuments.push(...chunks); - } - - return chunkedDocuments; - } - - private async chunkText( - document: Document, - chunkSize: number, - chunkOverlap: number, - ): Promise { - const textSplitter = new RecursiveCharacterTextSplitter({ - chunkSize, - chunkOverlap, - }); - return textSplitter.splitDocuments([document]); - } - - private async chunkJSON( - document: Document, - chunkSize: number, - ): Promise { - const jsonContent = JSON.parse(document.pageContent); - const chunks: Document[] = []; - let currentChunk: Record = {}; - let currentSize = 0; - - for (const [key, value] of Object.entries(jsonContent)) { - const entrySize = JSON.stringify({ [key]: value }).length; - - if (currentSize + entrySize > chunkSize && currentSize > 0) { - chunks.push( - new Document({ - pageContent: JSON.stringify(currentChunk), - metadata: { ...document.metadata, chunk: chunks.length + 1 }, - }), - ); - currentChunk = {}; - currentSize = 0; - } - - currentChunk[key] = value; - currentSize += entrySize; - } - - if (Object.keys(currentChunk).length > 0) { - chunks.push( - new Document({ - pageContent: JSON.stringify(currentChunk), - metadata: { ...document.metadata, chunk: chunks.length + 1 }, - }), - ); - } - - return chunks; - } -} \ No newline at end of file diff --git a/packages/api/src/@core/rag/document.processor.ts b/packages/api/src/@core/rag/document.processor.ts deleted file mode 100644 index ef5191c2c..000000000 --- a/packages/api/src/@core/rag/document.processor.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { Process, Processor } from '@nestjs/bull'; -import { Job } from 'bull'; -import { FileInfo } from './types'; -import { VectorDatabaseService } from './vecdb/vecdb.service'; -import { S3Service } from '@@core/s3/s3.service'; -import { DocumentSplitterService } from './chunking/chunking.service'; -import { EmbeddingService } from './embedding/embedding.service'; -import { DocumentLoaderService } from './loader/loader.service'; - -@Processor('RAG_DOCUMENT_PROCESSING') -export class ProcessDocumentProcessor { - constructor( - private s3Service: S3Service, - private documentLoaderService: DocumentLoaderService, - private documentSplitterService: DocumentSplitterService, - private embeddingService: EmbeddingService, - private vectorDatabaseService: VectorDatabaseService, - ) {} - - @Process('batchDocs') - async processDocuments( - job: Job<{ - filesInfo: FileInfo[]; - projectId: string; - linkedUserId: string; - }>, - ) { - const { filesInfo, projectId, linkedUserId } = job.data; - const results = []; - - for (const fileInfo of filesInfo) { - try { - const readStream = await this.s3Service.getReadStream(fileInfo.s3Key); - const document = - await this.documentLoaderService.loadDocumentFromStream( - readStream, - fileInfo.fileType, - fileInfo.s3Key, - ); - const chunks = await this.documentSplitterService.chunkDocument( - document, - fileInfo.fileType, - ); - // console.log(`chunks for ${fileInfo.id} are ` + JSON.stringify(chunks)); - const embeddings = await this.embeddingService.generateEmbeddings( - chunks, - projectId, - ); - // Split embeddings into smaller batches - const batchSize = 100; // Adjust this value as needed - for (let i = 0; i < chunks.length; i += batchSize) { - const batchChunks = chunks.slice(i, i + batchSize); - const batchEmbeddings = embeddings.slice(i, i + batchSize); - await this.vectorDatabaseService.storeEmbeddings( - fileInfo.id, - batchChunks, - batchEmbeddings, - projectId, - linkedUserId, - ); - } - results.push(`Successfully processed document ${fileInfo.id}`); - } catch (error) { - console.error(`Error processing document ${fileInfo.id}:`, error); - results.push( - `Failed to process document ${fileInfo.id}: ${error.message}`, - ); - } - } - - return results; - } -} diff --git a/packages/api/src/@core/rag/embedding/embedding.credentials.service.ts b/packages/api/src/@core/rag/embedding/embedding.credentials.service.ts deleted file mode 100644 index 4189298e9..000000000 --- a/packages/api/src/@core/rag/embedding/embedding.credentials.service.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { EnvironmentService } from '@@core/@core-services/environment/environment.service'; -import { ConnectionsStrategiesService } from '@@core/connections-strategies/connections-strategies.service'; -import { EmbeddingModelType } from './embedding.service'; - -@Injectable() -export class EmbeddingCredentialsService { - constructor( - private envService: EnvironmentService, - private connectionsStrategiesService: ConnectionsStrategiesService, - ) {} - - async getEmbeddingCredentials( - projectId: string, - embeddingModel: EmbeddingModelType, - ): Promise { - const type = `embeddingModel.${embeddingModel.toLowerCase()}`; - const isCustom = - await this.connectionsStrategiesService.isCustomCredentials( - projectId, - type, - ); - - if (isCustom) { - return this.getCustomCredentials(projectId, type); - } else { - return this.getManagedCredentials(embeddingModel); - } - } - - private async getCustomCredentials( - projectId: string, - type: string, - ): Promise { - return this.connectionsStrategiesService.getConnectionStrategyData( - projectId, - type, - ['embeddingApiKey'], - ); - } - - private getManagedCredentials(embeddingModel: EmbeddingModelType): string[] { - switch (embeddingModel) { - case 'OPENAI_ADA_SMALL_512': - case 'OPENAI_ADA_SMALL_1536': - case 'OPENAI_ADA_LARGE_256': - case 'OPENAI_ADA_LARGE_1024': - case 'OPENAI_ADA_LARGE_3072': - return [this.envService.getOpenAIApiKey()]; - case 'COHERE_MULTILINGUAL_V3': - return [this.envService.getCohereApiKey()]; - case 'JINA': - return [this.envService.getJinaApiKey()]; - default: - throw new Error(`Unsupported embedding model: ${embeddingModel}`); - } - } -} diff --git a/packages/api/src/@core/rag/embedding/embedding.service.ts b/packages/api/src/@core/rag/embedding/embedding.service.ts deleted file mode 100644 index f4c19c6e9..000000000 --- a/packages/api/src/@core/rag/embedding/embedding.service.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { EnvironmentService } from '@@core/@core-services/environment/environment.service'; -import { CohereEmbeddings } from '@langchain/cohere'; -import { Document } from '@langchain/core/documents'; -import { OpenAIEmbeddings } from '@langchain/openai'; -import { JinaEmbeddings } from '@langchain/community/embeddings/jina'; -import { Injectable, OnModuleInit } from '@nestjs/common'; -import { ConnectionsStrategiesService } from '@@core/connections-strategies/connections-strategies.service'; -import { EmbeddingCredentialsService } from './embedding.credentials.service'; - -export type EmbeddingModelType = - | 'OPENAI_ADA_SMALL_512' - | 'OPENAI_ADA_SMALL_1536' - | 'OPENAI_ADA_LARGE_256' - | 'OPENAI_ADA_LARGE_1024' - | 'OPENAI_ADA_002' - | 'OPENAI_ADA_LARGE_3072' - | 'COHERE_MULTILINGUAL_V3' - | 'JINA'; - -@Injectable() -export class EmbeddingService implements OnModuleInit { - private embeddings: OpenAIEmbeddings | CohereEmbeddings | JinaEmbeddings; - - constructor( - private envService: EnvironmentService, - private connectionsStrategiesService: ConnectionsStrategiesService, - private embeddingCredentialsService: EmbeddingCredentialsService, - ) {} - - async onModuleInit() { - // Initialize with default settings - console.log(); - } - - async initializeEmbeddings(projectId: string) { - let embeddingType: EmbeddingModelType; - let apiKey: string; - - if (projectId) { - const activeStrategies = - await this.connectionsStrategiesService.getConnectionStrategiesForProject( - projectId, - ); - const activeEmbeddingStrategy = activeStrategies.find( - (strategy) => - strategy.type.startsWith('embeddingModel.') && strategy.status, - ); - - if (activeEmbeddingStrategy) { - embeddingType = activeEmbeddingStrategy.type - .split('.')[1] - .toUpperCase() as EmbeddingModelType; - [apiKey] = - await this.embeddingCredentialsService.getEmbeddingCredentials( - projectId, - embeddingType, - ); - } else { - embeddingType = 'OPENAI_ADA_002'; - apiKey = this.envService.getOpenAIApiKey(); - } - } else { - embeddingType = 'OPENAI_ADA_002'; - apiKey = this.envService.getOpenAIApiKey(); - } - - switch (embeddingType) { - case 'OPENAI_ADA_002': - case 'OPENAI_ADA_SMALL_512': - case 'OPENAI_ADA_SMALL_1536': - case 'OPENAI_ADA_LARGE_256': - case 'OPENAI_ADA_LARGE_1024': - case 'OPENAI_ADA_LARGE_3072': - this.embeddings = new OpenAIEmbeddings({ - openAIApiKey: apiKey, - modelName: this.getOpenAIModelName(embeddingType), - }); - break; - case 'COHERE_MULTILINGUAL_V3': - this.embeddings = new CohereEmbeddings({ - apiKey, - model: 'multilingual-22-12', - }); - break; - case 'JINA': - this.embeddings = new JinaEmbeddings({ - apiKey, - }); - break; - default: - throw new Error(`Unsupported embedding type: ${embeddingType}`); - } - } - - private getOpenAIModelName(type: EmbeddingModelType): string { - const modelMap: { [key: string]: string } = { - OPENAI_ADA_002: 'text-embedding-ada-002', - OPENAI_ADA_SMALL_512: 'text-embedding-3-small', - OPENAI_ADA_SMALL_1536: 'text-embedding-3-small', - OPENAI_ADA_LARGE_256: 'text-embedding-3-large', - OPENAI_ADA_LARGE_1024: 'text-embedding-3-large', - OPENAI_ADA_LARGE_3072: 'text-embedding-3-large', - }; - return modelMap[type] || 'text-embedding-ada-002'; - } - - async generateEmbeddings(chunks: Document[], projectId: string) { - await this.initializeEmbeddings(projectId); - const texts = chunks.map((chunk) => chunk.pageContent); - return this.embeddings.embedDocuments(texts); - } - - async embedQuery(query: string, projectId?: string) { - await this.initializeEmbeddings(projectId); - return this.embeddings.embedQuery(query); - } -} diff --git a/packages/api/src/@core/rag/loader/loader.service.ts b/packages/api/src/@core/rag/loader/loader.service.ts deleted file mode 100644 index 687f5636b..000000000 --- a/packages/api/src/@core/rag/loader/loader.service.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { PDFLoader } from '@langchain/community/document_loaders/fs/pdf'; -import { DocxLoader } from '@langchain/community/document_loaders/fs/docx'; -import { TextLoader } from 'langchain/document_loaders/fs/text'; -import { UnstructuredLoader } from '@langchain/community/document_loaders/fs/unstructured'; -import { Readable } from 'stream'; -import { EnvironmentService } from '@@core/@core-services/environment/environment.service'; -import { Document } from 'langchain/document'; -import * as csvtojson from 'csvtojson'; - -type UnstructuredCredsType = { - apiKey: string; - apiUrl: string; -}; -@Injectable() -export class DocumentLoaderService { - private unstructuredCreds: UnstructuredCredsType; - constructor(private envService: EnvironmentService) { - this.unstructuredCreds = this.envService.getUnstructuredCreds(); - } - async loadDocumentFromStream( - stream: Readable, - fileType: string, - fileName?: string, - ) { - const buffer = await this.streamToBuffer(stream); - const loaders = { - pdf: (buf: Buffer) => new PDFLoader(new Blob([buf])), - docx: (buf: Buffer) => new DocxLoader(new Blob([buf])), - csv: (buf: Buffer) => ({ - load: async () => { - const content = buf.toString('utf-8'); - const lines = content.split('\n'); - const separator = this.detectSeparator(lines[0]); - const headers = lines[0] - .split(separator) - .map((header) => header.trim()); - - const jsonData = await csvtojson({ - delimiter: separator, - headers: headers, - output: 'json', - }).fromString(content); - - const formattedData = jsonData.map((item: any) => { - const formattedItem: Record = {}; - for (const key in item) { - const value = item[key]; - formattedItem[key] = isNaN(Number(value)) ? value : Number(value); - } - return formattedItem; - }); - - // console.log('json data from csv is ' + JSON.stringify(formattedData)); - - return formattedData.map( - (item, index) => - new Document({ - pageContent: JSON.stringify(item), - metadata: { - source: fileName || 'csv', - row: index + 2, - columns: headers, - }, - }), - ); - }, - }), - txt: (buf: Buffer) => new TextLoader(new Blob([buf])), - md: (buf: Buffer) => - new UnstructuredLoader( - { buffer: buf, fileName: fileName }, - { - apiKey: this.unstructuredCreds.apiKey, - apiUrl: this.unstructuredCreds.apiUrl, - }, - ), - }; - - const loaderFunction = loaders[fileType as keyof typeof loaders]; - if (!loaderFunction) { - throw new Error(`Unsupported file type: ${fileType}`); - } - - const loader = loaderFunction(buffer); - return loader.load(); - } - - private detectSeparator(headerLine: string): string { - const possibleSeparators = [',', ';', '\t', '|']; - return possibleSeparators.reduce((a, b) => - headerLine.split(a).length > headerLine.split(b).length ? a : b, - ); - } - - private async streamToBuffer(stream: Readable): Promise { - return new Promise((resolve, reject) => { - const chunks: Buffer[] = []; - stream.on('data', (chunk) => chunks.push(Buffer.from(chunk))); - stream.on('error', (err) => reject(err)); - stream.on('end', () => resolve(Buffer.concat(chunks))); - }); - } -} diff --git a/packages/api/src/@core/rag/rag.controller.ts b/packages/api/src/@core/rag/rag.controller.ts deleted file mode 100644 index 89d5e28b9..000000000 --- a/packages/api/src/@core/rag/rag.controller.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { ApiKeyAuthGuard } from '@@core/auth/guards/api-key.guard'; -import { ConnectionUtils } from '@@core/connections/@utils'; -import { ApiPostArrayCustomResponse } from '@@core/utils/dtos/openapi.respone.dto'; -import { Body, Controller, Headers, Post, UseGuards } from '@nestjs/common'; -import { ApiBody, ApiHeader, ApiOperation } from '@nestjs/swagger'; -import { QueryBody, RagQueryOutput } from './rag.dto'; -import { RagService } from './rag.service'; - -@Controller('rag') -export class RagController { - constructor( - private documentEmbeddingService: RagService, - private ragService: RagService, - private connectionUtils: ConnectionUtils, - ) {} - - @Post('query') - @ApiOperation({ - operationId: 'query', - summary: 'Query using RAG Search', - description: 'Query across your connected data sources using RAG Search', - }) - @ApiHeader({ - name: 'x-connection-token', - required: true, - description: 'The connection token', - example: 'b008e199-eda9-4629-bd41-a01b6195864a', - }) - @ApiPostArrayCustomResponse(RagQueryOutput) - @ApiBody({ type: QueryBody }) - @UseGuards(ApiKeyAuthGuard) - async queryEmbeddings( - @Body() body: QueryBody, - @Headers('x-connection-token') connection_token: string, - ) { - const { linkedUserId, remoteSource, connectionId, projectId } = - await this.connectionUtils.getConnectionMetadataFromConnectionToken( - connection_token, - ); - return await this.documentEmbeddingService.queryEmbeddings( - body.query, - body.topK, - linkedUserId, - projectId, - ); - } - - /* - @ApiOperation({ - operationId: 'listFilestorageFile', - summary: 'List Files', - }) - @ApiHeader({ - name: 'x-connection-token', - required: true, - description: 'The connection token', - example: 'b008e199-eda9-4629-bd41-a01b6195864a', - }) - @Post('process') - @UseGuards(ApiKeyAuthGuard) - async processFile(@Headers('x-connection-token') connection_token: string) { - const { linkedUserId, remoteSource, connectionId, projectId } = - await this.connectionUtils.getConnectionMetadataFromConnectionToken( - connection_token, - ); - const body = { - id: 'ID_1', - url: 'https://drive.google.com/file/d/1rrC1idlFpCBdF3DVzNDp1WeRZ4_mKGho/view', - s3Key: `${projectId}/ID_1.pdf`, - fileType: 'pdf', - }; - return await this.ragService.queueDocumentProcessing( - [body], - projectId, - linkedUserId, - ); - }*/ -} diff --git a/packages/api/src/@core/rag/rag.dto.ts b/packages/api/src/@core/rag/rag.dto.ts deleted file mode 100644 index 4337f69ef..000000000 --- a/packages/api/src/@core/rag/rag.dto.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; -import { IsNumber, IsString } from 'class-validator'; - -export class RagQueryOutput { - @ApiProperty({ - type: String, - example: 'Date : 06/07/2023', - nullable: false, - description: 'The chunk which matches the embed query', - }) - @IsString() - chunk: string; - - @ApiProperty({ - type: Object, - example: { - blobType: '', - text: 'ATTESTATION', - }, - additionalProperties: true, - nullable: true, - description: 'The metadata tied to the chunk', - }) - metadata: any; - - @ApiProperty({ - type: Number, - example: 0.87, - nullable: true, - description: 'The score', - }) - @IsNumber() - score: number; - - @ApiProperty({ - type: [Number], - example: [ - -0.00442447886, -0.00116857514, 0.00869117491, -0.0361584462, - -0.00220073434, 0.00946036354, -0.0101112155, - ], - nullable: true, - description: 'The embedding of the relevant chunk', - }) - embedding: number[]; -} - -export class QueryBody { - @ApiProperty({ - type: String, - example: 'When does Panora incorporated?', - nullable: false, - description: 'The query you want to received embeddings and chunks for', - }) - @IsString() - query: string; - - @ApiPropertyOptional({ - type: Number, - example: '3', - nullable: true, - description: 'The number of most appropriate documents for your query.', - }) - @IsNumber() - topK?: number; -} diff --git a/packages/api/src/@core/rag/rag.module.ts b/packages/api/src/@core/rag/rag.module.ts deleted file mode 100644 index 51f8ab763..000000000 --- a/packages/api/src/@core/rag/rag.module.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { EnvironmentService } from '@@core/@core-services/environment/environment.service'; -import { S3Service } from '@@core/s3/s3.service'; -import { Module } from '@nestjs/common'; -import { DocumentSplitterService } from './chunking/chunking.service'; -import { ProcessDocumentProcessor } from './document.processor'; -import { EmbeddingService } from './embedding/embedding.service'; -import { DocumentLoaderService } from './loader/loader.service'; -import { RagController } from './rag.controller'; -import { RagService } from './rag.service'; -import { ChromaDBService } from './vecdb/chromadb/chromadb.service'; -import { MilvusService } from './vecdb/milvus/milvus.service'; -import { PineconeService } from './vecdb/pinecone/pinecone.service'; -import { TurboPufferService } from './vecdb/turbopuffer/turbopuffer.service'; -import { VectorDatabaseService } from './vecdb/vecdb.service'; -import { WeaviateService } from './vecdb/weaviate/weaviate.service'; -import { QdrantDBService } from './vecdb/qdrant/qdrant.service'; -import { FileModule } from '@filestorage/file/file.module'; -import { VectorDbCredentialsService } from './vecdb/vecdb.credentials.service'; -import { ConnectionsStrategiesService } from '@@core/connections-strategies/connections-strategies.service'; -import { EmbeddingCredentialsService } from './embedding/embedding.credentials.service'; - -@Module({ - imports: [FileModule], - controllers: [RagController], - providers: [ - EnvironmentService, - VectorDatabaseService, - PineconeService, - WeaviateService, - TurboPufferService, - ChromaDBService, - QdrantDBService, - MilvusService, - RagService, - ProcessDocumentProcessor, - S3Service, - DocumentLoaderService, - DocumentSplitterService, - EmbeddingService, - VectorDatabaseService, - EmbeddingCredentialsService, - ConnectionsStrategiesService, - VectorDbCredentialsService, - ], - exports: [ - RagService, - VectorDatabaseService, - ProcessDocumentProcessor, - S3Service, - DocumentLoaderService, - DocumentSplitterService, - EmbeddingService, - PineconeService, - WeaviateService, - TurboPufferService, - ChromaDBService, - QdrantDBService, - MilvusService, - ConnectionsStrategiesService, - VectorDbCredentialsService, - ], -}) -export class RagModule {} diff --git a/packages/api/src/@core/rag/rag.service.ts b/packages/api/src/@core/rag/rag.service.ts deleted file mode 100644 index cb9251e85..000000000 --- a/packages/api/src/@core/rag/rag.service.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { BullQueueService } from '@@core/@core-services/queues/shared.service'; -import { Injectable } from '@nestjs/common'; -import { EmbeddingService } from './embedding/embedding.service'; -import { FileInfo } from './types'; -import { VectorDatabaseService } from './vecdb/vecdb.service'; -import { S3Service } from '@@core/s3/s3.service'; - -@Injectable() -export class RagService { - constructor( - private readonly queues: BullQueueService, - private embeddingService: EmbeddingService, - private vectorDatabaseService: VectorDatabaseService, - private s3Service: S3Service, - ) {} - - async queryEmbeddings( - query: string, - topK = 5, - linkedUserId: string, - projectId: string, - ) { - const queryEmbedding = await this.embeddingService.embedQuery( - query, - projectId, - ); - const results = await this.vectorDatabaseService.queryEmbeddings( - queryEmbedding, - topK, - linkedUserId, - projectId, - ); - return results.map((match: any) => ({ - chunk: match.metadata.text, - metadata: match.metadata, - score: match.score, - embedding: match.embedding, - })); - } - - async queueDocumentProcessing( - filesInfo: FileInfo[], - projectId: string, - linkedUserId: string, - ) { - // todo: check if RAG is enabled for the current projectId and for pricing concerns - // paywall before doing s3 + rag - await this.s3Service.uploadFilesFromUrls(filesInfo, linkedUserId); - await this.queues.getRagDocumentQueue().add('batchDocs', { - filesInfo, - projectId, - linkedUserId, - }); - return { message: `Documents queued for processing` }; - } -} diff --git a/packages/api/src/@core/rag/types/index.ts b/packages/api/src/@core/rag/types/index.ts deleted file mode 100644 index b54a4a832..000000000 --- a/packages/api/src/@core/rag/types/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -export interface FileInfo { - id: string; - url: string; - s3Key: string; - provider: string; - fileType: string; -} -export interface ProcessedChunk { - text: string; - metadata: Record; -} diff --git a/packages/api/src/@core/rag/vecdb/chromadb/chromadb.service.ts b/packages/api/src/@core/rag/vecdb/chromadb/chromadb.service.ts deleted file mode 100644 index acdb29dcb..000000000 --- a/packages/api/src/@core/rag/vecdb/chromadb/chromadb.service.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { EnvironmentService } from '@@core/@core-services/environment/environment.service'; -import { ProcessedChunk } from '@@core/rag/types'; -import { Injectable } from '@nestjs/common'; -import { ChromaClient, Collection } from 'chromadb'; - -@Injectable() -export class ChromaDBService { - private client: ChromaClient; - private collection: Collection; - - constructor(private envService: EnvironmentService) {} - - async onModuleInit() { - return; - } - - async initialize(credentials: string[]) { - this.client = new ChromaClient({ - path: credentials[0], - }); - this.collection = await this.client.getOrCreateCollection({ - name: credentials[1], - }); - } - - async storeEmbeddings( - fileId: string, - chunks: ProcessedChunk[], - embeddings: number[][], - linkedUserId: string, - ) { - await this.collection.add({ - ids: chunks.map((_, i) => `${fileId}_${i}`), - embeddings: embeddings, - metadatas: chunks.map((chunk) => ({ - text: chunk.text, - ...chunk.metadata, - user_id: `ns_${linkedUserId}`, - })), - }); - } - - async queryEmbeddings( - queryEmbedding: number[], - topK: number, - linkedUserId: string, - ) { - const result = await this.collection.query({ - queryEmbeddings: [queryEmbedding], - nResults: topK, - where: { user_id: `ns_${linkedUserId}` }, - }); - return result.metadatas[0]; - } -} diff --git a/packages/api/src/@core/rag/vecdb/milvus/milvus.service.ts b/packages/api/src/@core/rag/vecdb/milvus/milvus.service.ts deleted file mode 100644 index fd740a94b..000000000 --- a/packages/api/src/@core/rag/vecdb/milvus/milvus.service.ts +++ /dev/null @@ -1,116 +0,0 @@ -import { EnvironmentService } from '@@core/@core-services/environment/environment.service'; -import { ProcessedChunk } from '@@core/rag/types'; -import { Injectable } from '@nestjs/common'; -import { DataType, MilvusClient } from '@zilliz/milvus2-sdk-node'; - -@Injectable() -export class MilvusService { - private client: MilvusClient; - private collectionName: string; - - constructor(private envService: EnvironmentService) {} - - async onModuleInit() { - return; - } - - async initialize(credentials: string[]) { - this.client = new MilvusClient({ - address: credentials[0], - }); - this.collectionName = credentials[1]; - await this.client.connectPromise; - } - - async storeEmbeddings( - fileId: string, - chunks: ProcessedChunk[], - embeddings: number[][], - linkedUserId: string, - ) { - const tenant = `ns_${linkedUserId}`; - const hasCollection = await this.client.hasCollection({ - collection_name: this.collectionName, - }); - if (!hasCollection) { - await this.client.createCollection({ - collection_name: this.collectionName, - fields: [ - { - name: 'id', - description: 'ID field', - data_type: DataType.VarChar, - is_primary_key: true, - max_length: 100, - }, - { - name: 'tenant', - description: 'Tenant field', - data_type: DataType.VarChar, - max_length: 100, - }, - { - name: 'text', - description: 'Text field', - data_type: DataType.VarChar, - max_length: 65535, - }, - { - name: 'embedding', - description: 'Vector field', - data_type: DataType.FloatVector, - dim: embeddings[0].length, - }, - ], - enable_dynamic_field: true, - }); - - // Create index - await this.client.createIndex({ - collection_name: this.collectionName, - field_name: 'embedding', - index_type: 'HNSW', - params: { efConstruction: 10, M: 4 }, - metric_type: 'L2', - }); - } - - const data = chunks.map((chunk, i) => ({ - id: `${fileId}_${i}`, - tenant, - text: chunk.text, - embedding: embeddings[i], - })); - - await this.client.insert({ - collection_name: this.collectionName, - data, - }); - - await this.client.loadCollectionSync({ - collection_name: this.collectionName, - }); - } - - async queryEmbeddings( - queryEmbedding: number[], - topK: number, - linkedUserId: string, - ) { - const tenant = `ns_${linkedUserId}`; - const res = await this.client.search({ - collection_name: this.collectionName, - vector: queryEmbedding, - filter: `tenant == "${tenant}"`, - params: { nprobe: 10 }, - limit: topK, - output_fields: ['text'], - }); - - return res.results.map((hit) => ({ - id: hit.id, - text: hit.text, - score: hit.score, - })); - } -} diff --git a/packages/api/src/@core/rag/vecdb/pinecone/pinecone.service.ts b/packages/api/src/@core/rag/vecdb/pinecone/pinecone.service.ts deleted file mode 100644 index e618c3443..000000000 --- a/packages/api/src/@core/rag/vecdb/pinecone/pinecone.service.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { ProcessedChunk } from '@@core/rag/types'; -import { Injectable } from '@nestjs/common'; -import { Pinecone } from '@pinecone-database/pinecone'; - -@Injectable() -export class PineconeService { - private client: Pinecone; - private indexName: string; - - async initialize(credentials: string[]) { - this.client = new Pinecone({ - apiKey: credentials[0], - }); - this.indexName = credentials[1]; - } - - async storeEmbeddings( - fileId: string, - chunks: ProcessedChunk[], - embeddings: number[][], - projectId: string, - linkedUserId: string, - ) { - const index = this.client.Index(this.indexName); - const vectors = chunks.map((chunk, i) => ({ - id: `${fileId}_${i}`, - values: embeddings[i], - metadata: this.sanitizeMetadata({ - text: chunk.text, - ...chunk.metadata, - }), - })); - await index.namespace(`ns_${linkedUserId}`).upsert(vectors); - console.log(`Inserted embeddings on Pinecone for fileId ${fileId}`); - } - private sanitizeMetadata(metadata: Record): Record { - const sanitized: Record = {}; - for (const [key, value] of Object.entries(metadata)) { - if ( - typeof value === 'string' || - typeof value === 'number' || - typeof value === 'boolean' - ) { - sanitized[key] = value; - } else if ( - Array.isArray(value) && - value.every((item) => typeof item === 'string') - ) { - sanitized[key] = value; - } else if (typeof value === 'object' && value !== null) { - sanitized[key] = JSON.stringify(value); - } - // Ignore other types - } - return sanitized; - } - - async queryEmbeddings( - queryEmbedding: number[], - topK: number, - linkedUserId: string, - ) { - const index = this.client.Index(this.indexName); - const queryResponse = await index.namespace(`ns_${linkedUserId}`).query({ - vector: queryEmbedding, - topK, - includeMetadata: true, - includeValues: true, - }); - return (queryResponse.matches || []).map((match) => ({ - ...match, - embedding: match.values, - })); - } -} diff --git a/packages/api/src/@core/rag/vecdb/qdrant/qdrant.service.ts b/packages/api/src/@core/rag/vecdb/qdrant/qdrant.service.ts deleted file mode 100644 index 34653b4b0..000000000 --- a/packages/api/src/@core/rag/vecdb/qdrant/qdrant.service.ts +++ /dev/null @@ -1,121 +0,0 @@ -import { EnvironmentService } from '@@core/@core-services/environment/environment.service'; -import { ProcessedChunk } from '@@core/rag/types'; -import { Injectable, OnModuleInit } from '@nestjs/common'; -import { QdrantClient } from '@qdrant/js-client-rest'; - -@Injectable() -export class QdrantDBService implements OnModuleInit { - private client: QdrantClient; - private collectionName: string; - - constructor(private envService: EnvironmentService) {} - - async onModuleInit() { - return; - } - - async initialize(credentials: string[]) { - this.client = new QdrantClient({ - url: `https://${credentials[1]}.us-east-0-1.aws.cloud.qdrant.io`, - apiKey: credentials[0], - }); - this.collectionName = credentials[2]; - await this.ensureCollectionExists(); - } - - private async ensureCollectionExists() { - try { - await this.client.getCollection(this.collectionName); - } catch (error) { - if (error.status === 404) { - await this.client.createCollection(this.collectionName, { - vectors: { size: 1536, distance: 'Cosine' }, // Adjust size as needed - optimizers_config: { - indexing_threshold: 20000, - }, - replication_factor: 2, - }); - } else { - throw error; - } - } - } - - async storeEmbeddings( - fileId: string, - chunks: ProcessedChunk[], - embeddings: number[][], - linkedUserId: string, - ) { - const tenantId = `ns_${linkedUserId}`; - await this.client.upsert(this.collectionName, { - wait: true, - points: chunks.map((chunk, i) => ({ - id: `${fileId}_${i}`, - vector: embeddings[i], - payload: { - text: chunk.text, - ...chunk.metadata, - tenant_id: tenantId, - file_id: fileId, - }, - })), - }); - } - - async queryEmbeddings( - queryEmbedding: number[], - topK: number, - linkedUserId: string, - ) { - const tenantId = `ns_${linkedUserId}`; - const result = await this.client.search(this.collectionName, { - vector: queryEmbedding, - limit: topK, - filter: { - must: [ - { - key: 'tenant_id', - match: { value: tenantId }, - }, - ], - }, - }); - return result.map((item) => item.payload); - } - - /*async deleteEmbeddings(tenantId: string, fileId: string) { - await this.client.delete(this.collectionName, { - filter: { - must: [ - { - key: 'tenant_id', - match: { value: tenantId }, - }, - { - key: 'file_id', - match: { value: fileId }, - }, - ], - }, - }); - } - - async listTenants() { - const result = await this.client.scroll(this.collectionName, { - filter: { - must: [ - { - key: 'tenant_id', - match: { value: '' }, - }, - ], - }, - limit: 100, - }); - const tenants = new Set( - result.points.map((point) => point.payload.tenant_id), - ); - return Array.from(tenants); - }*/ -} diff --git a/packages/api/src/@core/rag/vecdb/turbopuffer/turbopuffer.service.ts b/packages/api/src/@core/rag/vecdb/turbopuffer/turbopuffer.service.ts deleted file mode 100644 index 34d3ba0bd..000000000 --- a/packages/api/src/@core/rag/vecdb/turbopuffer/turbopuffer.service.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { EnvironmentService } from '@@core/@core-services/environment/environment.service'; -import { ProcessedChunk } from '@@core/rag/types'; -import { Injectable } from '@nestjs/common'; -import { Namespace, Turbopuffer } from '@turbopuffer/turbopuffer'; - -@Injectable() -export class TurboPufferService { - private client: Turbopuffer; - private namespace: Namespace; - - constructor(private envService: EnvironmentService) { - //this.initialize(); - } - - async initialize() { - this.client = new Turbopuffer({ - apiKey: this.envService.getTurboPufferApiKey(), - }); - this.namespace = this.client.namespace('panora-namespace'); - } - - async storeEmbeddings( - fileId: string, - chunks: ProcessedChunk[], - embeddings: number[][], - ) { - const vectors = chunks.map((chunk, i) => ({ - id: `${fileId}_${i}`, - vector: embeddings[i], - attributes: { text: chunk.text, ...chunk.metadata }, - })); - await this.namespace.upsert({ - vectors, - distance_metric: 'cosine_distance', - }); - } - - async queryEmbeddings(queryEmbedding: number[], topK: number) { - const results = await this.namespace.query({ - vector: queryEmbedding, - top_k: topK, - distance_metric: 'cosine_distance', - include_attributes: ['text'], - include_vectors: false, - }); - return results; - } -} diff --git a/packages/api/src/@core/rag/vecdb/vecdb.credentials.service.ts b/packages/api/src/@core/rag/vecdb/vecdb.credentials.service.ts deleted file mode 100644 index 023243d4d..000000000 --- a/packages/api/src/@core/rag/vecdb/vecdb.credentials.service.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { EnvironmentService } from '@@core/@core-services/environment/environment.service'; -import { ConnectionsStrategiesService } from '@@core/connections-strategies/connections-strategies.service'; - -@Injectable() -export class VectorDbCredentialsService { - constructor( - private envService: EnvironmentService, - private connectionsStrategiesService: ConnectionsStrategiesService, - ) {} - - async getVectorDbCredentials( - projectId: string, - vectorDb: string, - ): Promise { - const type = `vectorDatabase.${vectorDb}`; - const isCustom = - await this.connectionsStrategiesService.isCustomCredentials( - projectId, - type, - ); - - if (isCustom) { - return this.getCustomCredentials(projectId, type, vectorDb); - } else { - return this.getManagedCredentials(vectorDb); - } - } - - private async getCustomCredentials( - projectId: string, - type: string, - vectorDb: string, - ) { - const attributes = this.getAttributesForVectorDb(vectorDb); - return this.connectionsStrategiesService.getConnectionStrategyData( - projectId, - type, - attributes, - ); - } - - getManagedCredentials(vectorDb: string): string[] { - switch (vectorDb) { - case 'pinecone': - return [ - this.envService.getPineconeCreds().apiKey, - this.envService.getPineconeCreds().indexName, - ]; - case 'chromadb': - return [ - this.envService.getChromaCreds().url, - this.envService.getChromaCreds().collectionName, - ]; - case 'weaviate': - const weaviateCreds = this.envService.getWeaviateCreds(); - return [ - weaviateCreds.apiKey, - weaviateCreds.url, - weaviateCreds.className, - ]; - case 'turbopuffer': - return [this.envService.getTurboPufferApiKey()]; - case 'qdrant': - const qdrantCreds = this.envService.getQdrantCreds(); - return [ - qdrantCreds.apiKey, - qdrantCreds.baseUrl, - qdrantCreds.collectionName, - ]; - default: - throw new Error(`Unsupported vector database: ${vectorDb}`); - } - } - - private getAttributesForVectorDb(vectorDb: string): string[] { - switch (vectorDb) { - case 'pinecone': - return ['apiKey', 'indexName']; - case 'turbopuffer': - return ['apiKey']; - case 'qdrant': - return ['apiKey', 'baseUrl', 'collectionName']; - case 'chromadb': - return ['url', 'collectionName']; - case 'weaviate': - return ['apiKey', 'url', 'className']; - default: - throw new Error(`Unsupported vector database: ${vectorDb}`); - } - } -} diff --git a/packages/api/src/@core/rag/vecdb/vecdb.service.ts b/packages/api/src/@core/rag/vecdb/vecdb.service.ts deleted file mode 100644 index 9a093962a..000000000 --- a/packages/api/src/@core/rag/vecdb/vecdb.service.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { Document } from '@langchain/core/documents'; -import { Injectable, OnModuleInit } from '@nestjs/common'; -import { ProcessedChunk } from '../types'; -import { ChromaDBService } from './chromadb/chromadb.service'; -import { MilvusService } from './milvus/milvus.service'; -import { PineconeService } from './pinecone/pinecone.service'; -import { QdrantDBService } from './qdrant/qdrant.service'; -import { TurboPufferService } from './turbopuffer/turbopuffer.service'; -import { WeaviateService } from './weaviate/weaviate.service'; -import { ConnectionsStrategiesService } from '@@core/connections-strategies/connections-strategies.service'; -import { VectorDbCredentialsService } from './vecdb.credentials.service'; - -export type VectorDbProvider = - | 'CHROMADB' - | 'PINECONE' - | 'QDRANT' - | 'TURBOPUFFER' - | 'MILVUS' - | 'WEAVIATE'; - -@Injectable() -export class VectorDatabaseService implements OnModuleInit { - private vectorDb: any; - - constructor( - private pineconeService: PineconeService, - private weaviateService: WeaviateService, - private turboPufferService: TurboPufferService, - private chromaDBService: ChromaDBService, - private qdrantService: QdrantDBService, - private milvusService: MilvusService, - private connectionsStrategiesService: ConnectionsStrategiesService, - private vectorDbCredentialsService: VectorDbCredentialsService, - ) {} - - onModuleInit() { - console.log(); - } - - async init(projectId: string) { - const activeStrategies = - await this.connectionsStrategiesService.getConnectionStrategiesForProject( - projectId, - ); - const activeVectorDbStrategy = activeStrategies.find( - (strategy) => - strategy.type.startsWith('vectorDatabase.') && strategy.status, - ); - - let dbType: string; - let credentials: string[]; - - if (activeVectorDbStrategy) { - dbType = activeVectorDbStrategy.type.split('.')[1].toLowerCase(); - credentials = - await this.vectorDbCredentialsService.getVectorDbCredentials( - projectId, - dbType, - ); - } else { - // Fall back to managed credentials - dbType = 'pinecone'; - credentials = - this.vectorDbCredentialsService.getManagedCredentials(dbType); - } - switch (dbType) { - case 'pinecone': - this.vectorDb = this.pineconeService; - break; - case 'weaviate': - this.vectorDb = this.weaviateService; - break; - case 'turbopuffer': - this.vectorDb = this.turboPufferService; - break; - case 'chromadb': - this.vectorDb = this.chromaDBService; - break; - case 'qdrant': - this.vectorDb = this.qdrantService; - break; - case 'milvus': - this.vectorDb = this.milvusService; - break; - default: - throw new Error(`Unsupported vector database type: ${dbType}`); - } - - await this.vectorDb.initialize(credentials); - } - - async storeEmbeddings( - fileId: string, - chunks: Document>[], - embeddings: number[][], - projectId: string, - linkedUserId: string, - ) { - await this.init(projectId); - const processedChunks: ProcessedChunk[] = chunks.map((chunk) => ({ - text: chunk.pageContent, - metadata: chunk.metadata, - })); - return this.vectorDb.storeEmbeddings( - fileId, - processedChunks, - embeddings, - projectId, - linkedUserId, - ); - } - - async queryEmbeddings( - queryEmbedding: number[], - topK: number, - linkedUserId: string, - projectId: string, - ) { - await this.init(projectId); - return this.vectorDb.queryEmbeddings(queryEmbedding, topK, linkedUserId); - } -} diff --git a/packages/api/src/@core/rag/vecdb/weaviate/weaviate.service.ts b/packages/api/src/@core/rag/vecdb/weaviate/weaviate.service.ts deleted file mode 100644 index 3275e84cb..000000000 --- a/packages/api/src/@core/rag/vecdb/weaviate/weaviate.service.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { EnvironmentService } from '@@core/@core-services/environment/environment.service'; -import { ProcessedChunk } from '@@core/rag/types'; -import { Injectable, OnModuleInit } from '@nestjs/common'; -import weaviate, { WeaviateClient, ApiKey } from 'weaviate-client'; - -@Injectable() -export class WeaviateService implements OnModuleInit { - private client: WeaviateClient; - private className: string; - - constructor(private envService: EnvironmentService) {} - - async onModuleInit() { - return; - } - - async initialize(credentials: string[]) { - this.client = await weaviate.connectToWeaviateCloud(credentials[1], { - authCredentials: new ApiKey(credentials[0]), - }); - this.className = credentials[2]; - await this.ensureClassExists(); - } - - private async ensureClassExists() { - try { - await this.client.collections.create({ - name: this.className, - multiTenancy: weaviate.configure.multiTenancy({ - enabled: true, - autoTenantCreation: true, - }), - }); - } catch (error) { - // Class might already exist, which is fine - console.log( - `Class ${this.className} might already exist:`, - error.message, - ); - } - } - - async storeEmbeddings( - fileId: string, - chunks: ProcessedChunk[], - embeddings: number[][], - linkedUserId: string, - ) { - const batchSize = 100; - const tenant = `ns_${linkedUserId}`; - const collection = this.client.collections.get(this.className); - const multiTenant = collection.withTenant(tenant); - - for (let i = 0; i < chunks.length; i += batchSize) { - const batch = chunks.slice(i, i + batchSize).map((chunk, index) => ({ - properties: { - text: chunk.text, - metadata: chunk.metadata, - }, - id: `${fileId}_${i + index}`, - vector: embeddings[i + index], - })); - - await multiTenant.data.insertMany(batch); - } - } - - async queryEmbeddings( - queryEmbedding: number[], - topK: number, - linkedUserId: string, - ) { - const tenant = `ns_${linkedUserId}`; - const multiCollection = this.client.collections.get(this.className); - - const multiTenantObj = multiCollection.withTenant(tenant); - const result = await multiTenantObj.query.nearVector(queryEmbedding, { - limit: topK, - returnMetadata: ['distance'], - }); - - return result; - } - - /*async deleteEmbeddings(fileId: string, tenant: string) { - await this.client.batch - .objectsBatcher() - .withTenant(tenant) - .withClassName(this.className) - .withWhere({ - operator: 'Like', - path: ['id'], - valueString: `${fileId}*`, - }) - .withDelete() - .do(); - }*/ -} diff --git a/packages/api/src/@core/s3/constants.ts b/packages/api/src/@core/s3/constants.ts deleted file mode 100644 index d45d01dd1..000000000 --- a/packages/api/src/@core/s3/constants.ts +++ /dev/null @@ -1 +0,0 @@ -export const BUCKET_NAME = 'panora-documents-bucket'; diff --git a/packages/api/src/@core/s3/s3.service.ts b/packages/api/src/@core/s3/s3.service.ts deleted file mode 100644 index 8ef336811..000000000 --- a/packages/api/src/@core/s3/s3.service.ts +++ /dev/null @@ -1,336 +0,0 @@ -import { EnvironmentService } from '@@core/@core-services/environment/environment.service'; -import { FileInfo } from '@@core/rag/types'; -import { - CreateBucketCommand, - GetObjectCommand, - HeadBucketCommand, - S3Client, -} from '@aws-sdk/client-s3'; -import { ServiceRegistry } from '@filestorage/file/services/registry.service'; -import { IFileService } from '@filestorage/file/types'; -import { Injectable } from '@nestjs/common'; -import { Readable } from 'stream'; -import { BUCKET_NAME } from './constants'; -import { PrismaService } from '@@core/@core-services/prisma/prisma.service'; -import { LoggerService } from '@@core/@core-services/logger/logger.service'; -import * as mammoth from 'mammoth'; -import * as marked from 'marked'; -import * as XLSX from 'xlsx'; -import { Upload } from '@aws-sdk/lib-storage'; - -@Injectable() -export class S3Service { - private s3: S3Client; - - constructor( - private prisma: PrismaService, - private logger: LoggerService, - private envService: EnvironmentService, - private fileServiceRegistry: ServiceRegistry, - ) { - // const creds = this.envService.getAwsCredentials(); - const creds = this.envService.getMinioCredentials(); - this.s3 = new S3Client({ - endpoint: 'http://minio:9000', - region: 'us-east-1', - forcePathStyle: true, - //region: creds.region, - credentials: { - accessKeyId: creds.accessKeyId || 'myaccesskey13', - secretAccessKey: creds.secretAccessKey || 'mysecretkey12', - }, - }); - } - - async ensureBucketExists(s3Client: S3Client, bucketName: string) { - try { - await s3Client.send(new HeadBucketCommand({ Bucket: bucketName })); - } catch (error) { - if (error.name === 'NotFound') { - try { - await s3Client.send(new CreateBucketCommand({ Bucket: bucketName })); - console.log(`Bucket ${bucketName} created successfully`); - } catch (createError) { - console.error(`Error creating bucket ${bucketName}:`, createError); - throw createError; - } - } else { - // Some other error occurred - console.error(`Error checking bucket ${bucketName}:`, error); - throw error; - } - } - } - - async uploadFilesFromUrls( - urlsWithKeys: FileInfo[], - linkedUserId: string, - ): Promise { - await this.ensureBucketExists(this.s3, BUCKET_NAME); - const batchSize = 10; - for (let i = 0; i < urlsWithKeys.length; i += batchSize) { - const batch = urlsWithKeys.slice(i, i + batchSize); - await Promise.all( - batch.map(async ({ id, url, s3Key, provider }) => { - try { - const service: IFileService = this.fileServiceRegistry.getService( - provider.toLowerCase().trim(), - ); - if (!service) return; - await this.streamFileToS3( - service, - id, - linkedUserId, - this.s3, - s3Key, - provider.toLowerCase().trim(), - ); - console.log(`Successfully uploaded ${s3Key} from ${provider}`); - } catch (error) { - console.error( - `Failed to upload file from ${url} to ${s3Key} (${provider}):`, - error, - ); - throw error; - } - }), - ); - } - } - - async streamFileToS3( - service: IFileService, - file_id: string, - linkedUserId: string, - s3Client: S3Client, - s3Key: string, - providerName: string, - ) { - const connection = await this.prisma.connections.findFirst({ - where: { - id_linked_user: linkedUserId, - provider_slug: providerName, - vertical: 'filestorage', - }, - }); - - const file = await this.prisma.fs_files.findUnique({ - where: { - id_fs_file: file_id, - }, - }); - - const fileUniqueIdentifier = file.remote_id; - - let processedContent: string | Buffer; - const mimeType = file.mime_type; - let contentType = 'text/plain'; // Default content type - - switch (mimeType) { - case 'application/pdf': - contentType = 'application/pdf'; - processedContent = await service.downloadFile( - fileUniqueIdentifier, - connection, - ); - break; - case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': - case 'text/csv': - contentType = 'text/csv'; - processedContent = await service.downloadFile( - fileUniqueIdentifier, - connection, - ); - break; - case 'text/tab-separated-values': - processedContent = await this.processSpreadsheet( - service, - connection, - fileUniqueIdentifier, - mimeType, - ); - break; - case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': - case 'text/plain': - case 'text/markdown': - case 'application/rtf': - case 'application/vnd.openxmlformats-officedocument.presentationml.presentation': - case 'text/html': - case 'message/rfc822': - case 'application/vnd.ms-outlook': - processedContent = await this.processTextContent( - service, - connection, - fileUniqueIdentifier, - mimeType, - ); - break; - case 'application/json': - processedContent = await this.processJsonContent( - service, - connection, - fileUniqueIdentifier, - ); - break; - default: - throw new Error(`Unsupported file type: ${mimeType}`); - } - - const upload = new Upload({ - client: s3Client, - params: { - Bucket: BUCKET_NAME, - Key: s3Key, - Body: Readable.from(processedContent), - ContentType: contentType, - ContentDisposition: `attachment; filename="${file.name}"`, - }, - }); - - try { - await upload.done(); - console.log(`Successfully uploaded ${s3Key} to ${BUCKET_NAME}`); - } catch (error) { - console.error('Error uploading to S3:', error); - throw error; - } - } - - private async processSpreadsheet( - service: IFileService, - connection: any, - fileId: string, - mimeType: string, - ): Promise { - const fileContent = await service.downloadFile(fileId, connection); - let result = ''; - - if (mimeType === 'text/csv') { - const content = fileContent.toString('utf-8'); - const lines = content.split('\n').filter((line) => line.trim() !== ''); - - if (lines.length === 0) { - return 'Empty CSV file'; - } - - // Detect separator - const possibleSeparators = [',', ';', '\t', '|']; - const firstLine = lines[0]; - const separator = - possibleSeparators.find((sep) => firstLine.includes(sep)) || ','; - - // Extract headers and determine the number of columns - const headerMatch = firstLine.match(/^(.*?):(.*)/); - const headers = headerMatch - ? headerMatch[2].split(separator).map((h) => h.trim()) - : firstLine.split(separator).map((h) => h.trim()); - const columnCount = headers.length; - - for (let i = 0; i < lines.length; i++) { - const line = lines[i]; - const dataMatch = line.match(/^(.*?):(.*)/); - const values = dataMatch - ? dataMatch[2].split(separator).map((v) => v.trim()) - : line.split(separator).map((v) => v.trim()); - - if (values.length === columnCount) { - for (let j = 0; j < columnCount; j++) { - result += `${headers[j]}: ${values[j]}\n`; - } - result += '\n'; - } - } - } else if ( - mimeType === - 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' - ) { - const workbook = XLSX.read(fileContent, { type: 'buffer' }); - workbook.SheetNames.forEach((sheetName) => { - const sheet = workbook.Sheets[sheetName]; - const data = XLSX.utils.sheet_to_json(sheet, { header: 1 }) as any[][]; - const headers = data[0] as string[]; - for (let i = 1; i < data.length; i++) { - const row = data[i] as any[]; - for (let j = 0; j < row.length; j++) { - result += `${headers[j]}: ${row[j]}\n`; - } - result += '\n'; - } - }); - } else { - throw new Error(`Unsupported spreadsheet type: ${mimeType}`); - } - - return result; - } - private async processTextContent( - service: IFileService, - connection: any, - fileId: string, - mimeType: string, - ): Promise { - const fileContent = await service.downloadFile(fileId, connection); - if ( - mimeType === - 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' - ) { - const result = await mammoth.extractRawText({ buffer: fileContent }); - return result.value; - } else if (mimeType === 'text/markdown') { - return marked.parse(fileContent.toString()); - } else { - // For other text-based formats, we'll assume they're already in plain text - return fileContent.toString(); - } - } - private async processJsonContent( - service: IFileService, - drive: any, - fileId: string, - ): Promise { - const fileContent = await service.downloadFile(drive, fileId); - const jsonContent = JSON.parse(fileContent.toString()); - - function flattenObject(obj: any, prefix = ''): { [key: string]: any } { - return Object.keys(obj).reduce( - (acc: { [key: string]: any }, k: string) => { - const pre = prefix.length ? prefix + '.' : ''; - if ( - typeof obj[k] === 'object' && - obj[k] !== null && - !Array.isArray(obj[k]) - ) { - Object.assign(acc, flattenObject(obj[k], pre + k)); - } else if (Array.isArray(obj[k])) { - obj[k].forEach((item: any, index: number) => { - if (typeof item === 'object' && item !== null) { - Object.assign(acc, flattenObject(item, `${pre}${k}[${index}]`)); - } else { - acc[`${pre}${k}[${index}]`] = item; - } - }); - } else { - acc[pre + k] = obj[k]; - } - return acc; - }, - {}, - ); - } - - const flattened = flattenObject(jsonContent); - return Object.entries(flattened) - .map(([key, value]) => `${key}: ${value}`) - .join('\n'); - } - - async getReadStream(s3Key: string): Promise { - const getObjectParams = { - Bucket: BUCKET_NAME, - Key: s3Key, - }; - const command = new GetObjectCommand(getObjectParams); - const { Body } = await this.s3.send(command); - return Body as Readable; - } -} diff --git a/packages/api/swagger/swagger-spec.yaml b/packages/api/swagger/swagger-spec.yaml index b8b36b094..23f5068ac 100644 --- a/packages/api/swagger/swagger-spec.yaml +++ b/packages/api/swagger/swagger-spec.yaml @@ -25,158 +25,6 @@ paths: schema: type: number example: 200 - /rag/query: - post: - operationId: query - summary: Query using RAG Search - description: Query across your connected data sources using RAG Search - parameters: - - name: x-connection-token - required: true - in: header - description: The connection token - schema: - type: string - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/QueryBody' - responses: - '201': - description: '' - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/RagQueryOutput' - x-speakeasy-group: rag - /filestorage/files: - get: - operationId: listFilestorageFile - summary: List Files - parameters: - - name: x-connection-token - required: true - in: header - description: The connection token - schema: - type: string - - name: remote_data - required: false - in: query - example: true - description: Set to true to include data from the original software. - schema: - type: boolean - - name: limit - required: false - in: query - example: 10 - description: Set to get the number of records. - schema: - type: number - - name: cursor - required: false - in: query - example: 1b8b05bb-5273-4012-b520-8657b0b90874 - description: Set to get the number of records after this cursor. - schema: - type: string - responses: - '200': - description: '' - content: - application/json: - schema: - allOf: - - $ref: '#/components/schemas/PaginatedDto' - - properties: - data: - type: array - items: - $ref: '#/components/schemas/UnifiedFilestorageFileOutput' - tags: &ref_0 - - filestorage/files - x-speakeasy-group: filestorage.files - x-speakeasy-pagination: - type: cursor - inputs: - - name: cursor - in: parameters - type: cursor - outputs: - nextCursor: $.next_cursor - post: - operationId: createFilestorageFile - summary: Create Files - description: Create Files in any supported Filestorage software - parameters: - - name: x-connection-token - required: true - in: header - description: The connection token - schema: - type: string - - name: remote_data - required: false - in: query - example: false - description: Set to true to include data from the original Accounting software. - schema: - type: boolean - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/UnifiedFilestorageFileInput' - responses: - '201': - description: '' - content: - application/json: - schema: - $ref: '#/components/schemas/UnifiedFilestorageFileOutput' - tags: *ref_0 - x-speakeasy-group: filestorage.files - /filestorage/files/{id}: - get: - operationId: retrieveFilestorageFile - summary: Retrieve Files - description: Retrieve Files from any connected Filestorage software - parameters: - - name: x-connection-token - required: true - in: header - description: The connection token - schema: - type: string - - name: id - required: true - in: path - description: id of the file you want to retrieve. - example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f - schema: - type: string - - name: remote_data - required: false - in: query - description: Set to true to include data from the original File Storage software. - example: false - schema: - type: boolean - responses: - '200': - description: '' - content: - application/json: - schema: - $ref: '#/components/schemas/UnifiedFilestorageFileOutput' - tags: *ref_0 - x-speakeasy-group: filestorage.files /auth/login: post: operationId: signIn @@ -224,7 +72,7 @@ paths: type: array items: $ref: '#/components/schemas/WebhookResponse' - tags: &ref_1 + tags: &ref_0 - webhooks x-speakeasy-group: webhooks post: @@ -244,7 +92,7 @@ paths: application/json: schema: $ref: '#/components/schemas/WebhookResponse' - tags: *ref_1 + tags: *ref_0 x-speakeasy-group: webhooks /webhooks/{id}: delete: @@ -259,13 +107,15 @@ paths: schema: type: string responses: + '200': + description: '' '201': description: '' content: application/json: schema: $ref: '#/components/schemas/WebhookResponse' - tags: *ref_1 + tags: *ref_0 x-speakeasy-group: webhooks put: operationId: updateStatus @@ -279,13 +129,15 @@ paths: schema: type: string responses: + '200': + description: '' '201': description: '' content: application/json: schema: $ref: '#/components/schemas/WebhookResponse' - tags: *ref_1 + tags: *ref_0 x-speakeasy-group: webhooks /webhooks/verifyEvent: post: @@ -307,7 +159,7 @@ paths: type: object additionalProperties: true description: Dynamic event payload - tags: *ref_1 + tags: *ref_0 x-speakeasy-group: webhooks /ticketing/tickets: get: @@ -333,6 +185,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -354,7 +207,7 @@ paths: type: array items: $ref: '#/components/schemas/UnifiedTicketingTicketOutput' - tags: &ref_2 + tags: &ref_1 - ticketing/tickets x-speakeasy-group: ticketing.tickets x-speakeasy-pagination: @@ -396,7 +249,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedTicketingTicketOutput' - tags: *ref_2 + tags: *ref_1 x-speakeasy-group: ticketing.tickets /ticketing/tickets/{id}: get: @@ -431,7 +284,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedTicketingTicketOutput' - tags: *ref_2 + tags: *ref_1 x-speakeasy-group: ticketing.tickets /ticketing/users: get: @@ -457,6 +310,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -478,7 +332,7 @@ paths: type: array items: $ref: '#/components/schemas/UnifiedTicketingUserOutput' - tags: &ref_3 + tags: &ref_2 - ticketing/users x-speakeasy-group: ticketing.users x-speakeasy-pagination: @@ -522,7 +376,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedTicketingUserOutput' - tags: *ref_3 + tags: *ref_2 x-speakeasy-group: ticketing.users /ticketing/accounts: get: @@ -548,6 +402,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -569,7 +424,7 @@ paths: type: array items: $ref: '#/components/schemas/UnifiedTicketingAccountOutput' - tags: &ref_4 + tags: &ref_3 - ticketing/accounts x-speakeasy-group: ticketing.accounts x-speakeasy-pagination: @@ -611,7 +466,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedTicketingAccountOutput' - tags: *ref_4 + tags: *ref_3 x-speakeasy-group: ticketing.accounts /ticketing/contacts: get: @@ -637,6 +492,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -658,7 +514,7 @@ paths: type: array items: $ref: '#/components/schemas/UnifiedTicketingContactOutput' - tags: &ref_5 + tags: &ref_4 - ticketing/contacts x-speakeasy-group: ticketing.contacts x-speakeasy-pagination: @@ -706,7 +562,7 @@ paths: type: array items: $ref: '#/components/schemas/UnifiedTicketingContactOutput' - tags: *ref_5 + tags: *ref_4 x-speakeasy-group: ticketing.contacts /sync/status/{vertical}: get: @@ -729,7 +585,7 @@ paths: responses: '200': description: '' - tags: &ref_6 + tags: &ref_5 - sync x-speakeasy-group: sync /sync/resync: @@ -744,7 +600,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ResyncStatusDto' - tags: *ref_6 + tags: *ref_5 x-speakeasy-group: sync /sync/pull_frequencies: post: @@ -760,7 +616,13 @@ paths: responses: '200': description: Pull frequency updated successfully - tags: *ref_6 + '201': + description: '' + content: + application/json: + schema: + type: object + tags: *ref_5 x-speakeasy-group: sync get: operationId: getPullFrequency @@ -773,7 +635,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UpdatePullFrequencyDto' - tags: *ref_6 + tags: *ref_5 x-speakeasy-group: sync /crm/companies: get: @@ -799,6 +661,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -820,7 +683,7 @@ paths: type: array items: $ref: '#/components/schemas/UnifiedCrmCompanyOutput' - tags: &ref_7 + tags: &ref_6 - crm/companies x-speakeasy-group: crm.companies x-speakeasy-pagination: @@ -862,7 +725,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedCrmCompanyOutput' - tags: *ref_7 + tags: *ref_6 x-speakeasy-group: crm.companies /crm/companies/{id}: get: @@ -897,7 +760,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedCrmCompanyOutput' - tags: *ref_7 + tags: *ref_6 x-speakeasy-group: crm.companies /crm/contacts: get: @@ -923,6 +786,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -944,7 +808,7 @@ paths: type: array items: $ref: '#/components/schemas/UnifiedCrmContactOutput' - tags: &ref_8 + tags: &ref_7 - crm/contacts x-speakeasy-group: crm.contacts x-speakeasy-pagination: @@ -986,7 +850,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedCrmContactOutput' - tags: *ref_8 + tags: *ref_7 x-speakeasy-group: crm.contacts /crm/contacts/{id}: get: @@ -1021,7 +885,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedCrmContactOutput' - tags: *ref_8 + tags: *ref_7 x-speakeasy-group: crm.contacts /crm/deals: get: @@ -1047,6 +911,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -1068,7 +933,7 @@ paths: type: array items: $ref: '#/components/schemas/UnifiedCrmDealOutput' - tags: &ref_9 + tags: &ref_8 - crm/deals x-speakeasy-group: crm.deals x-speakeasy-pagination: @@ -1109,7 +974,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedCrmDealOutput' - tags: *ref_9 + tags: *ref_8 x-speakeasy-group: crm.deals /crm/deals/{id}: get: @@ -1144,7 +1009,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedCrmDealOutput' - tags: *ref_9 + tags: *ref_8 x-speakeasy-group: crm.deals /crm/engagements: get: @@ -1170,6 +1035,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -1191,7 +1057,7 @@ paths: type: array items: $ref: '#/components/schemas/UnifiedCrmEngagementOutput' - tags: &ref_10 + tags: &ref_9 - crm/engagements x-speakeasy-group: crm.engagements x-speakeasy-pagination: @@ -1233,7 +1099,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedCrmEngagementOutput' - tags: *ref_10 + tags: *ref_9 x-speakeasy-group: crm.engagements /crm/engagements/{id}: get: @@ -1268,7 +1134,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedCrmEngagementOutput' - tags: *ref_10 + tags: *ref_9 x-speakeasy-group: crm.engagements /crm/notes: get: @@ -1294,6 +1160,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -1315,7 +1182,7 @@ paths: type: array items: $ref: '#/components/schemas/UnifiedCrmNoteOutput' - tags: &ref_11 + tags: &ref_10 - crm/notes x-speakeasy-group: crm.notes x-speakeasy-pagination: @@ -1357,7 +1224,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedCrmNoteOutput' - tags: *ref_11 + tags: *ref_10 x-speakeasy-group: crm.notes /crm/notes/{id}: get: @@ -1392,7 +1259,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedCrmNoteOutput' - tags: *ref_11 + tags: *ref_10 x-speakeasy-group: crm.notes /crm/stages: get: @@ -1418,6 +1285,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -1439,7 +1307,7 @@ paths: type: array items: $ref: '#/components/schemas/UnifiedCrmStageOutput' - tags: &ref_12 + tags: &ref_11 - crm/stages x-speakeasy-group: crm.stages x-speakeasy-pagination: @@ -1483,7 +1351,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedCrmStageOutput' - tags: *ref_12 + tags: *ref_11 x-speakeasy-group: crm.stages /crm/tasks: get: @@ -1509,6 +1377,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -1530,7 +1399,7 @@ paths: type: array items: $ref: '#/components/schemas/UnifiedCrmTaskOutput' - tags: &ref_13 + tags: &ref_12 - crm/tasks x-speakeasy-group: crm.tasks x-speakeasy-pagination: @@ -1571,7 +1440,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedCrmTaskOutput' - tags: *ref_13 + tags: *ref_12 x-speakeasy-group: crm.tasks /crm/tasks/{id}: get: @@ -1606,7 +1475,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedCrmTaskOutput' - tags: *ref_13 + tags: *ref_12 x-speakeasy-group: crm.tasks /crm/users: get: @@ -1632,6 +1501,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -1653,7 +1523,7 @@ paths: type: array items: $ref: '#/components/schemas/UnifiedCrmUserOutput' - tags: &ref_14 + tags: &ref_13 - crm/users x-speakeasy-group: crm.users x-speakeasy-pagination: @@ -1697,7 +1567,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedCrmUserOutput' - tags: *ref_14 + tags: *ref_13 x-speakeasy-group: crm.users /ticketing/collections: get: @@ -1723,6 +1593,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -1745,7 +1616,7 @@ paths: items: $ref: >- #/components/schemas/UnifiedTicketingCollectionOutput - tags: &ref_15 + tags: &ref_14 - ticketing/collections x-speakeasy-group: ticketing.collections x-speakeasy-pagination: @@ -1789,7 +1660,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedTicketingCollectionOutput' - tags: *ref_15 + tags: *ref_14 x-speakeasy-group: ticketing.collections /ticketing/comments: get: @@ -1815,6 +1686,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -1836,7 +1708,7 @@ paths: type: array items: $ref: '#/components/schemas/UnifiedTicketingCommentOutput' - tags: &ref_16 + tags: &ref_15 - ticketing/comments x-speakeasy-group: ticketing.comments x-speakeasy-pagination: @@ -1877,7 +1749,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedTicketingCommentOutput' - tags: *ref_16 + tags: *ref_15 x-speakeasy-group: ticketing.comments /ticketing/comments/{id}: get: @@ -1916,7 +1788,7 @@ paths: type: array items: $ref: '#/components/schemas/UnifiedTicketingCommentOutput' - tags: *ref_16 + tags: *ref_15 x-speakeasy-group: ticketing.comments /ticketing/tags: get: @@ -1942,6 +1814,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -1963,7 +1836,7 @@ paths: type: array items: $ref: '#/components/schemas/UnifiedTicketingTagOutput' - tags: &ref_17 + tags: &ref_16 - ticketing/tags x-speakeasy-group: ticketing.tags x-speakeasy-pagination: @@ -2007,7 +1880,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedTicketingTagOutput' - tags: *ref_17 + tags: *ref_16 x-speakeasy-group: ticketing.tags /ticketing/teams: get: @@ -2033,6 +1906,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -2054,7 +1928,7 @@ paths: type: array items: $ref: '#/components/schemas/UnifiedTicketingTeamOutput' - tags: &ref_18 + tags: &ref_17 - ticketing/teams x-speakeasy-group: ticketing.teams x-speakeasy-pagination: @@ -2098,7 +1972,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedTicketingTeamOutput' - tags: *ref_18 + tags: *ref_17 x-speakeasy-group: ticketing.teams /linked_users/fromRemoteId: get: @@ -2118,7 +1992,7 @@ paths: application/json: schema: $ref: '#/components/schemas/LinkedUserResponse' - tags: &ref_19 + tags: &ref_18 - linkedUsers x-speakeasy-group: linkedUsers /linked_users: @@ -2139,7 +2013,7 @@ paths: application/json: schema: $ref: '#/components/schemas/LinkedUserResponse' - tags: *ref_19 + tags: *ref_18 x-speakeasy-group: linkedUsers get: operationId: listLinkedUsers @@ -2154,7 +2028,7 @@ paths: type: array items: $ref: '#/components/schemas/LinkedUserResponse' - tags: *ref_19 + tags: *ref_18 x-speakeasy-group: linkedUsers /linked_users/batch: post: @@ -2176,7 +2050,7 @@ paths: type: array items: $ref: '#/components/schemas/LinkedUserResponse' - tags: *ref_19 + tags: *ref_18 x-speakeasy-group: linkedUsers /linked_users/{id}: get: @@ -2196,7 +2070,7 @@ paths: application/json: schema: $ref: '#/components/schemas/LinkedUserResponse' - tags: *ref_19 + tags: *ref_18 x-speakeasy-group: linkedUsers /projects: get: @@ -2212,7 +2086,7 @@ paths: type: array items: $ref: '#/components/schemas/ProjectResponse' - tags: &ref_20 + tags: &ref_19 - projects post: operationId: createProject @@ -2231,7 +2105,7 @@ paths: application/json: schema: $ref: '#/components/schemas/ProjectResponse' - tags: *ref_20 + tags: *ref_19 /field_mappings/values: get: operationId: getFieldMappingValues @@ -2240,7 +2114,7 @@ paths: responses: '200': description: '' - tags: &ref_21 + tags: &ref_20 - fieldMappings x-speakeasy-group: fieldMappings /field_mappings/entities: @@ -2251,7 +2125,7 @@ paths: responses: '200': description: '' - tags: *ref_21 + tags: *ref_20 x-speakeasy-group: fieldMappings /field_mappings/attributes: get: @@ -2261,7 +2135,7 @@ paths: responses: '200': description: '' - tags: *ref_21 + tags: *ref_20 x-speakeasy-group: fieldMappings /field_mappings/define: post: @@ -2281,7 +2155,7 @@ paths: application/json: schema: $ref: '#/components/schemas/CustomFieldResponse' - tags: *ref_21 + tags: *ref_20 x-speakeasy-group: fieldMappings /field_mappings: post: @@ -2301,7 +2175,7 @@ paths: application/json: schema: $ref: '#/components/schemas/CustomFieldResponse' - tags: *ref_21 + tags: *ref_20 x-speakeasy-group: fieldMappings /field_mappings/map: post: @@ -2321,7 +2195,7 @@ paths: application/json: schema: $ref: '#/components/schemas/CustomFieldResponse' - tags: *ref_21 + tags: *ref_20 x-speakeasy-group: fieldMappings /events: get: @@ -2332,11 +2206,15 @@ paths: required: false in: query schema: + minimum: 1 + default: 1 type: number - name: limit required: false in: query schema: + minimum: 1 + default: 10 type: number responses: '200': @@ -2372,7 +2250,13 @@ paths: application/json: schema: type: object - tags: &ref_22 + '201': + description: '' + content: + application/json: + schema: + type: object + tags: &ref_21 - passthrough x-speakeasy-group: passthrough /passthrough/{retryId}: @@ -2391,7 +2275,7 @@ paths: responses: '200': description: '' - tags: *ref_22 + tags: *ref_21 x-speakeasy-group: passthrough.{retryid} /marketingautomation/actions: get: @@ -2417,6 +2301,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -2439,7 +2324,7 @@ paths: items: $ref: >- #/components/schemas/UnifiedMarketingautomationActionOutput - tags: &ref_23 + tags: &ref_22 - marketingautomation/actions x-speakeasy-group: marketingautomation.actions x-speakeasy-pagination: @@ -2483,7 +2368,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedMarketingautomationActionOutput' - tags: *ref_23 + tags: *ref_22 x-speakeasy-group: marketingautomation.actions /marketingautomation/actions/{id}: get: @@ -2520,7 +2405,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedMarketingautomationActionOutput' - tags: *ref_23 + tags: *ref_22 x-speakeasy-group: marketingautomation.actions /marketingautomation/automations: get: @@ -2546,6 +2431,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -2568,7 +2454,7 @@ paths: items: $ref: >- #/components/schemas/UnifiedMarketingautomationAutomationOutput - tags: &ref_24 + tags: &ref_23 - marketingautomation/automations x-speakeasy-group: marketingautomation.automations x-speakeasy-pagination: @@ -2613,7 +2499,7 @@ paths: schema: $ref: >- #/components/schemas/UnifiedMarketingautomationAutomationOutput - tags: *ref_24 + tags: *ref_23 x-speakeasy-group: marketingautomation.automations /marketingautomation/automations/{id}: get: @@ -2651,7 +2537,7 @@ paths: schema: $ref: >- #/components/schemas/UnifiedMarketingautomationAutomationOutput - tags: *ref_24 + tags: *ref_23 x-speakeasy-group: marketingautomation.automations /marketingautomation/campaigns: get: @@ -2677,6 +2563,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -2699,7 +2586,7 @@ paths: items: $ref: >- #/components/schemas/UnifiedMarketingautomationCampaignOutput - tags: &ref_25 + tags: &ref_24 - marketingautomation/campaigns x-speakeasy-group: marketingautomation.campaigns x-speakeasy-pagination: @@ -2743,7 +2630,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedMarketingautomationCampaignOutput' - tags: *ref_25 + tags: *ref_24 x-speakeasy-group: marketingautomation.campaigns /marketingautomation/campaigns/{id}: get: @@ -2780,7 +2667,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedMarketingautomationCampaignOutput' - tags: *ref_25 + tags: *ref_24 x-speakeasy-group: marketingautomation.campaigns /marketingautomation/contacts: get: @@ -2806,6 +2693,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -2828,7 +2716,7 @@ paths: items: $ref: >- #/components/schemas/UnifiedMarketingautomationContactOutput - tags: &ref_26 + tags: &ref_25 - marketingautomation/contacts x-speakeasy-group: marketingautomation.contacts x-speakeasy-pagination: @@ -2872,7 +2760,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedMarketingautomationContactOutput' - tags: *ref_26 + tags: *ref_25 x-speakeasy-group: marketingautomation.contacts /marketingautomation/contacts/{id}: get: @@ -2909,7 +2797,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedMarketingautomationContactOutput' - tags: *ref_26 + tags: *ref_25 x-speakeasy-group: marketingautomation.contacts /marketingautomation/emails: get: @@ -2935,6 +2823,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -2957,7 +2846,7 @@ paths: items: $ref: >- #/components/schemas/UnifiedMarketingautomationEmailOutput - tags: &ref_27 + tags: &ref_26 - marketingautomation/emails x-speakeasy-group: marketingautomation.emails x-speakeasy-pagination: @@ -3003,7 +2892,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedMarketingautomationEmailOutput' - tags: *ref_27 + tags: *ref_26 x-speakeasy-group: marketingautomation.emails /marketingautomation/events: get: @@ -3029,6 +2918,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -3051,7 +2941,7 @@ paths: items: $ref: >- #/components/schemas/UnifiedMarketingautomationEventOutput - tags: &ref_28 + tags: &ref_27 - marketingautomation/events x-speakeasy-group: marketingautomation.events x-speakeasy-pagination: @@ -3097,7 +2987,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedMarketingautomationEventOutput' - tags: *ref_28 + tags: *ref_27 x-speakeasy-group: marketingautomation.events /marketingautomation/lists: get: @@ -3123,6 +3013,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -3145,7 +3036,7 @@ paths: items: $ref: >- #/components/schemas/UnifiedMarketingautomationListOutput - tags: &ref_29 + tags: &ref_28 - marketingautomation/lists x-speakeasy-group: marketingautomation.lists x-speakeasy-pagination: @@ -3188,7 +3079,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedMarketingautomationListOutput' - tags: *ref_29 + tags: *ref_28 x-speakeasy-group: marketingautomation.lists /marketingautomation/lists/{id}: get: @@ -3225,7 +3116,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedMarketingautomationListOutput' - tags: *ref_29 + tags: *ref_28 x-speakeasy-group: marketingautomation.lists /marketingautomation/messages: get: @@ -3251,6 +3142,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -3273,7 +3165,7 @@ paths: items: $ref: >- #/components/schemas/UnifiedMarketingautomationMessageOutput - tags: &ref_30 + tags: &ref_29 - marketingautomation/messages x-speakeasy-group: marketingautomation.messages x-speakeasy-pagination: @@ -3319,7 +3211,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedMarketingautomationMessageOutput' - tags: *ref_30 + tags: *ref_29 x-speakeasy-group: marketingautomation.messages /marketingautomation/templates: get: @@ -3345,6 +3237,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -3367,7 +3260,7 @@ paths: items: $ref: >- #/components/schemas/UnifiedMarketingautomationTemplateOutput - tags: &ref_31 + tags: &ref_30 - marketingautomation/templates x-speakeasy-group: marketingautomation.templates x-speakeasy-pagination: @@ -3410,7 +3303,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedMarketingautomationTemplateOutput' - tags: *ref_31 + tags: *ref_30 x-speakeasy-group: marketingautomation.templates /marketingautomation/templates/{id}: get: @@ -3447,7 +3340,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedMarketingautomationTemplateOutput' - tags: *ref_31 + tags: *ref_30 x-speakeasy-group: marketingautomation.templates /marketingautomation/users: get: @@ -3473,6 +3366,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -3495,7 +3389,7 @@ paths: items: $ref: >- #/components/schemas/UnifiedMarketingautomationUserOutput - tags: &ref_32 + tags: &ref_31 - marketingautomation/users x-speakeasy-group: marketingautomation.users x-speakeasy-pagination: @@ -3541,7 +3435,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedMarketingautomationUserOutput' - tags: *ref_32 + tags: *ref_31 x-speakeasy-group: marketingautomation.users /accounting/accounts: get: @@ -3567,6 +3461,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -3588,7 +3483,7 @@ paths: type: array items: $ref: '#/components/schemas/UnifiedAccountingAccountOutput' - tags: &ref_33 + tags: &ref_32 - accounting/accounts x-speakeasy-group: accounting.accounts x-speakeasy-pagination: @@ -3630,7 +3525,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedAccountingAccountOutput' - tags: *ref_33 + tags: *ref_32 x-speakeasy-group: accounting.accounts /accounting/accounts/{id}: get: @@ -3665,7 +3560,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedAccountingAccountOutput' - tags: *ref_33 + tags: *ref_32 x-speakeasy-group: accounting.accounts /accounting/addresses: get: @@ -3691,6 +3586,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -3712,7 +3608,7 @@ paths: type: array items: $ref: '#/components/schemas/UnifiedAccountingAddressOutput' - tags: &ref_34 + tags: &ref_33 - accounting/addresses x-speakeasy-group: accounting.addresses x-speakeasy-pagination: @@ -3756,7 +3652,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedAccountingAddressOutput' - tags: *ref_34 + tags: *ref_33 x-speakeasy-group: accounting.addresses /accounting/attachments: get: @@ -3782,6 +3678,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -3804,7 +3701,7 @@ paths: items: $ref: >- #/components/schemas/UnifiedAccountingAttachmentOutput - tags: &ref_35 + tags: &ref_34 - accounting/attachments x-speakeasy-group: accounting.attachments x-speakeasy-pagination: @@ -3846,7 +3743,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedAccountingAttachmentOutput' - tags: *ref_35 + tags: *ref_34 x-speakeasy-group: accounting.attachments /accounting/attachments/{id}: get: @@ -3881,7 +3778,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedAccountingAttachmentOutput' - tags: *ref_35 + tags: *ref_34 x-speakeasy-group: accounting.attachments /accounting/balancesheets: get: @@ -3907,6 +3804,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -3929,7 +3827,7 @@ paths: items: $ref: >- #/components/schemas/UnifiedAccountingBalancesheetOutput - tags: &ref_36 + tags: &ref_35 - accounting/balancesheets x-speakeasy-group: accounting.balancesheets x-speakeasy-pagination: @@ -3973,7 +3871,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedAccountingBalancesheetOutput' - tags: *ref_36 + tags: *ref_35 x-speakeasy-group: accounting.balancesheets /accounting/cashflowstatements: get: @@ -3999,6 +3897,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -4021,7 +3920,7 @@ paths: items: $ref: >- #/components/schemas/UnifiedAccountingCashflowstatementOutput - tags: &ref_37 + tags: &ref_36 - accounting/cashflowstatements x-speakeasy-group: accounting.cashflowstatements x-speakeasy-pagination: @@ -4065,7 +3964,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedAccountingCashflowstatementOutput' - tags: *ref_37 + tags: *ref_36 x-speakeasy-group: accounting.cashflowstatements /accounting/companyinfos: get: @@ -4091,6 +3990,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -4113,7 +4013,7 @@ paths: items: $ref: >- #/components/schemas/UnifiedAccountingCompanyinfoOutput - tags: &ref_38 + tags: &ref_37 - accounting/companyinfos x-speakeasy-group: accounting.companyinfos x-speakeasy-pagination: @@ -4157,7 +4057,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedAccountingCompanyinfoOutput' - tags: *ref_38 + tags: *ref_37 x-speakeasy-group: accounting.companyinfos /accounting/contacts: get: @@ -4183,6 +4083,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -4204,7 +4105,7 @@ paths: type: array items: $ref: '#/components/schemas/UnifiedAccountingContactOutput' - tags: &ref_39 + tags: &ref_38 - accounting/contacts x-speakeasy-group: accounting.contacts x-speakeasy-pagination: @@ -4246,7 +4147,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedAccountingContactOutput' - tags: *ref_39 + tags: *ref_38 x-speakeasy-group: accounting.contacts /accounting/contacts/{id}: get: @@ -4281,7 +4182,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedAccountingContactOutput' - tags: *ref_39 + tags: *ref_38 x-speakeasy-group: accounting.contacts /accounting/creditnotes: get: @@ -4307,6 +4208,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -4329,7 +4231,7 @@ paths: items: $ref: >- #/components/schemas/UnifiedAccountingCreditnoteOutput - tags: &ref_40 + tags: &ref_39 - accounting/creditnotes x-speakeasy-group: accounting.creditnotes x-speakeasy-pagination: @@ -4373,7 +4275,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedAccountingCreditnoteOutput' - tags: *ref_40 + tags: *ref_39 x-speakeasy-group: accounting.creditnotes /accounting/expenses: get: @@ -4399,6 +4301,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -4420,7 +4323,7 @@ paths: type: array items: $ref: '#/components/schemas/UnifiedAccountingExpenseOutput' - tags: &ref_41 + tags: &ref_40 - accounting/expenses x-speakeasy-group: accounting.expenses x-speakeasy-pagination: @@ -4462,7 +4365,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedAccountingExpenseOutput' - tags: *ref_41 + tags: *ref_40 x-speakeasy-group: accounting.expenses /accounting/expenses/{id}: get: @@ -4497,7 +4400,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedAccountingExpenseOutput' - tags: *ref_41 + tags: *ref_40 x-speakeasy-group: accounting.expenses /accounting/incomestatements: get: @@ -4523,6 +4426,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -4545,7 +4449,7 @@ paths: items: $ref: >- #/components/schemas/UnifiedAccountingIncomestatementOutput - tags: &ref_42 + tags: &ref_41 - accounting/incomestatements x-speakeasy-group: accounting.incomestatements x-speakeasy-pagination: @@ -4589,7 +4493,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedAccountingIncomestatementOutput' - tags: *ref_42 + tags: *ref_41 x-speakeasy-group: accounting.incomestatements /accounting/invoices: get: @@ -4615,6 +4519,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -4636,7 +4541,7 @@ paths: type: array items: $ref: '#/components/schemas/UnifiedAccountingInvoiceOutput' - tags: &ref_43 + tags: &ref_42 - accounting/invoices x-speakeasy-group: accounting.invoices x-speakeasy-pagination: @@ -4678,7 +4583,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedAccountingInvoiceOutput' - tags: *ref_43 + tags: *ref_42 x-speakeasy-group: accounting.invoices /accounting/invoices/{id}: get: @@ -4713,7 +4618,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedAccountingInvoiceOutput' - tags: *ref_43 + tags: *ref_42 x-speakeasy-group: accounting.invoices /accounting/items: get: @@ -4739,6 +4644,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -4760,7 +4666,7 @@ paths: type: array items: $ref: '#/components/schemas/UnifiedAccountingItemOutput' - tags: &ref_44 + tags: &ref_43 - accounting/items x-speakeasy-group: accounting.items x-speakeasy-pagination: @@ -4804,7 +4710,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedAccountingItemOutput' - tags: *ref_44 + tags: *ref_43 x-speakeasy-group: accounting.items /accounting/journalentries: get: @@ -4830,6 +4736,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -4852,7 +4759,7 @@ paths: items: $ref: >- #/components/schemas/UnifiedAccountingJournalentryOutput - tags: &ref_45 + tags: &ref_44 - accounting/journalentries x-speakeasy-group: accounting.journalentries x-speakeasy-pagination: @@ -4894,7 +4801,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedAccountingJournalentryOutput' - tags: *ref_45 + tags: *ref_44 x-speakeasy-group: accounting.journalentries /accounting/journalentries/{id}: get: @@ -4929,7 +4836,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedAccountingJournalentryOutput' - tags: *ref_45 + tags: *ref_44 x-speakeasy-group: accounting.journalentries /accounting/payments: get: @@ -4955,6 +4862,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -4976,7 +4884,7 @@ paths: type: array items: $ref: '#/components/schemas/UnifiedAccountingPaymentOutput' - tags: &ref_46 + tags: &ref_45 - accounting/payments x-speakeasy-group: accounting.payments x-speakeasy-pagination: @@ -5018,7 +4926,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedAccountingPaymentOutput' - tags: *ref_46 + tags: *ref_45 x-speakeasy-group: accounting.payments /accounting/payments/{id}: get: @@ -5053,7 +4961,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedAccountingPaymentOutput' - tags: *ref_46 + tags: *ref_45 x-speakeasy-group: accounting.payments /accounting/phonenumbers: get: @@ -5079,6 +4987,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -5101,7 +5010,7 @@ paths: items: $ref: >- #/components/schemas/UnifiedAccountingPhonenumberOutput - tags: &ref_47 + tags: &ref_46 - accounting/phonenumbers x-speakeasy-group: accounting.phonenumbers x-speakeasy-pagination: @@ -5145,7 +5054,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedAccountingPhonenumberOutput' - tags: *ref_47 + tags: *ref_46 x-speakeasy-group: accounting.phonenumbers /accounting/purchaseorders: get: @@ -5171,6 +5080,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -5193,7 +5103,7 @@ paths: items: $ref: >- #/components/schemas/UnifiedAccountingPurchaseorderOutput - tags: &ref_48 + tags: &ref_47 - accounting/purchaseorders x-speakeasy-group: accounting.purchaseorders x-speakeasy-pagination: @@ -5235,7 +5145,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedAccountingPurchaseorderOutput' - tags: *ref_48 + tags: *ref_47 x-speakeasy-group: accounting.purchaseorders /accounting/purchaseorders/{id}: get: @@ -5270,7 +5180,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedAccountingPurchaseorderOutput' - tags: *ref_48 + tags: *ref_47 x-speakeasy-group: accounting.purchaseorders /accounting/taxrates: get: @@ -5296,6 +5206,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -5317,7 +5228,7 @@ paths: type: array items: $ref: '#/components/schemas/UnifiedAccountingTaxrateOutput' - tags: &ref_49 + tags: &ref_48 - accounting/taxrates x-speakeasy-group: accounting.taxrates x-speakeasy-pagination: @@ -5361,7 +5272,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedAccountingTaxrateOutput' - tags: *ref_49 + tags: *ref_48 x-speakeasy-group: accounting.taxrates /accounting/trackingcategories: get: @@ -5387,6 +5298,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -5409,7 +5321,7 @@ paths: items: $ref: >- #/components/schemas/UnifiedAccountingTrackingcategoryOutput - tags: &ref_50 + tags: &ref_49 - accounting/trackingcategories x-speakeasy-group: accounting.trackingcategories x-speakeasy-pagination: @@ -5453,7 +5365,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedAccountingTrackingcategoryOutput' - tags: *ref_50 + tags: *ref_49 x-speakeasy-group: accounting.trackingcategories /accounting/transactions: get: @@ -5479,6 +5391,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -5501,7 +5414,7 @@ paths: items: $ref: >- #/components/schemas/UnifiedAccountingTransactionOutput - tags: &ref_51 + tags: &ref_50 - accounting/transactions x-speakeasy-group: accounting.transactions x-speakeasy-pagination: @@ -5545,7 +5458,7 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedAccountingTransactionOutput' - tags: *ref_51 + tags: *ref_50 x-speakeasy-group: accounting.transactions /accounting/vendorcredits: get: @@ -5571,6 +5484,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -5593,7 +5507,7 @@ paths: items: $ref: >- #/components/schemas/UnifiedAccountingVendorcreditOutput - tags: &ref_52 + tags: &ref_51 - accounting/vendorcredits x-speakeasy-group: accounting.vendorcredits x-speakeasy-pagination: @@ -5637,12 +5551,12 @@ paths: application/json: schema: $ref: '#/components/schemas/UnifiedAccountingVendorcreditOutput' - tags: *ref_52 + tags: *ref_51 x-speakeasy-group: accounting.vendorcredits - /filestorage/folders: + /filestorage/files: get: - operationId: listFilestorageFolder - summary: List Folders + operationId: listFilestorageFile + summary: List Files parameters: - name: x-connection-token required: true @@ -5663,6 +5577,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -5683,10 +5598,10 @@ paths: data: type: array items: - $ref: '#/components/schemas/UnifiedFilestorageFolderOutput' - tags: &ref_53 - - filestorage/folders - x-speakeasy-group: filestorage.folders + $ref: '#/components/schemas/UnifiedFilestorageFileOutput' + tags: &ref_52 + - filestorage/files + x-speakeasy-group: filestorage.files x-speakeasy-pagination: type: cursor inputs: @@ -5696,9 +5611,9 @@ paths: outputs: nextCursor: $.next_cursor post: - operationId: createFilestorageFolder - summary: Create Folders - description: Create Folders in any supported Filestorage software + operationId: createFilestorageFile + summary: Create Files + description: Create Files in any supported Filestorage software parameters: - name: x-connection-token required: true @@ -5718,21 +5633,21 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/UnifiedFilestorageFolderInput' + $ref: '#/components/schemas/UnifiedFilestorageFileInput' responses: '201': description: '' content: application/json: schema: - $ref: '#/components/schemas/UnifiedFilestorageFolderOutput' - tags: *ref_53 - x-speakeasy-group: filestorage.folders - /filestorage/folders/{id}: + $ref: '#/components/schemas/UnifiedFilestorageFileOutput' + tags: *ref_52 + x-speakeasy-group: filestorage.files + /filestorage/files/{id}: get: - operationId: retrieveFilestorageFolder - summary: Retrieve Folders - description: Retrieve Folders from any connected Filestorage software + operationId: retrieveFilestorageFile + summary: Retrieve Files + description: Retrieve Files from any connected Filestorage software parameters: - name: x-connection-token required: true @@ -5743,7 +5658,7 @@ paths: - name: id required: true in: path - description: id of the folder you want to retrieve. + description: id of the file you want to retrieve. example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f schema: type: string @@ -5760,13 +5675,13 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/UnifiedFilestorageFolderOutput' - tags: *ref_53 - x-speakeasy-group: filestorage.folders - /filestorage/groups: + $ref: '#/components/schemas/UnifiedFilestorageFileOutput' + tags: *ref_52 + x-speakeasy-group: filestorage.files + /filestorage/folders: get: - operationId: listFilestorageGroup - summary: List Groups + operationId: listFilestorageFolder + summary: List Folders parameters: - name: x-connection-token required: true @@ -5787,6 +5702,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -5807,10 +5723,10 @@ paths: data: type: array items: - $ref: '#/components/schemas/UnifiedFilestorageGroupOutput' - tags: &ref_54 - - filestorage/groups - x-speakeasy-group: filestorage.groups + $ref: '#/components/schemas/UnifiedFilestorageFolderOutput' + tags: &ref_53 + - filestorage/folders + x-speakeasy-group: filestorage.folders x-speakeasy-pagination: type: cursor inputs: @@ -5819,11 +5735,10 @@ paths: type: cursor outputs: nextCursor: $.next_cursor - /filestorage/groups/{id}: - get: - operationId: retrieveFilestorageGroup - summary: Retrieve Groups - description: Retrieve Groups from any connected Filestorage software + post: + operationId: createFilestorageFolder + summary: Create Folders + description: Create Folders in any supported Filestorage software parameters: - name: x-connection-token required: true @@ -5831,17 +5746,143 @@ paths: description: The connection token schema: type: string - - name: id - required: true - in: path - description: id of the permission you want to retrieve. - example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f - schema: - type: string - name: remote_data required: false in: query - description: Set to true to include data from the original File Storage software. + example: false + description: Set to true to include data from the original Accounting software. + schema: + type: boolean + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/UnifiedFilestorageFolderInput' + responses: + '201': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/UnifiedFilestorageFolderOutput' + tags: *ref_53 + x-speakeasy-group: filestorage.folders + /filestorage/folders/{id}: + get: + operationId: retrieveFilestorageFolder + summary: Retrieve Folders + description: Retrieve Folders from any connected Filestorage software + parameters: + - name: x-connection-token + required: true + in: header + description: The connection token + schema: + type: string + - name: id + required: true + in: path + description: id of the folder you want to retrieve. + example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f + schema: + type: string + - name: remote_data + required: false + in: query + description: Set to true to include data from the original File Storage software. + example: false + schema: + type: boolean + responses: + '200': + description: '' + content: + application/json: + schema: + $ref: '#/components/schemas/UnifiedFilestorageFolderOutput' + tags: *ref_53 + x-speakeasy-group: filestorage.folders + /filestorage/groups: + get: + operationId: listFilestorageGroup + summary: List Groups + parameters: + - name: x-connection-token + required: true + in: header + description: The connection token + schema: + type: string + - name: remote_data + required: false + in: query + example: true + description: Set to true to include data from the original software. + schema: + type: boolean + - name: limit + required: false + in: query + example: 10 + description: Set to get the number of records. + schema: + default: 50 + type: number + - name: cursor + required: false + in: query + example: 1b8b05bb-5273-4012-b520-8657b0b90874 + description: Set to get the number of records after this cursor. + schema: + type: string + responses: + '200': + description: '' + content: + application/json: + schema: + allOf: + - $ref: '#/components/schemas/PaginatedDto' + - properties: + data: + type: array + items: + $ref: '#/components/schemas/UnifiedFilestorageGroupOutput' + tags: &ref_54 + - filestorage/groups + x-speakeasy-group: filestorage.groups + x-speakeasy-pagination: + type: cursor + inputs: + - name: cursor + in: parameters + type: cursor + outputs: + nextCursor: $.next_cursor + /filestorage/groups/{id}: + get: + operationId: retrieveFilestorageGroup + summary: Retrieve Groups + description: Retrieve Groups from any connected Filestorage software + parameters: + - name: x-connection-token + required: true + in: header + description: The connection token + schema: + type: string + - name: id + required: true + in: path + description: id of the permission you want to retrieve. + example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f + schema: + type: string + - name: remote_data + required: false + in: query + description: Set to true to include data from the original File Storage software. example: false schema: type: boolean @@ -5878,6 +5919,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -5969,6 +6011,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -6091,6 +6134,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -6213,6 +6257,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -6302,6 +6347,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -6392,6 +6438,7 @@ paths: example: 10 description: Set to get the number of records. schema: + default: 50 type: number - name: cursor required: false @@ -6512,218 +6559,6 @@ components: in: header name: x-api-key schemas: - RagQueryOutput: - type: object - properties: - chunk: - type: string - example: 'Date : 06/07/2023' - nullable: false - description: The chunk which matches the embed query - metadata: - type: object - example: - blobType: '' - text: ATTESTATION - additionalProperties: true - nullable: true - description: The metadata tied to the chunk - score: - type: number - example: 0.87 - nullable: true - description: The score - embedding: - example: - - -0.00442447886 - - -0.00116857514 - - 0.00869117491 - - -0.0361584462 - - -0.00220073434 - - 0.00946036354 - - -0.0101112155 - nullable: true - description: The embedding of the relevant chunk - type: array - items: - type: number - required: - - chunk - - metadata - - score - - embedding - QueryBody: - type: object - properties: - query: - type: string - example: When does Panora incorporated? - nullable: false - description: The query you want to received embeddings and chunks for - topK: - type: number - example: '3' - nullable: true - description: The number of most appropriate documents for your query. - required: - - query - PaginatedDto: - type: object - properties: - prev_cursor: - type: string - nullable: true - next_cursor: - type: string - nullable: true - data: - type: array - items: - type: object - required: - - prev_cursor - - next_cursor - - data - UnifiedFilestorageFileOutput: - type: object - properties: - name: - type: string - example: my_paris_photo.png - description: The name of the file - nullable: true - file_url: - type: string - example: https://example.com/my_paris_photo.png - description: The url of the file - nullable: true - mime_type: - type: string - example: application/pdf - description: The mime type of the file - nullable: true - size: - type: string - example: '1024' - description: The size of the file - nullable: true - folder_id: - type: string - example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f - description: The UUID of the folder tied to the file - nullable: true - permission: - type: string - example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f - description: The UUID of the permission tied to the file - nullable: true - shared_link: - type: string - example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f - description: The UUID of the shared link tied to the file - nullable: true - field_mappings: - type: object - example: &ref_61 - fav_dish: broccoli - fav_color: red - description: >- - The custom field mappings of the object between the remote 3rd party - & Panora - nullable: true - additionalProperties: true - id: - type: string - example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f - description: The UUID of the file - nullable: true - remote_id: - type: string - example: id_1 - description: The id of the file in the context of the 3rd Party - nullable: true - remote_data: - type: object - example: - fav_dish: broccoli - fav_color: red - description: The remote data of the file in the context of the 3rd Party - nullable: true - additionalProperties: true - created_at: - format: date-time - type: string - example: '2024-10-01T12:00:00Z' - description: The created date of the object - nullable: true - modified_at: - format: date-time - type: string - example: '2024-10-01T12:00:00Z' - description: The modified date of the object - nullable: true - required: - - name - - file_url - - mime_type - - size - - folder_id - - permission - - shared_link - UnifiedFilestorageFileInput: - type: object - properties: - name: - type: string - example: my_paris_photo.png - description: The name of the file - nullable: true - file_url: - type: string - example: https://example.com/my_paris_photo.png - description: The url of the file - nullable: true - mime_type: - type: string - example: application/pdf - description: The mime type of the file - nullable: true - size: - type: string - example: '1024' - description: The size of the file - nullable: true - folder_id: - type: string - example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f - description: The UUID of the folder tied to the file - nullable: true - permission: - type: string - example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f - description: The UUID of the permission tied to the file - nullable: true - shared_link: - type: string - example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f - description: The UUID of the shared link tied to the file - nullable: true - field_mappings: - type: object - example: *ref_61 - description: >- - The custom field mappings of the object between the remote 3rd party - & Panora - nullable: true - additionalProperties: true - required: - - name - - file_url - - mime_type - - size - - folder_id - - permission - - shared_link LoginDto: type: object properties: @@ -6734,7 +6569,6 @@ components: password_hash: type: string required: - - id_user - email - password_hash Connection: @@ -6822,8 +6656,8 @@ components: description: The unique UUID of the webhook. endpoint_description: type: string - example: Webhook to receive connection events nullable: true + example: Webhook to receive connection events description: The description of the webhook. url: type: string @@ -6861,8 +6695,8 @@ components: last_update: format: date-time type: string - example: '2024-10-01T12:00:00Z' nullable: true + example: '2024-10-01T12:00:00Z' description: The last update date of the webhook. required: - id_webhook_endpoint @@ -6897,7 +6731,6 @@ components: type: string required: - url - - description - scope SignatureVerificationDto: type: object @@ -6919,6 +6752,23 @@ components: - payload - signature - secret + PaginatedDto: + type: object + properties: + prev_cursor: + type: string + nullable: true + next_cursor: + type: string + nullable: true + data: + type: array + items: + type: object + required: + - prev_cursor + - next_cursor + - data UnifiedTicketingCommentInput: type: object properties: @@ -6965,12 +6815,12 @@ components: specified) attachments: type: array - items: &ref_84 + items: &ref_83 oneOf: - type: string - $ref: '#/components/schemas/UnifiedTicketingAttachmentOutput' nullable: true - example: &ref_85 + example: &ref_84 - 801f9ede-c698-4e66-a7fc-48d19eebaa4f description: The attachements UUIDs tied to the comment required: @@ -7013,21 +6863,21 @@ components: description: The UUID of the parent ticket collections: type: array - items: &ref_62 + items: &ref_61 oneOf: - type: string - $ref: '#/components/schemas/UnifiedTicketingCollectionOutput' - example: &ref_63 + example: &ref_62 - 801f9ede-c698-4e66-a7fc-48d19eebaa4f nullable: true description: The collection UUIDs the ticket belongs to tags: type: array - items: &ref_64 + items: &ref_63 oneOf: - type: string - $ref: '#/components/schemas/UnifiedTicketingTagOutput' - example: &ref_65 + example: &ref_64 - my_tag - urgent_tag nullable: true @@ -7046,7 +6896,7 @@ components: The priority of the ticket. Authorized values are HIGH, MEDIUM or LOW. assigned_to: - example: &ref_66 + example: &ref_65 - 801f9ede-c698-4e66-a7fc-48d19eebaa4f nullable: true description: The users UUIDs the ticket is assigned to @@ -7054,7 +6904,7 @@ components: items: type: string comment: - example: &ref_67 + example: &ref_66 content: Assigned the issue ! nullable: true description: The comment of the ticket @@ -7072,17 +6922,17 @@ components: description: The UUID of the contact which the ticket belongs to attachments: type: array - items: &ref_68 + items: &ref_67 oneOf: - type: string - $ref: '#/components/schemas/UnifiedTicketingAttachmentInput' - example: &ref_69 + example: &ref_68 - 801f9ede-c698-4e66-a7fc-48d19eebaa4f description: The attachements UUIDs tied to the ticket nullable: true field_mappings: type: object - example: &ref_70 + example: &ref_69 fav_dish: broccoli fav_color: red nullable: true @@ -7162,14 +7012,14 @@ components: description: The UUID of the parent ticket collections: type: array - items: *ref_62 - example: *ref_63 + items: *ref_61 + example: *ref_62 nullable: true description: The collection UUIDs the ticket belongs to tags: type: array - items: *ref_64 - example: *ref_65 + items: *ref_63 + example: *ref_64 nullable: true description: The tags names of the ticket completed_at: @@ -7186,14 +7036,14 @@ components: The priority of the ticket. Authorized values are HIGH, MEDIUM or LOW. assigned_to: - example: *ref_66 + example: *ref_65 nullable: true description: The users UUIDs the ticket is assigned to type: array items: type: string comment: - example: *ref_67 + example: *ref_66 nullable: true description: The comment of the ticket allOf: @@ -7210,13 +7060,13 @@ components: description: The UUID of the contact which the ticket belongs to attachments: type: array - items: *ref_68 - example: *ref_69 + items: *ref_67 + example: *ref_68 description: The attachements UUIDs tied to the ticket nullable: true field_mappings: type: object - example: *ref_70 + example: *ref_69 nullable: true description: >- The custom field mappings of the ticket between the remote 3rd party @@ -7605,7 +7455,7 @@ components: nullable: true email_addresses: description: The email addresses of the company - example: &ref_71 + example: &ref_70 - email_address: acme@gmail.com email_address_type: WORK nullable: true @@ -7614,7 +7464,7 @@ components: $ref: '#/components/schemas/Email' addresses: description: The addresses of the company - example: &ref_72 + example: &ref_71 - street_1: 5th Avenue city: New York state: NY @@ -7626,7 +7476,7 @@ components: $ref: '#/components/schemas/Address' phone_numbers: description: The phone numbers of the company - example: &ref_73 + example: &ref_72 - phone_number: '+33660606067' phone_type: WORK nullable: true @@ -7635,7 +7485,7 @@ components: $ref: '#/components/schemas/Phone' field_mappings: type: object - example: &ref_74 + example: &ref_73 fav_dish: broccoli fav_color: red description: >- @@ -7700,28 +7550,28 @@ components: nullable: true email_addresses: description: The email addresses of the company - example: *ref_71 + example: *ref_70 nullable: true type: array items: $ref: '#/components/schemas/Email' addresses: description: The addresses of the company - example: *ref_72 + example: *ref_71 nullable: true type: array items: $ref: '#/components/schemas/Address' phone_numbers: description: The phone numbers of the company - example: *ref_73 + example: *ref_72 nullable: true type: array items: $ref: '#/components/schemas/Phone' field_mappings: type: object - example: *ref_74 + example: *ref_73 description: >- The custom field mappings of the company between the remote 3rd party & Panora @@ -7745,7 +7595,7 @@ components: email_addresses: nullable: true description: The email addresses of the contact - example: &ref_75 + example: &ref_74 - email: john.doe@example.com type: WORK type: array @@ -7754,7 +7604,7 @@ components: phone_numbers: nullable: true description: The phone numbers of the contact - example: &ref_76 + example: &ref_75 - phone: '1234567890' type: WORK type: array @@ -7763,7 +7613,7 @@ components: addresses: nullable: true description: The addresses of the contact - example: &ref_77 + example: &ref_76 - street: 123 Main St city: Anytown state: CA @@ -7780,7 +7630,7 @@ components: example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f field_mappings: type: object - example: &ref_78 + example: &ref_77 fav_dish: broccoli fav_color: red nullable: true @@ -7837,21 +7687,21 @@ components: email_addresses: nullable: true description: The email addresses of the contact - example: *ref_75 + example: *ref_74 type: array items: $ref: '#/components/schemas/Email' phone_numbers: nullable: true description: The phone numbers of the contact - example: *ref_76 + example: *ref_75 type: array items: $ref: '#/components/schemas/Phone' addresses: nullable: true description: The addresses of the contact - example: *ref_77 + example: *ref_76 type: array items: $ref: '#/components/schemas/Address' @@ -7862,7 +7712,7 @@ components: example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f field_mappings: type: object - example: *ref_78 + example: *ref_77 nullable: true description: >- The custom field mappings of the contact between the remote 3rd @@ -7907,7 +7757,7 @@ components: field_mappings: type: object nullable: true - example: &ref_79 + example: &ref_78 fav_dish: broccoli fav_color: red description: >- @@ -7984,7 +7834,7 @@ components: field_mappings: type: object nullable: true - example: *ref_79 + example: *ref_78 description: >- The custom field mappings of the company between the remote 3rd party & Panora @@ -8044,7 +7894,7 @@ components: description: The UUID of the company tied to the engagement contacts: nullable: true - example: &ref_80 + example: &ref_79 - 801f9ede-c698-4e66-a7fc-48d19eebaa4f description: The UUIDs of contacts tied to the engagement object type: array @@ -8053,7 +7903,7 @@ components: field_mappings: type: object nullable: true - example: &ref_81 + example: &ref_80 fav_dish: broccoli fav_color: red description: >- @@ -8145,7 +7995,7 @@ components: description: The UUID of the company tied to the engagement contacts: nullable: true - example: *ref_80 + example: *ref_79 description: The UUIDs of contacts tied to the engagement object type: array items: @@ -8153,7 +8003,7 @@ components: field_mappings: type: object nullable: true - example: *ref_81 + example: *ref_80 description: >- The custom field mappings of the engagement between the remote 3rd party & Panora @@ -8190,7 +8040,7 @@ components: description: The UUID of the deal tied to the note field_mappings: type: object - example: &ref_82 + example: &ref_81 fav_dish: broccoli fav_color: red nullable: true @@ -8260,7 +8110,7 @@ components: description: The UUID of the deal tied to the note field_mappings: type: object - example: *ref_82 + example: *ref_81 nullable: true description: >- The custom field mappings of the note between the remote 3rd party & @@ -8361,7 +8211,7 @@ components: nullable: true field_mappings: type: object - example: &ref_83 + example: &ref_82 fav_dish: broccoli fav_color: red description: >- @@ -8449,7 +8299,7 @@ components: nullable: true field_mappings: type: object - example: *ref_83 + example: *ref_82 description: >- The custom field mappings of the task between the remote 3rd party & Panora @@ -8613,9 +8463,9 @@ components: specified) attachments: type: array - items: *ref_84 + items: *ref_83 nullable: true - example: *ref_85 + example: *ref_84 description: The attachements UUIDs tied to the comment id: type: string @@ -8847,8 +8697,6 @@ components: - id_project - name - sync_mode - - pull_frequency - - redirect_url - id_user - id_connector_set CreateProjectDto: @@ -9217,10 +9065,10 @@ components: type: object properties: method: - type: string enum: - GET - POST + type: string path: type: string nullable: true @@ -9239,12 +9087,11 @@ components: type: object additionalProperties: true nullable: true + headers: + type: object required: - method - path - - data - - request_format - - overrideBaseUrl UnifiedMarketingautomationActionOutput: type: object properties: {} @@ -9348,7 +9195,7 @@ components: description: The UUID of the associated company info field_mappings: type: object - example: &ref_86 + example: &ref_85 custom_field_1: value1 custom_field_2: value2 nullable: true @@ -9439,7 +9286,7 @@ components: description: The UUID of the associated company info field_mappings: type: object - example: *ref_86 + example: *ref_85 nullable: true description: >- The custom field mappings of the object between the remote 3rd party @@ -9555,7 +9402,7 @@ components: description: The UUID of the associated account field_mappings: type: object - example: &ref_87 + example: &ref_86 custom_field_1: value1 custom_field_2: value2 nullable: true @@ -9611,7 +9458,7 @@ components: description: The UUID of the associated account field_mappings: type: object - example: *ref_87 + example: *ref_86 nullable: true description: >- The custom field mappings of the object between the remote 3rd party @@ -10011,7 +9858,7 @@ components: description: The UUID of the associated company info field_mappings: type: object - example: &ref_88 + example: &ref_87 custom_field_1: value1 custom_field_2: value2 nullable: true @@ -10097,7 +9944,7 @@ components: description: The UUID of the associated company info field_mappings: type: object - example: *ref_88 + example: *ref_87 nullable: true description: >- The custom field mappings of the object between the remote 3rd party @@ -10287,7 +10134,7 @@ components: nullable: true description: The UUID of the associated company info tracking_categories: - example: &ref_89 + example: &ref_88 - 801f9ede-c698-4e66-a7fc-48d19eebaa4f nullable: true description: The UUIDs of the tracking categories associated with the expense @@ -10301,7 +10148,7 @@ components: $ref: '#/components/schemas/LineItem' field_mappings: type: object - example: &ref_90 + example: &ref_89 custom_field_1: value1 custom_field_2: value2 nullable: true @@ -10398,7 +10245,7 @@ components: nullable: true description: The UUID of the associated company info tracking_categories: - example: *ref_89 + example: *ref_88 nullable: true description: The UUIDs of the tracking categories associated with the expense type: array @@ -10411,7 +10258,7 @@ components: $ref: '#/components/schemas/LineItem' field_mappings: type: object - example: *ref_90 + example: *ref_89 nullable: true description: >- The custom field mappings of the object between the remote 3rd party @@ -10585,7 +10432,7 @@ components: nullable: true description: The UUID of the associated accounting period tracking_categories: - example: &ref_91 + example: &ref_90 - 801f9ede-c698-4e66-a7fc-48d19eebaa4f - 801f9ede-c698-4e66-a7fc-48d19eebaa4f nullable: true @@ -10600,7 +10447,7 @@ components: $ref: '#/components/schemas/LineItem' field_mappings: type: object - example: &ref_92 + example: &ref_91 custom_field_1: value1 custom_field_2: value2 nullable: true @@ -10729,7 +10576,7 @@ components: nullable: true description: The UUID of the associated accounting period tracking_categories: - example: *ref_91 + example: *ref_90 nullable: true description: The UUIDs of the tracking categories associated with the invoice type: array @@ -10742,7 +10589,7 @@ components: $ref: '#/components/schemas/LineItem' field_mappings: type: object - example: *ref_92 + example: *ref_91 nullable: true description: >- The custom field mappings of the object between the remote 3rd party @@ -10839,7 +10686,7 @@ components: nullable: true description: The date of the transaction payments: - example: &ref_93 + example: &ref_92 - payment1 - payment2 nullable: true @@ -10848,7 +10695,7 @@ components: items: type: string applied_payments: - example: &ref_94 + example: &ref_93 - appliedPayment1 - appliedPayment2 nullable: true @@ -10882,7 +10729,7 @@ components: nullable: true description: The journal number tracking_categories: - example: &ref_95 + example: &ref_94 - 801f9ede-c698-4e66-a7fc-48d19eebaa4f nullable: true description: >- @@ -10908,7 +10755,7 @@ components: $ref: '#/components/schemas/LineItem' field_mappings: type: object - example: &ref_96 + example: &ref_95 custom_field_1: value1 custom_field_2: value2 nullable: true @@ -10968,14 +10815,14 @@ components: nullable: true description: The date of the transaction payments: - example: *ref_93 + example: *ref_92 nullable: true description: The payments associated with the journal entry type: array items: type: string applied_payments: - example: *ref_94 + example: *ref_93 nullable: true description: The applied payments for the journal entry type: array @@ -11007,7 +10854,7 @@ components: nullable: true description: The journal number tracking_categories: - example: *ref_95 + example: *ref_94 nullable: true description: >- The UUIDs of the tracking categories associated with the journal @@ -11032,7 +10879,7 @@ components: $ref: '#/components/schemas/LineItem' field_mappings: type: object - example: *ref_96 + example: *ref_95 nullable: true description: >- The custom field mappings of the object between the remote 3rd party @@ -11092,7 +10939,7 @@ components: nullable: true description: The UUID of the associated accounting period tracking_categories: - example: &ref_97 + example: &ref_96 - 801f9ede-c698-4e66-a7fc-48d19eebaa4f nullable: true description: The UUIDs of the tracking categories associated with the payment @@ -11106,7 +10953,7 @@ components: $ref: '#/components/schemas/LineItem' field_mappings: type: object - example: &ref_98 + example: &ref_97 custom_field_1: value1 custom_field_2: value2 nullable: true @@ -11203,7 +11050,7 @@ components: nullable: true description: The UUID of the associated accounting period tracking_categories: - example: *ref_97 + example: *ref_96 nullable: true description: The UUIDs of the tracking categories associated with the payment type: array @@ -11216,7 +11063,7 @@ components: $ref: '#/components/schemas/LineItem' field_mappings: type: object - example: *ref_98 + example: *ref_97 nullable: true description: >- The custom field mappings of the object between the remote 3rd party @@ -11348,7 +11195,7 @@ components: nullable: true description: The exchange rate applied to the purchase order tracking_categories: - example: &ref_99 + example: &ref_98 - 801f9ede-c698-4e66-a7fc-48d19eebaa4f nullable: true description: >- @@ -11369,7 +11216,7 @@ components: $ref: '#/components/schemas/LineItem' field_mappings: type: object - example: &ref_100 + example: &ref_99 custom_field_1: value1 custom_field_2: value2 nullable: true @@ -11487,7 +11334,7 @@ components: nullable: true description: The exchange rate applied to the purchase order tracking_categories: - example: *ref_99 + example: *ref_98 nullable: true description: >- The UUIDs of the tracking categories associated with the purchase @@ -11507,7 +11354,7 @@ components: $ref: '#/components/schemas/LineItem' field_mappings: type: object - example: *ref_100 + example: *ref_99 nullable: true description: >- The custom field mappings of the object between the remote 3rd party @@ -11856,6 +11703,146 @@ components: additional_field: some value nullable: true description: The remote data of the vendor credit in the context of the 3rd Party + UnifiedFilestorageFileOutput: + type: object + properties: + name: + type: string + example: my_paris_photo.png + description: The name of the file + nullable: true + file_url: + type: string + example: https://example.com/my_paris_photo.png + description: The url of the file + nullable: true + mime_type: + type: string + example: application/pdf + description: The mime type of the file + nullable: true + size: + type: string + example: '1024' + description: The size of the file + nullable: true + folder_id: + type: string + example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f + description: The UUID of the folder tied to the file + nullable: true + permission: + type: string + example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f + description: The UUID of the permission tied to the file + nullable: true + shared_link: + type: string + example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f + description: The UUID of the shared link tied to the file + nullable: true + field_mappings: + type: object + example: &ref_100 + fav_dish: broccoli + fav_color: red + description: >- + The custom field mappings of the object between the remote 3rd party + & Panora + nullable: true + additionalProperties: true + id: + type: string + example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f + description: The UUID of the file + nullable: true + remote_id: + type: string + example: id_1 + description: The id of the file in the context of the 3rd Party + nullable: true + remote_data: + type: object + example: + fav_dish: broccoli + fav_color: red + description: The remote data of the file in the context of the 3rd Party + nullable: true + additionalProperties: true + created_at: + format: date-time + type: string + example: '2024-10-01T12:00:00Z' + description: The created date of the object + nullable: true + modified_at: + format: date-time + type: string + example: '2024-10-01T12:00:00Z' + description: The modified date of the object + nullable: true + required: + - name + - file_url + - mime_type + - size + - folder_id + - permission + - shared_link + UnifiedFilestorageFileInput: + type: object + properties: + name: + type: string + example: my_paris_photo.png + description: The name of the file + nullable: true + file_url: + type: string + example: https://example.com/my_paris_photo.png + description: The url of the file + nullable: true + mime_type: + type: string + example: application/pdf + description: The mime type of the file + nullable: true + size: + type: string + example: '1024' + description: The size of the file + nullable: true + folder_id: + type: string + example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f + description: The UUID of the folder tied to the file + nullable: true + permission: + type: string + example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f + description: The UUID of the permission tied to the file + nullable: true + shared_link: + type: string + example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f + description: The UUID of the shared link tied to the file + nullable: true + field_mappings: + type: object + example: *ref_100 + description: >- + The custom field mappings of the object between the remote 3rd party + & Panora + nullable: true + additionalProperties: true + required: + - name + - file_url + - mime_type + - size + - folder_id + - permission + - shared_link UnifiedFilestorageFolderOutput: type: object properties: