diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +node_modules diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..6516908 --- /dev/null +++ b/.env.example @@ -0,0 +1,119 @@ +# Port used by the server +PORT=4000 # optional + +# Log level, set to "trace" for detailed logs +LOG_LEVEL=info # optional + +# Secret used by the server to encrypt/decrypt values +# You can use `$ openssl rand -base64 32` to generate new one +CRYPTO_CIPHER_KEY= + +# MongoDB database, must be a replica set, see https://www.mongodb.com/docs/manual/tutorial/deploy-replica-set/ +MONGODB_URL=mongodb://localhost:27017?directConnection=true +MONGODB_DATABASE_NAME=bee-api +MONGODB_CA_CERT= # optional + +# Redis database, used by distributed queue and as pub/sub broker +REDIS_URL=redis://127.0.0.1:6379/0 +REDIS_CA_CERT= # optional + +# Redis database for data caching +# In production, make sure you set up eviction policy to `volatile-lru` +# https://redis.io/docs/latest/develop/reference/eviction/#eviction-policies +REDIS_CACHE_URL=redis://127.0.0.1:6379/1 +REDIS_CACHE_CA_CERT= # optional + +# Object Storage used for files and their text extractions +S3_ENDPOINT= +S3_ACCESS_KEY_ID= +S3_SECRET_ACCESS_KEY= +S3_BUCKET_FILE_STORAGE= + +# OAuth2 client credentials for access token validation, acting as the resource server +AUTH_WELL_KNOWN= +AUTH_CLIENT_ID= +AUTH_CLIENT_SECRET= +AUTH_AUDIENCE= + +# Queue workers +RUN_BULLMQ_WORKERS=runs,runs:cleanup,vectorStores:cleanup,vectorStores:fileProcessor,files:extraction,threads:cleanup,files:cleanup + + +# --- BACKEND SECTION --- + +# LLM backend, possible values are: ollama, openai, watsonx, bam, ibm-vllm +LLM_BACKEND=watsonx + +# Embedding backend, possible values are: ollama, openai, watsonx, bam, caikit +EMBEDDING_BACKEND=watsonx + +# --- Backend details (only applicable to backend(s) selected above) --- + +# https://ollama.com/ +OLLAMA_URL= + +# https://openai.com/ +OPENAI_API_KEY= + +# https://www.ibm.com/products/watsonx-ai +WATSONX_API_KEY= +WATSONX_PROJECT_ID= + +BAM_API_KEY= + +# Must contain port, can contain {model_id} placeholder, e.g. "{model_id}.inference.example.com:443" +IBM_VLLM_URL= +IBM_VLLM_ROOT_CERT= +IBM_VLLM_CERT_CHAIN= +IBM_VLLM_PRIVATE_KEY= + +CAIKIT_URL= +CAIKIT_CA_CERT= +CAIKIT_CERT= +CAIKIT_KEY= + +# --- BACKEND SECTION --- + +# --- TOOLS SECTION --- + +# Code Interpreter, see https://github.com/i-am-bee/bee-code-interpreter +BEE_CODE_INTERPRETER_URL=http://localhost:50051 +BEE_CODE_INTERPRETER_CA_CERT= # optional +BEE_CODE_INTERPRETER_CERT= # optional +BEE_CODE_INTERPRETER_KEY= # optional +# Storage for code interpreter, possible values are: s3, filesystem +BEE_CODE_INTERPRETER_STORAGE_BACKEND=s3 +# applicable for s3 storage, uses S3 credential above +BEE_CODE_INTERPRETER_BUCKET_FILE_STORAGE= +# applicable for filesystem storage +BEE_CODE_INTERPRETER_FILE_STORAGE_PATH= + +# Milvus is used as a vector store for file search tool +MILVUS_HOST=127.0.0.1 +MILVUS_PORT=19530 +MILVUS_USE_TLS=false +MILVUS_USERNAME= +MILVUS_PASSWORD= +MILVUS_DATABASE_NAME= + +# Search tool backend, possible values are: google, duck-duck-go +SEARCH_TOOL_BACKEND=duck-duck-go +# applicable for google search tool +BEE_GOOGLE_SEARCH_API_KEY= +BEE_GOOGLE_SEARCH_CSE_ID= + +# Forward proxy for api calling tool +HTTP_PROXY_URL= # optional + +# --- TOOLS SECTION --- + +# Observer server, see https://github.com/i-am-bee/bee-observe +BEE_OBSERVE_API_URL= # optional +BEE_OBSERVE_API_AUTH_KEY= # optional + +# Text extraction service +WDU_URL= # optional + +# Identifiers to be used for seeder and to allocate new users into default org/project +ORGANIZATION_OWNER_ID_DEFAULT=org_user_670cc04869ddffe24f4fd70e +PROJECT_ADMIN_ID_DEFAULT=proj_principal_670cc04869ddffe24f4fd710 diff --git a/.env.test.example b/.env.test.example new file mode 100644 index 0000000..17e26e9 --- /dev/null +++ b/.env.test.example @@ -0,0 +1,2 @@ +BEE_URL=http://localhost:4000 +BEE_TOKEN= \ No newline at end of file diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..6a11105 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +src/**/grpc/types/** \ No newline at end of file diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 0000000..b3e740a --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,44 @@ +module.exports = { + root: true, + parser: '@typescript-eslint/parser', + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:import/recommended', + 'plugin:import/typescript', + 'plugin:prettier/recommended' + ], + parserOptions: { + project: ['tsconfig.json'], + tsconfigRootDir: __dirname + }, + plugins: ['@typescript-eslint', 'import'], + settings: { + 'import/resolver': { + typescript: true, + node: true + } + }, + rules: { + 'import/order': [ + 'error', + { + 'newlines-between': 'always' + } + ], + 'import/default': 'off', + '@typescript-eslint/no-explicit-any': 'off', + 'import/no-named-as-default-member': 'off', + 'import/no-named-as-default': 'off', + '@typescript-eslint/no-unused-vars': [ + 'error', + { + argsIgnorePattern: '^_', + varsIgnorePattern: '^_', + caughtErrorsIgnorePattern: '^_', + }, + ], + '@typescript-eslint/no-empty-function': 'off', + 'no-console': 'error' + } +}; diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d0e1c5c --- /dev/null +++ b/.gitignore @@ -0,0 +1,48 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js +.yarn/install-state.gz + +# testing +/coverage + +# production +/dist + +# playground +/playground + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# env files +.env +.env.test + +# typescript +*.tsbuildinfo + +# vscode +.vscode + +# mikro-orm ts metadata cache +/temp + +# npm +.npmrc + +# other +/tmp + + +# WebStorm +.idea diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..d5529fb --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,2 @@ +pnpm exec lint-staged +CI=true pnpm copyright diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..7bceec7 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +v22.2.0 diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..11cd494 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,5 @@ +{ + "printWidth": 100, + "singleQuote": true, + "trailingComma": "none" +} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c51cf49 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,54 @@ +FROM node:22.2-alpine AS base + +# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed. +RUN apk add --no-cache libc6-compat + +ENV APP_DIR=/app + +RUN mkdir -p ${APP_DIR} +WORKDIR ${APP_DIR} + +# Install dependencies only when needed +FROM base AS deps + +ENV CI=1 +ENV HUSKY=0 + +# Install dependencies based on the preferred package manager +COPY package.json pnpm-lock.yaml* ./ +RUN corepack enable pnpm && pnpm i --frozen-lockfile + +# Rebuild the source code only when needed +FROM base AS builder + +ENV CI=1 + +COPY --from=deps ${APP_DIR}/node_modules ./node_modules +COPY . . + +RUN corepack enable pnpm && pnpm run build; + +# Production image, copy all the files and run next +FROM base AS runner + +ENV NODE_ENV production + +# https://github.com/nodejs/docker-node/blob/main/docs/BestPractices.md +RUN deluser --remove-home node \ + && addgroup -S node -g 1001 \ + && adduser -S -G node -u 1001 node + +COPY --chown=node:node --from=deps ${APP_DIR}/package.json ./ +COPY --chown=node:node --from=deps ${APP_DIR}/node_modules ./node_modules +COPY --chown=node:node --from=builder ${APP_DIR}/dist ./dist + +RUN chown -R 1001:0 ${APP_DIR} &&\ + chmod -R g+w ${APP_DIR} + +USER node + +EXPOSE 4000 + +ENV PORT 4000 + +CMD [ "node", "--enable-source-maps", "--experimental-loader=@opentelemetry/instrumentation/hook.mjs", "--import", "./dist/opentelemetry.js", "./dist/server.js" ] diff --git a/README.md b/README.md new file mode 100644 index 0000000..092eadb --- /dev/null +++ b/README.md @@ -0,0 +1,50 @@ +

+ +

Bee API

+

+OpenAI-compatible Assistants API backed by [Bee Agent Framework](https://github.com/i-am-bee/bee-agent-framework) + +## Getting started + +1. Create `.env` (from `.env.example`) and fill in values. +2. Run `pnpm install` to install dependencies. +3. Start the server with `pnpm start:dev` + +## Technologies + +- [Fastify](https://fastify.dev/) as the web framework +- [MikroORM](https://mikro-orm.io/) backed by [MongoDB](https://www.mongodb.com/) as the database layer +- [BullMQ](https://docs.bullmq.io/guide/jobs) backed by [Redis](https://redis.io/) as the job executor +- [Bee Agent Framework](https://github.com/i-am-bee/bee-agent-framework) as the agent execution engine + +## Architecture overview + +The Assistants API consists mostly of CRUDL endpoints for managing API resources like assistants, threads, runs and more. Furthermore, some resources are asynchronous in a sense that they contain `status` changing over time as the background execution progresses. Clients use polling or streaming to watch for status updates of such resources. + +### Infrastructure + +The infrastructure consists of: +- REST API server +- MongoDB +- Redis + +The REST API server stores resources in MongoDB database. Redis is used by BullMQ, rate limiter and as pub/sub broker for event streaming. Agent execution is performed by the Bee Agent Framework using various adapters for inference and embeddings. + +### Server + +The codebase contains several types of modules: +- `*.modules.ts` containing endpoint handlers +- `*.services.ts` containing services for the handlers +- `dtos/*.ts` containing JSON schema definitions for resources +- `*.entity.ts` containing ORM definitions for database entities +- `*.queue.ts` containing BullMQ queues and workers for asynchronous execution + +These modules are connected in the following manner + +``` +module ---> dto + ---> service ---> entity + ---> queue ---> entity +``` + +OpenAPI schema is auto-generated from the `dtos` and exposed on the `/docs` endpoint. diff --git a/docs/assets/Bee_Dark.svg b/docs/assets/Bee_Dark.svg new file mode 100644 index 0000000..d80a408 --- /dev/null +++ b/docs/assets/Bee_Dark.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..d94cef9 --- /dev/null +++ b/package.json @@ -0,0 +1,122 @@ +{ + "name": "bee-api", + "version": "1.0.0", + "license": "Apache-2.0", + "author": "IBM Corp.", + "type": "module", + "scripts": { + "build": "vite build && cp -R src/embedding/adapters/caikit/grpc/protos dist/embedding/adapters/caikit/grpc/protos", + "start": "node --enable-source-maps --experimental-loader=@opentelemetry/instrumentation/hook.mjs --import ./dist/opentelemetry.js ./dist/server.js", + "start:dev": "tsx watch src/server.ts | pino-pretty --singleLine", + "start:dev:worker": "tsx watch src/jobs/worker.ts | pino-pretty --singleLine", + "start:dev:nowatch": "tsx src/server.ts | pino-pretty --singleLine", + "start:dev:worker:nowatch": "tsx src/jobs/worker.ts | pino-pretty --singleLine", + "test:e2e": "vitest run tests/e2e", + "test:e2e:watch": "vitest watch tests/e2e", + "mikro-orm": "NODE_OPTIONS='--import tsx' mikro-orm --config ./src/mikro-orm.config.ts", + "prepare": "husky", + "ts:check": "tsc --noEmit", + "grpc:generate-types": "proto-loader-gen-types --defaults --keepCase --oneofs --longs=Number --enums=String --grpcLib=@grpc/grpc-js --outDir=./src/embedding/adapters/caikit/grpc/types ./src/embedding/adapters/caikit/grpc/protos/*.proto", + "copyright": "./scripts/copyright.sh" + }, + "dependencies": { + "@appsignal/opentelemetry-instrumentation-bullmq": "^0.7.3", + "@fastify/multipart": "^8.3.0", + "@fastify/rate-limit": "^9.1.0", + "@fastify/request-context": "^5.1.0", + "@fastify/swagger": "^8.14.0", + "@fastify/swagger-ui": "^3.0.0", + "@fastify/type-provider-json-schema-to-ts": "^3.0.0", + "@godaddy/terminus": "^4.12.1", + "@grpc/grpc-js": "^1.11.1", + "@grpc/proto-loader": "^0.7.13", + "@ibm-generative-ai/node-sdk": "^3.2.3", + "@mikro-orm/core": "6.2.9", + "@mikro-orm/migrations-mongodb": "6.2.9", + "@mikro-orm/mongodb": "6.2.9", + "@mikro-orm/reflection": "6.2.9", + "@mikro-orm/seeder": "6.2.9", + "@opentelemetry/auto-instrumentations-node": "^0.50.0", + "@opentelemetry/exporter-metrics-otlp-http": "^0.53.0", + "@opentelemetry/instrumentation": "^0.53.0", + "@opentelemetry/sdk-node": "^0.53.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@zilliz/milvus2-sdk-node": "^2.4.4", + "ajv": "^8.17.1", + "axios": "^1.7.7", + "bee-agent-framework": "0.0.32", + "bee-observe-connector": "0.0.4", + "bullmq": "5.8.1", + "cache-manager": "^5.7.6", + "dayjs": "^1.11.11", + "dotenv": "^16.4.5", + "fastify": "^4.27.0", + "fastify-plugin": "^4.5.1", + "globby": "^14.0.2", + "http-proxy-agent": "^7.0.2", + "http-status-codes": "^2.3.0", + "https-proxy-agent": "^7.0.5", + "ibm-cos-sdk": "^1.13.4", + "ioredis": "^5.4.1", + "jose": "^5.6.3", + "json-schema-to-ts": "^3.1.0", + "langchain": "^0.2.16", + "mime": "^4.0.4", + "ollama": "^0.5.9", + "openai": "^4.67.3", + "openapi-fetch": "^0.10.2", + "openid-client": "^5.7.0", + "p-limit": "^6.1.0", + "pino": "^9.2.0", + "prom-client": "^15.1.3", + "remeda": "^2.2.2", + "yaml": "^2.5.0", + "yauzl": "^3.1.3", + "zod": "^3.23.8", + "zod-to-json-schema": "^3.23.1" + }, + "devDependencies": { + "@mikro-orm/cli": "6.2.9", + "@types/jsonwebtoken": "^9.0.6", + "@types/node": "^20.14.1", + "@types/yauzl": "^2.10.3", + "@typescript-eslint/eslint-plugin": "^7.13.0", + "@typescript-eslint/parser": "^7.13.0", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-import-resolver-typescript": "^3.6.1", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "glob": "^10.4.2", + "husky": "^9.0.11", + "lint-staged": "^15.2.7", + "openapi-typescript": "^7.0.2", + "pino-pretty": "^11.1.0", + "prettier": "^3.3.0", + "tsc-files": "^1.1.4", + "tsconfig-paths": "^4.2.0", + "tsx": "^4.11.2", + "typescript": "5.5.4", + "vite": "^5.2.12", + "vite-plugin-dts": "^3.9.1", + "vite-plugin-externalize-deps": "^0.8.0", + "vite-tsconfig-paths": "^4.3.2", + "vitest": "^1.6.0" + }, + "lint-staged": { + "*.{js,ts}": [ + "eslint --fix" + ], + "*.ts": [ + "tsc-files --noEmit" + ] + }, + "mikro-orm": { + "useTsNode": true, + "configPaths": [ + "./mikro-orm.config.ts", + "./dist/mikro-orm.config.js" + ] + }, + "packageManager": "pnpm@9.0.6+sha1.648f6014eb363abb36618f2ba59282a9eeb3e879" +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..d94c082 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,10404 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@appsignal/opentelemetry-instrumentation-bullmq': + specifier: ^0.7.3 + version: 0.7.3(bullmq@5.8.1) + '@fastify/multipart': + specifier: ^8.3.0 + version: 8.3.0 + '@fastify/rate-limit': + specifier: ^9.1.0 + version: 9.1.0 + '@fastify/request-context': + specifier: ^5.1.0 + version: 5.1.0 + '@fastify/swagger': + specifier: ^8.14.0 + version: 8.15.0 + '@fastify/swagger-ui': + specifier: ^3.0.0 + version: 3.1.0 + '@fastify/type-provider-json-schema-to-ts': + specifier: ^3.0.0 + version: 3.0.0(fastify@4.28.1)(json-schema-to-ts@3.1.0) + '@godaddy/terminus': + specifier: ^4.12.1 + version: 4.12.1 + '@grpc/grpc-js': + specifier: ^1.11.1 + version: 1.11.1 + '@grpc/proto-loader': + specifier: ^0.7.13 + version: 0.7.13 + '@ibm-generative-ai/node-sdk': + specifier: ^3.2.3 + version: 3.2.3(@langchain/core@0.2.23(langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8))) + '@mikro-orm/core': + specifier: 6.2.9 + version: 6.2.9 + '@mikro-orm/migrations-mongodb': + specifier: 6.2.9 + version: 6.2.9(@mikro-orm/core@6.2.9)(@types/node@20.14.15)(gcp-metadata@6.1.0) + '@mikro-orm/mongodb': + specifier: 6.2.9 + version: 6.2.9(@mikro-orm/core@6.2.9)(gcp-metadata@6.1.0) + '@mikro-orm/reflection': + specifier: 6.2.9 + version: 6.2.9(@mikro-orm/core@6.2.9) + '@mikro-orm/seeder': + specifier: 6.2.9 + version: 6.2.9(@mikro-orm/core@6.2.9) + '@opentelemetry/auto-instrumentations-node': + specifier: ^0.50.0 + version: 0.50.0(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-metrics-otlp-http': + specifier: ^0.53.0 + version: 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': + specifier: ^0.53.0 + version: 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-node': + specifier: ^0.53.0 + version: 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': + specifier: ^1.27.0 + version: 1.27.0 + '@zilliz/milvus2-sdk-node': + specifier: ^2.4.4 + version: 2.4.4 + ajv: + specifier: ^8.17.1 + version: 8.17.1 + axios: + specifier: ^1.7.7 + version: 1.7.7 + bee-agent-framework: + specifier: 0.0.32 + version: 0.0.32(@bufbuild/protobuf@1.10.0)(@googleapis/customsearch@3.2.0)(@grpc/grpc-js@1.11.1)(@grpc/proto-loader@0.7.13)(@ibm-generative-ai/node-sdk@3.2.3(@langchain/core@0.2.23(langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8))))(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(@langchain/core@0.2.23(langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8)))(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(groq-sdk@0.7.0)(ollama@0.5.9)(openai-chat-tokens@0.2.8)(openai@4.67.3(zod@3.23.8))(sequelize@6.37.3) + bee-observe-connector: + specifier: 0.0.4 + version: 0.0.4(bee-agent-framework@0.0.32(@bufbuild/protobuf@1.10.0)(@googleapis/customsearch@3.2.0)(@grpc/grpc-js@1.11.1)(@grpc/proto-loader@0.7.13)(@ibm-generative-ai/node-sdk@3.2.3(@langchain/core@0.2.23(langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8))))(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(@langchain/core@0.2.23(langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8)))(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(groq-sdk@0.7.0)(ollama@0.5.9)(openai-chat-tokens@0.2.8)(openai@4.67.3(zod@3.23.8))(sequelize@6.37.3)) + bullmq: + specifier: 5.8.1 + version: 5.8.1 + cache-manager: + specifier: ^5.7.6 + version: 5.7.6 + dayjs: + specifier: ^1.11.11 + version: 1.11.12 + dotenv: + specifier: ^16.4.5 + version: 16.4.5 + fastify: + specifier: ^4.27.0 + version: 4.28.1 + fastify-plugin: + specifier: ^4.5.1 + version: 4.5.1 + globby: + specifier: ^14.0.2 + version: 14.0.2 + http-proxy-agent: + specifier: ^7.0.2 + version: 7.0.2 + http-status-codes: + specifier: ^2.3.0 + version: 2.3.0 + https-proxy-agent: + specifier: ^7.0.5 + version: 7.0.5(supports-color@9.4.0) + ibm-cos-sdk: + specifier: ^1.13.4 + version: 1.13.4 + ioredis: + specifier: ^5.4.1 + version: 5.4.1 + jose: + specifier: ^5.6.3 + version: 5.6.3 + json-schema-to-ts: + specifier: ^3.1.0 + version: 3.1.0 + langchain: + specifier: ^0.2.16 + version: 0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)) + mime: + specifier: ^4.0.4 + version: 4.0.4 + ollama: + specifier: ^0.5.9 + version: 0.5.9 + openai: + specifier: ^4.67.3 + version: 4.67.3(zod@3.23.8) + openapi-fetch: + specifier: ^0.10.2 + version: 0.10.6 + openid-client: + specifier: ^5.7.0 + version: 5.7.0 + p-limit: + specifier: ^6.1.0 + version: 6.1.0 + pino: + specifier: ^9.2.0 + version: 9.4.0 + prom-client: + specifier: ^15.1.3 + version: 15.1.3 + remeda: + specifier: ^2.2.2 + version: 2.14.0 + yaml: + specifier: ^2.5.0 + version: 2.5.1 + yauzl: + specifier: ^3.1.3 + version: 3.1.3 + zod: + specifier: ^3.23.8 + version: 3.23.8 + zod-to-json-schema: + specifier: ^3.23.1 + version: 3.23.3(zod@3.23.8) + devDependencies: + '@mikro-orm/cli': + specifier: 6.2.9 + version: 6.2.9 + '@types/jsonwebtoken': + specifier: ^9.0.6 + version: 9.0.6 + '@types/node': + specifier: ^20.14.1 + version: 20.14.15 + '@types/yauzl': + specifier: ^2.10.3 + version: 2.10.3 + '@typescript-eslint/eslint-plugin': + specifier: ^7.13.0 + version: 7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0)(typescript@5.5.4) + '@typescript-eslint/parser': + specifier: ^7.13.0 + version: 7.18.0(eslint@8.57.0)(typescript@5.5.4) + eslint: + specifier: ^8.56.0 + version: 8.57.0 + eslint-config-prettier: + specifier: ^9.1.0 + version: 9.1.0(eslint@8.57.0) + eslint-import-resolver-typescript: + specifier: ^3.6.1 + version: 3.6.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@8.57.0) + eslint-plugin-import: + specifier: ^2.29.1 + version: 2.29.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + eslint-plugin-prettier: + specifier: ^5.1.3 + version: 5.2.1(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.3.3) + glob: + specifier: ^10.4.2 + version: 10.4.5 + husky: + specifier: ^9.0.11 + version: 9.1.4 + lint-staged: + specifier: ^15.2.7 + version: 15.2.10 + openapi-typescript: + specifier: ^7.0.2 + version: 7.4.1(typescript@5.5.4) + pino-pretty: + specifier: ^11.1.0 + version: 11.2.2 + prettier: + specifier: ^3.3.0 + version: 3.3.3 + tsc-files: + specifier: ^1.1.4 + version: 1.1.4(typescript@5.5.4) + tsconfig-paths: + specifier: ^4.2.0 + version: 4.2.0 + tsx: + specifier: ^4.11.2 + version: 4.19.1 + typescript: + specifier: 5.5.4 + version: 5.5.4 + vite: + specifier: ^5.2.12 + version: 5.4.8(@types/node@20.14.15) + vite-plugin-dts: + specifier: ^3.9.1 + version: 3.9.1(@types/node@20.14.15)(rollup@4.22.4)(typescript@5.5.4)(vite@5.4.8(@types/node@20.14.15)) + vite-plugin-externalize-deps: + specifier: ^0.8.0 + version: 0.8.0(vite@5.4.8(@types/node@20.14.15)) + vite-tsconfig-paths: + specifier: ^4.3.2 + version: 4.3.2(typescript@5.5.4)(vite@5.4.8(@types/node@20.14.15)) + vitest: + specifier: ^1.6.0 + version: 1.6.0(@types/node@20.14.15) + +packages: + + '@ai-zen/node-fetch-event-source@2.1.4': + resolution: {integrity: sha512-OHFwPJecr+qwlyX5CGmTvKAKPZAdZaxvx/XDqS1lx4I2ZAk9riU0XnEaRGOOAEFrdcLZ98O5yWqubwjaQc0umg==} + + '@apidevtools/json-schema-ref-parser@11.7.2': + resolution: {integrity: sha512-4gY54eEGEstClvEkGnwVkTkrx0sqwemEFG5OSRRn3tD91XH0+Q8XIkYIfo7IwEWPpJZwILb9GUXeShtplRc/eA==} + engines: {node: '>= 16'} + + '@appsignal/opentelemetry-instrumentation-bullmq@0.7.3': + resolution: {integrity: sha512-BSkrRNu7nfywkY+GDXDTCE4U8wUtF95hHvtFjFzwoFH0fsMRY+IFjwHlNLC6b4+YavJEs2ykSqVgy4GM7hLE+Q==} + peerDependencies: + bullmq: ^2 || ^3 || ^4 || ^5 + peerDependenciesMeta: + bullmq: + optional: true + + '@babel/code-frame@7.24.7': + resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.24.8': + resolution: {integrity: sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.24.7': + resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} + engines: {node: '>=6.9.0'} + + '@babel/highlight@7.24.7': + resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.25.3': + resolution: {integrity: sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/runtime@7.25.0': + resolution: {integrity: sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==} + engines: {node: '>=6.9.0'} + + '@babel/runtime@7.25.7': + resolution: {integrity: sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.25.2': + resolution: {integrity: sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==} + engines: {node: '>=6.9.0'} + + '@bufbuild/protobuf@1.10.0': + resolution: {integrity: sha512-QDdVFLoN93Zjg36NoQPZfsVH9tZew7wKDKyV5qRdj8ntT4wQCOradQjRaTdwMhWUYsgKsvCINKKm87FdEk96Ag==} + + '@colors/colors@1.6.0': + resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} + engines: {node: '>=0.1.90'} + + '@connectrpc/connect-node@1.6.1': + resolution: {integrity: sha512-DxcD1wsF/aX9GegjAtl7VbpiZNjVJozy87VbaFoN6AF0Ln1Q757r5dgV59Gz0wmlk5f17txUsrEr1f2inlnnAg==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@bufbuild/protobuf': ^1.10.0 + '@connectrpc/connect': 1.6.1 + + '@connectrpc/connect@1.6.1': + resolution: {integrity: sha512-KchMDNtU4CDTdkyf0qG7ugJ6qHTOR/aI7XebYn3OTCNagaDYWiZUVKgRgwH79yeMkpNgvEUaXSK7wKjaBK9b/Q==} + peerDependencies: + '@bufbuild/protobuf': ^1.10.0 + + '@dabh/diagnostics@2.0.3': + resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==} + + '@esbuild/aix-ppc64@0.21.5': + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + + '@esbuild/aix-ppc64@0.23.0': + resolution: {integrity: sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.21.5': + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm64@0.23.0': + resolution: {integrity: sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.21.5': + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-arm@0.23.0': + resolution: {integrity: sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.21.5': + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/android-x64@0.23.0': + resolution: {integrity: sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.21.5': + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-arm64@0.23.0': + resolution: {integrity: sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.21.5': + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/darwin-x64@0.23.0': + resolution: {integrity: sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.21.5': + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-arm64@0.23.0': + resolution: {integrity: sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.21.5': + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.23.0': + resolution: {integrity: sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.21.5': + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm64@0.23.0': + resolution: {integrity: sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.21.5': + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-arm@0.23.0': + resolution: {integrity: sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.21.5': + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-ia32@0.23.0': + resolution: {integrity: sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.21.5': + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-loong64@0.23.0': + resolution: {integrity: sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.21.5': + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-mips64el@0.23.0': + resolution: {integrity: sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.21.5': + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-ppc64@0.23.0': + resolution: {integrity: sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.21.5': + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-riscv64@0.23.0': + resolution: {integrity: sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.21.5': + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-s390x@0.23.0': + resolution: {integrity: sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.21.5': + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/linux-x64@0.23.0': + resolution: {integrity: sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-x64@0.21.5': + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.23.0': + resolution: {integrity: sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.23.0': + resolution: {integrity: sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.21.5': + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.23.0': + resolution: {integrity: sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.21.5': + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/sunos-x64@0.23.0': + resolution: {integrity: sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.21.5': + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-arm64@0.23.0': + resolution: {integrity: sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.21.5': + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-ia32@0.23.0': + resolution: {integrity: sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.21.5': + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@esbuild/win32-x64@0.23.0': + resolution: {integrity: sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-utils@4.4.0': + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.11.0': + resolution: {integrity: sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/eslintrc@2.1.4': + resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@eslint/js@8.57.0': + resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@fastify/accept-negotiator@1.1.0': + resolution: {integrity: sha512-OIHZrb2ImZ7XG85HXOONLcJWGosv7sIvM2ifAPQVhg9Lv7qdmMBNVaai4QTdyuaqbKM5eO6sLSQOYI7wEQeCJQ==} + engines: {node: '>=14'} + + '@fastify/ajv-compiler@3.6.0': + resolution: {integrity: sha512-LwdXQJjmMD+GwLOkP7TVC68qa+pSSogeWWmznRJ/coyTcfe9qA05AHFSe1eZFwK6q+xVRpChnvFUkf1iYaSZsQ==} + + '@fastify/busboy@2.1.1': + resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} + engines: {node: '>=14'} + + '@fastify/deepmerge@1.3.0': + resolution: {integrity: sha512-J8TOSBq3SoZbDhM9+R/u77hP93gz/rajSA+K2kGyijPpORPWUXHUpTaleoj+92As0S9uPRP7Oi8IqMf0u+ro6A==} + + '@fastify/error@3.4.1': + resolution: {integrity: sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ==} + + '@fastify/fast-json-stringify-compiler@4.3.0': + resolution: {integrity: sha512-aZAXGYo6m22Fk1zZzEUKBvut/CIIQe/BapEORnxiD5Qr0kPHqqI69NtEMCme74h+at72sPhbkb4ZrLd1W3KRLA==} + + '@fastify/merge-json-schemas@0.1.1': + resolution: {integrity: sha512-fERDVz7topgNjtXsJTTW1JKLy0rhuLRcquYqNR9rF7OcVpCa2OVW49ZPDIhaRRCaUuvVxI+N416xUoF76HNSXA==} + + '@fastify/multipart@8.3.0': + resolution: {integrity: sha512-A8h80TTyqUzaMVH0Cr9Qcm6RxSkVqmhK/MVBYHYeRRSUbUYv08WecjWKSlG2aSnD4aGI841pVxAjC+G1GafUeQ==} + + '@fastify/rate-limit@9.1.0': + resolution: {integrity: sha512-h5dZWCkuZXN0PxwqaFQLxeln8/LNwQwH9popywmDCFdKfgpi4b/HoMH1lluy6P+30CG9yzzpSpwTCIPNB9T1JA==} + + '@fastify/request-context@5.1.0': + resolution: {integrity: sha512-PM7wrLJOEylVDpxabOFLaYsdAiaa0lpDUcP2HMFJ1JzgiWuC6k4r3duf6Pm9YLnzlGmT+Yp4tkQjqsu7V/pSOA==} + + '@fastify/send@2.1.0': + resolution: {integrity: sha512-yNYiY6sDkexoJR0D8IDy3aRP3+L4wdqCpvx5WP+VtEU58sn7USmKynBzDQex5X42Zzvw2gNzzYgP90UfWShLFA==} + + '@fastify/static@7.0.4': + resolution: {integrity: sha512-p2uKtaf8BMOZWLs6wu+Ihg7bWNBdjNgCwDza4MJtTqg+5ovKmcbgbR9Xs5/smZ1YISfzKOCNYmZV8LaCj+eJ1Q==} + + '@fastify/swagger-ui@3.1.0': + resolution: {integrity: sha512-68jm6k8VzvHXkEBT4Dakm/kkzUlPO4POIi0agWJSWxsYichPBqzjo+IpfqPl4pSJR1zCToQhEOo+cv+yJL2qew==} + + '@fastify/swagger@8.15.0': + resolution: {integrity: sha512-zy+HEEKFqPMS2sFUsQU5X0MHplhKJvWeohBwTCkBAJA/GDYGLGUWQaETEhptiqxK7Hs0fQB9B4MDb3pbwIiCwA==} + + '@fastify/type-provider-json-schema-to-ts@3.0.0': + resolution: {integrity: sha512-xYU+a21K5IWsXsvDHNzTqwiWVxVbOldzUvNqnj+kFG5TihCZ00g3ODMbu8v6Nj66hBuzOrAz7agVqhgsH3hzGA==} + peerDependencies: + fastify: ^4.25.2 + json-schema-to-ts: ^3.0.0 + + '@godaddy/terminus@4.12.1': + resolution: {integrity: sha512-Tm+wVu1/V37uZXcT7xOhzdpFoovQReErff8x3y82k6YyWa1gzxWBjTyrx4G2enjEqoXPnUUmJ3MOmwH+TiP6Sw==} + + '@googleapis/customsearch@3.2.0': + resolution: {integrity: sha512-NTS4S3YepwYTqvk3aYKzm6g7oXjE7rQjswoXtw4leX7ykpyu2GWwflW6haaqctZHj6IJbJ1k0xgbgLTn1BByYQ==} + engines: {node: '>=12.0.0'} + + '@grpc/grpc-js@1.11.1': + resolution: {integrity: sha512-gyt/WayZrVPH2w/UTLansS7F9Nwld472JxxaETamrM8HNlsa+jSLNyKAZmhxI2Me4c3mQHFiS1wWHDY1g1Kthw==} + engines: {node: '>=12.10.0'} + + '@grpc/proto-loader@0.7.13': + resolution: {integrity: sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==} + engines: {node: '>=6'} + hasBin: true + + '@humanwhocodes/config-array@0.11.14': + resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} + engines: {node: '>=10.10.0'} + deprecated: Use @eslint/config-array instead + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/object-schema@2.0.3': + resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} + deprecated: Use @eslint/object-schema instead + + '@ibm-generative-ai/node-sdk@3.2.3': + resolution: {integrity: sha512-3RNvxg7655d/zZfjMqrL54QHbVMaEiErJGbO//KWumRDzCWdq0RTus12Ml7QL5c4/XwJsX5yr6ZV8RRHH6OBXg==} + peerDependencies: + '@langchain/core': '>=0.1.0' + + '@ioredis/commands@1.2.0': + resolution: {integrity: sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@jercle/yargonaut@1.1.5': + resolution: {integrity: sha512-zBp2myVvBHp1UaJsNTyS6q4UDKT7eRiqTS4oNTS6VQMd6mpxYOdbeK4pY279cDCdakGy6hG0J3ejoXZVsPwHqw==} + + '@jest/schemas@29.6.3': + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@js-sdsl/ordered-map@4.4.2': + resolution: {integrity: sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==} + + '@jsdevtools/ono@7.1.3': + resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==} + + '@langchain/community@0.2.28': + resolution: {integrity: sha512-O0O52kQ2cVw31XFMU2RcD+PGEhcsUk4KFgCvJTtbU3IFox5Cyc1+I/y8vkmuD+MyI0ES08OQN5ctUdh0kONl0g==} + engines: {node: '>=18'} + peerDependencies: + '@aws-crypto/sha256-js': ^5.0.0 + '@aws-sdk/client-bedrock-agent-runtime': ^3.583.0 + '@aws-sdk/client-bedrock-runtime': ^3.422.0 + '@aws-sdk/client-dynamodb': ^3.310.0 + '@aws-sdk/client-kendra': ^3.352.0 + '@aws-sdk/client-lambda': ^3.310.0 + '@aws-sdk/client-s3': ^3.310.0 + '@aws-sdk/client-sagemaker-runtime': ^3.310.0 + '@aws-sdk/client-sfn': ^3.310.0 + '@aws-sdk/credential-provider-node': ^3.388.0 + '@azure/search-documents': ^12.0.0 + '@azure/storage-blob': ^12.15.0 + '@browserbasehq/sdk': '*' + '@clickhouse/client': ^0.2.5 + '@cloudflare/ai': '*' + '@datastax/astra-db-ts': ^1.0.0 + '@elastic/elasticsearch': ^8.4.0 + '@getmetal/metal-sdk': '*' + '@getzep/zep-cloud': ^1.0.6 + '@getzep/zep-js': ^0.9.0 + '@gomomento/sdk': ^1.51.1 + '@gomomento/sdk-core': ^1.51.1 + '@google-ai/generativelanguage': '*' + '@google-cloud/storage': ^6.10.1 || ^7.7.0 + '@gradientai/nodejs-sdk': ^1.2.0 + '@huggingface/inference': ^2.6.4 + '@langchain/langgraph': ~0.0.26 + '@layerup/layerup-security': ^1.5.12 + '@mendable/firecrawl-js': ^0.0.13 + '@mlc-ai/web-llm': 0.2.46 + '@mozilla/readability': '*' + '@neondatabase/serverless': '*' + '@notionhq/client': ^2.2.10 + '@opensearch-project/opensearch': '*' + '@pinecone-database/pinecone': '*' + '@planetscale/database': ^1.8.0 + '@premai/prem-sdk': ^0.3.25 + '@qdrant/js-client-rest': ^1.8.2 + '@raycast/api': ^1.55.2 + '@rockset/client': ^0.9.1 + '@smithy/eventstream-codec': ^2.0.5 + '@smithy/protocol-http': ^3.0.6 + '@smithy/signature-v4': ^2.0.10 + '@smithy/util-utf8': ^2.0.0 + '@spider-cloud/spider-client': ^0.0.21 + '@supabase/supabase-js': ^2.45.0 + '@tensorflow-models/universal-sentence-encoder': '*' + '@tensorflow/tfjs-converter': '*' + '@tensorflow/tfjs-core': '*' + '@upstash/ratelimit': ^1.1.3 + '@upstash/redis': ^1.20.6 + '@upstash/vector': ^1.1.1 + '@vercel/kv': ^0.2.3 + '@vercel/postgres': ^0.5.0 + '@writerai/writer-sdk': ^0.40.2 + '@xata.io/client': ^0.28.0 + '@xenova/transformers': ^2.17.2 + '@zilliz/milvus2-sdk-node': '>=2.3.5' + apify-client: ^2.7.1 + assemblyai: ^4.6.0 + better-sqlite3: '>=9.4.0 <12.0.0' + cassandra-driver: ^4.7.2 + cborg: ^4.1.1 + cheerio: ^1.0.0-rc.12 + chromadb: '*' + closevector-common: 0.1.3 + closevector-node: 0.1.6 + closevector-web: 0.1.6 + cohere-ai: '*' + convex: ^1.3.1 + couchbase: ^4.3.0 + crypto-js: ^4.2.0 + d3-dsv: ^2.0.0 + discord.js: ^14.14.1 + dria: ^0.0.3 + duck-duck-scrape: ^2.2.5 + epub2: ^3.0.1 + faiss-node: ^0.5.1 + firebase-admin: ^11.9.0 || ^12.0.0 + google-auth-library: '*' + googleapis: '*' + hnswlib-node: ^3.0.0 + html-to-text: ^9.0.5 + ignore: ^5.2.0 + interface-datastore: ^8.2.11 + ioredis: ^5.3.2 + it-all: ^3.0.4 + jsdom: '*' + jsonwebtoken: ^9.0.2 + llmonitor: ^0.5.9 + lodash: ^4.17.21 + lunary: ^0.7.10 + mammoth: ^1.6.0 + mongodb: '>=5.2.0' + mysql2: ^3.9.8 + neo4j-driver: '*' + node-llama-cpp: '*' + notion-to-md: ^3.1.0 + officeparser: ^4.0.4 + pdf-parse: 1.1.1 + pg: ^8.11.0 + pg-copy-streams: ^6.0.5 + pickleparser: ^0.2.1 + playwright: ^1.32.1 + portkey-ai: ^0.1.11 + puppeteer: '*' + redis: '*' + replicate: ^0.29.4 + sonix-speech-recognition: ^2.1.1 + srt-parser-2: ^1.2.3 + typeorm: ^0.3.20 + typesense: ^1.5.3 + usearch: ^1.1.1 + vectordb: ^0.1.4 + voy-search: 0.6.2 + weaviate-ts-client: '*' + web-auth-library: ^1.0.3 + ws: ^8.14.2 + youtube-transcript: ^1.0.6 + youtubei.js: ^9.1.0 + peerDependenciesMeta: + '@aws-crypto/sha256-js': + optional: true + '@aws-sdk/client-bedrock-agent-runtime': + optional: true + '@aws-sdk/client-bedrock-runtime': + optional: true + '@aws-sdk/client-dynamodb': + optional: true + '@aws-sdk/client-kendra': + optional: true + '@aws-sdk/client-lambda': + optional: true + '@aws-sdk/client-s3': + optional: true + '@aws-sdk/client-sagemaker-runtime': + optional: true + '@aws-sdk/client-sfn': + optional: true + '@aws-sdk/credential-provider-node': + optional: true + '@azure/search-documents': + optional: true + '@azure/storage-blob': + optional: true + '@browserbasehq/sdk': + optional: true + '@clickhouse/client': + optional: true + '@cloudflare/ai': + optional: true + '@datastax/astra-db-ts': + optional: true + '@elastic/elasticsearch': + optional: true + '@getmetal/metal-sdk': + optional: true + '@getzep/zep-cloud': + optional: true + '@getzep/zep-js': + optional: true + '@gomomento/sdk': + optional: true + '@gomomento/sdk-core': + optional: true + '@google-ai/generativelanguage': + optional: true + '@google-cloud/storage': + optional: true + '@gradientai/nodejs-sdk': + optional: true + '@huggingface/inference': + optional: true + '@langchain/langgraph': + optional: true + '@layerup/layerup-security': + optional: true + '@mendable/firecrawl-js': + optional: true + '@mlc-ai/web-llm': + optional: true + '@mozilla/readability': + optional: true + '@neondatabase/serverless': + optional: true + '@notionhq/client': + optional: true + '@opensearch-project/opensearch': + optional: true + '@pinecone-database/pinecone': + optional: true + '@planetscale/database': + optional: true + '@premai/prem-sdk': + optional: true + '@qdrant/js-client-rest': + optional: true + '@raycast/api': + optional: true + '@rockset/client': + optional: true + '@smithy/eventstream-codec': + optional: true + '@smithy/protocol-http': + optional: true + '@smithy/signature-v4': + optional: true + '@smithy/util-utf8': + optional: true + '@spider-cloud/spider-client': + optional: true + '@supabase/supabase-js': + optional: true + '@tensorflow-models/universal-sentence-encoder': + optional: true + '@tensorflow/tfjs-converter': + optional: true + '@tensorflow/tfjs-core': + optional: true + '@upstash/ratelimit': + optional: true + '@upstash/redis': + optional: true + '@upstash/vector': + optional: true + '@vercel/kv': + optional: true + '@vercel/postgres': + optional: true + '@writerai/writer-sdk': + optional: true + '@xata.io/client': + optional: true + '@xenova/transformers': + optional: true + '@zilliz/milvus2-sdk-node': + optional: true + apify-client: + optional: true + assemblyai: + optional: true + better-sqlite3: + optional: true + cassandra-driver: + optional: true + cborg: + optional: true + cheerio: + optional: true + chromadb: + optional: true + closevector-common: + optional: true + closevector-node: + optional: true + closevector-web: + optional: true + cohere-ai: + optional: true + convex: + optional: true + couchbase: + optional: true + crypto-js: + optional: true + d3-dsv: + optional: true + discord.js: + optional: true + dria: + optional: true + duck-duck-scrape: + optional: true + epub2: + optional: true + faiss-node: + optional: true + firebase-admin: + optional: true + google-auth-library: + optional: true + googleapis: + optional: true + hnswlib-node: + optional: true + html-to-text: + optional: true + ignore: + optional: true + interface-datastore: + optional: true + ioredis: + optional: true + it-all: + optional: true + jsdom: + optional: true + jsonwebtoken: + optional: true + llmonitor: + optional: true + lodash: + optional: true + lunary: + optional: true + mammoth: + optional: true + mongodb: + optional: true + mysql2: + optional: true + neo4j-driver: + optional: true + node-llama-cpp: + optional: true + notion-to-md: + optional: true + officeparser: + optional: true + pdf-parse: + optional: true + pg: + optional: true + pg-copy-streams: + optional: true + pickleparser: + optional: true + playwright: + optional: true + portkey-ai: + optional: true + puppeteer: + optional: true + redis: + optional: true + replicate: + optional: true + sonix-speech-recognition: + optional: true + srt-parser-2: + optional: true + typeorm: + optional: true + typesense: + optional: true + usearch: + optional: true + vectordb: + optional: true + voy-search: + optional: true + weaviate-ts-client: + optional: true + web-auth-library: + optional: true + ws: + optional: true + youtube-transcript: + optional: true + youtubei.js: + optional: true + + '@langchain/core@0.2.23': + resolution: {integrity: sha512-elPg6WpAkxWEIGC9u38F2anbzqfYYEy32lJdsd9dtChcHSFmFLlXqa+SnpO3R772gUuJmcu+Pd+fCvmRFy029w==} + engines: {node: '>=18'} + + '@langchain/core@0.2.33': + resolution: {integrity: sha512-8WMied0Y5c4YDUjvoQqr/M63jAuZ3e+YqCAaszeGeBJbsHFoCdj8Ppr/yP6moAvsLImntxUXC6BxqAIDYkpGkg==} + engines: {node: '>=18'} + + '@langchain/langgraph@0.0.34': + resolution: {integrity: sha512-cuig46hGmZkf+eXw1Cx2CtkAWgsAbIpa5ABLxn9oe1rbtvHXmfekqHZA6tGE0DipEmsN4H64zFcDEJydll6Sdw==} + engines: {node: '>=18'} + peerDependencies: + better-sqlite3: ^9.5.0 + peerDependenciesMeta: + better-sqlite3: + optional: true + + '@langchain/openai@0.2.11': + resolution: {integrity: sha512-Pu8+WfJojCgSf0bAsXb4AjqvcDyAWyoEB1AoCRNACgEnBWZuitz3hLwCo9I+6hAbeg3QJ37g82yKcmvKAg1feg==} + engines: {node: '>=18'} + + '@langchain/openai@0.2.6': + resolution: {integrity: sha512-LZgSzHOZPJGsZr2ZXJICqZo1GN0kUyP9/RN+T45g7HDdMRfS5Df7fJgY9w7EIfznT83Q0Ywhz+At/UvWMR3xhw==} + engines: {node: '>=18'} + + '@langchain/textsplitters@0.0.3': + resolution: {integrity: sha512-cXWgKE3sdWLSqAa8ykbCcUsUF1Kyr5J3HOWYGuobhPEycXW4WI++d5DhzdpL238mzoEXTi90VqfSCra37l5YqA==} + engines: {node: '>=18'} + + '@lukeed/ms@2.0.2': + resolution: {integrity: sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==} + engines: {node: '>=8'} + + '@microsoft/api-extractor-model@7.28.13': + resolution: {integrity: sha512-39v/JyldX4MS9uzHcdfmjjfS6cYGAoXV+io8B5a338pkHiSt+gy2eXQ0Q7cGFJ7quSa1VqqlMdlPrB6sLR/cAw==} + + '@microsoft/api-extractor@7.43.0': + resolution: {integrity: sha512-GFhTcJpB+MI6FhvXEI9b2K0snulNLWHqC/BbcJtyNYcKUiw7l3Lgis5ApsYncJ0leALX7/of4XfmXk+maT111w==} + hasBin: true + + '@microsoft/tsdoc-config@0.16.2': + resolution: {integrity: sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==} + + '@microsoft/tsdoc@0.14.2': + resolution: {integrity: sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==} + + '@mikro-orm/cli@6.2.9': + resolution: {integrity: sha512-9eW9ZSzdO03KBkUn5Q0OxWBv/2RrKDwOabW2FKzuWslOY3ZBX+k+e8eP6a/+T8GeGGD/uqj8xVZSgM2DuGGqrw==} + engines: {node: '>= 18.12.0'} + hasBin: true + + '@mikro-orm/core@6.2.9': + resolution: {integrity: sha512-fzeg8qNwNr0f9embDhs0L75EBC8ivIOsK1GGPXe48Ab+P0Vmv1qCskSP7/vNDsz4s1xDu0h0l6fIsv1N7j4jKQ==} + engines: {node: '>= 18.12.0'} + + '@mikro-orm/knex@6.2.9': + resolution: {integrity: sha512-eSHPiS5em+RGv/jx5lP7a1xDVVlnrG+l90/7N7WAgTGcPOzyILVw9EJOZl2KR8dh8EfPI6Wm35Lo4qkO2LoDUg==} + engines: {node: '>= 18.12.0'} + peerDependencies: + '@mikro-orm/core': ^6.0.0 + better-sqlite3: '*' + libsql: '*' + mariadb: '*' + peerDependenciesMeta: + better-sqlite3: + optional: true + libsql: + optional: true + mariadb: + optional: true + + '@mikro-orm/migrations-mongodb@6.2.9': + resolution: {integrity: sha512-QmTApyWLuFEDj4sX60fbNduyytWemBA7E3K/4DWBzKKI0qVKl38x/GEFeMV2TFepVPqL44ZbMeVb6xCh9tGIXg==} + engines: {node: '>= 18.12.0'} + peerDependencies: + '@mikro-orm/core': ^6.0.0 + + '@mikro-orm/mongodb@6.2.9': + resolution: {integrity: sha512-ryFIFZVMwmlAW7p+/rmvIHZP2cpQ01h8bXvgZw0ri5rqXWHpTg+eQliaXlxum2yJdUSFNK4pjPvS2gyYcph+Sw==} + engines: {node: '>= 18.12.0'} + peerDependencies: + '@mikro-orm/core': ^6.0.0 + + '@mikro-orm/reflection@6.2.9': + resolution: {integrity: sha512-JkdQnEohwngC1LiNNB+tt0ReDiCMlTAJA4/n5N4+tdSv8aspgrIX8ARgB2a6IjgWwes7xIkJJ1nb5tWdFwPSmA==} + engines: {node: '>= 18.12.0'} + peerDependencies: + '@mikro-orm/core': ^6.0.0 + + '@mikro-orm/seeder@6.2.9': + resolution: {integrity: sha512-lmuAe/yXIzjFuYpIxnkcCL0/ZZLXbhmcpdXeYhQW79rYZbZ1WMref9m5EwbOjFtHlrPn73OLSF9ZeXQcF4Rn0g==} + engines: {node: '>= 18.12.0'} + peerDependencies: + '@mikro-orm/core': ^6.0.0 + + '@mixmark-io/domino@2.2.0': + resolution: {integrity: sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==} + + '@mongodb-js/saslprep@1.1.8': + resolution: {integrity: sha512-qKwC/M/nNNaKUBMQ0nuzm47b7ZYWQHN3pcXq4IIcoSBc2hOIrflAxJduIvvqmhoz3gR2TacTAs8vlsCVPkiEdQ==} + + '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3': + resolution: {integrity: sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==} + cpu: [arm64] + os: [darwin] + + '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3': + resolution: {integrity: sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==} + cpu: [x64] + os: [darwin] + + '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3': + resolution: {integrity: sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==} + cpu: [arm64] + os: [linux] + + '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3': + resolution: {integrity: sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==} + cpu: [arm] + os: [linux] + + '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3': + resolution: {integrity: sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==} + cpu: [x64] + os: [linux] + + '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3': + resolution: {integrity: sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==} + cpu: [x64] + os: [win32] + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@opentelemetry/api-logs@0.52.1': + resolution: {integrity: sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==} + engines: {node: '>=14'} + + '@opentelemetry/api-logs@0.53.0': + resolution: {integrity: sha512-8HArjKx+RaAI8uEIgcORbZIPklyh1YLjPSBus8hjRmvLi6DeFzgOcdZ7KwPabKj8mXF8dX0hyfAyGfycz0DbFw==} + engines: {node: '>=14'} + + '@opentelemetry/api@1.9.0': + resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} + engines: {node: '>=8.0.0'} + + '@opentelemetry/auto-instrumentations-node@0.50.0': + resolution: {integrity: sha512-LqoSiWrOM4Cnr395frDHL4R/o5c2fuqqrqW8sZwhxvkasImmVlyL66YMPHllM2O5xVj2nP2ANUKHZSd293meZA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.4.1 + + '@opentelemetry/context-async-hooks@1.26.0': + resolution: {integrity: sha512-HedpXXYzzbaoutw6DFLWLDket2FwLkLpil4hGCZ1xYEIMTcivdfwEOISgdbLEWyG3HW52gTq2V9mOVJrONgiwg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/core@1.26.0': + resolution: {integrity: sha512-1iKxXXE8415Cdv0yjG3G6hQnB5eVEsJce3QaawX8SjDn0mAS0ZM8fAbZZJD4ajvhC15cePvosSCut404KrIIvQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/exporter-logs-otlp-grpc@0.53.0': + resolution: {integrity: sha512-x5ygAQgWAQOI+UOhyV3z9eW7QU2dCfnfOuIBiyYmC2AWr74f6x/3JBnP27IAcEx6aihpqBYWKnpoUTztkVPAZw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/exporter-logs-otlp-http@0.53.0': + resolution: {integrity: sha512-cSRKgD/n8rb+Yd+Cif6EnHEL/VZg1o8lEcEwFji1lwene6BdH51Zh3feAD9p2TyVoBKrl6Q9Zm2WltSp2k9gWQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/exporter-logs-otlp-proto@0.53.0': + resolution: {integrity: sha512-jhEcVL1deeWNmTUP05UZMriZPSWUBcfg94ng7JuBb1q2NExgnADQFl1VQQ+xo62/JepK+MxQe4xAwlsDQFbISA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/exporter-metrics-otlp-http@0.53.0': + resolution: {integrity: sha512-nvZtOk23pZOrTW10Za2WPd9pk4tWDvL6ALlHRFfInpcTjtOgCrv+fQDxpzosa5PeXvYeFFUO5aYCTnwiCX4Dzg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/exporter-trace-otlp-grpc@0.53.0': + resolution: {integrity: sha512-m6KSh6OBDwfDjpzPVbuJbMgMbkoZfpxYH2r262KckgX9cMYvooWXEKzlJYsNDC6ADr28A1rtRoUVRwNfIN4tUg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/exporter-trace-otlp-http@0.53.0': + resolution: {integrity: sha512-m7F5ZTq+V9mKGWYpX8EnZ7NjoqAU7VemQ1E2HAG+W/u0wpY1x0OmbxAXfGKFHCspdJk8UKlwPGrpcB8nay3P8A==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/exporter-trace-otlp-proto@0.53.0': + resolution: {integrity: sha512-T/bdXslwRKj23S96qbvGtaYOdfyew3TjPEKOk5mHjkCmkVl1O9C/YMdejwSsdLdOq2YW30KjR9kVi0YMxZushQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/exporter-zipkin@1.26.0': + resolution: {integrity: sha512-PW5R34n3SJHO4t0UetyHKiXL6LixIqWN6lWncg3eRXhKuT30x+b7m5sDJS0kEWRfHeS+kG7uCw2vBzmB2lk3Dw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/instrumentation-amqplib@0.42.0': + resolution: {integrity: sha512-fiuU6OKsqHJiydHWgTRQ7MnIrJ2lEqsdgFtNIH4LbAUJl/5XmrIeoDzDnox+hfkgWK65jsleFuQDtYb5hW1koQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-aws-lambda@0.44.0': + resolution: {integrity: sha512-6vmr7FJIuopZzsQjEQTp4xWtF6kBp7DhD7pPIN8FN0dKUKyuVraABIpgWjMfelaUPy4rTYUGkYqPluhG0wx8Dw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-aws-sdk@0.44.0': + resolution: {integrity: sha512-HIWFg4TDQsayceiikOnruMmyQ0SZYW6WiR+wknWwWVLHC3lHTCpAnqzp5V42ckArOdlwHZu2Jvq2GMSM4Myx3w==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-bunyan@0.41.0': + resolution: {integrity: sha512-NoQS+gcwQ7pzb2PZFyra6bAxDAVXBMmpKxBblEuXJWirGrAksQllg9XTdmqhrwT/KxUYrbVca/lMams7e51ysg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-cassandra-driver@0.41.0': + resolution: {integrity: sha512-hvTNcC8qjCQEHZTLAlTmDptjsEGqCKpN+90hHH8Nn/GwilGr5TMSwGrlfstdJuZWyw8HAnRUed6bcjvmHHk2Xw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-connect@0.39.0': + resolution: {integrity: sha512-pGBiKevLq7NNglMgqzmeKczF4XQMTOUOTkK8afRHMZMnrK3fcETyTH7lVaSozwiOM3Ws+SuEmXZT7DYrrhxGlg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-cucumber@0.9.0': + resolution: {integrity: sha512-4PQNFnIqnA2WM3ZHpr0xhZpHSqJ5xJ6ppTIzZC7wPqe+ZBpj41vG8B6ieqiPfq+im4QdqbYnzLb3rj48GDEN9g==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/instrumentation-dataloader@0.12.0': + resolution: {integrity: sha512-pnPxatoFE0OXIZDQhL2okF//dmbiWFzcSc8pUg9TqofCLYZySSxDCgQc69CJBo5JnI3Gz1KP+mOjS4WAeRIH4g==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-dns@0.39.0': + resolution: {integrity: sha512-+iPzvXqVdJa67QBuz2tuP0UI3LS1/cMMo6dS7360DDtOQX+sQzkiN+mo3Omn4T6ZRhkTDw6c7uwsHBcmL31+1g==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-express@0.42.0': + resolution: {integrity: sha512-YNcy7ZfGnLsVEqGXQPT+S0G1AE46N21ORY7i7yUQyfhGAL4RBjnZUqefMI0NwqIl6nGbr1IpF0rZGoN8Q7x12Q==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-fastify@0.39.0': + resolution: {integrity: sha512-SS9uSlKcsWZabhBp2szErkeuuBDgxOUlllwkS92dVaWRnMmwysPhcEgHKB8rUe3BHg/GnZC1eo1hbTZv4YhfoA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-fs@0.15.0': + resolution: {integrity: sha512-JWVKdNLpu1skqZQA//jKOcKdJC66TWKqa2FUFq70rKohvaSq47pmXlnabNO+B/BvLfmidfiaN35XakT5RyMl2Q==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-generic-pool@0.39.0': + resolution: {integrity: sha512-y4v8Y+tSfRB3NNBvHjbjrn7rX/7sdARG7FuK6zR8PGb28CTa0kHpEGCJqvL9L8xkTNvTXo+lM36ajFGUaK1aNw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-graphql@0.43.0': + resolution: {integrity: sha512-aI3YMmC2McGd8KW5du1a2gBA0iOMOGLqg4s9YjzwbjFwjlmMNFSK1P3AIg374GWg823RPUGfVTIgZ/juk9CVOA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-grpc@0.53.0': + resolution: {integrity: sha512-Ss338T92yE1UCgr9zXSY3cPuaAy27uQw+wAC5IwsQKCXL5wwkiOgkd+2Ngksa9EGsgUEMwGeHi76bDdHFJ5Rrw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-hapi@0.41.0': + resolution: {integrity: sha512-jKDrxPNXDByPlYcMdZjNPYCvw0SQJjN+B1A+QH+sx+sAHsKSAf9hwFiJSrI6C4XdOls43V/f/fkp9ITkHhKFbQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-http@0.53.0': + resolution: {integrity: sha512-H74ErMeDuZfj7KgYCTOFGWF5W9AfaPnqLQQxeFq85+D29wwV2yqHbz2IKLYpkOh7EI6QwDEl7rZCIxjJLyc/CQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-ioredis@0.43.0': + resolution: {integrity: sha512-i3Dke/LdhZbiUAEImmRG3i7Dimm/BD7t8pDDzwepSvIQ6s2X6FPia7561gw+64w+nx0+G9X14D7rEfaMEmmjig==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-kafkajs@0.3.0': + resolution: {integrity: sha512-UnkZueYK1ise8FXQeKlpBd7YYUtC7mM8J0wzUSccEfc/G8UqHQqAzIyYCUOUPUKp8GsjLnWOOK/3hJc4owb7Jg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-knex@0.40.0': + resolution: {integrity: sha512-6jka2jfX8+fqjEbCn6hKWHVWe++mHrIkLQtaJqUkBt3ZBs2xn1+y0khxiDS0v/mNb0bIKDJWwtpKFfsQDM1Geg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-koa@0.43.0': + resolution: {integrity: sha512-lDAhSnmoTIN6ELKmLJBplXzT/Jqs5jGZehuG22EdSMaTwgjMpxMDI1YtlKEhiWPWkrz5LUsd0aOO0ZRc9vn3AQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-lru-memoizer@0.40.0': + resolution: {integrity: sha512-21xRwZsEdMPnROu/QsaOIODmzw59IYpGFmuC4aFWvMj6stA8+Ei1tX67nkarJttlNjoM94um0N4X26AD7ff54A==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-memcached@0.39.0': + resolution: {integrity: sha512-WfwvKAZ9I1qILRP5EUd88HQjwAAL+trXpCpozjBi4U6a0A07gB3fZ5PFAxbXemSjF5tHk9KVoROnqHvQ+zzFSQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-mongodb@0.47.0': + resolution: {integrity: sha512-yqyXRx2SulEURjgOQyJzhCECSh5i1uM49NUaq9TqLd6fA7g26OahyJfsr9NE38HFqGRHpi4loyrnfYGdrsoVjQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-mongoose@0.42.0': + resolution: {integrity: sha512-AnWv+RaR86uG3qNEMwt3plKX1ueRM7AspfszJYVkvkehiicC3bHQA6vWdb6Zvy5HAE14RyFbu9+2hUUjR2NSyg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-mysql2@0.41.0': + resolution: {integrity: sha512-REQB0x+IzVTpoNgVmy5b+UnH1/mDByrneimP6sbDHkp1j8QOl1HyWOrBH/6YWR0nrbU3l825Em5PlybjT3232g==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-mysql@0.41.0': + resolution: {integrity: sha512-jnvrV6BsQWyHS2qb2fkfbfSb1R/lmYwqEZITwufuRl37apTopswu9izc0b1CYRp/34tUG/4k/V39PND6eyiNvw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-nestjs-core@0.40.0': + resolution: {integrity: sha512-WF1hCUed07vKmf5BzEkL0wSPinqJgH7kGzOjjMAiTGacofNXjb/y4KQ8loj2sNsh5C/NN7s1zxQuCgbWbVTGKg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-net@0.39.0': + resolution: {integrity: sha512-rixHoODfI/Cx1B0mH1BpxCT0bRSxktuBDrt9IvpT2KSEutK5hR0RsRdgdz/GKk+BQ4u+IG6godgMSGwNQCueEA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-pg@0.44.0': + resolution: {integrity: sha512-oTWVyzKqXud1BYEGX1loo2o4k4vaU1elr3vPO8NZolrBtFvQ34nx4HgUaexUDuEog00qQt+MLR5gws/p+JXMLQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-pino@0.42.0': + resolution: {integrity: sha512-SoX6FzucBfTuFNMZjdurJhcYWq2ve8/LkhmyVLUW31HpIB45RF1JNum0u4MkGisosDmXlK4njomcgUovShI+WA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-redis-4@0.42.0': + resolution: {integrity: sha512-NaD+t2JNcOzX/Qa7kMy68JbmoVIV37fT/fJYzLKu2Wwd+0NCxt+K2OOsOakA8GVg8lSpFdbx4V/suzZZ2Pvdjg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-redis@0.42.0': + resolution: {integrity: sha512-jZBoqve0rEC51q0HuhjtZVq1DtUvJHzEJ3YKGvzGar2MU1J4Yt5+pQAQYh1W4jSoDyKeaI4hyeUdWM5N0c2lqA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-restify@0.41.0': + resolution: {integrity: sha512-gKEo+X/wVKUBuD2WDDlF7SlDNBHMWjSQoLxFCsGqeKgHR0MGtwMel8uaDGg9LJ83nKqYy+7Vl/cDFxjba6H+/w==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-router@0.40.0': + resolution: {integrity: sha512-bRo4RaclGFiKtmv/N1D0MuzO7DuxbeqMkMCbPPng6mDwzpHAMpHz/K/IxJmF+H1Hi/NYXVjCKvHGClageLe9eA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-socket.io@0.42.0': + resolution: {integrity: sha512-xB5tdsBzuZyicQTO3hDzJIpHQ7V1BYJ6vWPWgl19gWZDBdjEGc3HOupjkd3BUJyDoDhbMEHGk2nNlkUU99EfkA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-tedious@0.14.0': + resolution: {integrity: sha512-ofq7pPhSqvRDvD2FVx3RIWPj76wj4QubfrbqJtEx0A+fWoaYxJOCIQ92tYJh28elAmjMmgF/XaYuJuBhBv5J3A==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-undici@0.6.0': + resolution: {integrity: sha512-ABJBhm5OdhGmbh0S/fOTE4N69IZ00CsHC5ijMYfzbw3E5NwLgpQk5xsljaECrJ8wz1SfXbO03FiSuu5AyRAkvQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.7.0 + + '@opentelemetry/instrumentation-winston@0.40.0': + resolution: {integrity: sha512-eMk2tKl86YJ8/yHvtDbyhrE35/R0InhO9zuHTflPx8T0+IvKVUhPV71MsJr32sImftqeOww92QHt4Jd+a5db4g==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation@0.52.1': + resolution: {integrity: sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation@0.53.0': + resolution: {integrity: sha512-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/otlp-exporter-base@0.53.0': + resolution: {integrity: sha512-UCWPreGQEhD6FjBaeDuXhiMf6kkBODF0ZQzrk/tuQcaVDJ+dDQ/xhJp192H9yWnKxVpEjFrSSLnpqmX4VwX+eA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/otlp-grpc-exporter-base@0.53.0': + resolution: {integrity: sha512-F7RCN8VN+lzSa4fGjewit8Z5fEUpY/lmMVy5EWn2ZpbAabg3EE3sCLuTNfOiooNGnmvzimUPruoeqeko/5/TzQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/otlp-transformer@0.53.0': + resolution: {integrity: sha512-rM0sDA9HD8dluwuBxLetUmoqGJKSAbWenwD65KY9iZhUxdBHRLrIdrABfNDP7aiTjcgK8XFyTn5fhDz7N+W6DA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/propagation-utils@0.30.11': + resolution: {integrity: sha512-rY4L/2LWNk5p/22zdunpqVmgz6uN419DsRTw5KFMa6u21tWhXS8devlMy4h8m8nnS20wM7r6yYweCNNKjgLYJw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/propagator-aws-xray@1.26.0': + resolution: {integrity: sha512-Sex+JyEZ/xX328TArBqQjh1NZSfNyw5NdASUIi9hnPsnMBMSBaDe7B9JRnXv0swz7niNyAnXa6MY7yOCV76EvA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/propagator-b3@1.26.0': + resolution: {integrity: sha512-vvVkQLQ/lGGyEy9GT8uFnI047pajSOVnZI2poJqVGD3nJ+B9sFGdlHNnQKophE3lHfnIH0pw2ubrCTjZCgIj+Q==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/propagator-jaeger@1.26.0': + resolution: {integrity: sha512-DelFGkCdaxA1C/QA0Xilszfr0t4YbGd3DjxiCDPh34lfnFr+VkkrjV9S8ZTJvAzfdKERXhfOxIKBoGPJwoSz7Q==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/redis-common@0.36.2': + resolution: {integrity: sha512-faYX1N0gpLhej/6nyp6bgRjzAKXn5GOEMYY7YhciSfCoITAktLUtQ36d24QEWNA1/WA1y6qQunCe0OhHRkVl9g==} + engines: {node: '>=14'} + + '@opentelemetry/resource-detector-alibaba-cloud@0.29.1': + resolution: {integrity: sha512-Qshebw6azBuKUqGkVgambZlLS6Xh+LCoLXep1oqW1RSzSOHQxGYDsPs99v8NzO65eJHHOu8wc2yKsWZQAgYsSw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/resource-detector-aws@1.6.1': + resolution: {integrity: sha512-A/3lqx9xoew7sFi+AVUUVr6VgB7UJ5qqddkKR3gQk9hWLm1R7HUXVJG09cLcZ7DMNpX13DohPRGmHE/vp1vafw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/resource-detector-azure@0.2.11': + resolution: {integrity: sha512-XepvQfTXWyHAoAziCfXGwYbSZL0LHtFk5iuKKN2VE2vzcoiw5Tepi0Qafuwb7CCtpQRReao4H7E29MFbCmh47g==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/resource-detector-container@0.4.1': + resolution: {integrity: sha512-v0bvO6RxYtbxvY/HwqrPQnZ4UtP4nBq4AOyS30iqV2vEtiLTY1gNTbNvTF1lwN/gg/g5CY1tRSrHcYODDOv0vw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/resource-detector-gcp@0.29.11': + resolution: {integrity: sha512-07wJx4nyxD/c2z3n70OQOg8fmoO/baTsq8uU+f7tZaehRNQx76MPkRbV2L902N40Z21SPIG8biUZ30OXE9tOIg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.0.0 + + '@opentelemetry/resources@1.26.0': + resolution: {integrity: sha512-CPNYchBE7MBecCSVy0HKpUISEeJOniWqcHaAHpmasZ3j9o6V3AyBzhRc90jdmemq0HOxDr6ylhUbDhBqqPpeNw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/sdk-logs@0.53.0': + resolution: {integrity: sha512-dhSisnEgIj/vJZXZV6f6KcTnyLDx/VuQ6l3ejuZpMpPlh9S1qMHiZU9NMmOkVkwwHkMy3G6mEBwdP23vUZVr4g==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.4.0 <1.10.0' + + '@opentelemetry/sdk-metrics@1.26.0': + resolution: {integrity: sha512-0SvDXmou/JjzSDOjUmetAAvcKQW6ZrvosU0rkbDGpXvvZN+pQF6JbK/Kd4hNdK4q/22yeruqvukXEJyySTzyTQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + + '@opentelemetry/sdk-node@0.53.0': + resolution: {integrity: sha512-0hsxfq3BKy05xGktwG8YdGdxV978++x40EAKyKr1CaHZRh8uqVlXnclnl7OMi9xLMJEcXUw7lGhiRlArFcovyg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + + '@opentelemetry/sdk-trace-base@1.26.0': + resolution: {integrity: sha512-olWQldtvbK4v22ymrKLbIcBi9L2SpMO84sCPY54IVsJhP9fRsxJT194C/AVaAuJzLE30EdhhM1VmvVYR7az+cw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/sdk-trace-node@1.26.0': + resolution: {integrity: sha512-Fj5IVKrj0yeUwlewCRwzOVcr5avTuNnMHWf7GPc1t6WaT78J6CJyF3saZ/0RkZfdeNO8IcBl/bNcWMVZBMRW8Q==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/semantic-conventions@1.27.0': + resolution: {integrity: sha512-sAay1RrB+ONOem0OZanAR1ZI/k7yDpnOQSQmTMuGImUQb2y8EbSaCJ94FQluM74xoU03vlb2d2U90hZluL6nQg==} + engines: {node: '>=14'} + + '@opentelemetry/sql-common@0.40.1': + resolution: {integrity: sha512-nSDlnHSqzC3pXn/wZEZVLuAuJ1MYMXPBwtv2qAbCa3847SaHItdE7SzUq/Jtb0KZmh1zfAbNi3AAMjztTT4Ugg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.1.0 + + '@petamoriken/float16@3.8.7': + resolution: {integrity: sha512-/Ri4xDDpe12NT6Ex/DRgHzLlobiQXEW/hmG08w1wj/YU7hLemk97c+zHQFp0iZQ9r7YqgLEXZR2sls4HxBf9NA==} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@pkgr/core@0.1.1': + resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + + '@protobufjs/aspromise@1.1.2': + resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} + + '@protobufjs/base64@1.1.2': + resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} + + '@protobufjs/codegen@2.0.4': + resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} + + '@protobufjs/eventemitter@1.1.0': + resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} + + '@protobufjs/fetch@1.1.0': + resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} + + '@protobufjs/float@1.0.2': + resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} + + '@protobufjs/inquire@1.1.0': + resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} + + '@protobufjs/path@1.1.2': + resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} + + '@protobufjs/pool@1.1.0': + resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} + + '@protobufjs/utf8@1.1.0': + resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} + + '@redocly/ajv@8.11.2': + resolution: {integrity: sha512-io1JpnwtIcvojV7QKDUSIuMN/ikdOUd1ReEnUnMKGfDVridQZ31J0MmIuqwuRjWDZfmvr+Q0MqCcfHM2gTivOg==} + + '@redocly/config@0.11.0': + resolution: {integrity: sha512-vAc77vCuWsVgLx2LN02P6jqLBhHuot6O1LsSJEAAkWEvXARSGSQVon50QW7jlbCMg9OFTYYYRPN4W6K/YmnM3w==} + + '@redocly/openapi-core@1.25.3': + resolution: {integrity: sha512-dqJkyydgagW3FXX5cjtSUAnabsld4K6yq7RFgQ+ngI1m43PkEoSQt8pp+SfQDszSEoMbc7QKj8afbe7mZw17TA==} + engines: {node: '>=14.19.0', npm: '>=7.0.0'} + + '@rollup/pluginutils@5.1.0': + resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/rollup-android-arm-eabi@4.22.4': + resolution: {integrity: sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.22.4': + resolution: {integrity: sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.22.4': + resolution: {integrity: sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.22.4': + resolution: {integrity: sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-linux-arm-gnueabihf@4.22.4': + resolution: {integrity: sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.22.4': + resolution: {integrity: sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.22.4': + resolution: {integrity: sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.22.4': + resolution: {integrity: sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.22.4': + resolution: {integrity: sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.22.4': + resolution: {integrity: sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.22.4': + resolution: {integrity: sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.22.4': + resolution: {integrity: sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.22.4': + resolution: {integrity: sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.22.4': + resolution: {integrity: sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.22.4': + resolution: {integrity: sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.22.4': + resolution: {integrity: sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==} + cpu: [x64] + os: [win32] + + '@rushstack/node-core-library@4.0.2': + resolution: {integrity: sha512-hyES82QVpkfQMeBMteQUnrhASL/KHPhd7iJ8euduwNJG4mu2GSOKybf0rOEjOm1Wz7CwJEUm9y0yD7jg2C1bfg==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + '@rushstack/node-core-library@5.5.1': + resolution: {integrity: sha512-ZutW56qIzH8xIOlfyaLQJFx+8IBqdbVCZdnj+XT1MorQ1JqqxHse8vbCpEM+2MjsrqcbxcgDIbfggB1ZSQ2A3g==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + '@rushstack/rig-package@0.5.2': + resolution: {integrity: sha512-mUDecIJeH3yYGZs2a48k+pbhM6JYwWlgjs2Ca5f2n1G2/kgdgP9D/07oglEGf6mRyXEnazhEENeYTSNDRCwdqA==} + + '@rushstack/terminal@0.10.0': + resolution: {integrity: sha512-UbELbXnUdc7EKwfH2sb8ChqNgapUOdqcCIdQP4NGxBpTZV2sQyeekuK3zmfQSa/MN+/7b4kBogl2wq0vpkpYGw==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + '@rushstack/terminal@0.13.3': + resolution: {integrity: sha512-fc3zjXOw8E0pXS5t9vTiIPx9gHA0fIdTXsu9mT4WbH+P3mYvnrX0iAQ5a6NvyK1+CqYWBTw/wVNx7SDJkI+WYQ==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + '@rushstack/ts-command-line@4.19.1': + resolution: {integrity: sha512-J7H768dgcpG60d7skZ5uSSwyCZs/S2HrWP1Ds8d1qYAyaaeJmpmmLr9BVw97RjFzmQPOYnoXcKA4GkqDCkduQg==} + + '@rushstack/ts-command-line@4.22.4': + resolution: {integrity: sha512-QoyhbWfyF9Ixg5DWdPzxO3h2RmJ7i5WH9b7qLzD5h5WFya/ZqicjdPrVwQiGtrFvAbBj8jhcC9DhbzU9xAk78g==} + + '@sinclair/typebox@0.27.8': + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + + '@sindresorhus/is@4.6.0': + resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} + engines: {node: '>=10'} + + '@sindresorhus/merge-streams@2.3.0': + resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==} + engines: {node: '>=18'} + + '@streamparser/json@0.0.21': + resolution: {integrity: sha512-v+49JBiG1kmc/9Ug79Lz9wyKaRocBgCnpRaLpdy7p0d3ICKtOAfc/H/Epa1j3F6YdnzjnZKKrnJ8xnh/v1P8Aw==} + + '@ts-morph/common@0.23.0': + resolution: {integrity: sha512-m7Lllj9n/S6sOkCkRftpM7L24uvmfXQFedlW/4hENcuJH1HHm9u5EgxZb9uVjQSCGrbBWBkOGgcTxNg36r6ywA==} + + '@types/argparse@1.0.38': + resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} + + '@types/aws-lambda@8.10.143': + resolution: {integrity: sha512-u5vzlcR14ge/4pMTTMDQr3MF0wEe38B2F9o84uC4F43vN5DGTy63npRrB6jQhyt+C0lGv4ZfiRcRkqJoZuPnmg==} + + '@types/bunyan@1.8.9': + resolution: {integrity: sha512-ZqS9JGpBxVOvsawzmVt30sP++gSQMTejCkIAQ3VdadOcRE8izTyW66hufvwLeH+YEGP6Js2AW7Gz+RMyvrEbmw==} + + '@types/connect@3.4.36': + resolution: {integrity: sha512-P63Zd/JUGq+PdrM1lv0Wv5SBYeA2+CORvbrXbngriYY0jzLUWfQMQQxOhjONEz/wlHOAxOdY7CY65rgQdTjq2w==} + + '@types/debug@4.1.12': + resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + + '@types/estree@1.0.5': + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/json5@0.0.29': + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + + '@types/jsonwebtoken@9.0.6': + resolution: {integrity: sha512-/5hndP5dCjloafCXns6SZyESp3Ldq7YjH3zwzwczYnjxIT0Fqzk5ROSYVGfFyczIue7IUEj8hkvLbPoLQ18vQw==} + + '@types/lodash-es@4.17.12': + resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==} + + '@types/lodash@4.17.10': + resolution: {integrity: sha512-YpS0zzoduEhuOWjAotS6A5AVCva7X4lVlYLF0FYHAY9sdraBfnatttHItlWeZdGhuEkf+OzMNg2ZYAx8t+52uQ==} + + '@types/memcached@2.2.10': + resolution: {integrity: sha512-AM9smvZN55Gzs2wRrqeMHVP7KE8KWgCJO/XL5yCly2xF6EKa4YlbpK+cLSAH4NG/Ah64HrlegmGqW8kYws7Vxg==} + + '@types/ms@0.7.34': + resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} + + '@types/mysql@2.15.26': + resolution: {integrity: sha512-DSLCOXhkvfS5WNNPbfn2KdICAmk8lLc+/PNvnPnF7gOdMZCxopXduqv0OQ13y/yA/zXTSikZZqVgybUxOEg6YQ==} + + '@types/node-fetch@2.6.11': + resolution: {integrity: sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==} + + '@types/node@18.19.55': + resolution: {integrity: sha512-zzw5Vw52205Zr/nmErSEkN5FLqXPuKX/k5d1D7RKHATGqU7y6YfX9QxZraUzUrFGqH6XzOzG196BC35ltJC4Cw==} + + '@types/node@20.14.15': + resolution: {integrity: sha512-Fz1xDMCF/B00/tYSVMlmK7hVeLh7jE5f3B7X1/hmV0MJBwE27KlS7EvD/Yp+z1lm8mVhwV5w+n8jOZG8AfTlKw==} + + '@types/node@20.16.10': + resolution: {integrity: sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==} + + '@types/node@20.16.11': + resolution: {integrity: sha512-y+cTCACu92FyA5fgQSAI8A1H429g7aSK2HsO7K4XYUWc4dY5IUz55JSDIYT6/VsOLfGy8vmvQYC2hfb0iF16Uw==} + + '@types/pg-pool@2.0.6': + resolution: {integrity: sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ==} + + '@types/pg@8.6.1': + resolution: {integrity: sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w==} + + '@types/retry@0.12.0': + resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} + + '@types/shimmer@1.2.0': + resolution: {integrity: sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==} + + '@types/tedious@4.0.14': + resolution: {integrity: sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==} + + '@types/triple-beam@1.3.5': + resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==} + + '@types/uuid@10.0.0': + resolution: {integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==} + + '@types/uuid@9.0.8': + resolution: {integrity: sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==} + + '@types/validator@13.12.2': + resolution: {integrity: sha512-6SlHBzUW8Jhf3liqrGGXyTJSIFe4nqlJ5A5KaMZ2l/vbM3Wh3KSybots/wfWVzNLK4D1NZluDlSQIbIEPx6oyA==} + + '@types/webidl-conversions@7.0.3': + resolution: {integrity: sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==} + + '@types/whatwg-url@11.0.5': + resolution: {integrity: sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==} + + '@types/yauzl@2.10.3': + resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} + + '@typescript-eslint/eslint-plugin@7.18.0': + resolution: {integrity: sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + '@typescript-eslint/parser': ^7.0.0 + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/parser@7.18.0': + resolution: {integrity: sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/scope-manager@7.18.0': + resolution: {integrity: sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==} + engines: {node: ^18.18.0 || >=20.0.0} + + '@typescript-eslint/type-utils@7.18.0': + resolution: {integrity: sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/types@7.18.0': + resolution: {integrity: sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==} + engines: {node: ^18.18.0 || >=20.0.0} + + '@typescript-eslint/typescript-estree@7.18.0': + resolution: {integrity: sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/utils@7.18.0': + resolution: {integrity: sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + + '@typescript-eslint/visitor-keys@7.18.0': + resolution: {integrity: sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==} + engines: {node: ^18.18.0 || >=20.0.0} + + '@ungap/structured-clone@1.2.0': + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + + '@vitest/expect@1.6.0': + resolution: {integrity: sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==} + + '@vitest/runner@1.6.0': + resolution: {integrity: sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==} + + '@vitest/snapshot@1.6.0': + resolution: {integrity: sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==} + + '@vitest/spy@1.6.0': + resolution: {integrity: sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==} + + '@vitest/utils@1.6.0': + resolution: {integrity: sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==} + + '@volar/language-core@1.11.1': + resolution: {integrity: sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==} + + '@volar/source-map@1.11.1': + resolution: {integrity: sha512-hJnOnwZ4+WT5iupLRnuzbULZ42L7BWWPMmruzwtLhJfpDVoZLjNBxHDi2sY2bgZXCKlpU5XcsMFoYrsQmPhfZg==} + + '@volar/typescript@1.11.1': + resolution: {integrity: sha512-iU+t2mas/4lYierSnoFOeRFQUhAEMgsFuQxoxvwn5EdQopw43j+J27a4lt9LMInx1gLJBC6qL14WYGlgymaSMQ==} + + '@vue/compiler-core@3.4.37': + resolution: {integrity: sha512-ZDDT/KiLKuCRXyzWecNzC5vTcubGz4LECAtfGPENpo0nrmqJHwuWtRLxk/Sb9RAKtR9iFflFycbkjkY+W/PZUQ==} + + '@vue/compiler-dom@3.4.37': + resolution: {integrity: sha512-rIiSmL3YrntvgYV84rekAtU/xfogMUJIclUMeIKEtVBFngOL3IeZHhsH3UaFEgB5iFGpj6IW+8YuM/2Up+vVag==} + + '@vue/language-core@1.8.27': + resolution: {integrity: sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@vue/shared@3.4.37': + resolution: {integrity: sha512-nIh8P2fc3DflG8+5Uw8PT/1i17ccFn0xxN/5oE9RfV5SVnd7G0XEFRwakrnNFE/jlS95fpGXDVG5zDETS26nmg==} + + '@zilliz/milvus2-sdk-node@2.4.4': + resolution: {integrity: sha512-NskDv0dub4yZsJp3rWyXi/twV4JSWfi0ZBdUPHfsIY54dbu1CdYjZNYTrsxnqLQXpWfGSQ5RIBpIGJ7jUvXw5Q==} + + abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + + abstract-logging@2.0.1: + resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==} + + acorn-import-attributes@1.9.5: + resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==} + peerDependencies: + acorn: ^8 + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn-walk@8.3.3: + resolution: {integrity: sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==} + engines: {node: '>=0.4.0'} + + acorn@8.12.1: + resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} + engines: {node: '>=0.4.0'} + hasBin: true + + adm-zip@0.5.16: + resolution: {integrity: sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==} + engines: {node: '>=12.0'} + + agent-base@7.1.1: + resolution: {integrity: sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==} + engines: {node: '>= 14'} + + agentkeepalive@4.5.0: + resolution: {integrity: sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==} + engines: {node: '>= 8.0.0'} + + ajv-draft-04@1.0.0: + resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==} + peerDependencies: + ajv: ^8.5.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv-formats@2.1.1: + resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ajv@8.13.0: + resolution: {integrity: sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==} + + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + + ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + + ansi-escapes@7.0.0: + resolution: {integrity: sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==} + engines: {node: '>=18'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + + ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + array-buffer-byte-length@1.0.1: + resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} + engines: {node: '>= 0.4'} + + array-includes@3.1.8: + resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} + engines: {node: '>= 0.4'} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + array.prototype.findlastindex@1.2.5: + resolution: {integrity: sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==} + engines: {node: '>= 0.4'} + + array.prototype.flat@1.3.2: + resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} + engines: {node: '>= 0.4'} + + array.prototype.flatmap@1.3.2: + resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} + engines: {node: '>= 0.4'} + + arraybuffer.prototype.slice@1.0.3: + resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} + engines: {node: '>= 0.4'} + + assertion-error@1.1.0: + resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} + + async@3.2.5: + resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + atomic-sleep@1.0.0: + resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} + engines: {node: '>=8.0.0'} + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + avvio@8.4.0: + resolution: {integrity: sha512-CDSwaxINFy59iNwhYnkvALBwZiTydGkOecZyPkqBpABYR1KqGEsET0VOOYDwtleZSUIdeY36DC2bSZ24CO1igA==} + + axios@1.7.7: + resolution: {integrity: sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + bee-agent-framework@0.0.32: + resolution: {integrity: sha512-3t7HgwJAQ99bBcb8UXAuqHabXZ48KTRerNMzTpH5aqxZLxSzQbCdcGXNLF8pSiZKLtl9K+MFEa6IVWASw5gkPg==} + peerDependencies: + '@googleapis/customsearch': ^3.2.0 + '@grpc/grpc-js': ^1.11.3 + '@grpc/proto-loader': ^0.7.13 + '@ibm-generative-ai/node-sdk': ~3.2.3 + '@langchain/community': ~0.2.28 + '@langchain/core': ~0.2.27 + '@langchain/langgraph': ~0.0.34 + groq-sdk: ^0.7.0 + ollama: ^0.5.8 + openai: ^4.67.3 + openai-chat-tokens: ^0.2.8 + sequelize: ^6.37.3 + + bee-observe-connector@0.0.4: + resolution: {integrity: sha512-rEehLp67h/R+vD3NF513Zlxv13ZisyDrmdSWN5zCsjpNjQNxBNnJcsMDzdPiWZKLt2coVdqijwW3AFqCPFtqMA==} + peerDependencies: + bee-agent-framework: '>=0.0.27 <0.1.0' + + bee-proto@0.0.2: + resolution: {integrity: sha512-UgBcejkBslLdR39ozpDtX6gjD3OgB1pZS7GDO4v2CfthZhddwfzco/BdEd5IdeMX9d+srX7LgsBGOtn48djNWg==} + + bignumber.js@9.1.2: + resolution: {integrity: sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==} + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + bintrees@1.0.2: + resolution: {integrity: sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.24.0: + resolution: {integrity: sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + bson@6.8.0: + resolution: {integrity: sha512-iOJg8pr7wq2tg/zSlCCHMi3hMm5JTOxLTagf3zxhcenHsFp+c6uOs6K7W5UE7A4QIJGtqh/ZovFNMP4mOPJynQ==} + engines: {node: '>=16.20.1'} + + buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + + buffer-equal-constant-time@1.0.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + + buffer@4.9.2: + resolution: {integrity: sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==} + + buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + + bullmq@5.8.1: + resolution: {integrity: sha512-t6BTH3J6T7exR+1C1NtQYekCgzkzEnxzBKU8Qit2YVgoJyTsu/xlHk7z/6g088uv1qD6XtHtV5Aiur/sUewTQA==} + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + + cache-manager@5.7.6: + resolution: {integrity: sha512-wBxnBHjDxF1RXpHCBD6HGvKER003Ts7IIm0CHpggliHzN1RZditb7rXoduE1rplc2DEFYKxhLKgFuchXMJje9w==} + engines: {node: '>= 18'} + + call-bind@1.0.7: + resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camelcase@4.1.0: + resolution: {integrity: sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw==} + engines: {node: '>=4'} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + caniuse-lite@1.0.30001669: + resolution: {integrity: sha512-DlWzFDJqstqtIVx1zeSpIMLjunf5SmwOw0N2Ck/QSQdS8PLS4+9HrLaYei4w8BIAL7IB/UEDu889d8vhCTPA0w==} + + chai@4.5.0: + resolution: {integrity: sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==} + engines: {node: '>=4'} + + chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chalk@5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + change-case@5.4.4: + resolution: {integrity: sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==} + + check-error@1.0.3: + resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} + + cjs-module-lexer@1.4.1: + resolution: {integrity: sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==} + + cli-cursor@5.0.0: + resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} + engines: {node: '>=18'} + + cli-truncate@4.0.0: + resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} + engines: {node: '>=18'} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + cluster-key-slot@1.1.2: + resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} + engines: {node: '>=0.10.0'} + + code-block-writer@13.0.2: + resolution: {integrity: sha512-XfXzAGiStXSmCIwrkdfvc7FS5Dtj8yelCtyOf2p2skCAfvLd6zu0rGzuS9NSCO3bq1JKpFZ7tbKdKlcd5occQA==} + + codsen-utils@1.6.4: + resolution: {integrity: sha512-PDyvQ5f2PValmqZZIJATimcokDt4JjIev8cKbZgEOoZm+U1IJDYuLeTcxZPQdep99R/X0RIlQ6ReQgPOVnPbNw==} + engines: {node: '>=14.18.0'} + + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + + color@3.2.1: + resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==} + + colorette@1.4.0: + resolution: {integrity: sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==} + + colorette@2.0.19: + resolution: {integrity: sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==} + + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + + colorspace@1.1.4: + resolution: {integrity: sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + commander@10.0.1: + resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} + engines: {node: '>=14'} + + commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} + + commander@9.5.0: + resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} + engines: {node: ^12.20.0 || >=14} + + complex.js@2.3.0: + resolution: {integrity: sha512-wWHzifVdUPbPBhh+ObvpVGIzrAQjTvmnnEJKBfLW5YbyAB6OXQ0r+Q92fByMIrSSlxUuCujqxriJSR6R/kVxPA==} + + computeds@0.0.1: + resolution: {integrity: sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + confbox@0.1.7: + resolution: {integrity: sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==} + + content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + + cookie@0.6.0: + resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} + engines: {node: '>= 0.6'} + + cron-parser@4.9.0: + resolution: {integrity: sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==} + engines: {node: '>=12.0.0'} + + cross-fetch@4.0.0: + resolution: {integrity: sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==} + + cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + + data-view-buffer@1.0.1: + resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} + engines: {node: '>= 0.4'} + + data-view-byte-length@1.0.1: + resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==} + engines: {node: '>= 0.4'} + + data-view-byte-offset@1.0.0: + resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} + engines: {node: '>= 0.4'} + + dataloader@2.2.2: + resolution: {integrity: sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g==} + + dateformat@4.6.3: + resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==} + + dayjs@1.11.12: + resolution: {integrity: sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg==} + + de-indent@1.0.2: + resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} + + debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.3.6: + resolution: {integrity: sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.3.7: + resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + + decimal.js@10.4.3: + resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} + + deep-eql@4.1.4: + resolution: {integrity: sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==} + engines: {node: '>=6'} + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + denque@2.1.0: + resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} + engines: {node: '>=0.10'} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + detect-libc@2.0.3: + resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} + engines: {node: '>=8'} + + diff-sequences@29.6.3: + resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + dirty-json@0.9.2: + resolution: {integrity: sha512-7SCDfnQtBObcngVXNPZcnxGxqqPTK4UqeXeKAch+RGH5qpqadWbV9FmN71x9Bb4tTs0TNFb4FT/4Kz4P4Cjqcw==} + engines: {node: '>=6.0.0'} + + doctrine@2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + + doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + + dot-prop@6.0.1: + resolution: {integrity: sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==} + engines: {node: '>=10'} + + dotenv@16.4.5: + resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} + engines: {node: '>=12'} + + dottie@2.0.6: + resolution: {integrity: sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA==} + + duck-duck-scrape@2.2.5: + resolution: {integrity: sha512-RTu/Ag5LhgD/j1l2zVGCwTINBoEYCffl58nMoBjtXWJG8tTex72h3gxpDjAr8jVqFaBvhgASNKTUsE31JeqYgw==} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + + electron-to-chromium@1.5.39: + resolution: {integrity: sha512-4xkpSR6CjuiaNyvwiWDI85N9AxsvbPawB8xc7yzLPonYTuP19BVgYweKyUMFtHEZgIcHWMt1ks5Cqx2m+6/Grg==} + + emittery@0.13.1: + resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} + engines: {node: '>=12'} + + emoji-regex@10.3.0: + resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + enabled@2.0.0: + resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==} + + end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + + enhanced-resolve@5.17.1: + resolution: {integrity: sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==} + engines: {node: '>=10.13.0'} + + entities@5.0.0: + resolution: {integrity: sha512-BeJFvFRJddxobhvEdm5GqHzRV/X+ACeuw0/BuuxsCh1EUZcAIz8+kYmBp/LrQuloy6K1f3a0M7+IhmZ7QnkISA==} + engines: {node: '>=0.12'} + + environment@1.1.0: + resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} + engines: {node: '>=18'} + + es-abstract@1.23.3: + resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} + engines: {node: '>= 0.4'} + + es-define-property@1.0.0: + resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.0.0: + resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.0.3: + resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} + engines: {node: '>= 0.4'} + + es-shim-unscopables@1.0.2: + resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} + + es-to-primitive@1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + engines: {node: '>= 0.4'} + + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} + engines: {node: '>=12'} + hasBin: true + + esbuild@0.23.0: + resolution: {integrity: sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.1.2: + resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} + engines: {node: '>=6'} + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + escape-latex@1.2.0: + resolution: {integrity: sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw==} + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-config-prettier@9.1.0: + resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + + eslint-import-resolver-node@0.3.9: + resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} + + eslint-import-resolver-typescript@3.6.1: + resolution: {integrity: sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '*' + eslint-plugin-import: '*' + + eslint-module-utils@2.8.1: + resolution: {integrity: sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + + eslint-plugin-import@2.29.1: + resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + + eslint-plugin-prettier@5.2.1: + resolution: {integrity: sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + '@types/eslint': '>=8.0.0' + eslint: '>=8.0.0' + eslint-config-prettier: '*' + prettier: '>=3.0.0' + peerDependenciesMeta: + '@types/eslint': + optional: true + eslint-config-prettier: + optional: true + + eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint@8.57.0: + resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + + esm@3.2.25: + resolution: {integrity: sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==} + engines: {node: '>=6'} + + espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + + eventemitter3@4.0.7: + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + + eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + + events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + + execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + + expr-eval@2.0.2: + resolution: {integrity: sha512-4EMSHGOPSwAfBiibw3ndnP0AvjDWLsMvGOvWEZ2F96IGk0bIVdjQisOHxReSkE13mHcfbuCiXw+G4y0zv6N8Eg==} + + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + + fast-content-type-parse@1.1.0: + resolution: {integrity: sha512-fBHHqSTFLVnR61C+gltJuE5GkVQMV0S2nqUO8TJ+5Z3qAKG8vAx4FKai1s5jq/inV1+sREynIWSuQ6HgoSXpDQ==} + + fast-copy@3.0.2: + resolution: {integrity: sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==} + + fast-decode-uri-component@1.0.1: + resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-diff@1.3.0: + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + + fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-json-stringify@5.16.1: + resolution: {integrity: sha512-KAdnLvy1yu/XrRtP+LJnxbBGrhN+xXu+gt3EUvZhYGKCr3lFHq/7UFJHHFgmJKoqlh6B40bZLEv7w46B0mqn1g==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fast-querystring@1.1.2: + resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==} + + fast-redact@3.5.0: + resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==} + engines: {node: '>=6'} + + fast-safe-stringify@2.1.1: + resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + + fast-uri@2.4.0: + resolution: {integrity: sha512-ypuAmmMKInk5q7XcepxlnUWDLWv4GFtaJqAzWKqn62IpQ3pejtr5dTVbt3vwqVaMKmkNR55sTT+CqUKIaT21BA==} + + fast-uri@3.0.1: + resolution: {integrity: sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==} + + fast-xml-parser@4.5.0: + resolution: {integrity: sha512-/PlTQCI96+fZMAOLMZK4CWG1ItCbfZ/0jx7UIJFChPNrx7tcEgerUgWbeieCM9MfHInUDyK8DWYZ+YrywDJuTg==} + hasBin: true + + fastify-plugin@4.5.1: + resolution: {integrity: sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ==} + + fastify@4.28.1: + resolution: {integrity: sha512-kFWUtpNr4i7t5vY2EJPCN2KgMVpuqfU4NjnJNCgiNB900oiDeYqaNDRcAfeBbOF5hGixixxcKnOU4KN9z6QncQ==} + + fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + + fecha@4.2.3: + resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==} + + fetch-retry@5.0.6: + resolution: {integrity: sha512-3yurQZ2hD9VISAhJJP9bpYFNQrHHBXE2JxxjY5aLEcDi46RmAzJE2OC9FAde0yis5ElW0jTTzs0zfg/Cca4XqQ==} + + figlet@1.7.0: + resolution: {integrity: sha512-gO8l3wvqo0V7wEFLXPbkX83b7MVjRrk1oRLfYlZXol8nEpb/ON9pcKLI4qpBv5YtOTfrINtqb7b40iYY2FTWFg==} + engines: {node: '>= 0.4.0'} + hasBin: true + + file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-my-way@8.2.0: + resolution: {integrity: sha512-HdWXgFYc6b1BJcOBDBwjqWuHJj1WYiqrxSh25qtU4DabpMFdj/gSunNBQb83t+8Zt67D7CXEzJWTkxaShMTMOA==} + engines: {node: '>=14'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@3.2.0: + resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} + engines: {node: ^10.12.0 || >=12.0.0} + + flat@5.0.2: + resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} + hasBin: true + + flatted@3.3.1: + resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + + fn.name@1.1.0: + resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} + + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + + foreground-child@3.3.0: + resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} + engines: {node: '>=14'} + + form-data-encoder@1.7.2: + resolution: {integrity: sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==} + + form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + + formdata-node@4.4.1: + resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==} + engines: {node: '>= 12.20'} + + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + + fraction.js@4.3.7: + resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + + fs-extra@11.2.0: + resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} + engines: {node: '>=14.14'} + + fs-extra@7.0.1: + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} + engines: {node: '>=6 <7 || >=8'} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + function.prototype.name@1.1.6: + resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} + engines: {node: '>= 0.4'} + + functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + + gaxios@6.7.1: + resolution: {integrity: sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==} + engines: {node: '>=14'} + + gcp-metadata@6.1.0: + resolution: {integrity: sha512-Jh/AIwwgaxan+7ZUUmRLCjtchyDiqh4KjBJ5tW3plBZb5iL/BPcso8A5DlzeD9qlw0duCamnNdpFjxwaT0KyKg==} + engines: {node: '>=14'} + + generative-bayesian-network@2.1.56: + resolution: {integrity: sha512-pDuyJFI1wXGEIAlK2aqzSb1pEgC4onjB5itmgVmHnqVrpSBkfBjqKRbSy+RlzMP+F8DM7F8BRSHSS3wPiUoHow==} + + generic-pool@3.9.0: + resolution: {integrity: sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==} + engines: {node: '>= 4'} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-east-asian-width@1.2.0: + resolution: {integrity: sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==} + engines: {node: '>=18'} + + get-func-name@2.0.2: + resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} + + get-intrinsic@1.2.4: + resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + engines: {node: '>= 0.4'} + + get-package-type@0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + + get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + + get-symbol-description@1.0.2: + resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} + engines: {node: '>= 0.4'} + + get-tsconfig@4.7.6: + resolution: {integrity: sha512-ZAqrLlu18NbDdRaHq+AKXzAmqIUPswPWKUchfytdAjiRFnCe5ojG2bstg6mRiZabkKfCoL/e98pbBELIV/YCeA==} + + getopts@2.3.0: + resolution: {integrity: sha512-5eDf9fuSXwxBL6q5HX+dhDj+dslFGWzU5thZ9kNKUkcPtaPdatmUFKwHFrLb/uf/WpA4BHET+AX3Scl56cAjpA==} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported + + globals@13.24.0: + resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} + engines: {node: '>=8'} + + globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} + engines: {node: '>= 0.4'} + + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + globby@14.0.2: + resolution: {integrity: sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==} + engines: {node: '>=18'} + + globrex@0.1.2: + resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} + + google-auth-library@9.14.2: + resolution: {integrity: sha512-R+FRIfk1GBo3RdlRYWPdwk8nmtVUOn6+BkDomAC46KoU8kzXzE1HLmOasSCbWUByMMAGkknVF0G5kQ69Vj7dlA==} + engines: {node: '>=14'} + + googleapis-common@7.2.0: + resolution: {integrity: sha512-/fhDZEJZvOV3X5jmD+fKxMqma5q2Q9nZNSF3kn1F18tpxmA86BcTxAGBQdM0N89Z3bEaIs+HVznSmFJEAmMTjA==} + engines: {node: '>=14.0.0'} + + gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + groq-sdk@0.7.0: + resolution: {integrity: sha512-OgPqrRtti5MjEVclR8sgBHrhSkTLdFCmi47yrEF29uJZaiCkX3s7bXpnMhq8Lwoe1f4AwgC0qGOeHXpeSgu5lg==} + + gtoken@7.1.0: + resolution: {integrity: sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==} + engines: {node: '>=14.0.0'} + + has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + + has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-proto@1.0.3: + resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} + engines: {node: '>= 0.4'} + + has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + + header-generator@2.1.56: + resolution: {integrity: sha512-EFpPrnKh/XXWHA6i3bgjQ19xXgx/+E/iQKLFcKPVnusSSdnzcNlI0OFTWOYujbm8uiVkdU/BaiQ25AFzB0Zbvg==} + engines: {node: '>=16.0.0'} + + help-me@5.0.0: + resolution: {integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==} + + html-entities@2.5.2: + resolution: {integrity: sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==} + + http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + + http-status-codes@2.3.0: + resolution: {integrity: sha512-RJ8XvFvpPM/Dmc5SV+dC4y5PCeOhT3x1Hq0NU3rjGeg5a/CqlhZ7uudknPwZFz4aeAXDcbAyaeP7GAo9lvngtA==} + + https-proxy-agent@7.0.5: + resolution: {integrity: sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==} + engines: {node: '>= 14'} + + human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + + humanize-ms@1.2.1: + resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + + husky@9.1.4: + resolution: {integrity: sha512-bho94YyReb4JV7LYWRWxZ/xr6TtOTt8cMfmQ39MQYJ7f/YE268s3GdghGwi+y4zAeqewE5zYLvuhV0M0ijsDEA==} + engines: {node: '>=18'} + hasBin: true + + ibm-cos-sdk@1.13.4: + resolution: {integrity: sha512-6xQcePz/Ljvvf1EBD/2UnI7lh38AlZXWF+cFv/UhF++U4pvBb3VIbfOHV476bevMbwvjqKLtLmePOmLFe9blpQ==} + engines: {node: '>= 10.0.0'} + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + + import-in-the-middle@1.11.2: + resolution: {integrity: sha512-gK6Rr6EykBcc6cVWRSBR5TWf8nn6hZMYSRYqCcHa0l0d1fPK7JSYo6+Mlmck76jIX9aL/IZ71c06U2VpFwl1zA==} + + import-lazy@4.0.0: + resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} + engines: {node: '>=8'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + index-to-position@0.1.2: + resolution: {integrity: sha512-MWDKS3AS1bGCHLBA2VLImJz42f7bJh8wQsTGCzI3j519/CASStoDONUBVz2I/VID0MpiX3SGSnbOD2xUalbE5g==} + engines: {node: '>=18'} + + inflection@1.13.4: + resolution: {integrity: sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw==} + engines: {'0': node >= 0.4.0} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + + infobox-parser@3.6.4: + resolution: {integrity: sha512-d2lTlxKZX7WsYxk9/UPt51nkmZv5tbC75SSw4hfHqZ3LpRAn6ug0oru9xI2X+S78va3aUAze3xl/UqMuwLmJUw==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + internal-slot@1.0.7: + resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} + engines: {node: '>= 0.4'} + + interpret@2.2.0: + resolution: {integrity: sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==} + engines: {node: '>= 0.10'} + + ioredis@5.4.1: + resolution: {integrity: sha512-2YZsvl7jopIa1gaePkeMtd9rAcSjOOjPtpcLlOeusyO+XH2SK5ZcT+UCrElPP+WVIInh2TzeI4XW9ENaSLVVHA==} + engines: {node: '>=12.22.0'} + + ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + + is-arguments@1.1.1: + resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} + engines: {node: '>= 0.4'} + + is-array-buffer@3.0.4: + resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} + engines: {node: '>= 0.4'} + + is-arrayish@0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + + is-bigint@1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + + is-boolean-object@1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-core-module@2.15.0: + resolution: {integrity: sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==} + engines: {node: '>= 0.4'} + + is-data-view@1.0.1: + resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} + engines: {node: '>= 0.4'} + + is-date-object@1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-fullwidth-code-point@4.0.0: + resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} + engines: {node: '>=12'} + + is-fullwidth-code-point@5.0.0: + resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} + engines: {node: '>=18'} + + is-generator-function@1.0.10: + resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} + engines: {node: '>= 0.4'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + engines: {node: '>= 0.4'} + + is-number-object@1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-obj@2.0.0: + resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} + engines: {node: '>=8'} + + is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + + is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + + is-shared-array-buffer@1.0.3: + resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} + engines: {node: '>= 0.4'} + + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + + is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + + is-symbol@1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + + is-typed-array@1.1.13: + resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} + engines: {node: '>= 0.4'} + + is-weakref@1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + javascript-natural-sort@0.7.1: + resolution: {integrity: sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==} + + jju@1.4.0: + resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} + + jmespath@0.16.0: + resolution: {integrity: sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==} + engines: {node: '>= 0.6.0'} + + joplin-turndown-plugin-gfm@1.0.12: + resolution: {integrity: sha512-qL4+1iycQjZ1fs8zk3jSRk7cg3ROBUHk7GKtiLAQLFzLPKErnILUvz5DLszSQvz3s1sTjPbywLDISVUtBY6HaA==} + + jose@4.15.9: + resolution: {integrity: sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA==} + + jose@5.6.3: + resolution: {integrity: sha512-1Jh//hEEwMhNYPDDLwXHa2ePWgWiFNNUadVmguAAw2IJ6sj9mNxV5tGXJNqlMkJAybF6Lgw1mISDxTePP/187g==} + + joycon@3.1.1: + resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} + engines: {node: '>=10'} + + js-levenshtein@1.1.6: + resolution: {integrity: sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==} + engines: {node: '>=0.10.0'} + + js-tiktoken@1.0.12: + resolution: {integrity: sha512-L7wURW1fH9Qaext0VzaUDpFGVQgjkdE3Dgsy9/+yXyGEpBKnylTd0mU0bfbNkKDlXRb6TEsZkwuflu1B8uQbJQ==} + + js-tiktoken@1.0.15: + resolution: {integrity: sha512-65ruOWWXDEZHHbAo7EjOcNxOGasQKbL4Fq3jEr2xsCqSsoOo6VVSqzWQb6PRIqypFSDcma4jO90YP0w5X8qVXQ==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-tokens@9.0.0: + resolution: {integrity: sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==} + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + json-bigint@1.0.0: + resolution: {integrity: sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==} + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-schema-ref-resolver@1.0.1: + resolution: {integrity: sha512-EJAj1pgHc1hxF6vo2Z3s69fMjO1INq6eGHXZ8Z6wCQeldCuwxGK9Sxf4/cScGn3FZubCVUehfWtcDM/PLteCQw==} + + json-schema-resolver@2.0.0: + resolution: {integrity: sha512-pJ4XLQP4Q9HTxl6RVDLJ8Cyh1uitSs0CzDBAz1uoJ4sRD/Bk7cFSXL1FUXDW3zJ7YnfliJx6eu8Jn283bpZ4Yg==} + engines: {node: '>=10'} + + json-schema-to-ts@3.1.0: + resolution: {integrity: sha512-UeVN/ery4/JeXI8h4rM8yZPxsH+KqPi/84qFxHfTGHZnWnK9D0UU9ZGYO+6XAaJLqCWMiks+ARuFOKAiSxJCHA==} + engines: {node: '>=16'} + + json-schema-to-typescript@15.0.2: + resolution: {integrity: sha512-+cRBw+bBJ3k783mZroDIgz1pLNPB4hvj6nnbHTWwEVl0dkW8qdZ+M9jWhBb+Y0FAdHvNsXACga3lewGO8lktrw==} + engines: {node: '>=16.0.0'} + hasBin: true + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + + jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + + jsonpointer@5.0.1: + resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} + engines: {node: '>=0.10.0'} + + jsonrepair@3.8.1: + resolution: {integrity: sha512-5wnjaO53EJOhfLFY92nvBz2B9gqF9ql/D4HKUb1WOSBaqtVcAifFfmurblnhCJn/ySqKFA8U3n7nhGMAu/hEjQ==} + hasBin: true + + jwa@2.0.0: + resolution: {integrity: sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==} + + jws@4.0.0: + resolution: {integrity: sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + knex@3.1.0: + resolution: {integrity: sha512-GLoII6hR0c4ti243gMs5/1Rb3B+AjwMOfjYm97pu0FOQa7JH56hgBxYf5WK2525ceSbBY1cjeZ9yk99GPMB6Kw==} + engines: {node: '>=16'} + hasBin: true + peerDependencies: + better-sqlite3: '*' + mysql: '*' + mysql2: '*' + pg: '*' + pg-native: '*' + sqlite3: '*' + tedious: '*' + peerDependenciesMeta: + better-sqlite3: + optional: true + mysql: + optional: true + mysql2: + optional: true + pg: + optional: true + pg-native: + optional: true + sqlite3: + optional: true + tedious: + optional: true + + kolorist@1.8.0: + resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} + + kuler@2.0.0: + resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==} + + langchain@0.2.17: + resolution: {integrity: sha512-wFn7wo+XGzqYrv3KJLmMZ1M6BHx12C3YUSASOa03rcDsBzRL5onxhKAC/g4xAIqlAHrJYgU6Jb/T/S6uJ6UdkQ==} + engines: {node: '>=18'} + peerDependencies: + '@aws-sdk/client-s3': '*' + '@aws-sdk/client-sagemaker-runtime': '*' + '@aws-sdk/client-sfn': '*' + '@aws-sdk/credential-provider-node': '*' + '@azure/storage-blob': '*' + '@browserbasehq/sdk': '*' + '@gomomento/sdk': '*' + '@gomomento/sdk-core': '*' + '@gomomento/sdk-web': ^1.51.1 + '@langchain/anthropic': '*' + '@langchain/aws': '*' + '@langchain/cohere': '*' + '@langchain/community': '*' + '@langchain/google-genai': '*' + '@langchain/google-vertexai': '*' + '@langchain/groq': '*' + '@langchain/mistralai': '*' + '@langchain/ollama': '*' + '@mendable/firecrawl-js': '*' + '@notionhq/client': '*' + '@pinecone-database/pinecone': '*' + '@supabase/supabase-js': '*' + '@vercel/kv': '*' + '@xata.io/client': '*' + apify-client: '*' + assemblyai: '*' + axios: '*' + cheerio: '*' + chromadb: '*' + convex: '*' + couchbase: '*' + d3-dsv: '*' + epub2: '*' + faiss-node: '*' + fast-xml-parser: '*' + handlebars: ^4.7.8 + html-to-text: '*' + ignore: '*' + ioredis: '*' + jsdom: '*' + mammoth: '*' + mongodb: '*' + node-llama-cpp: '*' + notion-to-md: '*' + officeparser: '*' + pdf-parse: '*' + peggy: ^3.0.2 + playwright: '*' + puppeteer: '*' + pyodide: ^0.24.1 + redis: '*' + sonix-speech-recognition: '*' + srt-parser-2: '*' + typeorm: '*' + weaviate-ts-client: '*' + web-auth-library: '*' + ws: '*' + youtube-transcript: '*' + youtubei.js: '*' + peerDependenciesMeta: + '@aws-sdk/client-s3': + optional: true + '@aws-sdk/client-sagemaker-runtime': + optional: true + '@aws-sdk/client-sfn': + optional: true + '@aws-sdk/credential-provider-node': + optional: true + '@azure/storage-blob': + optional: true + '@browserbasehq/sdk': + optional: true + '@gomomento/sdk': + optional: true + '@gomomento/sdk-core': + optional: true + '@gomomento/sdk-web': + optional: true + '@langchain/anthropic': + optional: true + '@langchain/aws': + optional: true + '@langchain/cohere': + optional: true + '@langchain/community': + optional: true + '@langchain/google-genai': + optional: true + '@langchain/google-vertexai': + optional: true + '@langchain/groq': + optional: true + '@langchain/mistralai': + optional: true + '@langchain/ollama': + optional: true + '@mendable/firecrawl-js': + optional: true + '@notionhq/client': + optional: true + '@pinecone-database/pinecone': + optional: true + '@supabase/supabase-js': + optional: true + '@vercel/kv': + optional: true + '@xata.io/client': + optional: true + apify-client: + optional: true + assemblyai: + optional: true + axios: + optional: true + cheerio: + optional: true + chromadb: + optional: true + convex: + optional: true + couchbase: + optional: true + d3-dsv: + optional: true + epub2: + optional: true + faiss-node: + optional: true + fast-xml-parser: + optional: true + handlebars: + optional: true + html-to-text: + optional: true + ignore: + optional: true + ioredis: + optional: true + jsdom: + optional: true + mammoth: + optional: true + mongodb: + optional: true + node-llama-cpp: + optional: true + notion-to-md: + optional: true + officeparser: + optional: true + pdf-parse: + optional: true + peggy: + optional: true + playwright: + optional: true + puppeteer: + optional: true + pyodide: + optional: true + redis: + optional: true + sonix-speech-recognition: + optional: true + srt-parser-2: + optional: true + typeorm: + optional: true + weaviate-ts-client: + optional: true + web-auth-library: + optional: true + ws: + optional: true + youtube-transcript: + optional: true + youtubei.js: + optional: true + + langchain@0.2.20: + resolution: {integrity: sha512-tbels6Rr524iMM3VOQ4aTGnEOOjAA1BQuBR8u/8gJ2yT48lMtIQRAN32Y4KVjKK+hEWxHHlmLBrtgLpTphFjNA==} + engines: {node: '>=18'} + peerDependencies: + '@aws-sdk/client-s3': '*' + '@aws-sdk/client-sagemaker-runtime': '*' + '@aws-sdk/client-sfn': '*' + '@aws-sdk/credential-provider-node': '*' + '@azure/storage-blob': '*' + '@browserbasehq/sdk': '*' + '@gomomento/sdk': '*' + '@gomomento/sdk-core': '*' + '@gomomento/sdk-web': ^1.51.1 + '@langchain/anthropic': '*' + '@langchain/aws': '*' + '@langchain/cohere': '*' + '@langchain/google-genai': '*' + '@langchain/google-vertexai': '*' + '@langchain/groq': '*' + '@langchain/mistralai': '*' + '@langchain/ollama': '*' + '@mendable/firecrawl-js': '*' + '@notionhq/client': '*' + '@pinecone-database/pinecone': '*' + '@supabase/supabase-js': '*' + '@vercel/kv': '*' + '@xata.io/client': '*' + apify-client: '*' + assemblyai: '*' + axios: '*' + cheerio: '*' + chromadb: '*' + convex: '*' + couchbase: '*' + d3-dsv: '*' + epub2: '*' + faiss-node: '*' + fast-xml-parser: '*' + handlebars: ^4.7.8 + html-to-text: '*' + ignore: '*' + ioredis: '*' + jsdom: '*' + mammoth: '*' + mongodb: '*' + node-llama-cpp: '*' + notion-to-md: '*' + officeparser: '*' + pdf-parse: '*' + peggy: ^3.0.2 + playwright: '*' + puppeteer: '*' + pyodide: '>=0.24.1 <0.27.0' + redis: '*' + sonix-speech-recognition: '*' + srt-parser-2: '*' + typeorm: '*' + weaviate-ts-client: '*' + web-auth-library: '*' + ws: '*' + youtube-transcript: '*' + youtubei.js: '*' + peerDependenciesMeta: + '@aws-sdk/client-s3': + optional: true + '@aws-sdk/client-sagemaker-runtime': + optional: true + '@aws-sdk/client-sfn': + optional: true + '@aws-sdk/credential-provider-node': + optional: true + '@azure/storage-blob': + optional: true + '@browserbasehq/sdk': + optional: true + '@gomomento/sdk': + optional: true + '@gomomento/sdk-core': + optional: true + '@gomomento/sdk-web': + optional: true + '@langchain/anthropic': + optional: true + '@langchain/aws': + optional: true + '@langchain/cohere': + optional: true + '@langchain/google-genai': + optional: true + '@langchain/google-vertexai': + optional: true + '@langchain/groq': + optional: true + '@langchain/mistralai': + optional: true + '@langchain/ollama': + optional: true + '@mendable/firecrawl-js': + optional: true + '@notionhq/client': + optional: true + '@pinecone-database/pinecone': + optional: true + '@supabase/supabase-js': + optional: true + '@vercel/kv': + optional: true + '@xata.io/client': + optional: true + apify-client: + optional: true + assemblyai: + optional: true + axios: + optional: true + cheerio: + optional: true + chromadb: + optional: true + convex: + optional: true + couchbase: + optional: true + d3-dsv: + optional: true + epub2: + optional: true + faiss-node: + optional: true + fast-xml-parser: + optional: true + handlebars: + optional: true + html-to-text: + optional: true + ignore: + optional: true + ioredis: + optional: true + jsdom: + optional: true + mammoth: + optional: true + mongodb: + optional: true + node-llama-cpp: + optional: true + notion-to-md: + optional: true + officeparser: + optional: true + pdf-parse: + optional: true + peggy: + optional: true + playwright: + optional: true + puppeteer: + optional: true + pyodide: + optional: true + redis: + optional: true + sonix-speech-recognition: + optional: true + srt-parser-2: + optional: true + typeorm: + optional: true + weaviate-ts-client: + optional: true + web-auth-library: + optional: true + ws: + optional: true + youtube-transcript: + optional: true + youtubei.js: + optional: true + + langsmith@0.1.41: + resolution: {integrity: sha512-8R7s/225Pxmv0ipMfd6sqmWVsfHLQivYlQZ0vx5K+ReoknummTenQlVK8gapk3kqRMnzkrouuRHMhWjMR6RgUA==} + peerDependencies: + '@langchain/core': '*' + langchain: '*' + openai: '*' + peerDependenciesMeta: + '@langchain/core': + optional: true + langchain: + optional: true + openai: + optional: true + + langsmith@0.1.66: + resolution: {integrity: sha512-ZhZ9g8t/qjj0oUWpvKLtUe3qxDL/N0wG0m+Ctkxf0keopYJkcMJg4/71jl6ZYyiSU8xlC27aixXOT0uvLhqcFA==} + peerDependencies: + openai: '*' + peerDependenciesMeta: + openai: + optional: true + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lex@1.7.9: + resolution: {integrity: sha512-vzaalVBmFLnMaedq0QAsBAaXsWahzRpvnIBdBjj7y+7EKTS6lnziU2y/PsU2c6rV5qYj2B5IDw0uNJ9peXD0vw==} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. + + light-my-request@5.13.0: + resolution: {integrity: sha512-9IjUN9ZyCS9pTG+KqTDEQo68Sui2lHsYBrfMyVUTTZ3XhH8PMZq7xO94Kr+eP9dhi/kcKsx4N41p2IXEBil1pQ==} + + lilconfig@3.1.2: + resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} + engines: {node: '>=14'} + + lint-staged@15.2.10: + resolution: {integrity: sha512-5dY5t743e1byO19P9I4b3x8HJwalIznL5E1FWYnU6OWw33KxNBSLAc6Cy7F2PsFEO8FKnLwjwm5hx7aMF0jzZg==} + engines: {node: '>=18.12.0'} + hasBin: true + + listr2@8.2.4: + resolution: {integrity: sha512-opevsywziHd3zHCVQGAj8zu+Z3yHNkkoYhWIGnq54RrCVwLz0MozotJEDnKsIBLvkfLGN6BLOyAeRrYI0pKA4g==} + engines: {node: '>=18.0.0'} + + local-pkg@0.5.0: + resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==} + engines: {node: '>=14'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash-es@4.17.21: + resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + + lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + + lodash.clonedeep@4.5.0: + resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} + + lodash.defaults@4.2.0: + resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} + + lodash.get@4.4.2: + resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} + + lodash.isarguments@3.1.0: + resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==} + + lodash.isequal@4.5.0: + resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + log-update@6.1.0: + resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} + engines: {node: '>=18'} + + logform@2.6.1: + resolution: {integrity: sha512-CdaO738xRapbKIMVn2m4F6KTj4j7ooJ8POVnebSgKo3KBz5axNXRAL7ZdRjIV6NOr2Uf4vjtRkxrFETOioCqSA==} + engines: {node: '>= 12.0.0'} + + long@5.2.3: + resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} + + loupe@2.3.7: + resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + + lru-cache@9.1.2: + resolution: {integrity: sha512-ERJq3FOzJTxBbFjZ7iDs+NiK4VI9Wz+RdrrAB8dio1oV+YvdPzUEE4QNiT2VD51DkIbCYRUUzCRkssXCHqSnKQ==} + engines: {node: 14 || >=16.14} + + luxon@3.5.0: + resolution: {integrity: sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==} + engines: {node: '>=12'} + + magic-string@0.30.11: + resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==} + + mathjs@13.2.0: + resolution: {integrity: sha512-P5PZoiUX2Tkghkv3tsSqlK0B9My/ErKapv1j6wdxd0MOrYQ30cnGE4LH/kzYB2gA5rN46Njqc4cFgJjaxgijoQ==} + engines: {node: '>= 18'} + hasBin: true + + memory-pager@1.5.0: + resolution: {integrity: sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mikro-orm@6.2.9: + resolution: {integrity: sha512-zpP8D7Lw8Q2WYwd43iFQI+5e0zPUM+vEAAyJaGE87RzSiQwchqZNPuV/H74STNJYqj8mLSvwZxFvRzrQXsCRRw==} + engines: {node: '>= 18.12.0'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime@3.0.0: + resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} + engines: {node: '>=10.0.0'} + hasBin: true + + mime@4.0.4: + resolution: {integrity: sha512-v8yqInVjhXyqP6+Kw4fV3ZzeMRqEW6FotRsKXjRS5VMTNIuXsdRoAvklpoRgSqXm6o9VNH4/C0mgedko9DdLsQ==} + engines: {node: '>=16'} + hasBin: true + + mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + + mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} + + minimatch@3.0.8: + resolution: {integrity: sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + + mkdirp@3.0.1: + resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==} + engines: {node: '>=10'} + hasBin: true + + mlly@1.7.1: + resolution: {integrity: sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==} + + module-details-from-path@1.0.3: + resolution: {integrity: sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==} + + moment-timezone@0.5.46: + resolution: {integrity: sha512-ZXm9b36esbe7OmdABqIWJuBBiLLwAjrN7CE+7sYdCCx82Nabt1wHDj8TVseS59QIlfFPbOoiBPm6ca9BioG4hw==} + + moment@2.30.1: + resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==} + + mongodb-connection-string-url@3.0.1: + resolution: {integrity: sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==} + + mongodb@6.7.0: + resolution: {integrity: sha512-TMKyHdtMcO0fYBNORiYdmM25ijsHs+Njs963r4Tro4OQZzqYigAzYQouwWRg4OIaiLRUEGUh/1UAcH5lxdSLIA==} + engines: {node: '>=16.20.1'} + peerDependencies: + '@aws-sdk/credential-providers': ^3.188.0 + '@mongodb-js/zstd': ^1.1.0 + gcp-metadata: ^5.2.0 + kerberos: ^2.0.1 + mongodb-client-encryption: '>=6.0.0 <7' + snappy: ^7.2.2 + socks: ^2.7.1 + peerDependenciesMeta: + '@aws-sdk/credential-providers': + optional: true + '@mongodb-js/zstd': + optional: true + gcp-metadata: + optional: true + kerberos: + optional: true + mongodb-client-encryption: + optional: true + snappy: + optional: true + socks: + optional: true + + ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + msgpackr-extract@3.0.3: + resolution: {integrity: sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==} + hasBin: true + + msgpackr@1.11.0: + resolution: {integrity: sha512-I8qXuuALqJe5laEBYoFykChhSXLikZmUhccjGsPuSJ/7uPip2TJ7lwdIQwWSAi0jGZDXv4WOP8Qg65QZRuXxXw==} + + muggle-string@0.3.1: + resolution: {integrity: sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==} + + mustache@4.2.0: + resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==} + hasBin: true + + nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + needle@3.3.1: + resolution: {integrity: sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==} + engines: {node: '>= 4.4.x'} + hasBin: true + + node-abort-controller@3.1.1: + resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==} + + node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-gyp-build-optional-packages@5.2.2: + resolution: {integrity: sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==} + hasBin: true + + node-releases@2.0.18: + resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} + + npm-run-path@5.3.0: + resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + object-hash@2.2.0: + resolution: {integrity: sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==} + engines: {node: '>= 6'} + + object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + + object-inspect@1.13.2: + resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==} + engines: {node: '>= 0.4'} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + object.assign@4.1.5: + resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} + engines: {node: '>= 0.4'} + + object.fromentries@2.0.8: + resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} + engines: {node: '>= 0.4'} + + object.groupby@1.0.3: + resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} + engines: {node: '>= 0.4'} + + object.values@1.2.0: + resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==} + engines: {node: '>= 0.4'} + + oidc-token-hash@5.0.3: + resolution: {integrity: sha512-IF4PcGgzAr6XXSff26Sk/+P4KZFJVuHAJZj3wgO3vX2bMdNVp/QXTP3P7CEm9V1IdG8lDLY3HhiqpsE/nOwpPw==} + engines: {node: ^10.13.0 || >=12.0.0} + + ollama@0.5.9: + resolution: {integrity: sha512-F/KZuDRC+ZsVCuMvcOYuQ6zj42/idzCkkuknGyyGVmNStMZ/sU3jQpvhnl4SyC0+zBzLiKNZJnJeuPFuieWZvQ==} + + on-exit-leak-free@2.1.2: + resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} + engines: {node: '>=14.0.0'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + one-time@1.0.0: + resolution: {integrity: sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==} + + onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + + onetime@7.0.0: + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} + engines: {node: '>=18'} + + openai-chat-tokens@0.2.8: + resolution: {integrity: sha512-nW7QdFDIZlAYe6jsCT/VPJ/Lam3/w2DX9oxf/5wHpebBT49KI3TN43PPhYlq1klq2ajzXWKNOLY6U4FNZM7AoA==} + + openai@4.67.3: + resolution: {integrity: sha512-HT2tZgjLgRqbLQNKmYtjdF/4TQuiBvg1oGvTDhwpSEQzxo6/oM1us8VQ53vBK2BiKvCxFuq6gKGG70qfwrNhKg==} + hasBin: true + peerDependencies: + zod: ^3.23.8 + peerDependenciesMeta: + zod: + optional: true + + openapi-fetch@0.10.6: + resolution: {integrity: sha512-6xXfvIEL/POtLGOaFPsp3O+pDe+J3DZYxbD9BrsQHXOTeNK8z/gsWHT6adUy1KcpQOhmkerMzlQrJM6DbN55dQ==} + + openapi-fetch@0.11.3: + resolution: {integrity: sha512-r18fERgpxFrI4pv79ABD1dqFetWz7pTfwRd7jQmRm/lFdCDpWF43kvHUiOqOZu+tWsMydDJMpJN1hlZ9inRvfA==} + + openapi-fetch@0.8.2: + resolution: {integrity: sha512-4g+NLK8FmQ51RW6zLcCBOVy/lwYmFJiiT+ckYZxJWxUxH4XFhsNcX2eeqVMfVOi+mDNFja6qDXIZAz2c5J/RVw==} + + openapi-types@12.1.3: + resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==} + + openapi-typescript-helpers@0.0.11: + resolution: {integrity: sha512-xofUHlVFq+BMquf3nh9I8N2guHckW6mrDO/F3kaFgrL7MGbjldDnQ9TIT+rkH/+H0LiuO+RuZLnNmsJwsjwUKg==} + + openapi-typescript-helpers@0.0.13: + resolution: {integrity: sha512-z44WK2e7ygW3aUtAtiurfEACohf/Qt9g6BsejmIYgEoY4REHeRzgFJmO3ium0libsuzPc145I+8lE9aiiZrQvQ==} + + openapi-typescript-helpers@0.0.5: + resolution: {integrity: sha512-MRffg93t0hgGZbYTxg60hkRIK2sRuEOHEtCUgMuLgbCC33TMQ68AmxskzUlauzZYD47+ENeGV/ElI7qnWqrAxA==} + + openapi-typescript@7.4.1: + resolution: {integrity: sha512-HrRoWveViADezHCNgQqZmPKmQ74q7nuH/yg9ursFucZaYQNUqsX38fE/V2sKBHVM+pws4tAHpuh/ext2UJ/AoQ==} + hasBin: true + peerDependencies: + typescript: ^5.x + + openid-client@5.7.0: + resolution: {integrity: sha512-4GCCGZt1i2kTHpwvaC/sCpTpQqDnBzDzuJcJMbH+y1Q5qI8U8RBvoSh28svarXszZHR5BAMXbJPX1PGPRE3VOA==} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + ow@0.28.2: + resolution: {integrity: sha512-dD4UpyBh/9m4X2NVjA+73/ZPBRF+uF4zIMFvvQsabMiEK8x41L3rQ8EENOi35kyyoaJwNxEeJcP6Fj1H4U409Q==} + engines: {node: '>=12'} + + p-finally@1.0.0: + resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} + engines: {node: '>=4'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-limit@5.0.0: + resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==} + engines: {node: '>=18'} + + p-limit@6.1.0: + resolution: {integrity: sha512-H0jc0q1vOzlEk0TqAKXKZxdl7kX3OFUzCnNVUnq5Pc3DGo0kpeaMuPqxQn235HibwBEb0/pm9dgKTjXy66fBkg==} + engines: {node: '>=18'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-queue-compat@1.0.225: + resolution: {integrity: sha512-SdfGSQSJJpD7ZR+dJEjjn9GuuBizHPLW/yarJpXnmrHRruzrq7YM8OqsikSrKeoPv+Pi1YXw9IIBSIg5WveQHA==} + engines: {node: '>=12'} + + p-queue@6.6.2: + resolution: {integrity: sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==} + engines: {node: '>=8'} + + p-queue@8.0.1: + resolution: {integrity: sha512-NXzu9aQJTAzbBqOt2hwsR63ea7yvxJc0PwN/zobNAudYfb1B7R08SzB4TsLeSbUCuG467NhnoT0oO6w1qRO+BA==} + engines: {node: '>=18'} + + p-retry@4.6.2: + resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==} + engines: {node: '>=8'} + + p-throttle@6.2.0: + resolution: {integrity: sha512-NCKkOVj6PZa6NiTmfvGilDdf6vO1rFCD3KDnkHko8dTOtkpk4cSR/VTAhhLMG9aiQ7/A9HYgEDNmxzf6hxzR3g==} + engines: {node: '>=18'} + + p-timeout-compat@1.0.4: + resolution: {integrity: sha512-HEsjA3Df/845IQD0BS2/4691Sh2fnf8lifKHPtHUC6dQJ80NsKRCVVLnB5dApnJOU5JZJDWlE2Z0fd/vrGrUIA==} + engines: {node: '>=12'} + + p-timeout@3.2.0: + resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} + engines: {node: '>=8'} + + p-timeout@6.1.2: + resolution: {integrity: sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==} + engines: {node: '>=14.16'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parent-require@1.0.0: + resolution: {integrity: sha512-2MXDNZC4aXdkkap+rBBMv0lUsfJqvX5/2FiYYnfCnorZt3Pk06/IOR5KeaoghgS2w07MLWgjbsnyaq6PdHn2LQ==} + engines: {node: '>= 0.4.0'} + + parse-json@8.1.0: + resolution: {integrity: sha512-rum1bPifK5SSar35Z6EKZuYPJx85pkNaFrxBK3mwdfSJ1/WKbYrjoW/zTPSjRRamfmVX1ACBIdFAO0VRErW/EA==} + engines: {node: '>=18'} + + path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + path-type@5.0.0: + resolution: {integrity: sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==} + engines: {node: '>=12'} + + pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + + pathval@1.1.1: + resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} + + pend@1.2.0: + resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + + pg-connection-string@2.6.2: + resolution: {integrity: sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==} + + pg-connection-string@2.7.0: + resolution: {integrity: sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA==} + + pg-int8@1.0.1: + resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} + engines: {node: '>=4.0.0'} + + pg-protocol@1.7.0: + resolution: {integrity: sha512-hTK/mE36i8fDDhgDFjy6xNOG+LCorxLG3WO17tku+ij6sVHXh1jQUJ8hYAnRhNla4QVD2H8er/FOjc/+EgC6yQ==} + + pg-types@2.2.0: + resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} + engines: {node: '>=4'} + + picocolors@1.1.0: + resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + pidtree@0.6.0: + resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} + engines: {node: '>=0.10'} + hasBin: true + + pino-abstract-transport@1.2.0: + resolution: {integrity: sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==} + + pino-pretty@11.2.2: + resolution: {integrity: sha512-2FnyGir8nAJAqD3srROdrF1J5BIcMT4nwj7hHSc60El6Uxlym00UbCCd8pYIterstVBFlMyF1yFV8XdGIPbj4A==} + hasBin: true + + pino-std-serializers@7.0.0: + resolution: {integrity: sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==} + + pino@9.4.0: + resolution: {integrity: sha512-nbkQb5+9YPhQRz/BeQmrWpEknAaqjpAqRK8NwJpmrX/JHu7JuZC5G1CeAwJDJfGes4h+YihC6in3Q2nGb+Y09w==} + hasBin: true + + pkg-types@1.2.0: + resolution: {integrity: sha512-+ifYuSSqOQ8CqP4MbZA5hDpb97n3E8SVWdJe+Wms9kj745lmd3b7EZJiqvmLwAlmRfjrI7Hi5z3kdBJ93lFNPA==} + + pluralize@8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + + pony-cause@2.1.11: + resolution: {integrity: sha512-M7LhCsdNbNgiLYiP4WjsfLUuFmCfnjdF6jKe2R9NKl4WFN+HZPGHJZ9lnLP7f9ZnKe3U9nuWD0szirmj+migUg==} + engines: {node: '>=12.0.0'} + + possible-typed-array-names@1.0.0: + resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} + engines: {node: '>= 0.4'} + + postcss@8.4.47: + resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} + engines: {node: ^10 || ^12 || >=14} + + postgres-array@2.0.0: + resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} + engines: {node: '>=4'} + + postgres-bytea@1.0.0: + resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==} + engines: {node: '>=0.10.0'} + + postgres-date@1.0.7: + resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==} + engines: {node: '>=0.10.0'} + + postgres-interval@1.2.0: + resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==} + engines: {node: '>=0.10.0'} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prettier-linter-helpers@1.0.0: + resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} + engines: {node: '>=6.0.0'} + + prettier@3.3.3: + resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==} + engines: {node: '>=14'} + hasBin: true + + pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + process-warning@3.0.0: + resolution: {integrity: sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==} + + process-warning@4.0.0: + resolution: {integrity: sha512-/MyYDxttz7DfGMMHiysAsFE4qF+pQYAA8ziO/3NcRVrQ5fSk+Mns4QZA/oRPFzvcqNoVJXQNWNAsdwBXLUkQKw==} + + process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + + prom-client@15.1.3: + resolution: {integrity: sha512-6ZiOBfCywsD4k1BN9IX0uZhF+tJkV8q8llP64G5Hajs4JOeVLPCwpPVcpXy3BwYiUGgyJzsJJQeOIv7+hDSq8g==} + engines: {node: ^16 || ^18 || >=20} + + promise-based-task@3.1.0: + resolution: {integrity: sha512-YVG7pK/rWeN21PkwEeZIFh/sSTIxNfvYfdif9vAzcM1zFF8jBJMdAqwxh71XdhYyVOQESNEB43ih/A9wRcE0zw==} + + promise-coalesce@1.1.2: + resolution: {integrity: sha512-zLaJ9b8hnC564fnJH6NFSOGZYYdzrAJn2JUUIwzoQb32fG2QAakpDNM+CZo1km6keXkRXRM+hml1BFAPVnPkxg==} + engines: {node: '>=16'} + + protobufjs@7.4.0: + resolution: {integrity: sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==} + engines: {node: '>=12.0.0'} + + proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + pump@3.0.2: + resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} + + punycode@1.4.1: + resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + qs@6.13.0: + resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} + engines: {node: '>=0.6'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + quick-format-unescaped@4.0.4: + resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + + ranges-apply@7.0.16: + resolution: {integrity: sha512-4rGJHOyA7qatiMDg3vcETkc/TVBPU86/xZRTXff6o7a2neYLmj0EXUUAlhLVuiWAzTPHDPHOQxtk8EDrIF4ohg==} + engines: {node: '>=14.18.0'} + + ranges-merge@9.0.15: + resolution: {integrity: sha512-hvt4hx0FKIaVfjd1oKx0poL57ljxdL2KHC6bXBrAdsx2iCsH+x7nO/5J0k2veM/isnOcFZKp0ZKkiCjCtzy74Q==} + engines: {node: '>=14.18.0'} + + ranges-push@7.0.15: + resolution: {integrity: sha512-gXpBYQ5Umf3uG6jkJnw5ddok2Xfo5p22rAJBLrqzNKa7qkj3q5AOCoxfRPXEHUVaJutfXc9K9eGXdIzdyQKPkw==} + engines: {node: '>=14.18.0'} + + ranges-sort@6.0.11: + resolution: {integrity: sha512-fhNEG0vGi7bESitNNqNBAfYPdl2efB+1paFlI8BQDCNkruERKuuhG8LkQClDIVqUJLkrmKuOSPQ3xZHqVnVo3Q==} + engines: {node: '>=14.18.0'} + + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + readable-stream@4.5.2: + resolution: {integrity: sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + real-require@0.2.0: + resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} + engines: {node: '>= 12.13.0'} + + rechoir@0.8.0: + resolution: {integrity: sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==} + engines: {node: '>= 10.13.0'} + + redis-errors@1.2.0: + resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==} + engines: {node: '>=4'} + + redis-parser@3.0.0: + resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==} + engines: {node: '>=4'} + + reflect-metadata@0.2.2: + resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} + + regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + + regexp.prototype.flags@1.5.2: + resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} + engines: {node: '>= 0.4'} + + remeda@2.14.0: + resolution: {integrity: sha512-OSOhr9gGcb3AshMxlu9YnnUtKSkeYhj+AxWiWGfVh3HolYtJP5IF9vC1j1tq15uI7lxCPVd9qnnp43dOvZ840A==} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + require-in-the-middle@7.4.0: + resolution: {integrity: sha512-X34iHADNbNDfr6OTStIAHWSAvvKQRYgLO6duASaVf7J2VA3lvmNYboAHOuLC2huav1IwgZJtyEcJCKVzFxOSMQ==} + engines: {node: '>=8.6.0'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + resolve@1.19.0: + resolution: {integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==} + + resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + + restore-cursor@5.1.0: + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} + engines: {node: '>=18'} + + ret@0.4.3: + resolution: {integrity: sha512-0f4Memo5QP7WQyUEAYUO3esD/XjOc3Zjjg5CPsAq1p8sIu0XPeMbHJemKA0BO7tV0X7+A0FoEpbmHXWxPyD3wQ==} + engines: {node: '>=10'} + + retry-as-promised@7.0.4: + resolution: {integrity: sha512-XgmCoxKWkDofwH8WddD0w85ZfqYz+ZHlr5yo+3YUCfycWawU56T5ckWXsScsj5B8tqUcIG67DxXByo3VUgiAdA==} + + retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + + rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + + rollup@4.22.4: + resolution: {integrity: sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + safe-array-concat@1.1.2: + resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} + engines: {node: '>=0.4'} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-regex-test@1.0.3: + resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} + engines: {node: '>= 0.4'} + + safe-regex2@3.1.0: + resolution: {integrity: sha512-RAAZAGbap2kBfbVhvmnTFv73NWLMvDGOITFYTZBAaY8eR+Ir4ef7Up/e7amo+y1+AH+3PtLkrt9mvcTsG9LXug==} + + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + sax@1.4.1: + resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==} + + secure-json-parse@2.7.0: + resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} + + seedrandom@3.0.5: + resolution: {integrity: sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + + semver@7.6.3: + resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} + engines: {node: '>=10'} + hasBin: true + + sequelize-pool@7.1.0: + resolution: {integrity: sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg==} + engines: {node: '>= 10.0.0'} + + sequelize@6.37.3: + resolution: {integrity: sha512-V2FTqYpdZjPy3VQrZvjTPnOoLm0KudCRXfGWp48QwhyPPp2yW8z0p0sCYZd/em847Tl2dVxJJ1DR+hF+O77T7A==} + engines: {node: '>=10.0.0'} + peerDependencies: + ibm_db: '*' + mariadb: '*' + mysql2: '*' + oracledb: '*' + pg: '*' + pg-hstore: '*' + snowflake-sdk: '*' + sqlite3: '*' + tedious: '*' + peerDependenciesMeta: + ibm_db: + optional: true + mariadb: + optional: true + mysql2: + optional: true + oracledb: + optional: true + pg: + optional: true + pg-hstore: + optional: true + snowflake-sdk: + optional: true + sqlite3: + optional: true + tedious: + optional: true + + serialize-error@11.0.3: + resolution: {integrity: sha512-2G2y++21dhj2R7iHAdd0FIzjGwuKZld+7Pl/bTU6YIkrC2ZMbVUjm+luj6A6V34Rv9XfKJDKpTWu9W4Gse1D9g==} + engines: {node: '>=14.16'} + + set-cookie-parser@2.7.0: + resolution: {integrity: sha512-lXLOiqpkUumhRdFF3k1osNXCy9akgx/dyPZ5p8qAg9seJzXr5ZrlqZuWIMuY6ejOsVLE6flJ5/h3lsn57fQ/PQ==} + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + shimmer@1.2.1: + resolution: {integrity: sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==} + + side-channel@1.0.6: + resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} + engines: {node: '>= 0.4'} + + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + simple-swizzle@0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + slash@5.1.0: + resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} + engines: {node: '>=14.16'} + + slice-ansi@5.0.0: + resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} + engines: {node: '>=12'} + + slice-ansi@7.1.0: + resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} + engines: {node: '>=18'} + + sonic-boom@4.1.0: + resolution: {integrity: sha512-NGipjjRicyJJ03rPiZCJYjwlsuP2d1/5QUviozRXC7S3WdVWNK5e3Ojieb9CCyfhq2UC+3+SRd9nG3I2lPRvUw==} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + sparse-bitfield@3.0.3: + resolution: {integrity: sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==} + + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + sqlstring@2.3.3: + resolution: {integrity: sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==} + engines: {node: '>= 0.6'} + + stack-trace@0.0.10: + resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==} + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + standard-as-callback@2.1.0: + resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} + + statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + + std-env@3.7.0: + resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} + + stoppable@1.1.0: + resolution: {integrity: sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==} + engines: {node: '>=4', npm: '>=6'} + + stream-wormhole@1.1.0: + resolution: {integrity: sha512-gHFfL3px0Kctd6Po0M8TzEvt3De/xu6cnRrjlfYNhwbhLPLwigI2t1nc6jrzNuaYg5C4YF78PPFuQPzRiqn9ew==} + engines: {node: '>=4.0.0'} + + string-argv@0.3.2: + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} + engines: {node: '>=0.6.19'} + + string-collapse-leading-whitespace@7.0.7: + resolution: {integrity: sha512-jF9eynJoE6ezTCdYI8Qb02/ij/DlU9ItG93Dty4SWfJeLFrotOr+wH9IRiWHTqO3mjCyqBWEiU3uSTIbxYbAEQ==} + engines: {node: '>=14.18.0'} + + string-comparison@1.3.0: + resolution: {integrity: sha512-46aD+slEwybxAMPRII83ATbgMgTiz5P8mVd7Z6VJsCzSHFjdt1hkAVLeFxPIyEb11tc6ihpJTlIqoO0MCF6NPw==} + engines: {node: ^16.0.0 || >=18.0.0} + + string-left-right@6.0.17: + resolution: {integrity: sha512-nuyIV4D4ivnwT64E0TudmCRg52NfkumuEUilyoOrHb/Z2wEOF5I+9SI6P+veFKqWKZfGpAs6OqKe4nAjujARyw==} + engines: {node: '>=14.18.0'} + + string-strip-html@13.4.8: + resolution: {integrity: sha512-vlcRAtx5DN6zXGUx3EYGFg0/JOQWM65mqLgDaBHviQPP+ovUFzqZ30iQ+674JHWr9wNgnzFGxx9TGipPZMnZXg==} + engines: {node: '>=14.18.0'} + + string-trim-spaces-only@5.0.10: + resolution: {integrity: sha512-MhmjE5jNqb1Ylo+BARPRlsdChGLrnPpAUWrT1VOxo9WhWwKVUU6CbZTfjwKaQPYTGS/wsX/4Zek88FM2rEb5iA==} + engines: {node: '>=14.18.0'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + + string.fromcodepoint@0.2.1: + resolution: {integrity: sha512-n69H31OnxSGSZyZbgBlvYIXlrMhJQ0dQAX1js1QDhpaUH6zmU3QYlj07bCwCNlPOu3oRXIubGPl2gDGnHsiCqg==} + + string.prototype.trim@1.2.9: + resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} + engines: {node: '>= 0.4'} + + string.prototype.trimend@1.0.8: + resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==} + + string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + + strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + strip-literal@2.1.0: + resolution: {integrity: sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==} + + strnum@1.0.5: + resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==} + + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + + supports-color@9.4.0: + resolution: {integrity: sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==} + engines: {node: '>=12'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + synckit@0.9.1: + resolution: {integrity: sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==} + engines: {node: ^14.18.0 || >=16.0.0} + + tapable@2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + + tarn@3.0.2: + resolution: {integrity: sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ==} + engines: {node: '>=8.0.0'} + + tdigest@0.1.2: + resolution: {integrity: sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA==} + + text-hex@1.0.0: + resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==} + + text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + + thread-stream@3.1.0: + resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==} + + tildify@2.0.0: + resolution: {integrity: sha512-Cc+OraorugtXNfs50hU9KS369rFXCfgGLpfCfvlc+Ud5u6VWmUQsOAa9HbTvheQdYnrdJqqv1e5oIqXppMYnSw==} + engines: {node: '>=8'} + + tiny-emitter@2.1.0: + resolution: {integrity: sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==} + + tiny-invariant@1.3.3: + resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinypool@0.8.4: + resolution: {integrity: sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==} + engines: {node: '>=14.0.0'} + + tinyspy@2.2.1: + resolution: {integrity: sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==} + engines: {node: '>=14.0.0'} + + to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + toad-cache@3.7.0: + resolution: {integrity: sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==} + engines: {node: '>=12'} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + toposort-class@1.0.1: + resolution: {integrity: sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + tr46@4.1.1: + resolution: {integrity: sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==} + engines: {node: '>=14'} + + triple-beam@1.4.1: + resolution: {integrity: sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==} + engines: {node: '>= 14.0.0'} + + ts-algebra@2.0.0: + resolution: {integrity: sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==} + + ts-api-utils@1.3.0: + resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} + engines: {node: '>=16'} + peerDependencies: + typescript: '>=4.2.0' + + ts-morph@22.0.0: + resolution: {integrity: sha512-M9MqFGZREyeb5fTl6gNHKZLqBQA0TjA1lea+CR48R8EBTDuWrNqW6ccC5QvjNR4s6wDumD3LTCjOFSp9iwlzaw==} + + tsc-files@1.1.4: + resolution: {integrity: sha512-RePsRsOLru3BPpnf237y1Xe1oCGta8rmSYzM76kYo5tLGsv5R2r3s64yapYorGTPuuLyfS9NVbh9ydzmvNie2w==} + hasBin: true + peerDependencies: + typescript: '>=3' + + tsconfck@3.1.3: + resolution: {integrity: sha512-ulNZP1SVpRDesxeMLON/LtWM8HIgAJEIVpVVhBM6gsmvQ8+Rh+ZG7FWGvHh7Ah3pRABwVJWklWCr/BTZSv0xnQ==} + engines: {node: ^18 || >=20} + hasBin: true + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + tsconfig-paths@3.15.0: + resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} + + tsconfig-paths@4.2.0: + resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} + engines: {node: '>=6'} + + tslib@2.7.0: + resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} + + tslib@2.8.0: + resolution: {integrity: sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==} + + tsx@4.19.1: + resolution: {integrity: sha512-0flMz1lh74BR4wOvBjuh9olbnwqCPc35OOlfyzHba0Dc+QNUeWX/Gq2YTbnwcWPO3BMd8fkzRVrHcsR+a7z7rA==} + engines: {node: '>=18.0.0'} + hasBin: true + + turndown@7.2.0: + resolution: {integrity: sha512-eCZGBN4nNNqM9Owkv9HAtWRYfLA4h909E/WGAWWBpmB275ehNhZyk87/Tpvjbp0jjNl9XwCsbe6bm6CqFsgD+A==} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-detect@4.1.0: + resolution: {integrity: sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==} + engines: {node: '>=4'} + + type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + + type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + + type-fest@4.26.1: + resolution: {integrity: sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==} + engines: {node: '>=16'} + + typed-array-buffer@1.0.2: + resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} + engines: {node: '>= 0.4'} + + typed-array-byte-length@1.0.1: + resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} + engines: {node: '>= 0.4'} + + typed-array-byte-offset@1.0.2: + resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} + engines: {node: '>= 0.4'} + + typed-array-length@1.0.6: + resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} + engines: {node: '>= 0.4'} + + typed-function@4.2.1: + resolution: {integrity: sha512-EGjWssW7Tsk4DGfE+5yluuljS1OGYWiI1J6e8puZz9nTMM51Oug8CD5Zo4gWMsOhq5BI+1bF+rWTm4Vbj3ivRA==} + engines: {node: '>= 18'} + + typescript@5.4.2: + resolution: {integrity: sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==} + engines: {node: '>=14.17'} + hasBin: true + + typescript@5.5.4: + resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} + engines: {node: '>=14.17'} + hasBin: true + + ufo@1.5.4: + resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} + + umzug@3.8.0: + resolution: {integrity: sha512-FRBvdZxllW3eUzsqG3CIfgOVChUONrKNZozNOJfvmcfBn5pMKcJjICuMMEsDLHYa/aqd7a2NtXfYEG86XHe1lQ==} + engines: {node: '>=12'} + + unbox-primitive@1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + + undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + + undici@5.28.4: + resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==} + engines: {node: '>=14.0'} + + unescape-js@1.1.4: + resolution: {integrity: sha512-42SD8NOQEhdYntEiUQdYq/1V/YHwr1HLwlHuTJB5InVVdOSbgI6xu8jK5q65yIzuFCfczzyDF/7hbGzVbyCw0g==} + + unicorn-magic@0.1.0: + resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} + engines: {node: '>=18'} + + universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + update-browserslist-db@1.1.1: + resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js-replace@1.0.1: + resolution: {integrity: sha512-W+C9NWNLFOoBI2QWDp4UT9pv65r2w5Cx+3sTYFvtMdDBxkKt1syCqsUdSFAChbEe1uK5TfS04wt/nGwmaeIQ0g==} + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + url-template@2.0.8: + resolution: {integrity: sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==} + + url@0.11.4: + resolution: {integrity: sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==} + engines: {node: '>= 0.4'} + + utf8@3.0.0: + resolution: {integrity: sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + util@0.12.5: + resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} + + uuid@10.0.0: + resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} + hasBin: true + + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + + uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + + vali-date@1.0.0: + resolution: {integrity: sha512-sgECfZthyaCKW10N0fm27cg8HYTFK5qMWgypqkXMQ4Wbl/zZKx7xZICgcoxIIE+WFAP/MBL2EFwC/YvLxw3Zeg==} + engines: {node: '>=0.10.0'} + + validator@13.12.0: + resolution: {integrity: sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==} + engines: {node: '>= 0.10'} + + vite-node@1.6.0: + resolution: {integrity: sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + + vite-plugin-dts@3.9.1: + resolution: {integrity: sha512-rVp2KM9Ue22NGWB8dNtWEr+KekN3rIgz1tWD050QnRGlriUCmaDwa7qA5zDEjbXg5lAXhYMSBJtx3q3hQIJZSg==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + typescript: '*' + vite: '*' + peerDependenciesMeta: + vite: + optional: true + + vite-plugin-externalize-deps@0.8.0: + resolution: {integrity: sha512-MdC8kRNQ1ZjhUicU2HcqGVhL0UUFqv83Zp1JZdHjE82PoPR8wsSWZ3axpot7B6img3sW6g8shYJikE0CKA0chA==} + peerDependencies: + vite: ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 + + vite-tsconfig-paths@4.3.2: + resolution: {integrity: sha512-0Vd/a6po6Q+86rPlntHye7F31zA2URZMbH8M3saAZ/xR9QoGN/L21bxEGfXdWmFdNkqPpRdxFT7nmNe12e9/uA==} + peerDependencies: + vite: '*' + peerDependenciesMeta: + vite: + optional: true + + vite@5.4.8: + resolution: {integrity: sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + + vitest@1.6.0: + resolution: {integrity: sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': 1.6.0 + '@vitest/ui': 1.6.0 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + vue-template-compiler@2.7.16: + resolution: {integrity: sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==} + + vue-tsc@1.8.27: + resolution: {integrity: sha512-WesKCAZCRAbmmhuGl3+VrdWItEvfoFIPXOvUJkjULi+x+6G/Dy69yO3TBRJDr9eUlmsNAwVmxsNZxvHKzbkKdg==} + hasBin: true + peerDependencies: + typescript: '*' + + web-streams-polyfill@4.0.0-beta.3: + resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==} + engines: {node: '>= 14'} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + + whatwg-fetch@3.6.20: + resolution: {integrity: sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==} + + whatwg-url@13.0.0: + resolution: {integrity: sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==} + engines: {node: '>=16'} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + which-boxed-primitive@1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + + which-typed-array@1.1.15: + resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} + engines: {node: '>= 0.4'} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + + wikipedia@2.1.2: + resolution: {integrity: sha512-RAYaMpXC9/E873RaSEtlEa8dXK4e0p5k98GKOd210MtkE5emm6fcnwD+N6ZA4cuffjDWagvhaQKtp/mGp2BOVQ==} + engines: {node: '>=10'} + + winston-transport@4.7.1: + resolution: {integrity: sha512-wQCXXVgfv/wUPOfb2x0ruxzwkcZfxcktz6JIMUaPLmcNhO4bZTwA/WtDWK74xV3F2dKu8YadrFv0qhwYjVEwhA==} + engines: {node: '>= 12.0.0'} + + winston@3.14.2: + resolution: {integrity: sha512-CO8cdpBB2yqzEf8v895L+GNKYJiEq8eKlHU38af3snQBQ+sdAIUepjMSguOIJC7ICbzm0ZI+Af2If4vIJrtmOg==} + engines: {node: '>= 12.0.0'} + + wkx@0.5.0: + resolution: {integrity: sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==} + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrap-ansi@9.0.0: + resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} + engines: {node: '>=18'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + xml2js@0.6.2: + resolution: {integrity: sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==} + engines: {node: '>=4.0.0'} + + xmlbuilder@10.1.1: + resolution: {integrity: sha512-OyzrcFLL/nb6fMGHbiRDuPup9ljBycsdCypwuyg5AAHvyWzGfChJpCXMG88AGTIMFhGZ9RccFN1e6lhg3hkwKg==} + engines: {node: '>=4.0'} + + xmlbuilder@11.0.1: + resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} + engines: {node: '>=4.0'} + + xtend@4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + + yaml-ast-parser@0.0.43: + resolution: {integrity: sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==} + + yaml@2.5.1: + resolution: {integrity: sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==} + engines: {node: '>= 14'} + hasBin: true + + yaml@2.6.0: + resolution: {integrity: sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==} + engines: {node: '>= 14'} + hasBin: true + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yauzl@3.1.3: + resolution: {integrity: sha512-JCCdmlJJWv7L0q/KylOekyRaUrdEoUxWkWVcgorosTROCFWiS9p2NNPE9Yb91ak7b1N5SxAZEliWpspbZccivw==} + engines: {node: '>=12'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + yocto-queue@1.1.1: + resolution: {integrity: sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==} + engines: {node: '>=12.20'} + + z-schema@5.0.5: + resolution: {integrity: sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==} + engines: {node: '>=8.0.0'} + hasBin: true + + zod-to-json-schema@3.23.3: + resolution: {integrity: sha512-TYWChTxKQbRJp5ST22o/Irt9KC5nj7CdBKYB/AosCRdj/wxEMvv4NNaj9XVUHDOIp53ZxArGhnw5HMZziPFjog==} + peerDependencies: + zod: ^3.23.3 + + zod@3.23.8: + resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} + +snapshots: + + '@ai-zen/node-fetch-event-source@2.1.4': + dependencies: + cross-fetch: 4.0.0 + transitivePeerDependencies: + - encoding + + '@apidevtools/json-schema-ref-parser@11.7.2': + dependencies: + '@jsdevtools/ono': 7.1.3 + '@types/json-schema': 7.0.15 + js-yaml: 4.1.0 + + '@appsignal/opentelemetry-instrumentation-bullmq@0.7.3(bullmq@5.8.1)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + flat: 5.0.2 + optionalDependencies: + bullmq: 5.8.1 + transitivePeerDependencies: + - supports-color + + '@babel/code-frame@7.24.7': + dependencies: + '@babel/highlight': 7.24.7 + picocolors: 1.1.0 + + '@babel/helper-string-parser@7.24.8': {} + + '@babel/helper-validator-identifier@7.24.7': {} + + '@babel/highlight@7.24.7': + dependencies: + '@babel/helper-validator-identifier': 7.24.7 + chalk: 2.4.2 + js-tokens: 4.0.0 + picocolors: 1.1.0 + + '@babel/parser@7.25.3': + dependencies: + '@babel/types': 7.25.2 + + '@babel/runtime@7.25.0': + dependencies: + regenerator-runtime: 0.14.1 + + '@babel/runtime@7.25.7': + dependencies: + regenerator-runtime: 0.14.1 + + '@babel/types@7.25.2': + dependencies: + '@babel/helper-string-parser': 7.24.8 + '@babel/helper-validator-identifier': 7.24.7 + to-fast-properties: 2.0.0 + + '@bufbuild/protobuf@1.10.0': {} + + '@colors/colors@1.6.0': {} + + '@connectrpc/connect-node@1.6.1(@bufbuild/protobuf@1.10.0)(@connectrpc/connect@1.6.1(@bufbuild/protobuf@1.10.0))': + dependencies: + '@bufbuild/protobuf': 1.10.0 + '@connectrpc/connect': 1.6.1(@bufbuild/protobuf@1.10.0) + undici: 5.28.4 + + '@connectrpc/connect@1.6.1(@bufbuild/protobuf@1.10.0)': + dependencies: + '@bufbuild/protobuf': 1.10.0 + + '@dabh/diagnostics@2.0.3': + dependencies: + colorspace: 1.1.4 + enabled: 2.0.0 + kuler: 2.0.0 + + '@esbuild/aix-ppc64@0.21.5': + optional: true + + '@esbuild/aix-ppc64@0.23.0': + optional: true + + '@esbuild/android-arm64@0.21.5': + optional: true + + '@esbuild/android-arm64@0.23.0': + optional: true + + '@esbuild/android-arm@0.21.5': + optional: true + + '@esbuild/android-arm@0.23.0': + optional: true + + '@esbuild/android-x64@0.21.5': + optional: true + + '@esbuild/android-x64@0.23.0': + optional: true + + '@esbuild/darwin-arm64@0.21.5': + optional: true + + '@esbuild/darwin-arm64@0.23.0': + optional: true + + '@esbuild/darwin-x64@0.21.5': + optional: true + + '@esbuild/darwin-x64@0.23.0': + optional: true + + '@esbuild/freebsd-arm64@0.21.5': + optional: true + + '@esbuild/freebsd-arm64@0.23.0': + optional: true + + '@esbuild/freebsd-x64@0.21.5': + optional: true + + '@esbuild/freebsd-x64@0.23.0': + optional: true + + '@esbuild/linux-arm64@0.21.5': + optional: true + + '@esbuild/linux-arm64@0.23.0': + optional: true + + '@esbuild/linux-arm@0.21.5': + optional: true + + '@esbuild/linux-arm@0.23.0': + optional: true + + '@esbuild/linux-ia32@0.21.5': + optional: true + + '@esbuild/linux-ia32@0.23.0': + optional: true + + '@esbuild/linux-loong64@0.21.5': + optional: true + + '@esbuild/linux-loong64@0.23.0': + optional: true + + '@esbuild/linux-mips64el@0.21.5': + optional: true + + '@esbuild/linux-mips64el@0.23.0': + optional: true + + '@esbuild/linux-ppc64@0.21.5': + optional: true + + '@esbuild/linux-ppc64@0.23.0': + optional: true + + '@esbuild/linux-riscv64@0.21.5': + optional: true + + '@esbuild/linux-riscv64@0.23.0': + optional: true + + '@esbuild/linux-s390x@0.21.5': + optional: true + + '@esbuild/linux-s390x@0.23.0': + optional: true + + '@esbuild/linux-x64@0.21.5': + optional: true + + '@esbuild/linux-x64@0.23.0': + optional: true + + '@esbuild/netbsd-x64@0.21.5': + optional: true + + '@esbuild/netbsd-x64@0.23.0': + optional: true + + '@esbuild/openbsd-arm64@0.23.0': + optional: true + + '@esbuild/openbsd-x64@0.21.5': + optional: true + + '@esbuild/openbsd-x64@0.23.0': + optional: true + + '@esbuild/sunos-x64@0.21.5': + optional: true + + '@esbuild/sunos-x64@0.23.0': + optional: true + + '@esbuild/win32-arm64@0.21.5': + optional: true + + '@esbuild/win32-arm64@0.23.0': + optional: true + + '@esbuild/win32-ia32@0.21.5': + optional: true + + '@esbuild/win32-ia32@0.23.0': + optional: true + + '@esbuild/win32-x64@0.21.5': + optional: true + + '@esbuild/win32-x64@0.23.0': + optional: true + + '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)': + dependencies: + eslint: 8.57.0 + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.11.0': {} + + '@eslint/eslintrc@2.1.4': + dependencies: + ajv: 6.12.6 + debug: 4.3.6 + espree: 9.6.1 + globals: 13.24.0 + ignore: 5.3.2 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@8.57.0': {} + + '@fastify/accept-negotiator@1.1.0': {} + + '@fastify/ajv-compiler@3.6.0': + dependencies: + ajv: 8.17.1 + ajv-formats: 2.1.1(ajv@8.17.1) + fast-uri: 2.4.0 + + '@fastify/busboy@2.1.1': {} + + '@fastify/deepmerge@1.3.0': {} + + '@fastify/error@3.4.1': {} + + '@fastify/fast-json-stringify-compiler@4.3.0': + dependencies: + fast-json-stringify: 5.16.1 + + '@fastify/merge-json-schemas@0.1.1': + dependencies: + fast-deep-equal: 3.1.3 + + '@fastify/multipart@8.3.0': + dependencies: + '@fastify/busboy': 2.1.1 + '@fastify/deepmerge': 1.3.0 + '@fastify/error': 3.4.1 + fastify-plugin: 4.5.1 + secure-json-parse: 2.7.0 + stream-wormhole: 1.1.0 + + '@fastify/rate-limit@9.1.0': + dependencies: + '@lukeed/ms': 2.0.2 + fastify-plugin: 4.5.1 + toad-cache: 3.7.0 + + '@fastify/request-context@5.1.0': + dependencies: + fastify-plugin: 4.5.1 + + '@fastify/send@2.1.0': + dependencies: + '@lukeed/ms': 2.0.2 + escape-html: 1.0.3 + fast-decode-uri-component: 1.0.1 + http-errors: 2.0.0 + mime: 3.0.0 + + '@fastify/static@7.0.4': + dependencies: + '@fastify/accept-negotiator': 1.1.0 + '@fastify/send': 2.1.0 + content-disposition: 0.5.4 + fastify-plugin: 4.5.1 + fastq: 1.17.1 + glob: 10.4.5 + + '@fastify/swagger-ui@3.1.0': + dependencies: + '@fastify/static': 7.0.4 + fastify-plugin: 4.5.1 + openapi-types: 12.1.3 + rfdc: 1.4.1 + yaml: 2.5.1 + + '@fastify/swagger@8.15.0': + dependencies: + fastify-plugin: 4.5.1 + json-schema-resolver: 2.0.0 + openapi-types: 12.1.3 + rfdc: 1.4.1 + yaml: 2.5.1 + transitivePeerDependencies: + - supports-color + + '@fastify/type-provider-json-schema-to-ts@3.0.0(fastify@4.28.1)(json-schema-to-ts@3.1.0)': + dependencies: + fastify: 4.28.1 + json-schema-to-ts: 3.1.0 + + '@godaddy/terminus@4.12.1': + dependencies: + stoppable: 1.1.0 + + '@googleapis/customsearch@3.2.0': + dependencies: + googleapis-common: 7.2.0 + transitivePeerDependencies: + - encoding + - supports-color + + '@grpc/grpc-js@1.11.1': + dependencies: + '@grpc/proto-loader': 0.7.13 + '@js-sdsl/ordered-map': 4.4.2 + + '@grpc/proto-loader@0.7.13': + dependencies: + lodash.camelcase: 4.3.0 + long: 5.2.3 + protobufjs: 7.4.0 + yargs: 17.7.2 + + '@humanwhocodes/config-array@0.11.14': + dependencies: + '@humanwhocodes/object-schema': 2.0.3 + debug: 4.3.6 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/object-schema@2.0.3': {} + + '@ibm-generative-ai/node-sdk@3.2.3(@langchain/core@0.2.23(langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8)))': + dependencies: + '@ai-zen/node-fetch-event-source': 2.1.4 + '@langchain/core': 0.2.23(langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8)) + fetch-retry: 5.0.6 + http-status-codes: 2.3.0 + openapi-fetch: 0.8.2 + p-queue-compat: 1.0.225 + yaml: 2.5.1 + transitivePeerDependencies: + - encoding + + '@ioredis/commands@1.2.0': {} + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@jercle/yargonaut@1.1.5': + dependencies: + chalk: 4.1.2 + figlet: 1.7.0 + parent-require: 1.0.0 + + '@jest/schemas@29.6.3': + dependencies: + '@sinclair/typebox': 0.27.8 + + '@jridgewell/sourcemap-codec@1.5.0': {} + + '@js-sdsl/ordered-map@4.4.2': {} + + '@jsdevtools/ono@7.1.3': {} + + '@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8))': + dependencies: + '@langchain/core': 0.2.33(openai@4.67.3(zod@3.23.8)) + '@langchain/openai': 0.2.11 + binary-extensions: 2.3.0 + expr-eval: 2.0.2 + flat: 5.0.2 + js-yaml: 4.1.0 + langchain: 0.2.20(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)) + langsmith: 0.1.66(openai@4.67.3(zod@3.23.8)) + uuid: 10.0.0 + zod: 3.23.8 + zod-to-json-schema: 3.23.3(zod@3.23.8) + optionalDependencies: + '@langchain/langgraph': 0.0.34(openai@4.67.3(zod@3.23.8)) + '@zilliz/milvus2-sdk-node': 2.4.4 + duck-duck-scrape: 2.2.5 + google-auth-library: 9.14.2 + ignore: 5.3.2 + ioredis: 5.4.1 + lodash: 4.17.21 + mongodb: 6.7.0(gcp-metadata@6.1.0) + transitivePeerDependencies: + - '@gomomento/sdk-web' + - '@langchain/anthropic' + - '@langchain/aws' + - '@langchain/cohere' + - '@langchain/google-genai' + - '@langchain/google-vertexai' + - '@langchain/groq' + - '@langchain/mistralai' + - '@langchain/ollama' + - axios + - encoding + - fast-xml-parser + - handlebars + - openai + - peggy + - pyodide + + '@langchain/core@0.2.23(langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8))': + dependencies: + ansi-styles: 5.2.0 + camelcase: 6.3.0 + decamelize: 1.2.0 + js-tiktoken: 1.0.12 + langsmith: 0.1.41(@langchain/core@0.2.23(langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8)))(langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8)) + mustache: 4.2.0 + p-queue: 6.6.2 + p-retry: 4.6.2 + uuid: 10.0.0 + zod: 3.23.8 + zod-to-json-schema: 3.23.3(zod@3.23.8) + transitivePeerDependencies: + - langchain + - openai + + '@langchain/core@0.2.23(langchain@0.2.20(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8))': + dependencies: + ansi-styles: 5.2.0 + camelcase: 6.3.0 + decamelize: 1.2.0 + js-tiktoken: 1.0.12 + langsmith: 0.1.41(@langchain/core@0.2.23(langchain@0.2.20(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8)))(langchain@0.2.20(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8)) + mustache: 4.2.0 + p-queue: 6.6.2 + p-retry: 4.6.2 + uuid: 10.0.0 + zod: 3.23.8 + zod-to-json-schema: 3.23.3(zod@3.23.8) + transitivePeerDependencies: + - langchain + - openai + + '@langchain/core@0.2.33(openai@4.67.3(zod@3.23.8))': + dependencies: + ansi-styles: 5.2.0 + camelcase: 6.3.0 + decamelize: 1.2.0 + js-tiktoken: 1.0.15 + langsmith: 0.1.66(openai@4.67.3(zod@3.23.8)) + mustache: 4.2.0 + p-queue: 6.6.2 + p-retry: 4.6.2 + uuid: 10.0.0 + zod: 3.23.8 + zod-to-json-schema: 3.23.3(zod@3.23.8) + transitivePeerDependencies: + - openai + + '@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8))': + dependencies: + '@langchain/core': 0.2.33(openai@4.67.3(zod@3.23.8)) + uuid: 10.0.0 + zod: 3.23.8 + transitivePeerDependencies: + - openai + + '@langchain/openai@0.2.11': + dependencies: + '@langchain/core': 0.2.33(openai@4.67.3(zod@3.23.8)) + js-tiktoken: 1.0.15 + openai: 4.67.3(zod@3.23.8) + zod: 3.23.8 + zod-to-json-schema: 3.23.3(zod@3.23.8) + transitivePeerDependencies: + - encoding + + '@langchain/openai@0.2.6(langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))': + dependencies: + '@langchain/core': 0.2.23(langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8)) + js-tiktoken: 1.0.12 + openai: 4.67.3(zod@3.23.8) + zod: 3.23.8 + zod-to-json-schema: 3.23.3(zod@3.23.8) + transitivePeerDependencies: + - encoding + - langchain + + '@langchain/textsplitters@0.0.3(langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8))': + dependencies: + '@langchain/core': 0.2.23(langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8)) + js-tiktoken: 1.0.12 + transitivePeerDependencies: + - langchain + - openai + + '@langchain/textsplitters@0.0.3(langchain@0.2.20(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8))': + dependencies: + '@langchain/core': 0.2.23(langchain@0.2.20(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8)) + js-tiktoken: 1.0.12 + transitivePeerDependencies: + - langchain + - openai + + '@lukeed/ms@2.0.2': {} + + '@microsoft/api-extractor-model@7.28.13(@types/node@20.14.15)': + dependencies: + '@microsoft/tsdoc': 0.14.2 + '@microsoft/tsdoc-config': 0.16.2 + '@rushstack/node-core-library': 4.0.2(@types/node@20.14.15) + transitivePeerDependencies: + - '@types/node' + + '@microsoft/api-extractor@7.43.0(@types/node@20.14.15)': + dependencies: + '@microsoft/api-extractor-model': 7.28.13(@types/node@20.14.15) + '@microsoft/tsdoc': 0.14.2 + '@microsoft/tsdoc-config': 0.16.2 + '@rushstack/node-core-library': 4.0.2(@types/node@20.14.15) + '@rushstack/rig-package': 0.5.2 + '@rushstack/terminal': 0.10.0(@types/node@20.14.15) + '@rushstack/ts-command-line': 4.19.1(@types/node@20.14.15) + lodash: 4.17.21 + minimatch: 3.0.8 + resolve: 1.22.8 + semver: 7.5.4 + source-map: 0.6.1 + typescript: 5.4.2 + transitivePeerDependencies: + - '@types/node' + + '@microsoft/tsdoc-config@0.16.2': + dependencies: + '@microsoft/tsdoc': 0.14.2 + ajv: 6.12.6 + jju: 1.4.0 + resolve: 1.19.0 + + '@microsoft/tsdoc@0.14.2': {} + + '@mikro-orm/cli@6.2.9': + dependencies: + '@jercle/yargonaut': 1.1.5 + '@mikro-orm/core': 6.2.9 + '@mikro-orm/knex': 6.2.9(@mikro-orm/core@6.2.9) + fs-extra: 11.2.0 + tsconfig-paths: 4.2.0 + yargs: 17.7.2 + transitivePeerDependencies: + - better-sqlite3 + - libsql + - mariadb + - mysql + - mysql2 + - pg + - pg-native + - sqlite3 + - supports-color + - tedious + + '@mikro-orm/core@6.2.9': + dependencies: + dataloader: 2.2.2 + dotenv: 16.4.5 + esprima: 4.0.1 + fs-extra: 11.2.0 + globby: 11.1.0 + mikro-orm: 6.2.9 + reflect-metadata: 0.2.2 + + '@mikro-orm/knex@6.2.9(@mikro-orm/core@6.2.9)': + dependencies: + '@mikro-orm/core': 6.2.9 + fs-extra: 11.2.0 + knex: 3.1.0 + sqlstring: 2.3.3 + transitivePeerDependencies: + - mysql + - mysql2 + - pg + - pg-native + - sqlite3 + - supports-color + - tedious + + '@mikro-orm/migrations-mongodb@6.2.9(@mikro-orm/core@6.2.9)(@types/node@20.14.15)(gcp-metadata@6.1.0)': + dependencies: + '@mikro-orm/core': 6.2.9 + '@mikro-orm/mongodb': 6.2.9(@mikro-orm/core@6.2.9)(gcp-metadata@6.1.0) + fs-extra: 11.2.0 + mongodb: 6.7.0(gcp-metadata@6.1.0) + umzug: 3.8.0(@types/node@20.14.15) + transitivePeerDependencies: + - '@aws-sdk/credential-providers' + - '@mongodb-js/zstd' + - '@types/node' + - gcp-metadata + - kerberos + - mongodb-client-encryption + - snappy + - socks + + '@mikro-orm/mongodb@6.2.9(@mikro-orm/core@6.2.9)(gcp-metadata@6.1.0)': + dependencies: + '@mikro-orm/core': 6.2.9 + bson: 6.8.0 + mongodb: 6.7.0(gcp-metadata@6.1.0) + transitivePeerDependencies: + - '@aws-sdk/credential-providers' + - '@mongodb-js/zstd' + - gcp-metadata + - kerberos + - mongodb-client-encryption + - snappy + - socks + + '@mikro-orm/reflection@6.2.9(@mikro-orm/core@6.2.9)': + dependencies: + '@mikro-orm/core': 6.2.9 + globby: 11.1.0 + ts-morph: 22.0.0 + + '@mikro-orm/seeder@6.2.9(@mikro-orm/core@6.2.9)': + dependencies: + '@mikro-orm/core': 6.2.9 + fs-extra: 11.2.0 + globby: 11.1.0 + + '@mixmark-io/domino@2.2.0': {} + + '@mongodb-js/saslprep@1.1.8': + dependencies: + sparse-bitfield: 3.0.3 + + '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3': + optional: true + + '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3': + optional: true + + '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3': + optional: true + + '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3': + optional: true + + '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3': + optional: true + + '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3': + optional: true + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.17.1 + + '@opentelemetry/api-logs@0.52.1': + dependencies: + '@opentelemetry/api': 1.9.0 + + '@opentelemetry/api-logs@0.53.0': + dependencies: + '@opentelemetry/api': 1.9.0 + + '@opentelemetry/api@1.9.0': {} + + '@opentelemetry/auto-instrumentations-node@0.50.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-amqplib': 0.42.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-aws-lambda': 0.44.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-aws-sdk': 0.44.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-bunyan': 0.41.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-cassandra-driver': 0.41.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-connect': 0.39.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-cucumber': 0.9.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-dataloader': 0.12.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-dns': 0.39.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-express': 0.42.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-fastify': 0.39.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-fs': 0.15.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-generic-pool': 0.39.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-graphql': 0.43.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-grpc': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-hapi': 0.41.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-http': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-ioredis': 0.43.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-kafkajs': 0.3.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-knex': 0.40.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-koa': 0.43.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-lru-memoizer': 0.40.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-memcached': 0.39.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-mongodb': 0.47.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-mongoose': 0.42.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-mysql': 0.41.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-mysql2': 0.41.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-nestjs-core': 0.40.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-net': 0.39.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-pg': 0.44.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-pino': 0.42.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-redis': 0.42.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-redis-4': 0.42.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-restify': 0.41.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-router': 0.40.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-socket.io': 0.42.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-tedious': 0.14.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-undici': 0.6.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-winston': 0.40.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resource-detector-alibaba-cloud': 0.29.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resource-detector-aws': 1.6.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resource-detector-azure': 0.2.11(@opentelemetry/api@1.9.0) + '@opentelemetry/resource-detector-container': 0.4.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resource-detector-gcp': 0.29.11(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-node': 0.53.0(@opentelemetry/api@1.9.0) + transitivePeerDependencies: + - encoding + - supports-color + + '@opentelemetry/context-async-hooks@1.26.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + + '@opentelemetry/core@1.26.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/semantic-conventions': 1.27.0 + + '@opentelemetry/exporter-logs-otlp-grpc@0.53.0(@opentelemetry/api@1.9.0)': + dependencies: + '@grpc/grpc-js': 1.11.1 + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-grpc-exporter-base': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-logs': 0.53.0(@opentelemetry/api@1.9.0) + + '@opentelemetry/exporter-logs-otlp-http@0.53.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.53.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-logs': 0.53.0(@opentelemetry/api@1.9.0) + + '@opentelemetry/exporter-logs-otlp-proto@0.53.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.53.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-logs': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.26.0(@opentelemetry/api@1.9.0) + + '@opentelemetry/exporter-metrics-otlp-http@0.53.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-metrics': 1.26.0(@opentelemetry/api@1.9.0) + + '@opentelemetry/exporter-trace-otlp-grpc@0.53.0(@opentelemetry/api@1.9.0)': + dependencies: + '@grpc/grpc-js': 1.11.1 + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-grpc-exporter-base': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.26.0(@opentelemetry/api@1.9.0) + + '@opentelemetry/exporter-trace-otlp-http@0.53.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.26.0(@opentelemetry/api@1.9.0) + + '@opentelemetry/exporter-trace-otlp-proto@0.53.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.26.0(@opentelemetry/api@1.9.0) + + '@opentelemetry/exporter-zipkin@1.26.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + + '@opentelemetry/instrumentation-amqplib@0.42.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-aws-lambda@0.44.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/propagator-aws-xray': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + '@types/aws-lambda': 8.10.143 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-aws-sdk@0.44.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/propagation-utils': 0.30.11(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-bunyan@0.41.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.53.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@types/bunyan': 1.8.9 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-cassandra-driver@0.41.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-connect@0.39.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + '@types/connect': 3.4.36 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-cucumber@0.9.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-dataloader@0.12.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-dns@0.39.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + semver: 7.6.3 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-express@0.42.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-fastify@0.39.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-fs@0.15.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-generic-pool@0.39.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-graphql@0.43.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-grpc@0.53.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-hapi@0.41.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-http@0.53.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + semver: 7.6.3 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-ioredis@0.43.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/redis-common': 0.36.2 + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-kafkajs@0.3.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-knex@0.40.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-koa@0.43.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-lru-memoizer@0.40.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-memcached@0.39.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + '@types/memcached': 2.2.10 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-mongodb@0.47.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-metrics': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-mongoose@0.42.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-mysql2@0.41.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + '@opentelemetry/sql-common': 0.40.1(@opentelemetry/api@1.9.0) + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-mysql@0.41.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + '@types/mysql': 2.15.26 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-nestjs-core@0.40.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-net@0.39.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-pg@0.44.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + '@opentelemetry/sql-common': 0.40.1(@opentelemetry/api@1.9.0) + '@types/pg': 8.6.1 + '@types/pg-pool': 2.0.6 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-pino@0.42.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.53.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-redis-4@0.42.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/redis-common': 0.36.2 + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-redis@0.42.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/redis-common': 0.36.2 + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-restify@0.41.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-router@0.40.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-socket.io@0.42.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-tedious@0.14.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + '@types/tedious': 4.0.14 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-undici@0.6.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation-winston@0.40.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.53.0 + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation@0.52.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.52.1 + '@types/shimmer': 1.2.0 + import-in-the-middle: 1.11.2 + require-in-the-middle: 7.4.0 + semver: 7.6.3 + shimmer: 1.2.1 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation@0.53.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.53.0 + '@types/shimmer': 1.2.0 + import-in-the-middle: 1.11.2 + require-in-the-middle: 7.4.0 + semver: 7.6.3 + shimmer: 1.2.1 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/otlp-exporter-base@0.53.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.53.0(@opentelemetry/api@1.9.0) + + '@opentelemetry/otlp-grpc-exporter-base@0.53.0(@opentelemetry/api@1.9.0)': + dependencies: + '@grpc/grpc-js': 1.11.1 + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.53.0(@opentelemetry/api@1.9.0) + + '@opentelemetry/otlp-transformer@0.53.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.53.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-logs': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-metrics': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.26.0(@opentelemetry/api@1.9.0) + protobufjs: 7.4.0 + + '@opentelemetry/propagation-utils@0.30.11(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + + '@opentelemetry/propagator-aws-xray@1.26.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + + '@opentelemetry/propagator-b3@1.26.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + + '@opentelemetry/propagator-jaeger@1.26.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + + '@opentelemetry/redis-common@0.36.2': {} + + '@opentelemetry/resource-detector-alibaba-cloud@0.29.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/resources': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + + '@opentelemetry/resource-detector-aws@1.6.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + + '@opentelemetry/resource-detector-azure@0.2.11(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + + '@opentelemetry/resource-detector-container@0.4.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/resources': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + + '@opentelemetry/resource-detector-gcp@0.29.11(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + gcp-metadata: 6.1.0 + transitivePeerDependencies: + - encoding + - supports-color + + '@opentelemetry/resources@1.26.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + + '@opentelemetry/sdk-logs@0.53.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.53.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.26.0(@opentelemetry/api@1.9.0) + + '@opentelemetry/sdk-metrics@1.26.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.26.0(@opentelemetry/api@1.9.0) + + '@opentelemetry/sdk-node@0.53.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.53.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-logs-otlp-grpc': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-logs-otlp-http': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-logs-otlp-proto': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-trace-otlp-grpc': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-trace-otlp-http': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-trace-otlp-proto': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-zipkin': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-logs': 0.53.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-metrics': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-node': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/sdk-trace-base@1.26.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.27.0 + + '@opentelemetry/sdk-trace-node@1.26.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/context-async-hooks': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/propagator-b3': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/propagator-jaeger': 1.26.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.26.0(@opentelemetry/api@1.9.0) + semver: 7.6.3 + + '@opentelemetry/semantic-conventions@1.27.0': {} + + '@opentelemetry/sql-common@0.40.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.26.0(@opentelemetry/api@1.9.0) + + '@petamoriken/float16@3.8.7': {} + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@pkgr/core@0.1.1': {} + + '@protobufjs/aspromise@1.1.2': {} + + '@protobufjs/base64@1.1.2': {} + + '@protobufjs/codegen@2.0.4': {} + + '@protobufjs/eventemitter@1.1.0': {} + + '@protobufjs/fetch@1.1.0': + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/inquire': 1.1.0 + + '@protobufjs/float@1.0.2': {} + + '@protobufjs/inquire@1.1.0': {} + + '@protobufjs/path@1.1.2': {} + + '@protobufjs/pool@1.1.0': {} + + '@protobufjs/utf8@1.1.0': {} + + '@redocly/ajv@8.11.2': + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js-replace: 1.0.1 + + '@redocly/config@0.11.0': {} + + '@redocly/openapi-core@1.25.3(supports-color@9.4.0)': + dependencies: + '@redocly/ajv': 8.11.2 + '@redocly/config': 0.11.0 + colorette: 1.4.0 + https-proxy-agent: 7.0.5(supports-color@9.4.0) + js-levenshtein: 1.1.6 + js-yaml: 4.1.0 + lodash.isequal: 4.5.0 + minimatch: 5.1.6 + node-fetch: 2.7.0 + pluralize: 8.0.0 + yaml-ast-parser: 0.0.43 + transitivePeerDependencies: + - encoding + - supports-color + + '@rollup/pluginutils@5.1.0(rollup@4.22.4)': + dependencies: + '@types/estree': 1.0.5 + estree-walker: 2.0.2 + picomatch: 2.3.1 + optionalDependencies: + rollup: 4.22.4 + + '@rollup/rollup-android-arm-eabi@4.22.4': + optional: true + + '@rollup/rollup-android-arm64@4.22.4': + optional: true + + '@rollup/rollup-darwin-arm64@4.22.4': + optional: true + + '@rollup/rollup-darwin-x64@4.22.4': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.22.4': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.22.4': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.22.4': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.22.4': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.22.4': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.22.4': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.22.4': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.22.4': + optional: true + + '@rollup/rollup-linux-x64-musl@4.22.4': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.22.4': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.22.4': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.22.4': + optional: true + + '@rushstack/node-core-library@4.0.2(@types/node@20.14.15)': + dependencies: + fs-extra: 7.0.1 + import-lazy: 4.0.0 + jju: 1.4.0 + resolve: 1.22.8 + semver: 7.5.4 + z-schema: 5.0.5 + optionalDependencies: + '@types/node': 20.14.15 + + '@rushstack/node-core-library@5.5.1(@types/node@20.14.15)': + dependencies: + ajv: 8.13.0 + ajv-draft-04: 1.0.0(ajv@8.13.0) + ajv-formats: 3.0.1(ajv@8.13.0) + fs-extra: 7.0.1 + import-lazy: 4.0.0 + jju: 1.4.0 + resolve: 1.22.8 + semver: 7.5.4 + optionalDependencies: + '@types/node': 20.14.15 + + '@rushstack/rig-package@0.5.2': + dependencies: + resolve: 1.22.8 + strip-json-comments: 3.1.1 + + '@rushstack/terminal@0.10.0(@types/node@20.14.15)': + dependencies: + '@rushstack/node-core-library': 4.0.2(@types/node@20.14.15) + supports-color: 8.1.1 + optionalDependencies: + '@types/node': 20.14.15 + + '@rushstack/terminal@0.13.3(@types/node@20.14.15)': + dependencies: + '@rushstack/node-core-library': 5.5.1(@types/node@20.14.15) + supports-color: 8.1.1 + optionalDependencies: + '@types/node': 20.14.15 + + '@rushstack/ts-command-line@4.19.1(@types/node@20.14.15)': + dependencies: + '@rushstack/terminal': 0.10.0(@types/node@20.14.15) + '@types/argparse': 1.0.38 + argparse: 1.0.10 + string-argv: 0.3.2 + transitivePeerDependencies: + - '@types/node' + + '@rushstack/ts-command-line@4.22.4(@types/node@20.14.15)': + dependencies: + '@rushstack/terminal': 0.13.3(@types/node@20.14.15) + '@types/argparse': 1.0.38 + argparse: 1.0.10 + string-argv: 0.3.2 + transitivePeerDependencies: + - '@types/node' + + '@sinclair/typebox@0.27.8': {} + + '@sindresorhus/is@4.6.0': {} + + '@sindresorhus/merge-streams@2.3.0': {} + + '@streamparser/json@0.0.21': {} + + '@ts-morph/common@0.23.0': + dependencies: + fast-glob: 3.3.2 + minimatch: 9.0.5 + mkdirp: 3.0.1 + path-browserify: 1.0.1 + + '@types/argparse@1.0.38': {} + + '@types/aws-lambda@8.10.143': {} + + '@types/bunyan@1.8.9': + dependencies: + '@types/node': 20.16.10 + + '@types/connect@3.4.36': + dependencies: + '@types/node': 20.16.10 + + '@types/debug@4.1.12': + dependencies: + '@types/ms': 0.7.34 + + '@types/estree@1.0.5': {} + + '@types/json-schema@7.0.15': {} + + '@types/json5@0.0.29': {} + + '@types/jsonwebtoken@9.0.6': + dependencies: + '@types/node': 20.14.15 + + '@types/lodash-es@4.17.12': + dependencies: + '@types/lodash': 4.17.10 + + '@types/lodash@4.17.10': {} + + '@types/memcached@2.2.10': + dependencies: + '@types/node': 20.16.10 + + '@types/ms@0.7.34': {} + + '@types/mysql@2.15.26': + dependencies: + '@types/node': 20.16.10 + + '@types/node-fetch@2.6.11': + dependencies: + '@types/node': 20.16.11 + form-data: 4.0.0 + + '@types/node@18.19.55': + dependencies: + undici-types: 5.26.5 + + '@types/node@20.14.15': + dependencies: + undici-types: 5.26.5 + + '@types/node@20.16.10': + dependencies: + undici-types: 6.19.8 + + '@types/node@20.16.11': + dependencies: + undici-types: 6.19.8 + + '@types/pg-pool@2.0.6': + dependencies: + '@types/pg': 8.6.1 + + '@types/pg@8.6.1': + dependencies: + '@types/node': 20.16.10 + pg-protocol: 1.7.0 + pg-types: 2.2.0 + + '@types/retry@0.12.0': {} + + '@types/shimmer@1.2.0': {} + + '@types/tedious@4.0.14': + dependencies: + '@types/node': 20.16.10 + + '@types/triple-beam@1.3.5': {} + + '@types/uuid@10.0.0': {} + + '@types/uuid@9.0.8': {} + + '@types/validator@13.12.2': {} + + '@types/webidl-conversions@7.0.3': {} + + '@types/whatwg-url@11.0.5': + dependencies: + '@types/webidl-conversions': 7.0.3 + + '@types/yauzl@2.10.3': + dependencies: + '@types/node': 20.14.15 + + '@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0)(typescript@5.5.4)': + dependencies: + '@eslint-community/regexpp': 4.11.0 + '@typescript-eslint/parser': 7.18.0(eslint@8.57.0)(typescript@5.5.4) + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/type-utils': 7.18.0(eslint@8.57.0)(typescript@5.5.4) + '@typescript-eslint/utils': 7.18.0(eslint@8.57.0)(typescript@5.5.4) + '@typescript-eslint/visitor-keys': 7.18.0 + eslint: 8.57.0 + graphemer: 1.4.0 + ignore: 5.3.2 + natural-compare: 1.4.0 + ts-api-utils: 1.3.0(typescript@5.5.4) + optionalDependencies: + typescript: 5.5.4 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4)': + dependencies: + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.5.4) + '@typescript-eslint/visitor-keys': 7.18.0 + debug: 4.3.6 + eslint: 8.57.0 + optionalDependencies: + typescript: 5.5.4 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@7.18.0': + dependencies: + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/visitor-keys': 7.18.0 + + '@typescript-eslint/type-utils@7.18.0(eslint@8.57.0)(typescript@5.5.4)': + dependencies: + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.5.4) + '@typescript-eslint/utils': 7.18.0(eslint@8.57.0)(typescript@5.5.4) + debug: 4.3.6 + eslint: 8.57.0 + ts-api-utils: 1.3.0(typescript@5.5.4) + optionalDependencies: + typescript: 5.5.4 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@7.18.0': {} + + '@typescript-eslint/typescript-estree@7.18.0(typescript@5.5.4)': + dependencies: + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/visitor-keys': 7.18.0 + debug: 4.3.6 + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.6.3 + ts-api-utils: 1.3.0(typescript@5.5.4) + optionalDependencies: + typescript: 5.5.4 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@7.18.0(eslint@8.57.0)(typescript@5.5.4)': + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.5.4) + eslint: 8.57.0 + transitivePeerDependencies: + - supports-color + - typescript + + '@typescript-eslint/visitor-keys@7.18.0': + dependencies: + '@typescript-eslint/types': 7.18.0 + eslint-visitor-keys: 3.4.3 + + '@ungap/structured-clone@1.2.0': {} + + '@vitest/expect@1.6.0': + dependencies: + '@vitest/spy': 1.6.0 + '@vitest/utils': 1.6.0 + chai: 4.5.0 + + '@vitest/runner@1.6.0': + dependencies: + '@vitest/utils': 1.6.0 + p-limit: 5.0.0 + pathe: 1.1.2 + + '@vitest/snapshot@1.6.0': + dependencies: + magic-string: 0.30.11 + pathe: 1.1.2 + pretty-format: 29.7.0 + + '@vitest/spy@1.6.0': + dependencies: + tinyspy: 2.2.1 + + '@vitest/utils@1.6.0': + dependencies: + diff-sequences: 29.6.3 + estree-walker: 3.0.3 + loupe: 2.3.7 + pretty-format: 29.7.0 + + '@volar/language-core@1.11.1': + dependencies: + '@volar/source-map': 1.11.1 + + '@volar/source-map@1.11.1': + dependencies: + muggle-string: 0.3.1 + + '@volar/typescript@1.11.1': + dependencies: + '@volar/language-core': 1.11.1 + path-browserify: 1.0.1 + + '@vue/compiler-core@3.4.37': + dependencies: + '@babel/parser': 7.25.3 + '@vue/shared': 3.4.37 + entities: 5.0.0 + estree-walker: 2.0.2 + source-map-js: 1.2.1 + + '@vue/compiler-dom@3.4.37': + dependencies: + '@vue/compiler-core': 3.4.37 + '@vue/shared': 3.4.37 + + '@vue/language-core@1.8.27(typescript@5.5.4)': + dependencies: + '@volar/language-core': 1.11.1 + '@volar/source-map': 1.11.1 + '@vue/compiler-dom': 3.4.37 + '@vue/shared': 3.4.37 + computeds: 0.0.1 + minimatch: 9.0.5 + muggle-string: 0.3.1 + path-browserify: 1.0.1 + vue-template-compiler: 2.7.16 + optionalDependencies: + typescript: 5.5.4 + + '@vue/shared@3.4.37': {} + + '@zilliz/milvus2-sdk-node@2.4.4': + dependencies: + '@grpc/grpc-js': 1.11.1 + '@grpc/proto-loader': 0.7.13 + '@petamoriken/float16': 3.8.7 + dayjs: 1.11.12 + generic-pool: 3.9.0 + lru-cache: 9.1.2 + protobufjs: 7.4.0 + winston: 3.14.2 + + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 + + abstract-logging@2.0.1: {} + + acorn-import-attributes@1.9.5(acorn@8.12.1): + dependencies: + acorn: 8.12.1 + + acorn-jsx@5.3.2(acorn@8.12.1): + dependencies: + acorn: 8.12.1 + + acorn-walk@8.3.3: + dependencies: + acorn: 8.12.1 + + acorn@8.12.1: {} + + adm-zip@0.5.16: {} + + agent-base@7.1.1(supports-color@9.4.0): + dependencies: + debug: 4.3.7(supports-color@9.4.0) + transitivePeerDependencies: + - supports-color + + agentkeepalive@4.5.0: + dependencies: + humanize-ms: 1.2.1 + + ajv-draft-04@1.0.0(ajv@8.13.0): + optionalDependencies: + ajv: 8.13.0 + + ajv-formats@2.1.1(ajv@8.17.1): + optionalDependencies: + ajv: 8.17.1 + + ajv-formats@3.0.1(ajv@8.13.0): + optionalDependencies: + ajv: 8.13.0 + + ajv-formats@3.0.1(ajv@8.17.1): + optionalDependencies: + ajv: 8.17.1 + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ajv@8.13.0: + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + + ajv@8.17.1: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.0.1 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ansi-colors@4.1.3: {} + + ansi-escapes@7.0.0: + dependencies: + environment: 1.1.0 + + ansi-regex@5.0.1: {} + + ansi-regex@6.0.1: {} + + ansi-styles@3.2.1: + dependencies: + color-convert: 1.9.3 + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@5.2.0: {} + + ansi-styles@6.2.1: {} + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + + argparse@2.0.1: {} + + array-buffer-byte-length@1.0.1: + dependencies: + call-bind: 1.0.7 + is-array-buffer: 3.0.4 + + array-includes@3.1.8: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 + get-intrinsic: 1.2.4 + is-string: 1.0.7 + + array-union@2.1.0: {} + + array.prototype.findlastindex@1.2.5: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + es-shim-unscopables: 1.0.2 + + array.prototype.flat@1.3.2: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-shim-unscopables: 1.0.2 + + array.prototype.flatmap@1.3.2: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-shim-unscopables: 1.0.2 + + arraybuffer.prototype.slice@1.0.3: + dependencies: + array-buffer-byte-length: 1.0.1 + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + is-array-buffer: 3.0.4 + is-shared-array-buffer: 1.0.3 + + assertion-error@1.1.0: {} + + async@3.2.5: {} + + asynckit@0.4.0: {} + + atomic-sleep@1.0.0: {} + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.0.0 + + avvio@8.4.0: + dependencies: + '@fastify/error': 3.4.1 + fastq: 1.17.1 + + axios@1.7.7: + dependencies: + follow-redirects: 1.15.9 + form-data: 4.0.0 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + balanced-match@1.0.2: {} + + base64-js@1.5.1: {} + + ? bee-agent-framework@0.0.32(@bufbuild/protobuf@1.10.0)(@googleapis/customsearch@3.2.0)(@grpc/grpc-js@1.11.1)(@grpc/proto-loader@0.7.13)(@ibm-generative-ai/node-sdk@3.2.3(@langchain/core@0.2.23(langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8))))(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(@langchain/core@0.2.23(langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8)))(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(groq-sdk@0.7.0)(ollama@0.5.9)(openai-chat-tokens@0.2.8)(openai@4.67.3(zod@3.23.8))(sequelize@6.37.3) + : dependencies: + '@ai-zen/node-fetch-event-source': 2.1.4 + '@connectrpc/connect': 1.6.1(@bufbuild/protobuf@1.10.0) + '@connectrpc/connect-node': 1.6.1(@bufbuild/protobuf@1.10.0)(@connectrpc/connect@1.6.1(@bufbuild/protobuf@1.10.0)) + '@googleapis/customsearch': 3.2.0 + '@grpc/grpc-js': 1.11.1 + '@grpc/proto-loader': 0.7.13 + '@ibm-generative-ai/node-sdk': 3.2.3(@langchain/core@0.2.23(langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8))) + '@langchain/community': 0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)) + '@langchain/core': 0.2.23(langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8)) + '@langchain/langgraph': 0.0.34(openai@4.67.3(zod@3.23.8)) + '@streamparser/json': 0.0.21 + ajv: 8.17.1 + ajv-formats: 3.0.1(ajv@8.17.1) + bee-proto: 0.0.2 + dirty-json: 0.9.2 + duck-duck-scrape: 2.2.5 + fast-xml-parser: 4.5.0 + groq-sdk: 0.7.0 + header-generator: 2.1.56 + joplin-turndown-plugin-gfm: 1.0.12 + js-yaml: 4.1.0 + json-schema-to-typescript: 15.0.2 + jsonrepair: 3.8.1 + mathjs: 13.2.0 + mustache: 4.2.0 + object-hash: 3.0.0 + ollama: 0.5.9 + openai: 4.67.3(zod@3.23.8) + openai-chat-tokens: 0.2.8 + p-queue: 8.0.1 + p-throttle: 6.2.0 + pino: 9.4.0 + promise-based-task: 3.1.0 + remeda: 2.14.0 + sequelize: 6.37.3 + serialize-error: 11.0.3 + string-comparison: 1.3.0 + string-strip-html: 13.4.8 + turndown: 7.2.0 + wikipedia: 2.1.2 + zod: 3.23.8 + zod-to-json-schema: 3.23.3(zod@3.23.8) + transitivePeerDependencies: + - '@bufbuild/protobuf' + - debug + - encoding + + ? bee-observe-connector@0.0.4(bee-agent-framework@0.0.32(@bufbuild/protobuf@1.10.0)(@googleapis/customsearch@3.2.0)(@grpc/grpc-js@1.11.1)(@grpc/proto-loader@0.7.13)(@ibm-generative-ai/node-sdk@3.2.3(@langchain/core@0.2.23(langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8))))(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(@langchain/core@0.2.23(langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8)))(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(groq-sdk@0.7.0)(ollama@0.5.9)(openai-chat-tokens@0.2.8)(openai@4.67.3(zod@3.23.8))(sequelize@6.37.3)) + : dependencies: + bee-agent-framework: 0.0.32(@bufbuild/protobuf@1.10.0)(@googleapis/customsearch@3.2.0)(@grpc/grpc-js@1.11.1)(@grpc/proto-loader@0.7.13)(@ibm-generative-ai/node-sdk@3.2.3(@langchain/core@0.2.23(langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8))))(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(@langchain/core@0.2.23(langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8)))(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(groq-sdk@0.7.0)(ollama@0.5.9)(openai-chat-tokens@0.2.8)(openai@4.67.3(zod@3.23.8))(sequelize@6.37.3) + openapi-fetch: 0.11.3 + + bee-proto@0.0.2: + dependencies: + '@bufbuild/protobuf': 1.10.0 + '@connectrpc/connect': 1.6.1(@bufbuild/protobuf@1.10.0) + + bignumber.js@9.1.2: {} + + binary-extensions@2.3.0: {} + + bintrees@1.0.2: {} + + brace-expansion@1.1.11: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browserslist@4.24.0: + dependencies: + caniuse-lite: 1.0.30001669 + electron-to-chromium: 1.5.39 + node-releases: 2.0.18 + update-browserslist-db: 1.1.1(browserslist@4.24.0) + + bson@6.8.0: {} + + buffer-crc32@0.2.13: {} + + buffer-equal-constant-time@1.0.1: {} + + buffer@4.9.2: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + isarray: 1.0.0 + + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + bullmq@5.8.1: + dependencies: + cron-parser: 4.9.0 + ioredis: 5.4.1 + msgpackr: 1.11.0 + node-abort-controller: 3.1.1 + semver: 7.6.3 + tslib: 2.7.0 + uuid: 9.0.1 + transitivePeerDependencies: + - supports-color + + cac@6.7.14: {} + + cache-manager@5.7.6: + dependencies: + eventemitter3: 5.0.1 + lodash.clonedeep: 4.5.0 + lru-cache: 10.4.3 + promise-coalesce: 1.1.2 + + call-bind@1.0.7: + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + set-function-length: 1.2.2 + + callsites@3.1.0: {} + + camelcase@4.1.0: {} + + camelcase@6.3.0: {} + + caniuse-lite@1.0.30001669: {} + + chai@4.5.0: + dependencies: + assertion-error: 1.1.0 + check-error: 1.0.3 + deep-eql: 4.1.4 + get-func-name: 2.0.2 + loupe: 2.3.7 + pathval: 1.1.1 + type-detect: 4.1.0 + + chalk@2.4.2: + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@5.3.0: {} + + change-case@5.4.4: {} + + check-error@1.0.3: + dependencies: + get-func-name: 2.0.2 + + cjs-module-lexer@1.4.1: {} + + cli-cursor@5.0.0: + dependencies: + restore-cursor: 5.1.0 + + cli-truncate@4.0.0: + dependencies: + slice-ansi: 5.0.0 + string-width: 7.2.0 + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + cluster-key-slot@1.1.2: {} + + code-block-writer@13.0.2: {} + + codsen-utils@1.6.4: + dependencies: + rfdc: 1.4.1 + + color-convert@1.9.3: + dependencies: + color-name: 1.1.3 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.3: {} + + color-name@1.1.4: {} + + color-string@1.9.1: + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + + color@3.2.1: + dependencies: + color-convert: 1.9.3 + color-string: 1.9.1 + + colorette@1.4.0: {} + + colorette@2.0.19: {} + + colorette@2.0.20: {} + + colorspace@1.1.4: + dependencies: + color: 3.2.1 + text-hex: 1.0.0 + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + commander@10.0.1: {} + + commander@12.1.0: {} + + commander@9.5.0: + optional: true + + complex.js@2.3.0: {} + + computeds@0.0.1: {} + + concat-map@0.0.1: {} + + confbox@0.1.7: {} + + content-disposition@0.5.4: + dependencies: + safe-buffer: 5.2.1 + + cookie@0.6.0: {} + + cron-parser@4.9.0: + dependencies: + luxon: 3.5.0 + + cross-fetch@4.0.0: + dependencies: + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + + cross-spawn@7.0.3: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + data-view-buffer@1.0.1: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + + data-view-byte-length@1.0.1: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + + data-view-byte-offset@1.0.0: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + + dataloader@2.2.2: {} + + dateformat@4.6.3: {} + + dayjs@1.11.12: {} + + de-indent@1.0.2: {} + + debug@3.2.7: + dependencies: + ms: 2.1.3 + + debug@4.3.4: + dependencies: + ms: 2.1.2 + + debug@4.3.6: + dependencies: + ms: 2.1.2 + + debug@4.3.7(supports-color@9.4.0): + dependencies: + ms: 2.1.3 + optionalDependencies: + supports-color: 9.4.0 + + decamelize@1.2.0: {} + + decimal.js@10.4.3: {} + + deep-eql@4.1.4: + dependencies: + type-detect: 4.1.0 + + deep-is@0.1.4: {} + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + gopd: 1.0.1 + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + delayed-stream@1.0.0: {} + + denque@2.1.0: {} + + depd@2.0.0: {} + + detect-libc@2.0.3: + optional: true + + diff-sequences@29.6.3: {} + + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + dirty-json@0.9.2: + dependencies: + lex: 1.7.9 + unescape-js: 1.1.4 + utf8: 3.0.0 + + doctrine@2.1.0: + dependencies: + esutils: 2.0.3 + + doctrine@3.0.0: + dependencies: + esutils: 2.0.3 + + dot-prop@6.0.1: + dependencies: + is-obj: 2.0.0 + + dotenv@16.4.5: {} + + dottie@2.0.6: {} + + duck-duck-scrape@2.2.5: + dependencies: + html-entities: 2.5.2 + needle: 3.3.1 + + eastasianwidth@0.2.0: {} + + ecdsa-sig-formatter@1.0.11: + dependencies: + safe-buffer: 5.2.1 + + electron-to-chromium@1.5.39: {} + + emittery@0.13.1: {} + + emoji-regex@10.3.0: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + enabled@2.0.0: {} + + end-of-stream@1.4.4: + dependencies: + once: 1.4.0 + + enhanced-resolve@5.17.1: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + + entities@5.0.0: {} + + environment@1.1.0: {} + + es-abstract@1.23.3: + dependencies: + array-buffer-byte-length: 1.0.1 + arraybuffer.prototype.slice: 1.0.3 + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 + data-view-buffer: 1.0.1 + data-view-byte-length: 1.0.1 + data-view-byte-offset: 1.0.0 + es-define-property: 1.0.0 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + es-set-tostringtag: 2.0.3 + es-to-primitive: 1.2.1 + function.prototype.name: 1.1.6 + get-intrinsic: 1.2.4 + get-symbol-description: 1.0.2 + globalthis: 1.0.4 + gopd: 1.0.1 + has-property-descriptors: 1.0.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + hasown: 2.0.2 + internal-slot: 1.0.7 + is-array-buffer: 3.0.4 + is-callable: 1.2.7 + is-data-view: 1.0.1 + is-negative-zero: 2.0.3 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.3 + is-string: 1.0.7 + is-typed-array: 1.1.13 + is-weakref: 1.0.2 + object-inspect: 1.13.2 + object-keys: 1.1.1 + object.assign: 4.1.5 + regexp.prototype.flags: 1.5.2 + safe-array-concat: 1.1.2 + safe-regex-test: 1.0.3 + string.prototype.trim: 1.2.9 + string.prototype.trimend: 1.0.8 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.2 + typed-array-byte-length: 1.0.1 + typed-array-byte-offset: 1.0.2 + typed-array-length: 1.0.6 + unbox-primitive: 1.0.2 + which-typed-array: 1.1.15 + + es-define-property@1.0.0: + dependencies: + get-intrinsic: 1.2.4 + + es-errors@1.3.0: {} + + es-object-atoms@1.0.0: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.0.3: + dependencies: + get-intrinsic: 1.2.4 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + es-shim-unscopables@1.0.2: + dependencies: + hasown: 2.0.2 + + es-to-primitive@1.2.1: + dependencies: + is-callable: 1.2.7 + is-date-object: 1.0.5 + is-symbol: 1.0.4 + + esbuild@0.21.5: + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + + esbuild@0.23.0: + optionalDependencies: + '@esbuild/aix-ppc64': 0.23.0 + '@esbuild/android-arm': 0.23.0 + '@esbuild/android-arm64': 0.23.0 + '@esbuild/android-x64': 0.23.0 + '@esbuild/darwin-arm64': 0.23.0 + '@esbuild/darwin-x64': 0.23.0 + '@esbuild/freebsd-arm64': 0.23.0 + '@esbuild/freebsd-x64': 0.23.0 + '@esbuild/linux-arm': 0.23.0 + '@esbuild/linux-arm64': 0.23.0 + '@esbuild/linux-ia32': 0.23.0 + '@esbuild/linux-loong64': 0.23.0 + '@esbuild/linux-mips64el': 0.23.0 + '@esbuild/linux-ppc64': 0.23.0 + '@esbuild/linux-riscv64': 0.23.0 + '@esbuild/linux-s390x': 0.23.0 + '@esbuild/linux-x64': 0.23.0 + '@esbuild/netbsd-x64': 0.23.0 + '@esbuild/openbsd-arm64': 0.23.0 + '@esbuild/openbsd-x64': 0.23.0 + '@esbuild/sunos-x64': 0.23.0 + '@esbuild/win32-arm64': 0.23.0 + '@esbuild/win32-ia32': 0.23.0 + '@esbuild/win32-x64': 0.23.0 + + escalade@3.1.2: {} + + escalade@3.2.0: {} + + escape-html@1.0.3: {} + + escape-latex@1.2.0: {} + + escape-string-regexp@1.0.5: {} + + escape-string-regexp@4.0.0: {} + + eslint-config-prettier@9.1.0(eslint@8.57.0): + dependencies: + eslint: 8.57.0 + + eslint-import-resolver-node@0.3.9: + dependencies: + debug: 3.2.7 + is-core-module: 2.15.0 + resolve: 1.22.8 + transitivePeerDependencies: + - supports-color + + eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@8.57.0): + dependencies: + debug: 4.3.6 + enhanced-resolve: 5.17.1 + eslint: 8.57.0 + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + fast-glob: 3.3.2 + get-tsconfig: 4.7.6 + is-core-module: 2.15.0 + is-glob: 4.0.3 + transitivePeerDependencies: + - '@typescript-eslint/parser' + - eslint-import-resolver-node + - eslint-import-resolver-webpack + - supports-color + + eslint-module-utils@2.8.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0): + dependencies: + debug: 3.2.7 + optionalDependencies: + '@typescript-eslint/parser': 7.18.0(eslint@8.57.0)(typescript@5.5.4) + eslint: 8.57.0 + eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@8.57.0) + transitivePeerDependencies: + - supports-color + + eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): + dependencies: + array-includes: 3.1.8 + array.prototype.findlastindex: 1.2.5 + array.prototype.flat: 1.3.2 + array.prototype.flatmap: 1.3.2 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 8.57.0 + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) + hasown: 2.0.2 + is-core-module: 2.15.0 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.fromentries: 2.0.8 + object.groupby: 1.0.3 + object.values: 1.2.0 + semver: 6.3.1 + tsconfig-paths: 3.15.0 + optionalDependencies: + '@typescript-eslint/parser': 7.18.0(eslint@8.57.0)(typescript@5.5.4) + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + + eslint-plugin-prettier@5.2.1(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.3.3): + dependencies: + eslint: 8.57.0 + prettier: 3.3.3 + prettier-linter-helpers: 1.0.0 + synckit: 0.9.1 + optionalDependencies: + eslint-config-prettier: 9.1.0(eslint@8.57.0) + + eslint-scope@7.2.2: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint@8.57.0: + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint-community/regexpp': 4.11.0 + '@eslint/eslintrc': 2.1.4 + '@eslint/js': 8.57.0 + '@humanwhocodes/config-array': 0.11.14 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + '@ungap/structured-clone': 1.2.0 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.6 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.24.0 + graphemer: 1.4.0 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + strip-ansi: 6.0.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + + esm@3.2.25: {} + + espree@9.6.1: + dependencies: + acorn: 8.12.1 + acorn-jsx: 5.3.2(acorn@8.12.1) + eslint-visitor-keys: 3.4.3 + + esprima@4.0.1: {} + + esquery@1.6.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + estree-walker@2.0.2: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.5 + + esutils@2.0.3: {} + + event-target-shim@5.0.1: {} + + eventemitter3@4.0.7: {} + + eventemitter3@5.0.1: {} + + events@3.3.0: {} + + execa@8.0.1: + dependencies: + cross-spawn: 7.0.3 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + + expr-eval@2.0.2: {} + + extend@3.0.2: {} + + fast-content-type-parse@1.1.0: {} + + fast-copy@3.0.2: {} + + fast-decode-uri-component@1.0.1: {} + + fast-deep-equal@3.1.3: {} + + fast-diff@1.3.0: {} + + fast-glob@3.3.2: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-json-stable-stringify@2.1.0: {} + + fast-json-stringify@5.16.1: + dependencies: + '@fastify/merge-json-schemas': 0.1.1 + ajv: 8.17.1 + ajv-formats: 3.0.1(ajv@8.17.1) + fast-deep-equal: 3.1.3 + fast-uri: 2.4.0 + json-schema-ref-resolver: 1.0.1 + rfdc: 1.4.1 + + fast-levenshtein@2.0.6: {} + + fast-querystring@1.1.2: + dependencies: + fast-decode-uri-component: 1.0.1 + + fast-redact@3.5.0: {} + + fast-safe-stringify@2.1.1: {} + + fast-uri@2.4.0: {} + + fast-uri@3.0.1: {} + + fast-xml-parser@4.5.0: + dependencies: + strnum: 1.0.5 + + fastify-plugin@4.5.1: {} + + fastify@4.28.1: + dependencies: + '@fastify/ajv-compiler': 3.6.0 + '@fastify/error': 3.4.1 + '@fastify/fast-json-stringify-compiler': 4.3.0 + abstract-logging: 2.0.1 + avvio: 8.4.0 + fast-content-type-parse: 1.1.0 + fast-json-stringify: 5.16.1 + find-my-way: 8.2.0 + light-my-request: 5.13.0 + pino: 9.4.0 + process-warning: 3.0.0 + proxy-addr: 2.0.7 + rfdc: 1.4.1 + secure-json-parse: 2.7.0 + semver: 7.6.3 + toad-cache: 3.7.0 + + fastq@1.17.1: + dependencies: + reusify: 1.0.4 + + fecha@4.2.3: {} + + fetch-retry@5.0.6: {} + + figlet@1.7.0: {} + + file-entry-cache@6.0.1: + dependencies: + flat-cache: 3.2.0 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + find-my-way@8.2.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-querystring: 1.1.2 + safe-regex2: 3.1.0 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@3.2.0: + dependencies: + flatted: 3.3.1 + keyv: 4.5.4 + rimraf: 3.0.2 + + flat@5.0.2: {} + + flatted@3.3.1: {} + + fn.name@1.1.0: {} + + follow-redirects@1.15.9: {} + + for-each@0.3.3: + dependencies: + is-callable: 1.2.7 + + foreground-child@3.3.0: + dependencies: + cross-spawn: 7.0.3 + signal-exit: 4.1.0 + + form-data-encoder@1.7.2: {} + + form-data@4.0.0: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + + formdata-node@4.4.1: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 4.0.0-beta.3 + + forwarded@0.2.0: {} + + fraction.js@4.3.7: {} + + fs-extra@11.2.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + fs-extra@7.0.1: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fs.realpath@1.0.0: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + function.prototype.name@1.1.6: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + functions-have-names: 1.2.3 + + functions-have-names@1.2.3: {} + + gaxios@6.7.1: + dependencies: + extend: 3.0.2 + https-proxy-agent: 7.0.5(supports-color@9.4.0) + is-stream: 2.0.1 + node-fetch: 2.7.0 + uuid: 9.0.1 + transitivePeerDependencies: + - encoding + - supports-color + + gcp-metadata@6.1.0: + dependencies: + gaxios: 6.7.1 + json-bigint: 1.0.0 + transitivePeerDependencies: + - encoding + - supports-color + + generative-bayesian-network@2.1.56: + dependencies: + adm-zip: 0.5.16 + tslib: 2.8.0 + + generic-pool@3.9.0: {} + + get-caller-file@2.0.5: {} + + get-east-asian-width@1.2.0: {} + + get-func-name@2.0.2: {} + + get-intrinsic@1.2.4: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + hasown: 2.0.2 + + get-package-type@0.1.0: {} + + get-stream@8.0.1: {} + + get-symbol-description@1.0.2: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + + get-tsconfig@4.7.6: + dependencies: + resolve-pkg-maps: 1.0.0 + + getopts@2.3.0: {} + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob@10.4.5: + dependencies: + foreground-child: 3.3.0 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + + globals@13.24.0: + dependencies: + type-fest: 0.20.2 + + globalthis@1.0.4: + dependencies: + define-properties: 1.2.1 + gopd: 1.0.1 + + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.2 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + + globby@14.0.2: + dependencies: + '@sindresorhus/merge-streams': 2.3.0 + fast-glob: 3.3.2 + ignore: 5.3.2 + path-type: 5.0.0 + slash: 5.1.0 + unicorn-magic: 0.1.0 + + globrex@0.1.2: {} + + google-auth-library@9.14.2: + dependencies: + base64-js: 1.5.1 + ecdsa-sig-formatter: 1.0.11 + gaxios: 6.7.1 + gcp-metadata: 6.1.0 + gtoken: 7.1.0 + jws: 4.0.0 + transitivePeerDependencies: + - encoding + - supports-color + + googleapis-common@7.2.0: + dependencies: + extend: 3.0.2 + gaxios: 6.7.1 + google-auth-library: 9.14.2 + qs: 6.13.0 + url-template: 2.0.8 + uuid: 9.0.1 + transitivePeerDependencies: + - encoding + - supports-color + + gopd@1.0.1: + dependencies: + get-intrinsic: 1.2.4 + + graceful-fs@4.2.11: {} + + graphemer@1.4.0: {} + + groq-sdk@0.7.0: + dependencies: + '@types/node': 18.19.55 + '@types/node-fetch': 2.6.11 + abort-controller: 3.0.0 + agentkeepalive: 4.5.0 + form-data-encoder: 1.7.2 + formdata-node: 4.4.1 + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + + gtoken@7.1.0: + dependencies: + gaxios: 6.7.1 + jws: 4.0.0 + transitivePeerDependencies: + - encoding + - supports-color + + has-bigints@1.0.2: {} + + has-flag@3.0.0: {} + + has-flag@4.0.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.0 + + has-proto@1.0.3: {} + + has-symbols@1.0.3: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.0.3 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + he@1.2.0: {} + + header-generator@2.1.56: + dependencies: + browserslist: 4.24.0 + generative-bayesian-network: 2.1.56 + ow: 0.28.2 + tslib: 2.8.0 + + help-me@5.0.0: {} + + html-entities@2.5.2: {} + + http-errors@2.0.0: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + + http-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.1(supports-color@9.4.0) + debug: 4.3.7(supports-color@9.4.0) + transitivePeerDependencies: + - supports-color + + http-status-codes@2.3.0: {} + + https-proxy-agent@7.0.5(supports-color@9.4.0): + dependencies: + agent-base: 7.1.1(supports-color@9.4.0) + debug: 4.3.7(supports-color@9.4.0) + transitivePeerDependencies: + - supports-color + + human-signals@5.0.0: {} + + humanize-ms@1.2.1: + dependencies: + ms: 2.1.3 + + husky@9.1.4: {} + + ibm-cos-sdk@1.13.4: + dependencies: + buffer: 4.9.2 + jmespath: 0.16.0 + url: 0.11.4 + util: 0.12.5 + uuid: 8.3.2 + xml2js: 0.6.2 + xmlbuilder: 10.1.1 + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + + ieee754@1.2.1: {} + + ignore@5.3.2: {} + + import-fresh@3.3.0: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + import-in-the-middle@1.11.2: + dependencies: + acorn: 8.12.1 + acorn-import-attributes: 1.9.5(acorn@8.12.1) + cjs-module-lexer: 1.4.1 + module-details-from-path: 1.0.3 + + import-lazy@4.0.0: {} + + imurmurhash@0.1.4: {} + + index-to-position@0.1.2: {} + + inflection@1.13.4: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + infobox-parser@3.6.4: + dependencies: + camelcase: 4.1.0 + + inherits@2.0.4: {} + + internal-slot@1.0.7: + dependencies: + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.0.6 + + interpret@2.2.0: {} + + ioredis@5.4.1: + dependencies: + '@ioredis/commands': 1.2.0 + cluster-key-slot: 1.1.2 + debug: 4.3.6 + denque: 2.1.0 + lodash.defaults: 4.2.0 + lodash.isarguments: 3.1.0 + redis-errors: 1.2.0 + redis-parser: 3.0.0 + standard-as-callback: 2.1.0 + transitivePeerDependencies: + - supports-color + + ipaddr.js@1.9.1: {} + + is-arguments@1.1.1: + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + + is-array-buffer@3.0.4: + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + + is-arrayish@0.3.2: {} + + is-bigint@1.0.4: + dependencies: + has-bigints: 1.0.2 + + is-boolean-object@1.1.2: + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + + is-callable@1.2.7: {} + + is-core-module@2.15.0: + dependencies: + hasown: 2.0.2 + + is-data-view@1.0.1: + dependencies: + is-typed-array: 1.1.13 + + is-date-object@1.0.5: + dependencies: + has-tostringtag: 1.0.2 + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-fullwidth-code-point@4.0.0: {} + + is-fullwidth-code-point@5.0.0: + dependencies: + get-east-asian-width: 1.2.0 + + is-generator-function@1.0.10: + dependencies: + has-tostringtag: 1.0.2 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-negative-zero@2.0.3: {} + + is-number-object@1.0.7: + dependencies: + has-tostringtag: 1.0.2 + + is-number@7.0.0: {} + + is-obj@2.0.0: {} + + is-path-inside@3.0.3: {} + + is-regex@1.1.4: + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + + is-shared-array-buffer@1.0.3: + dependencies: + call-bind: 1.0.7 + + is-stream@2.0.1: {} + + is-stream@3.0.0: {} + + is-string@1.0.7: + dependencies: + has-tostringtag: 1.0.2 + + is-symbol@1.0.4: + dependencies: + has-symbols: 1.0.3 + + is-typed-array@1.1.13: + dependencies: + which-typed-array: 1.1.15 + + is-weakref@1.0.2: + dependencies: + call-bind: 1.0.7 + + isarray@1.0.0: {} + + isarray@2.0.5: {} + + isexe@2.0.0: {} + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + javascript-natural-sort@0.7.1: {} + + jju@1.4.0: {} + + jmespath@0.16.0: {} + + joplin-turndown-plugin-gfm@1.0.12: {} + + jose@4.15.9: {} + + jose@5.6.3: {} + + joycon@3.1.1: {} + + js-levenshtein@1.1.6: {} + + js-tiktoken@1.0.12: + dependencies: + base64-js: 1.5.1 + + js-tiktoken@1.0.15: + dependencies: + base64-js: 1.5.1 + + js-tokens@4.0.0: {} + + js-tokens@9.0.0: {} + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + json-bigint@1.0.0: + dependencies: + bignumber.js: 9.1.2 + + json-buffer@3.0.1: {} + + json-schema-ref-resolver@1.0.1: + dependencies: + fast-deep-equal: 3.1.3 + + json-schema-resolver@2.0.0: + dependencies: + debug: 4.3.6 + rfdc: 1.4.1 + uri-js: 4.4.1 + transitivePeerDependencies: + - supports-color + + json-schema-to-ts@3.1.0: + dependencies: + '@babel/runtime': 7.25.0 + ts-algebra: 2.0.0 + + json-schema-to-typescript@15.0.2: + dependencies: + '@apidevtools/json-schema-ref-parser': 11.7.2 + '@types/json-schema': 7.0.15 + '@types/lodash': 4.17.10 + glob: 10.4.5 + is-glob: 4.0.3 + js-yaml: 4.1.0 + lodash: 4.17.21 + minimist: 1.2.8 + prettier: 3.3.3 + + json-schema-traverse@0.4.1: {} + + json-schema-traverse@1.0.0: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json5@1.0.2: + dependencies: + minimist: 1.2.8 + + json5@2.2.3: {} + + jsonfile@4.0.0: + optionalDependencies: + graceful-fs: 4.2.11 + + jsonfile@6.1.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + jsonpointer@5.0.1: {} + + jsonrepair@3.8.1: {} + + jwa@2.0.0: + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + + jws@4.0.0: + dependencies: + jwa: 2.0.0 + safe-buffer: 5.2.1 + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + knex@3.1.0: + dependencies: + colorette: 2.0.19 + commander: 10.0.1 + debug: 4.3.4 + escalade: 3.1.2 + esm: 3.2.25 + get-package-type: 0.1.0 + getopts: 2.3.0 + interpret: 2.2.0 + lodash: 4.17.21 + pg-connection-string: 2.6.2 + rechoir: 0.8.0 + resolve-from: 5.0.0 + tarn: 3.0.2 + tildify: 2.0.0 + transitivePeerDependencies: + - supports-color + + kolorist@1.8.0: {} + + kuler@2.0.0: {} + + langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)): + dependencies: + '@langchain/core': 0.2.23(langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8)) + '@langchain/openai': 0.2.6(langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8))) + '@langchain/textsplitters': 0.0.3(langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8)) + binary-extensions: 2.3.0 + js-tiktoken: 1.0.12 + js-yaml: 4.1.0 + jsonpointer: 5.0.1 + langsmith: 0.1.41(@langchain/core@0.2.23(langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8)))(langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8)) + openapi-types: 12.1.3 + p-retry: 4.6.2 + uuid: 10.0.0 + yaml: 2.5.1 + zod: 3.23.8 + zod-to-json-schema: 3.23.3(zod@3.23.8) + optionalDependencies: + '@langchain/community': 0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)) + axios: 1.7.7 + fast-xml-parser: 4.5.0 + ignore: 5.3.2 + ioredis: 5.4.1 + mongodb: 6.7.0(gcp-metadata@6.1.0) + transitivePeerDependencies: + - encoding + - openai + + langchain@0.2.20(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)): + dependencies: + '@langchain/core': 0.2.33(openai@4.67.3(zod@3.23.8)) + '@langchain/openai': 0.2.11 + '@langchain/textsplitters': 0.0.3(langchain@0.2.20(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8)) + binary-extensions: 2.3.0 + js-tiktoken: 1.0.15 + js-yaml: 4.1.0 + jsonpointer: 5.0.1 + langsmith: 0.1.66(openai@4.67.3(zod@3.23.8)) + openapi-types: 12.1.3 + p-retry: 4.6.2 + uuid: 10.0.0 + yaml: 2.6.0 + zod: 3.23.8 + zod-to-json-schema: 3.23.3(zod@3.23.8) + optionalDependencies: + axios: 1.7.7 + fast-xml-parser: 4.5.0 + ignore: 5.3.2 + ioredis: 5.4.1 + mongodb: 6.7.0(gcp-metadata@6.1.0) + transitivePeerDependencies: + - encoding + - openai + + langsmith@0.1.41(@langchain/core@0.2.23(langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8)))(langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8)): + dependencies: + '@types/uuid': 9.0.8 + commander: 10.0.1 + p-queue: 6.6.2 + p-retry: 4.6.2 + semver: 7.6.3 + uuid: 9.0.1 + optionalDependencies: + '@langchain/core': 0.2.23(langchain@0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8)) + langchain: 0.2.17(@langchain/community@0.2.28(@langchain/langgraph@0.0.34(openai@4.67.3(zod@3.23.8)))(@zilliz/milvus2-sdk-node@2.4.4)(axios@1.7.7)(duck-duck-scrape@2.2.5)(fast-xml-parser@4.5.0)(google-auth-library@9.14.2)(ignore@5.3.2)(ioredis@5.4.1)(lodash@4.17.21)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)) + openai: 4.67.3(zod@3.23.8) + + langsmith@0.1.41(@langchain/core@0.2.23(langchain@0.2.20(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8)))(langchain@0.2.20(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8)): + dependencies: + '@types/uuid': 9.0.8 + commander: 10.0.1 + p-queue: 6.6.2 + p-retry: 4.6.2 + semver: 7.6.3 + uuid: 9.0.1 + optionalDependencies: + '@langchain/core': 0.2.23(langchain@0.2.20(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)))(openai@4.67.3(zod@3.23.8)) + langchain: 0.2.20(axios@1.7.7)(fast-xml-parser@4.5.0)(ignore@5.3.2)(ioredis@5.4.1)(mongodb@6.7.0(gcp-metadata@6.1.0))(openai@4.67.3(zod@3.23.8)) + openai: 4.67.3(zod@3.23.8) + + langsmith@0.1.66(openai@4.67.3(zod@3.23.8)): + dependencies: + '@types/uuid': 10.0.0 + commander: 10.0.1 + p-queue: 6.6.2 + p-retry: 4.6.2 + semver: 7.6.3 + uuid: 10.0.0 + optionalDependencies: + openai: 4.67.3(zod@3.23.8) + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lex@1.7.9: {} + + light-my-request@5.13.0: + dependencies: + cookie: 0.6.0 + process-warning: 3.0.0 + set-cookie-parser: 2.7.0 + + lilconfig@3.1.2: {} + + lint-staged@15.2.10: + dependencies: + chalk: 5.3.0 + commander: 12.1.0 + debug: 4.3.6 + execa: 8.0.1 + lilconfig: 3.1.2 + listr2: 8.2.4 + micromatch: 4.0.8 + pidtree: 0.6.0 + string-argv: 0.3.2 + yaml: 2.5.1 + transitivePeerDependencies: + - supports-color + + listr2@8.2.4: + dependencies: + cli-truncate: 4.0.0 + colorette: 2.0.20 + eventemitter3: 5.0.1 + log-update: 6.1.0 + rfdc: 1.4.1 + wrap-ansi: 9.0.0 + + local-pkg@0.5.0: + dependencies: + mlly: 1.7.1 + pkg-types: 1.2.0 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash-es@4.17.21: {} + + lodash.camelcase@4.3.0: {} + + lodash.clonedeep@4.5.0: {} + + lodash.defaults@4.2.0: {} + + lodash.get@4.4.2: {} + + lodash.isarguments@3.1.0: {} + + lodash.isequal@4.5.0: {} + + lodash.merge@4.6.2: {} + + lodash@4.17.21: {} + + log-update@6.1.0: + dependencies: + ansi-escapes: 7.0.0 + cli-cursor: 5.0.0 + slice-ansi: 7.1.0 + strip-ansi: 7.1.0 + wrap-ansi: 9.0.0 + + logform@2.6.1: + dependencies: + '@colors/colors': 1.6.0 + '@types/triple-beam': 1.3.5 + fecha: 4.2.3 + ms: 2.1.3 + safe-stable-stringify: 2.5.0 + triple-beam: 1.4.1 + + long@5.2.3: {} + + loupe@2.3.7: + dependencies: + get-func-name: 2.0.2 + + lru-cache@10.4.3: {} + + lru-cache@6.0.0: + dependencies: + yallist: 4.0.0 + + lru-cache@9.1.2: {} + + luxon@3.5.0: {} + + magic-string@0.30.11: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + + mathjs@13.2.0: + dependencies: + '@babel/runtime': 7.25.7 + complex.js: 2.3.0 + decimal.js: 10.4.3 + escape-latex: 1.2.0 + fraction.js: 4.3.7 + javascript-natural-sort: 0.7.1 + seedrandom: 3.0.5 + tiny-emitter: 2.1.0 + typed-function: 4.2.1 + + memory-pager@1.5.0: {} + + merge-stream@2.0.0: {} + + merge2@1.4.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mikro-orm@6.2.9: {} + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime@3.0.0: {} + + mime@4.0.4: {} + + mimic-fn@4.0.0: {} + + mimic-function@5.0.1: {} + + minimatch@3.0.8: + dependencies: + brace-expansion: 1.1.11 + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.11 + + minimatch@5.1.6: + dependencies: + brace-expansion: 2.0.1 + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.1 + + minimist@1.2.8: {} + + minipass@7.1.2: {} + + mkdirp@3.0.1: {} + + mlly@1.7.1: + dependencies: + acorn: 8.12.1 + pathe: 1.1.2 + pkg-types: 1.2.0 + ufo: 1.5.4 + + module-details-from-path@1.0.3: {} + + moment-timezone@0.5.46: + dependencies: + moment: 2.30.1 + + moment@2.30.1: {} + + mongodb-connection-string-url@3.0.1: + dependencies: + '@types/whatwg-url': 11.0.5 + whatwg-url: 13.0.0 + + mongodb@6.7.0(gcp-metadata@6.1.0): + dependencies: + '@mongodb-js/saslprep': 1.1.8 + bson: 6.8.0 + mongodb-connection-string-url: 3.0.1 + optionalDependencies: + gcp-metadata: 6.1.0 + + ms@2.1.2: {} + + ms@2.1.3: {} + + msgpackr-extract@3.0.3: + dependencies: + node-gyp-build-optional-packages: 5.2.2 + optionalDependencies: + '@msgpackr-extract/msgpackr-extract-darwin-arm64': 3.0.3 + '@msgpackr-extract/msgpackr-extract-darwin-x64': 3.0.3 + '@msgpackr-extract/msgpackr-extract-linux-arm': 3.0.3 + '@msgpackr-extract/msgpackr-extract-linux-arm64': 3.0.3 + '@msgpackr-extract/msgpackr-extract-linux-x64': 3.0.3 + '@msgpackr-extract/msgpackr-extract-win32-x64': 3.0.3 + optional: true + + msgpackr@1.11.0: + optionalDependencies: + msgpackr-extract: 3.0.3 + + muggle-string@0.3.1: {} + + mustache@4.2.0: {} + + nanoid@3.3.7: {} + + natural-compare@1.4.0: {} + + needle@3.3.1: + dependencies: + iconv-lite: 0.6.3 + sax: 1.4.1 + + node-abort-controller@3.1.1: {} + + node-domexception@1.0.0: {} + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + + node-gyp-build-optional-packages@5.2.2: + dependencies: + detect-libc: 2.0.3 + optional: true + + node-releases@2.0.18: {} + + npm-run-path@5.3.0: + dependencies: + path-key: 4.0.0 + + object-hash@2.2.0: {} + + object-hash@3.0.0: {} + + object-inspect@1.13.2: {} + + object-keys@1.1.1: {} + + object.assign@4.1.5: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + has-symbols: 1.0.3 + object-keys: 1.1.1 + + object.fromentries@2.0.8: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 + + object.groupby@1.0.3: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + + object.values@1.2.0: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + + oidc-token-hash@5.0.3: {} + + ollama@0.5.9: + dependencies: + whatwg-fetch: 3.6.20 + + on-exit-leak-free@2.1.2: {} + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + one-time@1.0.0: + dependencies: + fn.name: 1.1.0 + + onetime@6.0.0: + dependencies: + mimic-fn: 4.0.0 + + onetime@7.0.0: + dependencies: + mimic-function: 5.0.1 + + openai-chat-tokens@0.2.8: + dependencies: + js-tiktoken: 1.0.15 + + openai@4.67.3(zod@3.23.8): + dependencies: + '@types/node': 18.19.55 + '@types/node-fetch': 2.6.11 + abort-controller: 3.0.0 + agentkeepalive: 4.5.0 + form-data-encoder: 1.7.2 + formdata-node: 4.4.1 + node-fetch: 2.7.0 + optionalDependencies: + zod: 3.23.8 + transitivePeerDependencies: + - encoding + + openapi-fetch@0.10.6: + dependencies: + openapi-typescript-helpers: 0.0.11 + + openapi-fetch@0.11.3: + dependencies: + openapi-typescript-helpers: 0.0.13 + + openapi-fetch@0.8.2: + dependencies: + openapi-typescript-helpers: 0.0.5 + + openapi-types@12.1.3: {} + + openapi-typescript-helpers@0.0.11: {} + + openapi-typescript-helpers@0.0.13: {} + + openapi-typescript-helpers@0.0.5: {} + + openapi-typescript@7.4.1(typescript@5.5.4): + dependencies: + '@redocly/openapi-core': 1.25.3(supports-color@9.4.0) + ansi-colors: 4.1.3 + change-case: 5.4.4 + parse-json: 8.1.0 + supports-color: 9.4.0 + typescript: 5.5.4 + yargs-parser: 21.1.1 + transitivePeerDependencies: + - encoding + + openid-client@5.7.0: + dependencies: + jose: 4.15.9 + lru-cache: 6.0.0 + object-hash: 2.2.0 + oidc-token-hash: 5.0.3 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + ow@0.28.2: + dependencies: + '@sindresorhus/is': 4.6.0 + callsites: 3.1.0 + dot-prop: 6.0.1 + lodash.isequal: 4.5.0 + vali-date: 1.0.0 + + p-finally@1.0.0: {} + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-limit@5.0.0: + dependencies: + yocto-queue: 1.1.1 + + p-limit@6.1.0: + dependencies: + yocto-queue: 1.1.1 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + p-queue-compat@1.0.225: + dependencies: + eventemitter3: 5.0.1 + p-timeout-compat: 1.0.4 + + p-queue@6.6.2: + dependencies: + eventemitter3: 4.0.7 + p-timeout: 3.2.0 + + p-queue@8.0.1: + dependencies: + eventemitter3: 5.0.1 + p-timeout: 6.1.2 + + p-retry@4.6.2: + dependencies: + '@types/retry': 0.12.0 + retry: 0.13.1 + + p-throttle@6.2.0: {} + + p-timeout-compat@1.0.4: {} + + p-timeout@3.2.0: + dependencies: + p-finally: 1.0.0 + + p-timeout@6.1.2: {} + + package-json-from-dist@1.0.1: {} + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parent-require@1.0.0: {} + + parse-json@8.1.0: + dependencies: + '@babel/code-frame': 7.24.7 + index-to-position: 0.1.2 + type-fest: 4.26.1 + + path-browserify@1.0.1: {} + + path-exists@4.0.0: {} + + path-is-absolute@1.0.1: {} + + path-key@3.1.1: {} + + path-key@4.0.0: {} + + path-parse@1.0.7: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + + path-type@4.0.0: {} + + path-type@5.0.0: {} + + pathe@1.1.2: {} + + pathval@1.1.1: {} + + pend@1.2.0: {} + + pg-connection-string@2.6.2: {} + + pg-connection-string@2.7.0: {} + + pg-int8@1.0.1: {} + + pg-protocol@1.7.0: {} + + pg-types@2.2.0: + dependencies: + pg-int8: 1.0.1 + postgres-array: 2.0.0 + postgres-bytea: 1.0.0 + postgres-date: 1.0.7 + postgres-interval: 1.2.0 + + picocolors@1.1.0: {} + + picomatch@2.3.1: {} + + pidtree@0.6.0: {} + + pino-abstract-transport@1.2.0: + dependencies: + readable-stream: 4.5.2 + split2: 4.2.0 + + pino-pretty@11.2.2: + dependencies: + colorette: 2.0.20 + dateformat: 4.6.3 + fast-copy: 3.0.2 + fast-safe-stringify: 2.1.1 + help-me: 5.0.0 + joycon: 3.1.1 + minimist: 1.2.8 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 1.2.0 + pump: 3.0.2 + readable-stream: 4.5.2 + secure-json-parse: 2.7.0 + sonic-boom: 4.1.0 + strip-json-comments: 3.1.1 + + pino-std-serializers@7.0.0: {} + + pino@9.4.0: + dependencies: + atomic-sleep: 1.0.0 + fast-redact: 3.5.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 1.2.0 + pino-std-serializers: 7.0.0 + process-warning: 4.0.0 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.5.0 + sonic-boom: 4.1.0 + thread-stream: 3.1.0 + + pkg-types@1.2.0: + dependencies: + confbox: 0.1.7 + mlly: 1.7.1 + pathe: 1.1.2 + + pluralize@8.0.0: {} + + pony-cause@2.1.11: {} + + possible-typed-array-names@1.0.0: {} + + postcss@8.4.47: + dependencies: + nanoid: 3.3.7 + picocolors: 1.1.0 + source-map-js: 1.2.1 + + postgres-array@2.0.0: {} + + postgres-bytea@1.0.0: {} + + postgres-date@1.0.7: {} + + postgres-interval@1.2.0: + dependencies: + xtend: 4.0.2 + + prelude-ls@1.2.1: {} + + prettier-linter-helpers@1.0.0: + dependencies: + fast-diff: 1.3.0 + + prettier@3.3.3: {} + + pretty-format@29.7.0: + dependencies: + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.3.1 + + process-warning@3.0.0: {} + + process-warning@4.0.0: {} + + process@0.11.10: {} + + prom-client@15.1.3: + dependencies: + '@opentelemetry/api': 1.9.0 + tdigest: 0.1.2 + + promise-based-task@3.1.0: {} + + promise-coalesce@1.1.2: {} + + protobufjs@7.4.0: + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.4 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.0 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.0 + '@types/node': 20.14.15 + long: 5.2.3 + + proxy-addr@2.0.7: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + + proxy-from-env@1.1.0: {} + + pump@3.0.2: + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + + punycode@1.4.1: {} + + punycode@2.3.1: {} + + qs@6.13.0: + dependencies: + side-channel: 1.0.6 + + queue-microtask@1.2.3: {} + + quick-format-unescaped@4.0.4: {} + + ranges-apply@7.0.16: + dependencies: + ranges-merge: 9.0.15 + tiny-invariant: 1.3.3 + + ranges-merge@9.0.15: + dependencies: + ranges-push: 7.0.15 + ranges-sort: 6.0.11 + + ranges-push@7.0.15: + dependencies: + codsen-utils: 1.6.4 + ranges-sort: 6.0.11 + string-collapse-leading-whitespace: 7.0.7 + string-trim-spaces-only: 5.0.10 + + ranges-sort@6.0.11: {} + + react-is@18.3.1: {} + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + readable-stream@4.5.2: + dependencies: + abort-controller: 3.0.0 + buffer: 6.0.3 + events: 3.3.0 + process: 0.11.10 + string_decoder: 1.3.0 + + real-require@0.2.0: {} + + rechoir@0.8.0: + dependencies: + resolve: 1.22.8 + + redis-errors@1.2.0: {} + + redis-parser@3.0.0: + dependencies: + redis-errors: 1.2.0 + + reflect-metadata@0.2.2: {} + + regenerator-runtime@0.14.1: {} + + regexp.prototype.flags@1.5.2: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-errors: 1.3.0 + set-function-name: 2.0.2 + + remeda@2.14.0: + dependencies: + type-fest: 4.26.1 + + require-directory@2.1.1: {} + + require-from-string@2.0.2: {} + + require-in-the-middle@7.4.0: + dependencies: + debug: 4.3.7(supports-color@9.4.0) + module-details-from-path: 1.0.3 + resolve: 1.22.8 + transitivePeerDependencies: + - supports-color + + resolve-from@4.0.0: {} + + resolve-from@5.0.0: {} + + resolve-pkg-maps@1.0.0: {} + + resolve@1.19.0: + dependencies: + is-core-module: 2.15.0 + path-parse: 1.0.7 + + resolve@1.22.8: + dependencies: + is-core-module: 2.15.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + restore-cursor@5.1.0: + dependencies: + onetime: 7.0.0 + signal-exit: 4.1.0 + + ret@0.4.3: {} + + retry-as-promised@7.0.4: {} + + retry@0.13.1: {} + + reusify@1.0.4: {} + + rfdc@1.4.1: {} + + rimraf@3.0.2: + dependencies: + glob: 7.2.3 + + rollup@4.22.4: + dependencies: + '@types/estree': 1.0.5 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.22.4 + '@rollup/rollup-android-arm64': 4.22.4 + '@rollup/rollup-darwin-arm64': 4.22.4 + '@rollup/rollup-darwin-x64': 4.22.4 + '@rollup/rollup-linux-arm-gnueabihf': 4.22.4 + '@rollup/rollup-linux-arm-musleabihf': 4.22.4 + '@rollup/rollup-linux-arm64-gnu': 4.22.4 + '@rollup/rollup-linux-arm64-musl': 4.22.4 + '@rollup/rollup-linux-powerpc64le-gnu': 4.22.4 + '@rollup/rollup-linux-riscv64-gnu': 4.22.4 + '@rollup/rollup-linux-s390x-gnu': 4.22.4 + '@rollup/rollup-linux-x64-gnu': 4.22.4 + '@rollup/rollup-linux-x64-musl': 4.22.4 + '@rollup/rollup-win32-arm64-msvc': 4.22.4 + '@rollup/rollup-win32-ia32-msvc': 4.22.4 + '@rollup/rollup-win32-x64-msvc': 4.22.4 + fsevents: 2.3.3 + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + safe-array-concat@1.1.2: + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + has-symbols: 1.0.3 + isarray: 2.0.5 + + safe-buffer@5.2.1: {} + + safe-regex-test@1.0.3: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-regex: 1.1.4 + + safe-regex2@3.1.0: + dependencies: + ret: 0.4.3 + + safe-stable-stringify@2.5.0: {} + + safer-buffer@2.1.2: {} + + sax@1.4.1: {} + + secure-json-parse@2.7.0: {} + + seedrandom@3.0.5: {} + + semver@6.3.1: {} + + semver@7.5.4: + dependencies: + lru-cache: 6.0.0 + + semver@7.6.3: {} + + sequelize-pool@7.1.0: {} + + sequelize@6.37.3: + dependencies: + '@types/debug': 4.1.12 + '@types/validator': 13.12.2 + debug: 4.3.7(supports-color@9.4.0) + dottie: 2.0.6 + inflection: 1.13.4 + lodash: 4.17.21 + moment: 2.30.1 + moment-timezone: 0.5.46 + pg-connection-string: 2.7.0 + retry-as-promised: 7.0.4 + semver: 7.6.3 + sequelize-pool: 7.1.0 + toposort-class: 1.0.1 + uuid: 8.3.2 + validator: 13.12.0 + wkx: 0.5.0 + transitivePeerDependencies: + - supports-color + + serialize-error@11.0.3: + dependencies: + type-fest: 2.19.0 + + set-cookie-parser@2.7.0: {} + + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + gopd: 1.0.1 + has-property-descriptors: 1.0.2 + + set-function-name@2.0.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + + setprototypeof@1.2.0: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + shimmer@1.2.1: {} + + side-channel@1.0.6: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + object-inspect: 1.13.2 + + siginfo@2.0.0: {} + + signal-exit@4.1.0: {} + + simple-swizzle@0.2.2: + dependencies: + is-arrayish: 0.3.2 + + slash@3.0.0: {} + + slash@5.1.0: {} + + slice-ansi@5.0.0: + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 4.0.0 + + slice-ansi@7.1.0: + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 5.0.0 + + sonic-boom@4.1.0: + dependencies: + atomic-sleep: 1.0.0 + + source-map-js@1.2.1: {} + + source-map@0.6.1: {} + + sparse-bitfield@3.0.3: + dependencies: + memory-pager: 1.5.0 + + split2@4.2.0: {} + + sprintf-js@1.0.3: {} + + sqlstring@2.3.3: {} + + stack-trace@0.0.10: {} + + stackback@0.0.2: {} + + standard-as-callback@2.1.0: {} + + statuses@2.0.1: {} + + std-env@3.7.0: {} + + stoppable@1.1.0: {} + + stream-wormhole@1.1.0: {} + + string-argv@0.3.2: {} + + string-collapse-leading-whitespace@7.0.7: {} + + string-comparison@1.3.0: {} + + string-left-right@6.0.17: + dependencies: + codsen-utils: 1.6.4 + rfdc: 1.4.1 + + string-strip-html@13.4.8: + dependencies: + '@types/lodash-es': 4.17.12 + codsen-utils: 1.6.4 + html-entities: 2.5.2 + lodash-es: 4.17.21 + ranges-apply: 7.0.16 + ranges-push: 7.0.15 + string-left-right: 6.0.17 + + string-trim-spaces-only@5.0.10: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + + string-width@7.2.0: + dependencies: + emoji-regex: 10.3.0 + get-east-asian-width: 1.2.0 + strip-ansi: 7.1.0 + + string.fromcodepoint@0.2.1: {} + + string.prototype.trim@1.2.9: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 + + string.prototype.trimend@1.0.8: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + + string.prototype.trimstart@1.0.8: + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.0.1 + + strip-bom@3.0.0: {} + + strip-final-newline@3.0.0: {} + + strip-json-comments@3.1.1: {} + + strip-literal@2.1.0: + dependencies: + js-tokens: 9.0.0 + + strnum@1.0.5: {} + + supports-color@5.5.0: + dependencies: + has-flag: 3.0.0 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + + supports-color@9.4.0: {} + + supports-preserve-symlinks-flag@1.0.0: {} + + synckit@0.9.1: + dependencies: + '@pkgr/core': 0.1.1 + tslib: 2.7.0 + + tapable@2.2.1: {} + + tarn@3.0.2: {} + + tdigest@0.1.2: + dependencies: + bintrees: 1.0.2 + + text-hex@1.0.0: {} + + text-table@0.2.0: {} + + thread-stream@3.1.0: + dependencies: + real-require: 0.2.0 + + tildify@2.0.0: {} + + tiny-emitter@2.1.0: {} + + tiny-invariant@1.3.3: {} + + tinybench@2.9.0: {} + + tinypool@0.8.4: {} + + tinyspy@2.2.1: {} + + to-fast-properties@2.0.0: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + toad-cache@3.7.0: {} + + toidentifier@1.0.1: {} + + toposort-class@1.0.1: {} + + tr46@0.0.3: {} + + tr46@4.1.1: + dependencies: + punycode: 2.3.1 + + triple-beam@1.4.1: {} + + ts-algebra@2.0.0: {} + + ts-api-utils@1.3.0(typescript@5.5.4): + dependencies: + typescript: 5.5.4 + + ts-morph@22.0.0: + dependencies: + '@ts-morph/common': 0.23.0 + code-block-writer: 13.0.2 + + tsc-files@1.1.4(typescript@5.5.4): + dependencies: + typescript: 5.5.4 + + tsconfck@3.1.3(typescript@5.5.4): + optionalDependencies: + typescript: 5.5.4 + + tsconfig-paths@3.15.0: + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + + tsconfig-paths@4.2.0: + dependencies: + json5: 2.2.3 + minimist: 1.2.8 + strip-bom: 3.0.0 + + tslib@2.7.0: {} + + tslib@2.8.0: {} + + tsx@4.19.1: + dependencies: + esbuild: 0.23.0 + get-tsconfig: 4.7.6 + optionalDependencies: + fsevents: 2.3.3 + + turndown@7.2.0: + dependencies: + '@mixmark-io/domino': 2.2.0 + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-detect@4.1.0: {} + + type-fest@0.20.2: {} + + type-fest@2.19.0: {} + + type-fest@4.26.1: {} + + typed-array-buffer@1.0.2: + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-typed-array: 1.1.13 + + typed-array-byte-length@1.0.1: + dependencies: + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-proto: 1.0.3 + is-typed-array: 1.1.13 + + typed-array-byte-offset@1.0.2: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-proto: 1.0.3 + is-typed-array: 1.1.13 + + typed-array-length@1.0.6: + dependencies: + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-proto: 1.0.3 + is-typed-array: 1.1.13 + possible-typed-array-names: 1.0.0 + + typed-function@4.2.1: {} + + typescript@5.4.2: {} + + typescript@5.5.4: {} + + ufo@1.5.4: {} + + umzug@3.8.0(@types/node@20.14.15): + dependencies: + '@rushstack/ts-command-line': 4.22.4(@types/node@20.14.15) + emittery: 0.13.1 + fast-glob: 3.3.2 + pony-cause: 2.1.11 + type-fest: 4.26.1 + transitivePeerDependencies: + - '@types/node' + + unbox-primitive@1.0.2: + dependencies: + call-bind: 1.0.7 + has-bigints: 1.0.2 + has-symbols: 1.0.3 + which-boxed-primitive: 1.0.2 + + undici-types@5.26.5: {} + + undici-types@6.19.8: {} + + undici@5.28.4: + dependencies: + '@fastify/busboy': 2.1.1 + + unescape-js@1.1.4: + dependencies: + string.fromcodepoint: 0.2.1 + + unicorn-magic@0.1.0: {} + + universalify@0.1.2: {} + + universalify@2.0.1: {} + + update-browserslist-db@1.1.1(browserslist@4.24.0): + dependencies: + browserslist: 4.24.0 + escalade: 3.2.0 + picocolors: 1.1.0 + + uri-js-replace@1.0.1: {} + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + url-template@2.0.8: {} + + url@0.11.4: + dependencies: + punycode: 1.4.1 + qs: 6.13.0 + + utf8@3.0.0: {} + + util-deprecate@1.0.2: {} + + util@0.12.5: + dependencies: + inherits: 2.0.4 + is-arguments: 1.1.1 + is-generator-function: 1.0.10 + is-typed-array: 1.1.13 + which-typed-array: 1.1.15 + + uuid@10.0.0: {} + + uuid@8.3.2: {} + + uuid@9.0.1: {} + + vali-date@1.0.0: {} + + validator@13.12.0: {} + + vite-node@1.6.0(@types/node@20.14.15): + dependencies: + cac: 6.7.14 + debug: 4.3.6 + pathe: 1.1.2 + picocolors: 1.1.0 + vite: 5.4.8(@types/node@20.14.15) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + + vite-plugin-dts@3.9.1(@types/node@20.14.15)(rollup@4.22.4)(typescript@5.5.4)(vite@5.4.8(@types/node@20.14.15)): + dependencies: + '@microsoft/api-extractor': 7.43.0(@types/node@20.14.15) + '@rollup/pluginutils': 5.1.0(rollup@4.22.4) + '@vue/language-core': 1.8.27(typescript@5.5.4) + debug: 4.3.6 + kolorist: 1.8.0 + magic-string: 0.30.11 + typescript: 5.5.4 + vue-tsc: 1.8.27(typescript@5.5.4) + optionalDependencies: + vite: 5.4.8(@types/node@20.14.15) + transitivePeerDependencies: + - '@types/node' + - rollup + - supports-color + + vite-plugin-externalize-deps@0.8.0(vite@5.4.8(@types/node@20.14.15)): + dependencies: + vite: 5.4.8(@types/node@20.14.15) + + vite-tsconfig-paths@4.3.2(typescript@5.5.4)(vite@5.4.8(@types/node@20.14.15)): + dependencies: + debug: 4.3.6 + globrex: 0.1.2 + tsconfck: 3.1.3(typescript@5.5.4) + optionalDependencies: + vite: 5.4.8(@types/node@20.14.15) + transitivePeerDependencies: + - supports-color + - typescript + + vite@5.4.8(@types/node@20.14.15): + dependencies: + esbuild: 0.21.5 + postcss: 8.4.47 + rollup: 4.22.4 + optionalDependencies: + '@types/node': 20.14.15 + fsevents: 2.3.3 + + vitest@1.6.0(@types/node@20.14.15): + dependencies: + '@vitest/expect': 1.6.0 + '@vitest/runner': 1.6.0 + '@vitest/snapshot': 1.6.0 + '@vitest/spy': 1.6.0 + '@vitest/utils': 1.6.0 + acorn-walk: 8.3.3 + chai: 4.5.0 + debug: 4.3.6 + execa: 8.0.1 + local-pkg: 0.5.0 + magic-string: 0.30.11 + pathe: 1.1.2 + picocolors: 1.1.0 + std-env: 3.7.0 + strip-literal: 2.1.0 + tinybench: 2.9.0 + tinypool: 0.8.4 + vite: 5.4.8(@types/node@20.14.15) + vite-node: 1.6.0(@types/node@20.14.15) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 20.14.15 + transitivePeerDependencies: + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + + vue-template-compiler@2.7.16: + dependencies: + de-indent: 1.0.2 + he: 1.2.0 + + vue-tsc@1.8.27(typescript@5.5.4): + dependencies: + '@volar/typescript': 1.11.1 + '@vue/language-core': 1.8.27(typescript@5.5.4) + semver: 7.6.3 + typescript: 5.5.4 + + web-streams-polyfill@4.0.0-beta.3: {} + + webidl-conversions@3.0.1: {} + + webidl-conversions@7.0.0: {} + + whatwg-fetch@3.6.20: {} + + whatwg-url@13.0.0: + dependencies: + tr46: 4.1.1 + webidl-conversions: 7.0.0 + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + which-boxed-primitive@1.0.2: + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.7 + is-string: 1.0.7 + is-symbol: 1.0.4 + + which-typed-array@1.1.15: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.2 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + + wikipedia@2.1.2: + dependencies: + axios: 1.7.7 + infobox-parser: 3.6.4 + transitivePeerDependencies: + - debug + + winston-transport@4.7.1: + dependencies: + logform: 2.6.1 + readable-stream: 3.6.2 + triple-beam: 1.4.1 + + winston@3.14.2: + dependencies: + '@colors/colors': 1.6.0 + '@dabh/diagnostics': 2.0.3 + async: 3.2.5 + is-stream: 2.0.1 + logform: 2.6.1 + one-time: 1.0.0 + readable-stream: 3.6.2 + safe-stable-stringify: 2.5.0 + stack-trace: 0.0.10 + triple-beam: 1.4.1 + winston-transport: 4.7.1 + + wkx@0.5.0: + dependencies: + '@types/node': 20.16.11 + + word-wrap@1.2.5: {} + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + + wrap-ansi@9.0.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 7.2.0 + strip-ansi: 7.1.0 + + wrappy@1.0.2: {} + + xml2js@0.6.2: + dependencies: + sax: 1.4.1 + xmlbuilder: 11.0.1 + + xmlbuilder@10.1.1: {} + + xmlbuilder@11.0.1: {} + + xtend@4.0.2: {} + + y18n@5.0.8: {} + + yallist@4.0.0: {} + + yaml-ast-parser@0.0.43: {} + + yaml@2.5.1: {} + + yaml@2.6.0: {} + + yargs-parser@21.1.1: {} + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yauzl@3.1.3: + dependencies: + buffer-crc32: 0.2.13 + pend: 1.2.0 + + yocto-queue@0.1.0: {} + + yocto-queue@1.1.1: {} + + z-schema@5.0.5: + dependencies: + lodash.get: 4.4.2 + lodash.isequal: 4.5.0 + validator: 13.12.0 + optionalDependencies: + commander: 9.5.0 + + zod-to-json-schema@3.23.3(zod@3.23.8): + dependencies: + zod: 3.23.8 + + zod@3.23.8: {} diff --git a/scripts/copyright.sh b/scripts/copyright.sh new file mode 100755 index 0000000..3f92b2a --- /dev/null +++ b/scripts/copyright.sh @@ -0,0 +1,51 @@ +#!/bin/bash +# Copyright 2024 IBM Corp. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -e + +# Path to the package.json file +PACKAGE_JSON_PATH="./package.json" + +# Check if the package.json file exists +if [[ ! -f "$PACKAGE_JSON_PATH" ]]; then + echo "Error: package.json file not found at $PACKAGE_JSON_PATH" + exit 1 +fi + +# Retrieve the author property using jq +AUTHOR=$(jq -r '.author' "$PACKAGE_JSON_PATH") + +# Check if the author property is not null or empty +if [[ -z "$AUTHOR" ]]; then + echo "Error: author property not found in package.json" + exit 1 +fi + +# Check if 'nwa' command is not available and 'go' is available, then install 'nwa' +if ! command -v nwa &> /dev/null && command -v go &> /dev/null; then + echo "Installing 'nwa' via 'go' (https://github.com/B1NARY-GR0UP/nwa)" + go install github.com/B1NARY-GR0UP/nwa@latest + # Ensure the GOPATH is added to the PATH environment variable + export PATH=$PATH:$(go env GOPATH)/bin +fi + +if command -v nwa &> /dev/null; then + nwa add -l apache -c "$AUTHOR" scripts seeders migrations tests src +elif command -v docker &> /dev/null; then + docker run --rm -v "${PWD}:/src" ghcr.io/b1nary-gr0up/nwa:main add -l apache -c "$AUTHOR" scripts seeders migrations tests src +else + echo "Error: 'nwa' is not available. Either install it manually or install go/docker." + exit 1 +fi \ No newline at end of file diff --git a/seeders/DatabaseSeeder.ts b/seeders/DatabaseSeeder.ts new file mode 100644 index 0000000..f343d29 --- /dev/null +++ b/seeders/DatabaseSeeder.ts @@ -0,0 +1,121 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ref, type EntityManager } from '@mikro-orm/core'; +import { Seeder } from '@mikro-orm/seeder'; + +import { OrganizationUserRole, ProjectRole } from '@/administration/entities/constants'; +import { OrganizationUser } from '@/administration/entities/organization-user.entity'; +import { Organization } from '@/administration/entities/organization.entity'; +import { UserPrincipal } from '@/administration/entities/principals/user-principal.entity'; +import { ProjectPrincipal } from '@/administration/entities/project-principal.entity'; +import { Project } from '@/administration/entities/project.entity'; +import { Assistant } from '@/assistants/assistant.entity'; +import { User } from '@/users/entities/user.entity'; +import { getDefaultModel } from '@/runs/execution/factory'; +import { SystemTools } from '@/tools/entities/tool-calls/system-call.entity'; +import { ProjectApiKey } from '@/administration/entities/project-api-key.entity'; +import { scryptApiKey } from '@/auth/utils'; +import { + ORGANIZATION_ID_DEFAULT, + ORGANIZATION_OWNER_ID_DEFAULT, + PROJECT_ADMIN_ID_DEFAULT, + PROJECT_ID_DEFAULT +} from '@/config'; + +const USER_EXTERNAL_ID = 'test'; +const PROJECT_API_KEY = 'sk-testkey'; + +export class DatabaseSeeder extends Seeder { + async run(em: EntityManager): Promise { + process.env.IN_SEEDER = 'true'; + + const existingUser = await em.getRepository(User).findOne({ externalId: USER_EXTERNAL_ID }); + if (existingUser) { + throw new Error('Database is already seeded.'); + } + + const user = new User({ + externalId: USER_EXTERNAL_ID, + name: 'Test user', + email: 'test@email.com' + }); + const organization = new Organization({ createdBy: ref(user), name: 'Default Organization' }); + organization.id = ORGANIZATION_ID_DEFAULT ?? 'org_670cc04869ddffe24f4fd70d'; + const organizationUser = new OrganizationUser({ + user: ref(user), + role: OrganizationUserRole.OWNER, + organization: ref(organization), + createdBy: em.getRepository(OrganizationUser).getReference('placeholder', { wrapped: true }) + }); + organizationUser.id = ORGANIZATION_OWNER_ID_DEFAULT; + organizationUser.createdBy = em + .getRepository(OrganizationUser) + .getReference(organizationUser.id, { wrapped: true }); + const project = new Project({ + name: 'Default project', + createdBy: ref(organizationUser), + organization: ref(organization) + }); + project.id = PROJECT_ID_DEFAULT ?? 'proj_670cc04869ddffe24f4fd70f'; + const projectUser = new ProjectPrincipal({ + principal: new UserPrincipal({ user: ref(organizationUser) }), + role: ProjectRole.ADMIN, + createdBy: em.getRepository(ProjectPrincipal).getReference('placeholder', { wrapped: true }), + project: ref(project) + }); + projectUser.id = PROJECT_ADMIN_ID_DEFAULT; + projectUser.createdBy = em + .getRepository(ProjectPrincipal) + .getReference(projectUser.id, { wrapped: true }); + const projectApiKey = new ProjectApiKey({ + key: scryptApiKey(PROJECT_API_KEY), + createdBy: ref(projectUser), + project: ref(project) + }); + const assistant = new Assistant({ + model: getDefaultModel(), + tools: [ + { + type: 'system', + toolId: SystemTools.WEB_SEARCH + }, + { + type: 'system', + toolId: SystemTools.WEATHER + }, + { + type: 'system', + toolId: SystemTools.WIKIPEDIA + }, + { + type: 'code_interpreter' + } + ], + name: 'Bee Assistant', + project: ref(project), + createdBy: ref(projectUser), + description: 'An example agent powered by ReAct, not tailored to any specific task', + metadata: { + $ui_color: 'black', + $ui_icon: 'Bee' + } + }); + em.persist([assistant, projectApiKey]); + await em.flush(); + process.env.IN_SEEDER = undefined; + } +} diff --git a/src/@types/fastify/index.d.ts b/src/@types/fastify/index.d.ts new file mode 100644 index 0000000..3647e0e --- /dev/null +++ b/src/@types/fastify/index.d.ts @@ -0,0 +1,48 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* eslint-disable @typescript-eslint/no-unused-vars */ + +import fastify, { FastifyReply, FastifyRequest } from 'fastify'; +import { RequestContextData } from '@fastify/request-context'; +import { Loaded } from '@mikro-orm/core'; + +import type { AuthFn } from '@/auth/authentication.ts'; +import { ProjectPrincipal } from '@/administration/entities/project-principal.entity'; +import { OrganizationUser } from '@/administration/entities/organization-user.entity'; +import { ProjectApiKey } from '@/administration/entities/project-api-key.entity'; + +declare module 'fastify' { + interface FastifyInstance< + HttpServer = Server, + HttpRequest = IncomingMessage, + HttpResponse = ServerResponse + > { + auth: AuthFn; + } +} + +declare module '@fastify/request-context' { + interface RequestContextData { + req: FastifyRequest; + res: FastifyReply; + + user?: Loaded; + organizationUser?: Loaded; + apiKey?: Loaded; + projectPrincipal?: Loaded; + } +} diff --git a/src/@types/grpc/index.d.ts b/src/@types/grpc/index.d.ts new file mode 100644 index 0000000..a5ac075 --- /dev/null +++ b/src/@types/grpc/index.d.ts @@ -0,0 +1,467 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import '@grpc/proto-loader'; + +declare module '@grpc/proto-loader' { + declare class Long { + /** + * Constructs a 64 bit two's-complement integer, given its low and high 32 bit values as signed integers. See the from* functions below for more convenient ways of constructing Longs. + */ + constructor(low: number, high?: number, unsigned?: boolean); + + /** + * Maximum unsigned value. + */ + static MAX_UNSIGNED_VALUE: Long; + + /** + * Maximum signed value. + */ + static MAX_VALUE: Long; + + /** + * Minimum signed value. + */ + static MIN_VALUE: Long; + + /** + * Signed negative one. + */ + static NEG_ONE: Long; + + /** + * Signed one. + */ + static ONE: Long; + + /** + * Unsigned one. + */ + static UONE: Long; + + /** + * Unsigned zero. + */ + static UZERO: Long; + + /** + * Signed zero + */ + static ZERO: Long; + + /** + * The high 32 bits as a signed value. + */ + high: number; + + /** + * The low 32 bits as a signed value. + */ + low: number; + + /** + * Whether unsigned or not. + */ + unsigned: boolean; + + /** + * Returns a Long representing the 64 bit integer that comes by concatenating the given low and high bits. Each is assumed to use 32 bits. + */ + static fromBits(lowBits: number, highBits: number, unsigned?: boolean): Long; + + /** + * Returns a Long representing the given 32 bit integer value. + */ + static fromInt(value: number, unsigned?: boolean): Long; + + /** + * Returns a Long representing the given value, provided that it is a finite number. Otherwise, zero is returned. + */ + static fromNumber(value: number, unsigned?: boolean): Long; + + /** + * Returns a Long representation of the given string, written using the specified radix. + */ + static fromString(str: string, unsigned?: boolean | number, radix?: number): Long; + + /** + * Creates a Long from its byte representation. + */ + static fromBytes(bytes: number[], unsigned?: boolean, le?: boolean): Long; + + /** + * Creates a Long from its little endian byte representation. + */ + static fromBytesLE(bytes: number[], unsigned?: boolean): Long; + + /** + * Creates a Long from its big endian byte representation. + */ + static fromBytesBE(bytes: number[], unsigned?: boolean): Long; + + /** + * Tests if the specified object is a Long. + */ + static isLong(obj: any): obj is Long; + + /** + * Converts the specified value to a Long. + */ + static fromValue( + val: Long | number | string | { low: number; high: number; unsigned: boolean }, + unsigned?: boolean + ): Long; + + /** + * Returns the sum of this and the specified Long. + */ + add(addend: number | Long | string): Long; + + /** + * Returns the bitwise AND of this Long and the specified. + */ + and(other: Long | number | string): Long; + + /** + * Compares this Long's value with the specified's. + */ + compare(other: Long | number | string): number; + + /** + * Compares this Long's value with the specified's. + */ + comp(other: Long | number | string): number; + + /** + * Returns this Long divided by the specified. + */ + divide(divisor: Long | number | string): Long; + + /** + * Returns this Long divided by the specified. + */ + div(divisor: Long | number | string): Long; + + /** + * Tests if this Long's value equals the specified's. + */ + equals(other: Long | number | string): boolean; + + /** + * Tests if this Long's value equals the specified's. + */ + eq(other: Long | number | string): boolean; + + /** + * Gets the high 32 bits as a signed integer. + */ + getHighBits(): number; + + /** + * Gets the high 32 bits as an unsigned integer. + */ + getHighBitsUnsigned(): number; + + /** + * Gets the low 32 bits as a signed integer. + */ + getLowBits(): number; + + /** + * Gets the low 32 bits as an unsigned integer. + */ + getLowBitsUnsigned(): number; + + /** + * Gets the number of bits needed to represent the absolute value of this Long. + */ + getNumBitsAbs(): number; + + /** + * Tests if this Long's value is greater than the specified's. + */ + greaterThan(other: Long | number | string): boolean; + + /** + * Tests if this Long's value is greater than the specified's. + */ + gt(other: Long | number | string): boolean; + + /** + * Tests if this Long's value is greater than or equal the specified's. + */ + greaterThanOrEqual(other: Long | number | string): boolean; + + /** + * Tests if this Long's value is greater than or equal the specified's. + */ + gte(other: Long | number | string): boolean; + + /** + * Tests if this Long's value is greater than or equal the specified's. + */ + ge(other: Long | number | string): boolean; + + /** + * Tests if this Long's value is even. + */ + isEven(): boolean; + + /** + * Tests if this Long's value is negative. + */ + isNegative(): boolean; + + /** + * Tests if this Long's value is odd. + */ + isOdd(): boolean; + + /** + * Tests if this Long's value is positive or zero. + */ + isPositive(): boolean; + + /** + * Tests if this Long's value equals zero. + */ + isZero(): boolean; + + /** + * Tests if this Long's value equals zero. + */ + eqz(): boolean; + + /** + * Tests if this Long's value is less than the specified's. + */ + lessThan(other: Long | number | string): boolean; + + /** + * Tests if this Long's value is less than the specified's. + */ + lt(other: Long | number | string): boolean; + + /** + * Tests if this Long's value is less than or equal the specified's. + */ + lessThanOrEqual(other: Long | number | string): boolean; + + /** + * Tests if this Long's value is less than or equal the specified's. + */ + lte(other: Long | number | string): boolean; + + /** + * Tests if this Long's value is less than or equal the specified's. + */ + le(other: Long | number | string): boolean; + + /** + * Returns this Long modulo the specified. + */ + modulo(other: Long | number | string): Long; + + /** + * Returns this Long modulo the specified. + */ + mod(other: Long | number | string): Long; + + /** + * Returns this Long modulo the specified. + */ + rem(other: Long | number | string): Long; + + /** + * Returns the product of this and the specified Long. + */ + multiply(multiplier: Long | number | string): Long; + + /** + * Returns the product of this and the specified Long. + */ + mul(multiplier: Long | number | string): Long; + + /** + * Negates this Long's value. + */ + negate(): Long; + + /** + * Negates this Long's value. + */ + neg(): Long; + + /** + * Returns the bitwise NOT of this Long. + */ + not(): Long; + + /** + * Returns count leading zeros of this Long. + */ + countLeadingZeros(): number; + + /** + * Returns count leading zeros of this Long. + */ + clz(): number; + + /** + * Returns count trailing zeros of this Long. + */ + countTrailingZeros(): number; + + /** + * Returns count trailing zeros of this Long. + */ + ctz(): number; + + /** + * Tests if this Long's value differs from the specified's. + */ + notEquals(other: Long | number | string): boolean; + + /** + * Tests if this Long's value differs from the specified's. + */ + neq(other: Long | number | string): boolean; + + /** + * Tests if this Long's value differs from the specified's. + */ + ne(other: Long | number | string): boolean; + + /** + * Returns the bitwise OR of this Long and the specified. + */ + or(other: Long | number | string): Long; + + /** + * Returns this Long with bits shifted to the left by the given amount. + */ + shiftLeft(numBits: number | Long): Long; + + /** + * Returns this Long with bits shifted to the left by the given amount. + */ + shl(numBits: number | Long): Long; + + /** + * Returns this Long with bits arithmetically shifted to the right by the given amount. + */ + shiftRight(numBits: number | Long): Long; + + /** + * Returns this Long with bits arithmetically shifted to the right by the given amount. + */ + shr(numBits: number | Long): Long; + + /** + * Returns this Long with bits logically shifted to the right by the given amount. + */ + shiftRightUnsigned(numBits: number | Long): Long; + + /** + * Returns this Long with bits logically shifted to the right by the given amount. + */ + shru(numBits: number | Long): Long; + + /** + * Returns this Long with bits logically shifted to the right by the given amount. + */ + shr_u(numBits: number | Long): Long; + + /** + * Returns this Long with bits rotated to the left by the given amount. + */ + rotateLeft(numBits: number | Long): Long; + + /** + * Returns this Long with bits rotated to the left by the given amount. + */ + rotl(numBits: number | Long): Long; + + /** + * Returns this Long with bits rotated to the right by the given amount. + */ + rotateRight(numBits: number | Long): Long; + + /** + * Returns this Long with bits rotated to the right by the given amount. + */ + rotr(numBits: number | Long): Long; + + /** + * Returns the difference of this and the specified Long. + */ + subtract(subtrahend: number | Long | string): Long; + + /** + * Returns the difference of this and the specified Long. + */ + sub(subtrahend: number | Long | string): Long; + + /** + * Converts the Long to a 32 bit integer, assuming it is a 32 bit integer. + */ + toInt(): number; + + /** + * Converts the Long to a the nearest floating-point representation of this value (double, 53 bit mantissa). + */ + toNumber(): number; + + /** + * Converts this Long to its byte representation. + */ + + toBytes(le?: boolean): number[]; + + /** + * Converts this Long to its little endian byte representation. + */ + + toBytesLE(): number[]; + + /** + * Converts this Long to its big endian byte representation. + */ + + toBytesBE(): number[]; + + /** + * Converts this Long to signed. + */ + toSigned(): Long; + + /** + * Converts the Long to a string written in the specified radix. + */ + toString(radix?: number): string; + + /** + * Converts this Long to unsigned. + */ + toUnsigned(): Long; + + /** + * Returns the bitwise XOR of this Long and the given one. + */ + xor(other: Long | number | string): Long; + } +} diff --git a/src/administration/dtos/organization-user.ts b/src/administration/dtos/organization-user.ts new file mode 100644 index 0000000..3b657b2 --- /dev/null +++ b/src/administration/dtos/organization-user.ts @@ -0,0 +1,33 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { OrganizationUserRole } from '../entities/constants'; + +export const organizationUserSchema = { + type: 'object', + required: ['object', 'id', 'name', 'email', 'role', 'added_at'], + properties: { + object: { const: 'organization.user' }, + id: { type: 'string' }, + name: { type: 'string' }, + email: { type: 'string' }, + role: { type: 'string', enum: Object.values(OrganizationUserRole) }, + added_at: { type: 'number' } + } +} as const satisfies JSONSchema; +export type OrganizationUser = FromSchema; diff --git a/src/administration/dtos/organization-users-list.ts b/src/administration/dtos/organization-users-list.ts new file mode 100644 index 0000000..daebec3 --- /dev/null +++ b/src/administration/dtos/organization-users-list.ts @@ -0,0 +1,39 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema } from 'json-schema-to-ts'; + +import { organizationUserSchema } from './organization-user'; + +import { createPaginationQuerySchema, withPagination } from '@/schema.js'; +import { JSONSchema } from '@/ajv'; + +export const organizationUsersListQuerySchema = { + type: 'object', + additionalProperties: false, + properties: { + ...createPaginationQuerySchema().properties, + search: { + type: 'string', + minLength: 3, + nullable: true + } + } +} as const satisfies JSONSchema; +export type OrganizationUsersListQuery = FromSchema; + +export const organizationUsersListResponseSchema = withPagination(organizationUserSchema); +export type OrganizationUsersListResponse = FromSchema; diff --git a/src/administration/dtos/project-archive.ts b/src/administration/dtos/project-archive.ts new file mode 100644 index 0000000..942f8a5 --- /dev/null +++ b/src/administration/dtos/project-archive.ts @@ -0,0 +1,26 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema } from 'json-schema-to-ts'; + +import { projectSchema } from './project'; +import { projectReadParamsSchema } from './project-read'; + +export const projectArchiveParamsSchema = projectReadParamsSchema; +export type ProjectArchiveParams = FromSchema; + +export const projectArchiveResponseSchema = projectSchema; +export type ProjectArchiveResponse = FromSchema; diff --git a/src/administration/dtos/project-create.ts b/src/administration/dtos/project-create.ts new file mode 100644 index 0000000..b968065 --- /dev/null +++ b/src/administration/dtos/project-create.ts @@ -0,0 +1,39 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { ProjectVisiblity } from '../entities/project.entity.js'; + +import { projectSchema } from './project.js'; + +export const projectCreateBodySchema = { + type: 'object', + additionalProperties: false, + required: ['name'], + properties: { + name: { type: 'string' }, + visibility: { + type: 'string', + enum: Object.values(ProjectVisiblity), + default: ProjectVisiblity.PUBLIC + } + } +} as const satisfies JSONSchema; +export type ProjectCreateBody = FromSchema; + +export const projectCreateResponseSchema = projectSchema; +export type ProjectCreateResponse = FromSchema; diff --git a/src/administration/dtos/project-read.ts b/src/administration/dtos/project-read.ts new file mode 100644 index 0000000..a683448 --- /dev/null +++ b/src/administration/dtos/project-read.ts @@ -0,0 +1,32 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { projectSchema } from './project'; + +export const projectReadParamsSchema = { + type: 'object', + required: ['project_id'], + additionalProperties: false, + properties: { + project_id: { type: 'string' } + } +} as const satisfies JSONSchema; +export type ProjectReadParams = FromSchema; + +export const projectReadResponseSchema = projectSchema; +export type ProjectReadResponse = FromSchema; diff --git a/src/administration/dtos/project-update.ts b/src/administration/dtos/project-update.ts new file mode 100644 index 0000000..1a5dd5b --- /dev/null +++ b/src/administration/dtos/project-update.ts @@ -0,0 +1,41 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { ProjectVisiblity } from '../entities/project.entity.js'; + +import { projectSchema } from './project.js'; +import { projectReadParamsSchema } from './project-read.js'; + +export const projectUpdateParamsSchema = projectReadParamsSchema; +export type ProjectUpdateParams = FromSchema; + +export const projectUpdateBodySchema = { + type: 'object', + additionalProperties: false, + properties: { + name: { type: 'string' }, + visibility: { + type: 'string', + enum: Object.values(ProjectVisiblity) + } + } +} as const satisfies JSONSchema; +export type ProjectUpdateBody = FromSchema; + +export const projectUpdateResponseSchema = projectSchema; +export type ProjectUpdateResponse = FromSchema; diff --git a/src/administration/dtos/project-user-read.ts b/src/administration/dtos/project-user-read.ts new file mode 100644 index 0000000..c09a129 --- /dev/null +++ b/src/administration/dtos/project-user-read.ts @@ -0,0 +1,33 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { projectUserSchema } from './project-user'; + +export const projectUserReadParamsSchema = { + type: 'object', + required: ['project_id', 'user_id'], + additionalProperties: false, + properties: { + project_id: { type: 'string' }, + user_id: { type: 'string' } + } +} as const satisfies JSONSchema; +export type ProjectUserReadParams = FromSchema; + +export const projectUserReadResponseSchema = projectUserSchema; +export type ProjectUserReadResponse = FromSchema; diff --git a/src/administration/dtos/project-user.ts b/src/administration/dtos/project-user.ts new file mode 100644 index 0000000..69828e3 --- /dev/null +++ b/src/administration/dtos/project-user.ts @@ -0,0 +1,33 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { ProjectRole } from '../entities/constants'; + +export const projectUserSchema = { + type: 'object', + required: ['object', 'id', 'name', 'email', 'role', 'added_at'], + properties: { + object: { const: 'organization.project.user' }, + id: { type: 'string' }, + name: { type: 'string' }, + email: { type: 'string' }, + role: { type: 'string', enum: Object.values(ProjectRole) }, + added_at: { type: 'number' } + } +} as const satisfies JSONSchema; +export type ProjectUser = FromSchema; diff --git a/src/administration/dtos/project-users-create.ts b/src/administration/dtos/project-users-create.ts new file mode 100644 index 0000000..bb7fd67 --- /dev/null +++ b/src/administration/dtos/project-users-create.ts @@ -0,0 +1,39 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { ProjectRole } from '../entities/constants'; + +import { projectUserSchema } from './project-user'; +import { projectUsersListParamsSchema } from './project-users-list'; + +export const projectUserCreateBodySchema = { + type: 'object', + additionalProperties: false, + required: ['role', 'user_id'], + properties: { + role: { type: 'string', enum: Object.values(ProjectRole) }, + user_id: { type: 'string' } + } +} as const satisfies JSONSchema; +export type ProjectUserCreateBody = FromSchema; + +export const projectUserCreateResponseSchema = projectUserSchema; +export type ProjectUserCreateResponse = FromSchema; + +export const projectUserCreateParamsSchema = projectUsersListParamsSchema; +export type ProjectUserCreateParams = FromSchema; diff --git a/src/administration/dtos/project-users-delete.ts b/src/administration/dtos/project-users-delete.ts new file mode 100644 index 0000000..914bdb9 --- /dev/null +++ b/src/administration/dtos/project-users-delete.ts @@ -0,0 +1,27 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema } from 'json-schema-to-ts'; + +import { projectUsersReadParamsSchema } from './project-users-read'; + +import { createDeleteSchema } from '@/schema'; + +export const projectUserDeleteParamsSchema = projectUsersReadParamsSchema; +export type ProjectUserDeleteParams = FromSchema; + +export const projectUserDeleteResponseSchema = createDeleteSchema('project-user'); +export type ProjectUserDeleteResponse = FromSchema; diff --git a/src/administration/dtos/project-users-list.ts b/src/administration/dtos/project-users-list.ts new file mode 100644 index 0000000..5d40dcd --- /dev/null +++ b/src/administration/dtos/project-users-list.ts @@ -0,0 +1,49 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema } from 'json-schema-to-ts'; + +import { projectUserSchema } from './project-user'; + +import { createPaginationQuerySchema, withPagination } from '@/schema.js'; +import { JSONSchema } from '@/ajv'; + +export const projectUsersListQuerySchema = { + type: 'object', + additionalProperties: false, + properties: { + ...createPaginationQuerySchema().properties, + search: { + type: 'string', + minLength: 3, + nullable: true + } + } +} as const satisfies JSONSchema; +export type ProjectUsersListQuery = FromSchema; + +export const projectUsersListResponseSchema = withPagination(projectUserSchema); +export type ProjectUsersListResponse = FromSchema; + +export const projectUsersListParamsSchema = { + type: 'object', + required: ['project_id'], + additionalProperties: false, + properties: { + project_id: { type: 'string' } + } +} as const satisfies JSONSchema; +export type ProjectUsersListParams = FromSchema; diff --git a/src/administration/dtos/project-users-read.ts b/src/administration/dtos/project-users-read.ts new file mode 100644 index 0000000..47ceb19 --- /dev/null +++ b/src/administration/dtos/project-users-read.ts @@ -0,0 +1,33 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { projectUserSchema } from './project-user'; + +export const projectUsersReadParamsSchema = { + type: 'object', + required: ['project_id', 'user_id'], + additionalProperties: false, + properties: { + project_id: { type: 'string' }, + user_id: { type: 'string' } + } +} as const satisfies JSONSchema; +export type ProjectsUserReadParams = FromSchema; + +export const projectUsersReadResponseSchema = projectUserSchema; +export type ProjectUsersReadResponse = FromSchema; diff --git a/src/administration/dtos/project-users-update.ts b/src/administration/dtos/project-users-update.ts new file mode 100644 index 0000000..3894802 --- /dev/null +++ b/src/administration/dtos/project-users-update.ts @@ -0,0 +1,37 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { ProjectRole } from '../entities/constants'; + +import { projectUsersReadParamsSchema } from './project-users-read'; +import { projectUserSchema } from './project-user'; + +export const projectUserUpdateBodySchema = { + type: 'object', + additionalProperties: false, + properties: { + role: { type: 'string', enum: Object.values(ProjectRole) } + } +} as const satisfies JSONSchema; +export type ProjectUserUpdateBody = FromSchema; + +export const projectUserUpdateResponseSchema = projectUserSchema; +export type ProjectUserUpdateResponse = FromSchema; + +export const projectUserUpdateParamsSchema = projectUsersReadParamsSchema; +export type ProjectUserUpdateParams = FromSchema; diff --git a/src/administration/dtos/project.ts b/src/administration/dtos/project.ts new file mode 100644 index 0000000..7edc7f7 --- /dev/null +++ b/src/administration/dtos/project.ts @@ -0,0 +1,34 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { ProjectStatus, ProjectVisiblity } from '../entities/project.entity'; + +export const projectSchema = { + type: 'object', + required: ['object', 'id', 'name', 'visibility', 'status', 'created_at', 'archived_at'], + properties: { + object: { const: 'organization.project' }, + id: { type: 'string' }, + name: { type: 'string' }, + visibility: { type: 'string', enum: Object.values(ProjectVisiblity) }, + status: { type: 'string', enum: Object.values(ProjectStatus) }, + created_at: { type: 'number' }, + archived_at: { type: 'number', nullable: true } + } +} as const satisfies JSONSchema; +export type Project = FromSchema; diff --git a/src/administration/dtos/projects-list.ts b/src/administration/dtos/projects-list.ts new file mode 100644 index 0000000..bf1603a --- /dev/null +++ b/src/administration/dtos/projects-list.ts @@ -0,0 +1,37 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { projectSchema } from './project'; + +import { createPaginationQuerySchema, withPagination } from '@/schema.js'; + +export const projectsListQuerySchema = { + type: 'object', + additionalProperties: false, + properties: { + ...createPaginationQuerySchema().properties, + include_archived: { + type: 'boolean', + default: false + } + } +} as const satisfies JSONSchema; +export type ProjectsListQuery = FromSchema; + +export const projectsListResponseSchema = withPagination(projectSchema); +export type ProjectsListResponse = FromSchema; diff --git a/src/administration/entities/constants.ts b/src/administration/entities/constants.ts new file mode 100644 index 0000000..f868635 --- /dev/null +++ b/src/administration/entities/constants.ts @@ -0,0 +1,28 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const ProjectRole = { + ADMIN: 'admin', + WRITER: 'writer', + READER: 'reader' +} as const; +export type ProjectRole = (typeof ProjectRole)[keyof typeof ProjectRole]; + +export const OrganizationUserRole = { + OWNER: 'owner', + MEMBER: 'member' +} as const; +export type OrganizationUserRole = (typeof OrganizationUserRole)[keyof typeof OrganizationUserRole]; diff --git a/src/administration/entities/invite.entity.ts b/src/administration/entities/invite.entity.ts new file mode 100644 index 0000000..5699332 --- /dev/null +++ b/src/administration/entities/invite.entity.ts @@ -0,0 +1,64 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Entity, Enum, Index, Property } from '@mikro-orm/core'; + +import { OrganizationUserRole } from './constants'; +import { + OrganizationAdministrationScopedEntity, + OrganizationAdministrationScopedEntityInput +} from './organization-administration-scoped.entity'; + +export const InviteStatus = { + PENDING: 'pending', + ACCEPTED: 'accepted', + EXPIRED: 'expired' +} as const; +export type InviteStatus = (typeof InviteStatus)[keyof typeof InviteStatus]; + +@Entity() +export class Invite extends OrganizationAdministrationScopedEntity { + getIdPrefix(): string { + return 'invite'; + } + + @Index() + @Property() + email: string; + + @Enum(() => OrganizationUserRole) + role: OrganizationUserRole; + + @Enum(() => InviteStatus) + status: InviteStatus; + + @Property() + expiresAt: Date; + + @Property() + acceptedAt?: Date; + + constructor({ email, role, status, expiresAt, ...rest }: InviteInput) { + super(rest); + this.email = email; + this.role = role; + this.status = status; + this.expiresAt = expiresAt; + } +} + +export type InviteInput = OrganizationAdministrationScopedEntityInput & + Pick; diff --git a/src/administration/entities/organization-administration-scoped.entity.ts b/src/administration/entities/organization-administration-scoped.entity.ts new file mode 100644 index 0000000..6e7adbb --- /dev/null +++ b/src/administration/entities/organization-administration-scoped.entity.ts @@ -0,0 +1,97 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + BeforeCreate, + BeforeDelete, + BeforeUpdate, + Entity, + EventArgs, + Filter, + Index, + ManyToOne, + ref, + Ref +} from '@mikro-orm/core'; +import { requestContext } from '@fastify/request-context'; + +import { BaseEntity, BaseEntityInput } from '../../common/base.entity.js'; + +import type { Organization } from '@/administration/entities/organization.entity.js'; +import type { OrganizationUser } from '@/administration/entities/organization-user.entity.js'; +import { getOrganizationUser } from '@/administration/helpers.js'; +import { OrganizationUserRole } from '@/administration/entities/constants.js'; +import { APIError, APIErrorCode } from '@/errors/error.entity.js'; +import { inJob, inSeeder } from '@/context.js'; + +@Entity({ abstract: true }) +@Filter({ + name: 'orgAdministrationAccess', + cond: async (_ = {}, type) => { + if (inJob() || inSeeder()) return; + + const orgUser = requestContext.get('organizationUser'); + if (!orgUser) return { _id: null }; + + switch (type) { + case 'read': { + return { organization: orgUser.organization }; + } + default: + throw new Error('Not Implemented'); + } + }, + default: true +}) +export abstract class OrganizationAdministrationScopedEntity extends BaseEntity { + @Index() + @ManyToOne() + organization: Ref; + + @ManyToOne() + createdBy: Ref; + + constructor({ organization, createdBy, ...rest }: OrganizationAdministrationScopedEntityInput) { + super(rest); + + if (organization && createdBy) { + this.organization = organization; + this.createdBy = createdBy; + } else { + const orgUser = getOrganizationUser(); + + this.organization = orgUser.organization; + this.createdBy = createdBy ?? ref(orgUser); + } + } + + @BeforeCreate() + @BeforeUpdate() + @BeforeDelete() + async authorize(_: EventArgs) { + if (inJob() || inSeeder()) return; + + const orgUser = getOrganizationUser(); + if (orgUser.role !== OrganizationUserRole.OWNER) + throw new APIError({ + message: 'Insufficient organization role', + code: APIErrorCode.FORBIDDEN + }); + } +} + +export type OrganizationAdministrationScopedEntityInput = BaseEntityInput & + Partial>; diff --git a/src/administration/entities/organization-user.entity.ts b/src/administration/entities/organization-user.entity.ts new file mode 100644 index 0000000..2eb936b --- /dev/null +++ b/src/administration/entities/organization-user.entity.ts @@ -0,0 +1,59 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Entity, Enum, EventArgs, Index, ManyToOne, Ref, Unique } from '@mikro-orm/core'; + +import { getOrganizationUser } from '../helpers'; + +import { OrganizationUserRole } from './constants'; +import { + OrganizationAdministrationScopedEntity, + OrganizationAdministrationScopedEntityInput +} from './organization-administration-scoped.entity'; + +import { User } from '@/users/entities/user.entity.js'; +import { inSeeder } from '@/context'; + +@Entity() +@Unique({ properties: ['organization', 'user'] }) +export class OrganizationUser extends OrganizationAdministrationScopedEntity { + getIdPrefix(): string { + return 'org_user'; + } + + @Index() + @ManyToOne() + user: Ref; + + @Enum(() => OrganizationUserRole) + role: OrganizationUserRole; + + constructor({ user, role, ...rest }: OrganizationUserInput) { + super(rest); + this.user = user; + this.role = role; + } + + override async authorize(_: EventArgs) { + if (inSeeder()) return; + const orgUser = getOrganizationUser(); + if (this.id === orgUser.id) return; + super.authorize(_); + } +} + +export type OrganizationUserInput = OrganizationAdministrationScopedEntityInput & + Pick; diff --git a/src/administration/entities/organization.entity.ts b/src/administration/entities/organization.entity.ts new file mode 100644 index 0000000..8df94b7 --- /dev/null +++ b/src/administration/entities/organization.entity.ts @@ -0,0 +1,41 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Entity, ManyToOne, Property, Ref } from '@mikro-orm/core'; + +import { BaseEntity, BaseEntityInput } from '@/common/base.entity.js'; +import { User } from '@/users/entities/user.entity'; + +@Entity() +export class Organization extends BaseEntity { + getIdPrefix(): string { + return 'org'; + } + + @Property() + name: string; + + @ManyToOne() + createdBy: Ref; + + constructor({ name, createdBy, ...rest }: OrganizationInput) { + super(rest); + this.name = name; + this.createdBy = createdBy; + } +} + +export type OrganizationInput = BaseEntityInput & Pick; diff --git a/src/administration/entities/principals/principal.entity.ts b/src/administration/entities/principals/principal.entity.ts new file mode 100644 index 0000000..8a74b15 --- /dev/null +++ b/src/administration/entities/principals/principal.entity.ts @@ -0,0 +1,34 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, Enum } from '@mikro-orm/core'; + +import { UserPrincipal } from './user-principal.entity.js'; +import { ServiceAccountPrincipal } from './service-account-principal.entity.js'; + +export const PrincipalType = { + USER: 'user', + SERVICE_ACCOUNT: 'service_account' +} as const; +export type PrincipalType = (typeof PrincipalType)[keyof typeof PrincipalType]; + +@Embeddable({ abstract: true, discriminatorColumn: 'type' }) +export abstract class Principal { + @Enum(() => PrincipalType) + type!: PrincipalType; +} + +export type AnyPrincipal = ServiceAccountPrincipal | UserPrincipal; diff --git a/src/administration/entities/principals/service-account-principal.entity.ts b/src/administration/entities/principals/service-account-principal.entity.ts new file mode 100644 index 0000000..6f8a1c1 --- /dev/null +++ b/src/administration/entities/principals/service-account-principal.entity.ts @@ -0,0 +1,29 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, ManyToOne, Ref } from '@mikro-orm/core'; + +import { ServiceAccount } from '../service-account.entity.js'; + +import { Principal, PrincipalType } from './principal.entity.js'; + +@Embeddable({ discriminatorValue: PrincipalType.SERVICE_ACCOUNT }) +export class ServiceAccountPrincipal extends Principal { + type = PrincipalType.SERVICE_ACCOUNT; + + @ManyToOne() + account!: Ref; +} diff --git a/src/administration/entities/principals/user-principal.entity.ts b/src/administration/entities/principals/user-principal.entity.ts new file mode 100644 index 0000000..cea8a78 --- /dev/null +++ b/src/administration/entities/principals/user-principal.entity.ts @@ -0,0 +1,36 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, ManyToOne, Ref } from '@mikro-orm/core'; + +import { OrganizationUser } from '../organization-user.entity.js'; + +import { Principal, PrincipalType } from './principal.entity.js'; + +@Embeddable({ discriminatorValue: PrincipalType.USER }) +export class UserPrincipal extends Principal { + type = PrincipalType.USER; + + @ManyToOne() + user: Ref; + + constructor({ user }: UserPrincipalInput) { + super(); + this.user = user; + } +} + +export type UserPrincipalInput = Pick; diff --git a/src/administration/entities/project-administration-scoped.entity.ts b/src/administration/entities/project-administration-scoped.entity.ts new file mode 100644 index 0000000..8fab7fa --- /dev/null +++ b/src/administration/entities/project-administration-scoped.entity.ts @@ -0,0 +1,109 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + BeforeCreate, + BeforeDelete, + BeforeUpdate, + Entity, + EventArgs, + Filter, + Index, + ManyToOne, + ref, + Ref +} from '@mikro-orm/core'; +import { requestContext } from '@fastify/request-context'; + +import { BaseEntity, BaseEntityInput } from '../../common/base.entity.js'; + +import { getProjectPrincipal } from '@/administration/helpers.js'; +import type { Project } from '@/administration/entities/project.entity.js'; +import type { ProjectPrincipal } from '@/administration/entities/project-principal.entity.js'; +import { ProjectRole } from '@/administration/entities/constants.js'; +import { APIError, APIErrorCode } from '@/errors/error.entity.js'; +import { inJob, inSeeder } from '@/context.js'; + +export const projectAdministrationAccessFilter = async ( + _ = {}, + type: 'read' | 'update' | 'delete' +) => { + if (inJob() || inSeeder()) return; + + const projectPrincipal = requestContext.get('projectPrincipal'); + if (!projectPrincipal) return { _id: null }; + + switch (type) { + case 'read': + if (projectPrincipal.role === ProjectRole.ADMIN) return { project: projectPrincipal.project }; + else + return { + _id: projectPrincipal.id, + project: projectPrincipal.project + }; + default: + throw new Error('Not Implemented'); + } +}; + +@Entity({ abstract: true }) +@Filter({ + name: 'projectAdministrationAccess', + cond: projectAdministrationAccessFilter, + default: true +}) +export abstract class ProjectAdministrationScopedEntity extends BaseEntity { + @Index() + @ManyToOne() + project: Ref; + + @ManyToOne() + createdBy: Ref; + + constructor({ project, createdBy, ...rest }: ProjectAdministrationScopedEntityInput) { + super(rest); + + if (project && createdBy) { + this.project = project; + this.createdBy = createdBy; + } else { + const projectPrincipal = getProjectPrincipal(); + + this.project = projectPrincipal.project; + this.createdBy = ref(projectPrincipal); + } + } + + @BeforeCreate() + @BeforeUpdate() + @BeforeDelete() + async authorize(_: EventArgs) { + if (inJob() || inSeeder()) return; + + const projectPrincipal = getProjectPrincipal(); + if ( + projectPrincipal.role !== ProjectRole.ADMIN || + this.project.id !== projectPrincipal.project.id + ) + throw new APIError({ + message: 'Insufficient project role', + code: APIErrorCode.FORBIDDEN + }); + } +} + +export type ProjectAdministrationScopedEntityInput = BaseEntityInput & + Partial>; diff --git a/src/administration/entities/project-api-key.entity.ts b/src/administration/entities/project-api-key.entity.ts new file mode 100644 index 0000000..ac718a4 --- /dev/null +++ b/src/administration/entities/project-api-key.entity.ts @@ -0,0 +1,40 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Entity, Property } from '@mikro-orm/core'; + +import { + ProjectAdministrationScopedEntity, + ProjectAdministrationScopedEntityInput +} from './project-administration-scoped.entity'; + +@Entity() +export class ProjectApiKey extends ProjectAdministrationScopedEntity { + getIdPrefix(): string { + return 'key'; + } + + @Property() + key: string; + + constructor({ key, ...rest }: ProjectApiKeyInput) { + super(rest); + this.key = key; + } +} + +export type ProjectApiKeyInput = ProjectAdministrationScopedEntityInput & + Pick; diff --git a/src/administration/entities/project-principal.entity.ts b/src/administration/entities/project-principal.entity.ts new file mode 100644 index 0000000..40f335b --- /dev/null +++ b/src/administration/entities/project-principal.entity.ts @@ -0,0 +1,80 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embedded, Entity, Enum, Filter, Index } from '@mikro-orm/core'; +import { requestContext } from '@fastify/request-context'; + +import type { ServiceAccountPrincipal } from './principals/service-account-principal.entity.js'; +import type { UserPrincipal } from './principals/user-principal.entity.js'; +import { ProjectRole } from './constants.js'; +import { + projectAdministrationAccessFilter, + ProjectAdministrationScopedEntity, + ProjectAdministrationScopedEntityInput +} from './project-administration-scoped.entity.js'; +import { PrincipalType } from './principals/principal.entity.js'; + +@Index({ + options: [ + { + principal: 1, + project: 1 + }, + { + unique: true, + partialFilterExpression: { deletedAt: { $in: [null] } } + } + ] +}) +@Entity() +@Filter({ + name: 'projectAdministrationAccess', // override + cond: async (_ = {}, type) => { + const projectPrincipal = requestContext.get('projectPrincipal'); + if (projectPrincipal && type === 'read') { + // All project members are allowed to see project users + return { + $or: [ + await projectAdministrationAccessFilter(_, type), + { principal: { type: PrincipalType.USER }, project: projectPrincipal.project.id } + ] + }; + } else { + return await projectAdministrationAccessFilter(_, type); + } + }, + default: true +}) +export class ProjectPrincipal extends ProjectAdministrationScopedEntity { + getIdPrefix(): string { + return 'proj_principal'; + } + + @Embedded({ object: true }) + principal: ServiceAccountPrincipal | UserPrincipal; + + @Enum(() => ProjectRole) + role: ProjectRole; + + constructor({ principal, role, ...rest }: ProjectPrincipalInput) { + super(rest); + this.principal = principal; + this.role = role; + } +} + +export type ProjectPrincipalInput = ProjectAdministrationScopedEntityInput & + Pick; diff --git a/src/administration/entities/project.entity.ts b/src/administration/entities/project.entity.ts new file mode 100644 index 0000000..f824cb6 --- /dev/null +++ b/src/administration/entities/project.entity.ts @@ -0,0 +1,97 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Entity, Enum, EventArgs, Property } from '@mikro-orm/core'; + +import { getProjectPrincipal } from '../helpers'; + +import { + OrganizationAdministrationScopedEntity, + OrganizationAdministrationScopedEntityInput +} from './organization-administration-scoped.entity'; +import { ProjectRole } from './constants'; + +import { APIError, APIErrorCode } from '@/errors/error.entity'; + +export const ProjectStatus = { + ACTIVE: 'active', + ARCHIVED: 'archived' +} as const; +export type ProjectStatus = (typeof ProjectStatus)[keyof typeof ProjectStatus]; + +export const ProjectVisiblity = { + PUBLIC: 'public', + PRIVATE: 'private' +} as const; +export type ProjectVisiblity = (typeof ProjectVisiblity)[keyof typeof ProjectVisiblity]; + +@Entity() +export class Project extends OrganizationAdministrationScopedEntity { + getIdPrefix(): string { + return 'proj'; + } + + @Property() + name: string; + + @Enum(() => ProjectStatus) + status: ProjectStatus; + + @Property() + archivedAt?: Date; + + @Enum(() => ProjectVisiblity) + visibility: ProjectVisiblity; + + constructor({ + name, + status = ProjectStatus.ACTIVE, + visibility = ProjectVisiblity.PUBLIC, + ...rest + }: ProjectInput) { + super(rest); + + this.name = name; + this.status = status; + this.visibility = visibility; + } + + override delete(): void { + throw new Error("Projects can't be deleted, only archived"); + } + + archive() { + this.archivedAt = new Date(); + this.status = ProjectStatus.ARCHIVED; + } + + override async authorize(_: EventArgs) { + try { + await super.authorize(_); + } catch (err) { + if (err instanceof APIError && err.code === APIErrorCode.FORBIDDEN) { + const projectPrincipal = getProjectPrincipal(); + if (projectPrincipal.project.id === this.id && projectPrincipal.role === ProjectRole.ADMIN) + return; + } + throw err; + } + } +} + +export type ProjectInput = OrganizationAdministrationScopedEntityInput & + Pick & + Pick, 'status' | 'visibility'>; diff --git a/src/administration/entities/service-account.entity.ts b/src/administration/entities/service-account.entity.ts new file mode 100644 index 0000000..6c2ce66 --- /dev/null +++ b/src/administration/entities/service-account.entity.ts @@ -0,0 +1,40 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Entity, Property } from '@mikro-orm/core'; + +import { + ProjectAdministrationScopedEntity, + ProjectAdministrationScopedEntityInput +} from './project-administration-scoped.entity'; + +@Entity() +export class ServiceAccount extends ProjectAdministrationScopedEntity { + getIdPrefix(): string { + return 'svc_acct'; + } + + @Property() + name: string; + + constructor({ name, ...rest }: ServiceAccountInput) { + super(rest); + this.name = name; + } +} + +export type ServiceAccountInput = ProjectAdministrationScopedEntityInput & + Pick; diff --git a/src/administration/helpers.ts b/src/administration/helpers.ts new file mode 100644 index 0000000..1420499 --- /dev/null +++ b/src/administration/helpers.ts @@ -0,0 +1,33 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { requestContext } from '@fastify/request-context'; + +import { APIError, APIErrorCode } from '@/errors/error.entity'; + +export function getOrganizationUser() { + const orgUser = requestContext.get('organizationUser'); + if (!orgUser) + throw new APIError({ message: 'Organization user not found', code: APIErrorCode.NOT_FOUND }); + return orgUser; +} + +export function getProjectPrincipal() { + const projectPrincipal = requestContext.get('projectPrincipal'); + if (!projectPrincipal) + throw new APIError({ message: 'Project principal not found', code: APIErrorCode.NOT_FOUND }); + return projectPrincipal; +} diff --git a/src/administration/organization-users.module.ts b/src/administration/organization-users.module.ts new file mode 100644 index 0000000..92fc1b2 --- /dev/null +++ b/src/administration/organization-users.module.ts @@ -0,0 +1,43 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FastifyPluginAsyncJsonSchemaToTs } from '@fastify/type-provider-json-schema-to-ts'; +import { StatusCodes } from 'http-status-codes'; + +import { + OrganizationUsersListQuery, + organizationUsersListQuerySchema, + organizationUsersListResponseSchema +} from './dtos/organization-users-list'; +import { listOrganizationUsers } from './organization-users.service'; + +import { Tag } from '@/swagger.js'; +import { AuthSecret } from '@/auth/utils'; + +export const organizationUsersModule: FastifyPluginAsyncJsonSchemaToTs = async (app) => { + app.get<{ Querystring: OrganizationUsersListQuery }>( + '/organization/users', + { + schema: { + querystring: organizationUsersListQuerySchema, + response: { [StatusCodes.OK]: organizationUsersListResponseSchema }, + tags: [Tag.BEE_API] + }, + preHandler: app.auth([AuthSecret.ACCESS_TOKEN]) + }, + async (req) => listOrganizationUsers(req.query) + ); +}; diff --git a/src/administration/organization-users.service.ts b/src/administration/organization-users.service.ts new file mode 100644 index 0000000..0c5cfc2 --- /dev/null +++ b/src/administration/organization-users.service.ts @@ -0,0 +1,68 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FilterQuery, Loaded } from '@mikro-orm/core'; +import dayjs from 'dayjs'; + +import { OrganizationUser } from './entities/organization-user.entity'; +import { OrganizationUser as OrganizationUserDto } from './dtos/organization-user'; +import { + OrganizationUsersListQuery, + OrganizationUsersListResponse +} from './dtos/organization-users-list'; + +import { ORM } from '@/database'; +import { createPaginatedResponse, getListCursor } from '@/utils/pagination'; +import { User } from '@/users/entities/user.entity'; + +export function toOrganizationUserDto( + organizationUser: Loaded +): OrganizationUserDto { + return { + object: 'organization.user', + id: organizationUser.user.id, + role: organizationUser.role, + name: organizationUser.user.$.name ?? '', + email: organizationUser.user.$.email ?? '', + added_at: dayjs(organizationUser.createdAt).unix() + }; +} + +export async function listOrganizationUsers({ + limit, + order, + order_by, + after, + before, + search +}: OrganizationUsersListQuery): Promise { + const where: FilterQuery> = {}; + + if (search) { + const regexp = new RegExp(search, 'i'); + const users = await ORM.em + .getRepository(User) + .find({ $or: [{ email: regexp }, { name: regexp }] }); + where.user = { $in: users.map((u) => u.id) }; + } + + const cursor = await getListCursor>( + where, + { limit, order, order_by, after, before, populate: ['user'] }, + ORM.em.getRepository(OrganizationUser) + ); + return createPaginatedResponse(cursor, toOrganizationUserDto); +} diff --git a/src/administration/project-users.module.ts b/src/administration/project-users.module.ts new file mode 100644 index 0000000..cc1b0e8 --- /dev/null +++ b/src/administration/project-users.module.ts @@ -0,0 +1,130 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FastifyPluginAsyncJsonSchemaToTs } from '@fastify/type-provider-json-schema-to-ts'; +import { StatusCodes } from 'http-status-codes'; + +import { + createProjectUser, + listProjectUsers, + readProjectUser, + deleteProjectUser, + updateProjectUser +} from './project-users.service'; +import { + ProjectUserReadParams, + projectUserReadParamsSchema, + projectUserReadResponseSchema +} from './dtos/project-user-read'; +import { + ProjectUserDeleteParams, + projectUserDeleteParamsSchema +} from './dtos/project-users-delete'; +import { + ProjectUsersListParams, + projectUsersListParamsSchema, + ProjectUsersListQuery, + projectUsersListQuerySchema, + projectUsersListResponseSchema +} from './dtos/project-users-list'; +import { + ProjectUserCreateBody, + projectUserCreateBodySchema, + ProjectUserCreateParams, + projectUserCreateParamsSchema, + projectUserCreateResponseSchema +} from './dtos/project-users-create'; +import { + ProjectUserUpdateBody, + projectUserUpdateBodySchema, + ProjectUserUpdateParams, + projectUserUpdateParamsSchema, + projectUserUpdateResponseSchema +} from './dtos/project-users-update'; + +import { createDeleteSchema } from '@/schema'; +import { Tag } from '@/swagger.js'; +import { AuthSecret } from '@/auth/utils'; + +export const projectUsersModule: FastifyPluginAsyncJsonSchemaToTs = async (app) => { + app.get<{ Params: ProjectUserReadParams }>( + '/organization/projects/:project_id/users/:user_id', + { + schema: { + params: projectUserReadParamsSchema, + response: { [StatusCodes.OK]: projectUserReadResponseSchema }, + tags: [Tag.BEE_API] + }, + preHandler: app.auth([AuthSecret.ACCESS_TOKEN]) + }, + async (req) => readProjectUser(req.params) + ); + + app.get<{ Params: ProjectUsersListParams; Querystring: ProjectUsersListQuery }>( + '/organization/projects/:project_id/users', + { + schema: { + params: projectUsersListParamsSchema, + querystring: projectUsersListQuerySchema, + response: { [StatusCodes.OK]: projectUsersListResponseSchema }, + tags: [Tag.BEE_API] + }, + preHandler: app.auth([AuthSecret.ACCESS_TOKEN]) + }, + async (req) => listProjectUsers({ ...req.params, ...req.query }) + ); + + app.delete<{ Params: ProjectUserDeleteParams }>( + '/organization/projects/:project_id/users/:user_id', + { + schema: { + params: projectUserDeleteParamsSchema, + response: { [StatusCodes.OK]: createDeleteSchema('project-user') }, + tags: [Tag.BEE_API] + }, + preHandler: app.auth([AuthSecret.ACCESS_TOKEN]) + }, + async (req) => deleteProjectUser(req.params) + ); + + app.post<{ Params: ProjectUserCreateParams; Body: ProjectUserCreateBody }>( + '/organization/projects/:project_id/users', + { + schema: { + params: projectUserCreateParamsSchema, + body: projectUserCreateBodySchema, + response: { [StatusCodes.OK]: projectUserCreateResponseSchema }, + tags: [Tag.BEE_API] + }, + preHandler: app.auth([AuthSecret.ACCESS_TOKEN]) + }, + async (req) => createProjectUser({ ...req.params, ...req.body }) + ); + + app.post<{ Params: ProjectUserUpdateParams; Body: ProjectUserUpdateBody }>( + '/organization/projects/:project_id/users/:user_id', + { + schema: { + params: projectUserUpdateParamsSchema, + body: projectUserUpdateBodySchema, + response: { [StatusCodes.OK]: projectUserUpdateResponseSchema }, + tags: [Tag.BEE_API] + }, + preHandler: app.auth([AuthSecret.ACCESS_TOKEN]) + }, + async (req) => updateProjectUser({ ...req.params, ...req.body }) + ); +}; diff --git a/src/administration/project-users.service.ts b/src/administration/project-users.service.ts new file mode 100644 index 0000000..c340580 --- /dev/null +++ b/src/administration/project-users.service.ts @@ -0,0 +1,227 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FilterQuery, Loaded, ref } from '@mikro-orm/core'; +import dayjs from 'dayjs'; + +import { ProjectPrincipal } from './entities/project-principal.entity'; +import { ProjectUser as ProjectUserDto } from './dtos/project-user'; +import { PrincipalType } from './entities/principals/principal.entity'; +import { ProjectUserReadParams, ProjectUserReadResponse } from './dtos/project-user-read'; +import { OrganizationUser } from './entities/organization-user.entity'; +import { + ProjectUsersListParams, + ProjectUsersListQuery, + ProjectUsersListResponse +} from './dtos/project-users-list'; +import { UserPrincipal } from './entities/principals/user-principal.entity'; +import { ProjectUserDeleteParams, ProjectUserDeleteResponse } from './dtos/project-users-delete'; +import { + ProjectUserCreateBody, + ProjectUserCreateParams, + ProjectUserCreateResponse +} from './dtos/project-users-create'; +import { Project, ProjectStatus } from './entities/project.entity'; +import { + ProjectUserUpdateBody, + ProjectUserUpdateParams, + ProjectUserUpdateResponse +} from './dtos/project-users-update'; +import { ProjectRole } from './entities/constants'; +import { getProjectPrincipal } from './helpers'; + +import { getUpdatedValue } from '@/utils/update'; +import { createDeleteResponse } from '@/utils/delete'; +import { createPaginatedResponse, getListCursor } from '@/utils/pagination'; +import { ORM } from '@/database'; +import { APIError, APIErrorCode } from '@/errors/error.entity'; +import { User } from '@/users/entities/user.entity'; + +export function toProjectUserDto( + projectPrincipal: Loaded +): ProjectUserDto { + const principal = projectPrincipal.principal; + if (principal.type !== PrincipalType.USER) throw new Error('Not a user principal'); + const user = (principal as Loaded).user.$.user.$; + return { + object: 'organization.project.user', + id: user.id, + name: user.name ?? '', + email: user.email ?? '', + role: projectPrincipal.role, + added_at: dayjs(projectPrincipal.createdAt).unix() + }; +} + +export async function readProjectUser({ + project_id, + user_id +}: ProjectUserReadParams): Promise { + const orgUser = await ORM.em.getRepository(OrganizationUser).findOneOrFail({ user: user_id }); + const projectPrincipal = await ORM.em + .getRepository(ProjectPrincipal) + .findOneOrFail( + { project: project_id, principal: { type: PrincipalType.USER, user: orgUser } }, + { populate: ['principal.user.user' as any] } + ); + if (orgUser.id !== (projectPrincipal.principal as UserPrincipal).user.id) + throw new Error('Organization user mismatch'); + return toProjectUserDto(projectPrincipal); +} + +export async function deleteProjectUser({ + project_id, + user_id +}: ProjectUserDeleteParams): Promise { + const orgUser = await ORM.em.getRepository(OrganizationUser).findOneOrFail({ user: user_id }); + const projectPrincipal = await ORM.em + .getRepository(ProjectPrincipal) + .findOneOrFail( + { project: project_id, principal: { type: PrincipalType.USER, user: orgUser } }, + { populate: ['project', 'principal.user.user' as any] } + ); + + if ( + (projectPrincipal as Loaded).project.$.status === + ProjectStatus.ARCHIVED + ) { + await checkNotLastAdmin(projectPrincipal); + } + projectPrincipal.delete(); + await ORM.em.flush(); + + return createDeleteResponse(projectPrincipal.id, 'project-user'); +} + +export async function createProjectUser( + input: ProjectUserCreateParams & ProjectUserCreateBody +): Promise { + const { project_id, user_id, role } = input; + const authorProjectPrincipal = getProjectPrincipal(); + const project = await ORM.em.getRepository(Project).findOneOrFail({ id: project_id }); + if (authorProjectPrincipal.project.id !== project.id) { + throw new APIError({ + message: 'Project user mismatch', + code: APIErrorCode.INVALID_INPUT + }); + } + const orgUser = await ORM.em.getRepository(OrganizationUser).findOneOrFail({ user: user_id }); + + const existingProjectPrincipal = await ORM.em + .getRepository(ProjectPrincipal) + .findOne( + { project: project_id, principal: { type: PrincipalType.USER, user: orgUser } }, + { filters: { deleted: false } } + ); + if (existingProjectPrincipal) { + if (existingProjectPrincipal.deletedAt) { + existingProjectPrincipal.resurrect(); + updateUser(existingProjectPrincipal, input); + await ORM.em.flush(); + + return toProjectUserDto(existingProjectPrincipal); + } else { + throw new APIError({ + message: 'User already exists', + code: APIErrorCode.INVALID_INPUT + }); + } + } + + const projectPrincipal = new ProjectPrincipal({ + principal: new UserPrincipal({ user: ref(orgUser) }), + role + }); + await ORM.em.persistAndFlush(projectPrincipal); + + await ORM.em + .getRepository(ProjectPrincipal) + .populate(projectPrincipal, ['principal.user.user' as any]); + + return toProjectUserDto(projectPrincipal); +} + +function updateUser(projectPrincipal: ProjectPrincipal, newData: ProjectUserUpdateBody) { + projectPrincipal.role = getUpdatedValue(newData.role, projectPrincipal.role); +} + +export async function updateProjectUser({ + project_id, + user_id, + role +}: ProjectUserUpdateParams & ProjectUserUpdateBody): Promise { + const orgUser = await ORM.em.getRepository(OrganizationUser).findOneOrFail({ user: user_id }); + const projectPrincipal = await ORM.em + .getRepository(ProjectPrincipal) + .findOneOrFail( + { project: project_id, principal: { type: PrincipalType.USER, user: orgUser } }, + { populate: ['principal.user.user' as any] } + ); + await checkNotLastAdmin(projectPrincipal); + updateUser(projectPrincipal, { role }); + await ORM.em.flush(); + + return toProjectUserDto(projectPrincipal); +} + +export async function listProjectUsers({ + project_id, + limit, + order, + order_by, + after, + before, + search +}: ProjectUsersListParams & ProjectUsersListQuery): Promise { + const where: FilterQuery> = { + project: project_id, + principal: { type: PrincipalType.USER } + }; + + if (search) { + const regexp = new RegExp(search, 'i'); + const users = await ORM.em + .getRepository(User) + .find({ $or: [{ email: regexp }, { name: regexp }] }); + const orgUsers = await ORM.em + .getRepository(OrganizationUser) + .find({ user: { $in: users.map((u) => u.id) } }); + where.principal = { user: { $in: orgUsers.map((u) => u.id) } }; + } + + const cursor = await getListCursor( + where, + { limit, order, order_by, after, before, populate: ['principal.user.user'] }, + ORM.em.getRepository(ProjectPrincipal) + ); + return createPaginatedResponse(cursor, toProjectUserDto); +} + +async function checkNotLastAdmin(projectPrincipal: ProjectPrincipal) { + const projectAdmins = await ORM.em.getRepository(ProjectPrincipal).count({ + project: projectPrincipal.project.id, + principal: { type: PrincipalType.USER }, + role: ProjectRole.ADMIN, + id: { $ne: projectPrincipal.id } + }); + + if (projectAdmins <= 0) { + throw new APIError({ + message: 'Can not delete last project admin.', + code: APIErrorCode.INVALID_INPUT + }); + } +} diff --git a/src/administration/projects.module.ts b/src/administration/projects.module.ts new file mode 100644 index 0000000..43f1a8c --- /dev/null +++ b/src/administration/projects.module.ts @@ -0,0 +1,123 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FastifyPluginAsyncJsonSchemaToTs } from '@fastify/type-provider-json-schema-to-ts'; +import { StatusCodes } from 'http-status-codes'; + +import { + ProjectCreateBody, + projectCreateBodySchema, + projectCreateResponseSchema +} from './dtos/project-create'; +import { + archiveProject, + createProject, + listProjects, + readProject, + updateProject +} from './projects.service'; +import { + ProjectsListQuery, + projectsListQuerySchema, + projectsListResponseSchema +} from './dtos/projects-list'; +import { + ProjectReadParams, + projectReadParamsSchema, + projectReadResponseSchema +} from './dtos/project-read'; +import { + ProjectUpdateBody, + projectUpdateBodySchema, + ProjectUpdateParams, + projectUpdateParamsSchema +} from './dtos/project-update'; +import { + ProjectArchiveParams, + projectArchiveParamsSchema, + projectArchiveResponseSchema +} from './dtos/project-archive'; + +import { Tag } from '@/swagger.js'; +import { AuthSecret } from '@/auth/utils'; + +export const projectsModule: FastifyPluginAsyncJsonSchemaToTs = async (app) => { + app.post<{ Body: ProjectCreateBody }>( + '/organization/projects', + { + schema: { + body: projectCreateBodySchema, + response: { [StatusCodes.OK]: projectCreateResponseSchema }, + tags: [Tag.BEE_API] + }, + preHandler: app.auth([AuthSecret.ACCESS_TOKEN]) + }, + async (req) => createProject(req.body) + ); + + app.get<{ Params: ProjectReadParams }>( + '/organization/projects/:project_id', + { + schema: { + params: projectReadParamsSchema, + response: { [StatusCodes.OK]: projectReadResponseSchema }, + tags: [Tag.BEE_API] + }, + preHandler: app.auth([AuthSecret.ACCESS_TOKEN]) + }, + async (req) => readProject(req.params) + ); + + app.post<{ Params: ProjectUpdateParams; Body: ProjectUpdateBody }>( + '/organization/projects/:project_id', + { + schema: { + params: projectUpdateParamsSchema, + body: projectUpdateBodySchema, + response: { [StatusCodes.OK]: projectUpdateBodySchema }, + tags: [Tag.BEE_API] + }, + preHandler: app.auth([AuthSecret.ACCESS_TOKEN]) + }, + async (req) => updateProject({ ...req.params, ...req.body }) + ); + + app.get<{ Querystring: ProjectsListQuery }>( + '/organization/projects', + { + schema: { + querystring: projectsListQuerySchema, + response: { [StatusCodes.OK]: projectsListResponseSchema }, + tags: [Tag.BEE_API] + }, + preHandler: app.auth([AuthSecret.ACCESS_TOKEN]) + }, + async (req) => listProjects(req.query) + ); + + app.post<{ Params: ProjectArchiveParams }>( + '/organization/projects/:project_id/archive', + { + schema: { + params: projectArchiveParamsSchema, + response: { [StatusCodes.OK]: projectArchiveResponseSchema }, + tags: [Tag.BEE_API] + }, + preHandler: app.auth([AuthSecret.ACCESS_TOKEN]) + }, + async (req) => archiveProject(req.params) + ); +}; diff --git a/src/administration/projects.service.ts b/src/administration/projects.service.ts new file mode 100644 index 0000000..715a426 --- /dev/null +++ b/src/administration/projects.service.ts @@ -0,0 +1,160 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FilterQuery, Loaded, ref } from '@mikro-orm/core'; +import { requestContext } from '@fastify/request-context'; +import dayjs from 'dayjs'; + +import { ProjectCreateBody, ProjectCreateResponse } from './dtos/project-create'; +import { Project, ProjectStatus, ProjectVisiblity } from './entities/project.entity'; +import { Project as ProjectDto } from './dtos/project'; +import { ProjectsListQuery, ProjectsListResponse } from './dtos/projects-list'; +import { ProjectPrincipal } from './entities/project-principal.entity'; +import { UserPrincipal } from './entities/principals/user-principal.entity'; +import { OrganizationUserRole, ProjectRole } from './entities/constants'; +import { getOrganizationUser } from './helpers'; +import { ProjectReadParams, ProjectReadResponse } from './dtos/project-read'; +import { + ProjectUpdateBody, + ProjectUpdateParams, + ProjectUpdateResponse +} from './dtos/project-update'; +import { ProjectArchiveParams, ProjectArchiveResponse } from './dtos/project-archive'; +import { PrincipalType } from './entities/principals/principal.entity'; + +import { ORM } from '@/database'; +import { createPaginatedResponse, getListCursor } from '@/utils/pagination'; +import { APIError, APIErrorCode } from '@/errors/error.entity'; +import { getUpdatedValue } from '@/utils/update'; + +export function toDto(project: Loaded): ProjectDto { + return { + object: 'organization.project', + id: project.id, + name: project.name, + visibility: project.visibility, + status: project.status, + created_at: dayjs(project.createdAt).unix(), + archived_at: project.archivedAt ? dayjs(project.archivedAt).unix() : null + }; +} + +export async function createProject({ + name, + visibility +}: ProjectCreateBody): Promise { + const orgUser = getOrganizationUser(); + + if (orgUser.role === OrganizationUserRole.MEMBER && visibility === ProjectVisiblity.PUBLIC) { + throw new APIError({ + message: 'Members can only create private projects', + code: APIErrorCode.INVALID_INPUT + }); + } + + const project = new Project({ name, visibility }); + const projectPrincipal = new ProjectPrincipal({ + project: ref(project), + createdBy: ORM.em + .getRepository(ProjectPrincipal) + .getReference('placeholder', { wrapped: true }), + principal: new UserPrincipal({ user: ref(orgUser) }), + role: ProjectRole.ADMIN + }); + projectPrincipal.createdBy = ORM.em + .getRepository(ProjectPrincipal) + .getReference(projectPrincipal.id, { wrapped: true }); // Bypass chicken-egg problem + requestContext.set('projectPrincipal', projectPrincipal); + + await ORM.em.persistAndFlush([project, projectPrincipal]); + + return toDto(project); +} + +export async function readProject({ project_id }: ProjectReadParams): Promise { + const project = await ORM.em.getRepository(Project).findOneOrFail({ id: project_id }); + return toDto(project); +} + +export async function updateProject({ + project_id, + name, + visibility +}: ProjectUpdateParams & ProjectUpdateBody): Promise { + const project = await ORM.em.getRepository(Project).findOneOrFail({ id: project_id }); + + if (project.status === ProjectStatus.ARCHIVED) + throw new APIError({ + message: "Archived project can't be modified", + code: APIErrorCode.FORBIDDEN + }); + + project.name = getUpdatedValue(name, project.name); + project.visibility = getUpdatedValue(visibility, project.visibility); + await ORM.em.flush(); + + return toDto(project); +} + +export async function listProjects({ + limit, + order, + order_by, + after, + before, + include_archived +}: ProjectsListQuery): Promise { + const orgUser = getOrganizationUser(); + const principals = await ORM.em + .getRepository(ProjectPrincipal) + .find( + { principal: { type: PrincipalType.USER, user: orgUser } }, + { filters: { projectAdministrationAccess: false } } + ); // TODO missing pagination + + const filter: FilterQuery = { + $and: [ + { + $or: [ + { id: { $in: principals.map(({ project }) => project.id) } }, + { visibility: ProjectVisiblity.PUBLIC } + ] + } + ] + }; + + if (!include_archived) { + filter.$and!.push({ status: ProjectStatus.ACTIVE }); + } + + const cursor = await getListCursor( + filter, + { limit, order, order_by, after, before }, + ORM.em.getRepository(Project) + ); + return createPaginatedResponse(cursor, toDto); +} + +export async function archiveProject({ + project_id +}: ProjectArchiveParams): Promise { + const project = await ORM.em.getRepository(Project).findOneOrFail({ id: project_id }); + + project.archive(); + await ORM.em.flush(); + + return toDto(project); +} diff --git a/src/ajv.ts b/src/ajv.ts new file mode 100644 index 0000000..38d66fd --- /dev/null +++ b/src/ajv.ts @@ -0,0 +1,35 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ajvFilePlugin as multipartAjvPlugin } from '@fastify/multipart'; +import { ExtendedJSONSchema, FromExtendedSchema } from 'json-schema-to-ts'; + +export const ajv = { + plugins: [multipartAjvPlugin], + customOptions: { + removeAdditional: false, + coerceTypes: 'array' as const, + useDefaults: true, + strict: false + } +}; + +type ExtensionProps = { + isFile: boolean; +}; + +export type JSONSchema = ExtendedJSONSchema; +export type FromSchema = FromExtendedSchema; diff --git a/src/assistants/assistant.entity.ts b/src/assistants/assistant.entity.ts new file mode 100644 index 0000000..a4cf855 --- /dev/null +++ b/src/assistants/assistant.entity.ts @@ -0,0 +1,97 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embedded, Entity, Property } from '@mikro-orm/core'; + +import { ProjectScopedEntity, ProjectScopedEntityInput } from '@/common/project-scoped.entity'; +import { AnyToolUsage } from '@/tools/entities/tool-usages/tool-usage.entity.js'; +import { CodeInterpreterUsage } from '@/tools/entities/tool-usages/code-interpreter-usage.entity.js'; +import { FileSearchUsage } from '@/tools/entities/tool-usages/file-search-usage.entity.js'; +import { FunctionUsage } from '@/tools/entities/tool-usages/function-usage.entity.js'; +import { UserUsage } from '@/tools/entities/tool-usages/user-usage.entity.js'; +import { SystemUsage } from '@/tools/entities/tool-usages/system-usage.entity.js'; +import { CodeInterpreterResource } from '@/tools/entities/tool-resources/code-interpreter-resource.entity.js'; +import { AnyToolResource } from '@/tools/entities/tool-resources/tool-resource.entity.js'; +import { FileSearchResource } from '@/tools/entities/tool-resources/file-search-resources.entity.js'; +import { UserResource } from '@/tools/entities/tool-resources/user-resource.entity'; +import { SystemResource } from '@/tools/entities/tool-resources/system-resource.entity'; + +@Entity() +export class Assistant extends ProjectScopedEntity { + getIdPrefix(): string { + return 'asst'; + } + + // Union must be defined in alphabetical order, otherwise Mikro-ORM won't discovered the auto-created virtual polymorphic entity + @Embedded({ object: true }) + tools!: (CodeInterpreterUsage | FileSearchUsage | FunctionUsage | SystemUsage | UserUsage)[]; + + // Union must be defined in alphabetical order, otherwise Mikro-ORM won't discovered the auto-created virtual polymorphic entity + @Embedded({ object: true }) + toolResources?: (CodeInterpreterResource | FileSearchResource | SystemResource | UserResource)[]; + + @Property() + name?: string; + + @Property() + description?: string; + + @Property() + instructions?: string; + + @Property() + systemPromptOverwrite?: string; + + @Property() + model!: string; + + @Property() + topP?: number; + + @Property() + temperature?: number; + + constructor({ + name, + description, + instructions, + tools, + toolResources, + model, + topP, + temperature, + systemPromptOverwrite, + ...rest + }: AssistantInput) { + super(rest); + + this.name = name; + this.description = description; + this.instructions = instructions; + this.tools = tools; + this.toolResources = toolResources; + this.model = model; + this.topP = topP; + this.temperature = temperature; + this.systemPromptOverwrite = systemPromptOverwrite; + } +} + +export type AssistantInput = ProjectScopedEntityInput & { + tools: AnyToolUsage[]; + toolResources?: AnyToolResource[]; +} & Pick & + Partial>; diff --git a/src/assistants/assistants.module.ts b/src/assistants/assistants.module.ts new file mode 100644 index 0000000..40bd27c --- /dev/null +++ b/src/assistants/assistants.module.ts @@ -0,0 +1,129 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FastifyPluginAsyncJsonSchemaToTs } from '@fastify/type-provider-json-schema-to-ts'; +import { StatusCodes } from 'http-status-codes'; + +import { + AssistantCreateBody, + assistantCreateBodySchema, + assistantCreateResponseSchema +} from './dtos/assistant-create.js'; +import { + AssistantsListQuery, + assistantsListQuerySchema, + assistantsListResponseSchema +} from './dtos/assistants-list.js'; +import { + createAssistant, + deleteAssistant, + listAssistants, + readAssistant, + updateAssistant +} from './assistants.service.js'; +import { + AssistantReadParams, + assistantReadParamsSchema, + assistantReadResponseSchema +} from './dtos/assistant-read.js'; +import { + AssistantUpdateBody, + AssistantUpdateParams, + assistantUpdateBodySchema, + assistantUpdateParamsSchema, + assistantUpdateResponseSchema +} from './dtos/assistant-update.js'; +import { AssistantDeleteParams, assistantDeleteParamsSchema } from './dtos/assistant-delete.js'; + +import { Tag } from '@/swagger.js'; +import { createDeleteSchema } from '@/schema.js'; + +export const assistantsModule: FastifyPluginAsyncJsonSchemaToTs = async (app) => { + app.post<{ Body: AssistantCreateBody }>( + '/assistants', + { + schema: { + body: assistantCreateBodySchema, + response: { [StatusCodes.OK]: assistantCreateResponseSchema }, + tags: [Tag.OPENAI_ASSISTANTS_API] + }, + preHandler: app.auth() + }, + async (req) => createAssistant(req.body) + ); + + app.get<{ Params: AssistantReadParams }>( + '/assistants/:assistant_id', + { + schema: { + params: assistantReadParamsSchema, + response: { [StatusCodes.OK]: assistantReadResponseSchema }, + tags: [Tag.OPENAI_ASSISTANTS_API] + }, + preHandler: app.auth() + }, + async (req) => { + const { assistant_id } = req.params; + return readAssistant({ assistant_id }); + } + ); + + app.post<{ Params: AssistantUpdateParams; Body: AssistantUpdateBody }>( + '/assistants/:assistant_id', + { + schema: { + params: assistantUpdateParamsSchema, + body: assistantUpdateBodySchema, + response: { [StatusCodes.OK]: assistantUpdateResponseSchema }, + tags: [Tag.OPENAI_ASSISTANTS_API] + }, + preHandler: app.auth() + }, + async (req) => { + return updateAssistant({ ...req.params, ...req.body }); + } + ); + + app.get<{ Querystring: AssistantsListQuery }>( + '/assistants', + { + schema: { + querystring: assistantsListQuerySchema, + response: { [StatusCodes.OK]: assistantsListResponseSchema }, + tags: [Tag.OPENAI_ASSISTANTS_API] + }, + preHandler: app.auth() + }, + async (req) => { + return listAssistants(req.query); + } + ); + + app.delete<{ Params: AssistantDeleteParams }>( + '/assistants/:assistant_id', + { + preHandler: app.auth(), + schema: { + params: assistantDeleteParamsSchema, + response: { + [StatusCodes.OK]: createDeleteSchema('assistant') + }, + tags: [Tag.OPENAI_ASSISTANTS_API] + } + }, + async (req) => deleteAssistant(req.params) + ); +}; diff --git a/src/assistants/assistants.service.ts b/src/assistants/assistants.service.ts new file mode 100644 index 0000000..4da7780 --- /dev/null +++ b/src/assistants/assistants.service.ts @@ -0,0 +1,187 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FilterQuery, Loaded } from '@mikro-orm/core'; +import dayjs from 'dayjs'; + +import { + AssistantUpdateBody, + AssistantUpdateParams, + AssistantUpdateResponse +} from './dtos/assistant-update.js'; +import { AssistantsListQuery, AssistantsListResponse } from './dtos/assistants-list.js'; +import { Assistant } from './assistant.entity.js'; +import { AssistantReadParams, AssistantReadResponse } from './dtos/assistant-read.js'; +import type { Assistant as AssistantDto } from './dtos/assistant.js'; +import { AssistantCreateBody, AssistantCreateResponse } from './dtos/assistant-create.js'; +import { AssistantDeleteParams, AssistantDeleteResponse } from './dtos/assistant-delete.js'; + +import { ORM } from '@/database.js'; +import { createPaginatedResponse, getListCursor } from '@/utils/pagination.js'; +import { + createToolResources, + createToolUsage, + toToolResourcesDto, + toToolUsageDto +} from '@/tools/tools.service.js'; +import { APIError, APIErrorCode } from '@/errors/error.entity.js'; +import { Tool, ToolType } from '@/tools/entities/tool/tool.entity.js'; +import { getUpdatedValue } from '@/utils/update.js'; +import { createDeleteResponse } from '@/utils/delete.js'; +import { getDefaultModel } from '@/runs/execution/factory'; + +export function toDto(assistant: Loaded): AssistantDto { + return { + id: assistant.id, + object: 'assistant', + tools: assistant.tools.map(toToolUsageDto) ?? [], + tool_resources: toToolResourcesDto(assistant.toolResources), + instructions: assistant.instructions ?? null, + name: assistant.name ?? null, + description: assistant.description ?? null, + metadata: assistant.metadata ?? {}, + created_at: dayjs(assistant.createdAt).unix(), + model: assistant.model, + top_p: assistant.topP, + temperature: assistant.temperature, + system_prompt: assistant.systemPromptOverwrite + }; +} + +export async function createAssistant({ + tools: toolsParam, + tool_resources, + instructions, + name, + description, + metadata, + top_p, + model, + temperature, + system_prompt_overwrite +}: AssistantCreateBody): Promise { + const customToolIds = toolsParam.flatMap((toolUsage) => + toolUsage.type === ToolType.USER ? toolUsage.user.tool.id : [] + ); + const tools = + customToolIds.length > 0 + ? await ORM.em.getRepository(Tool).find({ + id: { $in: customToolIds } + }) + : []; + + if (tools.length !== customToolIds.length) { + throw new APIError({ + message: 'Some tool not found', + code: APIErrorCode.INVALID_INPUT + }); + } + + const assistant = new Assistant({ + tools: toolsParam.map(createToolUsage), + toolResources: await createToolResources(tool_resources), + instructions: instructions ?? undefined, + name: name ?? undefined, + description: description ?? undefined, + metadata, + topP: top_p ?? undefined, + model: model ?? getDefaultModel(), + temperature: temperature ?? undefined, + systemPromptOverwrite: system_prompt_overwrite ?? undefined + }); + await ORM.em.persistAndFlush(assistant); + return toDto(assistant); +} + +export async function readAssistant({ + assistant_id +}: AssistantReadParams): Promise { + const assistant = await ORM.em.getRepository(Assistant).findOneOrFail({ + id: assistant_id + }); + return toDto(assistant); +} + +export async function updateAssistant({ + assistant_id, + name, + description, + metadata, + instructions, + tools, + tool_resources, + temperature, + top_p, + model, + system_prompt_overwrite +}: AssistantUpdateParams & AssistantUpdateBody): Promise { + const assistant = await ORM.em.getRepository(Assistant).findOneOrFail({ + id: assistant_id + }); + assistant.name = getUpdatedValue(name, assistant.name); + assistant.description = getUpdatedValue(description, assistant.description); + assistant.instructions = getUpdatedValue(instructions, assistant.instructions); + assistant.systemPromptOverwrite = getUpdatedValue( + system_prompt_overwrite, + assistant.systemPromptOverwrite + ); + assistant.tools = getUpdatedValue(tools?.map(createToolUsage), assistant.tools); + assistant.toolResources = getUpdatedValue( + await createToolResources(tool_resources), + assistant.toolResources + ); + assistant.metadata = getUpdatedValue(metadata, assistant.metadata); + assistant.topP = getUpdatedValue(top_p, assistant.topP); + assistant.model = getUpdatedValue(model, assistant.model); + assistant.temperature = getUpdatedValue(temperature, assistant.temperature); + await ORM.em.flush(); + return toDto(assistant); +} + +export async function listAssistants({ + limit, + after, + before, + order, + order_by, + search +}: AssistantsListQuery): Promise { + const where: FilterQuery = {}; + + if (search) { + const regexp = new RegExp(search, 'i'); + where.$or = [{ description: regexp }, { name: regexp }]; + } + + const repo = ORM.em.getRepository(Assistant); + const cursor = await getListCursor( + where, + { limit, order, order_by, after, before }, + repo + ); + return createPaginatedResponse(cursor, toDto); +} + +export async function deleteAssistant({ + assistant_id +}: AssistantDeleteParams): Promise { + const assistant = await ORM.em.getRepository(Assistant).findOneOrFail({ id: assistant_id }); + + assistant.delete(); + await ORM.em.flush(); + + return createDeleteResponse(assistant_id, 'assistant'); +} diff --git a/src/assistants/dtos/assistant-create.ts b/src/assistants/dtos/assistant-create.ts new file mode 100644 index 0000000..7c14e2a --- /dev/null +++ b/src/assistants/dtos/assistant-create.ts @@ -0,0 +1,77 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { assistantSchema } from './assistant.js'; + +import { toolUsageSchema } from '@/tools/dtos/tools-usage.js'; +import { metadataSchema } from '@/schema.js'; +import { toolResourcesSchema } from '@/tools/dtos/tool-resources.js'; + +export const assistantCreateBodySchema = { + type: 'object', + additionalProperties: false, + properties: { + tools: { + type: 'array', + uniqueItems: true, + default: [], + items: toolUsageSchema + }, + tool_resources: toolResourcesSchema, + name: { + type: 'string', + nullable: true, + maxLength: 256 + }, + description: { + type: 'string', + nullable: true, + maxLength: 512 + }, + instructions: { + type: 'string', + nullable: true + }, + system_prompt_overwrite: { + type: 'string', + nullable: true + }, + metadata: metadataSchema, + model: { + type: 'string' + }, + top_p: { + type: 'number', + nullable: true, + maximum: 1, + minimum: 0, + multipleOf: 0.01 + }, + temperature: { + type: 'number', + nullable: true, + maximum: 2, + minimum: 0, + multipleOf: 0.01 + } + } +} as const satisfies JSONSchema; +export type AssistantCreateBody = FromSchema; + +export const assistantCreateResponseSchema = assistantSchema; +export type AssistantCreateResponse = FromSchema; diff --git a/src/assistants/dtos/assistant-delete.ts b/src/assistants/dtos/assistant-delete.ts new file mode 100644 index 0000000..6b519cb --- /dev/null +++ b/src/assistants/dtos/assistant-delete.ts @@ -0,0 +1,27 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema } from 'json-schema-to-ts'; + +import { assistantReadParamsSchema } from './assistant-read.js'; + +import { createDeleteSchema } from '@/schema.js'; + +export const assistantDeleteParamsSchema = assistantReadParamsSchema; +export type AssistantDeleteParams = FromSchema; + +export const assistantDeleteResponseSchema = createDeleteSchema('assistant'); +export type AssistantDeleteResponse = FromSchema; diff --git a/src/assistants/dtos/assistant-read.ts b/src/assistants/dtos/assistant-read.ts new file mode 100644 index 0000000..cec7aa3 --- /dev/null +++ b/src/assistants/dtos/assistant-read.ts @@ -0,0 +1,32 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { assistantSchema } from './assistant.js'; + +export const assistantReadParamsSchema = { + type: 'object', + required: ['assistant_id'], + additionalProperties: false, + properties: { + assistant_id: { type: 'string' } + } +} as const satisfies JSONSchema; +export type AssistantReadParams = FromSchema; + +export const assistantReadResponseSchema = assistantSchema; +export type AssistantReadResponse = FromSchema; diff --git a/src/assistants/dtos/assistant-update.ts b/src/assistants/dtos/assistant-update.ts new file mode 100644 index 0000000..ae532ba --- /dev/null +++ b/src/assistants/dtos/assistant-update.ts @@ -0,0 +1,86 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { assistantSchema } from './assistant.js'; + +import { toolUsageSchema } from '@/tools/dtos/tools-usage.js'; +import { toolResourcesSchema } from '@/tools/dtos/tool-resources.js'; +import { metadataSchema } from '@/schema.js'; + +export const assistantUpdateParamsSchema = { + type: 'object', + required: ['assistant_id'], + additionalProperties: false, + properties: { + assistant_id: { type: 'string' } + } +} as const satisfies JSONSchema; +export type AssistantUpdateParams = FromSchema; + +export const assistantUpdateBodySchema = { + type: 'object', + additionalProperties: false, + properties: { + model: { + type: 'string' + }, + name: { + type: 'string', + nullable: true, + maxLength: 256 + }, + description: { + type: 'string', + nullable: true, + maxLength: 512 + }, + instructions: { + type: 'string', + nullable: true + }, + system_prompt_overwrite: { + type: 'string', + nullable: true + }, + tools: { + type: 'array', + uniqueItems: true, + items: toolUsageSchema + }, + tool_resources: toolResourcesSchema, + metadata: metadataSchema, + temperature: { + type: 'number', + nullable: true, + maximum: 2, + minimum: 0, + multipleOf: 0.01 + }, + top_p: { + type: 'number', + nullable: true, + maximum: 1, + minimum: 0, + multipleOf: 0.01 + } + } +} as const satisfies JSONSchema; +export type AssistantUpdateBody = FromSchema; + +export const assistantUpdateResponseSchema = assistantSchema; +export type AssistantUpdateResponse = FromSchema; diff --git a/src/assistants/dtos/assistant.ts b/src/assistants/dtos/assistant.ts new file mode 100644 index 0000000..a1dc0e4 --- /dev/null +++ b/src/assistants/dtos/assistant.ts @@ -0,0 +1,75 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { toolUsageSchema } from '@/tools/dtos/tools-usage.js'; +import { metadataSchema } from '@/schema.js'; +import { toolResourcesSchema } from '@/tools/dtos/tool-resources.js'; + +export const assistantSchema = { + type: 'object', + required: [ + 'id', + 'object', + 'tools', + 'instructions', + 'name', + 'description', + 'metadata', + 'created_at', + 'model' + ], + properties: { + id: { type: 'string' }, + object: { const: 'assistant' }, + tools: { + type: 'array', + items: toolUsageSchema + }, + tool_resources: toolResourcesSchema, + instructions: { + type: 'string', + nullable: true + }, + system_prompt_overwrite: { + type: 'string', + nullable: true + }, + name: { + type: 'string', + nullable: true + }, + description: { + type: 'string', + nullable: true + }, + metadata: metadataSchema, + created_at: { type: 'number' }, + model: { + type: 'string' + }, + top_p: { + type: 'number', + nullable: true + }, + temperature: { + type: 'number', + nullable: true + } + } +} as const satisfies JSONSchema; +export type Assistant = FromSchema; diff --git a/src/assistants/dtos/assistants-list.ts b/src/assistants/dtos/assistants-list.ts new file mode 100644 index 0000000..bb6dab8 --- /dev/null +++ b/src/assistants/dtos/assistants-list.ts @@ -0,0 +1,41 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { assistantSchema } from './assistant.js'; + +import { createPaginationQuerySchema, withPagination } from '@/schema.js'; + +export const assistantsListQuerySchema = { + type: 'object', + additionalProperties: false, + properties: { + ...createPaginationQuerySchema(['name'] as const).properties, + public: { + type: 'boolean', + default: false + }, + search: { + type: 'string', + nullable: true + } + } +} as const satisfies JSONSchema; +export type AssistantsListQuery = FromSchema; + +export const assistantsListResponseSchema = withPagination(assistantSchema); +export type AssistantsListResponse = FromSchema; diff --git a/src/auth/accessToken.ts b/src/auth/accessToken.ts new file mode 100644 index 0000000..a5116a6 --- /dev/null +++ b/src/auth/accessToken.ts @@ -0,0 +1,126 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Issuer } from 'openid-client'; +import { createRemoteJWKSet, jwtVerify, decodeJwt } from 'jose'; +import { JOSEError } from 'jose/errors'; +import { isArray } from 'remeda'; + +import '@/ui/auth-server.js'; +import { AUTH_CLIENT_ID, AUTH_CLIENT_SECRET, AUTH_AUDIENCE, AUTH_WELL_KNOWN } from '@/config.js'; +import { APIError, APIErrorCode } from '@/errors/error.entity.js'; + +const issuer = await Issuer.discover(AUTH_WELL_KNOWN); + +const client = new issuer.Client({ + client_id: AUTH_CLIENT_ID, + client_secret: AUTH_CLIENT_SECRET +}); + +const JWKS_URI = issuer.metadata.jwks_uri; +const JWKS = JWKS_URI && createRemoteJWKSet(new URL(JWKS_URI)); + +function isJwt(accessToken: string) { + try { + decodeJwt(accessToken); + return true; + } catch (err) { + return false; + } +} + +function hasJwks() { + return !!JWKS; +} + +async function validateJwt(jwtToken: string) { + if (!JWKS) throw new Error('JWKS is not supported by the issuer'); + try { + const { payload } = await jwtVerify(jwtToken, JWKS); + return payload; + } catch (e) { + if (e instanceof JOSEError) { + throw new APIError({ + message: e.message, + code: APIErrorCode.AUTH_ERROR + }); + } else { + throw new APIError({ + message: 'Invalid JWT token', + code: APIErrorCode.AUTH_ERROR + }); + } + } +} + +async function validateByIntrospection(accessToken: string) { + const payload = await client.introspect(accessToken); + if (!payload.active) + throw new APIError({ + message: 'Invalid access token', + code: APIErrorCode.AUTH_ERROR + }); + return payload; +} + +async function validatePayload({ + sub, + iss, + aud, + email, + preferred_username +}: { + sub?: string; + iss?: string; + aud?: string | string[]; + email?: string; + preferred_username?: string; +}) { + if (!sub) + throw new APIError({ + message: 'Missing sub claim', + code: APIErrorCode.AUTH_ERROR + }); + if (iss !== issuer.metadata.issuer) + throw new APIError({ + message: 'Invalid issuer claim', + code: APIErrorCode.AUTH_ERROR + }); + if (isArray(aud) ? !aud.includes(AUTH_AUDIENCE) : aud !== AUTH_AUDIENCE) + throw new APIError({ + message: 'Invalid audience claim', + code: APIErrorCode.AUTH_ERROR + }); + if (email && typeof email !== 'string') + throw new APIError({ + message: 'Invalid email claim', + code: APIErrorCode.AUTH_ERROR + }); + if (preferred_username && typeof preferred_username !== 'string') + throw new APIError({ + message: 'Invalid preferred_username claim', + code: APIErrorCode.AUTH_ERROR + }); + return { sub, iss, aud, email, preferred_username }; +} + +export async function validateAccessToken(accessToken: string) { + const payload = + hasJwks() && isJwt(accessToken) + ? await validateJwt(accessToken) + : await validateByIntrospection(accessToken); + return validatePayload(payload); +} diff --git a/src/auth/authentication.ts b/src/auth/authentication.ts new file mode 100644 index 0000000..ec96719 --- /dev/null +++ b/src/auth/authentication.ts @@ -0,0 +1,166 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FastifyInstance, FastifyPluginAsync, FastifyRequest } from 'fastify'; +import fp from 'fastify-plugin'; + +import { ORM } from '../database.js'; +import { User } from '../users/entities/user.entity.js'; + +import { AuthSecret, determineAuthType, scryptApiKey } from './utils.js'; +import { validateAccessToken } from './accessToken.js'; + +import { APIError, APIErrorCode } from '@/errors/error.entity.js'; +import { ProjectApiKey } from '@/administration/entities/project-api-key.entity.js'; +import { ProjectPrincipal } from '@/administration/entities/project-principal.entity.js'; +import { OrganizationUser } from '@/administration/entities/organization-user.entity.js'; +import { PrincipalType } from '@/administration/entities/principals/principal.entity.js'; + +export async function getTrustedIdentity(request: FastifyRequest) { + const authType = determineAuthType(request); + switch (authType.type) { + case AuthSecret.ACCESS_TOKEN: + return await validateAccessToken(authType.value); + default: + throw new APIError({ + message: 'Invalid identity', + code: APIErrorCode.AUTH_ERROR + }); + } +} + +const ORGANIZATION_HEADER = 'x-organization'; +const PROJECT_HEADER = 'x-project'; + +// This needs to be async, otherwise "done" callback would need to be used +// See: https://github.com/fastify/fastify-auth +const authJwt = async (request: FastifyRequest, jwtToken: string) => { + const { sub, email, preferred_username } = await validateAccessToken(jwtToken); + + const user = await ORM.em.getRepository(User).findOne({ externalId: sub }); + if (!user) + throw new APIError({ + message: `User not found`, + code: APIErrorCode.AUTH_ERROR + }); + + // Add email and name for existing emails + // TODO remove once all accounts have been populated + if (!user.email || !user.name) { + user.email = email; + user.name = preferred_username; + await ORM.em.flush(); + } + + request.requestContext.set('user', user); + + const organization = request.headers[ORGANIZATION_HEADER]; + if (organization) { + if (typeof organization !== 'string') + throw new APIError({ message: 'Invalid organization', code: APIErrorCode.INVALID_INPUT }); + + const orgUser = await ORM.em + .getRepository(OrganizationUser) + .findOne({ user: user.id, organization }, { filters: { orgAdministrationAccess: false } }); + if (!orgUser) + throw new APIError({ + message: `Organization not found`, + code: APIErrorCode.AUTH_ERROR + }); + request.requestContext.set('organizationUser', orgUser); + } + + const project = request.headers[PROJECT_HEADER]; + if (project) { + if (typeof project !== 'string') + throw new APIError({ message: 'Invalid project', code: APIErrorCode.INVALID_INPUT }); + + const orgUser = request.requestContext.get('organizationUser'); + if (!orgUser) + throw new APIError({ message: 'Missing organization', code: APIErrorCode.INVALID_INPUT }); + + const projectPrincipal = await ORM.em + .getRepository(ProjectPrincipal) + .findOne( + { project, principal: { type: PrincipalType.USER, user: orgUser } }, + { populate: ['project'], filters: { projectAdministrationAccess: false } } + ); + if (!projectPrincipal) + throw new APIError({ + message: `Project user not found`, + code: APIErrorCode.AUTH_ERROR + }); + request.requestContext.set('projectPrincipal', projectPrincipal); + } +}; + +const authApiKey = async (request: FastifyRequest, apiKey: string) => { + const key = await ORM.em + .getRepository(ProjectApiKey) + .findOne( + { key: scryptApiKey(apiKey) }, + { populate: ['createdBy'], filters: { projectAdministrationAccess: false } } + ); + if (!key) { + throw new APIError({ + message: `Key not found`, + code: APIErrorCode.AUTH_ERROR + }); + } + request.requestContext.set('apiKey', key); + request.requestContext.set('projectPrincipal', key.createdBy.$); +}; + +export type AuthFn = (allowedTypes?: AuthSecret[]) => (request: FastifyRequest) => Promise; + +const auth: AuthFn = + (allowedTypes = [AuthSecret.ACCESS_TOKEN, AuthSecret.API_KEY]) => + async (request) => { + const authType = determineAuthType(request); + + if (!allowedTypes.includes(authType.type)) { + throw new APIError({ + message: 'Invalid authorization', + code: APIErrorCode.AUTH_ERROR + }); + } + + switch (authType.type) { + case AuthSecret.ACCESS_TOKEN: + await authJwt(request, authType.value); + break; + case AuthSecret.API_KEY: + await authApiKey(request, authType.value); + break; + case AuthSecret.UNKNOWN: + break; + } + + request.log.info( + { + authType: authType.type, + apiKey: request.requestContext.get('apiKey')?.id, + user: request.requestContext.get('user')?.id, + organizationUser: request.requestContext.get('organizationUser')?.id, + projectPrincipal: request.requestContext.get('projectPrincipal')?.id + }, + 'Authenticated' + ); + }; + +export const authPlugin: FastifyPluginAsync = fp.default(async (app: FastifyInstance) => { + app.decorate('auth', auth); +}); diff --git a/src/auth/utils.ts b/src/auth/utils.ts new file mode 100644 index 0000000..97cdfd4 --- /dev/null +++ b/src/auth/utils.ts @@ -0,0 +1,79 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import crypto from 'node:crypto'; + +import { FastifyRequest } from 'fastify'; + +export const AuthSecret = { + ACCESS_TOKEN: 'access_token', + API_KEY: 'key', + UNKNOWN: 'unknown' +} as const; +export type AuthSecret = (typeof AuthSecret)[keyof typeof AuthSecret]; + +interface AuthTypeAccessToken { + type: typeof AuthSecret.ACCESS_TOKEN; + value: string; +} + +interface AuthTypeApiKey { + type: typeof AuthSecret.API_KEY; + value: string; +} + +interface AuthTypeUnknown { + type: typeof AuthSecret.UNKNOWN; +} + +type AuthType = AuthTypeAccessToken | AuthTypeApiKey | AuthTypeUnknown; + +const BEARER_PREFIX = 'Bearer '; +const API_KEY_PREFIX = 'sk-'; + +const API_KEY_SIZE = 32; + +export const determineAuthType = (req: FastifyRequest): AuthType => { + if (req.headers.authorization) { + const firstPart = req.headers.authorization.substring(0, BEARER_PREFIX.length); + const secondPart = req.headers.authorization.substring(BEARER_PREFIX.length).trim(); + if (firstPart === BEARER_PREFIX && secondPart.length > 0) { + if (secondPart.startsWith(API_KEY_PREFIX) && secondPart.length > API_KEY_PREFIX.length) { + return { + value: secondPart, + type: AuthSecret.API_KEY + }; + } else { + return { + value: secondPart, + type: AuthSecret.ACCESS_TOKEN + }; + } + } + } + return { + type: AuthSecret.UNKNOWN + }; +}; + +export function scryptApiKey(apiKey: string) { + // We expect the key to be random and high entropy, therefore constant salt is not an issue + return crypto.scryptSync(apiKey, 'salt', 64).toString('hex'); +} + +export function generateApiKey() { + return `${API_KEY_PREFIX}${crypto.randomBytes(API_KEY_SIZE).toString('base64url')}`; +} diff --git a/src/common/base.entity.ts b/src/common/base.entity.ts new file mode 100644 index 0000000..c881440 --- /dev/null +++ b/src/common/base.entity.ts @@ -0,0 +1,57 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Filter, PrimaryKey, Property } from '@mikro-orm/core'; + +import { generatePrefixedObjectId } from '@/utils/id.js'; + +@Filter({ + name: 'deleted', + cond: { deletedAt: undefined }, + default: true +}) +export abstract class BaseEntity { + abstract getIdPrefix(): string; + + @PrimaryKey({ fieldName: '_id' }) + id = generatePrefixedObjectId(this.getIdPrefix()); + + @Property() + createdAt: Date = new Date(); + + @Property({ onUpdate: () => new Date() }) + updatedAt: Date = new Date(); + + @Property() + deletedAt?: Date; + + delete() { + this.deletedAt = new Date(); + } + + resurrect() { + this.deletedAt = undefined; + } + + @Property() + metadata?: Record; + + constructor({ metadata }: BaseEntityInput) { + this.metadata = metadata; + } +} + +export type BaseEntityInput = Pick; diff --git a/src/common/principal-scoped.entity.ts b/src/common/principal-scoped.entity.ts new file mode 100644 index 0000000..3c07a64 --- /dev/null +++ b/src/common/principal-scoped.entity.ts @@ -0,0 +1,105 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + BeforeCreate, + BeforeDelete, + BeforeUpdate, + Entity, + EventArgs, + Filter, + Index, + ManyToOne, + ref, + Ref +} from '@mikro-orm/core'; +import { requestContext } from '@fastify/request-context'; + +import { BaseEntity, BaseEntityInput } from './base.entity'; + +import { getProjectPrincipal } from '@/administration/helpers'; +import { ProjectPrincipal } from '@/administration/entities/project-principal.entity'; +import { Project, ProjectStatus } from '@/administration/entities/project.entity'; +import { APIError, APIErrorCode } from '@/errors/error.entity'; +import { inJob, inSeeder } from '@/context'; + +@Entity({ abstract: true }) +@Filter({ + name: 'principalAccess', + cond: async (_ = {}, type) => { + if (inJob() || inSeeder()) return; + + const projectPrincipal = requestContext.get('projectPrincipal'); + if (!projectPrincipal) return { _id: null }; + + switch (type) { + case 'read': + return { + createdBy: projectPrincipal, + project: projectPrincipal.project + }; + default: + throw new Error('Not Implemented'); + } + }, + default: true +}) +export abstract class PrincipalScopedEntity extends BaseEntity { + @Index() + @ManyToOne() + project: Ref; + + @ManyToOne() + createdBy: Ref; + + constructor({ project, createdBy, ...rest }: PrincipalScopedEntityInput) { + super(rest); + + if (project && createdBy) { + this.project = project; + this.createdBy = createdBy; + } else { + const projectPrincipal = getProjectPrincipal(); + + this.project = projectPrincipal.project; + this.createdBy = ref(projectPrincipal); + } + } + + @BeforeCreate() + @BeforeUpdate() + @BeforeDelete() + async authorize(_: EventArgs) { + if (inJob() || inSeeder()) return; + + const project = await this.project.loadOrFail({ filters: false }); + if (project.status === ProjectStatus.ARCHIVED) + throw new APIError({ + message: "Archived project can't be used", + code: APIErrorCode.FORBIDDEN + }); + + const projectPrincipal = getProjectPrincipal(); + if (this.createdBy.id !== projectPrincipal.id) + throw new APIError({ + message: 'Insufficient permissions', + code: APIErrorCode.FORBIDDEN + }); + } +} + +export type PrincipalScopedEntityInput = BaseEntityInput & + Partial>; diff --git a/src/common/project-scoped.entity.ts b/src/common/project-scoped.entity.ts new file mode 100644 index 0000000..e0a0e78 --- /dev/null +++ b/src/common/project-scoped.entity.ts @@ -0,0 +1,116 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + BeforeCreate, + BeforeDelete, + BeforeUpdate, + Entity, + EventArgs, + Filter, + Index, + ManyToOne, + ref, + Ref +} from '@mikro-orm/core'; +import { requestContext } from '@fastify/request-context'; + +import { BaseEntity, BaseEntityInput } from './base.entity.js'; + +import { Project, ProjectStatus } from '@/administration/entities/project.entity.js'; +import { ProjectPrincipal } from '@/administration/entities/project-principal.entity.js'; +import { getProjectPrincipal } from '@/administration/helpers.js'; +import { APIError, APIErrorCode } from '@/errors/error.entity.js'; +import { Thread } from '@/threads/thread.entity.js'; +import { inJob, inSeeder } from '@/context.js'; +import { ProjectRole } from '@/administration/entities/constants.js'; + +@Entity({ abstract: true }) +@Filter({ + name: 'projectAccess', + cond: async (_ = {}, type) => { + if (inJob() || inSeeder()) return; + + const projectPrincipal = requestContext.get('projectPrincipal'); + if (!projectPrincipal) return { _id: null }; + + switch (type) { + case 'read': { + return { + project: projectPrincipal.project, + $or: [{ dependsOn: null }, { createdBy: projectPrincipal.id }] + }; + } + default: + throw new Error('Not Implemented'); + } + }, + default: true +}) +export abstract class ProjectScopedEntity extends BaseEntity { + @Index() + @ManyToOne() + project: Ref; + + @ManyToOne() + createdBy: Ref; + + @Index() + @ManyToOne() + dependsOn?: Ref; + + constructor({ project, createdBy, dependsOn, ...rest }: ProjectScopedEntityInput) { + super(rest); + + if (project && createdBy) { + this.project = project; + this.createdBy = createdBy; + } else { + const projectPrincipal = getProjectPrincipal(); + this.project = projectPrincipal.project; + this.createdBy = ref(projectPrincipal); + } + + this.dependsOn = dependsOn; + } + + @BeforeCreate() + @BeforeUpdate() + @BeforeDelete() + async authorize(_: EventArgs) { + if (inJob() || inSeeder()) return; + + const project = await this.project.loadOrFail({ filters: false }); + if (project.status === ProjectStatus.ARCHIVED) + throw new APIError({ + message: "Archived project can't be used", + code: APIErrorCode.FORBIDDEN + }); + + const projectPrincipal = getProjectPrincipal(); + const role = projectPrincipal.role; + if (this.dependsOn) { + if (this.createdBy.id === projectPrincipal.id) return; + } else if (role === ProjectRole.ADMIN || role === ProjectRole.WRITER) return; + throw new APIError({ + message: 'Insufficient project role', + code: APIErrorCode.FORBIDDEN + }); + } +} + +export type ProjectScopedEntityInput = BaseEntityInput & + Partial>; diff --git a/src/config.ts b/src/config.ts new file mode 100644 index 0000000..0b38502 --- /dev/null +++ b/src/config.ts @@ -0,0 +1,174 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import 'dotenv/config'; +import { difference } from 'remeda'; + +import { + CodeInterpreterStorageBackend, + LLMBackend, + SearchToolBackend +} from './runs/execution/constants'; +import { EmbeddingBackend } from './embedding/constants'; + +import { QueueName } from '@/jobs/constants.js'; + +function getEnv(name: keyof typeof process.env): string; +function getEnv(name: keyof typeof process.env, fallback: string): string; +function getEnv(name: keyof typeof process.env, fallback: null): string | null; +function getEnv(name: keyof typeof process.env, fallback?: string | null): string | null { + const env = process.env[name]; + if (env) return env; + else if (fallback !== undefined) return fallback; + else throw new Error(`Missing env ${name}`); +} + +function getStringArray( + name: keyof typeof process.env, + allowedValues: AllowedValues, + fallback?: AllowedValues +): AllowedValues { + const items = getEnv(name, null)?.split(',') ?? fallback ?? []; + const unknownValues = difference(items, allowedValues); + if (unknownValues.length) throw Error(`Unknown items ${unknownValues.join(',')} in ${name}`); + return items as AllowedValues; +} + +function getEnum( + name: keyof typeof process.env, + allowedValues: T, + fallback?: T[number] +): T[number] { + const value = getEnv(name, null) ?? fallback; + if (!value || !allowedValues.includes(value)) + throw Error(`Invalid enum value ${value} in ${name}`); + return value as T[number]; +} + +export const GIT_TAG = getEnv('GIT_TAG', 'dev'); + +export const PORT = parseInt(getEnv('PORT', '4000')); +export const LOG_LEVEL = getEnv('LOG_LEVEL', 'info'); +export const SHUTDOWN_GRACEFUL_PERIOD = parseInt(getEnv('SHUTDOWN_GRACEFUL_PERIOD', '5000')); + +export const MONGODB_URL = getEnv('MONGODB_URL'); +export const MONGODB_DATABASE_NAME = getEnv('MONGODB_DATABASE_NAME'); +export const MONGODB_CA_CERT = getEnv('MONGODB_CA_CERT', null); + +export const REDIS_URL = getEnv('REDIS_URL'); +export const REDIS_CA_CERT = getEnv('REDIS_CA_CERT', null); +export const REDIS_CACHE_URL = getEnv('REDIS_CACHE_URL'); +export const REDIS_CACHE_CA_CERT = getEnv('REDIS_CACHE_CA_CERT', null); + +export const AUTH_SERVER_PORT = parseInt(getEnv('AUTH_SERVER_PORT', '0')); +export const AUTH_WELL_KNOWN = getEnv('AUTH_WELL_KNOWN'); +export const AUTH_CLIENT_ID = getEnv('AUTH_CLIENT_ID'); +export const AUTH_CLIENT_SECRET = getEnv('AUTH_CLIENT_SECRET'); +export const AUTH_AUDIENCE = getEnv('AUTH_AUDIENCE'); + +// Backends +export const LLM_BACKEND = getEnum('LLM_BACKEND', Object.values(LLMBackend)); +export const EMBEDDING_BACKEND = getEnum('EMBEDDING_BACKEND', Object.values(EmbeddingBackend)); + +export const OLLAMA_URL = getEnv('OLLAMA_URL', null); + +export const IBM_VLLM_URL = getEnv('IBM_VLLM_URL', null); +export const IBM_VLLM_ROOT_CERT = getEnv('IBM_VLLM_ROOT_CERT', null); +export const IBM_VLLM_CERT_CHAIN = getEnv('IBM_VLLM_CERT_CHAIN', null); +export const IBM_VLLM_PRIVATE_KEY = getEnv('IBM_VLLM_PRIVATE_KEY', null); + +export const OPENAI_API_KEY = getEnv('OPENAI_API_KEY', null); + +export const BAM_API_KEY = getEnv('BAM_API_KEY', null); + +export const WATSONX_API_KEY = getEnv('WATSONX_API_KEY', null); +export const WATSONX_PROJECT_ID = getEnv('WATSONX_PROJECT_ID', null); + +export const CAIKIT_URL = getEnv('CAIKIT_URL', null); +export const CAIKIT_CA_CERT = getEnv('CAIKIT_CA_CERT', null); +export const CAIKIT_CERT = getEnv('CAIKIT_CERT', null); +export const CAIKIT_KEY = getEnv('CAIKIT_KEY', null); + +export const BEE_CODE_INTERPRETER_URL = getEnv('BEE_CODE_INTERPRETER_URL', null); +export const BEE_CODE_INTERPRETER_CA_CERT = getEnv('BEE_CODE_INTERPRETER_CA_CERT', null); +export const BEE_CODE_INTERPRETER_CERT = getEnv('BEE_CODE_INTERPRETER_CERT', null); +export const BEE_CODE_INTERPRETER_KEY = getEnv('BEE_CODE_INTERPRETER_KEY', null); + +export const BEE_CODE_INTERPRETER_BUCKET_FILE_STORAGE = getEnv( + 'BEE_CODE_INTERPRETER_BUCKET_FILE_STORAGE', + null +); + +export const BEE_CODE_INTERPRETER_FILE_STORAGE_PATH = getEnv( + 'BEE_CODE_INTERPRETER_FILE_STORAGE_PATH', + null +); + +export const BEE_CODE_INTERPRETER_STORAGE_BACKEND = getEnum( + 'BEE_CODE_INTERPRETER_STORAGE_BACKEND', + Object.values(CodeInterpreterStorageBackend) +); + +export const SEARCH_TOOL_BACKEND = getEnum( + 'SEARCH_TOOL_BACKEND', + Object.values(SearchToolBackend), + SearchToolBackend.DUCK_DUCK_GO +); +export const BEE_GOOGLE_SEARCH_API_KEY = getEnv('BEE_GOOGLE_SEARCH_API_KEY', null); +export const BEE_GOOGLE_SEARCH_CSE_ID = getEnv('BEE_GOOGLE_SEARCH_CSE_ID', null); + +export const S3_ENDPOINT = getEnv('S3_ENDPOINT'); +export const S3_ACCESS_KEY_ID = getEnv('S3_ACCESS_KEY_ID'); +export const S3_SECRET_ACCESS_KEY = getEnv('S3_SECRET_ACCESS_KEY'); +export const S3_BUCKET_FILE_STORAGE = getEnv('S3_BUCKET_FILE_STORAGE'); + +export const PROMETHEUS_PUSHGATEWAY_URL = getEnv('PROMETHEUS_PUSHGATEWAY_URL', null); + +export const BEE_OBSERVE_API_URL = getEnv('BEE_OBSERVE_API_URL', null); +export const BEE_OBSERVE_API_AUTH_KEY = getEnv('BEE_OBSERVE_API_AUTH_KEY', null); +if (BEE_OBSERVE_API_URL && !BEE_OBSERVE_API_AUTH_KEY) { + throw new Error('Missing env BEE_OBSERVE_API_AUTH_KEY'); +} + +export const MILVUS_HOST = getEnv('MILVUS_HOST', '127.0.0.1'); +export const MILVUS_PORT = getEnv('MILVUS_PORT', '19530'); +export const MILVUS_USERNAME = getEnv('MILVUS_USERNAME'); +export const MILVUS_PASSWORD = getEnv('MILVUS_PASSWORD'); +export const MILVUS_DATABASE_NAME = getEnv('MILVUS_DATABASE_NAME', 'default'); +export const MILVUS_USE_TLS = getEnv('MILVUS_USE_TLS', 'true') == 'true'; +export const MILVUS_CA_CERT = Buffer.from(getEnv('MILVUS_CA_CERT', '')); +export const MILVUS_CERT = Buffer.from(getEnv('MILVUS_CERT', '')); +export const MILVUS_KEY = Buffer.from(getEnv('MILVUS_KEY', '')); + +export const HTTP_PROXY_URL = getEnv('HTTP_PROXY_URL', null); + +if (MILVUS_USE_TLS && (!MILVUS_CA_CERT || !MILVUS_CERT || !MILVUS_KEY)) { + throw new Error('MILVUS TLS is enabled but required certificates are not provided'); +} + +export const WDU_URL = getEnv('WDU_URL', null); + +// cannot import QueueName object due to cyclic import, using this weaker type-check +const allowedQueues = Object.values(QueueName); +export const RUN_BULLMQ_WORKERS = getStringArray('RUN_BULLMQ_WORKERS', allowedQueues, []); + +export const CRYPTO_CIPHER_KEY = Buffer.from(getEnv('CRYPTO_CIPHER_KEY'), 'base64'); + +// TODO remove after org/project management is ready +export const ORGANIZATION_ID_DEFAULT = getEnv('ORGANIZATION_ID_DEFAULT', null); +export const ORGANIZATION_OWNER_ID_DEFAULT = getEnv('ORGANIZATION_OWNER_ID_DEFAULT'); +export const PROJECT_ID_DEFAULT = getEnv('PROJECT_ID_DEFAULT', null); +export const PROJECT_ADMIN_ID_DEFAULT = getEnv('PROJECT_ADMIN_ID_DEFAULT'); diff --git a/src/context.ts b/src/context.ts new file mode 100644 index 0000000..6d43be9 --- /dev/null +++ b/src/context.ts @@ -0,0 +1,56 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AsyncLocalStorage } from 'node:async_hooks'; + +import { FastifyPluginAsync } from 'fastify'; +import fp from 'fastify-plugin'; +import { + fastifyRequestContext, + requestContext, + RequestContextData +} from '@fastify/request-context'; +import { Job } from 'bullmq'; + +export const requestContextPlugin: FastifyPluginAsync = fp.default(async (app) => { + app.register(fastifyRequestContext); + app.addHook('onRequest', async (req, res) => { + req.requestContext.set('req', req); + req.requestContext.set('res', res); + }); +}); + +export function ensureRequestContextData( + key: K +): Required[K] { + const value = requestContext.get(key); + if (!value) throw new Error(`Missing request context key: ${key}`); + return value; +} + +export function inRequest(): boolean { + return !!requestContext.get('req'); +} + +export const jobLocalStorage = new AsyncLocalStorage<{ job: Job }>(); + +export function inJob(): boolean { + return !!jobLocalStorage.getStore()?.job; +} + +export function inSeeder(): boolean { + return process.env.IN_SEEDER === 'true'; +} diff --git a/src/database.ts b/src/database.ts new file mode 100644 index 0000000..1125678 --- /dev/null +++ b/src/database.ts @@ -0,0 +1,35 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { MongoDriver, MikroORM } from '@mikro-orm/mongodb'; +import { RequestContext } from '@mikro-orm/core'; +import { FastifyPluginAsync } from 'fastify'; +import fp from 'fastify-plugin'; + +import config from './mikro-orm.config.js'; +import { getLogger } from './logger.js'; + +export const ORM = await MikroORM.init({ + ...config, + logger: (msg) => getLogger().trace(msg) +}); +await ORM.schema.createSchema(); + +export const databasePlugin: FastifyPluginAsync = fp.default(async (app) => { + app.addHook('preHandler', (request, reply, done) => { + RequestContext.create(ORM.em, done); + }); +}); diff --git a/src/embedding/adapters/bam-embedding.ts b/src/embedding/adapters/bam-embedding.ts new file mode 100644 index 0000000..f05804f --- /dev/null +++ b/src/embedding/adapters/bam-embedding.ts @@ -0,0 +1,56 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Client } from '@ibm-generative-ai/node-sdk'; +import pLimit from 'p-limit'; +import { chunk } from 'remeda'; + +import { Embedding, EmbeddingOptions } from './embedding'; + +const MAX_EMBEDDING_INPUTS = 20; + +export class BAMEmbedding extends Embedding { + protected static limit = pLimit(5); + + constructor( + public readonly model: string, + public readonly client: Client + ) { + super(model); + } + + async embedMany(texts: string[], options?: EmbeddingOptions): Promise { + const results = await Promise.all( + chunk(texts, MAX_EMBEDDING_INPUTS).map((texts) => + BAMEmbedding.limit(async () => { + const response = await this.client.text.embedding.create( + { + model_id: this.model, + input: texts, + parameters: { + truncate_input_tokens: true + } + }, + { signal: options?.signal } + ); + if (response.results?.length !== texts.length) throw new Error('Missing embedding'); + return response.results.map((result) => result.embedding); + }) + ) + ); + return results.flat(); + } +} diff --git a/src/embedding/adapters/caikit/caikit-embedding.ts b/src/embedding/adapters/caikit/caikit-embedding.ts new file mode 100644 index 0000000..84ac675 --- /dev/null +++ b/src/embedding/adapters/caikit/caikit-embedding.ts @@ -0,0 +1,61 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import pLimit from 'p-limit'; +import { chunk } from 'remeda'; + +import { Embedding, EmbeddingOptions } from '../embedding'; + +import { EmbeddingResults__Output } from './grpc/types/caikit_data_model/caikit_nlp/EmbeddingResults'; +import { createGrpcMetadata } from './grpc/utils/metadata'; +import { wrapGrpcCall } from './grpc/utils/wrappers'; +import { EmbeddingTasksRequest } from './grpc/types/caikit/runtime/Nlp/EmbeddingTasksRequest'; +import { NlpServiceClient } from './grpc/types/caikit/runtime/Nlp/NlpService'; + +const MAX_EMBEDDING_INPUTS = 100; + +export class CaikitEmbedding extends Embedding { + protected static limit = pLimit(5); + + constructor( + public readonly model: string, + public readonly client: NlpServiceClient + ) { + super(model); + } + + async embedMany(texts: string[], options?: EmbeddingOptions): Promise { + const results = await Promise.all( + chunk(texts, MAX_EMBEDDING_INPUTS).map((texts) => + CaikitEmbedding.limit(async () => { + const output = await wrapGrpcCall( + this.client.embeddingTasksPredict.bind(this.client) + )({ texts, truncate_input_tokens: 512 }, createGrpcMetadata({ modelId: this.model }), { + signal: options?.signal + }); + const embeddings = output.results?.vectors.map((vector) => { + const embedding = vector[vector.data]?.values; + if (!embedding) throw new Error('Missing embedding'); + return embedding; + }); + if (embeddings?.length !== texts.length) throw new Error('Missing embedding'); + return embeddings; + }) + ) + ); + return results.flat(); + } +} diff --git a/src/embedding/adapters/caikit/grpc/client.ts b/src/embedding/adapters/caikit/grpc/client.ts new file mode 100644 index 0000000..94da739 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/client.ts @@ -0,0 +1,57 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import protoLoader from '@grpc/proto-loader'; +import grpc from '@grpc/grpc-js'; +import { createCache, memoryStore } from 'cache-manager'; + +import { ProtoGrpcType as EmbeddingsProtoGentypes } from './types/caikit_runtime_Nlp.js'; +import { buildClient } from './utils/build-client.js'; +import { NlpServiceClient } from './types/caikit/runtime/Nlp/NlpService.js'; +import { GRPC_CLIENT_TTL } from './constants.js'; + +const embeddingsProtoPath = './protos/caikit_runtime_Nlp.proto'; // separate variable to avoid Vite transformation https://vitejs.dev/guide/assets#new-url-url-import-meta-url +const EMBEDDINGS_PROTO_PATH = new URL(embeddingsProtoPath, import.meta.url); + +const packageOptions = { + longs: Number, + enums: String, + arrays: true, + objects: true, + oneofs: true, + keepCase: true, + defaults: true +} as const; + +const embeddingsPackageObject = grpc.loadPackageDefinition( + protoLoader.loadSync([EMBEDDINGS_PROTO_PATH.pathname], { + ...packageOptions + }) +) as unknown as EmbeddingsProtoGentypes; + +const embeddingsCache = createCache( + memoryStore({ + max: 100, + ttl: GRPC_CLIENT_TTL + }) +); +export const createEmbeddingsClient = async (modelId: string): Promise => { + return buildClient({ + cache: embeddingsCache, + modelId, + service: embeddingsPackageObject.caikit.runtime.Nlp.NlpService + }); +}; diff --git a/src/embedding/adapters/caikit/grpc/constants.ts b/src/embedding/adapters/caikit/grpc/constants.ts new file mode 100644 index 0000000..d518063 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/constants.ts @@ -0,0 +1,23 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const GRPC_CLIENT_TTL = 15 * 60 * 1000; +export const GRPC_CLIENT_SHUTDOWN_TIMEOUT = GRPC_CLIENT_TTL + 5 * 60 * 1000; + +export const GrpcEmbeddingModel = { + BGE_LARGE_EN_V_1_5: 'baai/bge-large-en-v1.5' +} as const; +export type GrpcEmbeddingModel = (typeof GrpcEmbeddingModel)[keyof typeof GrpcEmbeddingModel]; diff --git a/src/embedding/adapters/caikit/grpc/protos/caikit_data_model_caikit_nlp.proto b/src/embedding/adapters/caikit/grpc/protos/caikit_data_model_caikit_nlp.proto new file mode 100644 index 0000000..feda79d --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/protos/caikit_data_model_caikit_nlp.proto @@ -0,0 +1,120 @@ +// Copyright 2024 IBM Corp. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/*------------------------------------------------------------------------------ + * AUTO GENERATED + *----------------------------------------------------------------------------*/ + +syntax = "proto3"; +package caikit_data_model.caikit_nlp; +import "google/protobuf/struct.proto"; +import "caikit_data_model_common.proto"; + + +/*-- MESSAGES ----------------------------------------------------------------*/ + +message EmbeddingResult { + + /*-- fields --*/ + caikit_data_model.common.Vector1D result = 1; + caikit_data_model.common.ProducerId producer_id = 2; + int64 input_token_count = 3; +} + +message EmbeddingResults { + + /*-- fields --*/ + caikit_data_model.common.ListOfVector1D results = 1; + caikit_data_model.common.ProducerId producer_id = 2; + int64 input_token_count = 3; +} + +message ExponentialDecayLengthPenalty { + + /*-- fields --*/ + int64 start_index = 1; + double decay_factor = 2; +} + +message GenerationTrainRecord { + + /*-- fields --*/ + string input = 1; + string output = 2; +} + +message RerankResult { + + /*-- fields --*/ + caikit_data_model.caikit_nlp.RerankScores result = 1; + caikit_data_model.common.ProducerId producer_id = 2; + int64 input_token_count = 3; +} + +message RerankResults { + + /*-- fields --*/ + repeated caikit_data_model.caikit_nlp.RerankScores results = 1; + caikit_data_model.common.ProducerId producer_id = 2; + int64 input_token_count = 3; +} + +message RerankScore { + + /*-- fields --*/ + google.protobuf.Struct document = 1; + int64 index = 2; + double score = 3; + string text = 4; +} + +message RerankScores { + + /*-- fields --*/ + string query = 1; + repeated caikit_data_model.caikit_nlp.RerankScore scores = 2; +} + +message SentenceSimilarityResult { + + /*-- fields --*/ + caikit_data_model.caikit_nlp.SentenceSimilarityScores result = 1; + caikit_data_model.common.ProducerId producer_id = 2; + int64 input_token_count = 3; +} + +message SentenceSimilarityResults { + + /*-- fields --*/ + repeated caikit_data_model.caikit_nlp.SentenceSimilarityScores results = 1; + caikit_data_model.common.ProducerId producer_id = 2; + int64 input_token_count = 3; +} + +message SentenceSimilarityScores { + + /*-- fields --*/ + repeated double scores = 1; +} + +message TuningConfig { + + /*-- fields --*/ + int64 num_virtual_tokens = 1; + string prompt_tuning_init_text = 2; + string prompt_tuning_init_method = 3; + string prompt_tuning_init_source_model = 4; + repeated string output_model_types = 5; +} diff --git a/src/embedding/adapters/caikit/grpc/protos/caikit_data_model_common.proto b/src/embedding/adapters/caikit/grpc/protos/caikit_data_model_common.proto new file mode 100644 index 0000000..b4003b5 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/protos/caikit_data_model_common.proto @@ -0,0 +1,196 @@ +// Copyright 2024 IBM Corp. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/*------------------------------------------------------------------------------ + * AUTO GENERATED + *----------------------------------------------------------------------------*/ + +syntax = "proto3"; +package caikit_data_model.common; + + +/*-- ENUMS -------------------------------------------------------------------*/ + +enum TrainingStatus { + PLACEHOLDER_UNSET = 0; + QUEUED = 1; + RUNNING = 2; + COMPLETED = 3; + CANCELED = 4; + ERRORED = 5; +} + + +/*-- MESSAGES ----------------------------------------------------------------*/ + +message BoolSequence { + + /*-- fields --*/ + repeated bool values = 1; +} + +message ConnectionInfo { + + /*-- nested messages --*/ + + /*-- fields --*/ + string hostname = 1; + optional int64 port = 2; + optional caikit_data_model.common.ConnectionTlsInfo tls = 3; + optional int64 timeout = 4; + map options = 5; +} + +message ConnectionTlsInfo { + + /*-- fields --*/ + optional bool enabled = 1; + optional bool insecure_verify = 2; + optional string ca_file = 3; + optional string cert_file = 4; + optional string key_file = 5; +} + +message Directory { + + /*-- fields --*/ + string dirname = 1; + string extension = 2; +} + +message File { + + /*-- fields --*/ + bytes data = 1; + string filename = 2; + string type = 3; +} + +message FileReference { + + /*-- fields --*/ + string filename = 1; +} + +message FloatSequence { + + /*-- fields --*/ + repeated double values = 1; +} + +message IntSequence { + + /*-- fields --*/ + repeated int64 values = 1; +} + +message ListOfFileReferences { + + /*-- fields --*/ + repeated string files = 1; +} + +message ListOfVector1D { + + /*-- fields --*/ + repeated caikit_data_model.common.Vector1D vectors = 1; +} + +message NpFloat32Sequence { + + /*-- fields --*/ + repeated float values = 1; +} + +message NpFloat64Sequence { + + /*-- fields --*/ + repeated double values = 1; +} + +message ProducerId { + + /*-- fields --*/ + string name = 1; + string version = 2; +} + +message ProducerPriority { + + /*-- fields --*/ + repeated caikit_data_model.common.ProducerId producers = 1; +} + +message PyFloatSequence { + + /*-- fields --*/ + repeated double values = 1; +} + +message S3Base { + + /*-- fields --*/ + string endpoint = 2; + string region = 3; + string bucket = 4; + string accessKey = 5; + string secretKey = 6; + string IAM_id = 7; + string IAM_api_key = 8; +} + +message S3Files { + + /*-- fields --*/ + string endpoint = 2; + string region = 3; + string bucket = 4; + string accessKey = 5; + string secretKey = 6; + string IAM_id = 7; + string IAM_api_key = 8; + repeated string files = 1; +} + +message S3Path { + + /*-- fields --*/ + string endpoint = 2; + string region = 3; + string bucket = 4; + string accessKey = 5; + string secretKey = 6; + string IAM_id = 7; + string IAM_api_key = 8; + string path = 1; +} + +message StrSequence { + + /*-- fields --*/ + repeated string values = 1; +} + +message Vector1D { + + /*-- fields --*/ + + /*-- oneofs --*/ + oneof data { + caikit_data_model.common.PyFloatSequence data_pyfloatsequence = 1; + caikit_data_model.common.NpFloat32Sequence data_npfloat32sequence = 2; + caikit_data_model.common.NpFloat64Sequence data_npfloat64sequence = 3; + } +} diff --git a/src/embedding/adapters/caikit/grpc/protos/caikit_data_model_common_runtime.proto b/src/embedding/adapters/caikit/grpc/protos/caikit_data_model_common_runtime.proto new file mode 100644 index 0000000..15616a1 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/protos/caikit_data_model_common_runtime.proto @@ -0,0 +1,63 @@ +// Copyright 2024 IBM Corp. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/*------------------------------------------------------------------------------ + * AUTO GENERATED + *----------------------------------------------------------------------------*/ + +syntax = "proto3"; +package caikit_data_model.common.runtime; +import "caikit_data_model_common.proto"; +import "google/protobuf/struct.proto"; + +/*-- MESSAGES ----------------------------------------------------------------*/ + +message ModelInfo { + + /*-- nested messages --*/ + + /*-- fields --*/ + string model_path = 1; + string name = 2; + int64 size = 3; + google.protobuf.Struct metadata = 4; + bool loaded = 7; + string module_id = 5; + map module_metadata = 6; +} + +message ModelInfoRequest { + + /*-- fields --*/ + repeated string model_ids = 1; +} + +message ModelInfoResponse { + + /*-- fields --*/ + repeated caikit_data_model.common.runtime.ModelInfo models = 1; +} + +message RuntimeInfoRequest { +} + +message RuntimeInfoResponse { + + /*-- nested messages --*/ + + /*-- fields --*/ + string runtime_version = 1; + map python_packages = 2; +} diff --git a/src/embedding/adapters/caikit/grpc/protos/caikit_data_model_nlp.proto b/src/embedding/adapters/caikit/grpc/protos/caikit_data_model_nlp.proto new file mode 100644 index 0000000..132d844 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/protos/caikit_data_model_nlp.proto @@ -0,0 +1,196 @@ +// Copyright 2024 IBM Corp. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/*------------------------------------------------------------------------------ + * AUTO GENERATED + *----------------------------------------------------------------------------*/ + +syntax = "proto3"; +package caikit_data_model.nlp; +import "caikit_data_model_common.proto"; + + +/*-- ENUMS -------------------------------------------------------------------*/ + +enum FinishReason { + NOT_FINISHED = 0; + MAX_TOKENS = 1; + EOS_TOKEN = 2; + CANCELLED = 3; + TIME_LIMIT = 4; + STOP_SEQUENCE = 5; + TOKEN_LIMIT = 6; + ERROR = 7; +} + +enum InputWarningReason { + UNSUITABLE_INPUT = 0; +} + + +/*-- MESSAGES ----------------------------------------------------------------*/ + +message ClassificationResult { + + /*-- fields --*/ + string label = 1; + double score = 2; +} + +message ClassificationResults { + + /*-- fields --*/ + repeated caikit_data_model.nlp.ClassificationResult results = 1; +} + +message ClassificationTrainRecord { + + /*-- fields --*/ + string text = 1; + repeated string labels = 2; +} + +message ClassifiedGeneratedTextResult { + + /*-- fields --*/ + string generated_text = 1; + caikit_data_model.nlp.TextGenTokenClassificationResults token_classification_results = 2; + caikit_data_model.nlp.FinishReason finish_reason = 3; + int64 generated_token_count = 4; + uint64 seed = 5; + int64 input_token_count = 6; + repeated caikit_data_model.nlp.InputWarning warnings = 9; + repeated caikit_data_model.nlp.GeneratedToken tokens = 10; + repeated caikit_data_model.nlp.GeneratedToken input_tokens = 11; +} + +message ClassifiedGeneratedTextStreamResult { + + /*-- fields --*/ + string generated_text = 1; + caikit_data_model.nlp.TextGenTokenClassificationResults token_classification_results = 2; + caikit_data_model.nlp.FinishReason finish_reason = 3; + int64 generated_token_count = 4; + uint64 seed = 5; + int64 input_token_count = 6; + repeated caikit_data_model.nlp.InputWarning warnings = 9; + repeated caikit_data_model.nlp.GeneratedToken tokens = 10; + repeated caikit_data_model.nlp.GeneratedToken input_tokens = 11; + int64 processed_index = 7; + int64 start_index = 8; +} + +message GeneratedTextResult { + + /*-- fields --*/ + string generated_text = 1; + int64 generated_tokens = 2; + caikit_data_model.nlp.FinishReason finish_reason = 3; + caikit_data_model.common.ProducerId producer_id = 4; + int64 input_token_count = 5; + uint64 seed = 6; + repeated caikit_data_model.nlp.GeneratedToken tokens = 7; + repeated caikit_data_model.nlp.GeneratedToken input_tokens = 8; +} + +message GeneratedTextStreamResult { + + /*-- fields --*/ + string generated_text = 1; + repeated caikit_data_model.nlp.GeneratedToken tokens = 2; + caikit_data_model.nlp.TokenStreamDetails details = 3; + caikit_data_model.common.ProducerId producer_id = 4; + repeated caikit_data_model.nlp.GeneratedToken input_tokens = 5; +} + +message GeneratedToken { + + /*-- fields --*/ + string text = 1; + double logprob = 3; +} + +message InputWarning { + + /*-- fields --*/ + caikit_data_model.nlp.InputWarningReason id = 1; + string message = 2; +} + +message TextGenTokenClassificationResults { + + /*-- fields --*/ + repeated caikit_data_model.nlp.TokenClassificationResult input = 10; + repeated caikit_data_model.nlp.TokenClassificationResult output = 20; +} + +message Token { + + /*-- fields --*/ + int64 start = 1; + int64 end = 2; + string text = 3; +} + +message TokenClassificationResult { + + /*-- fields --*/ + int64 start = 1; + int64 end = 2; + string word = 3; + string entity = 4; + string entity_group = 5; + double score = 6; + int64 token_count = 7; +} + +message TokenClassificationResults { + + /*-- fields --*/ + repeated caikit_data_model.nlp.TokenClassificationResult results = 1; +} + +message TokenClassificationStreamResult { + + /*-- fields --*/ + repeated caikit_data_model.nlp.TokenClassificationResult results = 1; + int64 processed_index = 2; + int64 start_index = 3; +} + +message TokenStreamDetails { + + /*-- fields --*/ + caikit_data_model.nlp.FinishReason finish_reason = 1; + uint32 generated_tokens = 2; + uint64 seed = 3; + int64 input_token_count = 4; +} + +message TokenizationResults { + + /*-- fields --*/ + repeated caikit_data_model.nlp.Token results = 1; + int64 token_count = 4; +} + +message TokenizationStreamResult { + + /*-- fields --*/ + repeated caikit_data_model.nlp.Token results = 1; + int64 token_count = 4; + int64 processed_index = 2; + int64 start_index = 3; +} diff --git a/src/embedding/adapters/caikit/grpc/protos/caikit_data_model_runtime.proto b/src/embedding/adapters/caikit/grpc/protos/caikit_data_model_runtime.proto new file mode 100644 index 0000000..57c7d53 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/protos/caikit_data_model_runtime.proto @@ -0,0 +1,55 @@ +// Copyright 2024 IBM Corp. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/*------------------------------------------------------------------------------ + * AUTO GENERATED + *----------------------------------------------------------------------------*/ + +syntax = "proto3"; +package caikit_data_model.runtime; +import "google/protobuf/timestamp.proto"; +import "caikit_data_model_common.proto"; + + +/*-- MESSAGES ----------------------------------------------------------------*/ + +message ModelPointer { + + /*-- fields --*/ + string model_id = 1; +} + +message TrainingInfoRequest { + + /*-- fields --*/ + string training_id = 1; +} + +message TrainingJob { + + /*-- fields --*/ + string training_id = 1; + string model_name = 2; +} + +message TrainingStatusResponse { + + /*-- fields --*/ + string training_id = 1; + caikit_data_model.common.TrainingStatus state = 2; + google.protobuf.Timestamp submission_timestamp = 3; + google.protobuf.Timestamp completion_timestamp = 4; + repeated string reasons = 5; +} diff --git a/src/embedding/adapters/caikit/grpc/protos/caikit_runtime_Nlp.proto b/src/embedding/adapters/caikit/grpc/protos/caikit_runtime_Nlp.proto new file mode 100644 index 0000000..02fe48c --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/protos/caikit_runtime_Nlp.proto @@ -0,0 +1,245 @@ +// Copyright 2024 IBM Corp. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/*------------------------------------------------------------------------------ + * AUTO GENERATED + *----------------------------------------------------------------------------*/ + +syntax = "proto3"; +package caikit.runtime.Nlp; +import "google/protobuf/struct.proto"; +import "caikit_data_model_caikit_nlp.proto"; +import "caikit_data_model_common.proto"; +import "caikit_data_model_nlp.proto"; +import "caikit_data_model_runtime.proto"; + + +/*-- MESSAGES ----------------------------------------------------------------*/ + +message BidiStreamingTokenClassificationTaskRequest { + + /*-- fields --*/ + string text_stream = 1; + optional double threshold = 2; +} + +message DataStreamSourceGenerationTrainRecord { + + /*-- fields --*/ + + /*-- oneofs --*/ + oneof data_stream { + caikit.runtime.Nlp.DataStreamSourceGenerationTrainRecordJsonData jsondata = 1; + caikit_data_model.common.FileReference file = 2; + caikit_data_model.common.ListOfFileReferences list_of_files = 3; + caikit_data_model.common.Directory directory = 4; + caikit_data_model.common.S3Files s3files = 5; + } +} + +message DataStreamSourceGenerationTrainRecordJsonData { + + /*-- fields --*/ + repeated caikit_data_model.caikit_nlp.GenerationTrainRecord data = 1; +} + +message EmbeddingTaskRequest { + + /*-- fields --*/ + string text = 1; + optional int64 truncate_input_tokens = 2; +} + +message EmbeddingTasksRequest { + + /*-- fields --*/ + repeated string texts = 1; + optional int64 truncate_input_tokens = 2; +} + +message RerankTaskRequest { + + /*-- fields --*/ + string query = 1; + repeated google.protobuf.Struct documents = 2; + optional int64 top_n = 3; + optional int64 truncate_input_tokens = 4; + optional bool return_documents = 5; + optional bool return_query = 6; + optional bool return_text = 7; +} + +message RerankTasksRequest { + + /*-- fields --*/ + repeated string queries = 1; + repeated google.protobuf.Struct documents = 2; + optional int64 top_n = 3; + optional int64 truncate_input_tokens = 4; + optional bool return_documents = 5; + optional bool return_queries = 6; + optional bool return_text = 7; +} + +message SentenceSimilarityTaskRequest { + + /*-- fields --*/ + string source_sentence = 1; + repeated string sentences = 2; + optional int64 truncate_input_tokens = 3; +} + +message SentenceSimilarityTasksRequest { + + /*-- fields --*/ + repeated string source_sentences = 1; + repeated string sentences = 2; + optional int64 truncate_input_tokens = 3; +} + +message ServerStreamingTextGenerationTaskRequest { + + /*-- fields --*/ + string text = 1; + optional int64 max_new_tokens = 2; + optional int64 min_new_tokens = 3; + optional int64 truncate_input_tokens = 4; + optional string decoding_method = 5; + optional int64 top_k = 6; + optional double top_p = 7; + optional double typical_p = 8; + optional double temperature = 9; + optional double repetition_penalty = 10; + optional double max_time = 11; + optional caikit_data_model.caikit_nlp.ExponentialDecayLengthPenalty exponential_decay_length_penalty = 12; + repeated string stop_sequences = 13; + optional uint64 seed = 14; + optional bool preserve_input_text = 15; +} + +message TextClassificationTaskRequest { + + /*-- fields --*/ + string text = 1; +} + +message TextGenerationTaskPeftPromptTuningTrainParameters { + + /*-- fields --*/ + string base_model = 1; + caikit.runtime.Nlp.DataStreamSourceGenerationTrainRecord train_stream = 2; + caikit_data_model.caikit_nlp.TuningConfig tuning_config = 3; + optional caikit.runtime.Nlp.DataStreamSourceGenerationTrainRecord val_stream = 4; + optional string device = 5; + optional string tuning_type = 6; + optional int64 num_epochs = 7; + optional double learning_rate = 8; + optional string verbalizer = 9; + optional int64 batch_size = 10; + optional int64 max_source_length = 11; + optional int64 max_target_length = 12; + optional int64 accumulate_steps = 13; + optional string torch_dtype = 14; + optional bool silence_progress_bars = 15; + optional int64 seed = 16; +} + +message TextGenerationTaskPeftPromptTuningTrainRequest { + + /*-- fields --*/ + string model_name = 1; + caikit_data_model.common.S3Path output_path = 2; + caikit.runtime.Nlp.TextGenerationTaskPeftPromptTuningTrainParameters parameters = 3; +} + +message TextGenerationTaskRequest { + + /*-- fields --*/ + string text = 1; + optional int64 max_new_tokens = 2; + optional int64 min_new_tokens = 3; + optional int64 truncate_input_tokens = 4; + optional string decoding_method = 5; + optional int64 top_k = 6; + optional double top_p = 7; + optional double typical_p = 8; + optional double temperature = 9; + optional double repetition_penalty = 10; + optional double max_time = 11; + optional caikit_data_model.caikit_nlp.ExponentialDecayLengthPenalty exponential_decay_length_penalty = 12; + repeated string stop_sequences = 13; + optional uint64 seed = 14; + optional bool preserve_input_text = 15; +} + +message TextGenerationTaskTextGenerationTrainParameters { + + /*-- fields --*/ + string base_model = 1; + caikit.runtime.Nlp.DataStreamSourceGenerationTrainRecord train_stream = 2; + optional string torch_dtype = 3; + optional int64 max_source_length = 4; + optional int64 max_target_length = 5; + optional int64 batch_size = 6; + optional int64 num_epochs = 7; + optional int64 accumulate_steps = 8; + optional int64 random_seed = 9; + optional double lr = 10; + optional bool use_iterable_dataset = 11; +} + +message TextGenerationTaskTextGenerationTrainRequest { + + /*-- fields --*/ + string model_name = 1; + caikit_data_model.common.S3Path output_path = 2; + caikit.runtime.Nlp.TextGenerationTaskTextGenerationTrainParameters parameters = 3; +} + +message TokenClassificationTaskRequest { + + /*-- fields --*/ + string text = 1; + optional double threshold = 2; +} + +message TokenizationTaskRequest { + + /*-- fields --*/ + string text = 1; +} + + +/*-- SERVICES ----------------------------------------------------------------*/ + +service NlpService { + rpc BidiStreamingTokenClassificationTaskPredict(stream caikit.runtime.Nlp.BidiStreamingTokenClassificationTaskRequest) returns (stream caikit_data_model.nlp.TokenClassificationStreamResult); + rpc EmbeddingTaskPredict(caikit.runtime.Nlp.EmbeddingTaskRequest) returns (caikit_data_model.caikit_nlp.EmbeddingResult); + rpc EmbeddingTasksPredict(caikit.runtime.Nlp.EmbeddingTasksRequest) returns (caikit_data_model.caikit_nlp.EmbeddingResults); + rpc RerankTaskPredict(caikit.runtime.Nlp.RerankTaskRequest) returns (caikit_data_model.caikit_nlp.RerankResult); + rpc RerankTasksPredict(caikit.runtime.Nlp.RerankTasksRequest) returns (caikit_data_model.caikit_nlp.RerankResults); + rpc SentenceSimilarityTaskPredict(caikit.runtime.Nlp.SentenceSimilarityTaskRequest) returns (caikit_data_model.caikit_nlp.SentenceSimilarityResult); + rpc SentenceSimilarityTasksPredict(caikit.runtime.Nlp.SentenceSimilarityTasksRequest) returns (caikit_data_model.caikit_nlp.SentenceSimilarityResults); + rpc ServerStreamingTextGenerationTaskPredict(caikit.runtime.Nlp.ServerStreamingTextGenerationTaskRequest) returns (stream caikit_data_model.nlp.GeneratedTextStreamResult); + rpc TextClassificationTaskPredict(caikit.runtime.Nlp.TextClassificationTaskRequest) returns (caikit_data_model.nlp.ClassificationResults); + rpc TextGenerationTaskPredict(caikit.runtime.Nlp.TextGenerationTaskRequest) returns (caikit_data_model.nlp.GeneratedTextResult); + rpc TokenClassificationTaskPredict(caikit.runtime.Nlp.TokenClassificationTaskRequest) returns (caikit_data_model.nlp.TokenClassificationResults); + rpc TokenizationTaskPredict(caikit.runtime.Nlp.TokenizationTaskRequest) returns (caikit_data_model.nlp.TokenizationResults); +} + +service NlpTrainingService { + rpc TextGenerationTaskPeftPromptTuningTrain(caikit.runtime.Nlp.TextGenerationTaskPeftPromptTuningTrainRequest) returns (caikit_data_model.runtime.TrainingJob); + rpc TextGenerationTaskTextGenerationTrain(caikit.runtime.Nlp.TextGenerationTaskTextGenerationTrainRequest) returns (caikit_data_model.runtime.TrainingJob); +} diff --git a/src/embedding/adapters/caikit/grpc/protos/caikit_runtime_info.proto b/src/embedding/adapters/caikit/grpc/protos/caikit_runtime_info.proto new file mode 100644 index 0000000..754b48d --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/protos/caikit_runtime_info.proto @@ -0,0 +1,31 @@ +// Copyright 2024 IBM Corp. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/*------------------------------------------------------------------------------ + * AUTO GENERATED + *----------------------------------------------------------------------------*/ + +syntax = "proto3"; +package caikit.runtime.info; +import "caikit_data_model_common.proto"; +import "caikit_data_model_common_runtime.proto"; + + +/*-- SERVICES ----------------------------------------------------------------*/ + +service InfoService { + rpc GetRuntimeInfo(caikit_data_model.common.runtime.RuntimeInfoRequest) returns (caikit_data_model.common.runtime.RuntimeInfoResponse); + rpc GetModelsInfo(caikit_data_model.common.runtime.ModelInfoRequest) returns (caikit_data_model.common.runtime.ModelInfoResponse); +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/BidiStreamingTokenClassificationTaskRequest.ts b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/BidiStreamingTokenClassificationTaskRequest.ts new file mode 100644 index 0000000..3214aae --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/BidiStreamingTokenClassificationTaskRequest.ts @@ -0,0 +1,30 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_runtime_Nlp.proto + + +export interface BidiStreamingTokenClassificationTaskRequest { + 'text_stream'?: (string); + 'threshold'?: (number | string); + '_threshold'?: "threshold"; +} + +export interface BidiStreamingTokenClassificationTaskRequest__Output { + 'text_stream': (string); + 'threshold'?: (number); + '_threshold': "threshold"; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/DataStreamSourceGenerationTrainRecord.ts b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/DataStreamSourceGenerationTrainRecord.ts new file mode 100644 index 0000000..4417e64 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/DataStreamSourceGenerationTrainRecord.ts @@ -0,0 +1,56 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_runtime_Nlp.proto + +import type { + DataStreamSourceGenerationTrainRecordJsonData as _caikit_runtime_Nlp_DataStreamSourceGenerationTrainRecordJsonData, + DataStreamSourceGenerationTrainRecordJsonData__Output as _caikit_runtime_Nlp_DataStreamSourceGenerationTrainRecordJsonData__Output +} from './DataStreamSourceGenerationTrainRecordJsonData'; +import type { + FileReference as _caikit_data_model_common_FileReference, + FileReference__Output as _caikit_data_model_common_FileReference__Output +} from '../../../caikit_data_model/common/FileReference'; +import type { + ListOfFileReferences as _caikit_data_model_common_ListOfFileReferences, + ListOfFileReferences__Output as _caikit_data_model_common_ListOfFileReferences__Output +} from '../../../caikit_data_model/common/ListOfFileReferences'; +import type { + Directory as _caikit_data_model_common_Directory, + Directory__Output as _caikit_data_model_common_Directory__Output +} from '../../../caikit_data_model/common/Directory'; +import type { + S3Files as _caikit_data_model_common_S3Files, + S3Files__Output as _caikit_data_model_common_S3Files__Output +} from '../../../caikit_data_model/common/S3Files'; + +export interface DataStreamSourceGenerationTrainRecord { + jsondata?: _caikit_runtime_Nlp_DataStreamSourceGenerationTrainRecordJsonData | null; + file?: _caikit_data_model_common_FileReference | null; + list_of_files?: _caikit_data_model_common_ListOfFileReferences | null; + directory?: _caikit_data_model_common_Directory | null; + s3files?: _caikit_data_model_common_S3Files | null; + data_stream?: 'jsondata' | 'file' | 'list_of_files' | 'directory' | 's3files'; +} + +export interface DataStreamSourceGenerationTrainRecord__Output { + jsondata?: _caikit_runtime_Nlp_DataStreamSourceGenerationTrainRecordJsonData__Output | null; + file?: _caikit_data_model_common_FileReference__Output | null; + list_of_files?: _caikit_data_model_common_ListOfFileReferences__Output | null; + directory?: _caikit_data_model_common_Directory__Output | null; + s3files?: _caikit_data_model_common_S3Files__Output | null; + data_stream: 'jsondata' | 'file' | 'list_of_files' | 'directory' | 's3files'; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/DataStreamSourceGenerationTrainRecordJsonData.ts b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/DataStreamSourceGenerationTrainRecordJsonData.ts new file mode 100644 index 0000000..ca07998 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/DataStreamSourceGenerationTrainRecordJsonData.ts @@ -0,0 +1,27 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_runtime_Nlp.proto + +import type { GenerationTrainRecord as _caikit_data_model_caikit_nlp_GenerationTrainRecord, GenerationTrainRecord__Output as _caikit_data_model_caikit_nlp_GenerationTrainRecord__Output } from '../../../caikit_data_model/caikit_nlp/GenerationTrainRecord'; + +export interface DataStreamSourceGenerationTrainRecordJsonData { + 'data'?: (_caikit_data_model_caikit_nlp_GenerationTrainRecord)[]; +} + +export interface DataStreamSourceGenerationTrainRecordJsonData__Output { + 'data': (_caikit_data_model_caikit_nlp_GenerationTrainRecord__Output)[]; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/EmbeddingTaskRequest.ts b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/EmbeddingTaskRequest.ts new file mode 100644 index 0000000..9e16440 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/EmbeddingTaskRequest.ts @@ -0,0 +1,31 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_runtime_Nlp.proto + +import type { Long } from '@grpc/proto-loader'; + +export interface EmbeddingTaskRequest { + 'text'?: (string); + 'truncate_input_tokens'?: (number | string | Long); + '_truncate_input_tokens'?: "truncate_input_tokens"; +} + +export interface EmbeddingTaskRequest__Output { + 'text': (string); + 'truncate_input_tokens'?: (number); + '_truncate_input_tokens': "truncate_input_tokens"; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/EmbeddingTasksRequest.ts b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/EmbeddingTasksRequest.ts new file mode 100644 index 0000000..486f632 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/EmbeddingTasksRequest.ts @@ -0,0 +1,31 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_runtime_Nlp.proto + +import type { Long } from '@grpc/proto-loader'; + +export interface EmbeddingTasksRequest { + 'texts'?: (string)[]; + 'truncate_input_tokens'?: (number | string | Long); + '_truncate_input_tokens'?: "truncate_input_tokens"; +} + +export interface EmbeddingTasksRequest__Output { + 'texts': (string)[]; + 'truncate_input_tokens'?: (number); + '_truncate_input_tokens': "truncate_input_tokens"; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/NlpService.ts b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/NlpService.ts new file mode 100644 index 0000000..3090f7c --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/NlpService.ts @@ -0,0 +1,711 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_runtime_Nlp.proto + +import type * as grpc from '@grpc/grpc-js'; +import type { MethodDefinition } from '@grpc/proto-loader'; +import type { + BidiStreamingTokenClassificationTaskRequest as _caikit_runtime_Nlp_BidiStreamingTokenClassificationTaskRequest, + BidiStreamingTokenClassificationTaskRequest__Output as _caikit_runtime_Nlp_BidiStreamingTokenClassificationTaskRequest__Output +} from './BidiStreamingTokenClassificationTaskRequest'; +import type { + ClassificationResults as _caikit_data_model_nlp_ClassificationResults, + ClassificationResults__Output as _caikit_data_model_nlp_ClassificationResults__Output +} from '../../../caikit_data_model/nlp/ClassificationResults'; +import type { + EmbeddingResult as _caikit_data_model_caikit_nlp_EmbeddingResult, + EmbeddingResult__Output as _caikit_data_model_caikit_nlp_EmbeddingResult__Output +} from '../../../caikit_data_model/caikit_nlp/EmbeddingResult'; +import type { + EmbeddingResults as _caikit_data_model_caikit_nlp_EmbeddingResults, + EmbeddingResults__Output as _caikit_data_model_caikit_nlp_EmbeddingResults__Output +} from '../../../caikit_data_model/caikit_nlp/EmbeddingResults'; +import type { + EmbeddingTaskRequest as _caikit_runtime_Nlp_EmbeddingTaskRequest, + EmbeddingTaskRequest__Output as _caikit_runtime_Nlp_EmbeddingTaskRequest__Output +} from './EmbeddingTaskRequest'; +import type { + EmbeddingTasksRequest as _caikit_runtime_Nlp_EmbeddingTasksRequest, + EmbeddingTasksRequest__Output as _caikit_runtime_Nlp_EmbeddingTasksRequest__Output +} from './EmbeddingTasksRequest'; +import type { + GeneratedTextResult as _caikit_data_model_nlp_GeneratedTextResult, + GeneratedTextResult__Output as _caikit_data_model_nlp_GeneratedTextResult__Output +} from '../../../caikit_data_model/nlp/GeneratedTextResult'; +import type { + GeneratedTextStreamResult as _caikit_data_model_nlp_GeneratedTextStreamResult, + GeneratedTextStreamResult__Output as _caikit_data_model_nlp_GeneratedTextStreamResult__Output +} from '../../../caikit_data_model/nlp/GeneratedTextStreamResult'; +import type { + RerankResult as _caikit_data_model_caikit_nlp_RerankResult, + RerankResult__Output as _caikit_data_model_caikit_nlp_RerankResult__Output +} from '../../../caikit_data_model/caikit_nlp/RerankResult'; +import type { + RerankResults as _caikit_data_model_caikit_nlp_RerankResults, + RerankResults__Output as _caikit_data_model_caikit_nlp_RerankResults__Output +} from '../../../caikit_data_model/caikit_nlp/RerankResults'; +import type { + RerankTaskRequest as _caikit_runtime_Nlp_RerankTaskRequest, + RerankTaskRequest__Output as _caikit_runtime_Nlp_RerankTaskRequest__Output +} from './RerankTaskRequest'; +import type { + RerankTasksRequest as _caikit_runtime_Nlp_RerankTasksRequest, + RerankTasksRequest__Output as _caikit_runtime_Nlp_RerankTasksRequest__Output +} from './RerankTasksRequest'; +import type { + SentenceSimilarityResult as _caikit_data_model_caikit_nlp_SentenceSimilarityResult, + SentenceSimilarityResult__Output as _caikit_data_model_caikit_nlp_SentenceSimilarityResult__Output +} from '../../../caikit_data_model/caikit_nlp/SentenceSimilarityResult'; +import type { + SentenceSimilarityResults as _caikit_data_model_caikit_nlp_SentenceSimilarityResults, + SentenceSimilarityResults__Output as _caikit_data_model_caikit_nlp_SentenceSimilarityResults__Output +} from '../../../caikit_data_model/caikit_nlp/SentenceSimilarityResults'; +import type { + SentenceSimilarityTaskRequest as _caikit_runtime_Nlp_SentenceSimilarityTaskRequest, + SentenceSimilarityTaskRequest__Output as _caikit_runtime_Nlp_SentenceSimilarityTaskRequest__Output +} from './SentenceSimilarityTaskRequest'; +import type { + SentenceSimilarityTasksRequest as _caikit_runtime_Nlp_SentenceSimilarityTasksRequest, + SentenceSimilarityTasksRequest__Output as _caikit_runtime_Nlp_SentenceSimilarityTasksRequest__Output +} from './SentenceSimilarityTasksRequest'; +import type { + ServerStreamingTextGenerationTaskRequest as _caikit_runtime_Nlp_ServerStreamingTextGenerationTaskRequest, + ServerStreamingTextGenerationTaskRequest__Output as _caikit_runtime_Nlp_ServerStreamingTextGenerationTaskRequest__Output +} from './ServerStreamingTextGenerationTaskRequest'; +import type { + TextClassificationTaskRequest as _caikit_runtime_Nlp_TextClassificationTaskRequest, + TextClassificationTaskRequest__Output as _caikit_runtime_Nlp_TextClassificationTaskRequest__Output +} from './TextClassificationTaskRequest'; +import type { + TextGenerationTaskRequest as _caikit_runtime_Nlp_TextGenerationTaskRequest, + TextGenerationTaskRequest__Output as _caikit_runtime_Nlp_TextGenerationTaskRequest__Output +} from './TextGenerationTaskRequest'; +import type { + TokenClassificationResults as _caikit_data_model_nlp_TokenClassificationResults, + TokenClassificationResults__Output as _caikit_data_model_nlp_TokenClassificationResults__Output +} from '../../../caikit_data_model/nlp/TokenClassificationResults'; +import type { + TokenClassificationStreamResult as _caikit_data_model_nlp_TokenClassificationStreamResult, + TokenClassificationStreamResult__Output as _caikit_data_model_nlp_TokenClassificationStreamResult__Output +} from '../../../caikit_data_model/nlp/TokenClassificationStreamResult'; +import type { + TokenClassificationTaskRequest as _caikit_runtime_Nlp_TokenClassificationTaskRequest, + TokenClassificationTaskRequest__Output as _caikit_runtime_Nlp_TokenClassificationTaskRequest__Output +} from './TokenClassificationTaskRequest'; +import type { + TokenizationResults as _caikit_data_model_nlp_TokenizationResults, + TokenizationResults__Output as _caikit_data_model_nlp_TokenizationResults__Output +} from '../../../caikit_data_model/nlp/TokenizationResults'; +import type { + TokenizationTaskRequest as _caikit_runtime_Nlp_TokenizationTaskRequest, + TokenizationTaskRequest__Output as _caikit_runtime_Nlp_TokenizationTaskRequest__Output +} from './TokenizationTaskRequest'; + +export interface NlpServiceClient extends grpc.Client { + BidiStreamingTokenClassificationTaskPredict( + metadata: grpc.Metadata, + options?: grpc.CallOptions + ): grpc.ClientDuplexStream< + _caikit_runtime_Nlp_BidiStreamingTokenClassificationTaskRequest, + _caikit_data_model_nlp_TokenClassificationStreamResult__Output + >; + BidiStreamingTokenClassificationTaskPredict( + options?: grpc.CallOptions + ): grpc.ClientDuplexStream< + _caikit_runtime_Nlp_BidiStreamingTokenClassificationTaskRequest, + _caikit_data_model_nlp_TokenClassificationStreamResult__Output + >; + bidiStreamingTokenClassificationTaskPredict( + metadata: grpc.Metadata, + options?: grpc.CallOptions + ): grpc.ClientDuplexStream< + _caikit_runtime_Nlp_BidiStreamingTokenClassificationTaskRequest, + _caikit_data_model_nlp_TokenClassificationStreamResult__Output + >; + bidiStreamingTokenClassificationTaskPredict( + options?: grpc.CallOptions + ): grpc.ClientDuplexStream< + _caikit_runtime_Nlp_BidiStreamingTokenClassificationTaskRequest, + _caikit_data_model_nlp_TokenClassificationStreamResult__Output + >; + + EmbeddingTaskPredict( + argument: _caikit_runtime_Nlp_EmbeddingTaskRequest, + metadata: grpc.Metadata, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_EmbeddingResult__Output> + ): grpc.ClientUnaryCall; + EmbeddingTaskPredict( + argument: _caikit_runtime_Nlp_EmbeddingTaskRequest, + metadata: grpc.Metadata, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_EmbeddingResult__Output> + ): grpc.ClientUnaryCall; + EmbeddingTaskPredict( + argument: _caikit_runtime_Nlp_EmbeddingTaskRequest, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_EmbeddingResult__Output> + ): grpc.ClientUnaryCall; + EmbeddingTaskPredict( + argument: _caikit_runtime_Nlp_EmbeddingTaskRequest, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_EmbeddingResult__Output> + ): grpc.ClientUnaryCall; + embeddingTaskPredict( + argument: _caikit_runtime_Nlp_EmbeddingTaskRequest, + metadata: grpc.Metadata, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_EmbeddingResult__Output> + ): grpc.ClientUnaryCall; + embeddingTaskPredict( + argument: _caikit_runtime_Nlp_EmbeddingTaskRequest, + metadata: grpc.Metadata, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_EmbeddingResult__Output> + ): grpc.ClientUnaryCall; + embeddingTaskPredict( + argument: _caikit_runtime_Nlp_EmbeddingTaskRequest, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_EmbeddingResult__Output> + ): grpc.ClientUnaryCall; + embeddingTaskPredict( + argument: _caikit_runtime_Nlp_EmbeddingTaskRequest, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_EmbeddingResult__Output> + ): grpc.ClientUnaryCall; + + EmbeddingTasksPredict( + argument: _caikit_runtime_Nlp_EmbeddingTasksRequest, + metadata: grpc.Metadata, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_EmbeddingResults__Output> + ): grpc.ClientUnaryCall; + EmbeddingTasksPredict( + argument: _caikit_runtime_Nlp_EmbeddingTasksRequest, + metadata: grpc.Metadata, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_EmbeddingResults__Output> + ): grpc.ClientUnaryCall; + EmbeddingTasksPredict( + argument: _caikit_runtime_Nlp_EmbeddingTasksRequest, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_EmbeddingResults__Output> + ): grpc.ClientUnaryCall; + EmbeddingTasksPredict( + argument: _caikit_runtime_Nlp_EmbeddingTasksRequest, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_EmbeddingResults__Output> + ): grpc.ClientUnaryCall; + embeddingTasksPredict( + argument: _caikit_runtime_Nlp_EmbeddingTasksRequest, + metadata: grpc.Metadata, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_EmbeddingResults__Output> + ): grpc.ClientUnaryCall; + embeddingTasksPredict( + argument: _caikit_runtime_Nlp_EmbeddingTasksRequest, + metadata: grpc.Metadata, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_EmbeddingResults__Output> + ): grpc.ClientUnaryCall; + embeddingTasksPredict( + argument: _caikit_runtime_Nlp_EmbeddingTasksRequest, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_EmbeddingResults__Output> + ): grpc.ClientUnaryCall; + embeddingTasksPredict( + argument: _caikit_runtime_Nlp_EmbeddingTasksRequest, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_EmbeddingResults__Output> + ): grpc.ClientUnaryCall; + + RerankTaskPredict( + argument: _caikit_runtime_Nlp_RerankTaskRequest, + metadata: grpc.Metadata, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_RerankResult__Output> + ): grpc.ClientUnaryCall; + RerankTaskPredict( + argument: _caikit_runtime_Nlp_RerankTaskRequest, + metadata: grpc.Metadata, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_RerankResult__Output> + ): grpc.ClientUnaryCall; + RerankTaskPredict( + argument: _caikit_runtime_Nlp_RerankTaskRequest, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_RerankResult__Output> + ): grpc.ClientUnaryCall; + RerankTaskPredict( + argument: _caikit_runtime_Nlp_RerankTaskRequest, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_RerankResult__Output> + ): grpc.ClientUnaryCall; + rerankTaskPredict( + argument: _caikit_runtime_Nlp_RerankTaskRequest, + metadata: grpc.Metadata, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_RerankResult__Output> + ): grpc.ClientUnaryCall; + rerankTaskPredict( + argument: _caikit_runtime_Nlp_RerankTaskRequest, + metadata: grpc.Metadata, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_RerankResult__Output> + ): grpc.ClientUnaryCall; + rerankTaskPredict( + argument: _caikit_runtime_Nlp_RerankTaskRequest, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_RerankResult__Output> + ): grpc.ClientUnaryCall; + rerankTaskPredict( + argument: _caikit_runtime_Nlp_RerankTaskRequest, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_RerankResult__Output> + ): grpc.ClientUnaryCall; + + RerankTasksPredict( + argument: _caikit_runtime_Nlp_RerankTasksRequest, + metadata: grpc.Metadata, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_RerankResults__Output> + ): grpc.ClientUnaryCall; + RerankTasksPredict( + argument: _caikit_runtime_Nlp_RerankTasksRequest, + metadata: grpc.Metadata, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_RerankResults__Output> + ): grpc.ClientUnaryCall; + RerankTasksPredict( + argument: _caikit_runtime_Nlp_RerankTasksRequest, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_RerankResults__Output> + ): grpc.ClientUnaryCall; + RerankTasksPredict( + argument: _caikit_runtime_Nlp_RerankTasksRequest, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_RerankResults__Output> + ): grpc.ClientUnaryCall; + rerankTasksPredict( + argument: _caikit_runtime_Nlp_RerankTasksRequest, + metadata: grpc.Metadata, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_RerankResults__Output> + ): grpc.ClientUnaryCall; + rerankTasksPredict( + argument: _caikit_runtime_Nlp_RerankTasksRequest, + metadata: grpc.Metadata, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_RerankResults__Output> + ): grpc.ClientUnaryCall; + rerankTasksPredict( + argument: _caikit_runtime_Nlp_RerankTasksRequest, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_RerankResults__Output> + ): grpc.ClientUnaryCall; + rerankTasksPredict( + argument: _caikit_runtime_Nlp_RerankTasksRequest, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_RerankResults__Output> + ): grpc.ClientUnaryCall; + + SentenceSimilarityTaskPredict( + argument: _caikit_runtime_Nlp_SentenceSimilarityTaskRequest, + metadata: grpc.Metadata, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_SentenceSimilarityResult__Output> + ): grpc.ClientUnaryCall; + SentenceSimilarityTaskPredict( + argument: _caikit_runtime_Nlp_SentenceSimilarityTaskRequest, + metadata: grpc.Metadata, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_SentenceSimilarityResult__Output> + ): grpc.ClientUnaryCall; + SentenceSimilarityTaskPredict( + argument: _caikit_runtime_Nlp_SentenceSimilarityTaskRequest, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_SentenceSimilarityResult__Output> + ): grpc.ClientUnaryCall; + SentenceSimilarityTaskPredict( + argument: _caikit_runtime_Nlp_SentenceSimilarityTaskRequest, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_SentenceSimilarityResult__Output> + ): grpc.ClientUnaryCall; + sentenceSimilarityTaskPredict( + argument: _caikit_runtime_Nlp_SentenceSimilarityTaskRequest, + metadata: grpc.Metadata, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_SentenceSimilarityResult__Output> + ): grpc.ClientUnaryCall; + sentenceSimilarityTaskPredict( + argument: _caikit_runtime_Nlp_SentenceSimilarityTaskRequest, + metadata: grpc.Metadata, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_SentenceSimilarityResult__Output> + ): grpc.ClientUnaryCall; + sentenceSimilarityTaskPredict( + argument: _caikit_runtime_Nlp_SentenceSimilarityTaskRequest, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_SentenceSimilarityResult__Output> + ): grpc.ClientUnaryCall; + sentenceSimilarityTaskPredict( + argument: _caikit_runtime_Nlp_SentenceSimilarityTaskRequest, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_SentenceSimilarityResult__Output> + ): grpc.ClientUnaryCall; + + SentenceSimilarityTasksPredict( + argument: _caikit_runtime_Nlp_SentenceSimilarityTasksRequest, + metadata: grpc.Metadata, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_SentenceSimilarityResults__Output> + ): grpc.ClientUnaryCall; + SentenceSimilarityTasksPredict( + argument: _caikit_runtime_Nlp_SentenceSimilarityTasksRequest, + metadata: grpc.Metadata, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_SentenceSimilarityResults__Output> + ): grpc.ClientUnaryCall; + SentenceSimilarityTasksPredict( + argument: _caikit_runtime_Nlp_SentenceSimilarityTasksRequest, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_SentenceSimilarityResults__Output> + ): grpc.ClientUnaryCall; + SentenceSimilarityTasksPredict( + argument: _caikit_runtime_Nlp_SentenceSimilarityTasksRequest, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_SentenceSimilarityResults__Output> + ): grpc.ClientUnaryCall; + sentenceSimilarityTasksPredict( + argument: _caikit_runtime_Nlp_SentenceSimilarityTasksRequest, + metadata: grpc.Metadata, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_SentenceSimilarityResults__Output> + ): grpc.ClientUnaryCall; + sentenceSimilarityTasksPredict( + argument: _caikit_runtime_Nlp_SentenceSimilarityTasksRequest, + metadata: grpc.Metadata, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_SentenceSimilarityResults__Output> + ): grpc.ClientUnaryCall; + sentenceSimilarityTasksPredict( + argument: _caikit_runtime_Nlp_SentenceSimilarityTasksRequest, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_SentenceSimilarityResults__Output> + ): grpc.ClientUnaryCall; + sentenceSimilarityTasksPredict( + argument: _caikit_runtime_Nlp_SentenceSimilarityTasksRequest, + callback: grpc.requestCallback<_caikit_data_model_caikit_nlp_SentenceSimilarityResults__Output> + ): grpc.ClientUnaryCall; + + ServerStreamingTextGenerationTaskPredict( + argument: _caikit_runtime_Nlp_ServerStreamingTextGenerationTaskRequest, + metadata: grpc.Metadata, + options?: grpc.CallOptions + ): grpc.ClientReadableStream<_caikit_data_model_nlp_GeneratedTextStreamResult__Output>; + ServerStreamingTextGenerationTaskPredict( + argument: _caikit_runtime_Nlp_ServerStreamingTextGenerationTaskRequest, + options?: grpc.CallOptions + ): grpc.ClientReadableStream<_caikit_data_model_nlp_GeneratedTextStreamResult__Output>; + serverStreamingTextGenerationTaskPredict( + argument: _caikit_runtime_Nlp_ServerStreamingTextGenerationTaskRequest, + metadata: grpc.Metadata, + options?: grpc.CallOptions + ): grpc.ClientReadableStream<_caikit_data_model_nlp_GeneratedTextStreamResult__Output>; + serverStreamingTextGenerationTaskPredict( + argument: _caikit_runtime_Nlp_ServerStreamingTextGenerationTaskRequest, + options?: grpc.CallOptions + ): grpc.ClientReadableStream<_caikit_data_model_nlp_GeneratedTextStreamResult__Output>; + + TextClassificationTaskPredict( + argument: _caikit_runtime_Nlp_TextClassificationTaskRequest, + metadata: grpc.Metadata, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_nlp_ClassificationResults__Output> + ): grpc.ClientUnaryCall; + TextClassificationTaskPredict( + argument: _caikit_runtime_Nlp_TextClassificationTaskRequest, + metadata: grpc.Metadata, + callback: grpc.requestCallback<_caikit_data_model_nlp_ClassificationResults__Output> + ): grpc.ClientUnaryCall; + TextClassificationTaskPredict( + argument: _caikit_runtime_Nlp_TextClassificationTaskRequest, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_nlp_ClassificationResults__Output> + ): grpc.ClientUnaryCall; + TextClassificationTaskPredict( + argument: _caikit_runtime_Nlp_TextClassificationTaskRequest, + callback: grpc.requestCallback<_caikit_data_model_nlp_ClassificationResults__Output> + ): grpc.ClientUnaryCall; + textClassificationTaskPredict( + argument: _caikit_runtime_Nlp_TextClassificationTaskRequest, + metadata: grpc.Metadata, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_nlp_ClassificationResults__Output> + ): grpc.ClientUnaryCall; + textClassificationTaskPredict( + argument: _caikit_runtime_Nlp_TextClassificationTaskRequest, + metadata: grpc.Metadata, + callback: grpc.requestCallback<_caikit_data_model_nlp_ClassificationResults__Output> + ): grpc.ClientUnaryCall; + textClassificationTaskPredict( + argument: _caikit_runtime_Nlp_TextClassificationTaskRequest, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_nlp_ClassificationResults__Output> + ): grpc.ClientUnaryCall; + textClassificationTaskPredict( + argument: _caikit_runtime_Nlp_TextClassificationTaskRequest, + callback: grpc.requestCallback<_caikit_data_model_nlp_ClassificationResults__Output> + ): grpc.ClientUnaryCall; + + TextGenerationTaskPredict( + argument: _caikit_runtime_Nlp_TextGenerationTaskRequest, + metadata: grpc.Metadata, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_nlp_GeneratedTextResult__Output> + ): grpc.ClientUnaryCall; + TextGenerationTaskPredict( + argument: _caikit_runtime_Nlp_TextGenerationTaskRequest, + metadata: grpc.Metadata, + callback: grpc.requestCallback<_caikit_data_model_nlp_GeneratedTextResult__Output> + ): grpc.ClientUnaryCall; + TextGenerationTaskPredict( + argument: _caikit_runtime_Nlp_TextGenerationTaskRequest, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_nlp_GeneratedTextResult__Output> + ): grpc.ClientUnaryCall; + TextGenerationTaskPredict( + argument: _caikit_runtime_Nlp_TextGenerationTaskRequest, + callback: grpc.requestCallback<_caikit_data_model_nlp_GeneratedTextResult__Output> + ): grpc.ClientUnaryCall; + textGenerationTaskPredict( + argument: _caikit_runtime_Nlp_TextGenerationTaskRequest, + metadata: grpc.Metadata, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_nlp_GeneratedTextResult__Output> + ): grpc.ClientUnaryCall; + textGenerationTaskPredict( + argument: _caikit_runtime_Nlp_TextGenerationTaskRequest, + metadata: grpc.Metadata, + callback: grpc.requestCallback<_caikit_data_model_nlp_GeneratedTextResult__Output> + ): grpc.ClientUnaryCall; + textGenerationTaskPredict( + argument: _caikit_runtime_Nlp_TextGenerationTaskRequest, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_nlp_GeneratedTextResult__Output> + ): grpc.ClientUnaryCall; + textGenerationTaskPredict( + argument: _caikit_runtime_Nlp_TextGenerationTaskRequest, + callback: grpc.requestCallback<_caikit_data_model_nlp_GeneratedTextResult__Output> + ): grpc.ClientUnaryCall; + + TokenClassificationTaskPredict( + argument: _caikit_runtime_Nlp_TokenClassificationTaskRequest, + metadata: grpc.Metadata, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_nlp_TokenClassificationResults__Output> + ): grpc.ClientUnaryCall; + TokenClassificationTaskPredict( + argument: _caikit_runtime_Nlp_TokenClassificationTaskRequest, + metadata: grpc.Metadata, + callback: grpc.requestCallback<_caikit_data_model_nlp_TokenClassificationResults__Output> + ): grpc.ClientUnaryCall; + TokenClassificationTaskPredict( + argument: _caikit_runtime_Nlp_TokenClassificationTaskRequest, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_nlp_TokenClassificationResults__Output> + ): grpc.ClientUnaryCall; + TokenClassificationTaskPredict( + argument: _caikit_runtime_Nlp_TokenClassificationTaskRequest, + callback: grpc.requestCallback<_caikit_data_model_nlp_TokenClassificationResults__Output> + ): grpc.ClientUnaryCall; + tokenClassificationTaskPredict( + argument: _caikit_runtime_Nlp_TokenClassificationTaskRequest, + metadata: grpc.Metadata, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_nlp_TokenClassificationResults__Output> + ): grpc.ClientUnaryCall; + tokenClassificationTaskPredict( + argument: _caikit_runtime_Nlp_TokenClassificationTaskRequest, + metadata: grpc.Metadata, + callback: grpc.requestCallback<_caikit_data_model_nlp_TokenClassificationResults__Output> + ): grpc.ClientUnaryCall; + tokenClassificationTaskPredict( + argument: _caikit_runtime_Nlp_TokenClassificationTaskRequest, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_nlp_TokenClassificationResults__Output> + ): grpc.ClientUnaryCall; + tokenClassificationTaskPredict( + argument: _caikit_runtime_Nlp_TokenClassificationTaskRequest, + callback: grpc.requestCallback<_caikit_data_model_nlp_TokenClassificationResults__Output> + ): grpc.ClientUnaryCall; + + TokenizationTaskPredict( + argument: _caikit_runtime_Nlp_TokenizationTaskRequest, + metadata: grpc.Metadata, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_nlp_TokenizationResults__Output> + ): grpc.ClientUnaryCall; + TokenizationTaskPredict( + argument: _caikit_runtime_Nlp_TokenizationTaskRequest, + metadata: grpc.Metadata, + callback: grpc.requestCallback<_caikit_data_model_nlp_TokenizationResults__Output> + ): grpc.ClientUnaryCall; + TokenizationTaskPredict( + argument: _caikit_runtime_Nlp_TokenizationTaskRequest, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_nlp_TokenizationResults__Output> + ): grpc.ClientUnaryCall; + TokenizationTaskPredict( + argument: _caikit_runtime_Nlp_TokenizationTaskRequest, + callback: grpc.requestCallback<_caikit_data_model_nlp_TokenizationResults__Output> + ): grpc.ClientUnaryCall; + tokenizationTaskPredict( + argument: _caikit_runtime_Nlp_TokenizationTaskRequest, + metadata: grpc.Metadata, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_nlp_TokenizationResults__Output> + ): grpc.ClientUnaryCall; + tokenizationTaskPredict( + argument: _caikit_runtime_Nlp_TokenizationTaskRequest, + metadata: grpc.Metadata, + callback: grpc.requestCallback<_caikit_data_model_nlp_TokenizationResults__Output> + ): grpc.ClientUnaryCall; + tokenizationTaskPredict( + argument: _caikit_runtime_Nlp_TokenizationTaskRequest, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_nlp_TokenizationResults__Output> + ): grpc.ClientUnaryCall; + tokenizationTaskPredict( + argument: _caikit_runtime_Nlp_TokenizationTaskRequest, + callback: grpc.requestCallback<_caikit_data_model_nlp_TokenizationResults__Output> + ): grpc.ClientUnaryCall; +} + +export interface NlpServiceHandlers extends grpc.UntypedServiceImplementation { + BidiStreamingTokenClassificationTaskPredict: grpc.handleBidiStreamingCall< + _caikit_runtime_Nlp_BidiStreamingTokenClassificationTaskRequest__Output, + _caikit_data_model_nlp_TokenClassificationStreamResult + >; + + EmbeddingTaskPredict: grpc.handleUnaryCall< + _caikit_runtime_Nlp_EmbeddingTaskRequest__Output, + _caikit_data_model_caikit_nlp_EmbeddingResult + >; + + EmbeddingTasksPredict: grpc.handleUnaryCall< + _caikit_runtime_Nlp_EmbeddingTasksRequest__Output, + _caikit_data_model_caikit_nlp_EmbeddingResults + >; + + RerankTaskPredict: grpc.handleUnaryCall< + _caikit_runtime_Nlp_RerankTaskRequest__Output, + _caikit_data_model_caikit_nlp_RerankResult + >; + + RerankTasksPredict: grpc.handleUnaryCall< + _caikit_runtime_Nlp_RerankTasksRequest__Output, + _caikit_data_model_caikit_nlp_RerankResults + >; + + SentenceSimilarityTaskPredict: grpc.handleUnaryCall< + _caikit_runtime_Nlp_SentenceSimilarityTaskRequest__Output, + _caikit_data_model_caikit_nlp_SentenceSimilarityResult + >; + + SentenceSimilarityTasksPredict: grpc.handleUnaryCall< + _caikit_runtime_Nlp_SentenceSimilarityTasksRequest__Output, + _caikit_data_model_caikit_nlp_SentenceSimilarityResults + >; + + ServerStreamingTextGenerationTaskPredict: grpc.handleServerStreamingCall< + _caikit_runtime_Nlp_ServerStreamingTextGenerationTaskRequest__Output, + _caikit_data_model_nlp_GeneratedTextStreamResult + >; + + TextClassificationTaskPredict: grpc.handleUnaryCall< + _caikit_runtime_Nlp_TextClassificationTaskRequest__Output, + _caikit_data_model_nlp_ClassificationResults + >; + + TextGenerationTaskPredict: grpc.handleUnaryCall< + _caikit_runtime_Nlp_TextGenerationTaskRequest__Output, + _caikit_data_model_nlp_GeneratedTextResult + >; + + TokenClassificationTaskPredict: grpc.handleUnaryCall< + _caikit_runtime_Nlp_TokenClassificationTaskRequest__Output, + _caikit_data_model_nlp_TokenClassificationResults + >; + + TokenizationTaskPredict: grpc.handleUnaryCall< + _caikit_runtime_Nlp_TokenizationTaskRequest__Output, + _caikit_data_model_nlp_TokenizationResults + >; +} + +export interface NlpServiceDefinition extends grpc.ServiceDefinition { + BidiStreamingTokenClassificationTaskPredict: MethodDefinition< + _caikit_runtime_Nlp_BidiStreamingTokenClassificationTaskRequest, + _caikit_data_model_nlp_TokenClassificationStreamResult, + _caikit_runtime_Nlp_BidiStreamingTokenClassificationTaskRequest__Output, + _caikit_data_model_nlp_TokenClassificationStreamResult__Output + >; + EmbeddingTaskPredict: MethodDefinition< + _caikit_runtime_Nlp_EmbeddingTaskRequest, + _caikit_data_model_caikit_nlp_EmbeddingResult, + _caikit_runtime_Nlp_EmbeddingTaskRequest__Output, + _caikit_data_model_caikit_nlp_EmbeddingResult__Output + >; + EmbeddingTasksPredict: MethodDefinition< + _caikit_runtime_Nlp_EmbeddingTasksRequest, + _caikit_data_model_caikit_nlp_EmbeddingResults, + _caikit_runtime_Nlp_EmbeddingTasksRequest__Output, + _caikit_data_model_caikit_nlp_EmbeddingResults__Output + >; + RerankTaskPredict: MethodDefinition< + _caikit_runtime_Nlp_RerankTaskRequest, + _caikit_data_model_caikit_nlp_RerankResult, + _caikit_runtime_Nlp_RerankTaskRequest__Output, + _caikit_data_model_caikit_nlp_RerankResult__Output + >; + RerankTasksPredict: MethodDefinition< + _caikit_runtime_Nlp_RerankTasksRequest, + _caikit_data_model_caikit_nlp_RerankResults, + _caikit_runtime_Nlp_RerankTasksRequest__Output, + _caikit_data_model_caikit_nlp_RerankResults__Output + >; + SentenceSimilarityTaskPredict: MethodDefinition< + _caikit_runtime_Nlp_SentenceSimilarityTaskRequest, + _caikit_data_model_caikit_nlp_SentenceSimilarityResult, + _caikit_runtime_Nlp_SentenceSimilarityTaskRequest__Output, + _caikit_data_model_caikit_nlp_SentenceSimilarityResult__Output + >; + SentenceSimilarityTasksPredict: MethodDefinition< + _caikit_runtime_Nlp_SentenceSimilarityTasksRequest, + _caikit_data_model_caikit_nlp_SentenceSimilarityResults, + _caikit_runtime_Nlp_SentenceSimilarityTasksRequest__Output, + _caikit_data_model_caikit_nlp_SentenceSimilarityResults__Output + >; + ServerStreamingTextGenerationTaskPredict: MethodDefinition< + _caikit_runtime_Nlp_ServerStreamingTextGenerationTaskRequest, + _caikit_data_model_nlp_GeneratedTextStreamResult, + _caikit_runtime_Nlp_ServerStreamingTextGenerationTaskRequest__Output, + _caikit_data_model_nlp_GeneratedTextStreamResult__Output + >; + TextClassificationTaskPredict: MethodDefinition< + _caikit_runtime_Nlp_TextClassificationTaskRequest, + _caikit_data_model_nlp_ClassificationResults, + _caikit_runtime_Nlp_TextClassificationTaskRequest__Output, + _caikit_data_model_nlp_ClassificationResults__Output + >; + TextGenerationTaskPredict: MethodDefinition< + _caikit_runtime_Nlp_TextGenerationTaskRequest, + _caikit_data_model_nlp_GeneratedTextResult, + _caikit_runtime_Nlp_TextGenerationTaskRequest__Output, + _caikit_data_model_nlp_GeneratedTextResult__Output + >; + TokenClassificationTaskPredict: MethodDefinition< + _caikit_runtime_Nlp_TokenClassificationTaskRequest, + _caikit_data_model_nlp_TokenClassificationResults, + _caikit_runtime_Nlp_TokenClassificationTaskRequest__Output, + _caikit_data_model_nlp_TokenClassificationResults__Output + >; + TokenizationTaskPredict: MethodDefinition< + _caikit_runtime_Nlp_TokenizationTaskRequest, + _caikit_data_model_nlp_TokenizationResults, + _caikit_runtime_Nlp_TokenizationTaskRequest__Output, + _caikit_data_model_nlp_TokenizationResults__Output + >; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/NlpTrainingService.ts b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/NlpTrainingService.ts new file mode 100644 index 0000000..40b6723 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/NlpTrainingService.ts @@ -0,0 +1,143 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_runtime_Nlp.proto + +import type * as grpc from '@grpc/grpc-js'; +import type { MethodDefinition } from '@grpc/proto-loader'; +import type { + TextGenerationTaskPeftPromptTuningTrainRequest as _caikit_runtime_Nlp_TextGenerationTaskPeftPromptTuningTrainRequest, + TextGenerationTaskPeftPromptTuningTrainRequest__Output as _caikit_runtime_Nlp_TextGenerationTaskPeftPromptTuningTrainRequest__Output +} from './TextGenerationTaskPeftPromptTuningTrainRequest'; +import type { + TextGenerationTaskTextGenerationTrainRequest as _caikit_runtime_Nlp_TextGenerationTaskTextGenerationTrainRequest, + TextGenerationTaskTextGenerationTrainRequest__Output as _caikit_runtime_Nlp_TextGenerationTaskTextGenerationTrainRequest__Output +} from './TextGenerationTaskTextGenerationTrainRequest'; +import type { + TrainingJob as _caikit_data_model_runtime_TrainingJob, + TrainingJob__Output as _caikit_data_model_runtime_TrainingJob__Output +} from '../../../caikit_data_model/runtime/TrainingJob'; + +export interface NlpTrainingServiceClient extends grpc.Client { + TextGenerationTaskPeftPromptTuningTrain( + argument: _caikit_runtime_Nlp_TextGenerationTaskPeftPromptTuningTrainRequest, + metadata: grpc.Metadata, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_runtime_TrainingJob__Output> + ): grpc.ClientUnaryCall; + TextGenerationTaskPeftPromptTuningTrain( + argument: _caikit_runtime_Nlp_TextGenerationTaskPeftPromptTuningTrainRequest, + metadata: grpc.Metadata, + callback: grpc.requestCallback<_caikit_data_model_runtime_TrainingJob__Output> + ): grpc.ClientUnaryCall; + TextGenerationTaskPeftPromptTuningTrain( + argument: _caikit_runtime_Nlp_TextGenerationTaskPeftPromptTuningTrainRequest, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_runtime_TrainingJob__Output> + ): grpc.ClientUnaryCall; + TextGenerationTaskPeftPromptTuningTrain( + argument: _caikit_runtime_Nlp_TextGenerationTaskPeftPromptTuningTrainRequest, + callback: grpc.requestCallback<_caikit_data_model_runtime_TrainingJob__Output> + ): grpc.ClientUnaryCall; + textGenerationTaskPeftPromptTuningTrain( + argument: _caikit_runtime_Nlp_TextGenerationTaskPeftPromptTuningTrainRequest, + metadata: grpc.Metadata, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_runtime_TrainingJob__Output> + ): grpc.ClientUnaryCall; + textGenerationTaskPeftPromptTuningTrain( + argument: _caikit_runtime_Nlp_TextGenerationTaskPeftPromptTuningTrainRequest, + metadata: grpc.Metadata, + callback: grpc.requestCallback<_caikit_data_model_runtime_TrainingJob__Output> + ): grpc.ClientUnaryCall; + textGenerationTaskPeftPromptTuningTrain( + argument: _caikit_runtime_Nlp_TextGenerationTaskPeftPromptTuningTrainRequest, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_runtime_TrainingJob__Output> + ): grpc.ClientUnaryCall; + textGenerationTaskPeftPromptTuningTrain( + argument: _caikit_runtime_Nlp_TextGenerationTaskPeftPromptTuningTrainRequest, + callback: grpc.requestCallback<_caikit_data_model_runtime_TrainingJob__Output> + ): grpc.ClientUnaryCall; + + TextGenerationTaskTextGenerationTrain( + argument: _caikit_runtime_Nlp_TextGenerationTaskTextGenerationTrainRequest, + metadata: grpc.Metadata, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_runtime_TrainingJob__Output> + ): grpc.ClientUnaryCall; + TextGenerationTaskTextGenerationTrain( + argument: _caikit_runtime_Nlp_TextGenerationTaskTextGenerationTrainRequest, + metadata: grpc.Metadata, + callback: grpc.requestCallback<_caikit_data_model_runtime_TrainingJob__Output> + ): grpc.ClientUnaryCall; + TextGenerationTaskTextGenerationTrain( + argument: _caikit_runtime_Nlp_TextGenerationTaskTextGenerationTrainRequest, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_runtime_TrainingJob__Output> + ): grpc.ClientUnaryCall; + TextGenerationTaskTextGenerationTrain( + argument: _caikit_runtime_Nlp_TextGenerationTaskTextGenerationTrainRequest, + callback: grpc.requestCallback<_caikit_data_model_runtime_TrainingJob__Output> + ): grpc.ClientUnaryCall; + textGenerationTaskTextGenerationTrain( + argument: _caikit_runtime_Nlp_TextGenerationTaskTextGenerationTrainRequest, + metadata: grpc.Metadata, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_runtime_TrainingJob__Output> + ): grpc.ClientUnaryCall; + textGenerationTaskTextGenerationTrain( + argument: _caikit_runtime_Nlp_TextGenerationTaskTextGenerationTrainRequest, + metadata: grpc.Metadata, + callback: grpc.requestCallback<_caikit_data_model_runtime_TrainingJob__Output> + ): grpc.ClientUnaryCall; + textGenerationTaskTextGenerationTrain( + argument: _caikit_runtime_Nlp_TextGenerationTaskTextGenerationTrainRequest, + options: grpc.CallOptions, + callback: grpc.requestCallback<_caikit_data_model_runtime_TrainingJob__Output> + ): grpc.ClientUnaryCall; + textGenerationTaskTextGenerationTrain( + argument: _caikit_runtime_Nlp_TextGenerationTaskTextGenerationTrainRequest, + callback: grpc.requestCallback<_caikit_data_model_runtime_TrainingJob__Output> + ): grpc.ClientUnaryCall; +} + +export interface NlpTrainingServiceHandlers extends grpc.UntypedServiceImplementation { + TextGenerationTaskPeftPromptTuningTrain: grpc.handleUnaryCall< + _caikit_runtime_Nlp_TextGenerationTaskPeftPromptTuningTrainRequest__Output, + _caikit_data_model_runtime_TrainingJob + >; + + TextGenerationTaskTextGenerationTrain: grpc.handleUnaryCall< + _caikit_runtime_Nlp_TextGenerationTaskTextGenerationTrainRequest__Output, + _caikit_data_model_runtime_TrainingJob + >; +} + +export interface NlpTrainingServiceDefinition extends grpc.ServiceDefinition { + TextGenerationTaskPeftPromptTuningTrain: MethodDefinition< + _caikit_runtime_Nlp_TextGenerationTaskPeftPromptTuningTrainRequest, + _caikit_data_model_runtime_TrainingJob, + _caikit_runtime_Nlp_TextGenerationTaskPeftPromptTuningTrainRequest__Output, + _caikit_data_model_runtime_TrainingJob__Output + >; + TextGenerationTaskTextGenerationTrain: MethodDefinition< + _caikit_runtime_Nlp_TextGenerationTaskTextGenerationTrainRequest, + _caikit_data_model_runtime_TrainingJob, + _caikit_runtime_Nlp_TextGenerationTaskTextGenerationTrainRequest__Output, + _caikit_data_model_runtime_TrainingJob__Output + >; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/RerankTaskRequest.ts b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/RerankTaskRequest.ts new file mode 100644 index 0000000..ef76366 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/RerankTaskRequest.ts @@ -0,0 +1,50 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_runtime_Nlp.proto + +import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../google/protobuf/Struct'; +import type { Long } from '@grpc/proto-loader'; + +export interface RerankTaskRequest { + 'query'?: (string); + 'documents'?: (_google_protobuf_Struct)[]; + 'top_n'?: (number | string | Long); + 'truncate_input_tokens'?: (number | string | Long); + 'return_documents'?: (boolean); + 'return_query'?: (boolean); + 'return_text'?: (boolean); + '_top_n'?: "top_n"; + '_truncate_input_tokens'?: "truncate_input_tokens"; + '_return_documents'?: "return_documents"; + '_return_query'?: "return_query"; + '_return_text'?: "return_text"; +} + +export interface RerankTaskRequest__Output { + 'query': (string); + 'documents': (_google_protobuf_Struct__Output)[]; + 'top_n'?: (number); + 'truncate_input_tokens'?: (number); + 'return_documents'?: (boolean); + 'return_query'?: (boolean); + 'return_text'?: (boolean); + '_top_n': "top_n"; + '_truncate_input_tokens': "truncate_input_tokens"; + '_return_documents': "return_documents"; + '_return_query': "return_query"; + '_return_text': "return_text"; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/RerankTasksRequest.ts b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/RerankTasksRequest.ts new file mode 100644 index 0000000..ce780a6 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/RerankTasksRequest.ts @@ -0,0 +1,50 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_runtime_Nlp.proto + +import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../google/protobuf/Struct'; +import type { Long } from '@grpc/proto-loader'; + +export interface RerankTasksRequest { + 'queries'?: (string)[]; + 'documents'?: (_google_protobuf_Struct)[]; + 'top_n'?: (number | string | Long); + 'truncate_input_tokens'?: (number | string | Long); + 'return_documents'?: (boolean); + 'return_queries'?: (boolean); + 'return_text'?: (boolean); + '_top_n'?: "top_n"; + '_truncate_input_tokens'?: "truncate_input_tokens"; + '_return_documents'?: "return_documents"; + '_return_queries'?: "return_queries"; + '_return_text'?: "return_text"; +} + +export interface RerankTasksRequest__Output { + 'queries': (string)[]; + 'documents': (_google_protobuf_Struct__Output)[]; + 'top_n'?: (number); + 'truncate_input_tokens'?: (number); + 'return_documents'?: (boolean); + 'return_queries'?: (boolean); + 'return_text'?: (boolean); + '_top_n': "top_n"; + '_truncate_input_tokens': "truncate_input_tokens"; + '_return_documents': "return_documents"; + '_return_queries': "return_queries"; + '_return_text': "return_text"; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/SentenceSimilarityTaskRequest.ts b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/SentenceSimilarityTaskRequest.ts new file mode 100644 index 0000000..7926d87 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/SentenceSimilarityTaskRequest.ts @@ -0,0 +1,33 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_runtime_Nlp.proto + +import type { Long } from '@grpc/proto-loader'; + +export interface SentenceSimilarityTaskRequest { + 'source_sentence'?: (string); + 'sentences'?: (string)[]; + 'truncate_input_tokens'?: (number | string | Long); + '_truncate_input_tokens'?: "truncate_input_tokens"; +} + +export interface SentenceSimilarityTaskRequest__Output { + 'source_sentence': (string); + 'sentences': (string)[]; + 'truncate_input_tokens'?: (number); + '_truncate_input_tokens': "truncate_input_tokens"; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/SentenceSimilarityTasksRequest.ts b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/SentenceSimilarityTasksRequest.ts new file mode 100644 index 0000000..97ae70f --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/SentenceSimilarityTasksRequest.ts @@ -0,0 +1,33 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_runtime_Nlp.proto + +import type { Long } from '@grpc/proto-loader'; + +export interface SentenceSimilarityTasksRequest { + 'source_sentences'?: (string)[]; + 'sentences'?: (string)[]; + 'truncate_input_tokens'?: (number | string | Long); + '_truncate_input_tokens'?: "truncate_input_tokens"; +} + +export interface SentenceSimilarityTasksRequest__Output { + 'source_sentences': (string)[]; + 'sentences': (string)[]; + 'truncate_input_tokens'?: (number); + '_truncate_input_tokens': "truncate_input_tokens"; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/ServerStreamingTextGenerationTaskRequest.ts b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/ServerStreamingTextGenerationTaskRequest.ts new file mode 100644 index 0000000..9fd2494 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/ServerStreamingTextGenerationTaskRequest.ts @@ -0,0 +1,82 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_runtime_Nlp.proto + +import type { ExponentialDecayLengthPenalty as _caikit_data_model_caikit_nlp_ExponentialDecayLengthPenalty, ExponentialDecayLengthPenalty__Output as _caikit_data_model_caikit_nlp_ExponentialDecayLengthPenalty__Output } from '../../../caikit_data_model/caikit_nlp/ExponentialDecayLengthPenalty'; +import type { Long } from '@grpc/proto-loader'; + +export interface ServerStreamingTextGenerationTaskRequest { + 'text'?: (string); + 'max_new_tokens'?: (number | string | Long); + 'min_new_tokens'?: (number | string | Long); + 'truncate_input_tokens'?: (number | string | Long); + 'decoding_method'?: (string); + 'top_k'?: (number | string | Long); + 'top_p'?: (number | string); + 'typical_p'?: (number | string); + 'temperature'?: (number | string); + 'repetition_penalty'?: (number | string); + 'max_time'?: (number | string); + 'exponential_decay_length_penalty'?: (_caikit_data_model_caikit_nlp_ExponentialDecayLengthPenalty | null); + 'stop_sequences'?: (string)[]; + 'seed'?: (number | string | Long); + 'preserve_input_text'?: (boolean); + '_max_new_tokens'?: "max_new_tokens"; + '_min_new_tokens'?: "min_new_tokens"; + '_truncate_input_tokens'?: "truncate_input_tokens"; + '_decoding_method'?: "decoding_method"; + '_top_k'?: "top_k"; + '_top_p'?: "top_p"; + '_typical_p'?: "typical_p"; + '_temperature'?: "temperature"; + '_repetition_penalty'?: "repetition_penalty"; + '_max_time'?: "max_time"; + '_exponential_decay_length_penalty'?: "exponential_decay_length_penalty"; + '_seed'?: "seed"; + '_preserve_input_text'?: "preserve_input_text"; +} + +export interface ServerStreamingTextGenerationTaskRequest__Output { + 'text': (string); + 'max_new_tokens'?: (number); + 'min_new_tokens'?: (number); + 'truncate_input_tokens'?: (number); + 'decoding_method'?: (string); + 'top_k'?: (number); + 'top_p'?: (number); + 'typical_p'?: (number); + 'temperature'?: (number); + 'repetition_penalty'?: (number); + 'max_time'?: (number); + 'exponential_decay_length_penalty'?: (_caikit_data_model_caikit_nlp_ExponentialDecayLengthPenalty__Output | null); + 'stop_sequences': (string)[]; + 'seed'?: (number); + 'preserve_input_text'?: (boolean); + '_max_new_tokens': "max_new_tokens"; + '_min_new_tokens': "min_new_tokens"; + '_truncate_input_tokens': "truncate_input_tokens"; + '_decoding_method': "decoding_method"; + '_top_k': "top_k"; + '_top_p': "top_p"; + '_typical_p': "typical_p"; + '_temperature': "temperature"; + '_repetition_penalty': "repetition_penalty"; + '_max_time': "max_time"; + '_exponential_decay_length_penalty': "exponential_decay_length_penalty"; + '_seed': "seed"; + '_preserve_input_text': "preserve_input_text"; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/TextClassificationTaskRequest.ts b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/TextClassificationTaskRequest.ts new file mode 100644 index 0000000..c898b13 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/TextClassificationTaskRequest.ts @@ -0,0 +1,26 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_runtime_Nlp.proto + + +export interface TextClassificationTaskRequest { + 'text'?: (string); +} + +export interface TextClassificationTaskRequest__Output { + 'text': (string); +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/TextGenerationTaskPeftPromptTuningTrainParameters.ts b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/TextGenerationTaskPeftPromptTuningTrainParameters.ts new file mode 100644 index 0000000..681343d --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/TextGenerationTaskPeftPromptTuningTrainParameters.ts @@ -0,0 +1,91 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_runtime_Nlp.proto + +import type { + DataStreamSourceGenerationTrainRecord as _caikit_runtime_Nlp_DataStreamSourceGenerationTrainRecord, + DataStreamSourceGenerationTrainRecord__Output as _caikit_runtime_Nlp_DataStreamSourceGenerationTrainRecord__Output +} from './DataStreamSourceGenerationTrainRecord'; +import type { + TuningConfig as _caikit_data_model_caikit_nlp_TuningConfig, + TuningConfig__Output as _caikit_data_model_caikit_nlp_TuningConfig__Output +} from '../../../caikit_data_model/caikit_nlp/TuningConfig'; +import type { Long } from '@grpc/proto-loader'; + +export interface TextGenerationTaskPeftPromptTuningTrainParameters { + base_model?: string; + train_stream?: _caikit_runtime_Nlp_DataStreamSourceGenerationTrainRecord | null; + tuning_config?: _caikit_data_model_caikit_nlp_TuningConfig | null; + val_stream?: _caikit_runtime_Nlp_DataStreamSourceGenerationTrainRecord | null; + device?: string; + tuning_type?: string; + num_epochs?: number | string | Long; + learning_rate?: number | string; + verbalizer?: string; + batch_size?: number | string | Long; + max_source_length?: number | string | Long; + max_target_length?: number | string | Long; + accumulate_steps?: number | string | Long; + torch_dtype?: string; + silence_progress_bars?: boolean; + seed?: number | string | Long; + _val_stream?: 'val_stream'; + _device?: 'device'; + _tuning_type?: 'tuning_type'; + _num_epochs?: 'num_epochs'; + _learning_rate?: 'learning_rate'; + _verbalizer?: 'verbalizer'; + _batch_size?: 'batch_size'; + _max_source_length?: 'max_source_length'; + _max_target_length?: 'max_target_length'; + _accumulate_steps?: 'accumulate_steps'; + _torch_dtype?: 'torch_dtype'; + _silence_progress_bars?: 'silence_progress_bars'; + _seed?: 'seed'; +} + +export interface TextGenerationTaskPeftPromptTuningTrainParameters__Output { + base_model: string; + train_stream: _caikit_runtime_Nlp_DataStreamSourceGenerationTrainRecord__Output | null; + tuning_config: _caikit_data_model_caikit_nlp_TuningConfig__Output | null; + val_stream?: _caikit_runtime_Nlp_DataStreamSourceGenerationTrainRecord__Output | null; + device?: string; + tuning_type?: string; + num_epochs?: number; + learning_rate?: number; + verbalizer?: string; + batch_size?: number; + max_source_length?: number; + max_target_length?: number; + accumulate_steps?: number; + torch_dtype?: string; + silence_progress_bars?: boolean; + seed?: number; + _val_stream: 'val_stream'; + _device: 'device'; + _tuning_type: 'tuning_type'; + _num_epochs: 'num_epochs'; + _learning_rate: 'learning_rate'; + _verbalizer: 'verbalizer'; + _batch_size: 'batch_size'; + _max_source_length: 'max_source_length'; + _max_target_length: 'max_target_length'; + _accumulate_steps: 'accumulate_steps'; + _torch_dtype: 'torch_dtype'; + _silence_progress_bars: 'silence_progress_bars'; + _seed: 'seed'; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/TextGenerationTaskPeftPromptTuningTrainRequest.ts b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/TextGenerationTaskPeftPromptTuningTrainRequest.ts new file mode 100644 index 0000000..783de41 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/TextGenerationTaskPeftPromptTuningTrainRequest.ts @@ -0,0 +1,38 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_runtime_Nlp.proto + +import type { + S3Path as _caikit_data_model_common_S3Path, + S3Path__Output as _caikit_data_model_common_S3Path__Output +} from '../../../caikit_data_model/common/S3Path'; +import type { + TextGenerationTaskPeftPromptTuningTrainParameters as _caikit_runtime_Nlp_TextGenerationTaskPeftPromptTuningTrainParameters, + TextGenerationTaskPeftPromptTuningTrainParameters__Output as _caikit_runtime_Nlp_TextGenerationTaskPeftPromptTuningTrainParameters__Output +} from './TextGenerationTaskPeftPromptTuningTrainParameters'; + +export interface TextGenerationTaskPeftPromptTuningTrainRequest { + model_name?: string; + output_path?: _caikit_data_model_common_S3Path | null; + parameters?: _caikit_runtime_Nlp_TextGenerationTaskPeftPromptTuningTrainParameters | null; +} + +export interface TextGenerationTaskPeftPromptTuningTrainRequest__Output { + model_name: string; + output_path: _caikit_data_model_common_S3Path__Output | null; + parameters: _caikit_runtime_Nlp_TextGenerationTaskPeftPromptTuningTrainParameters__Output | null; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/TextGenerationTaskRequest.ts b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/TextGenerationTaskRequest.ts new file mode 100644 index 0000000..41f7efd --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/TextGenerationTaskRequest.ts @@ -0,0 +1,82 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_runtime_Nlp.proto + +import type { ExponentialDecayLengthPenalty as _caikit_data_model_caikit_nlp_ExponentialDecayLengthPenalty, ExponentialDecayLengthPenalty__Output as _caikit_data_model_caikit_nlp_ExponentialDecayLengthPenalty__Output } from '../../../caikit_data_model/caikit_nlp/ExponentialDecayLengthPenalty'; +import type { Long } from '@grpc/proto-loader'; + +export interface TextGenerationTaskRequest { + 'text'?: (string); + 'max_new_tokens'?: (number | string | Long); + 'min_new_tokens'?: (number | string | Long); + 'truncate_input_tokens'?: (number | string | Long); + 'decoding_method'?: (string); + 'top_k'?: (number | string | Long); + 'top_p'?: (number | string); + 'typical_p'?: (number | string); + 'temperature'?: (number | string); + 'repetition_penalty'?: (number | string); + 'max_time'?: (number | string); + 'exponential_decay_length_penalty'?: (_caikit_data_model_caikit_nlp_ExponentialDecayLengthPenalty | null); + 'stop_sequences'?: (string)[]; + 'seed'?: (number | string | Long); + 'preserve_input_text'?: (boolean); + '_max_new_tokens'?: "max_new_tokens"; + '_min_new_tokens'?: "min_new_tokens"; + '_truncate_input_tokens'?: "truncate_input_tokens"; + '_decoding_method'?: "decoding_method"; + '_top_k'?: "top_k"; + '_top_p'?: "top_p"; + '_typical_p'?: "typical_p"; + '_temperature'?: "temperature"; + '_repetition_penalty'?: "repetition_penalty"; + '_max_time'?: "max_time"; + '_exponential_decay_length_penalty'?: "exponential_decay_length_penalty"; + '_seed'?: "seed"; + '_preserve_input_text'?: "preserve_input_text"; +} + +export interface TextGenerationTaskRequest__Output { + 'text': (string); + 'max_new_tokens'?: (number); + 'min_new_tokens'?: (number); + 'truncate_input_tokens'?: (number); + 'decoding_method'?: (string); + 'top_k'?: (number); + 'top_p'?: (number); + 'typical_p'?: (number); + 'temperature'?: (number); + 'repetition_penalty'?: (number); + 'max_time'?: (number); + 'exponential_decay_length_penalty'?: (_caikit_data_model_caikit_nlp_ExponentialDecayLengthPenalty__Output | null); + 'stop_sequences': (string)[]; + 'seed'?: (number); + 'preserve_input_text'?: (boolean); + '_max_new_tokens': "max_new_tokens"; + '_min_new_tokens': "min_new_tokens"; + '_truncate_input_tokens': "truncate_input_tokens"; + '_decoding_method': "decoding_method"; + '_top_k': "top_k"; + '_top_p': "top_p"; + '_typical_p': "typical_p"; + '_temperature': "temperature"; + '_repetition_penalty': "repetition_penalty"; + '_max_time': "max_time"; + '_exponential_decay_length_penalty': "exponential_decay_length_penalty"; + '_seed': "seed"; + '_preserve_input_text': "preserve_input_text"; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/TextGenerationTaskTextGenerationTrainParameters.ts b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/TextGenerationTaskTextGenerationTrainParameters.ts new file mode 100644 index 0000000..68b1bdb --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/TextGenerationTaskTextGenerationTrainParameters.ts @@ -0,0 +1,69 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_runtime_Nlp.proto + +import type { + DataStreamSourceGenerationTrainRecord as _caikit_runtime_Nlp_DataStreamSourceGenerationTrainRecord, + DataStreamSourceGenerationTrainRecord__Output as _caikit_runtime_Nlp_DataStreamSourceGenerationTrainRecord__Output +} from './DataStreamSourceGenerationTrainRecord'; +import type { Long } from '@grpc/proto-loader'; + +export interface TextGenerationTaskTextGenerationTrainParameters { + base_model?: string; + train_stream?: _caikit_runtime_Nlp_DataStreamSourceGenerationTrainRecord | null; + torch_dtype?: string; + max_source_length?: number | string | Long; + max_target_length?: number | string | Long; + batch_size?: number | string | Long; + num_epochs?: number | string | Long; + accumulate_steps?: number | string | Long; + random_seed?: number | string | Long; + lr?: number | string; + use_iterable_dataset?: boolean; + _torch_dtype?: 'torch_dtype'; + _max_source_length?: 'max_source_length'; + _max_target_length?: 'max_target_length'; + _batch_size?: 'batch_size'; + _num_epochs?: 'num_epochs'; + _accumulate_steps?: 'accumulate_steps'; + _random_seed?: 'random_seed'; + _lr?: 'lr'; + _use_iterable_dataset?: 'use_iterable_dataset'; +} + +export interface TextGenerationTaskTextGenerationTrainParameters__Output { + base_model: string; + train_stream: _caikit_runtime_Nlp_DataStreamSourceGenerationTrainRecord__Output | null; + torch_dtype?: string; + max_source_length?: number; + max_target_length?: number; + batch_size?: number; + num_epochs?: number; + accumulate_steps?: number; + random_seed?: number; + lr?: number; + use_iterable_dataset?: boolean; + _torch_dtype: 'torch_dtype'; + _max_source_length: 'max_source_length'; + _max_target_length: 'max_target_length'; + _batch_size: 'batch_size'; + _num_epochs: 'num_epochs'; + _accumulate_steps: 'accumulate_steps'; + _random_seed: 'random_seed'; + _lr: 'lr'; + _use_iterable_dataset: 'use_iterable_dataset'; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/TextGenerationTaskTextGenerationTrainRequest.ts b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/TextGenerationTaskTextGenerationTrainRequest.ts new file mode 100644 index 0000000..51e875b --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/TextGenerationTaskTextGenerationTrainRequest.ts @@ -0,0 +1,38 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_runtime_Nlp.proto + +import type { + S3Path as _caikit_data_model_common_S3Path, + S3Path__Output as _caikit_data_model_common_S3Path__Output +} from '../../../caikit_data_model/common/S3Path'; +import type { + TextGenerationTaskTextGenerationTrainParameters as _caikit_runtime_Nlp_TextGenerationTaskTextGenerationTrainParameters, + TextGenerationTaskTextGenerationTrainParameters__Output as _caikit_runtime_Nlp_TextGenerationTaskTextGenerationTrainParameters__Output +} from './TextGenerationTaskTextGenerationTrainParameters'; + +export interface TextGenerationTaskTextGenerationTrainRequest { + model_name?: string; + output_path?: _caikit_data_model_common_S3Path | null; + parameters?: _caikit_runtime_Nlp_TextGenerationTaskTextGenerationTrainParameters | null; +} + +export interface TextGenerationTaskTextGenerationTrainRequest__Output { + model_name: string; + output_path: _caikit_data_model_common_S3Path__Output | null; + parameters: _caikit_runtime_Nlp_TextGenerationTaskTextGenerationTrainParameters__Output | null; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/TokenClassificationTaskRequest.ts b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/TokenClassificationTaskRequest.ts new file mode 100644 index 0000000..c270d53 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/TokenClassificationTaskRequest.ts @@ -0,0 +1,30 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_runtime_Nlp.proto + + +export interface TokenClassificationTaskRequest { + 'text'?: (string); + 'threshold'?: (number | string); + '_threshold'?: "threshold"; +} + +export interface TokenClassificationTaskRequest__Output { + 'text': (string); + 'threshold'?: (number); + '_threshold': "threshold"; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/TokenizationTaskRequest.ts b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/TokenizationTaskRequest.ts new file mode 100644 index 0000000..be670ff --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/Nlp/TokenizationTaskRequest.ts @@ -0,0 +1,26 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_runtime_Nlp.proto + + +export interface TokenizationTaskRequest { + 'text'?: (string); +} + +export interface TokenizationTaskRequest__Output { + 'text': (string); +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit/runtime/info/InfoService.ts b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/info/InfoService.ts new file mode 100644 index 0000000..3bec099 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit/runtime/info/InfoService.ts @@ -0,0 +1,57 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_runtime_info.proto + +import type * as grpc from '@grpc/grpc-js' +import type { MethodDefinition } from '@grpc/proto-loader' +import type { ModelInfoRequest as _caikit_data_model_common_runtime_ModelInfoRequest, ModelInfoRequest__Output as _caikit_data_model_common_runtime_ModelInfoRequest__Output } from '../../../caikit_data_model/common/runtime/ModelInfoRequest'; +import type { ModelInfoResponse as _caikit_data_model_common_runtime_ModelInfoResponse, ModelInfoResponse__Output as _caikit_data_model_common_runtime_ModelInfoResponse__Output } from '../../../caikit_data_model/common/runtime/ModelInfoResponse'; +import type { RuntimeInfoRequest as _caikit_data_model_common_runtime_RuntimeInfoRequest, RuntimeInfoRequest__Output as _caikit_data_model_common_runtime_RuntimeInfoRequest__Output } from '../../../caikit_data_model/common/runtime/RuntimeInfoRequest'; +import type { RuntimeInfoResponse as _caikit_data_model_common_runtime_RuntimeInfoResponse, RuntimeInfoResponse__Output as _caikit_data_model_common_runtime_RuntimeInfoResponse__Output } from '../../../caikit_data_model/common/runtime/RuntimeInfoResponse'; + +export interface InfoServiceClient extends grpc.Client { + GetModelsInfo(argument: _caikit_data_model_common_runtime_ModelInfoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_caikit_data_model_common_runtime_ModelInfoResponse__Output>): grpc.ClientUnaryCall; + GetModelsInfo(argument: _caikit_data_model_common_runtime_ModelInfoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_caikit_data_model_common_runtime_ModelInfoResponse__Output>): grpc.ClientUnaryCall; + GetModelsInfo(argument: _caikit_data_model_common_runtime_ModelInfoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_caikit_data_model_common_runtime_ModelInfoResponse__Output>): grpc.ClientUnaryCall; + GetModelsInfo(argument: _caikit_data_model_common_runtime_ModelInfoRequest, callback: grpc.requestCallback<_caikit_data_model_common_runtime_ModelInfoResponse__Output>): grpc.ClientUnaryCall; + getModelsInfo(argument: _caikit_data_model_common_runtime_ModelInfoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_caikit_data_model_common_runtime_ModelInfoResponse__Output>): grpc.ClientUnaryCall; + getModelsInfo(argument: _caikit_data_model_common_runtime_ModelInfoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_caikit_data_model_common_runtime_ModelInfoResponse__Output>): grpc.ClientUnaryCall; + getModelsInfo(argument: _caikit_data_model_common_runtime_ModelInfoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_caikit_data_model_common_runtime_ModelInfoResponse__Output>): grpc.ClientUnaryCall; + getModelsInfo(argument: _caikit_data_model_common_runtime_ModelInfoRequest, callback: grpc.requestCallback<_caikit_data_model_common_runtime_ModelInfoResponse__Output>): grpc.ClientUnaryCall; + + GetRuntimeInfo(argument: _caikit_data_model_common_runtime_RuntimeInfoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_caikit_data_model_common_runtime_RuntimeInfoResponse__Output>): grpc.ClientUnaryCall; + GetRuntimeInfo(argument: _caikit_data_model_common_runtime_RuntimeInfoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_caikit_data_model_common_runtime_RuntimeInfoResponse__Output>): grpc.ClientUnaryCall; + GetRuntimeInfo(argument: _caikit_data_model_common_runtime_RuntimeInfoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_caikit_data_model_common_runtime_RuntimeInfoResponse__Output>): grpc.ClientUnaryCall; + GetRuntimeInfo(argument: _caikit_data_model_common_runtime_RuntimeInfoRequest, callback: grpc.requestCallback<_caikit_data_model_common_runtime_RuntimeInfoResponse__Output>): grpc.ClientUnaryCall; + getRuntimeInfo(argument: _caikit_data_model_common_runtime_RuntimeInfoRequest, metadata: grpc.Metadata, options: grpc.CallOptions, callback: grpc.requestCallback<_caikit_data_model_common_runtime_RuntimeInfoResponse__Output>): grpc.ClientUnaryCall; + getRuntimeInfo(argument: _caikit_data_model_common_runtime_RuntimeInfoRequest, metadata: grpc.Metadata, callback: grpc.requestCallback<_caikit_data_model_common_runtime_RuntimeInfoResponse__Output>): grpc.ClientUnaryCall; + getRuntimeInfo(argument: _caikit_data_model_common_runtime_RuntimeInfoRequest, options: grpc.CallOptions, callback: grpc.requestCallback<_caikit_data_model_common_runtime_RuntimeInfoResponse__Output>): grpc.ClientUnaryCall; + getRuntimeInfo(argument: _caikit_data_model_common_runtime_RuntimeInfoRequest, callback: grpc.requestCallback<_caikit_data_model_common_runtime_RuntimeInfoResponse__Output>): grpc.ClientUnaryCall; + +} + +export interface InfoServiceHandlers extends grpc.UntypedServiceImplementation { + GetModelsInfo: grpc.handleUnaryCall<_caikit_data_model_common_runtime_ModelInfoRequest__Output, _caikit_data_model_common_runtime_ModelInfoResponse>; + + GetRuntimeInfo: grpc.handleUnaryCall<_caikit_data_model_common_runtime_RuntimeInfoRequest__Output, _caikit_data_model_common_runtime_RuntimeInfoResponse>; + +} + +export interface InfoServiceDefinition extends grpc.ServiceDefinition { + GetModelsInfo: MethodDefinition<_caikit_data_model_common_runtime_ModelInfoRequest, _caikit_data_model_common_runtime_ModelInfoResponse, _caikit_data_model_common_runtime_ModelInfoRequest__Output, _caikit_data_model_common_runtime_ModelInfoResponse__Output> + GetRuntimeInfo: MethodDefinition<_caikit_data_model_common_runtime_RuntimeInfoRequest, _caikit_data_model_common_runtime_RuntimeInfoResponse, _caikit_data_model_common_runtime_RuntimeInfoRequest__Output, _caikit_data_model_common_runtime_RuntimeInfoResponse__Output> +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/EmbeddingResult.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/EmbeddingResult.ts new file mode 100644 index 0000000..66e7019 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/EmbeddingResult.ts @@ -0,0 +1,39 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_caikit_nlp.proto + +import type { + Vector1D as _caikit_data_model_common_Vector1D, + Vector1D__Output as _caikit_data_model_common_Vector1D__Output +} from '../common/Vector1D'; +import type { + ProducerId as _caikit_data_model_common_ProducerId, + ProducerId__Output as _caikit_data_model_common_ProducerId__Output +} from '../common/ProducerId'; +import type { Long } from '@grpc/proto-loader'; + +export interface EmbeddingResult { + result?: _caikit_data_model_common_Vector1D | null; + producer_id?: _caikit_data_model_common_ProducerId | null; + input_token_count?: number | string | Long; +} + +export interface EmbeddingResult__Output { + result: _caikit_data_model_common_Vector1D__Output | null; + producer_id: _caikit_data_model_common_ProducerId__Output | null; + input_token_count: number; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/EmbeddingResults.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/EmbeddingResults.ts new file mode 100644 index 0000000..69c689f --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/EmbeddingResults.ts @@ -0,0 +1,39 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_caikit_nlp.proto + +import type { + ListOfVector1D as _caikit_data_model_common_ListOfVector1D, + ListOfVector1D__Output as _caikit_data_model_common_ListOfVector1D__Output +} from '../common/ListOfVector1D'; +import type { + ProducerId as _caikit_data_model_common_ProducerId, + ProducerId__Output as _caikit_data_model_common_ProducerId__Output +} from '../common/ProducerId'; +import type { Long } from '@grpc/proto-loader'; + +export interface EmbeddingResults { + results?: _caikit_data_model_common_ListOfVector1D | null; + producer_id?: _caikit_data_model_common_ProducerId | null; + input_token_count?: number | string | Long; +} + +export interface EmbeddingResults__Output { + results: _caikit_data_model_common_ListOfVector1D__Output | null; + producer_id: _caikit_data_model_common_ProducerId__Output | null; + input_token_count: number; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/ExponentialDecayLengthPenalty.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/ExponentialDecayLengthPenalty.ts new file mode 100644 index 0000000..2a02b8e --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/ExponentialDecayLengthPenalty.ts @@ -0,0 +1,29 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_caikit_nlp.proto + +import type { Long } from '@grpc/proto-loader'; + +export interface ExponentialDecayLengthPenalty { + 'start_index'?: (number | string | Long); + 'decay_factor'?: (number | string); +} + +export interface ExponentialDecayLengthPenalty__Output { + 'start_index': (number); + 'decay_factor': (number); +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/GenerationTrainRecord.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/GenerationTrainRecord.ts new file mode 100644 index 0000000..6630f99 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/GenerationTrainRecord.ts @@ -0,0 +1,28 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_caikit_nlp.proto + + +export interface GenerationTrainRecord { + 'input'?: (string); + 'output'?: (string); +} + +export interface GenerationTrainRecord__Output { + 'input': (string); + 'output': (string); +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/RerankResult.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/RerankResult.ts new file mode 100644 index 0000000..917fe46 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/RerankResult.ts @@ -0,0 +1,39 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_caikit_nlp.proto + +import type { + RerankScores as _caikit_data_model_caikit_nlp_RerankScores, + RerankScores__Output as _caikit_data_model_caikit_nlp_RerankScores__Output +} from './RerankScores'; +import type { + ProducerId as _caikit_data_model_common_ProducerId, + ProducerId__Output as _caikit_data_model_common_ProducerId__Output +} from '../common/ProducerId'; +import type { Long } from '@grpc/proto-loader'; + +export interface RerankResult { + result?: _caikit_data_model_caikit_nlp_RerankScores | null; + producer_id?: _caikit_data_model_common_ProducerId | null; + input_token_count?: number | string | Long; +} + +export interface RerankResult__Output { + result: _caikit_data_model_caikit_nlp_RerankScores__Output | null; + producer_id: _caikit_data_model_common_ProducerId__Output | null; + input_token_count: number; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/RerankResults.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/RerankResults.ts new file mode 100644 index 0000000..ca890ff --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/RerankResults.ts @@ -0,0 +1,39 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_caikit_nlp.proto + +import type { + RerankScores as _caikit_data_model_caikit_nlp_RerankScores, + RerankScores__Output as _caikit_data_model_caikit_nlp_RerankScores__Output +} from './RerankScores'; +import type { + ProducerId as _caikit_data_model_common_ProducerId, + ProducerId__Output as _caikit_data_model_common_ProducerId__Output +} from '../common/ProducerId'; +import type { Long } from '@grpc/proto-loader'; + +export interface RerankResults { + results?: _caikit_data_model_caikit_nlp_RerankScores[]; + producer_id?: _caikit_data_model_common_ProducerId | null; + input_token_count?: number | string | Long; +} + +export interface RerankResults__Output { + results: _caikit_data_model_caikit_nlp_RerankScores__Output[]; + producer_id: _caikit_data_model_common_ProducerId__Output | null; + input_token_count: number; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/RerankScore.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/RerankScore.ts new file mode 100644 index 0000000..ba8f6de --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/RerankScore.ts @@ -0,0 +1,34 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_caikit_nlp.proto + +import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../google/protobuf/Struct'; +import type { Long } from '@grpc/proto-loader'; + +export interface RerankScore { + 'document'?: (_google_protobuf_Struct | null); + 'index'?: (number | string | Long); + 'score'?: (number | string); + 'text'?: (string); +} + +export interface RerankScore__Output { + 'document': (_google_protobuf_Struct__Output | null); + 'index': (number); + 'score': (number); + 'text': (string); +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/RerankScores.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/RerankScores.ts new file mode 100644 index 0000000..aa1a6b7 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/RerankScores.ts @@ -0,0 +1,32 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_caikit_nlp.proto + +import type { + RerankScore as _caikit_data_model_caikit_nlp_RerankScore, + RerankScore__Output as _caikit_data_model_caikit_nlp_RerankScore__Output +} from './RerankScore'; + +export interface RerankScores { + query?: string; + scores?: _caikit_data_model_caikit_nlp_RerankScore[]; +} + +export interface RerankScores__Output { + query: string; + scores: _caikit_data_model_caikit_nlp_RerankScore__Output[]; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/SentenceSimilarityResult.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/SentenceSimilarityResult.ts new file mode 100644 index 0000000..d91e58c --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/SentenceSimilarityResult.ts @@ -0,0 +1,39 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_caikit_nlp.proto + +import type { + SentenceSimilarityScores as _caikit_data_model_caikit_nlp_SentenceSimilarityScores, + SentenceSimilarityScores__Output as _caikit_data_model_caikit_nlp_SentenceSimilarityScores__Output +} from './SentenceSimilarityScores'; +import type { + ProducerId as _caikit_data_model_common_ProducerId, + ProducerId__Output as _caikit_data_model_common_ProducerId__Output +} from '../common/ProducerId'; +import type { Long } from '@grpc/proto-loader'; + +export interface SentenceSimilarityResult { + result?: _caikit_data_model_caikit_nlp_SentenceSimilarityScores | null; + producer_id?: _caikit_data_model_common_ProducerId | null; + input_token_count?: number | string | Long; +} + +export interface SentenceSimilarityResult__Output { + result: _caikit_data_model_caikit_nlp_SentenceSimilarityScores__Output | null; + producer_id: _caikit_data_model_common_ProducerId__Output | null; + input_token_count: number; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/SentenceSimilarityResults.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/SentenceSimilarityResults.ts new file mode 100644 index 0000000..f0e9024 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/SentenceSimilarityResults.ts @@ -0,0 +1,39 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_caikit_nlp.proto + +import type { + SentenceSimilarityScores as _caikit_data_model_caikit_nlp_SentenceSimilarityScores, + SentenceSimilarityScores__Output as _caikit_data_model_caikit_nlp_SentenceSimilarityScores__Output +} from './SentenceSimilarityScores'; +import type { + ProducerId as _caikit_data_model_common_ProducerId, + ProducerId__Output as _caikit_data_model_common_ProducerId__Output +} from '../common/ProducerId'; +import type { Long } from '@grpc/proto-loader'; + +export interface SentenceSimilarityResults { + results?: _caikit_data_model_caikit_nlp_SentenceSimilarityScores[]; + producer_id?: _caikit_data_model_common_ProducerId | null; + input_token_count?: number | string | Long; +} + +export interface SentenceSimilarityResults__Output { + results: _caikit_data_model_caikit_nlp_SentenceSimilarityScores__Output[]; + producer_id: _caikit_data_model_common_ProducerId__Output | null; + input_token_count: number; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/SentenceSimilarityScores.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/SentenceSimilarityScores.ts new file mode 100644 index 0000000..0959b61 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/SentenceSimilarityScores.ts @@ -0,0 +1,26 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_caikit_nlp.proto + + +export interface SentenceSimilarityScores { + 'scores'?: (number | string)[]; +} + +export interface SentenceSimilarityScores__Output { + 'scores': (number)[]; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/TuningConfig.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/TuningConfig.ts new file mode 100644 index 0000000..97cc7ef --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/caikit_nlp/TuningConfig.ts @@ -0,0 +1,35 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_caikit_nlp.proto + +import type { Long } from '@grpc/proto-loader'; + +export interface TuningConfig { + 'num_virtual_tokens'?: (number | string | Long); + 'prompt_tuning_init_text'?: (string); + 'prompt_tuning_init_method'?: (string); + 'prompt_tuning_init_source_model'?: (string); + 'output_model_types'?: (string)[]; +} + +export interface TuningConfig__Output { + 'num_virtual_tokens': (number); + 'prompt_tuning_init_text': (string); + 'prompt_tuning_init_method': (string); + 'prompt_tuning_init_source_model': (string); + 'output_model_types': (string)[]; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/BoolSequence.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/BoolSequence.ts new file mode 100644 index 0000000..24c8f9e --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/BoolSequence.ts @@ -0,0 +1,26 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_common.proto + + +export interface BoolSequence { + 'values'?: (boolean)[]; +} + +export interface BoolSequence__Output { + 'values': (boolean)[]; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/ConnectionInfo.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/ConnectionInfo.ts new file mode 100644 index 0000000..3aeabcd --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/ConnectionInfo.ts @@ -0,0 +1,45 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_common.proto + +import type { + ConnectionTlsInfo as _caikit_data_model_common_ConnectionTlsInfo, + ConnectionTlsInfo__Output as _caikit_data_model_common_ConnectionTlsInfo__Output +} from './ConnectionTlsInfo'; +import type { Long } from '@grpc/proto-loader'; + +export interface ConnectionInfo { + hostname?: string; + port?: number | string | Long; + tls?: _caikit_data_model_common_ConnectionTlsInfo | null; + timeout?: number | string | Long; + options?: { [key: string]: string }; + _port?: 'port'; + _tls?: 'tls'; + _timeout?: 'timeout'; +} + +export interface ConnectionInfo__Output { + hostname: string; + port?: number; + tls?: _caikit_data_model_common_ConnectionTlsInfo__Output | null; + timeout?: number; + options: { [key: string]: string }; + _port: 'port'; + _tls: 'tls'; + _timeout: 'timeout'; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/ConnectionTlsInfo.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/ConnectionTlsInfo.ts new file mode 100644 index 0000000..7982f92 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/ConnectionTlsInfo.ts @@ -0,0 +1,44 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_common.proto + + +export interface ConnectionTlsInfo { + 'enabled'?: (boolean); + 'insecure_verify'?: (boolean); + 'ca_file'?: (string); + 'cert_file'?: (string); + 'key_file'?: (string); + '_enabled'?: "enabled"; + '_insecure_verify'?: "insecure_verify"; + '_ca_file'?: "ca_file"; + '_cert_file'?: "cert_file"; + '_key_file'?: "key_file"; +} + +export interface ConnectionTlsInfo__Output { + 'enabled'?: (boolean); + 'insecure_verify'?: (boolean); + 'ca_file'?: (string); + 'cert_file'?: (string); + 'key_file'?: (string); + '_enabled': "enabled"; + '_insecure_verify': "insecure_verify"; + '_ca_file': "ca_file"; + '_cert_file': "cert_file"; + '_key_file': "key_file"; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/Directory.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/Directory.ts new file mode 100644 index 0000000..7dcaae7 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/Directory.ts @@ -0,0 +1,28 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_common.proto + + +export interface Directory { + 'dirname'?: (string); + 'extension'?: (string); +} + +export interface Directory__Output { + 'dirname': (string); + 'extension': (string); +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/File.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/File.ts new file mode 100644 index 0000000..6c3dffb --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/File.ts @@ -0,0 +1,30 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_common.proto + + +export interface File { + 'data'?: (Buffer | Uint8Array | string); + 'filename'?: (string); + 'type'?: (string); +} + +export interface File__Output { + 'data': (Buffer); + 'filename': (string); + 'type': (string); +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/FileReference.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/FileReference.ts new file mode 100644 index 0000000..e43209d --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/FileReference.ts @@ -0,0 +1,26 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_common.proto + + +export interface FileReference { + 'filename'?: (string); +} + +export interface FileReference__Output { + 'filename': (string); +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/FloatSequence.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/FloatSequence.ts new file mode 100644 index 0000000..b3b35dd --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/FloatSequence.ts @@ -0,0 +1,26 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_common.proto + + +export interface FloatSequence { + 'values'?: (number | string)[]; +} + +export interface FloatSequence__Output { + 'values': (number)[]; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/IntSequence.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/IntSequence.ts new file mode 100644 index 0000000..d82cacb --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/IntSequence.ts @@ -0,0 +1,27 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_common.proto + +import type { Long } from '@grpc/proto-loader'; + +export interface IntSequence { + 'values'?: (number | string | Long)[]; +} + +export interface IntSequence__Output { + 'values': (number)[]; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/ListOfFileReferences.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/ListOfFileReferences.ts new file mode 100644 index 0000000..4b94c7a --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/ListOfFileReferences.ts @@ -0,0 +1,26 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_common.proto + + +export interface ListOfFileReferences { + 'files'?: (string)[]; +} + +export interface ListOfFileReferences__Output { + 'files': (string)[]; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/ListOfVector1D.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/ListOfVector1D.ts new file mode 100644 index 0000000..5244ce9 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/ListOfVector1D.ts @@ -0,0 +1,30 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_common.proto + +import type { + Vector1D as _caikit_data_model_common_Vector1D, + Vector1D__Output as _caikit_data_model_common_Vector1D__Output +} from './Vector1D'; + +export interface ListOfVector1D { + vectors?: _caikit_data_model_common_Vector1D[]; +} + +export interface ListOfVector1D__Output { + vectors: _caikit_data_model_common_Vector1D__Output[]; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/NpFloat32Sequence.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/NpFloat32Sequence.ts new file mode 100644 index 0000000..d1d1faa --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/NpFloat32Sequence.ts @@ -0,0 +1,26 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_common.proto + + +export interface NpFloat32Sequence { + 'values'?: (number | string)[]; +} + +export interface NpFloat32Sequence__Output { + 'values': (number)[]; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/NpFloat64Sequence.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/NpFloat64Sequence.ts new file mode 100644 index 0000000..9b92837 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/NpFloat64Sequence.ts @@ -0,0 +1,26 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_common.proto + + +export interface NpFloat64Sequence { + 'values'?: (number | string)[]; +} + +export interface NpFloat64Sequence__Output { + 'values': (number)[]; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/ProducerId.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/ProducerId.ts new file mode 100644 index 0000000..3b60909 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/ProducerId.ts @@ -0,0 +1,28 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_common.proto + + +export interface ProducerId { + 'name'?: (string); + 'version'?: (string); +} + +export interface ProducerId__Output { + 'name': (string); + 'version': (string); +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/ProducerPriority.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/ProducerPriority.ts new file mode 100644 index 0000000..27f119e --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/ProducerPriority.ts @@ -0,0 +1,30 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_common.proto + +import type { + ProducerId as _caikit_data_model_common_ProducerId, + ProducerId__Output as _caikit_data_model_common_ProducerId__Output +} from './ProducerId'; + +export interface ProducerPriority { + producers?: _caikit_data_model_common_ProducerId[]; +} + +export interface ProducerPriority__Output { + producers: _caikit_data_model_common_ProducerId__Output[]; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/PyFloatSequence.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/PyFloatSequence.ts new file mode 100644 index 0000000..8b7a885 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/PyFloatSequence.ts @@ -0,0 +1,26 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_common.proto + + +export interface PyFloatSequence { + 'values'?: (number | string)[]; +} + +export interface PyFloatSequence__Output { + 'values': (number)[]; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/S3Base.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/S3Base.ts new file mode 100644 index 0000000..6688974 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/S3Base.ts @@ -0,0 +1,38 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_common.proto + + +export interface S3Base { + 'endpoint'?: (string); + 'region'?: (string); + 'bucket'?: (string); + 'accessKey'?: (string); + 'secretKey'?: (string); + 'IAM_id'?: (string); + 'IAM_api_key'?: (string); +} + +export interface S3Base__Output { + 'endpoint': (string); + 'region': (string); + 'bucket': (string); + 'accessKey': (string); + 'secretKey': (string); + 'IAM_id': (string); + 'IAM_api_key': (string); +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/S3Files.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/S3Files.ts new file mode 100644 index 0000000..03cf7e2 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/S3Files.ts @@ -0,0 +1,40 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_common.proto + + +export interface S3Files { + 'files'?: (string)[]; + 'endpoint'?: (string); + 'region'?: (string); + 'bucket'?: (string); + 'accessKey'?: (string); + 'secretKey'?: (string); + 'IAM_id'?: (string); + 'IAM_api_key'?: (string); +} + +export interface S3Files__Output { + 'files': (string)[]; + 'endpoint': (string); + 'region': (string); + 'bucket': (string); + 'accessKey': (string); + 'secretKey': (string); + 'IAM_id': (string); + 'IAM_api_key': (string); +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/S3Path.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/S3Path.ts new file mode 100644 index 0000000..6ddb2e8 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/S3Path.ts @@ -0,0 +1,40 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_common.proto + + +export interface S3Path { + 'path'?: (string); + 'endpoint'?: (string); + 'region'?: (string); + 'bucket'?: (string); + 'accessKey'?: (string); + 'secretKey'?: (string); + 'IAM_id'?: (string); + 'IAM_api_key'?: (string); +} + +export interface S3Path__Output { + 'path': (string); + 'endpoint': (string); + 'region': (string); + 'bucket': (string); + 'accessKey': (string); + 'secretKey': (string); + 'IAM_id': (string); + 'IAM_api_key': (string); +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/StrSequence.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/StrSequence.ts new file mode 100644 index 0000000..965e453 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/StrSequence.ts @@ -0,0 +1,26 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_common.proto + + +export interface StrSequence { + 'values'?: (string)[]; +} + +export interface StrSequence__Output { + 'values': (string)[]; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/TrainingStatus.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/TrainingStatus.ts new file mode 100644 index 0000000..3b713a3 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/TrainingStatus.ts @@ -0,0 +1,42 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_common.proto + +export const TrainingStatus = { + PLACEHOLDER_UNSET: 'PLACEHOLDER_UNSET', + QUEUED: 'QUEUED', + RUNNING: 'RUNNING', + COMPLETED: 'COMPLETED', + CANCELED: 'CANCELED', + ERRORED: 'ERRORED', +} as const; + +export type TrainingStatus = + | 'PLACEHOLDER_UNSET' + | 0 + | 'QUEUED' + | 1 + | 'RUNNING' + | 2 + | 'COMPLETED' + | 3 + | 'CANCELED' + | 4 + | 'ERRORED' + | 5 + +export type TrainingStatus__Output = typeof TrainingStatus[keyof typeof TrainingStatus] diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/Vector1D.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/Vector1D.ts new file mode 100644 index 0000000..7e8b299 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/Vector1D.ts @@ -0,0 +1,44 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_common.proto + +import type { + PyFloatSequence as _caikit_data_model_common_PyFloatSequence, + PyFloatSequence__Output as _caikit_data_model_common_PyFloatSequence__Output +} from './PyFloatSequence'; +import type { + NpFloat32Sequence as _caikit_data_model_common_NpFloat32Sequence, + NpFloat32Sequence__Output as _caikit_data_model_common_NpFloat32Sequence__Output +} from './NpFloat32Sequence'; +import type { + NpFloat64Sequence as _caikit_data_model_common_NpFloat64Sequence, + NpFloat64Sequence__Output as _caikit_data_model_common_NpFloat64Sequence__Output +} from './NpFloat64Sequence'; + +export interface Vector1D { + data_pyfloatsequence?: _caikit_data_model_common_PyFloatSequence | null; + data_npfloat32sequence?: _caikit_data_model_common_NpFloat32Sequence | null; + data_npfloat64sequence?: _caikit_data_model_common_NpFloat64Sequence | null; + data?: 'data_pyfloatsequence' | 'data_npfloat32sequence' | 'data_npfloat64sequence'; +} + +export interface Vector1D__Output { + data_pyfloatsequence?: _caikit_data_model_common_PyFloatSequence__Output | null; + data_npfloat32sequence?: _caikit_data_model_common_NpFloat32Sequence__Output | null; + data_npfloat64sequence?: _caikit_data_model_common_NpFloat64Sequence__Output | null; + data: 'data_pyfloatsequence' | 'data_npfloat32sequence' | 'data_npfloat64sequence'; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/runtime/ModelInfo.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/runtime/ModelInfo.ts new file mode 100644 index 0000000..c427419 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/runtime/ModelInfo.ts @@ -0,0 +1,40 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_common_runtime.proto + +import type { Struct as _google_protobuf_Struct, Struct__Output as _google_protobuf_Struct__Output } from '../../../google/protobuf/Struct'; +import type { Long } from '@grpc/proto-loader'; + +export interface ModelInfo { + 'model_path'?: (string); + 'name'?: (string); + 'size'?: (number | string | Long); + 'metadata'?: (_google_protobuf_Struct | null); + 'module_id'?: (string); + 'module_metadata'?: ({[key: string]: string}); + 'loaded'?: (boolean); +} + +export interface ModelInfo__Output { + 'model_path': (string); + 'name': (string); + 'size': (number); + 'metadata': (_google_protobuf_Struct__Output | null); + 'module_id': (string); + 'module_metadata': ({[key: string]: string}); + 'loaded': (boolean); +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/runtime/ModelInfoRequest.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/runtime/ModelInfoRequest.ts new file mode 100644 index 0000000..bd2aab5 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/runtime/ModelInfoRequest.ts @@ -0,0 +1,26 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_common_runtime.proto + + +export interface ModelInfoRequest { + 'model_ids'?: (string)[]; +} + +export interface ModelInfoRequest__Output { + 'model_ids': (string)[]; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/runtime/ModelInfoResponse.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/runtime/ModelInfoResponse.ts new file mode 100644 index 0000000..609ccd7 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/runtime/ModelInfoResponse.ts @@ -0,0 +1,30 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_common_runtime.proto + +import type { + ModelInfo as _caikit_data_model_common_runtime_ModelInfo, + ModelInfo__Output as _caikit_data_model_common_runtime_ModelInfo__Output +} from './ModelInfo'; + +export interface ModelInfoResponse { + models?: _caikit_data_model_common_runtime_ModelInfo[]; +} + +export interface ModelInfoResponse__Output { + models: _caikit_data_model_common_runtime_ModelInfo__Output[]; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/runtime/RuntimeInfoRequest.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/runtime/RuntimeInfoRequest.ts new file mode 100644 index 0000000..9963f45 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/runtime/RuntimeInfoRequest.ts @@ -0,0 +1,24 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_common_runtime.proto + + +export interface RuntimeInfoRequest { +} + +export interface RuntimeInfoRequest__Output { +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/runtime/RuntimeInfoResponse.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/runtime/RuntimeInfoResponse.ts new file mode 100644 index 0000000..4a08dd0 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/common/runtime/RuntimeInfoResponse.ts @@ -0,0 +1,28 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_common_runtime.proto + + +export interface RuntimeInfoResponse { + 'runtime_version'?: (string); + 'python_packages'?: ({[key: string]: string}); +} + +export interface RuntimeInfoResponse__Output { + 'runtime_version': (string); + 'python_packages': ({[key: string]: string}); +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/ClassificationResult.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/ClassificationResult.ts new file mode 100644 index 0000000..24862c0 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/ClassificationResult.ts @@ -0,0 +1,28 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_nlp.proto + + +export interface ClassificationResult { + 'label'?: (string); + 'score'?: (number | string); +} + +export interface ClassificationResult__Output { + 'label': (string); + 'score': (number); +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/ClassificationResults.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/ClassificationResults.ts new file mode 100644 index 0000000..f3f035f --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/ClassificationResults.ts @@ -0,0 +1,30 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_nlp.proto + +import type { + ClassificationResult as _caikit_data_model_nlp_ClassificationResult, + ClassificationResult__Output as _caikit_data_model_nlp_ClassificationResult__Output +} from './ClassificationResult'; + +export interface ClassificationResults { + results?: _caikit_data_model_nlp_ClassificationResult[]; +} + +export interface ClassificationResults__Output { + results: _caikit_data_model_nlp_ClassificationResult__Output[]; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/ClassificationTrainRecord.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/ClassificationTrainRecord.ts new file mode 100644 index 0000000..585e11b --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/ClassificationTrainRecord.ts @@ -0,0 +1,28 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_nlp.proto + + +export interface ClassificationTrainRecord { + 'text'?: (string); + 'labels'?: (string)[]; +} + +export interface ClassificationTrainRecord__Output { + 'text': (string); + 'labels': (string)[]; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/ClassifiedGeneratedTextResult.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/ClassifiedGeneratedTextResult.ts new file mode 100644 index 0000000..fd47044 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/ClassifiedGeneratedTextResult.ts @@ -0,0 +1,59 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_nlp.proto + +import type { + TextGenTokenClassificationResults as _caikit_data_model_nlp_TextGenTokenClassificationResults, + TextGenTokenClassificationResults__Output as _caikit_data_model_nlp_TextGenTokenClassificationResults__Output +} from './TextGenTokenClassificationResults'; +import type { + FinishReason as _caikit_data_model_nlp_FinishReason, + FinishReason__Output as _caikit_data_model_nlp_FinishReason__Output +} from './FinishReason'; +import type { + InputWarning as _caikit_data_model_nlp_InputWarning, + InputWarning__Output as _caikit_data_model_nlp_InputWarning__Output +} from './InputWarning'; +import type { + GeneratedToken as _caikit_data_model_nlp_GeneratedToken, + GeneratedToken__Output as _caikit_data_model_nlp_GeneratedToken__Output +} from './GeneratedToken'; +import type { Long } from '@grpc/proto-loader'; + +export interface ClassifiedGeneratedTextResult { + generated_text?: string; + token_classification_results?: _caikit_data_model_nlp_TextGenTokenClassificationResults | null; + finish_reason?: _caikit_data_model_nlp_FinishReason; + generated_token_count?: number | string | Long; + seed?: number | string | Long; + input_token_count?: number | string | Long; + warnings?: _caikit_data_model_nlp_InputWarning[]; + tokens?: _caikit_data_model_nlp_GeneratedToken[]; + input_tokens?: _caikit_data_model_nlp_GeneratedToken[]; +} + +export interface ClassifiedGeneratedTextResult__Output { + generated_text: string; + token_classification_results: _caikit_data_model_nlp_TextGenTokenClassificationResults__Output | null; + finish_reason: _caikit_data_model_nlp_FinishReason__Output; + generated_token_count: number; + seed: number; + input_token_count: number; + warnings: _caikit_data_model_nlp_InputWarning__Output[]; + tokens: _caikit_data_model_nlp_GeneratedToken__Output[]; + input_tokens: _caikit_data_model_nlp_GeneratedToken__Output[]; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/ClassifiedGeneratedTextStreamResult.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/ClassifiedGeneratedTextStreamResult.ts new file mode 100644 index 0000000..0003c9c --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/ClassifiedGeneratedTextStreamResult.ts @@ -0,0 +1,63 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_nlp.proto + +import type { + TextGenTokenClassificationResults as _caikit_data_model_nlp_TextGenTokenClassificationResults, + TextGenTokenClassificationResults__Output as _caikit_data_model_nlp_TextGenTokenClassificationResults__Output +} from './TextGenTokenClassificationResults'; +import type { + FinishReason as _caikit_data_model_nlp_FinishReason, + FinishReason__Output as _caikit_data_model_nlp_FinishReason__Output +} from './FinishReason'; +import type { + InputWarning as _caikit_data_model_nlp_InputWarning, + InputWarning__Output as _caikit_data_model_nlp_InputWarning__Output +} from './InputWarning'; +import type { + GeneratedToken as _caikit_data_model_nlp_GeneratedToken, + GeneratedToken__Output as _caikit_data_model_nlp_GeneratedToken__Output +} from './GeneratedToken'; +import type { Long } from '@grpc/proto-loader'; + +export interface ClassifiedGeneratedTextStreamResult { + generated_text?: string; + token_classification_results?: _caikit_data_model_nlp_TextGenTokenClassificationResults | null; + finish_reason?: _caikit_data_model_nlp_FinishReason; + generated_token_count?: number | string | Long; + seed?: number | string | Long; + input_token_count?: number | string | Long; + processed_index?: number | string | Long; + start_index?: number | string | Long; + warnings?: _caikit_data_model_nlp_InputWarning[]; + tokens?: _caikit_data_model_nlp_GeneratedToken[]; + input_tokens?: _caikit_data_model_nlp_GeneratedToken[]; +} + +export interface ClassifiedGeneratedTextStreamResult__Output { + generated_text: string; + token_classification_results: _caikit_data_model_nlp_TextGenTokenClassificationResults__Output | null; + finish_reason: _caikit_data_model_nlp_FinishReason__Output; + generated_token_count: number; + seed: number; + input_token_count: number; + processed_index: number; + start_index: number; + warnings: _caikit_data_model_nlp_InputWarning__Output[]; + tokens: _caikit_data_model_nlp_GeneratedToken__Output[]; + input_tokens: _caikit_data_model_nlp_GeneratedToken__Output[]; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/FinishReason.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/FinishReason.ts new file mode 100644 index 0000000..9b2ad6b --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/FinishReason.ts @@ -0,0 +1,48 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_nlp.proto + +export const FinishReason = { + NOT_FINISHED: 'NOT_FINISHED', + MAX_TOKENS: 'MAX_TOKENS', + EOS_TOKEN: 'EOS_TOKEN', + CANCELLED: 'CANCELLED', + TIME_LIMIT: 'TIME_LIMIT', + STOP_SEQUENCE: 'STOP_SEQUENCE', + TOKEN_LIMIT: 'TOKEN_LIMIT', + ERROR: 'ERROR', +} as const; + +export type FinishReason = + | 'NOT_FINISHED' + | 0 + | 'MAX_TOKENS' + | 1 + | 'EOS_TOKEN' + | 2 + | 'CANCELLED' + | 3 + | 'TIME_LIMIT' + | 4 + | 'STOP_SEQUENCE' + | 5 + | 'TOKEN_LIMIT' + | 6 + | 'ERROR' + | 7 + +export type FinishReason__Output = typeof FinishReason[keyof typeof FinishReason] diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/GeneratedTextResult.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/GeneratedTextResult.ts new file mode 100644 index 0000000..08406dd --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/GeneratedTextResult.ts @@ -0,0 +1,53 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_nlp.proto + +import type { + FinishReason as _caikit_data_model_nlp_FinishReason, + FinishReason__Output as _caikit_data_model_nlp_FinishReason__Output +} from './FinishReason'; +import type { + ProducerId as _caikit_data_model_common_ProducerId, + ProducerId__Output as _caikit_data_model_common_ProducerId__Output +} from '../common/ProducerId'; +import type { + GeneratedToken as _caikit_data_model_nlp_GeneratedToken, + GeneratedToken__Output as _caikit_data_model_nlp_GeneratedToken__Output +} from './GeneratedToken'; +import type { Long } from '@grpc/proto-loader'; + +export interface GeneratedTextResult { + generated_text?: string; + generated_tokens?: number | string | Long; + finish_reason?: _caikit_data_model_nlp_FinishReason; + producer_id?: _caikit_data_model_common_ProducerId | null; + input_token_count?: number | string | Long; + seed?: number | string | Long; + tokens?: _caikit_data_model_nlp_GeneratedToken[]; + input_tokens?: _caikit_data_model_nlp_GeneratedToken[]; +} + +export interface GeneratedTextResult__Output { + generated_text: string; + generated_tokens: number; + finish_reason: _caikit_data_model_nlp_FinishReason__Output; + producer_id: _caikit_data_model_common_ProducerId__Output | null; + input_token_count: number; + seed: number; + tokens: _caikit_data_model_nlp_GeneratedToken__Output[]; + input_tokens: _caikit_data_model_nlp_GeneratedToken__Output[]; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/GeneratedTextStreamResult.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/GeneratedTextStreamResult.ts new file mode 100644 index 0000000..ab1815e --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/GeneratedTextStreamResult.ts @@ -0,0 +1,46 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_nlp.proto + +import type { + GeneratedToken as _caikit_data_model_nlp_GeneratedToken, + GeneratedToken__Output as _caikit_data_model_nlp_GeneratedToken__Output +} from './GeneratedToken'; +import type { + TokenStreamDetails as _caikit_data_model_nlp_TokenStreamDetails, + TokenStreamDetails__Output as _caikit_data_model_nlp_TokenStreamDetails__Output +} from './TokenStreamDetails'; +import type { + ProducerId as _caikit_data_model_common_ProducerId, + ProducerId__Output as _caikit_data_model_common_ProducerId__Output +} from '../common/ProducerId'; + +export interface GeneratedTextStreamResult { + generated_text?: string; + tokens?: _caikit_data_model_nlp_GeneratedToken[]; + details?: _caikit_data_model_nlp_TokenStreamDetails | null; + producer_id?: _caikit_data_model_common_ProducerId | null; + input_tokens?: _caikit_data_model_nlp_GeneratedToken[]; +} + +export interface GeneratedTextStreamResult__Output { + generated_text: string; + tokens: _caikit_data_model_nlp_GeneratedToken__Output[]; + details: _caikit_data_model_nlp_TokenStreamDetails__Output | null; + producer_id: _caikit_data_model_common_ProducerId__Output | null; + input_tokens: _caikit_data_model_nlp_GeneratedToken__Output[]; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/GeneratedToken.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/GeneratedToken.ts new file mode 100644 index 0000000..98ea12c --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/GeneratedToken.ts @@ -0,0 +1,28 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_nlp.proto + + +export interface GeneratedToken { + 'text'?: (string); + 'logprob'?: (number | string); +} + +export interface GeneratedToken__Output { + 'text': (string); + 'logprob': (number); +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/InputWarning.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/InputWarning.ts new file mode 100644 index 0000000..14a5274 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/InputWarning.ts @@ -0,0 +1,32 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_nlp.proto + +import type { + InputWarningReason as _caikit_data_model_nlp_InputWarningReason, + InputWarningReason__Output as _caikit_data_model_nlp_InputWarningReason__Output +} from './InputWarningReason'; + +export interface InputWarning { + id?: _caikit_data_model_nlp_InputWarningReason; + message?: string; +} + +export interface InputWarning__Output { + id: _caikit_data_model_nlp_InputWarningReason__Output; + message: string; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/InputWarningReason.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/InputWarningReason.ts new file mode 100644 index 0000000..2b61679 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/InputWarningReason.ts @@ -0,0 +1,27 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_nlp.proto + +export const InputWarningReason = { + UNSUITABLE_INPUT: 'UNSUITABLE_INPUT', +} as const; + +export type InputWarningReason = + | 'UNSUITABLE_INPUT' + | 0 + +export type InputWarningReason__Output = typeof InputWarningReason[keyof typeof InputWarningReason] diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/TextGenTokenClassificationResults.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/TextGenTokenClassificationResults.ts new file mode 100644 index 0000000..a554bcb --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/TextGenTokenClassificationResults.ts @@ -0,0 +1,32 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_nlp.proto + +import type { + TokenClassificationResult as _caikit_data_model_nlp_TokenClassificationResult, + TokenClassificationResult__Output as _caikit_data_model_nlp_TokenClassificationResult__Output +} from './TokenClassificationResult'; + +export interface TextGenTokenClassificationResults { + input?: _caikit_data_model_nlp_TokenClassificationResult[]; + output?: _caikit_data_model_nlp_TokenClassificationResult[]; +} + +export interface TextGenTokenClassificationResults__Output { + input: _caikit_data_model_nlp_TokenClassificationResult__Output[]; + output: _caikit_data_model_nlp_TokenClassificationResult__Output[]; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/Token.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/Token.ts new file mode 100644 index 0000000..0fe5f89 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/Token.ts @@ -0,0 +1,31 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_nlp.proto + +import type { Long } from '@grpc/proto-loader'; + +export interface Token { + 'start'?: (number | string | Long); + 'end'?: (number | string | Long); + 'text'?: (string); +} + +export interface Token__Output { + 'start': (number); + 'end': (number); + 'text': (string); +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/TokenClassificationResult.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/TokenClassificationResult.ts new file mode 100644 index 0000000..9ec43cb --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/TokenClassificationResult.ts @@ -0,0 +1,39 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_nlp.proto + +import type { Long } from '@grpc/proto-loader'; + +export interface TokenClassificationResult { + 'start'?: (number | string | Long); + 'end'?: (number | string | Long); + 'word'?: (string); + 'entity'?: (string); + 'entity_group'?: (string); + 'score'?: (number | string); + 'token_count'?: (number | string | Long); +} + +export interface TokenClassificationResult__Output { + 'start': (number); + 'end': (number); + 'word': (string); + 'entity': (string); + 'entity_group': (string); + 'score': (number); + 'token_count': (number); +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/TokenClassificationResults.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/TokenClassificationResults.ts new file mode 100644 index 0000000..75d6271 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/TokenClassificationResults.ts @@ -0,0 +1,30 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_nlp.proto + +import type { + TokenClassificationResult as _caikit_data_model_nlp_TokenClassificationResult, + TokenClassificationResult__Output as _caikit_data_model_nlp_TokenClassificationResult__Output +} from './TokenClassificationResult'; + +export interface TokenClassificationResults { + results?: _caikit_data_model_nlp_TokenClassificationResult[]; +} + +export interface TokenClassificationResults__Output { + results: _caikit_data_model_nlp_TokenClassificationResult__Output[]; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/TokenClassificationStreamResult.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/TokenClassificationStreamResult.ts new file mode 100644 index 0000000..1aed39d --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/TokenClassificationStreamResult.ts @@ -0,0 +1,35 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_nlp.proto + +import type { + TokenClassificationResult as _caikit_data_model_nlp_TokenClassificationResult, + TokenClassificationResult__Output as _caikit_data_model_nlp_TokenClassificationResult__Output +} from './TokenClassificationResult'; +import type { Long } from '@grpc/proto-loader'; + +export interface TokenClassificationStreamResult { + results?: _caikit_data_model_nlp_TokenClassificationResult[]; + processed_index?: number | string | Long; + start_index?: number | string | Long; +} + +export interface TokenClassificationStreamResult__Output { + results: _caikit_data_model_nlp_TokenClassificationResult__Output[]; + processed_index: number; + start_index: number; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/TokenStreamDetails.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/TokenStreamDetails.ts new file mode 100644 index 0000000..fc8f04f --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/TokenStreamDetails.ts @@ -0,0 +1,37 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_nlp.proto + +import type { + FinishReason as _caikit_data_model_nlp_FinishReason, + FinishReason__Output as _caikit_data_model_nlp_FinishReason__Output +} from './FinishReason'; +import type { Long } from '@grpc/proto-loader'; + +export interface TokenStreamDetails { + finish_reason?: _caikit_data_model_nlp_FinishReason; + generated_tokens?: number; + seed?: number | string | Long; + input_token_count?: number | string | Long; +} + +export interface TokenStreamDetails__Output { + finish_reason: _caikit_data_model_nlp_FinishReason__Output; + generated_tokens: number; + seed: number; + input_token_count: number; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/TokenizationResults.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/TokenizationResults.ts new file mode 100644 index 0000000..999e801 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/TokenizationResults.ts @@ -0,0 +1,33 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_nlp.proto + +import type { + Token as _caikit_data_model_nlp_Token, + Token__Output as _caikit_data_model_nlp_Token__Output +} from './Token'; +import type { Long } from '@grpc/proto-loader'; + +export interface TokenizationResults { + results?: _caikit_data_model_nlp_Token[]; + token_count?: number | string | Long; +} + +export interface TokenizationResults__Output { + results: _caikit_data_model_nlp_Token__Output[]; + token_count: number; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/TokenizationStreamResult.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/TokenizationStreamResult.ts new file mode 100644 index 0000000..3d51968 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/nlp/TokenizationStreamResult.ts @@ -0,0 +1,37 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_nlp.proto + +import type { + Token as _caikit_data_model_nlp_Token, + Token__Output as _caikit_data_model_nlp_Token__Output +} from './Token'; +import type { Long } from '@grpc/proto-loader'; + +export interface TokenizationStreamResult { + results?: _caikit_data_model_nlp_Token[]; + processed_index?: number | string | Long; + start_index?: number | string | Long; + token_count?: number | string | Long; +} + +export interface TokenizationStreamResult__Output { + results: _caikit_data_model_nlp_Token__Output[]; + processed_index: number; + start_index: number; + token_count: number; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/runtime/ModelPointer.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/runtime/ModelPointer.ts new file mode 100644 index 0000000..c8f6315 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/runtime/ModelPointer.ts @@ -0,0 +1,26 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_runtime.proto + + +export interface ModelPointer { + 'model_id'?: (string); +} + +export interface ModelPointer__Output { + 'model_id': (string); +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/runtime/TrainingInfoRequest.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/runtime/TrainingInfoRequest.ts new file mode 100644 index 0000000..172be1d --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/runtime/TrainingInfoRequest.ts @@ -0,0 +1,26 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_runtime.proto + + +export interface TrainingInfoRequest { + 'training_id'?: (string); +} + +export interface TrainingInfoRequest__Output { + 'training_id': (string); +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/runtime/TrainingJob.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/runtime/TrainingJob.ts new file mode 100644 index 0000000..aef68fb --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/runtime/TrainingJob.ts @@ -0,0 +1,28 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_runtime.proto + + +export interface TrainingJob { + 'training_id'?: (string); + 'model_name'?: (string); +} + +export interface TrainingJob__Output { + 'training_id': (string); + 'model_name': (string); +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model/runtime/TrainingStatusResponse.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/runtime/TrainingStatusResponse.ts new file mode 100644 index 0000000..926855f --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model/runtime/TrainingStatusResponse.ts @@ -0,0 +1,42 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: src/grpc/protos/caikit_data_model_runtime.proto + +import type { + TrainingStatus as _caikit_data_model_common_TrainingStatus, + TrainingStatus__Output as _caikit_data_model_common_TrainingStatus__Output +} from '../common/TrainingStatus'; +import type { + Timestamp as _google_protobuf_Timestamp, + Timestamp__Output as _google_protobuf_Timestamp__Output +} from '../../google/protobuf/Timestamp'; + +export interface TrainingStatusResponse { + training_id?: string; + state?: _caikit_data_model_common_TrainingStatus; + submission_timestamp?: _google_protobuf_Timestamp | null; + completion_timestamp?: _google_protobuf_Timestamp | null; + reasons?: string[]; +} + +export interface TrainingStatusResponse__Output { + training_id: string; + state: _caikit_data_model_common_TrainingStatus__Output; + submission_timestamp: _google_protobuf_Timestamp__Output | null; + completion_timestamp: _google_protobuf_Timestamp__Output | null; + reasons: string[]; +} diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model_caikit_nlp.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model_caikit_nlp.ts new file mode 100644 index 0000000..0fd3b6f --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model_caikit_nlp.ts @@ -0,0 +1,74 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type * as grpc from '@grpc/grpc-js'; +import type { EnumTypeDefinition, MessageTypeDefinition } from '@grpc/proto-loader'; + + +type SubtypeConstructor any, Subtype> = { + new(...args: ConstructorParameters): Subtype; +}; + +export interface ProtoGrpcType { + caikit_data_model: { + caikit_nlp: { + EmbeddingResult: MessageTypeDefinition + EmbeddingResults: MessageTypeDefinition + ExponentialDecayLengthPenalty: MessageTypeDefinition + GenerationTrainRecord: MessageTypeDefinition + RerankResult: MessageTypeDefinition + RerankResults: MessageTypeDefinition + RerankScore: MessageTypeDefinition + RerankScores: MessageTypeDefinition + SentenceSimilarityResult: MessageTypeDefinition + SentenceSimilarityResults: MessageTypeDefinition + SentenceSimilarityScores: MessageTypeDefinition + TuningConfig: MessageTypeDefinition + } + common: { + BoolSequence: MessageTypeDefinition + ConnectionInfo: MessageTypeDefinition + ConnectionTlsInfo: MessageTypeDefinition + Directory: MessageTypeDefinition + File: MessageTypeDefinition + FileReference: MessageTypeDefinition + FloatSequence: MessageTypeDefinition + IntSequence: MessageTypeDefinition + ListOfFileReferences: MessageTypeDefinition + ListOfVector1D: MessageTypeDefinition + NpFloat32Sequence: MessageTypeDefinition + NpFloat64Sequence: MessageTypeDefinition + ProducerId: MessageTypeDefinition + ProducerPriority: MessageTypeDefinition + PyFloatSequence: MessageTypeDefinition + S3Base: MessageTypeDefinition + S3Files: MessageTypeDefinition + S3Path: MessageTypeDefinition + StrSequence: MessageTypeDefinition + TrainingStatus: EnumTypeDefinition + Vector1D: MessageTypeDefinition + } + } + google: { + protobuf: { + ListValue: MessageTypeDefinition + NullValue: EnumTypeDefinition + Struct: MessageTypeDefinition + Value: MessageTypeDefinition + } + } +} + diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model_common.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model_common.ts new file mode 100644 index 0000000..2b35135 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model_common.ts @@ -0,0 +1,52 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type * as grpc from '@grpc/grpc-js'; +import type { EnumTypeDefinition, MessageTypeDefinition } from '@grpc/proto-loader'; + + +type SubtypeConstructor any, Subtype> = { + new(...args: ConstructorParameters): Subtype; +}; + +export interface ProtoGrpcType { + caikit_data_model: { + common: { + BoolSequence: MessageTypeDefinition + ConnectionInfo: MessageTypeDefinition + ConnectionTlsInfo: MessageTypeDefinition + Directory: MessageTypeDefinition + File: MessageTypeDefinition + FileReference: MessageTypeDefinition + FloatSequence: MessageTypeDefinition + IntSequence: MessageTypeDefinition + ListOfFileReferences: MessageTypeDefinition + ListOfVector1D: MessageTypeDefinition + NpFloat32Sequence: MessageTypeDefinition + NpFloat64Sequence: MessageTypeDefinition + ProducerId: MessageTypeDefinition + ProducerPriority: MessageTypeDefinition + PyFloatSequence: MessageTypeDefinition + S3Base: MessageTypeDefinition + S3Files: MessageTypeDefinition + S3Path: MessageTypeDefinition + StrSequence: MessageTypeDefinition + TrainingStatus: EnumTypeDefinition + Vector1D: MessageTypeDefinition + } + } +} + diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model_common_runtime.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model_common_runtime.ts new file mode 100644 index 0000000..4ddfe12 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model_common_runtime.ts @@ -0,0 +1,67 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type * as grpc from '@grpc/grpc-js'; +import type { EnumTypeDefinition, MessageTypeDefinition } from '@grpc/proto-loader'; + + +type SubtypeConstructor any, Subtype> = { + new(...args: ConstructorParameters): Subtype; +}; + +export interface ProtoGrpcType { + caikit_data_model: { + common: { + BoolSequence: MessageTypeDefinition + ConnectionInfo: MessageTypeDefinition + ConnectionTlsInfo: MessageTypeDefinition + Directory: MessageTypeDefinition + File: MessageTypeDefinition + FileReference: MessageTypeDefinition + FloatSequence: MessageTypeDefinition + IntSequence: MessageTypeDefinition + ListOfFileReferences: MessageTypeDefinition + ListOfVector1D: MessageTypeDefinition + NpFloat32Sequence: MessageTypeDefinition + NpFloat64Sequence: MessageTypeDefinition + ProducerId: MessageTypeDefinition + ProducerPriority: MessageTypeDefinition + PyFloatSequence: MessageTypeDefinition + S3Base: MessageTypeDefinition + S3Files: MessageTypeDefinition + S3Path: MessageTypeDefinition + StrSequence: MessageTypeDefinition + TrainingStatus: EnumTypeDefinition + Vector1D: MessageTypeDefinition + runtime: { + ModelInfo: MessageTypeDefinition + ModelInfoRequest: MessageTypeDefinition + ModelInfoResponse: MessageTypeDefinition + RuntimeInfoRequest: MessageTypeDefinition + RuntimeInfoResponse: MessageTypeDefinition + } + } + } + google: { + protobuf: { + ListValue: MessageTypeDefinition + NullValue: EnumTypeDefinition + Struct: MessageTypeDefinition + Value: MessageTypeDefinition + } + } +} + diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model_nlp.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model_nlp.ts new file mode 100644 index 0000000..8166579 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model_nlp.ts @@ -0,0 +1,73 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type * as grpc from '@grpc/grpc-js'; +import type { EnumTypeDefinition, MessageTypeDefinition } from '@grpc/proto-loader'; + + +type SubtypeConstructor any, Subtype> = { + new(...args: ConstructorParameters): Subtype; +}; + +export interface ProtoGrpcType { + caikit_data_model: { + common: { + BoolSequence: MessageTypeDefinition + ConnectionInfo: MessageTypeDefinition + ConnectionTlsInfo: MessageTypeDefinition + Directory: MessageTypeDefinition + File: MessageTypeDefinition + FileReference: MessageTypeDefinition + FloatSequence: MessageTypeDefinition + IntSequence: MessageTypeDefinition + ListOfFileReferences: MessageTypeDefinition + ListOfVector1D: MessageTypeDefinition + NpFloat32Sequence: MessageTypeDefinition + NpFloat64Sequence: MessageTypeDefinition + ProducerId: MessageTypeDefinition + ProducerPriority: MessageTypeDefinition + PyFloatSequence: MessageTypeDefinition + S3Base: MessageTypeDefinition + S3Files: MessageTypeDefinition + S3Path: MessageTypeDefinition + StrSequence: MessageTypeDefinition + TrainingStatus: EnumTypeDefinition + Vector1D: MessageTypeDefinition + } + nlp: { + ClassificationResult: MessageTypeDefinition + ClassificationResults: MessageTypeDefinition + ClassificationTrainRecord: MessageTypeDefinition + ClassifiedGeneratedTextResult: MessageTypeDefinition + ClassifiedGeneratedTextStreamResult: MessageTypeDefinition + FinishReason: EnumTypeDefinition + GeneratedTextResult: MessageTypeDefinition + GeneratedTextStreamResult: MessageTypeDefinition + GeneratedToken: MessageTypeDefinition + InputWarning: MessageTypeDefinition + InputWarningReason: EnumTypeDefinition + TextGenTokenClassificationResults: MessageTypeDefinition + Token: MessageTypeDefinition + TokenClassificationResult: MessageTypeDefinition + TokenClassificationResults: MessageTypeDefinition + TokenClassificationStreamResult: MessageTypeDefinition + TokenStreamDetails: MessageTypeDefinition + TokenizationResults: MessageTypeDefinition + TokenizationStreamResult: MessageTypeDefinition + } + } +} + diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_data_model_runtime.ts b/src/embedding/adapters/caikit/grpc/types/caikit_data_model_runtime.ts new file mode 100644 index 0000000..7474cd7 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_data_model_runtime.ts @@ -0,0 +1,63 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type * as grpc from '@grpc/grpc-js'; +import type { EnumTypeDefinition, MessageTypeDefinition } from '@grpc/proto-loader'; + + +type SubtypeConstructor any, Subtype> = { + new(...args: ConstructorParameters): Subtype; +}; + +export interface ProtoGrpcType { + caikit_data_model: { + common: { + BoolSequence: MessageTypeDefinition + ConnectionInfo: MessageTypeDefinition + ConnectionTlsInfo: MessageTypeDefinition + Directory: MessageTypeDefinition + File: MessageTypeDefinition + FileReference: MessageTypeDefinition + FloatSequence: MessageTypeDefinition + IntSequence: MessageTypeDefinition + ListOfFileReferences: MessageTypeDefinition + ListOfVector1D: MessageTypeDefinition + NpFloat32Sequence: MessageTypeDefinition + NpFloat64Sequence: MessageTypeDefinition + ProducerId: MessageTypeDefinition + ProducerPriority: MessageTypeDefinition + PyFloatSequence: MessageTypeDefinition + S3Base: MessageTypeDefinition + S3Files: MessageTypeDefinition + S3Path: MessageTypeDefinition + StrSequence: MessageTypeDefinition + TrainingStatus: EnumTypeDefinition + Vector1D: MessageTypeDefinition + } + runtime: { + ModelPointer: MessageTypeDefinition + TrainingInfoRequest: MessageTypeDefinition + TrainingJob: MessageTypeDefinition + TrainingStatusResponse: MessageTypeDefinition + } + } + google: { + protobuf: { + Timestamp: MessageTypeDefinition + } + } +} + diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_runtime_Nlp.ts b/src/embedding/adapters/caikit/grpc/types/caikit_runtime_Nlp.ts new file mode 100644 index 0000000..a09cd21 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_runtime_Nlp.ts @@ -0,0 +1,130 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type * as grpc from '@grpc/grpc-js'; +import type { EnumTypeDefinition, MessageTypeDefinition } from '@grpc/proto-loader'; + +import type { NlpServiceClient as _caikit_runtime_Nlp_NlpServiceClient, NlpServiceDefinition as _caikit_runtime_Nlp_NlpServiceDefinition } from './caikit/runtime/Nlp/NlpService'; +import type { NlpTrainingServiceClient as _caikit_runtime_Nlp_NlpTrainingServiceClient, NlpTrainingServiceDefinition as _caikit_runtime_Nlp_NlpTrainingServiceDefinition } from './caikit/runtime/Nlp/NlpTrainingService'; + +type SubtypeConstructor any, Subtype> = { + new(...args: ConstructorParameters): Subtype; +}; + +export interface ProtoGrpcType { + caikit: { + runtime: { + Nlp: { + BidiStreamingTokenClassificationTaskRequest: MessageTypeDefinition + DataStreamSourceGenerationTrainRecord: MessageTypeDefinition + DataStreamSourceGenerationTrainRecordJsonData: MessageTypeDefinition + EmbeddingTaskRequest: MessageTypeDefinition + EmbeddingTasksRequest: MessageTypeDefinition + NlpService: SubtypeConstructor & { service: _caikit_runtime_Nlp_NlpServiceDefinition } + NlpTrainingService: SubtypeConstructor & { service: _caikit_runtime_Nlp_NlpTrainingServiceDefinition } + RerankTaskRequest: MessageTypeDefinition + RerankTasksRequest: MessageTypeDefinition + SentenceSimilarityTaskRequest: MessageTypeDefinition + SentenceSimilarityTasksRequest: MessageTypeDefinition + ServerStreamingTextGenerationTaskRequest: MessageTypeDefinition + TextClassificationTaskRequest: MessageTypeDefinition + TextGenerationTaskPeftPromptTuningTrainParameters: MessageTypeDefinition + TextGenerationTaskPeftPromptTuningTrainRequest: MessageTypeDefinition + TextGenerationTaskRequest: MessageTypeDefinition + TextGenerationTaskTextGenerationTrainParameters: MessageTypeDefinition + TextGenerationTaskTextGenerationTrainRequest: MessageTypeDefinition + TokenClassificationTaskRequest: MessageTypeDefinition + TokenizationTaskRequest: MessageTypeDefinition + } + } + } + caikit_data_model: { + caikit_nlp: { + EmbeddingResult: MessageTypeDefinition + EmbeddingResults: MessageTypeDefinition + ExponentialDecayLengthPenalty: MessageTypeDefinition + GenerationTrainRecord: MessageTypeDefinition + RerankResult: MessageTypeDefinition + RerankResults: MessageTypeDefinition + RerankScore: MessageTypeDefinition + RerankScores: MessageTypeDefinition + SentenceSimilarityResult: MessageTypeDefinition + SentenceSimilarityResults: MessageTypeDefinition + SentenceSimilarityScores: MessageTypeDefinition + TuningConfig: MessageTypeDefinition + } + common: { + BoolSequence: MessageTypeDefinition + ConnectionInfo: MessageTypeDefinition + ConnectionTlsInfo: MessageTypeDefinition + Directory: MessageTypeDefinition + File: MessageTypeDefinition + FileReference: MessageTypeDefinition + FloatSequence: MessageTypeDefinition + IntSequence: MessageTypeDefinition + ListOfFileReferences: MessageTypeDefinition + ListOfVector1D: MessageTypeDefinition + NpFloat32Sequence: MessageTypeDefinition + NpFloat64Sequence: MessageTypeDefinition + ProducerId: MessageTypeDefinition + ProducerPriority: MessageTypeDefinition + PyFloatSequence: MessageTypeDefinition + S3Base: MessageTypeDefinition + S3Files: MessageTypeDefinition + S3Path: MessageTypeDefinition + StrSequence: MessageTypeDefinition + TrainingStatus: EnumTypeDefinition + Vector1D: MessageTypeDefinition + } + nlp: { + ClassificationResult: MessageTypeDefinition + ClassificationResults: MessageTypeDefinition + ClassificationTrainRecord: MessageTypeDefinition + ClassifiedGeneratedTextResult: MessageTypeDefinition + ClassifiedGeneratedTextStreamResult: MessageTypeDefinition + FinishReason: EnumTypeDefinition + GeneratedTextResult: MessageTypeDefinition + GeneratedTextStreamResult: MessageTypeDefinition + GeneratedToken: MessageTypeDefinition + InputWarning: MessageTypeDefinition + InputWarningReason: EnumTypeDefinition + TextGenTokenClassificationResults: MessageTypeDefinition + Token: MessageTypeDefinition + TokenClassificationResult: MessageTypeDefinition + TokenClassificationResults: MessageTypeDefinition + TokenClassificationStreamResult: MessageTypeDefinition + TokenStreamDetails: MessageTypeDefinition + TokenizationResults: MessageTypeDefinition + TokenizationStreamResult: MessageTypeDefinition + } + runtime: { + ModelPointer: MessageTypeDefinition + TrainingInfoRequest: MessageTypeDefinition + TrainingJob: MessageTypeDefinition + TrainingStatusResponse: MessageTypeDefinition + } + } + google: { + protobuf: { + ListValue: MessageTypeDefinition + NullValue: EnumTypeDefinition + Struct: MessageTypeDefinition + Timestamp: MessageTypeDefinition + Value: MessageTypeDefinition + } + } +} + diff --git a/src/embedding/adapters/caikit/grpc/types/caikit_runtime_info.ts b/src/embedding/adapters/caikit/grpc/types/caikit_runtime_info.ts new file mode 100644 index 0000000..57830c8 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/caikit_runtime_info.ts @@ -0,0 +1,75 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type * as grpc from '@grpc/grpc-js'; +import type { EnumTypeDefinition, MessageTypeDefinition } from '@grpc/proto-loader'; + +import type { InfoServiceClient as _caikit_runtime_info_InfoServiceClient, InfoServiceDefinition as _caikit_runtime_info_InfoServiceDefinition } from './caikit/runtime/info/InfoService'; + +type SubtypeConstructor any, Subtype> = { + new(...args: ConstructorParameters): Subtype; +}; + +export interface ProtoGrpcType { + caikit: { + runtime: { + info: { + InfoService: SubtypeConstructor & { service: _caikit_runtime_info_InfoServiceDefinition } + } + } + } + caikit_data_model: { + common: { + BoolSequence: MessageTypeDefinition + ConnectionInfo: MessageTypeDefinition + ConnectionTlsInfo: MessageTypeDefinition + Directory: MessageTypeDefinition + File: MessageTypeDefinition + FileReference: MessageTypeDefinition + FloatSequence: MessageTypeDefinition + IntSequence: MessageTypeDefinition + ListOfFileReferences: MessageTypeDefinition + ListOfVector1D: MessageTypeDefinition + NpFloat32Sequence: MessageTypeDefinition + NpFloat64Sequence: MessageTypeDefinition + ProducerId: MessageTypeDefinition + ProducerPriority: MessageTypeDefinition + PyFloatSequence: MessageTypeDefinition + S3Base: MessageTypeDefinition + S3Files: MessageTypeDefinition + S3Path: MessageTypeDefinition + StrSequence: MessageTypeDefinition + TrainingStatus: EnumTypeDefinition + Vector1D: MessageTypeDefinition + runtime: { + ModelInfo: MessageTypeDefinition + ModelInfoRequest: MessageTypeDefinition + ModelInfoResponse: MessageTypeDefinition + RuntimeInfoRequest: MessageTypeDefinition + RuntimeInfoResponse: MessageTypeDefinition + } + } + } + google: { + protobuf: { + ListValue: MessageTypeDefinition + NullValue: EnumTypeDefinition + Struct: MessageTypeDefinition + Value: MessageTypeDefinition + } + } +} + diff --git a/src/embedding/adapters/caikit/grpc/types/google/protobuf/ListValue.ts b/src/embedding/adapters/caikit/grpc/types/google/protobuf/ListValue.ts new file mode 100644 index 0000000..3dfedcd --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/google/protobuf/ListValue.ts @@ -0,0 +1,30 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: null + +import type { + Value as _google_protobuf_Value, + Value__Output as _google_protobuf_Value__Output +} from './Value'; + +export interface ListValue { + values?: _google_protobuf_Value[]; +} + +export interface ListValue__Output { + values: _google_protobuf_Value__Output[]; +} diff --git a/src/embedding/adapters/caikit/grpc/types/google/protobuf/NullValue.ts b/src/embedding/adapters/caikit/grpc/types/google/protobuf/NullValue.ts new file mode 100644 index 0000000..c8ae5d9 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/google/protobuf/NullValue.ts @@ -0,0 +1,27 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: null + +export const NullValue = { + NULL_VALUE: 'NULL_VALUE', +} as const; + +export type NullValue = + | 'NULL_VALUE' + | 0 + +export type NullValue__Output = typeof NullValue[keyof typeof NullValue] diff --git a/src/embedding/adapters/caikit/grpc/types/google/protobuf/Struct.ts b/src/embedding/adapters/caikit/grpc/types/google/protobuf/Struct.ts new file mode 100644 index 0000000..250f7ec --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/google/protobuf/Struct.ts @@ -0,0 +1,30 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: null + +import type { + Value as _google_protobuf_Value, + Value__Output as _google_protobuf_Value__Output +} from './Value'; + +export interface Struct { + fields?: { [key: string]: _google_protobuf_Value }; +} + +export interface Struct__Output { + fields: { [key: string]: _google_protobuf_Value__Output }; +} diff --git a/src/embedding/adapters/caikit/grpc/types/google/protobuf/Timestamp.ts b/src/embedding/adapters/caikit/grpc/types/google/protobuf/Timestamp.ts new file mode 100644 index 0000000..3a0d5ec --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/google/protobuf/Timestamp.ts @@ -0,0 +1,29 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: null + +import type { Long } from '@grpc/proto-loader'; + +export interface Timestamp { + 'seconds'?: (number | string | Long); + 'nanos'?: (number); +} + +export interface Timestamp__Output { + 'seconds': (number); + 'nanos': (number); +} diff --git a/src/embedding/adapters/caikit/grpc/types/google/protobuf/Value.ts b/src/embedding/adapters/caikit/grpc/types/google/protobuf/Value.ts new file mode 100644 index 0000000..4333264 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/types/google/protobuf/Value.ts @@ -0,0 +1,50 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Original file: null + +import type { + NullValue as _google_protobuf_NullValue, + NullValue__Output as _google_protobuf_NullValue__Output +} from './NullValue'; +import type { + Struct as _google_protobuf_Struct, + Struct__Output as _google_protobuf_Struct__Output +} from './Struct'; +import type { + ListValue as _google_protobuf_ListValue, + ListValue__Output as _google_protobuf_ListValue__Output +} from './ListValue'; + +export interface Value { + nullValue?: _google_protobuf_NullValue; + numberValue?: number | string; + stringValue?: string; + boolValue?: boolean; + structValue?: _google_protobuf_Struct | null; + listValue?: _google_protobuf_ListValue | null; + kind?: 'nullValue' | 'numberValue' | 'stringValue' | 'boolValue' | 'structValue' | 'listValue'; +} + +export interface Value__Output { + nullValue?: _google_protobuf_NullValue__Output; + numberValue?: number; + stringValue?: string; + boolValue?: boolean; + structValue?: _google_protobuf_Struct__Output | null; + listValue?: _google_protobuf_ListValue__Output | null; + kind: 'nullValue' | 'numberValue' | 'stringValue' | 'boolValue' | 'structValue' | 'listValue'; +} diff --git a/src/embedding/adapters/caikit/grpc/utils/build-client.ts b/src/embedding/adapters/caikit/grpc/utils/build-client.ts new file mode 100644 index 0000000..dbafc6d --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/utils/build-client.ts @@ -0,0 +1,66 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import grpc from '@grpc/grpc-js'; +import { MemoryCache } from 'cache-manager'; + +import { NlpServiceClient } from '../types/caikit/runtime/Nlp/NlpService.js'; +import { GRPC_CLIENT_SHUTDOWN_TIMEOUT } from '../constants.js'; + +import { createGrpcURLFromModel } from './url.js'; + +import { getLogger } from '@/logger.js'; +import { CAIKIT_CA_CERT, CAIKIT_CERT, CAIKIT_KEY, CAIKIT_URL } from '@/config.js'; + +const options = { + // This is needed, otherwise communication to DIPC cluster fails with "Dropped connection" error after +- 50 secs + 'grpc.keepalive_time_ms': 25000, + 'grpc.max_receive_message_length': 32 * 1024 * 1024 // 32MiB +} as const; + +type AnyClient = NlpServiceClient; + +type SubtypeConstructor any, Subtype> = { + new (...args: ConstructorParameters): Subtype; +}; + +interface BuildClientProps { + cache: MemoryCache; + modelId: string; + service: SubtypeConstructor; +} + +export function buildClient({ cache, modelId, service }: BuildClientProps) { + if (!CAIKIT_URL || !CAIKIT_CA_CERT || !CAIKIT_KEY || !CAIKIT_CERT) + throw new Error('Missing caikit env(s)'); + const credentials = grpc.credentials.createSsl( + Buffer.from(CAIKIT_CA_CERT), + Buffer.from(CAIKIT_KEY), + Buffer.from(CAIKIT_CERT) + ); + return cache.wrap(CAIKIT_URL, async () => { + const url = createGrpcURLFromModel(modelId); + const client = new service(url, credentials, options); + setTimeout(() => { + try { + client.close(); + } catch (err) { + getLogger().warn({ url }, 'Failed to close grpc client'); + } + }, GRPC_CLIENT_SHUTDOWN_TIMEOUT).unref(); + return client; + }); +} diff --git a/src/embedding/adapters/caikit/grpc/utils/errors.ts b/src/embedding/adapters/caikit/grpc/utils/errors.ts new file mode 100644 index 0000000..e791aaa --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/utils/errors.ts @@ -0,0 +1,66 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ServiceError } from '@grpc/grpc-js'; + +import { APIError, APIErrorCode } from '@/errors/error.entity'; + +export function isGrpcServiceError(err: unknown): err is ServiceError { + return ( + err instanceof Error && + err.constructor.name === 'Error' && + 'code' in err && + typeof err.code === 'number' + ); +} + +export function convertGrpcError(err: ServiceError): APIError { + // Error codes from https://grpc.github.io/grpc/core/md_doc_statuscodes.html + switch (err.code) { + case 3: + case 11: + return new APIError({ + message: `Invalid argument or out of range`, + code: APIErrorCode.SERVICE_ERROR + }); + case 5: + return new APIError({ + message: `Unrecognized model`, + code: APIErrorCode.SERVICE_UNAVAILABLE + }); + case 8: + return new APIError({ + message: `The model is currently overloaded.`, + code: APIErrorCode.SERVICE_UNAVAILABLE + }); + case 10: + return new APIError({ + message: 'The operation was aborted.', + code: APIErrorCode.SERVICE_UNAVAILABLE + }); + case 4: + case 14: + return new APIError({ + message: 'The model is temporarily unavailable. This is most likely a temporary condition.', + code: APIErrorCode.SERVICE_UNAVAILABLE + }); + default: + return new APIError({ + message: 'Unspecified service error', + code: APIErrorCode.SERVICE_ERROR + }); + } +} diff --git a/src/embedding/adapters/caikit/grpc/utils/metadata.ts b/src/embedding/adapters/caikit/grpc/utils/metadata.ts new file mode 100644 index 0000000..5954474 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/utils/metadata.ts @@ -0,0 +1,25 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Metadata } from '@grpc/grpc-js'; + +const GRPC_MODEL_ID_HEADER = 'mm-model-id'; + +export function createGrpcMetadata({ modelId }: { modelId?: string } = {}) { + const metadata = new Metadata({}); + if (modelId) metadata.add(GRPC_MODEL_ID_HEADER, modelId); + return metadata; +} diff --git a/src/embedding/adapters/caikit/grpc/utils/url.ts b/src/embedding/adapters/caikit/grpc/utils/url.ts new file mode 100644 index 0000000..70e234f --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/utils/url.ts @@ -0,0 +1,22 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { IBM_VLLM_URL } from '@/config'; + +export function createGrpcURLFromModel(modelId: string) { + if (!IBM_VLLM_URL) throw new Error('Missing IBM_VLLM_URL'); + return IBM_VLLM_URL.replace(/{model_id}/, modelId.replaceAll('/', '--')); +} diff --git a/src/embedding/adapters/caikit/grpc/utils/wrappers.ts b/src/embedding/adapters/caikit/grpc/utils/wrappers.ts new file mode 100644 index 0000000..2bb2075 --- /dev/null +++ b/src/embedding/adapters/caikit/grpc/utils/wrappers.ts @@ -0,0 +1,74 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CallOptions, ClientReadableStream, ClientUnaryCall, Metadata } from '@grpc/grpc-js'; +import { UnaryCallback } from '@grpc/grpc-js/build/src/client'; + +export function wrapGrpcCall( + fn: ( + request: TRequest, + metadata: Metadata, + options: CallOptions, + callback: UnaryCallback + ) => ClientUnaryCall +) { + return ( + request: TRequest, + metadata: Metadata, + { signal, ...options }: CallOptions & { signal?: AbortSignal } = {} + ): Promise => { + return new Promise((resolve, reject) => { + const call = fn(request, metadata, options, (err, response) => { + signal?.removeEventListener('abort', abortHandler); + if (err) { + reject(err); + } else { + if (response === undefined) { + reject(new Error('Invalid response from GRPC server')); + } else { + resolve(response); + } + } + }); + const abortHandler = () => { + call.cancel(); + }; + signal?.addEventListener('abort', abortHandler, { once: true }); + }); + }; +} + +export function wrapGrpcStream( + fn: ( + request: TRequest, + metadata: Metadata, + options: CallOptions + ) => ClientReadableStream +) { + return async ( + request: TRequest, + metadata: Metadata, + { signal, ...options }: CallOptions & { signal?: AbortSignal } = {} + ): Promise> => { + const stream = fn(request, metadata, options); + const abortHandler = () => { + stream.cancel(); + }; + signal?.addEventListener('abort', abortHandler, { once: true }); + stream.addListener('close', () => signal?.removeEventListener('abort', abortHandler)); + return stream; + }; +} diff --git a/src/embedding/adapters/embedding.ts b/src/embedding/adapters/embedding.ts new file mode 100644 index 0000000..3a95156 --- /dev/null +++ b/src/embedding/adapters/embedding.ts @@ -0,0 +1,45 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { cosineSimilarity } from 'langchain/util/math'; + +export type EmbeddingOptions = { + signal?: AbortSignal; +}; + +export abstract class Embedding { + constructor(public readonly model: string) {} + + async embed(text: string, options?: EmbeddingOptions): Promise { + const result = await this.embedMany([text], options); + const embedding = result.at(0); + if (!embedding) throw new Error('Missing embedding'); + return embedding; + } + + abstract embedMany(texts: string[], options?: EmbeddingOptions): Promise; + + async similarity( + { query, texts }: { query: string; texts: string[] }, + options?: EmbeddingOptions + ): Promise<{ score: number }[]> { + const [sourceEmbedding, ...textEmbeddings] = await this.embedMany([query, ...texts], options); + const matrix = cosineSimilarity([sourceEmbedding], textEmbeddings); + const similarities = matrix.at(0); + if (!similarities) throw new Error('Missing similarities'); + return similarities.map((score) => ({ score })); + } +} diff --git a/src/embedding/adapters/ollama-embedding.ts b/src/embedding/adapters/ollama-embedding.ts new file mode 100644 index 0000000..1f67eb6 --- /dev/null +++ b/src/embedding/adapters/ollama-embedding.ts @@ -0,0 +1,33 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Ollama } from 'ollama'; + +import { Embedding } from './embedding'; + +export class OllamaEmbedding extends Embedding { + constructor( + public readonly model: string, + public readonly client: Ollama + ) { + super(model); + } + + async embedMany(texts: string[]): Promise { + const response = await this.client.embed({ model: this.model, input: texts }); + return response.embeddings; + } +} diff --git a/src/embedding/adapters/openai-embedding.ts b/src/embedding/adapters/openai-embedding.ts new file mode 100644 index 0000000..b5dcb0f --- /dev/null +++ b/src/embedding/adapters/openai-embedding.ts @@ -0,0 +1,36 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import OpenAI from 'openai'; + +import { Embedding, EmbeddingOptions } from './embedding'; + +export class OpenAIEmbedding extends Embedding { + constructor( + public readonly model: string, + public readonly client: OpenAI + ) { + super(model); + } + + async embedMany(texts: string[], options?: EmbeddingOptions): Promise { + const response = await this.client.embeddings.create( + { model: this.model, input: texts }, + { signal: options?.signal } + ); + return response.data.map((data) => data.embedding); + } +} diff --git a/src/embedding/adapters/watsonx-embedding.ts b/src/embedding/adapters/watsonx-embedding.ts new file mode 100644 index 0000000..822f8f8 --- /dev/null +++ b/src/embedding/adapters/watsonx-embedding.ts @@ -0,0 +1,50 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { RestfulClient } from 'bee-agent-framework/internals/fetcher'; + +import { Embedding, EmbeddingOptions } from './embedding'; + +export class WatsonXEmbedding extends Embedding { + constructor( + public readonly model: string, + public readonly project: string, + public readonly client: RestfulClient> + ) { + super(model); + } + + async embedMany(texts: string[], options?: EmbeddingOptions): Promise { + const response: { results: { embedding: number[] }[] } = await this.client.fetch( + '/ml/v1/text/embeddings', + { + method: 'POST', + searchParams: new URLSearchParams({ version: '2023-10-25' }), + body: JSON.stringify({ + inputs: texts, + model_id: this.model, + project_id: this.project, + parameters: { + truncate_input_tokens: 512 + } + }), + signal: options?.signal + } + ); + if (response.results?.length !== texts.length) throw new Error('Missing embedding'); + return response.results.map((result) => result.embedding); + } +} diff --git a/src/embedding/constants.ts b/src/embedding/constants.ts new file mode 100644 index 0000000..487352a --- /dev/null +++ b/src/embedding/constants.ts @@ -0,0 +1,24 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const EmbeddingBackend = { + CAIKIT: 'caikit', + OLLAMA: 'ollama', + OPENAI: 'openai', + BAM: 'bam', + WATSONX: 'watsonx' +} as const; +export type EmbeddingBackend = (typeof EmbeddingBackend)[keyof typeof EmbeddingBackend]; diff --git a/src/embedding/factory.ts b/src/embedding/factory.ts new file mode 100644 index 0000000..b245f50 --- /dev/null +++ b/src/embedding/factory.ts @@ -0,0 +1,91 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Ollama } from 'ollama'; +import OpenAI from 'openai'; +import { Client as BAMClient } from '@ibm-generative-ai/node-sdk'; +import { WatsonXLLM } from 'bee-agent-framework/adapters/watsonx/llm'; + +import { EmbeddingBackend } from './constants'; +import { CaikitEmbedding } from './adapters/caikit/caikit-embedding'; +import { GrpcEmbeddingModel } from './adapters/caikit/grpc/constants'; +import { OllamaEmbedding } from './adapters/ollama-embedding'; +import { OpenAIEmbedding } from './adapters/openai-embedding'; +import { createEmbeddingsClient } from './adapters/caikit/grpc/client'; +import { BAMEmbedding } from './adapters/bam-embedding'; +import { WatsonXEmbedding } from './adapters/watsonx-embedding'; + +import { + BAM_API_KEY, + EMBEDDING_BACKEND, + OLLAMA_URL, + OPENAI_API_KEY, + WATSONX_API_KEY, + WATSONX_PROJECT_ID +} from '@/config'; + +export function getDefaultEmbeddingModel(backend: EmbeddingBackend = EMBEDDING_BACKEND) { + switch (backend) { + case EmbeddingBackend.CAIKIT: + return GrpcEmbeddingModel.BGE_LARGE_EN_V_1_5; + case EmbeddingBackend.OLLAMA: + return 'nomic-embed-text'; + case EmbeddingBackend.OPENAI: + return 'text-embedding-3-large'; + case EmbeddingBackend.BAM: + return 'baai/bge-large-en-v1.5'; + case EmbeddingBackend.WATSONX: + return 'ibm/slate-30m-english-rtrvr-v2'; + } +} + +let ollamaClient: Ollama | null; +let openAIClient: OpenAI | null; +let bamClient: BAMClient | null; + +export async function createEmbeddingAdapter( + model: string = getDefaultEmbeddingModel(), + backend: EmbeddingBackend = EMBEDDING_BACKEND +) { + switch (backend) { + case EmbeddingBackend.CAIKIT: { + const caikitClient = await createEmbeddingsClient(model); // caikit clients are managed + return new CaikitEmbedding(model, caikitClient); + } + case EmbeddingBackend.OLLAMA: + ollamaClient ??= new Ollama({ host: OLLAMA_URL ?? undefined }); + return new OllamaEmbedding(model, ollamaClient); + case EmbeddingBackend.OPENAI: + openAIClient ??= new OpenAI({ apiKey: OPENAI_API_KEY ?? undefined }); + return new OpenAIEmbedding(model, openAIClient); + case EmbeddingBackend.BAM: + bamClient ??= new BAMClient({ apiKey: BAM_API_KEY ?? undefined }); + return new BAMEmbedding(model, bamClient); + case EmbeddingBackend.WATSONX: { + if (!WATSONX_API_KEY) throw new Error('Missing WATSONX_API_KEY'); + if (!WATSONX_PROJECT_ID) throw new Error('Missing WATSONX_PROJECT_ID'); + // Framework doesn't expose factory for WatsonX fetcher, therefore we grab it via LLM + const llm = new WatsonXLLM({ + modelId: 'foobar', + apiKey: WATSONX_API_KEY, + projectId: WATSONX_PROJECT_ID + }); + // @ts-expect-error use protected property + const client = llm.client; + return new WatsonXEmbedding(model, WATSONX_PROJECT_ID, client); + } + } +} diff --git a/src/errors/dtos/error-response.ts b/src/errors/dtos/error-response.ts new file mode 100644 index 0000000..bd65f6a --- /dev/null +++ b/src/errors/dtos/error-response.ts @@ -0,0 +1,28 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { errorSchema } from './error.js'; + +export const errorResponseSchema = { + type: 'object', + required: ['error'], + properties: { + error: errorSchema + } +} as const satisfies JSONSchema; +export type ErrorResponse = FromSchema; diff --git a/src/errors/dtos/error.ts b/src/errors/dtos/error.ts new file mode 100644 index 0000000..cdb0d97 --- /dev/null +++ b/src/errors/dtos/error.ts @@ -0,0 +1,29 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { APIErrorCode } from '../error.entity.js'; + +export const errorSchema = { + type: 'object', + required: ['code', 'message'], + properties: { + message: { type: 'string' }, + code: { type: 'string', enum: Object.values(APIErrorCode) } + } +} as const satisfies JSONSchema; +export type Error = FromSchema; diff --git a/src/errors/error.entity.ts b/src/errors/error.entity.ts new file mode 100644 index 0000000..b64eb96 --- /dev/null +++ b/src/errors/error.entity.ts @@ -0,0 +1,97 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, Property } from '@mikro-orm/core'; +import { FrameworkError } from 'bee-agent-framework'; +import { AgentError } from 'bee-agent-framework/agents/base'; +import { ToolError } from 'bee-agent-framework/tools/base'; + +import { + convertGrpcError, + isGrpcServiceError +} from '@/embedding/adapters/caikit/grpc/utils/errors'; + +export const APIErrorCode = { + AUTH_ERROR: 'auth_error', + INTERNAL_SERVER_ERROR: 'internal_server_error', + INVALID_INPUT: 'invalid_input', + NOT_FOUND: 'not_found', + SERVICE_UNAVAILABLE: 'service_unavailable', + SERVICE_ERROR: 'service_error', + TOO_MANY_REQUESTS: 'too_many_requests', + FORBIDDEN: 'forbidden', + + FRAMEWORK_ERROR: 'framework_error', + AGENT_ERROR: 'agent_error', + TOOL_ERROR: 'tool_error' +} as const; +export type APIErrorCode = (typeof APIErrorCode)[keyof typeof APIErrorCode]; + +@Embeddable() +export class APIError { + @Property() + public readonly code: APIErrorCode; + + @Property() + public readonly message: string; + + public readonly cause?: unknown; + + constructor({ message, code }: { message: string; code: APIErrorCode }, options?: ErrorOptions) { + this.code = code; + this.message = message; + this.cause = options?.cause; + } + + static from(err: unknown): APIError { + if (err instanceof FrameworkError) { + for (const innerErr of Array.from(err.traverseErrors()).reverse()) { + if (innerErr instanceof ToolError) { + return new APIError( + { message: innerErr.message, code: APIErrorCode.TOOL_ERROR }, + { cause: innerErr } + ); + } else if (innerErr instanceof AgentError) { + return new APIError( + { message: innerErr.message, code: APIErrorCode.AGENT_ERROR }, + { cause: innerErr } + ); + } + return new APIError( + { message: innerErr.message, code: APIErrorCode.INTERNAL_SERVER_ERROR }, + { cause: innerErr } + ); + } + return new APIError( + { message: err.message, code: APIErrorCode.FRAMEWORK_ERROR }, + { cause: err } + ); + } + + // This should be last check before generic error since isGrpcServiceError is just a heuristic + if (isGrpcServiceError(err)) { + return convertGrpcError(err); + } + + return new APIError( + { + message: err instanceof Error ? err.message : 'Unspecified error', + code: APIErrorCode.INTERNAL_SERVER_ERROR + }, + { cause: err } + ); + } +} diff --git a/src/errors/plugin.ts b/src/errors/plugin.ts new file mode 100644 index 0000000..554ee47 --- /dev/null +++ b/src/errors/plugin.ts @@ -0,0 +1,104 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FastifyError, FastifyPluginAsync, errorCodes } from 'fastify'; +import fp from 'fastify-plugin'; +import { StatusCodes } from 'http-status-codes'; +import { NotFoundError, UniqueConstraintViolationException } from '@mikro-orm/core'; + +import { Error as ErrorDto } from './dtos/error.js'; +import { ErrorResponse } from './dtos/error-response.js'; +import { APIError, APIErrorCode } from './error.entity.js'; + +export function toErrorDto(error: APIError): ErrorDto { + return { + code: error.code, + message: error.message + }; +} + +export function toErrorResponseDto(error: APIError): ErrorResponse { + return { + error: toErrorDto(error) + }; +} + +function getStatusCode(error: APIError): StatusCodes { + switch (error.code) { + case APIErrorCode.AUTH_ERROR: + return StatusCodes.UNAUTHORIZED; + case APIErrorCode.INVALID_INPUT: + return StatusCodes.BAD_REQUEST; + case APIErrorCode.NOT_FOUND: + return StatusCodes.NOT_FOUND; + case APIErrorCode.TOO_MANY_REQUESTS: + return StatusCodes.TOO_MANY_REQUESTS; + case APIErrorCode.SERVICE_UNAVAILABLE: + return StatusCodes.SERVICE_UNAVAILABLE; + case APIErrorCode.FORBIDDEN: + return StatusCodes.FORBIDDEN; + default: + return StatusCodes.INTERNAL_SERVER_ERROR; + } +} + +function convertToAPIError(error: FastifyError): APIError { + if (error instanceof APIError) { + return error; + } else if (error instanceof NotFoundError || error instanceof errorCodes.FST_ERR_NOT_FOUND) { + return new APIError({ + message: error.message, + code: APIErrorCode.NOT_FOUND + }); + } else if (error instanceof UniqueConstraintViolationException) { + return new APIError({ + message: 'Submitted data violates the uniqueness constraint', + code: APIErrorCode.INVALID_INPUT + }); + } else if ( + error instanceof SyntaxError || + error.code === 'FST_ERR_VALIDATION' || // instanceof check doesn't work for this code + error instanceof errorCodes.FST_ERR_CTP_EMPTY_JSON_BODY + ) { + return new APIError({ + message: error.message, + code: APIErrorCode.INVALID_INPUT + }); + } else { + return new APIError({ + message: error.message, + code: APIErrorCode.INTERNAL_SERVER_ERROR + }); + } +} + +export const errorPlugin: FastifyPluginAsync = fp.default(async (app) => { + app.setNotFoundHandler((request, reply) => { + const apiError = new APIError({ + message: 'Route does not exist', + code: APIErrorCode.NOT_FOUND + }); + reply.status(getStatusCode(apiError)).send(toErrorResponseDto(apiError)); + }); + + app.setErrorHandler(function (error, request, reply) { + const apiError = convertToAPIError(error); + if (apiError.code === APIErrorCode.INTERNAL_SERVER_ERROR) { + this.log.error(error); + } + reply.status(getStatusCode(apiError)).send(toErrorResponseDto(apiError)); + }); +}); diff --git a/src/files/dtos/file-content-read.ts b/src/files/dtos/file-content-read.ts new file mode 100644 index 0000000..cd2b981 --- /dev/null +++ b/src/files/dtos/file-content-read.ts @@ -0,0 +1,30 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +export const fileContentReadParamsSchema = { + type: 'object', + required: ['file_id'], + additionalProperties: false, + properties: { + file_id: { type: 'string' } + } +} as const satisfies JSONSchema; +export type FileContentReadParams = FromSchema; + +export const fileContentReadResponseSchema = {} as const as JSONSchema; +export type FileContentReadResponse = FromSchema; diff --git a/src/files/dtos/file-create.ts b/src/files/dtos/file-create.ts new file mode 100644 index 0000000..ce419e3 --- /dev/null +++ b/src/files/dtos/file-create.ts @@ -0,0 +1,43 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FilePurpose } from '../entities/file.entity.js'; + +import { fileSchema } from './file.js'; + +import { FromSchema, JSONSchema } from '@/ajv.js'; + +export const fileCreateBodySchema = { + type: 'object', + required: ['purpose', 'file'], + additionalProperties: false, + properties: { + purpose: { + type: 'string', + enum: [FilePurpose.ASSISTANTS] + }, + file: { + isFile: true + }, + depends_on_thread_id: { + type: 'string' + } + } +} as const satisfies JSONSchema; +export type FileCreateBody = FromSchema; + +export const FileCreateResponseSchema = fileSchema; +export type FileCreateResponse = FromSchema; diff --git a/src/files/dtos/file-delete.ts b/src/files/dtos/file-delete.ts new file mode 100644 index 0000000..dfa7138 --- /dev/null +++ b/src/files/dtos/file-delete.ts @@ -0,0 +1,32 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { createDeleteSchema } from '@/schema.js'; + +export const fileDeleteParamsSchema = { + type: 'object', + required: ['file_id'], + additionalProperties: false, + properties: { + file_id: { type: 'string' } + } +} as const satisfies JSONSchema; +export type FileDeleteParams = FromSchema; + +export const fileDeleteResponseSchema = createDeleteSchema('file'); +export type FileDeleteResponse = FromSchema; diff --git a/src/files/dtos/file-read.ts b/src/files/dtos/file-read.ts new file mode 100644 index 0000000..ecd8eb5 --- /dev/null +++ b/src/files/dtos/file-read.ts @@ -0,0 +1,32 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { fileSchema } from './file.js'; + +export const fileReadParamsSchema = { + type: 'object', + required: ['file_id'], + additionalProperties: false, + properties: { + file_id: { type: 'string' } + } +} as const satisfies JSONSchema; +export type FileReadParams = FromSchema; + +export const fileReadResponseSchema = fileSchema; +export type FileReadResponse = FromSchema; diff --git a/src/files/dtos/file.ts b/src/files/dtos/file.ts new file mode 100644 index 0000000..0d8f806 --- /dev/null +++ b/src/files/dtos/file.ts @@ -0,0 +1,51 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { FilePurpose } from '../entities/file.entity.js'; + +export const fileSchema = { + type: 'object', + required: ['id', 'bytes', 'created_at', 'filename', 'object', 'purpose'], + properties: { + id: { type: 'string' }, + bytes: { type: 'integer' }, + created_at: { type: 'number' }, + filename: { type: 'string' }, + object: { const: 'file' }, + purpose: { + type: 'string', + enum: Object.values(FilePurpose) + }, + depends_on: { + type: 'object', + required: ['thread'], + properties: { + thread: { + type: 'object', + required: ['id'], + properties: { + id: { + type: 'string' + } + } + } + } + } + } +} as const satisfies JSONSchema; +export type File = FromSchema; diff --git a/src/files/dtos/files-list.ts b/src/files/dtos/files-list.ts new file mode 100644 index 0000000..6d566c1 --- /dev/null +++ b/src/files/dtos/files-list.ts @@ -0,0 +1,50 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { fileSchema } from './file.js'; + +import { createPaginationQuerySchema, withPagination } from '@/schema.js'; + +export const filesListQuerySchema = { + type: 'object', + additionalProperties: false, + properties: { + ...createPaginationQuerySchema(['filename'] as const).properties, + // Stupid name to stay compatible with OpenAI (an undocumented query param in their API) + 'ids[]': { + type: 'array', + uniqueItems: true, + /* + Note: this is used mainly when fetching file info for a vector store, which can have at most + 500 files, so the consumer will need to call this endpoint max 10 times (edge case). + Our id has 24 characters, so the limit is keeping this under 2000 chars per recommendation: + https://stackoverflow.com/a/417184 + */ + maxItems: 50, + items: { type: 'string' } + }, + show_dependent: { + type: 'boolean', + default: true + } + } +} as const satisfies JSONSchema; +export type FilesListQuery = FromSchema; + +export const filesListResponseSchema = withPagination(fileSchema); +export type FilesListResponse = FromSchema; diff --git a/src/files/entities/extraction.entity.ts b/src/files/entities/extraction.entity.ts new file mode 100644 index 0000000..5e9dc56 --- /dev/null +++ b/src/files/entities/extraction.entity.ts @@ -0,0 +1,33 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, Property } from '@mikro-orm/core'; + +@Embeddable() +export class Extraction { + @Property() + jobId?: string; + + @Property() + storageId?: string; + + constructor(input: ExtractionInput) { + this.jobId = input.jobId; + this.storageId = input.storageId; + } +} + +export type ExtractionInput = Pick; diff --git a/src/files/entities/file.entity.ts b/src/files/entities/file.entity.ts new file mode 100644 index 0000000..8786d14 --- /dev/null +++ b/src/files/entities/file.entity.ts @@ -0,0 +1,68 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { randomUUID } from 'node:crypto'; + +import { Embedded, Entity, Enum, Property } from '@mikro-orm/core'; + +import { Extraction } from './extraction.entity.js'; + +import { ProjectScopedEntity, ProjectScopedEntityInput } from '@/common/project-scoped.entity.js'; + +export const FilePurpose = { + ASSISTANTS: 'assistants', + ASSISTANTS_OUTPUT: 'assistants_output' +} as const; +export type FilePurpose = (typeof FilePurpose)[keyof typeof FilePurpose]; + +@Entity() +export class File extends ProjectScopedEntity { + getIdPrefix(): string { + return 'file'; + } + + @Enum(() => FilePurpose) + purpose!: FilePurpose; + + @Property() + bytes!: number; + + @Property() + filename!: string; + + @Property() + contentHash!: string; // SHA256 hash of the file content + + @Property() + storageId: string; + + @Embedded({ object: true }) + extraction?: Extraction; + + constructor({ purpose, bytes, filename, contentHash, storageId, ...rest }: FilePurposeInput) { + super(rest); + + this.purpose = purpose; + this.bytes = bytes; + this.filename = filename; + this.contentHash = contentHash; + this.storageId = storageId ?? randomUUID(); + } +} + +export type FilePurposeInput = ProjectScopedEntityInput & + Pick & + Partial>; diff --git a/src/files/entities/files-container.entity.ts b/src/files/entities/files-container.entity.ts new file mode 100644 index 0000000..ec2cd7e --- /dev/null +++ b/src/files/entities/files-container.entity.ts @@ -0,0 +1,31 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, ManyToOne, Ref, ref } from '@mikro-orm/core'; + +import { File } from '@/files/entities/file.entity.js'; + +@Embeddable() +export class FileContainer { + @ManyToOne() + file!: Ref; + + constructor({ file }: FileContainerInput) { + this.file = ref(file); + } +} + +export type FileContainerInput = { file: File | Ref }; diff --git a/src/files/extraction/extract.ts b/src/files/extraction/extract.ts new file mode 100644 index 0000000..17f1b24 --- /dev/null +++ b/src/files/extraction/extract.ts @@ -0,0 +1,90 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Readable } from 'node:stream'; +import { promisify } from 'node:util'; + +import yauzl, { Options, ZipFile } from 'yauzl'; + +import { WDU_URL } from '@/config.js'; +import { toBuffer } from '@/utils/streams.js'; + +export function canBeExtracted(mimeType: string) { + if (!WDU_URL) return false; + // allowed types are specified in WDU docs + return [ + 'application/pdf', + 'image/jpeg', + 'image/png', + 'image/tiff', + 'image/bmp', + 'image/gif' + ].includes(mimeType); +} + +export async function extract(filename: string, content: Readable) { + if (!WDU_URL) throw new Error('Missing WDU_URL'); + const response = await fetch(new URL('/api/v1/task/doc-processing', WDU_URL), { + method: 'POST', + headers: { + ['Content-Type']: 'application/json' + }, + body: JSON.stringify({ + model_id: 'doc_processing', + inputs: { + file: { + filename, + data: (await toBuffer(content)).toString('base64') + } + }, + parameters: { + languages_list: ['eng'], + output_type: 'parse_json_and_gte', + auto_rotation_correction: false, + include_serialization: true + } + }) + }); + + if (!response.ok) { + const text = await response.text().catch(() => null); + throw new Error(`Extraction service failed; status: ${response.status}; response: ${text}`); + } + + const fromBuffer = promisify(yauzl.fromBuffer); + const zipFile = await fromBuffer(Buffer.from(await response.arrayBuffer()), { + decodeStrings: false + }); // built-in string decoding throws on absolute paths like /page_images, that is apparently a safety feature. We trust the backend so we decode the filename manually. + const openReadStream = promisify(zipFile.openReadStream.bind(zipFile)); + + let dataBufferPromise: Promise | undefined; + // Parse the zip file and start uploads + await new Promise((resolve) => { + zipFile.on('entry', async (entry) => { + const fileName = entry.fileName.toString('utf8'); + if (fileName === 'serialization.txt') { + dataBufferPromise = toBuffer(await openReadStream(entry)); + } + }); + zipFile.on('end', () => { + resolve(); + }); + }); + + if (!dataBufferPromise) throw new Error('Response is missing serialized extraction'); + + return (await dataBufferPromise).toString('utf8'); +} diff --git a/src/files/files.module.ts b/src/files/files.module.ts new file mode 100644 index 0000000..03c75d1 --- /dev/null +++ b/src/files/files.module.ts @@ -0,0 +1,118 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FastifyPluginAsyncJsonSchemaToTs } from '@fastify/type-provider-json-schema-to-ts'; +import { StatusCodes } from 'http-status-codes'; + +import { + FileCreateBody, + FileCreateResponseSchema, + fileCreateBodySchema +} from './dtos/file-create.js'; +import { FileReadParams, fileReadParamsSchema, fileReadResponseSchema } from './dtos/file-read.js'; +import { + FilesListQuery, + filesListQuerySchema, + filesListResponseSchema +} from './dtos/files-list.js'; +import { FileDeleteParams, fileDeleteParamsSchema } from './dtos/file-delete.js'; +import { + FileContentReadParams, + fileContentReadParamsSchema, + fileContentReadResponseSchema +} from './dtos/file-content-read.js'; +import { createFile, deleteFile, listFiles, readFile, readFileContent } from './files.service.js'; + +import { Tag } from '@/swagger.js'; +import { createDeleteSchema } from '@/schema.js'; + +export const filesModule: FastifyPluginAsyncJsonSchemaToTs = async (app) => { + app.post<{ Body: FileCreateBody }>( + '/files', + { + schema: { + consumes: ['multipart/form-data'], + body: fileCreateBodySchema, + response: { [StatusCodes.OK]: FileCreateResponseSchema }, + tags: [Tag.OPENAI_API] + }, + preHandler: app.auth() + }, + async (req) => { + return createFile(req.body); + } + ); + + app.get<{ Params: FileReadParams }>( + '/files/:file_id', + { + schema: { + params: fileReadParamsSchema, + response: { [StatusCodes.OK]: fileReadResponseSchema }, + tags: [Tag.OPENAI_API] + }, + preHandler: app.auth() + }, + async (req) => { + return readFile(req.params); + } + ); + + app.delete<{ Params: FileDeleteParams }>( + '/files/:file_id', + { + schema: { + params: fileDeleteParamsSchema, + response: { [StatusCodes.OK]: createDeleteSchema('file') }, + tags: [Tag.OPENAI_API] + }, + preHandler: app.auth() + }, + async (req) => deleteFile(req.params) + ); + + app.get<{ Querystring: FilesListQuery }>( + '/files', + { + schema: { + querystring: filesListQuerySchema, + response: { [StatusCodes.OK]: filesListResponseSchema }, + tags: [Tag.OPENAI_API] + }, + preHandler: app.auth() + }, + async (req) => { + return listFiles(req.query); + } + ); + + app.get<{ Params: FileContentReadParams }>( + '/files/:file_id/content', + { + schema: { + params: fileContentReadParamsSchema, + response: { + [StatusCodes.OK]: { 'application/octet-stream': fileContentReadResponseSchema } + }, + tags: [Tag.OPENAI_API] + }, + preHandler: app.auth() + }, + async (req) => { + return readFileContent(req.params); + } + ); +}; diff --git a/src/files/files.service.ts b/src/files/files.service.ts new file mode 100644 index 0000000..d5c5f84 --- /dev/null +++ b/src/files/files.service.ts @@ -0,0 +1,268 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { createHash } from 'node:crypto'; + +import { FilterQuery, Loaded, ref, Ref } from '@mikro-orm/core'; +import ibm from 'ibm-cos-sdk'; +import { MultipartFile } from '@fastify/multipart'; +import dayjs from 'dayjs'; +import mime from 'mime/lite'; + +import { File } from './entities/file.entity.js'; +import { File as FileDto } from './dtos/file.js'; +import { FileCreateBody, FileCreateResponse } from './dtos/file-create.js'; +import { FileReadParams, FileReadResponse } from './dtos/file-read.js'; +import { FileDeleteParams, FileDeleteResponse } from './dtos/file-delete.js'; +import { FilesListQuery, FilesListResponse } from './dtos/files-list.js'; +import { FileContentReadParams, FileContentReadResponse } from './dtos/file-content-read.js'; +import { queue } from './jobs/extraction.queue.js'; +import { Extraction } from './entities/extraction.entity.js'; +import { canBeExtracted } from './extraction/extract.js'; + +import { PassthroughHash } from '@/utils/streams.js'; +import { ORM } from '@/database.js'; +import { getServiceLogger } from '@/logger.js'; +import { createPaginatedResponse, getListCursor } from '@/utils/pagination.js'; +import { + S3_ACCESS_KEY_ID, + S3_BUCKET_FILE_STORAGE, + S3_ENDPOINT, + S3_SECRET_ACCESS_KEY +} from '@/config.js'; +import { APIError, APIErrorCode } from '@/errors/error.entity.js'; +import { listenToSocketClose } from '@/utils/networking.js'; +import { createDeleteResponse } from '@/utils/delete.js'; +import { QueueName } from '@/jobs/constants.js'; +import { Thread } from '@/threads/thread.entity.js'; +import { ensureRequestContextData } from '@/context.js'; +import { Project } from '@/administration/entities/project.entity.js'; +import { getProjectPrincipal } from '@/administration/helpers.js'; + +const getFilesLogger = (fileId?: string) => getServiceLogger('file').child({ fileId }); + +export const s3Client = new ibm.S3({ + endpoint: S3_ENDPOINT, + s3ForcePathStyle: true, // Needed for MinIO + credentials: { accessKeyId: S3_ACCESS_KEY_ID, secretAccessKey: S3_SECRET_ACCESS_KEY } +}); + +const USER_FILES_STORAGE_LIMIT = 10_000_000_000; +const USER_FILE_SIZE_LIMIT = 100_000_000; +const CONTENT_SIZE_CORRECTION = 500; + +async function getProjectStorageSize(project: Ref) { + const aggregation = (await ORM.em.aggregate(File, [ + { $match: { project: project.id } }, + { $group: { _id: null, totalSize: { $sum: '$bytes' } } } + ])) as { totalSize: number }[]; + return aggregation.at(0)?.totalSize ?? 0; +} + +export function toFileDto(file: Loaded): FileDto { + return { + id: file.id, + created_at: dayjs(file.createdAt).unix(), + purpose: file.purpose, + bytes: file.bytes, + object: 'file', + filename: file.filename, + depends_on: file.dependsOn + ? { + thread: { + id: file.dependsOn.id + } + } + : undefined + }; +} + +export async function createFile({ + purpose, + file: multipartFile, + depends_on_thread_id +}: FileCreateBody): Promise { + const req = ensureRequestContextData('req'); + + const userStorageSize = await getProjectStorageSize(getProjectPrincipal().project); + const allowedFileSize = Math.min( + USER_FILE_SIZE_LIMIT, + USER_FILES_STORAGE_LIMIT - userStorageSize + ); + + // quick content size check before uploading (subtracting CONTENT_SIZE_CORRECTION because of parameters size) + const contentLength = parseInt(req.headers['content-length'] ?? 'NaN'); + if (contentLength && contentLength - CONTENT_SIZE_CORRECTION > allowedFileSize) { + throw new APIError({ + message: `Content is too large`, + code: APIErrorCode.INVALID_INPUT + }); + } + + const { filename, mimetype, file: content } = multipartFile as MultipartFile; + + const dependsOn = depends_on_thread_id + ? ref(await ORM.em.getRepository(Thread).findOneOrFail({ id: depends_on_thread_id })) + : undefined; + const file = new File({ + purpose, + filename, + bytes: 0, + contentHash: '', + dependsOn + }); + + const storageLimitExceeded = () => file.bytes > allowedFileSize; + const passthroughHash = new PassthroughHash({ hash: createHash('sha256') }); + + const s3request = s3Client.upload({ + Bucket: S3_BUCKET_FILE_STORAGE, + Key: file.storageId, + Body: content.compose(passthroughHash), + ContentType: mimetype + }); + const unsub = listenToSocketClose(req.socket, () => s3request.abort()); + s3request.on('httpUploadProgress', (progress) => { + getFilesLogger().trace({ progress }, 'Upload progress'); + file.bytes = progress.total ?? file.bytes; + if (storageLimitExceeded()) s3request.abort(); + }); + try { + await s3request.promise(); + const head = await s3Client + .headObject({ Bucket: S3_BUCKET_FILE_STORAGE, Key: file.storageId }) + .promise(); + file.contentHash = passthroughHash.hash.digest('hex'); + file.bytes = head.ContentLength ?? 0; + await ORM.em.persistAndFlush(file); + getFilesLogger(file.id).info('File created'); + + (async () => { + try { + if (head.ContentType?.startsWith('text/') || head.ContentType === 'application/json') { + file.extraction = new Extraction({ storageId: file.storageId }); + } else if (head.ContentType && canBeExtracted(head.ContentType)) { + const job = await queue.add(QueueName.FILES_EXTRACTION, { fileId: file.id }); + file.extraction = new Extraction({ jobId: job.id }); + } + await ORM.em.flush(); + } catch (err) { + getFilesLogger(file.id).warn({ err }, 'Failed to schedule extraction'); + } + })(); + + return toFileDto(file); + } catch (err) { + if (storageLimitExceeded()) + throw new APIError({ message: 'Storage limit exceeded', code: APIErrorCode.INVALID_INPUT }); + throw err; + } finally { + unsub(); + } +} + +export async function readFile({ file_id }: FileReadParams): Promise { + const file = await ORM.em + .getRepository(File) + .findOneOrFail({ id: file_id }, { filters: { hasAccess: {} } }); + return toFileDto(file); +} + +export async function deleteFile({ file_id }: FileDeleteParams): Promise { + const file = await ORM.em.getRepository(File).findOneOrFail({ id: file_id }); + + if (file.extraction?.jobId) { + const success = !!(await queue.remove(file.extraction.jobId)); + if (success) { + file.extraction = new Extraction({ storageId: file.extraction.storageId }); + } + } + + file.delete(); + + await ORM.em.flush(); + getFilesLogger(file.id).info('File deleted'); + return createDeleteResponse(file_id, 'file'); +} + +export async function listFiles({ + limit, + after, + before, + order, + order_by, + show_dependent, + ...rest +}: FilesListQuery): Promise { + const where: FilterQuery = {}; + const ids = rest['ids[]']; + if (ids) { + where.id = { $in: ids }; + } + if (!show_dependent) { + where.dependsOn = { $exists: false }; + } + const repo = ORM.em.getRepository(File); + const cursor = await getListCursor(where, { limit, order, order_by, after, before }, repo); + return createPaginatedResponse(cursor, toFileDto); +} + +export async function getExtractedFileStats(file: Loaded) { + if (!file.extraction?.storageId) throw new Error('Extraction not found'); + return s3Client + .headObject({ + Bucket: S3_BUCKET_FILE_STORAGE, + Key: file.extraction.storageId + }) + .promise(); +} + +export async function getExtractedFileObject(file: Loaded) { + if (!file.extraction?.storageId) throw new Error('Extraction not found'); + return s3Client + .getObject({ + Bucket: S3_BUCKET_FILE_STORAGE, + Key: file.extraction.storageId + }) + .promise(); +} + +export async function readFileContent({ + file_id +}: FileContentReadParams): Promise { + const file = await ORM.em.getRepository(File).findOneOrFail({ id: file_id }); + + const head = await s3Client + .headObject({ + Bucket: S3_BUCKET_FILE_STORAGE, + Key: file.storageId + }) + .promise(); + + const content = s3Client + .getObject({ + Bucket: S3_BUCKET_FILE_STORAGE, + Key: file.storageId + }) + .createReadStream(); + + return ensureRequestContextData('res') + .header( + 'content-type', + head.ContentType ?? mime.getType(file.filename) ?? 'application/octet-stream' + ) + .send(content); +} diff --git a/src/files/jobs/cleanup.queue.ts b/src/files/jobs/cleanup.queue.ts new file mode 100644 index 0000000..18fe0a3 --- /dev/null +++ b/src/files/jobs/cleanup.queue.ts @@ -0,0 +1,99 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Job } from 'bullmq'; +import { RequestContext } from '@mikro-orm/core'; + +import { File } from '../entities/file.entity.js'; +import { s3Client } from '../files.service.js'; + +import { ORM } from '@/database.js'; +import { createQueue } from '@/jobs/bullmq.js'; +import { QueueName } from '@/jobs/constants.js'; +import { S3_BUCKET_FILE_STORAGE } from '@/config.js'; +import { getJobLogger } from '@/logger.js'; +import { deleteVectorStoreFiles } from '@/vector-store-files/vector-store-files.service.js'; +import { VectorStoreFile } from '@/vector-store-files/entities/vector-store-file.entity.js'; +import { Thread } from '@/threads/thread.entity.js'; + +async function jobHandler(_: Job) { + let files: File[] = []; + await RequestContext.create(ORM.em, async () => { + files = await ORM.em.getRepository(File).find( + { bytes: { $gt: 0 }, deletedAt: { $exists: true } }, + { + filters: { deleted: false } + } + ); + }); + + await Promise.all( + files.map(async (fileObj) => { + return RequestContext.create(ORM.em, async () => { + const file = await ORM.em.getRepository(File).findOneOrFail( + { id: fileObj.id }, + { + filters: { deleted: false } + } + ); + try { + if (file.storageId !== '') { + await s3Client + .deleteObject({ Bucket: S3_BUCKET_FILE_STORAGE, Key: file.storageId }) + .promise(); + file.storageId = ''; + } + + if (file.extraction) { + if (file.extraction?.storageId && file.extraction.storageId !== file.storageId) { + await s3Client + .deleteObject({ Bucket: S3_BUCKET_FILE_STORAGE, Key: file.extraction.storageId }) + .promise(); + } + file.extraction = undefined; + } + + const vectoreStoreFiles = await ORM.em.getRepository(VectorStoreFile).find({ file }); + if (vectoreStoreFiles.length > 0) await deleteVectorStoreFiles(vectoreStoreFiles); + + if (file.dependsOn) { + // hard delete the file when depends on the deleted thread + const thread = await ORM.em + .getRepository(Thread) + .findOne({ id: file.dependsOn.id }, { filters: { deleted: false } }); + if (!thread) { + ORM.em.remove(file); + } + } + + file.bytes = 0; + await ORM.em.flush(); + } catch (err) { + getJobLogger('filesCleanup').warn({ err }, 'File can not be deleted.'); + } + }); + }) + ); +} + +export const { queue, worker } = createQueue({ + name: QueueName.FILES_CLEANUP, + jobHandler, + jobsOptions: { attempts: 1 }, + workerOptions: { + concurrency: 1 + } +}); diff --git a/src/files/jobs/extraction.queue.ts b/src/files/jobs/extraction.queue.ts new file mode 100644 index 0000000..4294ec6 --- /dev/null +++ b/src/files/jobs/extraction.queue.ts @@ -0,0 +1,70 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { randomUUID } from 'node:crypto'; + +import { Job } from 'bullmq'; +import { RequestContext } from '@mikro-orm/core'; + +import { File } from '../entities/file.entity.js'; +import { s3Client } from '../files.service.js'; +import { Extraction } from '../entities/extraction.entity.js'; +import { extract } from '../extraction/extract.js'; + +import { ORM } from '@/database.js'; +import { createQueue } from '@/jobs/bullmq.js'; +import { QueueName } from '@/jobs/constants.js'; +import { S3_BUCKET_FILE_STORAGE } from '@/config.js'; + +async function jobHandler(job: Job<{ fileId: string }>) { + return RequestContext.create(ORM.em, async () => { + const file = await ORM.em.getRepository(File).findOneOrFail( + { id: job.data.fileId }, + { + filters: { deleted: false } + } + ); + + const extraction = await extract( + file.filename, + s3Client + .getObject({ + Bucket: S3_BUCKET_FILE_STORAGE, + Key: file.storageId + }) + .createReadStream() + ); + const extractionObject = await s3Client + .upload({ + Bucket: S3_BUCKET_FILE_STORAGE, + Key: randomUUID(), + Body: extraction + }) + .promise(); + file.extraction = new Extraction({ jobId: job.id, storageId: extractionObject.Key }); + + await ORM.em.flush(); + }); +} + +export const { queue, worker } = createQueue({ + name: QueueName.FILES_EXTRACTION, + jobHandler, + jobsOptions: { attempts: 5 }, + workerOptions: { + concurrency: 100 + } +}); diff --git a/src/files/utils/wait-for-extraction.ts b/src/files/utils/wait-for-extraction.ts new file mode 100644 index 0000000..9a34242 --- /dev/null +++ b/src/files/utils/wait-for-extraction.ts @@ -0,0 +1,57 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Loaded } from '@mikro-orm/core'; +import { DelayedError, Job } from 'bullmq'; + +import { File } from '../entities/file.entity.js'; + +import { queue as extractionQueue } from '@/files/jobs/extraction.queue.js'; + +export async function waitForExtraction( + job: Job, + files: Loaded[] +): Promise<{ ready: File[]; failed: { file: File; err: any }[] }> { + const ready = [], + failed = []; + for (const file of files) { + try { + if (!file.extraction) throw new Error('Extraction not found'); + if (!file.extraction.storageId) { + if (!file.extraction.jobId) throw new Error('Extraction job not found'); + + const extractionJob = await extractionQueue.getJob(file.extraction.jobId); + if (!extractionJob) throw new Error('Extraction job not found'); + + const state = await extractionJob.getState(); + + if (state == 'failed') { + throw new Error('Extraction job failed, unable to proceed'); + } + if (state !== 'completed') { + await job.moveToDelayed(Date.now() + 3000, job.token); + throw new DelayedError(); + } + ready.push(file); + } + } catch (err) { + if (err instanceof DelayedError) throw err; + failed.push({ file, err }); + } + } + + return { ready, failed }; +} diff --git a/src/jobs/bullmq.ts b/src/jobs/bullmq.ts new file mode 100644 index 0000000..4d7f011 --- /dev/null +++ b/src/jobs/bullmq.ts @@ -0,0 +1,141 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { DefaultJobOptions, Job, Queue, Worker, WorkerOptions } from 'bullmq'; +import { isTruthy } from 'remeda'; + +import { createClient } from '../redis.js'; +import { getLogger } from '../logger.js'; +import { gateway } from '../metrics.js'; + +import { QueueName } from './constants.js'; + +import { jobLocalStorage } from '@/context.js'; + +const getQueueLogger = (queueName: string, job?: Job) => + getLogger().child({ + queueName: queueName, + job: job && { + id: job.id, + name: job.name, + repeatJobKey: job.repeatJobKey, + failedReason: job.failedReason, + data: job.data + } + }); + +const logger = getLogger(); + +const connection = createClient({ + // https://docs.bullmq.io/guide/going-to-production#maxretriesperrequest + maxRetriesPerRequest: null +}); + +const defaultJobOptions = { + removeOnComplete: true, + removeOnFail: true, + attempts: 3, + backoff: { + type: 'exponential', + delay: 1000 + } +}; + +function addCallbacks(worker: Worker, queue: Queue) { + worker.on('active', (job) => { + getQueueLogger(queue.name, job).info('Job started'); + }); + + worker.on('error', (err) => { + getQueueLogger(queue.name).warn({ err }, `Worker failed`); + }); + + worker.on('failed', async (job, err) => { + getQueueLogger(queue.name, job).error({ err }, `Job failed`); + }); + + worker.on('completed', async (job) => { + getQueueLogger(queue.name, job).info(`Job done`); + try { + await gateway?.push({ jobName: queue.name }); + } catch (err) { + getQueueLogger(queue.name, job).warn({ err }, 'Failed to push metrics'); + } + }); +} + +const Queues = new Map(); + +interface CreateQueueInput { + name: QueueName; + jobsOptions?: DefaultJobOptions; + workerOptions?: Partial>; + jobHandler: (job: Job) => Promise; +} + +export function createQueue({ + name, + jobsOptions, + workerOptions, + jobHandler +}: CreateQueueInput) { + const queue = new Queue(name, { + connection: connection.options, + defaultJobOptions: jobsOptions ? { ...defaultJobOptions, ...jobsOptions } : defaultJobOptions + }); + + queue.on('error', (err) => { + getQueueLogger(name).error({ err }, `Queue has failed`); + }); + + const worker = new Worker( + name, + (job) => jobLocalStorage.run({ job }, () => jobHandler(job)), + + { + // We need to set autorun to false otherwise the worker might pick up stuff while ORM is not ready + autorun: false, + ...workerOptions, + connection: connection.options + } + ); + + addCallbacks(worker, queue); + + Queues.set(name, { queue, worker }); + + return { queue, worker }; +} + +export function runWorkers(queueNames: QueueName[]) { + queueNames.forEach((queueName) => { + if (!Queues.has(queueName)) throw Error(`Worker for ${queueName} has not been registered!`); + }); + const workers = queueNames + .map((name) => Queues.get(name)) + .filter(isTruthy) + .map(({ worker }) => worker); + + workers.forEach((worker) => worker.run()); + + logger.info({ queueNames }, `Workers started successfully`); +} + +export async function closeAllWorkers() { + await Promise.all([...Queues.values()].map(({ worker }) => worker.close())); + connection.quit(); + logger.info('Workers shutdown successfully'); +} diff --git a/src/jobs/constants.ts b/src/jobs/constants.ts new file mode 100644 index 0000000..fefcf01 --- /dev/null +++ b/src/jobs/constants.ts @@ -0,0 +1,26 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const QueueName = { + RUNS: 'runs', + RUNS_CLEANUP: 'runs:cleanup', + THREADS_CLEANUP: 'threads:cleanup', + VECTOR_STORES_CLEANUP: 'vectorStores:cleanup', + VECTOR_STORES_FILE_PROCESSOR: 'vectorStores:fileProcessor', + FILES_EXTRACTION: 'files:extraction', + FILES_CLEANUP: 'files:cleanup' +} as const; +export type QueueName = (typeof QueueName)[keyof typeof QueueName]; diff --git a/src/jobs/jobs.ts b/src/jobs/jobs.ts new file mode 100644 index 0000000..1a31e0a --- /dev/null +++ b/src/jobs/jobs.ts @@ -0,0 +1,51 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { queue as cleanupVectorStoresQueue } from '@/vector-store-files/queues/cleanup-vector-store.queue.js'; +import { queue as runsCleanupQueue } from '@/runs/jobs/runs-cleanup.queue.js'; +import { queue as cleanupThreadsQueue } from '@/threads/jobs/cleanup.queue.js'; +import { queue as filesCleanupQueue } from '@/files/jobs/cleanup.queue.js'; +import { QueueName } from '@/jobs/constants.js'; + +export const createCronJobs = async () => { + await runsCleanupQueue.add(QueueName.RUNS_CLEANUP, null, { + repeat: { + pattern: '0 */1 * * * *' + }, + jobId: QueueName.RUNS_CLEANUP + }); + + await cleanupVectorStoresQueue.add(QueueName.VECTOR_STORES_CLEANUP, null, { + repeat: { + pattern: '0 */15 * * * *' + }, + jobId: QueueName.VECTOR_STORES_CLEANUP + }); + + await cleanupThreadsQueue.add(QueueName.THREADS_CLEANUP, null, { + repeat: { + pattern: '0 0 */1 * * *' + }, + jobId: QueueName.THREADS_CLEANUP + }); + + await filesCleanupQueue.add(QueueName.FILES_CLEANUP, null, { + repeat: { + pattern: '0 0 */1 * * *' + }, + jobId: QueueName.FILES_CLEANUP + }); +}; diff --git a/src/jobs/worker.ts b/src/jobs/worker.ts new file mode 100644 index 0000000..9732856 --- /dev/null +++ b/src/jobs/worker.ts @@ -0,0 +1,48 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as http from 'node:http'; +import path from 'node:path'; + +import { Utils } from '@mikro-orm/core'; +import { globby } from 'globby'; + +import { runWorkers } from '@/jobs/bullmq.js'; +import { PORT, RUN_BULLMQ_WORKERS } from '@/config.js'; +import { getLogger } from '@/logger.js'; +import { createTerminus } from '@/terminus.js'; + +const logger = getLogger(); + +async function discoverQueues() { + const isTsNode = Utils.detectTsNode(); + const queueGlobs = isTsNode ? './**/*.queue.ts' : './**/*.queue.js'; + const cwd = isTsNode ? `${process.cwd()}/src` : `${process.cwd()}/dist`; + const queues = await globby(queueGlobs, { cwd }); + logger.info({ queues }, `Discovered queues.`); + await Promise.all(queues.map((file) => import(path.join(cwd, file)))); +} + +try { + await discoverQueues(); + runWorkers(RUN_BULLMQ_WORKERS); + const server = http.createServer((_, res) => res.writeHead(404).end()); + createTerminus(server); + server.listen({ port: PORT, host: '0.0.0.0' }); +} catch (err) { + logger.fatal({ err }, 'Failed to start worker!'); + process.exit(1); +} diff --git a/src/logger.ts b/src/logger.ts new file mode 100644 index 0000000..ae121e4 --- /dev/null +++ b/src/logger.ts @@ -0,0 +1,101 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import os from 'node:os'; +import { randomUUID } from 'node:crypto'; +import { IncomingMessage } from 'node:http'; + +import { Logger, LoggerOptions, pino } from 'pino'; +import { FastifyReply, FastifyRequest } from 'fastify'; +import { requestContext } from '@fastify/request-context'; + +import { LOG_LEVEL } from './config.js'; + +export const LogLabels = { + ALERT: 'alert', + CORRELATION_ID: 'correlationId' +} as const; + +export const createLogger = ( + options?: Omit +): Logger => + pino({ + ...options, + name: 'bee-api', + level: LOG_LEVEL, + base: { hostname: os.hostname(), ...options?.base }, + timestamp: pino.stdTimeFunctions.isoTime, + formatters: { + level(label) { + return { level: label }; + }, + ...options?.formatters + } + }); + +export const fastifyLogger = createLogger({ + serializers: { + req(request: FastifyRequest) { + return { + host: + request.headers['x-forwarded-host'] || + request.headers.host || + request.headers[':authority'], + correlationId: request.id || null, + ipAddress: request.ip || request.headers['x-forwarded-for'] || request.socket.remoteAddress, + method: request.method, + url: request.url, + hostname: request.hostname, + params: request.params + }; + }, + res(response: FastifyReply) { + return { + hostname: response.request?.hostname, + correlationId: response.request?.id || null, + statusMessage: response.raw?.statusMessage, + statusCode: response.statusCode + }; + } + } +}); + +export function getLogger() { + const request = requestContext.get('req'); + if (!request?.id) { + return fastifyLogger; + } + return fastifyLogger.child({ + [LogLabels.CORRELATION_ID]: request.id + }); +} + +export function getServiceLogger(service: string) { + return getLogger().child({ service }); +} + +export function getJobLogger(job: string) { + return getLogger().child({ job }); +} + +export const CORRELATION_ID_HEADER = 'x-correlation-id'; + +export const getCorrelationId = (req: IncomingMessage) => { + const correlationId = Array.isArray(req.headers[CORRELATION_ID_HEADER]) + ? req.headers[CORRELATION_ID_HEADER][0] + : req.headers[CORRELATION_ID_HEADER]; + return correlationId ?? randomUUID(); +}; diff --git a/src/messages/attachment.entity.ts b/src/messages/attachment.entity.ts new file mode 100644 index 0000000..a25d755 --- /dev/null +++ b/src/messages/attachment.entity.ts @@ -0,0 +1,44 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, ManyToOne, Property, Ref } from '@mikro-orm/core'; + +import { File } from '@/files/entities/file.entity.js'; +import { ToolType } from '@/tools/entities/tool/tool.entity.js'; + +export const attachmentTypes = [ + ToolType.CODE_INTERPRETER, + ToolType.FILE_SEARCH, + ToolType.USER, + ToolType.SYSTEM +] satisfies Partial[]; +export type AttachmentType = typeof attachmentTypes; + +@Embeddable() +export class Attachment { + @ManyToOne() + file!: Ref; + + @Property() + tools?: { type: (typeof attachmentTypes)[number]; id?: string }[]; + + constructor(input: AttachmentInput) { + this.file = input.file; + this.tools = input.tools; + } +} + +export type AttachmentInput = Pick; diff --git a/src/messages/dtos/message-create.ts b/src/messages/dtos/message-create.ts new file mode 100644 index 0000000..2a1836c --- /dev/null +++ b/src/messages/dtos/message-create.ts @@ -0,0 +1,119 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { MessageRole } from '../message.entity.js'; + +import { messageSchema } from './message.js'; + +import { metadataSchema } from '@/schema.js'; +import { ToolType } from '@/tools/entities/tool/tool.entity.js'; + +export const messageCreateParamsSchema = { + type: 'object', + required: ['thread_id'], + additionalProperties: false, + properties: { + thread_id: { type: 'string' } + } +} as const satisfies JSONSchema; +export type MessageCreateParams = FromSchema; + +export const messageCreateBodySchema = { + type: 'object', + required: ['role', 'content'], + additionalProperties: false, + properties: { + role: { + type: 'string', + enum: Object.values(MessageRole) + }, + content: { + type: 'string' + }, + attachments: { + type: 'array', + nullable: true, + items: { + type: 'object', + additionalProperties: false, + required: ['file_id'], + properties: { + file_id: { + type: 'string' + }, + tools: { + type: 'array', + minItems: 1, + items: { + type: 'object', + oneOf: [ + { + additionalProperties: false, + required: ['type'], + properties: { + type: { + const: ToolType.CODE_INTERPRETER + } + } + }, + { + additionalProperties: false, + required: ['type'], + properties: { + type: { + const: ToolType.FILE_SEARCH + } + } + }, + { + additionalProperties: false, + required: ['type', 'id'], + properties: { + type: { + const: ToolType.SYSTEM + }, + id: { + type: 'string' + } + } + }, + { + additionalProperties: false, + required: ['type', 'id'], + properties: { + type: { + const: ToolType.USER + }, + id: { + type: 'string' + } + } + } + ] + } + } + } + } + }, + metadata: metadataSchema + } +} as const satisfies JSONSchema; +export type MessageCreateBody = FromSchema; + +export const messageCreateResponseSchema = messageSchema; +export type MessageCreateResponse = FromSchema; diff --git a/src/messages/dtos/message-delete.ts b/src/messages/dtos/message-delete.ts new file mode 100644 index 0000000..97cc265 --- /dev/null +++ b/src/messages/dtos/message-delete.ts @@ -0,0 +1,27 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema } from 'json-schema-to-ts'; + +import { messageReadParamsSchema } from './message-read.js'; + +import { createDeleteSchema } from '@/schema.js'; + +export const messageDeleteParamsSchema = messageReadParamsSchema; +export type MessageDeleteParams = FromSchema; + +export const messageDeleteResponseSchema = createDeleteSchema('thread.message'); +export type MessageDeleteResponse = FromSchema; diff --git a/src/messages/dtos/message-delta.ts b/src/messages/dtos/message-delta.ts new file mode 100644 index 0000000..4c5fb71 --- /dev/null +++ b/src/messages/dtos/message-delta.ts @@ -0,0 +1,54 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { MessageRole } from '@/messages/message.entity.js'; + +export const messageDeltaSchema = { + type: 'object', + required: ['id', 'object', 'delta'], + properties: { + id: { type: 'string' }, + object: { const: 'thread.message.delta' }, + delta: { + type: 'object', + required: ['role', 'content'], + properties: { + role: { type: 'string', enum: Object.values(MessageRole) }, + content: { + type: 'array', + items: { + type: 'object', + required: ['index', 'type', 'text'], + properties: { + index: { type: 'integer' }, + type: { const: 'text' }, + text: { + type: 'object', + required: ['value'], + properties: { + value: { type: 'string' } + } + } + } + } + } + } + } + } +} as const satisfies JSONSchema; +export type MessageDelta = FromSchema; diff --git a/src/messages/dtos/message-read.ts b/src/messages/dtos/message-read.ts new file mode 100644 index 0000000..7a27706 --- /dev/null +++ b/src/messages/dtos/message-read.ts @@ -0,0 +1,33 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { messageSchema } from './message.js'; + +export const messageReadParamsSchema = { + type: 'object', + required: ['thread_id', 'message_id'], + additionalProperties: false, + properties: { + thread_id: { type: 'string' }, + message_id: { type: 'string' } + } +} as const satisfies JSONSchema; +export type MessageReadParams = FromSchema; + +export const messageReadResponseSchema = messageSchema; +export type MessageReadResponse = FromSchema; diff --git a/src/messages/dtos/message-update.ts b/src/messages/dtos/message-update.ts new file mode 100644 index 0000000..beebb72 --- /dev/null +++ b/src/messages/dtos/message-update.ts @@ -0,0 +1,44 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { messageSchema } from './message.js'; + +import { metadataSchema } from '@/schema.js'; + +export const messageUpdateParamsSchema = { + type: 'object', + required: ['thread_id', 'message_id'], + additionalProperties: false, + properties: { + thread_id: { type: 'string' }, + message_id: { type: 'string' } + } +} as const satisfies JSONSchema; +export type MessageUpdateParams = FromSchema; + +export const messageUpdateBodySchema = { + type: 'object', + additionalProperties: false, + properties: { + metadata: metadataSchema + } +} as const satisfies JSONSchema; +export type MessageUpdateBody = FromSchema; + +export const messageUpdateResponseSchema = messageSchema; +export type MessageUpdateResponse = FromSchema; diff --git a/src/messages/dtos/message.ts b/src/messages/dtos/message.ts new file mode 100644 index 0000000..9032207 --- /dev/null +++ b/src/messages/dtos/message.ts @@ -0,0 +1,119 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { MessageRole } from '../message.entity.js'; + +import { metadataSchema } from '@/schema.js'; +import { ToolType } from '@/tools/entities/tool/tool.entity.js'; + +export const messageSchema = { + type: 'object', + required: ['id', 'role', 'content', 'metadata', 'created_at', 'object'], + properties: { + id: { type: 'string' }, + object: { const: 'thread.message' }, + role: { + type: 'string', + enum: Object.values(MessageRole) + }, + content: { + type: 'array', + items: { + type: 'object', + required: ['type', 'text'], + properties: { + type: { const: 'text' }, + text: { + type: 'object', + required: ['value'], + properties: { + value: { type: 'string' } + } + } + } + } + }, + run_id: { type: 'string' }, + metadata: metadataSchema, + created_at: { type: 'number' }, + attachments: { + type: 'array', + nullable: true, + items: { + type: 'object', + required: ['file_id', 'tools'], + properties: { + file_id: { + type: 'string' + }, + tools: { + type: 'array', + items: { + type: 'object', + oneOf: [ + { + additionalProperties: false, + required: ['type'], + properties: { + type: { + const: ToolType.CODE_INTERPRETER + } + } + }, + { + additionalProperties: false, + required: ['type'], + properties: { + type: { + const: ToolType.FILE_SEARCH + } + } + }, + { + additionalProperties: false, + required: ['type', 'id'], + properties: { + type: { + const: ToolType.SYSTEM + }, + id: { + type: 'string' + } + } + }, + { + additionalProperties: false, + required: ['type', 'id'], + properties: { + type: { + const: ToolType.USER + }, + id: { + type: 'string' + } + } + } + ] + } + } + } + } + } + } +} as const satisfies JSONSchema; +export type Message = FromSchema; diff --git a/src/messages/dtos/messages-list.ts b/src/messages/dtos/messages-list.ts new file mode 100644 index 0000000..0608e68 --- /dev/null +++ b/src/messages/dtos/messages-list.ts @@ -0,0 +1,37 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { messageSchema } from './message.js'; + +import { createPaginationQuerySchema, withPagination } from '@/schema.js'; + +export const messagesListParamsSchema = { + type: 'object', + required: ['thread_id'], + additionalProperties: false, + properties: { + thread_id: { type: 'string' } + } +} as const satisfies JSONSchema; +export type MessagesListParams = FromSchema; + +export const messagesListQuerySchema = createPaginationQuerySchema(); +export type MessagesListQuery = FromSchema; + +export const messagesListResponseSchema = withPagination(messageSchema); +export type MessagesListResponse = FromSchema; diff --git a/src/messages/message.entity.ts b/src/messages/message.entity.ts new file mode 100644 index 0000000..4c31bee --- /dev/null +++ b/src/messages/message.entity.ts @@ -0,0 +1,83 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embedded, Entity, Enum, Index, ManyToOne, Property, Ref } from '@mikro-orm/core'; + +import { Attachment } from './attachment.entity.js'; + +import { Thread } from '@/threads/thread.entity.js'; +import { Run } from '@/runs/entities/run.entity.js'; +import { + PrincipalScopedEntity, + PrincipalScopedEntityInput +} from '@/common/principal-scoped.entity.js'; + +export const MessageRole = { + USER: 'user', + ASSISTANT: 'assistant' +} as const; +export type MessageRole = (typeof MessageRole)[keyof typeof MessageRole]; + +export const MessageStatus = { + IN_PROGRESS: 'in_progress', + INCOMPLETE: 'incomplete', + COMPLETED: 'completed' +} as const; +export type MessageStatus = (typeof MessageStatus)[keyof typeof MessageStatus]; + +@Entity() +export class Message extends PrincipalScopedEntity { + getIdPrefix(): string { + return 'msg'; + } + + @Index() + @ManyToOne() + thread: Ref; + + @ManyToOne() + run?: Ref; // Run that created the message, applies to assistant messages generated on the server + + @Enum(() => MessageRole) + role: MessageRole; + + @Property() + content: string; + + @Enum(() => MessageStatus) + status: MessageStatus; + + @Property() + order: number; // secondary ordering after createdAt + + @Embedded({ object: true }) + attachments?: Attachment[]; + + constructor({ thread, run, role, content, order, status, attachments, ...rest }: MessageInput) { + super(rest); + this.thread = thread; + this.run = run; + this.role = role; + this.content = content; + this.order = order ?? 0; + this.status = status ?? MessageStatus.COMPLETED; + this.attachments = attachments; + } +} + +export type MessageInput = PrincipalScopedEntityInput & + Pick & + Partial>; diff --git a/src/messages/messages.module.ts b/src/messages/messages.module.ts new file mode 100644 index 0000000..7848dbd --- /dev/null +++ b/src/messages/messages.module.ts @@ -0,0 +1,136 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FastifyPluginAsyncJsonSchemaToTs } from '@fastify/type-provider-json-schema-to-ts'; +import { StatusCodes } from 'http-status-codes'; + +import { + MessageCreateBody, + MessageCreateParams, + messageCreateBodySchema, + messageCreateParamsSchema, + messageCreateResponseSchema +} from './dtos/message-create.js'; +import { + createMessage, + deleteMessage, + listMessages, + readMessage, + updateMessage +} from './messages.service.js'; +import { + MessageReadParams, + messageReadParamsSchema, + messageReadResponseSchema +} from './dtos/message-read.js'; +import { + MessagesListParams, + MessagesListQuery, + messagesListParamsSchema, + messagesListQuerySchema, + messagesListResponseSchema +} from './dtos/messages-list.js'; +import { + MessageUpdateBody, + MessageUpdateParams, + messageUpdateBodySchema, + messageUpdateParamsSchema, + messageUpdateResponseSchema +} from './dtos/message-update.js'; +import { MessageDeleteParams, messageDeleteParamsSchema } from './dtos/message-delete.js'; + +import { Tag } from '@/swagger.js'; +import { createDeleteSchema } from '@/schema.js'; + +export const messagesModule: FastifyPluginAsyncJsonSchemaToTs = async (app) => { + app.post<{ Params: MessageCreateParams; Body: MessageCreateBody }>( + '/threads/:thread_id/messages', + { + schema: { + params: messageCreateParamsSchema, + body: messageCreateBodySchema, + response: { [StatusCodes.OK]: messageCreateResponseSchema }, + tags: [Tag.OPENAI_ASSISTANTS_API] + }, + preHandler: app.auth() + }, + async (req) => { + return createMessage({ ...req.body, ...req.params }); + } + ); + + app.get<{ Params: MessageReadParams }>( + '/threads/:thread_id/messages/:message_id', + { + schema: { + params: messageReadParamsSchema, + response: { [StatusCodes.OK]: messageReadResponseSchema }, + tags: [Tag.OPENAI_ASSISTANTS_API] + }, + preHandler: app.auth() + }, + async (req) => { + return readMessage(req.params); + } + ); + + app.post<{ Params: MessageUpdateParams; Body: MessageUpdateBody }>( + '/threads/:thread_id/messages/:message_id', + { + schema: { + params: messageUpdateParamsSchema, + body: messageUpdateBodySchema, + response: { [StatusCodes.OK]: messageUpdateResponseSchema }, + tags: [Tag.OPENAI_ASSISTANTS_API] + }, + preHandler: app.auth() + }, + async (req) => { + return updateMessage({ ...req.params, ...req.body }); + } + ); + + app.get<{ Querystring: MessagesListQuery; Params: MessagesListParams }>( + '/threads/:thread_id/messages', + { + schema: { + params: messagesListParamsSchema, + querystring: messagesListQuerySchema, + response: { [StatusCodes.OK]: messagesListResponseSchema }, + tags: [Tag.OPENAI_ASSISTANTS_API] + }, + preHandler: app.auth() + }, + async (req) => { + return listMessages({ ...req.params, ...req.query }); + } + ); + + app.delete<{ Params: MessageDeleteParams }>( + '/threads/:thread_id/messages/:message_id', + { + preHandler: app.auth(), + schema: { + params: messageDeleteParamsSchema, + response: { + [StatusCodes.OK]: createDeleteSchema('thread.message') + }, + tags: [Tag.OPENAI_ASSISTANTS_API] + } + }, + async (req) => deleteMessage(req.params) + ); +}; diff --git a/src/messages/messages.service.ts b/src/messages/messages.service.ts new file mode 100644 index 0000000..0a4e531 --- /dev/null +++ b/src/messages/messages.service.ts @@ -0,0 +1,235 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Loaded, ref } from '@mikro-orm/core'; +import dayjs from 'dayjs'; +import { isNonNullish, unique } from 'remeda'; + +import { Message } from './message.entity.js'; +import { + MessageCreateBody, + MessageCreateParams, + MessageCreateResponse +} from './dtos/message-create.js'; +import { MessageReadParams, MessageReadResponse } from './dtos/message-read.js'; +import { + MessagesListParams, + MessagesListQuery, + MessagesListResponse +} from './dtos/messages-list.js'; +import type { Message as MessageDto } from './dtos/message.js'; +import { + MessageUpdateBody, + MessageUpdateParams, + MessageUpdateResponse +} from './dtos/message-update.js'; +import { MessageDeleteParams, MessageDeleteResponse } from './dtos/message-delete.js'; +import { Attachment, attachmentTypes } from './attachment.entity.js'; + +import { Thread } from '@/threads/thread.entity.js'; +import { ORM } from '@/database.js'; +import { createPaginatedResponse } from '@/utils/pagination.js'; +import { getUpdatedValue } from '@/utils/update.js'; +import { createDeleteResponse } from '@/utils/delete.js'; +import { snakeToCamel } from '@/utils/strings.js'; +import { File, FilePurpose } from '@/files/entities/file.entity.js'; +import { APIError, APIErrorCode } from '@/errors/error.entity.js'; +import { Tool, ToolType } from '@/tools/entities/tool/tool.entity.js'; +import { SystemTools } from '@/tools/entities/tool-calls/system-call.entity.js'; + +export function toMessageDto(message: Loaded): MessageDto { + return { + id: message.id, + object: 'thread.message', + role: message.role, + content: [{ type: 'text', text: { value: message.content } }], + run_id: message.run?.id, + metadata: message.metadata ?? {}, + created_at: dayjs(message.createdAt).unix(), + attachments: message.attachments?.map(toAttachmentDto) ?? null + }; +} + +function toAttachmentDto(attachment: Attachment) { + return { + file_id: attachment.file.id, + tools: (attachment.tools ?? []).map(toToolDto) + }; +} + +function toToolDto(tool: { type: (typeof attachmentTypes)[number]; id?: string }) { + switch (tool.type) { + case ToolType.CODE_INTERPRETER: + case ToolType.FILE_SEARCH: + return { type: tool.type }; + case ToolType.USER: + case ToolType.SYSTEM: + if (!tool.id) throw new Error('Tool id not found'); + return { type: tool.type, id: tool.id }; + } +} + +export async function createMessage( + body: MessageCreateParams & MessageCreateBody +): Promise { + const message = await createMessageEntity(body); + await ORM.em.flush(); + return toMessageDto(message); +} + +export async function createMessageEntity({ + thread_id, + role, + content, + metadata, + attachments, + order +}: MessageCreateParams & MessageCreateBody & { order?: number }): Promise { + const thread = await ORM.em.getRepository(Thread).findOneOrFail({ id: thread_id }); + + const attachmentFiles = attachments + ? await ORM.em.getRepository(File).find({ + id: { $in: attachments.map((attachment) => attachment.file_id) }, + purpose: { $in: [FilePurpose.ASSISTANTS, FilePurpose.ASSISTANTS_OUTPUT] } + }) + : []; + + const attachmentToolIds = attachments + ? attachments + .flatMap( + (attachment) => + attachment.tools?.flatMap((t) => + t.type === 'user' || t.type === 'system' ? t.id : [] + ) ?? [] + ) + .filter((id) => !Object.keys(SystemTools).includes(id.toUpperCase())) + : []; + const toolsForAttachments = await ORM.em.getRepository(Tool).find({ + id: { + $in: attachmentToolIds + } + }); + + if (toolsForAttachments.length !== unique(attachmentToolIds).length) { + throw new APIError({ + message: 'Some tool not found', + code: APIErrorCode.NOT_FOUND + }); + } + + const _attachments = attachments + ? attachments + .map((attachment) => { + const file = attachmentFiles.find( + (attachmentFile) => attachmentFile.id === attachment.file_id + ); + if (!file) + throw new APIError({ + message: 'File not found', + code: APIErrorCode.NOT_FOUND + }); + return new Attachment({ + file: ref(file), + tools: attachment.tools?.map((tool) => ({ + type: tool.type, + id: tool.type === 'system' || tool.type === 'user' ? tool.id : undefined + })) + }); + }) + .filter(isNonNullish) + : undefined; + + const message = new Message({ + thread: ref(thread), + role, + content, + metadata, + attachments: _attachments, + order + }); + ORM.em.persist(message); + return message; +} + +export async function readMessage({ + thread_id, + message_id +}: MessageReadParams): Promise { + const message = await ORM.em.getRepository(Message).findOneOrFail({ + id: message_id, + thread: thread_id + }); + return toMessageDto(message); +} + +export async function updateMessage({ + thread_id, + message_id, + metadata +}: MessageUpdateParams & MessageUpdateBody): Promise { + const message = await ORM.em.getRepository(Message).findOneOrFail({ + id: message_id, + thread: thread_id + }); + message.metadata = getUpdatedValue(metadata, message.metadata); + await ORM.em.flush(); + return toMessageDto(message); +} + +export async function listMessages({ + thread_id, + limit, + after, + before, + order, + order_by +}: MessagesListParams & MessagesListQuery): Promise { + const repo = ORM.em.getRepository(Message); + const aftr = after ? await repo.findOneOrFail({ id: after }) : undefined; + const bfr = before ? await repo.findOneOrFail({ id: before }) : undefined; + const cursor = await repo.findByCursor( + { + thread: thread_id + }, + { + first: limit, + before: bfr && { + [snakeToCamel(order_by)]: bfr[snakeToCamel(order_by) as keyof Message], + id: bfr.id + }, + after: aftr && { + [snakeToCamel(order_by)]: aftr[snakeToCamel(order_by) as keyof Message], + id: aftr.id + }, + orderBy: [{ [snakeToCamel(order_by)]: order }, { order }, { id: order }] + } + ); + return createPaginatedResponse(cursor, toMessageDto); +} + +export async function deleteMessage({ + thread_id, + message_id +}: MessageDeleteParams): Promise { + const message = await ORM.em + .getRepository(Message) + .findOneOrFail({ id: message_id, thread: thread_id }); + + message.delete(); + await ORM.em.flush(); + + return createDeleteResponse(message_id, 'thread.message'); +} diff --git a/src/metrics.ts b/src/metrics.ts new file mode 100644 index 0000000..f76a7a3 --- /dev/null +++ b/src/metrics.ts @@ -0,0 +1,47 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FastifyPluginAsync } from 'fastify'; +import { fastifyPlugin } from 'fastify-plugin'; +import { Pushgateway, Registry, collectDefaultMetrics, register } from 'prom-client'; + +import { PROMETHEUS_PUSHGATEWAY_URL } from './config.js'; +import { Tag } from './swagger.js'; + +export const jobRegistry = new Registry(); +export const gateway = PROMETHEUS_PUSHGATEWAY_URL + ? new Pushgateway(PROMETHEUS_PUSHGATEWAY_URL, { timeout: 5000 }, jobRegistry) + : null; + +export const metricsPlugin: FastifyPluginAsync = fastifyPlugin(async (app) => { + collectDefaultMetrics(); + + app.get( + '/metrics', + { + schema: { + tags: [Tag.BEE_API] + } + }, + async (request, reply) => { + const payload = await register.metrics(); + return reply + .header('Content-Type', register.contentType) + .header('Cache-Control', 'no-cache') + .send(payload); + } + ); +}); diff --git a/src/mikro-orm.config.ts b/src/mikro-orm.config.ts new file mode 100644 index 0000000..28faa15 --- /dev/null +++ b/src/mikro-orm.config.ts @@ -0,0 +1,87 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import path from 'node:path'; +import fs from 'node:fs'; +import os from 'node:os'; + +import { LoadStrategy, Options } from '@mikro-orm/core'; +import { MongoDriver } from '@mikro-orm/mongodb'; +import { TsMorphMetadataProvider } from '@mikro-orm/reflection'; +import { Migrator } from '@mikro-orm/migrations-mongodb'; +import { SeedManager } from '@mikro-orm/seeder'; + +import { MONGODB_CA_CERT, MONGODB_DATABASE_NAME, MONGODB_URL } from './config.js'; + +if (process.env.NODE_ENV === 'production') { + process.env.MIKRO_ORM_NO_COLOR = 'true'; +} + +const baseConfig = { + metadataProvider: TsMorphMetadataProvider, + debug: process.env.NODE_ENV !== 'production' ? true : ['query', 'info'], + + /** + * We are having some ECONNRESET errors on the DIPC cluster. Seems like problem with f5 load balancer. + * These seems could help to fix the issue. Motivated by: + * https://github.com/strapi/strapi/issues/8117#issuecomment-702559536 + */ + pool: { + min: 2, + max: 10, + acquireTimeoutMillis: 8000, + idleTimeoutMillis: 8000, + reapIntervalMillis: 1000 + }, + loadStrategy: LoadStrategy.SELECT_IN, // Do not change, has security implications due to its effect on filters. See https://mikro-orm.io/docs/filters#filters-and-populating-of-relationships + forceUndefined: true +} as const satisfies Options; + +function createMongoTLSConfig() { + if (!MONGODB_CA_CERT) return; + + const rootMongoCertPath = path.join(os.tmpdir(), `mongodb-ca.pem`); + fs.writeFileSync(rootMongoCertPath, MONGODB_CA_CERT, 'utf-8'); + return { tls: true, tlsCAFile: rootMongoCertPath }; +} + +const config: Options = { + ...baseConfig, + entities: ['./dist/**/*.entity.js'], + entitiesTs: ['./src/**/*.entity.ts'], + clientUrl: MONGODB_URL, + dbName: MONGODB_DATABASE_NAME, + driver: MongoDriver, + driverOptions: { + ...createMongoTLSConfig() + }, + extensions: [Migrator, SeedManager], + migrations: { + path: './dist/migrations', + pathTs: './migrations', + // Need to set this, otherwise superuser is needed and our cloud database doesn't support that + // https://github.com/mikro-orm/mikro-orm/issues/190 + disableForeignKeys: false + }, + seeder: { + path: './dist/seeders', + pathTs: './seeders' + }, + ensureIndexes: true, + implicitTransactions: true +}; + +export default config; diff --git a/src/multipart.ts b/src/multipart.ts new file mode 100644 index 0000000..686e1b8 --- /dev/null +++ b/src/multipart.ts @@ -0,0 +1,55 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FastifyPluginAsync } from 'fastify'; +import fp from 'fastify-plugin'; +import multipart from '@fastify/multipart'; + +export const multipartPlugin: FastifyPluginAsync = fp.fastifyPlugin(async (app) => { + app.register(multipart, { + limits: { + fieldNameSize: 1024, // Max field name size in bytes + fieldSize: 1024, // Max field value size in bytes + fields: 10, // Max number of non-file fields + fileSize: Infinity, // For multipart forms, the max file size in bytes + files: 1, // Max number of file fields + headerPairs: 2000 // Max number of header key=>value pairs + } + }); + app.addHook('preValidation', async (req) => { + if (!req.isMultipart()) { + return; + } + const data = await req.file(); + if (!data) return; + + // Modification of https://github.com/fastify/fastify-multipart/blob/469b3e56dd5dad529973c8a3c845e19772630bfe/index.js#L92 + req.body = data.fields; + const body = {} as Record; + const reqBodyKeys = Object.keys(req.body as any); + for (let i = 0; i < reqBodyKeys.length; ++i) { + const key = reqBodyKeys[i]; + const field = (req.body as any)[key]; + + if (field.value !== undefined) { + body[key] = field.value; + } else if (field.type === 'file') { + body[key] = field; + } + } + req.body = body; + }); +}); diff --git a/src/observe/api/client.ts b/src/observe/api/client.ts new file mode 100644 index 0000000..35340ab --- /dev/null +++ b/src/observe/api/client.ts @@ -0,0 +1,36 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import createClient from 'openapi-fetch'; + +import { paths } from './schema.js'; + +import { BEE_OBSERVE_API_AUTH_KEY, BEE_OBSERVE_API_URL } from '@/config.js'; + +export type Span = + paths['/trace']['post']['requestBody']['content']['application/json']['spans'][0]; + +export type Client = ReturnType>; + +export const client = BEE_OBSERVE_API_URL + ? createClient({ + baseUrl: BEE_OBSERVE_API_URL, + headers: { + ['x-bee-authorization']: BEE_OBSERVE_API_AUTH_KEY, + 'Content-Type': 'application/json' + } + }) + : undefined; diff --git a/src/observe/api/schema.d.ts b/src/observe/api/schema.d.ts new file mode 100644 index 0000000..6163a44 --- /dev/null +++ b/src/observe/api/schema.d.ts @@ -0,0 +1,1036 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * This file was auto-generated by openapi-typescript. + * Do not make direct changes to the file. + */ + +export interface paths { + '/span': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: { + parameters: { + query: { + include_attributes_ctx?: boolean; + trace_id: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Default Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': { + results: { + attributes: { + ctx?: { + [key: string]: unknown; + } | null; + data?: { + [key: string]: unknown; + } | null; + target: string; + }; + context: { + span_id: string; + }; + /** Format: date-time */ + end_time: string; + name: string; + parent_id?: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + status_message?: string; + }[]; + total_count: number; + }; + }; + }; + /** @description Server could not understand the request due to invalid syntax. In most cases relates with the schema validation. */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['BadRequestResponse']; + }; + }; + /** @description Unauthorized route access. */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['UnauthorizedResponse']; + }; + }; + /** @description The server encountered an unexpected condition that prevented it from fulfilling the request. */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['InternalServerErrorResponse']; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/trace': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: { + parameters: { + query: { + include_mlflow?: boolean; + include_mlflow_tree?: boolean; + include_tree?: boolean; + limit: number; + offset: number; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Default Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': { + results: { + finish_at: string; + id: string; + mlflow?: { + /** Format: date-time */ + created_at: string; + error?: { + code: string; + data?: { + [key: string]: unknown; + }; + message: string; + reason?: string; + } | null; + id: string; + request_id?: string; + /** @enum {string} */ + step: 'ADD_TREE' | 'CHECK_TREE' | 'CLOSE_TRACE' | 'START_TRACE'; + tree?: { + attributes: { + 'mlflow.spanType': string; + 'mlflow.traceRequestId': string; + } & { + [key: string]: unknown; + }; + context: { + span_id: string; + trace_id: string; + }; + end_time: number; + events: { + [key: string]: unknown; + }[]; + name: string; + parent_id?: string | null; + start_time: number; + status_code: string; + status_message: string; + }[]; + } | null; + request: { + connector?: { + version: string; + }; + framework?: { + version: string; + }; + history?: { + content: string; + metadata?: { + [key: string]: string; + }; + role: string; + }[]; + message?: string; + rawPrompt?: string; + } & { + [key: string]: unknown; + }; + response?: { + text: string; + } & { + [key: string]: unknown; + }; + start_at: string; + tree?: + | { + children: { + children: { + children: { + children: { + children: { + children: { + [key: string]: unknown; + }[]; + /** Format: date-time */ + end_time: string; + events?: { + data: { + [key: string]: unknown; + } | null; + /** Format: date-time */ + end_time: string; + name: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + status_message?: string | null; + }[]; + id: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + target: string; + }[]; + /** Format: date-time */ + end_time: string; + events?: { + data: { + [key: string]: unknown; + } | null; + /** Format: date-time */ + end_time: string; + name: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + status_message?: string | null; + }[]; + id: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + target: string; + }[]; + /** Format: date-time */ + end_time: string; + events?: { + data: { + [key: string]: unknown; + } | null; + /** Format: date-time */ + end_time: string; + name: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + status_message?: string | null; + }[]; + id: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + target: string; + }[]; + /** Format: date-time */ + end_time: string; + events?: { + data: { + [key: string]: unknown; + } | null; + /** Format: date-time */ + end_time: string; + name: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + status_message?: string | null; + }[]; + id: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + target: string; + }[]; + /** Format: date-time */ + end_time: string; + events?: { + data: { + [key: string]: unknown; + } | null; + /** Format: date-time */ + end_time: string; + name: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + status_message?: string | null; + }[]; + id: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + target: string; + }[]; + /** Format: date-time */ + end_time: string; + events?: { + data: { + [key: string]: unknown; + } | null; + /** Format: date-time */ + end_time: string; + name: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + status_message?: string | null; + }[]; + id: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + target: string; + }[] + | null; + }[]; + total_count: number; + }; + }; + }; + /** @description Server could not understand the request due to invalid syntax. In most cases relates with the schema validation. */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['BadRequestResponse']; + }; + }; + /** @description Unauthorized route access. */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['UnauthorizedResponse']; + }; + }; + /** @description The server encountered an unexpected condition that prevented it from fulfilling the request. */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['InternalServerErrorResponse']; + }; + }; + }; + }; + put?: never; + post: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + 'application/json': { + experiment_tracker?: { + experiment_id?: string; + run_id?: string; + } | null; + request: { + connector?: { + version: string; + }; + framework?: { + version: string; + }; + history?: { + content: string; + metadata?: { + [key: string]: string; + }; + role: string; + }[]; + message?: string; + rawPrompt?: string; + } & { + [key: string]: unknown; + }; + response?: { + text: string; + } & { + [key: string]: unknown; + }; + spans: { + attributes: { + ctx?: { + [key: string]: unknown; + } | null; + data?: { + [key: string]: unknown; + } | null; + target: string; + }; + context: { + span_id: string; + }; + /** Format: date-time */ + end_time: string; + name: string; + parent_id?: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + status_message?: string; + }[]; + }; + }; + }; + responses: { + /** @description Default Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': { + result: { + finish_at: string; + id: string; + mlflow?: { + /** Format: date-time */ + created_at: string; + error?: { + code: string; + data?: { + [key: string]: unknown; + }; + message: string; + reason?: string; + } | null; + id: string; + request_id?: string; + /** @enum {string} */ + step: 'ADD_TREE' | 'CHECK_TREE' | 'CLOSE_TRACE' | 'START_TRACE'; + tree?: { + attributes: { + 'mlflow.spanType': string; + 'mlflow.traceRequestId': string; + } & { + [key: string]: unknown; + }; + context: { + span_id: string; + trace_id: string; + }; + end_time: number; + events: { + [key: string]: unknown; + }[]; + name: string; + parent_id?: string | null; + start_time: number; + status_code: string; + status_message: string; + }[]; + } | null; + request: { + connector?: { + version: string; + }; + framework?: { + version: string; + }; + history?: { + content: string; + metadata?: { + [key: string]: string; + }; + role: string; + }[]; + message?: string; + rawPrompt?: string; + } & { + [key: string]: unknown; + }; + response?: { + text: string; + } & { + [key: string]: unknown; + }; + start_at: string; + tree?: + | { + children: { + children: { + children: { + children: { + children: { + children: { + [key: string]: unknown; + }[]; + /** Format: date-time */ + end_time: string; + events?: { + data: { + [key: string]: unknown; + } | null; + /** Format: date-time */ + end_time: string; + name: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + status_message?: string | null; + }[]; + id: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + target: string; + }[]; + /** Format: date-time */ + end_time: string; + events?: { + data: { + [key: string]: unknown; + } | null; + /** Format: date-time */ + end_time: string; + name: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + status_message?: string | null; + }[]; + id: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + target: string; + }[]; + /** Format: date-time */ + end_time: string; + events?: { + data: { + [key: string]: unknown; + } | null; + /** Format: date-time */ + end_time: string; + name: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + status_message?: string | null; + }[]; + id: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + target: string; + }[]; + /** Format: date-time */ + end_time: string; + events?: { + data: { + [key: string]: unknown; + } | null; + /** Format: date-time */ + end_time: string; + name: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + status_message?: string | null; + }[]; + id: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + target: string; + }[]; + /** Format: date-time */ + end_time: string; + events?: { + data: { + [key: string]: unknown; + } | null; + /** Format: date-time */ + end_time: string; + name: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + status_message?: string | null; + }[]; + id: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + target: string; + }[]; + /** Format: date-time */ + end_time: string; + events?: { + data: { + [key: string]: unknown; + } | null; + /** Format: date-time */ + end_time: string; + name: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + status_message?: string | null; + }[]; + id: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + target: string; + }[] + | null; + }; + }; + }; + }; + /** @description Server could not understand the request due to invalid syntax. In most cases relates with the schema validation. */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['BadRequestResponse']; + }; + }; + /** @description Unauthorized route access. */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['UnauthorizedResponse']; + }; + }; + /** @description The server can not find requested resource. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['NotFoundResponse']; + }; + }; + /** @description The server encountered an unexpected condition that prevented it from fulfilling the request. */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['InternalServerErrorResponse']; + }; + }; + }; + }; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + '/trace/{id}': { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get: { + parameters: { + query?: { + include_mlflow?: boolean; + include_mlflow_tree?: boolean; + include_tree?: boolean; + }; + header?: never; + path: { + id: string; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description Default Response */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': { + result: { + finish_at: string; + id: string; + mlflow?: { + /** Format: date-time */ + created_at: string; + error?: { + code: string; + data?: { + [key: string]: unknown; + }; + message: string; + reason?: string; + } | null; + id: string; + request_id?: string; + /** @enum {string} */ + step: 'ADD_TREE' | 'CHECK_TREE' | 'CLOSE_TRACE' | 'START_TRACE'; + tree?: { + attributes: { + 'mlflow.spanType': string; + 'mlflow.traceRequestId': string; + } & { + [key: string]: unknown; + }; + context: { + span_id: string; + trace_id: string; + }; + end_time: number; + events: { + [key: string]: unknown; + }[]; + name: string; + parent_id?: string | null; + start_time: number; + status_code: string; + status_message: string; + }[]; + } | null; + request: { + connector?: { + version: string; + }; + framework?: { + version: string; + }; + history?: { + content: string; + metadata?: { + [key: string]: string; + }; + role: string; + }[]; + message?: string; + rawPrompt?: string; + } & { + [key: string]: unknown; + }; + response?: { + text: string; + } & { + [key: string]: unknown; + }; + start_at: string; + tree?: + | { + children: { + children: { + children: { + children: { + children: { + children: { + [key: string]: unknown; + }[]; + /** Format: date-time */ + end_time: string; + events?: { + data: { + [key: string]: unknown; + } | null; + /** Format: date-time */ + end_time: string; + name: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + status_message?: string | null; + }[]; + id: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + target: string; + }[]; + /** Format: date-time */ + end_time: string; + events?: { + data: { + [key: string]: unknown; + } | null; + /** Format: date-time */ + end_time: string; + name: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + status_message?: string | null; + }[]; + id: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + target: string; + }[]; + /** Format: date-time */ + end_time: string; + events?: { + data: { + [key: string]: unknown; + } | null; + /** Format: date-time */ + end_time: string; + name: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + status_message?: string | null; + }[]; + id: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + target: string; + }[]; + /** Format: date-time */ + end_time: string; + events?: { + data: { + [key: string]: unknown; + } | null; + /** Format: date-time */ + end_time: string; + name: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + status_message?: string | null; + }[]; + id: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + target: string; + }[]; + /** Format: date-time */ + end_time: string; + events?: { + data: { + [key: string]: unknown; + } | null; + /** Format: date-time */ + end_time: string; + name: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + status_message?: string | null; + }[]; + id: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + target: string; + }[]; + /** Format: date-time */ + end_time: string; + events?: { + data: { + [key: string]: unknown; + } | null; + /** Format: date-time */ + end_time: string; + name: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + status_message?: string | null; + }[]; + id: string; + /** Format: date-time */ + start_time: string; + /** @enum {string} */ + status_code: 'ERROR' | 'OK'; + target: string; + }[] + | null; + }; + }; + }; + }; + /** @description Server could not understand the request due to invalid syntax. In most cases relates with the schema validation. */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['BadRequestResponse']; + }; + }; + /** @description Unauthorized route access. */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['UnauthorizedResponse']; + }; + }; + /** @description The server can not find requested resource. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['NotFoundResponse']; + }; + }; + /** @description The server encountered an unexpected condition that prevented it from fulfilling the request. */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['InternalServerErrorResponse']; + }; + }; + }; + }; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; +} +export type webhooks = Record; +export interface components { + schemas: { + BadRequestResponse: components['schemas']['BaseErrorResponse'] & { + /** @enum {unknown} */ + code: 'INVALID_INPUT'; + }; + BaseErrorResponse: { + code: string; + data?: { + [key: string]: unknown; + }; + message: string; + reason?: string; + }; + InternalServerErrorResponse: components['schemas']['BaseErrorResponse'] & { + /** @enum {unknown} */ + code: 'INTERNAL_SERVER_ERROR'; + }; + NotFoundResponse: components['schemas']['BaseErrorResponse'] & { + /** @enum {unknown} */ + code: 'NOT_FOUND'; + }; + UnauthorizedResponse: components['schemas']['BaseErrorResponse'] & { + /** @enum {unknown} */ + code: 'AUTH_ERROR'; + }; + }; + responses: never; + parameters: never; + requestBodies: never; + headers: never; + pathItems: never; +} +export type $defs = Record; +export type operations = Record; diff --git a/src/observe/dtos/shared.ts b/src/observe/dtos/shared.ts new file mode 100644 index 0000000..2db9599 --- /dev/null +++ b/src/observe/dtos/shared.ts @@ -0,0 +1,19 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { JSONSchema } from 'json-schema-to-ts'; + +export const includeProperty = { type: 'boolean', default: false } as const satisfies JSONSchema; diff --git a/src/observe/dtos/span-read.ts b/src/observe/dtos/span-read.ts new file mode 100644 index 0000000..3178116 --- /dev/null +++ b/src/observe/dtos/span-read.ts @@ -0,0 +1,31 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { includeProperty } from './shared.js'; + +export const spanReadQuerySchema = { + type: 'object', + required: ['trace_id'], + additionalProperties: false, + properties: { + trace_id: { type: 'string' }, + include_attributes_ctx: includeProperty + } +} as const satisfies JSONSchema; + +export type SpanReadQuery = FromSchema; diff --git a/src/observe/dtos/trace-read.ts b/src/observe/dtos/trace-read.ts new file mode 100644 index 0000000..178a1e3 --- /dev/null +++ b/src/observe/dtos/trace-read.ts @@ -0,0 +1,41 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { includeProperty } from './shared.js'; + +export const traceReadParamsSchema = { + type: 'object', + required: ['id'], + additionalProperties: false, + properties: { + id: { type: 'string' } + } +} as const satisfies JSONSchema; + +export const traceReadQuerySchema = { + type: 'object', + additionalProperties: false, + properties: { + include_tree: includeProperty, + include_mlflow: includeProperty, + include_mlflow_tree: includeProperty + } +} as const satisfies JSONSchema; + +export type TraceReadQuery = FromSchema; +export type TraceReadParams = FromSchema; diff --git a/src/observe/dtos/trace.ts b/src/observe/dtos/trace.ts new file mode 100644 index 0000000..0f44b25 --- /dev/null +++ b/src/observe/dtos/trace.ts @@ -0,0 +1,47 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +export const traceSchema = { + type: 'object', + required: ['id', 'iterations'], + additionalProperties: false, + properties: { + id: { type: 'string' }, + iterations: { + type: 'array', + items: { + type: 'object', + additionalProperties: false, + required: ['id', 'event'], + properties: { + id: { type: 'string' }, + event: { + type: 'object', + additionalProperties: false, + required: ['group_id'], + properties: { + group_id: { type: 'string' } + } + } + } + } + } + } +} as const satisfies JSONSchema; + +export type Trace = FromSchema; diff --git a/src/observe/entities/trace.entity.ts b/src/observe/entities/trace.entity.ts new file mode 100644 index 0000000..8733d43 --- /dev/null +++ b/src/observe/entities/trace.entity.ts @@ -0,0 +1,29 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, Property } from '@mikro-orm/core'; + +@Embeddable() +export class Trace { + @Property() + id!: string; + + constructor(input: TraceInput) { + Object.assign(this, input); + } +} + +export type TraceInput = Pick; diff --git a/src/observe/observe.module.ts b/src/observe/observe.module.ts new file mode 100644 index 0000000..abc6c0d --- /dev/null +++ b/src/observe/observe.module.ts @@ -0,0 +1,52 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FastifyPluginAsyncJsonSchemaToTs } from '@fastify/type-provider-json-schema-to-ts'; + +import { listSpans, getTrace } from './observe.service.js'; +import { traceReadParamsSchema, traceReadQuerySchema } from './dtos/trace-read.js'; +import { spanReadQuerySchema } from './dtos/span-read.js'; + +export const observeModule: FastifyPluginAsyncJsonSchemaToTs = async (app) => { + app.get( + '/trace/:id', + { + preHandler: app.auth(), + schema: { + params: traceReadParamsSchema, + querystring: traceReadQuerySchema, + hide: true + } + }, + async (req) => { + return getTrace({ ...req.params, ...req.query }); + } + ); + + app.get( + '/span', + { + preHandler: app.auth(), + schema: { + querystring: spanReadQuerySchema, + hide: true + } + }, + async (req) => { + return listSpans(req.query); + } + ); +}; diff --git a/src/observe/observe.service.ts b/src/observe/observe.service.ts new file mode 100644 index 0000000..2e80966 --- /dev/null +++ b/src/observe/observe.service.ts @@ -0,0 +1,58 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { client } from './api/client.js'; +import { SpanReadQuery } from './dtos/span-read.js'; +import { assertTracePermission, assertClient, processApiProxyResponse } from './utils.js'; +import { TraceReadParams, TraceReadQuery } from './dtos/trace-read.js'; + +export async function getTrace({ + id, + include_mlflow, + include_mlflow_tree, + include_tree +}: TraceReadParams & TraceReadQuery) { + await assertTracePermission({ traceId: id }); + assertClient(client); + + return processApiProxyResponse( + client.GET('/trace/{id}', { + params: { + path: { + id + }, + query: { + include_mlflow, + include_mlflow_tree, + include_tree + } + } + }) + ); +} + +export async function listSpans(query: SpanReadQuery) { + await assertTracePermission({ traceId: query.trace_id }); + assertClient(client); + + return processApiProxyResponse( + client.GET('/span', { + params: { + query: query + } + }) + ); +} diff --git a/src/observe/utils.ts b/src/observe/utils.ts new file mode 100644 index 0000000..cc63d70 --- /dev/null +++ b/src/observe/utils.ts @@ -0,0 +1,65 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FetchResponse } from 'openapi-fetch'; + +import { Client } from './api/client.js'; + +import { getServiceLogger } from '@/logger.js'; +import { ORM } from '@/database.js'; +import { Run } from '@/runs/entities/run.entity.js'; +import { APIError, APIErrorCode } from '@/errors/error.entity.js'; + +export const getTraceLogger = () => getServiceLogger('trace'); + +export async function assertTracePermission({ traceId }: { traceId: string }) { + await ORM.em.getRepository(Run).findOneOrFail({ + trace: { + id: traceId + } + }); +} + +export function assertClient(client: Client | undefined): asserts client is Client { + if (!client) { + throw new APIError({ + message: 'Bee observe API client is not defined', + code: APIErrorCode.SERVICE_UNAVAILABLE + }); + } +} + +type MediaType = `${string}/${string}`; +export async function processApiProxyResponse( + response: Promise> +): Promise['data']> { + const { data, error } = await response; + + if (error) { + getTraceLogger().error({ err: error }, 'Observe API: Invalid response'); + throw new APIError( + { + message: 'Observe API: Invalid response', + code: APIErrorCode.SERVICE_ERROR + }, + { + cause: error + } + ); + } + + return data; +} diff --git a/src/opentelemetry.ts b/src/opentelemetry.ts new file mode 100644 index 0000000..b369c65 --- /dev/null +++ b/src/opentelemetry.ts @@ -0,0 +1,39 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import 'dotenv/config'; + +import { NodeSDK, resources, metrics } from '@opentelemetry/sdk-node'; +import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node'; +import { BullMQInstrumentation } from '@appsignal/opentelemetry-instrumentation-bullmq'; +import { ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions'; +import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http'; +import { ATTR_DEPLOYMENT_ENVIRONMENT_NAME } from '@opentelemetry/semantic-conventions/incubating'; + +const ENV = process.env.ENVIRONMENT; + +export const opentelemetrySDK = new NodeSDK({ + resource: new resources.Resource({ + [ATTR_SERVICE_NAME]: `bee-api${ENV ? `-${ENV}` : ''}`, // Instana works best over service names + [ATTR_DEPLOYMENT_ENVIRONMENT_NAME]: ENV + }), + metricReader: new metrics.PeriodicExportingMetricReader({ exporter: new OTLPMetricExporter() }), + instrumentations: [ + ...getNodeAutoInstrumentations(), + new BullMQInstrumentation({ useProducerSpanAsConsumerParent: true }) + ] +}); +opentelemetrySDK.start(); diff --git a/src/rate-limit.ts b/src/rate-limit.ts new file mode 100644 index 0000000..e8aaa23 --- /dev/null +++ b/src/rate-limit.ts @@ -0,0 +1,68 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FastifyPluginAsync, FastifyRequest } from 'fastify'; +import fp from 'fastify-plugin'; +import rateLimit, { errorResponseBuilderContext } from '@fastify/rate-limit'; + +import { createClient } from './redis.js'; +import { AuthSecret, determineAuthType, scryptApiKey } from './auth/utils.js'; +import { toErrorResponseDto } from './errors/plugin.js'; +import { APIError, APIErrorCode } from './errors/error.entity.js'; + +export const rateLimitPlugin: FastifyPluginAsync = fp.default(async (app) => { + const redis = createClient({ + /** + * "The default parameters of a redis connection are not the fastest to provide a rate-limit. We suggest to customize the connectTimeout and maxRetriesPerRequest. + * Source: https://github.com/fastify/fastify-rate-limit + */ + connectTimeout: 1000, // 500 was too low, getting ETIMEDOUT + maxRetriesPerRequest: 1 + }); + + await app.register(rateLimit, { + global: true, + max: 25, + hook: 'onRequest', + timeWindow: 1000, + cache: 5000, + redis, + nameSpace: 'bee-api-ratelimit-', + skipOnError: true, + onExceeded: (req, key) => { + req.log.info({ key }, `Rate-limit exceeded`); + }, + errorResponseBuilder: (request: FastifyRequest, context: errorResponseBuilderContext) => { + return toErrorResponseDto( + new APIError({ + message: `Exceeded ${context.max} requests per ${context.after}`, + code: APIErrorCode.TOO_MANY_REQUESTS + }) + ); + }, + keyGenerator: (request: FastifyRequest): string => { + const authType = determineAuthType(request); + switch (authType.type) { + case AuthSecret.ACCESS_TOKEN: + return authType.value; + case AuthSecret.API_KEY: + return scryptApiKey(authType.value); + case AuthSecret.UNKNOWN: + return request.ip; + } + } + }); +}); diff --git a/src/redis.ts b/src/redis.ts new file mode 100644 index 0000000..db9a858 --- /dev/null +++ b/src/redis.ts @@ -0,0 +1,45 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Redis, RedisOptions } from 'ioredis'; + +import { REDIS_CA_CERT, REDIS_CACHE_CA_CERT, REDIS_CACHE_URL, REDIS_URL } from './config.js'; + +export function createClient(opts?: Partial): Redis { + const client = new Redis(REDIS_URL, { + tls: + REDIS_URL.startsWith('rediss') && REDIS_CA_CERT + ? { + ca: Buffer.from(REDIS_CA_CERT) + } + : undefined, + ...opts + }); + return client; +} + +export function createCacheClient(opts?: Partial): Redis { + const client = new Redis(REDIS_CACHE_URL, { + tls: + REDIS_URL.startsWith('rediss') && REDIS_CACHE_CA_CERT + ? { + ca: Buffer.from(REDIS_CACHE_CA_CERT) + } + : undefined, + ...opts + }); + return client; +} diff --git a/src/run-steps/dtos/run-step-delta.ts b/src/run-steps/dtos/run-step-delta.ts new file mode 100644 index 0000000..2c46a2d --- /dev/null +++ b/src/run-steps/dtos/run-step-delta.ts @@ -0,0 +1,36 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { runStepDetailsDeltaSchema } from './run-step-details-delta.js'; + +export const runStepDeltaSchema = { + type: 'object', + required: ['id', 'object', 'delta'], + properties: { + id: { type: 'string' }, + object: { const: 'thread.run.step.delta' }, + delta: { + type: 'object', + required: ['step_details'], + properties: { + step_details: runStepDetailsDeltaSchema + } + } + } +} as const satisfies JSONSchema; +export type RunStepDelta = FromSchema; diff --git a/src/run-steps/dtos/run-step-details-delta.ts b/src/run-steps/dtos/run-step-details-delta.ts new file mode 100644 index 0000000..35816d7 --- /dev/null +++ b/src/run-steps/dtos/run-step-details-delta.ts @@ -0,0 +1,62 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { RunStepDetailsType } from '../entities/details/run-step-details.entity.js'; + +import { toolCallDeltaSchema } from '@/tools/dtos/tool-call-delta.js'; + +export const runStepDetailsDeltaSchema = { + oneOf: [ + { + type: 'object', + required: ['type', RunStepDetailsType.MESSAGE_CREATION], + properties: { + type: { const: RunStepDetailsType.MESSAGE_CREATION }, + [RunStepDetailsType.MESSAGE_CREATION]: { + type: 'object', + required: ['message_id'], + properties: { message_id: { type: 'string' } } + } + } + }, + { + type: 'object', + required: ['type', RunStepDetailsType.TOOL_CALLS], + properties: { + type: { const: RunStepDetailsType.TOOL_CALLS }, + [RunStepDetailsType.TOOL_CALLS]: { + type: 'array', + items: toolCallDeltaSchema + } + } + }, + { + type: 'object', + required: ['type', RunStepDetailsType.THOUGHT], + properties: { + type: { const: RunStepDetailsType.THOUGHT }, + [RunStepDetailsType.THOUGHT]: { + type: 'object', + required: ['content'], + properties: { content: { type: 'string', nullable: true } } + } + } + } + ] +} as const satisfies JSONSchema; +export type RunStepDetailsDelta = FromSchema; diff --git a/src/run-steps/dtos/run-step-details.ts b/src/run-steps/dtos/run-step-details.ts new file mode 100644 index 0000000..d31c54b --- /dev/null +++ b/src/run-steps/dtos/run-step-details.ts @@ -0,0 +1,62 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { RunStepDetailsType } from '../entities/details/run-step-details.entity.js'; + +import { toolCallSchema } from '@/tools/dtos/tool-call.js'; + +export const runStepDetailsSchema = { + oneOf: [ + { + type: 'object', + required: ['type', RunStepDetailsType.MESSAGE_CREATION], + properties: { + type: { const: RunStepDetailsType.MESSAGE_CREATION }, + [RunStepDetailsType.MESSAGE_CREATION]: { + type: 'object', + required: ['message_id'], + properties: { message_id: { type: 'string' } } + } + } + }, + { + type: 'object', + required: ['type', RunStepDetailsType.TOOL_CALLS], + properties: { + type: { const: RunStepDetailsType.TOOL_CALLS }, + [RunStepDetailsType.TOOL_CALLS]: { + type: 'array', + items: toolCallSchema + } + } + }, + { + type: 'object', + required: ['type', RunStepDetailsType.THOUGHT], + properties: { + type: { const: RunStepDetailsType.THOUGHT }, + [RunStepDetailsType.THOUGHT]: { + type: 'object', + required: ['content'], + properties: { content: { type: 'string', nullable: true } } + } + } + } + ] +} as const satisfies JSONSchema; +export type RunStepDetails = FromSchema; diff --git a/src/run-steps/dtos/run-step-read.ts b/src/run-steps/dtos/run-step-read.ts new file mode 100644 index 0000000..227ec5c --- /dev/null +++ b/src/run-steps/dtos/run-step-read.ts @@ -0,0 +1,34 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { runStepSchema } from './run-step.js'; + +export const runStepReadParamsSchema = { + type: 'object', + required: ['thread_id', 'run_id', 'step_id'], + properties: { + thread_id: { type: 'string' }, + run_id: { type: 'string' }, + step_id: { type: 'string' } + }, + additionalProperties: false +} as const satisfies JSONSchema; +export type RunStepReadParams = FromSchema; + +export const runStepReadResponseSchema = runStepSchema; +export type RunStepReadResponse = FromSchema; diff --git a/src/run-steps/dtos/run-step.ts b/src/run-steps/dtos/run-step.ts new file mode 100644 index 0000000..f2b8542 --- /dev/null +++ b/src/run-steps/dtos/run-step.ts @@ -0,0 +1,57 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { RunStepDetailsType } from '../entities/details/run-step-details.entity.js'; +import { RunStepStatus } from '../entities/run-step.entity.js'; + +import { runStepDetailsSchema } from './run-step-details.js'; + +import { errorSchema } from '@/errors/dtos/error.js'; +import { metadataSchema } from '@/schema.js'; + +export const runStepSchema = { + type: 'object', + required: [ + 'id', + 'object', + 'thread_id', + 'assistant_id', + 'run_id', + 'type', + 'step_details', + 'metadata', + 'created_at' + ], + properties: { + id: { type: 'string' }, + object: { const: 'thread.run.step' }, + thread_id: { type: 'string' }, + assistant_id: { type: 'string' }, + run_id: { type: 'string' }, + status: { type: 'string', enum: Object.values(RunStepStatus) }, + type: { type: 'string', enum: Object.values(RunStepDetailsType) }, + step_details: runStepDetailsSchema, + last_error: { + ...errorSchema, + nullable: true + }, + metadata: metadataSchema, + created_at: { type: 'number' } + } +} as const satisfies JSONSchema; +export type RunStep = FromSchema; diff --git a/src/run-steps/dtos/run-steps-list.ts b/src/run-steps/dtos/run-steps-list.ts new file mode 100644 index 0000000..353d964 --- /dev/null +++ b/src/run-steps/dtos/run-steps-list.ts @@ -0,0 +1,38 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { runStepSchema } from './run-step.js'; + +import { createPaginationQuerySchema, withPagination } from '@/schema.js'; + +export const runStepsListParamsSchema = { + type: 'object', + required: ['thread_id', 'run_id'], + properties: { + thread_id: { type: 'string' }, + run_id: { type: 'string' } + }, + additionalProperties: false +} as const satisfies JSONSchema; +export type RunStepsListParams = FromSchema; + +export const runStepsListQuerySchema = createPaginationQuerySchema(); +export type RunStepsListQuery = FromSchema; + +export const runStepsListResponseSchema = withPagination(runStepSchema); +export type RunStepsListResponse = FromSchema; diff --git a/src/run-steps/entities/details/run-step-details.entity.ts b/src/run-steps/entities/details/run-step-details.entity.ts new file mode 100644 index 0000000..e565c4f --- /dev/null +++ b/src/run-steps/entities/details/run-step-details.entity.ts @@ -0,0 +1,36 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, Enum } from '@mikro-orm/core'; + +import { RunStepMessageCreation } from './run-step-message-creation.entity.js'; +import { RunStepToolCalls } from './run-step-tool-calls.entity.js'; +import { RunStepThought } from './run-step-thought.entity.js'; + +export const RunStepDetailsType = { + MESSAGE_CREATION: 'message_creation', + TOOL_CALLS: 'tool_calls', + THOUGHT: 'thought' +} as const; +export type RunStepDetailsType = (typeof RunStepDetailsType)[keyof typeof RunStepDetailsType]; + +@Embeddable({ abstract: true, discriminatorColumn: 'type' }) +export abstract class RunStepDetails { + @Enum(() => RunStepDetailsType) + type!: RunStepDetailsType; +} + +export type AnyRunStepDetails = RunStepMessageCreation | RunStepThought | RunStepToolCalls; diff --git a/src/run-steps/entities/details/run-step-message-creation.entity.ts b/src/run-steps/entities/details/run-step-message-creation.entity.ts new file mode 100644 index 0000000..a2cce62 --- /dev/null +++ b/src/run-steps/entities/details/run-step-message-creation.entity.ts @@ -0,0 +1,36 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, ManyToOne, Ref } from '@mikro-orm/core'; + +import { RunStepDetails, RunStepDetailsType } from './run-step-details.entity.js'; + +import { Message } from '@/messages/message.entity.js'; + +@Embeddable({ discriminatorValue: RunStepDetailsType.MESSAGE_CREATION }) +export class RunStepMessageCreation extends RunStepDetails { + type = RunStepDetailsType.MESSAGE_CREATION; + + @ManyToOne() + message!: Ref; + + constructor(input: RunStepMessageCreationInput) { + super(); + this.message = input.message; + } +} + +export type RunStepMessageCreationInput = Pick; diff --git a/src/run-steps/entities/details/run-step-thought.entity.ts b/src/run-steps/entities/details/run-step-thought.entity.ts new file mode 100644 index 0000000..e192cdf --- /dev/null +++ b/src/run-steps/entities/details/run-step-thought.entity.ts @@ -0,0 +1,34 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, Property } from '@mikro-orm/core'; + +import { RunStepDetails, RunStepDetailsType } from './run-step-details.entity.js'; + +@Embeddable({ discriminatorValue: RunStepDetailsType.THOUGHT }) +export class RunStepThought extends RunStepDetails { + type = RunStepDetailsType.THOUGHT; + + @Property() + content?: string; + + constructor(input: RunStepThoughtInput) { + super(); + this.content = input.content; + } +} + +export type RunStepThoughtInput = Pick; diff --git a/src/run-steps/entities/details/run-step-tool-calls.entity.ts b/src/run-steps/entities/details/run-step-tool-calls.entity.ts new file mode 100644 index 0000000..ba21b55 --- /dev/null +++ b/src/run-steps/entities/details/run-step-tool-calls.entity.ts @@ -0,0 +1,41 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, Embedded } from '@mikro-orm/core'; + +import { RunStepDetails, RunStepDetailsType } from './run-step-details.entity.js'; + +import { CodeInterpreterCall } from '@/tools/entities/tool-calls/code-interpreter-call.entity.js'; +import { FileSearchCall } from '@/tools/entities/tool-calls/file-search-call.entity.js'; +import { FunctionCall } from '@/tools/entities/tool-calls/function-call.entity.js'; +import { UserCall } from '@/tools/entities/tool-calls/user-call.entity.js'; +import { SystemCall } from '@/tools/entities/tool-calls/system-call.entity.js'; + +@Embeddable({ discriminatorValue: RunStepDetailsType.TOOL_CALLS }) +export class RunStepToolCalls extends RunStepDetails { + type = RunStepDetailsType.TOOL_CALLS; + + // Union must be defined in alphabetical order, otherwise Mikro-ORM won't discovered the auto-created virtual polymorphic entity + @Embedded({ object: true }) + toolCalls!: (CodeInterpreterCall | FileSearchCall | FunctionCall | SystemCall | UserCall)[]; + + constructor(input: RunStepToolCallsInput) { + super(); + this.toolCalls = input.toolCalls; + } +} + +export type RunStepToolCallsInput = Pick; diff --git a/src/run-steps/entities/emitter-event.entity.ts b/src/run-steps/entities/emitter-event.entity.ts new file mode 100644 index 0000000..e41ceb9 --- /dev/null +++ b/src/run-steps/entities/emitter-event.entity.ts @@ -0,0 +1,42 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, Property } from '@mikro-orm/core'; + +@Embeddable() +export class EmitterEvent { + @Property() + public readonly id!: string; + + @Property() + public readonly groupId!: string; + + @Property() + public readonly runId?: string; + + @Property() + public readonly parentRunId?: string; + + @Property() + public readonly name!: string; + + @Property() + public readonly path!: string; + + constructor(input: EmitterEvent) { + Object.assign(this, input); + } +} diff --git a/src/run-steps/entities/run-step.entity.ts b/src/run-steps/entities/run-step.entity.ts new file mode 100644 index 0000000..1fdfd20 --- /dev/null +++ b/src/run-steps/entities/run-step.entity.ts @@ -0,0 +1,78 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embedded, Entity, Enum, Index, ManyToOne, Ref } from '@mikro-orm/core'; + +import { Run } from '../../runs/entities/run.entity.js'; + +import { RunStepMessageCreation } from './details/run-step-message-creation.entity.js'; +import { RunStepToolCalls } from './details/run-step-tool-calls.entity.js'; +import { RunStepThought } from './details/run-step-thought.entity.js'; +import { EmitterEvent } from './emitter-event.entity.js'; + +import { Assistant } from '@/assistants/assistant.entity.js'; +import { Thread } from '@/threads/thread.entity.js'; +import { APIError } from '@/errors/error.entity.js'; +import { + PrincipalScopedEntity, + PrincipalScopedEntityInput +} from '@/common/principal-scoped.entity.js'; + +export const RunStepStatus = { + IN_PROGRESS: 'in_progress', + COMPLETED: 'completed', + FAILED: 'failed', + CANCELLED: 'cancelled' +} as const; +export type RunStepStatus = (typeof RunStepStatus)[keyof typeof RunStepStatus]; + +@Entity() +@Index({ properties: ['thread', 'run'] }) +export class RunStep extends PrincipalScopedEntity { + getIdPrefix(): string { + return 'step'; + } + + @Index() + @ManyToOne() + thread!: Ref; + + @ManyToOne() + run!: Ref; + + @ManyToOne() + assistant!: Ref; + + @Enum(() => RunStepStatus) + status: RunStepStatus = RunStepStatus.IN_PROGRESS; + + @Embedded({ object: true }) + details!: RunStepMessageCreation | RunStepThought | RunStepToolCalls; + + @Embedded({ object: true }) + lastError?: APIError; + + @Embedded({ object: true }) + event?: EmitterEvent; + + constructor(input: RunStepInput) { + super(input); + Object.assign(this, input); + } +} + +export type RunStepInput = PrincipalScopedEntityInput & + Pick; diff --git a/src/run-steps/run-steps.module.ts b/src/run-steps/run-steps.module.ts new file mode 100644 index 0000000..4771a88 --- /dev/null +++ b/src/run-steps/run-steps.module.ts @@ -0,0 +1,67 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FastifyPluginAsyncJsonSchemaToTs } from '@fastify/type-provider-json-schema-to-ts'; +import { StatusCodes } from 'http-status-codes'; + +import { + RunStepsListParams, + RunStepsListQuery, + runStepsListParamsSchema, + runStepsListQuerySchema, + runStepsListResponseSchema +} from './dtos/run-steps-list.js'; +import { + RunStepReadParams, + runStepReadParamsSchema, + runStepReadResponseSchema +} from './dtos/run-step-read.js'; +import { listRunSteps, readRunStep } from './run-steps.service.js'; + +import { Tag } from '@/swagger.js'; + +export const runStepsModule: FastifyPluginAsyncJsonSchemaToTs = async (app) => { + app.get<{ Params: RunStepReadParams }>( + '/threads/:thread_id/runs/:run_id/steps/:step_id', + { + schema: { + params: runStepReadParamsSchema, + response: { [StatusCodes.OK]: runStepReadResponseSchema }, + tags: [Tag.OPENAI_ASSISTANTS_API] + }, + preHandler: app.auth() + }, + async (req) => { + return readRunStep(req.params); + } + ); + + app.get<{ Params: RunStepsListParams; Querystring: RunStepsListQuery }>( + '/threads/:thread_id/runs/:run_id/steps', + { + schema: { + params: runStepsListParamsSchema, + querystring: runStepsListQuerySchema, + response: { [StatusCodes.OK]: runStepsListResponseSchema }, + tags: [Tag.OPENAI_ASSISTANTS_API] + }, + preHandler: app.auth() + }, + async (req) => { + return listRunSteps({ ...req.params, ...req.query }); + } + ); +}; diff --git a/src/run-steps/run-steps.service.ts b/src/run-steps/run-steps.service.ts new file mode 100644 index 0000000..80c6e14 --- /dev/null +++ b/src/run-steps/run-steps.service.ts @@ -0,0 +1,144 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Loaded } from '@mikro-orm/core'; +import dayjs from 'dayjs'; + +import { RunStep } from './entities/run-step.entity.js'; +import type { RunStep as RunStepDto } from './dtos/run-step.js'; +import type { RunStepDelta as RunStepDeltaDto } from './dtos/run-step-delta.js'; +import type { RunStepDetails as RunStepDetailsDto } from './dtos/run-step-details.js'; +import type { RunStepDetailsDelta as RunStepDetailsDeltaDto } from './dtos/run-step-details-delta.js'; +import { RunStepReadParams, RunStepReadResponse } from './dtos/run-step-read.js'; +import { + RunStepsListParams, + RunStepsListQuery, + RunStepsListResponse +} from './dtos/run-steps-list.js'; +import { + AnyRunStepDetails, + RunStepDetailsType +} from './entities/details/run-step-details.entity.js'; + +import { ORM } from '@/database.js'; +import { createPaginatedResponse, getListCursor } from '@/utils/pagination.js'; +import { toToolCallDeltaDto, toToolCallDto } from '@/tools/tools.service.js'; +import { toErrorDto } from '@/errors/plugin.js'; + +export function toRunStepDto(runStep: Loaded): RunStepDto { + return { + id: runStep.id, + object: 'thread.run.step', + assistant_id: runStep.assistant.id, + thread_id: runStep.thread.id, + run_id: runStep.run.id, + status: runStep.status, + type: runStep.details.type, + step_details: toRunStepDetailsDto(runStep.details), + last_error: runStep.lastError ? toErrorDto(runStep.lastError) : null, + metadata: runStep.metadata ?? {}, + created_at: dayjs(runStep.createdAt).unix() + }; +} + +export function toRunStepDeltaDto( + runStep: Loaded, + delta: string +): RunStepDeltaDto { + return { + id: runStep.id, + object: 'thread.run.step.delta', + delta: { + step_details: toRunStepDetailsDeltaDto(runStep.details, delta) + } + }; +} + +function toRunStepDetailsDto( + runStep: Loaded +): RunStepDetailsDto { + switch (runStep.type) { + case RunStepDetailsType.MESSAGE_CREATION: + return { + type: RunStepDetailsType.MESSAGE_CREATION, + [RunStepDetailsType.MESSAGE_CREATION]: { message_id: runStep.message.id } + }; + case RunStepDetailsType.TOOL_CALLS: + return { + type: RunStepDetailsType.TOOL_CALLS, + [RunStepDetailsType.TOOL_CALLS]: runStep.toolCalls.map(toToolCallDto) + }; + case RunStepDetailsType.THOUGHT: + return { + type: RunStepDetailsType.THOUGHT, + [RunStepDetailsType.THOUGHT]: { content: runStep.content ?? null } + }; + } +} + +function toRunStepDetailsDeltaDto( + runStep: AnyRunStepDetails, + delta: string +): RunStepDetailsDeltaDto { + switch (runStep.type) { + case RunStepDetailsType.MESSAGE_CREATION: + return { + type: RunStepDetailsType.MESSAGE_CREATION, + [RunStepDetailsType.MESSAGE_CREATION]: { message_id: runStep.message.id } + }; + case RunStepDetailsType.TOOL_CALLS: + return { + type: RunStepDetailsType.TOOL_CALLS, + [RunStepDetailsType.TOOL_CALLS]: runStep.toolCalls.map(toToolCallDeltaDto) + }; + case RunStepDetailsType.THOUGHT: + return { + type: RunStepDetailsType.THOUGHT, + [RunStepDetailsType.THOUGHT]: { content: delta } + }; + } +} + +export async function readRunStep({ + thread_id, + run_id, + step_id +}: RunStepReadParams): Promise { + const runStep = await ORM.em.getRepository(RunStep).findOneOrFail({ + id: step_id, + run: run_id, + thread: thread_id + }); + return toRunStepDto(runStep); +} + +export async function listRunSteps({ + thread_id, + run_id, + limit, + after, + before, + order, + order_by +}: RunStepsListParams & RunStepsListQuery): Promise { + const repo = ORM.em.getRepository(RunStep); + const cursor = await getListCursor( + { thread: thread_id, run: run_id }, + { limit, order, order_by, after, before }, + repo + ); + return createPaginatedResponse(cursor, toRunStepDto); +} diff --git a/src/runs/dtos/run-cancel.ts b/src/runs/dtos/run-cancel.ts new file mode 100644 index 0000000..1579b48 --- /dev/null +++ b/src/runs/dtos/run-cancel.ts @@ -0,0 +1,25 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema } from 'json-schema-to-ts'; + +import { runParamsSchema, runSchema } from './run.js'; + +export const runCancelParamsSchema = runParamsSchema; +export type RunCancelParams = FromSchema; + +export const runCancelResponseSchema = runSchema; +export type RunCancelResponse = FromSchema; diff --git a/src/runs/dtos/run-create.ts b/src/runs/dtos/run-create.ts new file mode 100644 index 0000000..da6bc21 --- /dev/null +++ b/src/runs/dtos/run-create.ts @@ -0,0 +1,100 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { runSchema } from './run.js'; + +import { eventSchema } from '@/streaming/dtos/event.js'; +import { toolUsageSchema } from '@/tools/dtos/tools-usage.js'; +import { metadataSchema } from '@/schema.js'; + +export const runCreateParamsSchema = { + type: 'object', + required: ['thread_id'], + additionalProperties: false, + properties: { + thread_id: { type: 'string' } + } +} as const satisfies JSONSchema; +export type RunCreateParams = FromSchema; + +export const runCreateBodySchema = { + type: 'object', + required: ['assistant_id'], + additionalProperties: false, + properties: { + assistant_id: { type: 'string' }, + stream: { type: 'boolean', nullable: true }, + tools: { + type: 'array', + uniqueItems: true, + items: toolUsageSchema, + nullable: true + }, + tool_approvals: { + type: 'object', + patternProperties: { + '.*': { + type: 'object', + required: ['require'], + additionalProperties: false, + properties: { + require: { + type: 'string', + enum: ['always', 'never'] + } + } + } + }, + nullable: true + }, + instructions: { + type: 'string', + nullable: true + }, + additional_instructions: { + type: 'string', + nullable: true + }, + model: { + type: 'string', + nullable: true + }, + top_p: { + type: 'number', + nullable: true, + maximum: 1, + minimum: 0, + multipleOf: 0.01 + }, + temperature: { + type: 'number', + nullable: true, + maximum: 2, + minimum: 0, + multipleOf: 0.01 + }, + metadata: metadataSchema + } +} as const satisfies JSONSchema; +export type RunCreateBody = FromSchema; + +export const runCreateResponseSchema = runSchema; +export type RunCreateResponse = FromSchema; + +export const runCreateStreamSchema = eventSchema; +export type RunCreateStream = FromSchema; diff --git a/src/runs/dtos/run-read.ts b/src/runs/dtos/run-read.ts new file mode 100644 index 0000000..796f7a3 --- /dev/null +++ b/src/runs/dtos/run-read.ts @@ -0,0 +1,25 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema } from 'json-schema-to-ts'; + +import { runParamsSchema, runSchema } from './run.js'; + +export const runReadParamsSchema = runParamsSchema; +export type RunReadParams = FromSchema; + +export const runReadResponseSchema = runSchema; +export type RunReadResponse = FromSchema; diff --git a/src/runs/dtos/run-submit-tool-approvals.ts b/src/runs/dtos/run-submit-tool-approvals.ts new file mode 100644 index 0000000..46971ca --- /dev/null +++ b/src/runs/dtos/run-submit-tool-approvals.ts @@ -0,0 +1,57 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { runParamsSchema, runSchema } from './run.js'; + +import { eventSchema } from '@/streaming/dtos/event.js'; + +export const runSubmitToolApprovalsParamsSchema = runParamsSchema; +export type RunSubmitToolApprovalsParams = FromSchema; + +export const runSubmitToolApprovalsBodySchema = { + type: 'object', + required: ['tool_approvals'], + additionalProperties: false, + properties: { + tool_approvals: { + type: 'array', + items: { + type: 'object', + additionalProperties: false, + required: ['tool_call_id', 'approve'], + properties: { + tool_call_id: { type: 'string' }, + approve: { type: 'boolean' } + } + } + }, + stream: { + type: 'boolean', + nullable: true + } + } +} as const satisfies JSONSchema; +export type RunSubmitToolApprovalsBody = FromSchema; + +export const runSubmitToolApprovalsResponseSchema = runSchema; +export type RunSubmitToolApprovalsResponse = FromSchema< + typeof runSubmitToolApprovalsResponseSchema +>; + +export const runSubmitToolApprovalsStreamSchema = eventSchema; +export type RunSubmitToolApprovalsStream = FromSchema; diff --git a/src/runs/dtos/run-submit-tool-outputs.ts b/src/runs/dtos/run-submit-tool-outputs.ts new file mode 100644 index 0000000..d410948 --- /dev/null +++ b/src/runs/dtos/run-submit-tool-outputs.ts @@ -0,0 +1,55 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { runParamsSchema, runSchema } from './run.js'; + +import { eventSchema } from '@/streaming/dtos/event.js'; + +export const runSubmitToolOutputsParamsSchema = runParamsSchema; +export type RunSubmitToolOutputsParams = FromSchema; + +export const runSubmitToolOutputsBodySchema = { + type: 'object', + required: ['tool_outputs'], + additionalProperties: false, + properties: { + tool_outputs: { + type: 'array', + items: { + type: 'object', + additionalProperties: false, + required: ['tool_call_id', 'output'], + properties: { + tool_call_id: { type: 'string' }, + output: { type: 'string' } + } + } + }, + stream: { + type: 'boolean', + nullable: true + } + } +} as const satisfies JSONSchema; +export type RunSubmitToolOutputsBody = FromSchema; + +export const runSubmitToolOutputsResponseSchema = runSchema; +export type RunSubmitToolOutputsResponse = FromSchema; + +export const runSubmitToolOutputsStreamSchema = eventSchema; +export type RunSubmitToolOutputsStream = FromSchema; diff --git a/src/runs/dtos/run-update.ts b/src/runs/dtos/run-update.ts new file mode 100644 index 0000000..ad7116b --- /dev/null +++ b/src/runs/dtos/run-update.ts @@ -0,0 +1,36 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { runParamsSchema, runSchema } from './run.js'; + +import { metadataSchema } from '@/schema.js'; + +export const runUpdateParamsSchema = runParamsSchema; +export type RunUpdateParams = FromSchema; + +export const runUpdateBodySchema = { + type: 'object', + additionalProperties: false, + properties: { + metadata: metadataSchema + } +} as const satisfies JSONSchema; +export type RunUpdateBody = FromSchema; + +export const runUpdateResponseSchema = runSchema; +export type RunUpdateResponse = FromSchema; diff --git a/src/runs/dtos/run.ts b/src/runs/dtos/run.ts new file mode 100644 index 0000000..c40d3e9 --- /dev/null +++ b/src/runs/dtos/run.ts @@ -0,0 +1,139 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { RunStatus } from '../entities/run.entity.js'; + +import { errorSchema } from '@/errors/dtos/error.js'; +import { toolUsageSchema } from '@/tools/dtos/tools-usage.js'; +import { metadataSchema } from '@/schema.js'; +import { toolCallSchema } from '@/tools/dtos/tool-call.js'; + +export const runParamsSchema = { + type: 'object', + required: ['thread_id', 'run_id'], + additionalProperties: false, + properties: { + thread_id: { type: 'string' }, + run_id: { type: 'string' } + } +} as const satisfies JSONSchema; +export type RunParams = FromSchema; + +export const runSchema = { + type: 'object', + required: [ + 'id', + 'object', + 'thread_id', + 'assistant_id', + 'status', + 'last_error', + 'required_action', + 'tools', + 'instructions', + 'additional_instructions', + 'metadata', + 'created_at', + 'expires_at', + 'started_at', + 'completed_at', + 'failed_at', + 'cancelled_at', + 'model' + ], + properties: { + id: { type: 'string' }, + object: { const: 'thread.run' }, + thread_id: { type: 'string' }, + assistant_id: { type: 'string' }, + status: { type: 'string', enum: Object.values(RunStatus) }, + last_error: { + ...errorSchema, + nullable: true + }, + required_action: { + type: 'object', + oneOf: [ + { + required: ['type', 'submit_tool_outputs'], + properties: { + type: { const: 'submit_tool_outputs' }, + submit_tool_outputs: { + type: 'object', + required: ['tool_calls'], + properties: { + tool_calls: { + type: 'array', + items: toolCallSchema + } + } + } + } + }, + { + required: ['type', 'submit_tool_approvals'], + properties: { + type: { const: 'submit_tool_approvals' }, + submit_tool_approvals: { + type: 'object', + required: ['tool_calls'], + properties: { + tool_calls: { + type: 'array', + items: toolCallSchema + } + } + } + } + } + ], + nullable: true + }, + tools: { + type: 'array', + items: toolUsageSchema + }, + instructions: { + type: 'string', + nullable: true + }, + additional_instructions: { + type: 'string', + nullable: true + }, + metadata: metadataSchema, + model: { + type: 'string' + }, + top_p: { + type: 'number', + nullable: true + }, + temperature: { + type: 'number', + nullable: true + }, + created_at: { type: 'number', nullable: true }, + started_at: { type: 'number', nullable: true }, + expires_at: { type: 'number', nullable: true }, + failed_at: { type: 'number', nullable: true }, + cancelled_at: { type: 'number', nullable: true }, + completed_at: { type: 'number', nullable: true } + } +} as const satisfies JSONSchema; +export type Run = FromSchema; diff --git a/src/runs/dtos/runs-list.ts b/src/runs/dtos/runs-list.ts new file mode 100644 index 0000000..3a7fe9c --- /dev/null +++ b/src/runs/dtos/runs-list.ts @@ -0,0 +1,53 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { runSchema } from './run.js'; + +import { createPaginationQuerySchema, withPagination } from '@/schema.js'; + +export const runsListParamsSchema = { + type: 'object', + required: ['thread_id'], + properties: { + thread_id: { type: 'string' } + } +} as const satisfies JSONSchema; +export type RunsListParams = FromSchema; + +export const runsListQuerySchema = { + type: 'object', + additionalProperties: false, + properties: { + ...createPaginationQuerySchema().properties, + // Stupid name to stay compatible with OpenAI (an undocumented query param in their API) + 'ids[]': { + type: 'array', + uniqueItems: true, + /* + Our id has 24 characters, so the limit is keeping this under 2000 chars per recommendation: + https://stackoverflow.com/a/417184 + */ + maxItems: 50, + items: { type: 'string' } + } + } +} as const satisfies JSONSchema; +export type RunsListQuery = FromSchema; + +export const runsListResponseSchema = withPagination(runSchema); +export type RunsListResponse = FromSchema; diff --git a/src/runs/dtos/thread-run-create.ts b/src/runs/dtos/thread-run-create.ts new file mode 100644 index 0000000..da6ce0d --- /dev/null +++ b/src/runs/dtos/thread-run-create.ts @@ -0,0 +1,82 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { runSchema } from './run.js'; + +import { threadCreateBodySchema } from '@/threads/dtos/thread-create.js'; +import { eventSchema } from '@/streaming/dtos/event.js'; +import { toolUsageSchema } from '@/tools/dtos/tools-usage.js'; + +export const threadRunCreateBodySchema = { + type: 'object', + required: ['assistant_id'], + additionalProperties: false, + properties: { + assistant_id: { type: 'string' }, + thread: threadCreateBodySchema, + stream: { type: 'boolean', nullable: true }, + tools: { + type: 'array', + uniqueItems: true, + items: toolUsageSchema, + nullable: true + }, + tool_approvals: { + type: 'object', + patternProperties: { + '.*': { + type: 'object', + required: ['require'], + additionalProperties: false, + properties: { + require: { + type: 'string', + enum: ['always', 'never'] + } + } + } + }, + nullable: true + }, + model: { + type: 'string', + nullable: true + }, + top_p: { + type: 'number', + nullable: true, + maximum: 1, + minimum: 0, + multipleOf: 0.01 + }, + temperature: { + type: 'number', + nullable: true, + maximum: 2, + minimum: 0, + multipleOf: 0.01 + } + } +} as const satisfies JSONSchema; +export type ThreadRunCreateBody = FromSchema; + +export const threadRunCreateResponseSchema = runSchema; +export type ThreadRunCreateResponse = FromSchema; + +export const threadRunCreateStreamSchema = eventSchema; +export type ThreadRunCreateStream = FromSchema; diff --git a/src/runs/dtos/trace-read.ts b/src/runs/dtos/trace-read.ts new file mode 100644 index 0000000..2d1b2d4 --- /dev/null +++ b/src/runs/dtos/trace-read.ts @@ -0,0 +1,26 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema } from 'json-schema-to-ts'; + +import { runParamsSchema } from './run'; + +import { traceSchema } from '@/observe/dtos/trace.js'; + +export const traceReadParamsSchema = runParamsSchema; +export const traceReadResponseSchema = traceSchema; + +export type TraceReadResponse = FromSchema; diff --git a/src/runs/entities/requiredAction.entity.ts b/src/runs/entities/requiredAction.entity.ts new file mode 100644 index 0000000..489c960 --- /dev/null +++ b/src/runs/entities/requiredAction.entity.ts @@ -0,0 +1,38 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, Enum, Property } from '@mikro-orm/core'; + +import { RequiredToolApprove } from './requiredToolApprove.entity'; +import { RequiredToolOutput } from './requiredToolOutput.entity'; + +import { generatePrefixedObjectId } from '@/utils/id'; + +export enum RequiredActionType { + OUTPUT = 'output', + APPROVE = 'approve' +} + +@Embeddable({ abstract: true, discriminatorColumn: 'type' }) +export abstract class RequiredAction { + @Property({ fieldName: '_id' }) + id = generatePrefixedObjectId('action'); + + @Enum(() => RequiredActionType) + type!: RequiredActionType; +} + +export type AnyRequiredAction = RequiredToolApprove | RequiredToolOutput; diff --git a/src/runs/entities/requiredToolApprove.entity.ts b/src/runs/entities/requiredToolApprove.entity.ts new file mode 100644 index 0000000..3420d78 --- /dev/null +++ b/src/runs/entities/requiredToolApprove.entity.ts @@ -0,0 +1,41 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, Embedded } from '@mikro-orm/core'; + +import { RequiredAction, RequiredActionType } from './requiredAction.entity'; + +import { CodeInterpreterCall } from '@/tools/entities/tool-calls/code-interpreter-call.entity'; +import { FileSearchCall } from '@/tools/entities/tool-calls/file-search-call.entity'; +import { FunctionCall } from '@/tools/entities/tool-calls/function-call.entity'; +import { SystemCall } from '@/tools/entities/tool-calls/system-call.entity'; +import { UserCall } from '@/tools/entities/tool-calls/user-call.entity'; + +@Embeddable({ discriminatorValue: RequiredActionType.APPROVE }) +export class RequiredToolApprove extends RequiredAction { + type = RequiredActionType.APPROVE; + + // Union must be defined in alphabetical order, otherwise Mikro-ORM won't discovered the auto-created virtual polymorphic entity + @Embedded({ object: true }) + toolCalls!: (CodeInterpreterCall | FileSearchCall | FunctionCall | SystemCall | UserCall)[]; + + constructor({ toolCalls }: RequiredToolApproveInput) { + super(); + this.toolCalls = toolCalls; + } +} + +export type RequiredToolApproveInput = Pick; diff --git a/src/runs/entities/requiredToolOutput.entity.ts b/src/runs/entities/requiredToolOutput.entity.ts new file mode 100644 index 0000000..f88c772 --- /dev/null +++ b/src/runs/entities/requiredToolOutput.entity.ts @@ -0,0 +1,41 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, Embedded } from '@mikro-orm/core'; + +import { RequiredAction, RequiredActionType } from './requiredAction.entity'; + +import { CodeInterpreterCall } from '@/tools/entities/tool-calls/code-interpreter-call.entity'; +import { FileSearchCall } from '@/tools/entities/tool-calls/file-search-call.entity'; +import { FunctionCall } from '@/tools/entities/tool-calls/function-call.entity'; +import { SystemCall } from '@/tools/entities/tool-calls/system-call.entity'; +import { UserCall } from '@/tools/entities/tool-calls/user-call.entity'; + +@Embeddable({ discriminatorValue: RequiredActionType.OUTPUT }) +export class RequiredToolOutput extends RequiredAction { + type = RequiredActionType.OUTPUT; + + // Union must be defined in alphabetical order, otherwise Mikro-ORM won't discovered the auto-created virtual polymorphic entity + @Embedded({ object: true }) + toolCalls!: (CodeInterpreterCall | FileSearchCall | FunctionCall | SystemCall | UserCall)[]; + + constructor({ toolCalls }: RequiredToolOutputInput) { + super(); + this.toolCalls = toolCalls; + } +} + +export type RequiredToolOutputInput = Pick; diff --git a/src/runs/entities/run.entity.ts b/src/runs/entities/run.entity.ts new file mode 100644 index 0000000..176b3ff --- /dev/null +++ b/src/runs/entities/run.entity.ts @@ -0,0 +1,206 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embedded, Entity, Enum, Index, ManyToOne, Property, Ref } from '@mikro-orm/core'; +import dayjs from 'dayjs'; + +import { RUN_EXPIRATION_MILLISECONDS } from '../execution/constants.js'; + +import { RequiredToolApprove } from './requiredToolApprove.entity.js'; +import { RequiredToolOutput } from './requiredToolOutput.entity.js'; +import { ToolApproval } from './toolApproval.entity.js'; + +import { Assistant } from '@/assistants/assistant.entity.js'; +import { Thread } from '@/threads/thread.entity.js'; +import { APIError } from '@/errors/error.entity.js'; +import { AnyToolUsage } from '@/tools/entities/tool-usages/tool-usage.entity.js'; +import { CodeInterpreterUsage } from '@/tools/entities/tool-usages/code-interpreter-usage.entity.js'; +import { FileSearchUsage } from '@/tools/entities/tool-usages/file-search-usage.entity.js'; +import { FunctionUsage } from '@/tools/entities/tool-usages/function-usage.entity.js'; +import { UserUsage } from '@/tools/entities/tool-usages/user-usage.entity.js'; +import { SystemUsage } from '@/tools/entities/tool-usages/system-usage.entity.js'; +import { Trace } from '@/observe/entities/trace.entity.js'; +import { + PrincipalScopedEntity, + PrincipalScopedEntityInput +} from '@/common/principal-scoped.entity.js'; + +export const RunStatus = { + QUEUED: 'queued', + IN_PROGRESS: 'in_progress', + REQUIRES_ACTION: 'requires_action', + CANCELLING: 'cancelling', + CANCELLED: 'cancelled', + FAILED: 'failed', + COMPLETED: 'completed', + INCOMPLETE: 'incomplete', + EXPIRED: 'expired' +} as const; +export type RunStatus = (typeof RunStatus)[keyof typeof RunStatus]; + +@Entity() +export class Run extends PrincipalScopedEntity { + getIdPrefix(): string { + return 'run'; + } + + @Index() + @ManyToOne() + thread!: Ref; + + @ManyToOne() + assistant!: Ref; + + @Enum(() => RunStatus) + status: RunStatus = RunStatus.QUEUED; + + @Embedded({ object: true }) + lastError?: APIError; + + @Embedded({ object: true }) + trace?: Trace; + + // Union must be defined in alphabetical order, otherwise Mikro-ORM won't discovered the auto-created virtual polymorphic entity + @Embedded({ object: true }) + requiredAction?: RequiredToolApprove | RequiredToolOutput; + + @Embedded({ object: true }) + toolApprovals?: ToolApproval[]; + + // Union must be defined in alphabetical order, otherwise Mikro-ORM won't discovered the auto-created virtual polymorphic entity + @Embedded({ object: true }) + tools!: (CodeInterpreterUsage | FileSearchUsage | FunctionUsage | SystemUsage | UserUsage)[]; + + @Property() + instructions?: string; + + @Property() + additionalInstructions?: string; + + @Property() + expiresAt: Date; + + @Property() + startedAt?: Date; + + @Property() + cancelledAt?: Date; + + @Property() + failedAt?: Date; + + @Property() + completedAt?: Date; + + @Property() + model!: string; + + @Property() + topP?: number; + + @Property() + temperature?: number; + + constructor({ + thread, + assistant, + tools, + model, + topP, + temperature, + toolApprovals, + instructions, + additionalInstructions, + ...rest + }: RunInput) { + super(rest); + this.thread = thread; + this.assistant = assistant; + this.tools = tools; + this.model = model; + this.topP = topP; + this.temperature = temperature; + this.toolApprovals = toolApprovals; + this.instructions = instructions; + this.additionalInstructions = additionalInstructions; + + this.expiresAt = dayjs(this.createdAt) + .add(RUN_EXPIRATION_MILLISECONDS, 'milliseconds') + .toDate(); + } + + private assertCurrentStatus(...statuses: RunStatus[]) { + if (!statuses.includes(this.status)) + throw new Error(`Run state ${this.status} is not in ${statuses}`); + } + + start() { + this.assertCurrentStatus(RunStatus.QUEUED); + this.status = RunStatus.IN_PROGRESS; + this.startedAt = new Date(); + } + + startCancel() { + this.status = RunStatus.CANCELLING; + } + + cancel() { + this.assertCurrentStatus(RunStatus.CANCELLING); + this.status = RunStatus.CANCELLED; + this.cancelledAt = new Date(); + } + + fail(error: APIError) { + this.assertCurrentStatus(RunStatus.QUEUED, RunStatus.IN_PROGRESS); + this.status = RunStatus.FAILED; + this.failedAt = new Date(); + this.lastError = error; + } + + expire() { + this.assertCurrentStatus( + RunStatus.QUEUED, + RunStatus.IN_PROGRESS, + RunStatus.REQUIRES_ACTION, + RunStatus.CANCELLING + ); + this.status = RunStatus.EXPIRED; + } + + complete() { + this.assertCurrentStatus(RunStatus.IN_PROGRESS); + this.status = RunStatus.COMPLETED; + this.completedAt = new Date(); + } + + requireAction(requiredActions: typeof this.requiredAction) { + this.assertCurrentStatus(RunStatus.IN_PROGRESS); + this.status = RunStatus.REQUIRES_ACTION; + this.requiredAction = requiredActions; + } + + submitAction() { + this.assertCurrentStatus(RunStatus.REQUIRES_ACTION); + this.status = RunStatus.IN_PROGRESS; + this.requiredAction = undefined; + } +} + +export type RunInput = PrincipalScopedEntityInput & + Pick & { + tools: AnyToolUsage[]; + } & Partial> & + Partial>; diff --git a/src/runs/entities/toolApproval.entity.ts b/src/runs/entities/toolApproval.entity.ts new file mode 100644 index 0000000..c590ea0 --- /dev/null +++ b/src/runs/entities/toolApproval.entity.ts @@ -0,0 +1,38 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, Enum, Property } from '@mikro-orm/core'; + +export enum ToolApprovalType { + ALWAYS = 'always', + NEVER = 'never' +} + +@Embeddable() +export class ToolApproval { + @Property() + toolId?: string; + + @Enum(() => ToolApprovalType) + requireApproval?: ToolApprovalType; + + constructor(input: ToolApprovalInput) { + this.toolId = input.toolId; + this.requireApproval = input.requireApproval; + } +} + +export type ToolApprovalInput = Pick; diff --git a/src/runs/execution/cache.ts b/src/runs/execution/cache.ts new file mode 100644 index 0000000..1d252cd --- /dev/null +++ b/src/runs/execution/cache.ts @@ -0,0 +1,97 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Redis } from 'ioredis'; +import { BaseCache } from 'bee-agent-framework/cache/base'; +import { Serializer } from 'bee-agent-framework'; + +import { getLogger } from '@/logger'; + +export interface RedisCacheInput { + client: Redis; + ttlSeconds?: number; + keyPrefix?: string; +} + +export class RedisCache extends BaseCache { + public readonly client: Redis; + public readonly keyPrefix?: string; + public ttlSeconds?: number; + + static { + this.register(); + } + + constructor({ client, ttlSeconds, keyPrefix }: RedisCacheInput) { + super(); + this.client = client; + this.keyPrefix = keyPrefix; + this.ttlSeconds = ttlSeconds; + } + + private createRedisKey(key: string) { + return `${this.keyPrefix ?? ''}${key}`; + } + + async size(): Promise { + throw new Error('Operation not supported'); + } + + async set(key: string, value: T): Promise { + // Awaiting the value directly would cause deadlock when used with Tasks + (async () => { + try { + const redisKey = this.createRedisKey(key); + if (this.ttlSeconds) { + await this.client.set(redisKey, Serializer.serialize(await value), 'EX', this.ttlSeconds); + } else { + await this.client.set(redisKey, Serializer.serialize(await value)); + } + } catch (err) { + getLogger().warn({ err }, 'Failed to set cache'); + } + })(); + } + + async get(key: string): Promise { + const value = await this.client.get(this.createRedisKey(key)); + if (value) { + return Serializer.deserialize(value); + } + } + + async has(key: string): Promise { + const result = await this.client.exists(this.createRedisKey(key)); + return !!result; + } + + async delete(key: string): Promise { + const result = await this.client.del(this.createRedisKey(key)); + return !!result; + } + + clear(): Promise { + throw new Error('Operation not supported'); + } + + createSnapshot(): unknown { + throw new Error('Operation not supported'); + } + + loadSnapshot(_: unknown): void { + throw new Error('Operation not supported'); + } +} diff --git a/src/runs/execution/constants.ts b/src/runs/execution/constants.ts new file mode 100644 index 0000000..fdf080c --- /dev/null +++ b/src/runs/execution/constants.ts @@ -0,0 +1,39 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const RUN_EXPIRATION_MILLISECONDS = 10 * 60 * 1000; +export const STATUS_POLL_INTERVAL = 5 * 1000; + +export const LLMBackend = { + OLLAMA: 'ollama', + IBM_VLLM: 'ibm-vllm', + OPENAI: 'openai', + BAM: 'bam', + WATSONX: 'watsonx' +} as const; +export type LLMBackend = (typeof LLMBackend)[keyof typeof LLMBackend]; + +export const CodeInterpreterStorageBackend = { + S3: 's3', + FILESYSTEM: 'filesystem' +} as const; +export type CodeInterpreterStorageBackend = (typeof LLMBackend)[keyof typeof LLMBackend]; + +export const SearchToolBackend = { + GOOGLE: 'google', + DUCK_DUCK_GO: 'duck-duck-go' +} as const; +export type SearchToolBackend = (typeof SearchToolBackend)[keyof typeof SearchToolBackend]; diff --git a/src/runs/execution/event-handlers/streaming.ts b/src/runs/execution/event-handlers/streaming.ts new file mode 100644 index 0000000..98aecfa --- /dev/null +++ b/src/runs/execution/event-handlers/streaming.ts @@ -0,0 +1,352 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FrameworkError, Version } from 'bee-agent-framework'; +import { EventMeta, Emitter } from 'bee-agent-framework/emitter/emitter'; +import { ref } from '@mikro-orm/core'; +import { Role } from 'bee-agent-framework/llms/primitives/message'; +import { BeeCallbacks } from 'bee-agent-framework/agents/bee/types'; +import { Summary } from 'prom-client'; +import { ToolError } from 'bee-agent-framework/tools/base'; + +import { AgentContext } from '@/runs/execution/execute.js'; +import { getLogger } from '@/logger.js'; +import { createToolCall, finalizeToolCall } from '@/runs/execution/tools/helpers.js'; +import { RunStep, RunStepStatus } from '@/run-steps/entities/run-step.entity.js'; +import { RunStepToolCalls } from '@/run-steps/entities/details/run-step-tool-calls.entity.js'; +import { ORM } from '@/database.js'; +import { toRunStepDeltaDto, toRunStepDto } from '@/run-steps/run-steps.service.js'; +import { Message, MessageStatus } from '@/messages/message.entity.js'; +import { toMessageDto } from '@/messages/messages.service.js'; +import { RunStepMessageCreation } from '@/run-steps/entities/details/run-step-message-creation.entity.js'; +import { RunStepThought } from '@/run-steps/entities/details/run-step-thought.entity.js'; +import { RunStatus } from '@/runs/entities/run.entity.js'; +import { APIError } from '@/errors/error.entity.js'; +import { jobRegistry } from '@/metrics.js'; +import { EmitterEvent } from '@/run-steps/entities/emitter-event.entity'; +import { createClient } from '@/redis.js'; +import { createApproveChannel, toRunDto } from '@/runs/runs.service'; +import { RequiredToolApprove } from '@/runs/entities/requiredToolApprove.entity'; +import { ToolApprovalType } from '@/runs/entities/toolApproval.entity'; +import { ToolType } from '@/tools/entities/tool/tool.entity'; + +const agentToolExecutionTime = new Summary({ + name: 'agent_tool_execution_time_seconds', + help: 'Agent tool execution time in seconds', + labelNames: ['framework', 'tool'] as const, + registers: [jobRegistry] +}); + +export function createStreamingHandler(ctx: AgentContext) { + return (emitter: Emitter) => { + const logger = getLogger().child({ runId: ctx.run.id }); + + let toolExecutionEnd: (() => number) | null = null; + + emitter.on('toolStart', async ({ data }, meta) => { + toolExecutionEnd = agentToolExecutionTime.startTimer({ + framework: Version, + tool: data.tool.name + }); + + if (ctx.runStep) + logger.warn( + { data, step: ctx.runStep.id }, + 'Tool has started while previous run step has not finished' + ); + if (ctx.toolCall) + logger.warn( + { data, call: ctx.toolCall.id }, + 'Tool has started while previous call has not finished' + ); + + ctx.toolCall = await createToolCall(data, ctx); + ctx.runStep = new RunStep({ + project: ctx.run.project, + run: ref(ctx.run), + thread: ctx.run.thread, + assistant: ctx.run.assistant, + createdBy: ctx.run.createdBy, + details: new RunStepToolCalls({ + toolCalls: [ctx.toolCall] + }), + metadata: data.iteration.tool_caption ? { caption: data.iteration.tool_caption } : {}, + event: createEventFromMeta(meta) + }); + await ORM.em.persistAndFlush(ctx.runStep); + await ctx.publish({ + event: 'thread.run.step.created', + data: toRunStepDto(ctx.runStep) + }); + + const toolCall = ctx.toolCall; + if (toolCall) { + if ( + ctx.run.toolApprovals?.find( + (approval) => + approval.toolId === + (toolCall.type === ToolType.USER + ? toolCall.tool.id + : toolCall.type === ToolType.SYSTEM + ? toolCall.toolId + : toolCall.type) + )?.requireApproval === ToolApprovalType.ALWAYS + ) { + const client = createClient(); + await new Promise((resolve, reject) => { + client.subscribe(createApproveChannel(ctx.run, toolCall), async (err) => { + if (err) { + reject(err); + } else { + ctx.run.requireAction( + new RequiredToolApprove({ + toolCalls: [...(ctx.run.requiredAction?.toolCalls ?? []), toolCall] + }) + ); + await ORM.em.flush(); + await ctx.publish({ + event: 'thread.run.requires_action', + data: toRunDto(ctx.run) + }); + await ctx.publish({ + event: 'done', + data: '[DONE]' + }); + } + }); + client.on('message', async (_, approval) => { + ctx.run.submitAction(); + await ORM.em.flush(); + if (approval !== 'true') { + reject( + new ToolError('User has not approved this tool to run.', [], { + isFatal: false, + isRetryable: false + }) + ); + } + resolve(true); + }); + }); + } + } + + await ctx.publish({ + event: 'thread.run.step.in_progress', + data: toRunStepDto(ctx.runStep) + }); + }); + + emitter.on('toolSuccess', async ({ data }) => { + if (toolExecutionEnd) toolExecutionEnd(); + + if (!ctx.runStep) { + logger.warn({ data }, 'Tool has finished with missing run step'); + return; + } + if (!ctx.toolCall) { + logger.warn({ data }, 'Tool has finished with missing call'); + return; + } + + await finalizeToolCall(data, ctx); + }); + + emitter.on('toolError', ({ data }) => onError(ctx)(data.error)); + + // onUpdate follows with a flush and publish + emitter.on('update', async ({ data, update, meta }) => { + if (update.key === 'final_answer') { + if (!ctx.message) { + logger.warn({ successCall: data }, 'Agent success with missing message'); + return; + } + ctx.message.content = data.final_answer ?? ctx.message.content; + ctx.message.status = MessageStatus.COMPLETED; + await ORM.em.flush(); + await ctx.publish({ event: 'thread.message.completed', data: toMessageDto(ctx.message) }); + ctx.message = undefined; + } + if ( + update.key === 'final_answer' || + update.key === 'tool_output' || + update.key === 'thought' + ) { + if (!ctx.runStep) { + logger.warn({ successCall: data }, 'Agent finished step with missing run step'); + return; + } + if (update.key === 'thought' && ctx.runStep.details instanceof RunStepThought) { + ctx.runStep.details.content = data.thought ?? ctx.runStep.details.content; + } + if (meta.success) { + ctx.runStep.status = RunStepStatus.COMPLETED; + await ORM.em.flush(); + await ctx.publish({ + event: 'thread.run.step.completed', + data: toRunStepDto(ctx.runStep) + }); + } else { + ctx.runStep.status = RunStepStatus.FAILED; + await ORM.em.flush(); + await ctx.publish({ event: 'thread.run.step.failed', data: toRunStepDto(ctx.runStep) }); + } + ctx.runStep = undefined; + ctx.toolCall = undefined; + } + }); + + emitter.on('partialUpdate', async ({ update }, meta) => { + if (update.key === 'final_answer') { + if (!ctx.message) { + if (ctx.runStep) + logger.warn( + { messageCall: update, step: ctx.runStep.id }, + 'Message creation has started while previous run step has not finished' + ); + ctx.message = new Message({ + project: ctx.run.project, + role: Role.ASSISTANT, + content: '', + thread: ctx.run.thread, + run: ref(ctx.run), + createdBy: ctx.run.createdBy, + status: MessageStatus.IN_PROGRESS + }); + ctx.runStep = new RunStep({ + project: ctx.run.project, + run: ref(ctx.run), + thread: ctx.run.thread, + assistant: ctx.run.assistant, + createdBy: ctx.run.createdBy, + details: new RunStepMessageCreation({ message: ref(ctx.message) }), + event: createEventFromMeta(meta) + }); + await ORM.em.persistAndFlush([ctx.message, ctx.runStep]); + await ctx.publish({ + event: 'thread.run.step.created', + data: toRunStepDto(ctx.runStep) + }); + await ctx.publish({ + event: 'thread.run.step.in_progress', + data: toRunStepDto(ctx.runStep) + }); + await ctx.publish({ event: 'thread.message.created', data: toMessageDto(ctx.message) }); + await ctx.publish({ + event: 'thread.message.in_progress', + data: toMessageDto(ctx.message) + }); + } + ctx.message.content += update.value; + await ctx.publish({ + event: 'thread.message.delta', + data: { + id: ctx.message.id, + object: 'thread.message.delta', + delta: { + role: Role.ASSISTANT, + content: [ + { + index: 0, + type: 'text', + text: { + value: update.value + } + } + ] + } + } + }); + } else if (update.key === 'thought') { + if (!ctx.runStep) { + ctx.runStep = new RunStep({ + project: ctx.run.project, + run: ref(ctx.run), + thread: ctx.run.thread, + assistant: ctx.run.assistant, + createdBy: ctx.run.createdBy, + details: new RunStepThought({ content: undefined }), + event: createEventFromMeta(meta) + }); + await ORM.em.persistAndFlush(ctx.runStep); + await ctx.publish({ + event: 'thread.run.step.created', + data: toRunStepDto(ctx.runStep) + }); + await ctx.publish({ + event: 'thread.run.step.in_progress', + data: toRunStepDto(ctx.runStep) + }); + } + if (!(ctx.runStep?.details instanceof RunStepThought)) { + logger.warn( + { messageCall: update, step: ctx.runStep.id }, + 'Invalid run step type for thought update' + ); + return; + } + ctx.runStep.details.content += update.value; + await ctx.publish({ + event: 'thread.run.step.delta', + data: toRunStepDeltaDto(ctx.runStep, update.value) + }); + } + }); + emitter.on('error', ({ error }) => onError(ctx)(error)); + }; +} + +const onError = (ctx: AgentContext) => async (error: Error) => { + if (ctx.message) { + ctx.message.status = MessageStatus.INCOMPLETE; + await ORM.em.flush(); + await ctx.publish({ + event: 'thread.message.incomplete', + data: toMessageDto(ctx.message) + }); + ctx.message = undefined; + } + if (ctx.runStep) { + if (FrameworkError.isAbortError(error)) { + ctx.runStep.status = RunStatus.CANCELLED; + await ORM.em.flush(); + await ctx.publish({ + event: 'thread.run.step.cancelled', + data: toRunStepDto(ctx.runStep) + }); + } else { + ctx.runStep.status = RunStepStatus.FAILED; + ctx.runStep.lastError = APIError.from(error); + await ORM.em.flush(); + await ctx.publish({ event: 'thread.run.step.failed', data: toRunStepDto(ctx.runStep) }); + } + ctx.runStep = undefined; + ctx.toolCall = undefined; + } +}; + +const createEventFromMeta = (meta: EventMeta) => { + return meta.groupId + ? new EmitterEvent({ + id: meta.id, + groupId: meta.groupId, + name: meta.name, + path: meta.path, + runId: meta.trace?.runId, + parentRunId: meta.trace?.parentRunId + }) + : undefined; +}; diff --git a/src/runs/execution/execute.ts b/src/runs/execution/execute.ts new file mode 100644 index 0000000..0e2fa39 --- /dev/null +++ b/src/runs/execution/execute.ts @@ -0,0 +1,228 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Loaded } from '@mikro-orm/core'; +import { TokenMemory } from 'bee-agent-framework/memory/tokenMemory'; +import { BaseMessage } from 'bee-agent-framework/llms/primitives/message'; +import { Version } from 'bee-agent-framework'; +import { BeeAgent } from 'bee-agent-framework/agents/bee/agent'; +import { Summary } from 'prom-client'; +import dayjs from 'dayjs'; +import { isTruthy } from 'remeda'; +import { createObserveConnector } from 'bee-observe-connector'; + +import { Run } from '../entities/run.entity.js'; +import { toRunDto } from '../runs.service.js'; + +import { + addFileToToolResource, + checkFileExistsOnToolResource, + createToolResource, + getPromptTemplate +} from './helpers.js'; +import { getTools } from './tools/helpers.js'; +import { createChatLLM } from './factory.js'; + +import { ORM } from '@/database.js'; +import { getLogger } from '@/logger.js'; +import { createPublisher } from '@/streaming/pubsub.js'; +import { APIError } from '@/errors/error.entity.js'; +import { jobRegistry } from '@/metrics.js'; +import { getTraceLogger } from '@/observe/utils.js'; +import { watchForCancellation } from '@/utils/jobs.js'; +import { Trace } from '@/observe/entities/trace.entity.js'; +import { RunStep } from '@/run-steps/entities/run-step.entity.js'; +import { Message } from '@/messages/message.entity.js'; +import { AnyToolCall } from '@/tools/entities/tool-calls/tool-call.entity.js'; +import { createStreamingHandler } from '@/runs/execution/event-handlers/streaming.js'; +import { LoadedRun } from '@/runs/execution/types.js'; +import { UserResource } from '@/tools/entities/tool-resources/user-resource.entity.js'; +import { SystemResource } from '@/tools/entities/tool-resources/system-resource.entity.js'; +import { BEE_OBSERVE_API_AUTH_KEY, BEE_OBSERVE_API_URL } from '@/config.js'; + +const agentExecutionTime = new Summary({ + name: 'agent_execution_time_seconds', + help: 'Agent execution time in seconds', + labelNames: ['framework'] as const, + registers: [jobRegistry] +}); + +export type AgentContext = { + run: Loaded; + publish: ReturnType; + runStep?: Loaded; + message?: Loaded; + toolCall?: Loaded; +}; + +export async function executeRun(run: LoadedRun) { + const runLogger = getLogger().child({ runId: run.id }); + + const llm = createChatLLM(run); + + const publish = createPublisher(run); + + // create messages and add file ids to message content + const messages = run.thread.$.messages.$.filter((message) => !message.deletedAt).map( + (message) => + new BaseMessage( + message.role, + `${message.content}${message.attachments && message.attachments.length > 0 ? `\n\nFiles:\n${message.attachments.map((attachment) => attachment.file.id).join('\n')}` : ''}`, + { + createdAt: message.createdAt + } + ) + ); + + // add all files from the message attachments to the thread tool_resources + const attachments = run.thread.$.messages.$.getItems() + .filter((m) => !m.run && m.attachments) + .flatMap((m) => m.attachments ?? []); + + for (const attachment of attachments) { + const toolResources = run.thread.$.toolResources ?? []; + + await Promise.all( + (attachment.tools ?? [])?.map(async (tool) => { + const existingToolResources = toolResources.filter( + (tr) => + tr.type === tool.type && + (tr instanceof UserResource + ? tool.id === tr.tool.id + : tr instanceof SystemResource + ? tool.id === tr.toolId + : true) + ); + if (existingToolResources.length > 0) { + const fileExistsChecks = await Promise.all( + existingToolResources.map(async (existingToolResource) => + checkFileExistsOnToolResource(existingToolResource, attachment.file) + ) + ); + const fileExists = fileExistsChecks.some(isTruthy); + if (!fileExists) addFileToToolResource(existingToolResources[0], attachment.file); + } else { + const newResource = await createToolResource(tool.type, [attachment.file], tool.id); + newResource && toolResources.push(newResource); + } + }) + ); + + run.thread.$.toolResources = toolResources; + } + + const memory = new TokenMemory({ + llm + }); + await memory.addMany(messages); + + run.start(); + await ORM.em.flush(); + await publish({ event: 'thread.run.in_progress', data: toRunDto(run) }); + + const context = { run, publish } as AgentContext; + + const agent = new BeeAgent({ + llm, + memory, + tools: await getTools(run, context), + templates: { + system: getPromptTemplate(run) + } + }); + + const cancellationController = new AbortController(); + const unsub = watchForCancellation(Run, run, () => cancellationController.abort()); + + const expirationSignal = AbortSignal.timeout(dayjs(run.expiresAt).diff(dayjs(), 'milliseconds')); + + try { + const endAgentExecutionTimer = agentExecutionTime.labels({ framework: Version }).startTimer(); + const agentRunPromise = agent + .run( + { prompt: null }, // messages have been loaded to agent's memory + { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + signal: AbortSignal.any([cancellationController.signal, expirationSignal]), + execution: { + totalMaxRetries: 10, + maxRetriesPerStep: 3, + maxIterations: 10 + } + } + ) + .observe(createStreamingHandler(context)); + + // apply observe middleware only when the observe API is enabled + if (BEE_OBSERVE_API_URL && BEE_OBSERVE_API_AUTH_KEY) { + agentRunPromise.middleware( + createObserveConnector({ + api: { + baseUrl: BEE_OBSERVE_API_URL, + apiAuthKey: BEE_OBSERVE_API_AUTH_KEY, + ignored_keys: [ + 'apiToken', + 'apiKey', + 'cseId', + 'accessToken', + 'proxy', + 'username', + 'password' + ] + }, + cb: async (err, traceResponse) => { + if (err) { + getTraceLogger().warn({ err }, 'bee-observe API error'); + } else if (traceResponse) { + run.trace = new Trace({ id: traceResponse.result.id }); + } + } + }) + ); + } + + await agentRunPromise; + + endAgentExecutionTimer(); + run.complete(); + + await ORM.em.flush(); + await publish({ event: 'thread.run.completed', data: toRunDto(run) }); + } catch (err) { + if (expirationSignal.aborted) { + run.expire(); + await ORM.em.flush(); + await publish({ event: 'thread.run.expired', data: toRunDto(run) }); + return; + } else if (cancellationController.signal.aborted) { + run.cancel(); + await ORM.em.flush(); + await publish({ event: 'thread.run.cancelled', data: toRunDto(run) }); + return; + } + + runLogger.error({ err }, 'Run execution failed'); + run.fail(APIError.from(err)); + await ORM.em.flush(); + await publish({ event: 'thread.run.failed', data: toRunDto(run) }); + return; + } finally { + await publish({ event: 'done', data: '[DONE]' }); + unsub(); + agent.destroy(); + } +} diff --git a/src/runs/execution/factory.ts b/src/runs/execution/factory.ts new file mode 100644 index 0000000..5c36e6c --- /dev/null +++ b/src/runs/execution/factory.ts @@ -0,0 +1,200 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Loaded } from '@mikro-orm/core'; +import { Ollama } from 'ollama'; +import { OpenAI } from 'openai'; +import { Client as BAMClient } from '@ibm-generative-ai/node-sdk'; +import { Client as IBMvLLLClient } from 'bee-agent-framework/adapters/ibm-vllm/client'; +import { IBMVllmChatLLM } from 'bee-agent-framework/adapters/ibm-vllm/chat'; +import { OllamaChatLLM } from 'bee-agent-framework/adapters/ollama/chat'; +import { OpenAIChatLLM } from 'bee-agent-framework/adapters/openai/chat'; +import { + IBMVllmChatLLMPresetModel, + IBMVllmModel +} from 'bee-agent-framework/adapters/ibm-vllm/chatPreset'; +import { BAMChatLLMPresetModel } from 'bee-agent-framework/adapters/bam/chatPreset'; +import { BAMChatLLM } from 'bee-agent-framework/adapters/bam/chat'; +import { WatsonXChatLLM } from 'bee-agent-framework/adapters/watsonx/chat'; +import { WatsonXChatLLMPresetModel } from 'bee-agent-framework/adapters/watsonx/chatPreset'; +import { BAMLLM } from 'bee-agent-framework/adapters/bam/llm'; +import { IBMvLLM } from 'bee-agent-framework/adapters/ibm-vllm/llm'; +import { WatsonXLLM } from 'bee-agent-framework/adapters/watsonx/llm'; + +import { Run } from '../entities/run.entity'; + +import { LLMBackend } from './constants'; + +import { + BAM_API_KEY, + IBM_VLLM_CERT_CHAIN, + IBM_VLLM_PRIVATE_KEY, + IBM_VLLM_ROOT_CERT, + IBM_VLLM_URL, + LLM_BACKEND, + OLLAMA_URL, + OPENAI_API_KEY, + WATSONX_API_KEY, + WATSONX_PROJECT_ID +} from '@/config'; + +export function getDefaultModel(backend: LLMBackend = LLM_BACKEND) { + switch (backend) { + case LLMBackend.IBM_VLLM: + return IBMVllmModel.LLAMA_3_1_70B_INSTRUCT; + case LLMBackend.OLLAMA: + return 'llama3.1'; + case LLMBackend.OPENAI: + return 'gpt-4o'; + case LLMBackend.BAM: + return 'meta-llama/llama-3-1-70b-instruct'; + case LLMBackend.WATSONX: + return 'meta-llama/llama-3-1-70b-instruct'; + } +} + +// Clients are instantiated lazily in createLLM funciton +let vllmClient: IBMvLLLClient | null; +let ollamaClient: Ollama | null; +let openAIClient: OpenAI | null; +let bamClient: BAMClient | null; + +export function createChatLLM(run: Loaded, backend: LLMBackend = LLM_BACKEND) { + switch (backend) { + case LLMBackend.IBM_VLLM: { + vllmClient ??= new IBMvLLLClient({ + url: IBM_VLLM_URL ?? undefined, + credentials: + IBM_VLLM_ROOT_CERT && IBM_VLLM_CERT_CHAIN && IBM_VLLM_PRIVATE_KEY + ? { + rootCert: IBM_VLLM_ROOT_CERT, + certChain: IBM_VLLM_CERT_CHAIN, + privateKey: IBM_VLLM_PRIVATE_KEY + } + : undefined + }); + return IBMVllmChatLLM.fromPreset(run.model as IBMVllmChatLLMPresetModel, { + client: vllmClient, + parameters: (parameters) => ({ + ...parameters, + sampling: { + ...parameters.sampling, + top_p: run.topP ?? parameters.sampling?.top_p, + temperature: run.temperature ?? parameters.sampling?.temperature + } + }) + }); + } + case LLMBackend.OLLAMA: { + ollamaClient ??= new Ollama({ host: OLLAMA_URL ?? undefined }); + return new OllamaChatLLM({ + client: ollamaClient, + modelId: run.model, + parameters: { + top_p: run.topP, + temperature: run.temperature + } + }); + } + case LLMBackend.OPENAI: { + openAIClient ??= new OpenAI({ apiKey: OPENAI_API_KEY ?? undefined }); + return new OpenAIChatLLM({ + client: openAIClient, + modelId: run.model as OpenAI.ChatModel, + parameters: { + top_p: run.topP, + temperature: run.temperature + } + }); + } + case LLMBackend.BAM: { + bamClient ??= new BAMClient({ apiKey: BAM_API_KEY ?? undefined }); + return BAMChatLLM.fromPreset(run.model as BAMChatLLMPresetModel, { + client: bamClient, + parameters: (parameters) => ({ + ...parameters, + top_p: run.topP ?? parameters.top_p, + temperature: run.temperature ?? parameters.temperature + }) + }); + } + case LLMBackend.WATSONX: { + if (!WATSONX_API_KEY) throw new Error('Missing WATSONX_API_KEY'); + if (!WATSONX_PROJECT_ID) throw new Error('Missing WATSONX_PROJECT_ID'); + return WatsonXChatLLM.fromPreset(run.model as WatsonXChatLLMPresetModel, { + apiKey: WATSONX_API_KEY, + projectId: WATSONX_PROJECT_ID, + parameters: (parameters) => ({ + ...parameters, + top_p: run.topP ?? parameters.top_p, + temperature: run.temperature ?? parameters.temperature + }) + }); + } + } +} + +// TODO make lazy client init DRY + +export function createCodeLLM(backend: LLMBackend = LLM_BACKEND) { + switch (backend) { + case LLMBackend.IBM_VLLM: { + vllmClient ??= new IBMvLLLClient({ + url: IBM_VLLM_URL ?? undefined, + credentials: + IBM_VLLM_ROOT_CERT && IBM_VLLM_CERT_CHAIN && IBM_VLLM_PRIVATE_KEY + ? { + rootCert: IBM_VLLM_ROOT_CERT, + certChain: IBM_VLLM_CERT_CHAIN, + privateKey: IBM_VLLM_PRIVATE_KEY + } + : undefined + }); + return new IBMvLLM({ + client: vllmClient, + modelId: 'ibm/granite-34b-code-instruct', + parameters: { method: 'GREEDY', stopping: { include_stop_sequence: false } } + }); + } + case LLMBackend.BAM: { + bamClient ??= new BAMClient({ apiKey: BAM_API_KEY ?? undefined }); + return new BAMLLM({ + client: bamClient, + modelId: 'ibm/granite-34b-code-instruct', + parameters: { + decoding_method: 'greedy', + include_stop_sequence: false + } + }); + } + case LLMBackend.WATSONX: { + if (!WATSONX_API_KEY) throw new Error('Missing WATSONX_API_KEY'); + if (!WATSONX_PROJECT_ID) throw new Error('Missing WATSONX_PROJECT_ID'); + return new WatsonXLLM({ + modelId: 'ibm/granite-34b-code-instruct', + apiKey: WATSONX_API_KEY, + projectId: WATSONX_PROJECT_ID, + parameters: { + decoding_method: 'greedy', + include_stop_sequence: false, + max_new_tokens: 2048 + } + }); + } + default: + return undefined; + } +} diff --git a/src/runs/execution/helpers.ts b/src/runs/execution/helpers.ts new file mode 100644 index 0000000..2010e9b --- /dev/null +++ b/src/runs/execution/helpers.ts @@ -0,0 +1,118 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Loaded, ref, Ref } from '@mikro-orm/core'; +import { BeeSystemPrompt } from 'bee-agent-framework/agents/bee/prompts'; +import { unique } from 'remeda'; + +import { Run } from '../entities/run.entity.js'; + +import { ORM } from '@/database.js'; +import { File } from '@/files/entities/file.entity.js'; +import { FileSearchResource } from '@/tools/entities/tool-resources/file-search-resources.entity.js'; +import { Assistant } from '@/assistants/assistant.entity.js'; +import { Thread } from '@/threads/thread.entity.js'; +import { VectorStoreContainer } from '@/vector-stores/entities/vector-store-container.entity.js'; +import { AnyToolResource } from '@/tools/entities/tool-resources/tool-resource.entity.js'; +import { Tool, ToolType } from '@/tools/entities/tool/tool.entity.js'; +import { CodeInterpreterResource } from '@/tools/entities/tool-resources/code-interpreter-resource.entity.js'; +import { FileContainer } from '@/files/entities/files-container.entity.js'; +import { VectorStore } from '@/vector-stores/entities/vector-store.entity.js'; +import { UserResource } from '@/tools/entities/tool-resources/user-resource.entity.js'; +import { SystemResource } from '@/tools/entities/tool-resources/system-resource.entity.js'; + +export function getRunVectorStores( + assistant: Loaded, + thread: Loaded +): Loaded[] { + const vectorStores = [...(assistant.toolResources ?? []), ...(thread.toolResources ?? [])] + .filter((resource): resource is FileSearchResource => resource.type === ToolType.FILE_SEARCH) + .flatMap( + (resource) => resource.vectorStoreContainers as Loaded[] + ) + .flatMap((container) => container.vectorStore.$); + return unique(vectorStores); // filter out duplicates +} + +export function getPromptTemplate(run: Loaded) { + const instructions = run.additionalInstructions + ? `${run.instructions} ${run.additionalInstructions}` + : run.instructions; + return BeeSystemPrompt.fork((input) => ({ + ...input, + ...(run.assistant.$.systemPromptOverwrite + ? { template: run.assistant.$.systemPromptOverwrite } + : {}), + defaults: { + ...input.defaults, + ...(instructions ? { instructions } : {}) + } + })); +} + +export async function checkFileExistsOnToolResource( + toolResource: AnyToolResource, + file: Ref +): Promise { + switch (toolResource.type) { + case ToolType.USER: + case ToolType.CODE_INTERPRETER: + return !!toolResource.fileContainers.find((fc) => fc.file.id === file.id); + case ToolType.FILE_SEARCH: { + const vectorStoreContainers = await ORM.em + .getRepository(VectorStoreContainer) + .populate(toolResource.vectorStoreContainers, ['vectorStore.files']); + + return !!vectorStoreContainers + .flatMap((vsc) => vsc.vectorStore) + .flatMap((vs) => vs.$.files.getItems()) + .find((f) => f.file.id === file.id); + } + default: + return true; + } +} + +export function addFileToToolResource(toolResource: AnyToolResource, file: Ref) { + switch (toolResource.type) { + case ToolType.CODE_INTERPRETER: + case ToolType.USER: + case ToolType.SYSTEM: + toolResource.fileContainers.push(new FileContainer({ file })); + break; + case ToolType.FILE_SEARCH: + throw new Error('Not implemented'); + default: + return undefined; + } +} + +export async function createToolResource(type: ToolType, files: Ref[], toolId?: string) { + switch (type) { + case ToolType.CODE_INTERPRETER: + return new CodeInterpreterResource({ files }); + case ToolType.SYSTEM: + if (!toolId) throw new Error('Missing tool id'); + return new SystemResource({ toolId, files }); + case ToolType.USER: + if (!toolId) throw new Error('Missing tool id'); + return new UserResource({ tool: ref(Tool, toolId), files }); + case ToolType.FILE_SEARCH: + throw new Error('Not implemented'); + default: + return undefined; + } +} diff --git a/src/runs/execution/tools/api-call-tool.ts b/src/runs/execution/tools/api-call-tool.ts new file mode 100644 index 0000000..14c46c2 --- /dev/null +++ b/src/runs/execution/tools/api-call-tool.ts @@ -0,0 +1,137 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { join } from 'path'; + +import { BaseToolOptions, StringToolOutput, Tool, ToolError } from 'bee-agent-framework/tools/base'; +import { SchemaObject } from 'ajv'; +import { parse } from 'yaml'; +import { isEmpty } from 'remeda'; +import axios from 'axios'; +import { HttpProxyAgent } from 'http-proxy-agent'; +import { HttpsProxyAgent } from 'https-proxy-agent'; + +import { AgentContext } from '../execute.js'; + +import { APIError, APIErrorCode } from '@/errors/error.entity.js'; +import decrypt from '@/utils/crypto/decrypt.js'; +import { HTTP_PROXY_URL } from '@/config'; + +export interface ApiCallToolOptions extends BaseToolOptions { + name: string; + description?: string; + openApiSchema?: any; + apiKey?: string; + + context: AgentContext; +} + +// TODO use tool from the framework +export class ApiCallTool extends Tool { + name: string; + description: string; + openApiSchema: any; + apiKey?: string; + + inputSchema() { + return { + type: 'object', + required: ['path', 'method'], + oneOf: Object.entries(this.openApiSchema.paths).flatMap(([path, pathSpec]: [string, any]) => + Object.entries(pathSpec).map(([method, methodSpec]: [string, any]) => ({ + additionalProperties: false, + properties: { + path: { + const: path, + description: + 'Do not replace variables in path, instead of, put them to the parameters object.' + }, + method: { const: method, description: methodSpec.summary || methodSpec.description }, + ...(methodSpec.requestBody?.content?.['application/json']?.schema + ? { + body: methodSpec.requestBody?.content?.['application/json']?.schema + } + : {}), + ...(methodSpec.parameters + ? { + parameters: { + type: 'object', + additionalProperties: false, + required: methodSpec.parameters + .filter((p: any) => p.required === true) + .map((p: any) => p.name), + properties: methodSpec.parameters.reduce( + (acc: any, p: any) => ({ + ...acc, + [p.name]: { ...p.schema, description: p.name } + }), + {} + ) + } + } + : {}) + } + })) + ) + } as const satisfies SchemaObject; + } + + public constructor({ name, description, openApiSchema, apiKey, ...rest }: ApiCallToolOptions) { + super({ name, description, ...rest }); + this.name = name; + this.apiKey = apiKey; + this.description = description ?? 'Use input schema to infer description'; + this.openApiSchema = parse(openApiSchema); + if (!this.openApiSchema?.paths) { + throw new APIError({ + message: `Server is not specified`, + code: APIErrorCode.INVALID_INPUT + }); + } + } + + protected async _run(input: any) { + let path: string = input.path || ''; + const url = new URL(this.openApiSchema.servers[0].url); + Object.keys(input.parameters ?? {}).forEach((key) => { + if (path.search(`{${key}}`) >= 0) { + path = path.replace(`{${key}}`, input.parameters[key]); + } else { + url.searchParams.append(key, input.parameters[key]); + } + }); + url.pathname = join(url.pathname, path); + const headers: { [key: string]: string } = { Accept: 'application/json' }; + if (this.apiKey) { + headers['Authorization'] = `Bearer ${decrypt(this.apiKey)}`; + } + try { + const response = await axios.request({ + url: url.toString(), + data: !isEmpty(input.body) ? input.body : undefined, + method: input.method.toLowerCase(), + headers, + transformResponse: [(data) => data], + httpsAgent: HTTP_PROXY_URL && new HttpsProxyAgent(HTTP_PROXY_URL), + httpAgent: HTTP_PROXY_URL && new HttpProxyAgent(HTTP_PROXY_URL), + signal: AbortSignal.timeout(30_000) + }); + return new StringToolOutput(response.data); + } catch (error) { + throw new ToolError(`Request to ${url} failed.`); + } + } +} diff --git a/src/runs/execution/tools/file-search-tool.ts b/src/runs/execution/tools/file-search-tool.ts new file mode 100644 index 0000000..796c9c8 --- /dev/null +++ b/src/runs/execution/tools/file-search-tool.ts @@ -0,0 +1,126 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + BaseToolOptions, + BaseToolRunOptions, + Tool, + ToolInput, + ToolOutput +} from 'bee-agent-framework/tools/base'; +import { z } from 'zod'; +import { isTruthy } from 'remeda'; +import { Loaded } from '@mikro-orm/core'; + +import { getVectorStoreClient } from '@/vector-store-files/execution/client.js'; +import { VectorStore } from '@/vector-stores/entities/vector-store.entity.js'; +import { createEmbeddingAdapter } from '@/embedding/factory'; + +export interface FileSearchToolOptions extends BaseToolOptions { + vectorStores: Loaded[]; + maxNumResults: number; +} + +export interface FileSearchToolResult { + content: string; + source?: string; +} +export class FileSearchToolOutput extends ToolOutput { + constructor(public readonly results: FileSearchToolResult[]) { + super(); + } + + get sources() { + return this.results.map((result) => result.source).filter(isTruthy); + } + + isEmpty() { + return this.results.length === 0; + } + + getTextContent(): string { + return JSON.stringify(this.results); + } + + createSnapshot() { + return { results: this.results }; + } + + loadSnapshot(snapshot: ReturnType): void { + Object.assign(this, snapshot); + } +} + +export class FileSearchTool extends Tool { + static { + this.register(); + } + + maxNumResults: number; + name: string; + description: string; + inputSchema() { + return z.object({ + query: z.string({ description: 'Question to answer using file search.' }).min(1).max(128) + }); + } + vectorStores: Loaded[]; + + async _run( + { query }: ToolInput, + options: BaseToolRunOptions + ): Promise { + const vectorStoreClient = getVectorStoreClient(); + + const embeddingAdapter = await createEmbeddingAdapter(); + + const embedding = await embeddingAdapter.embed(query, { signal: options.signal }); + if (!embedding) throw new Error('Missing embedding data in embedding response'); + + if (this.vectorStores.some((vectorStore) => vectorStore.expired)) { + throw new Error('Some of the vector stores are expired'); + } + + const vectorStoreFileIds = ( + await Promise.all(this.vectorStores.map((store) => store.completedFiles.loadItems())) + ) + .flatMap((vectorStoreFiles) => vectorStoreFiles) + .map((vectorStore) => vectorStore.id); + + const documents = await vectorStoreClient.similaritySearchVectorWithScore( + embedding, + this.maxNumResults, + vectorStoreFileIds + ); + + return new FileSearchToolOutput( + documents.map((d) => ({ + content: d.document.text, + source: d.document.source?.url ?? d.document.source?.file?.name + })) + ); + } + + constructor(config: FileSearchToolOptions) { + super(config); + this.name = `FileSearch`; + this.maxNumResults = config.maxNumResults; + this.vectorStores = config.vectorStores; + this.description = + `Worker that searches results from content of files. ` + + `Use to find out single fact about the content. Input must be a short specific query.`; + } +} diff --git a/src/runs/execution/tools/function.ts b/src/runs/execution/tools/function.ts new file mode 100644 index 0000000..bade934 --- /dev/null +++ b/src/runs/execution/tools/function.ts @@ -0,0 +1,129 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + BaseToolOptions, + BaseToolRunOptions, + Tool, + ToolInput, + ToolOutput +} from 'bee-agent-framework/tools/base'; +import { SchemaObject } from 'ajv'; +import { Loaded } from '@mikro-orm/core'; + +import { AgentContext } from '../execute.js'; + +import { createClient } from '@/redis.js'; +import { Run } from '@/runs/entities/run.entity.js'; +import { ORM } from '@/database.js'; +import { toRunDto } from '@/runs/runs.service.js'; +import { FunctionCall } from '@/tools/entities/tool-calls/function-call.entity.js'; +import { RequiredToolOutput } from '@/runs/entities/requiredToolOutput.entity.js'; + +export interface FunctionToolOptions extends BaseToolOptions { + name: string; + description?: string; + parameters?: SchemaObject; + + context: AgentContext; +} + +export class FunctionToolOutput extends ToolOutput { + constructor(public readonly output: string) { + super(); + } + + getTextContent(): string { + return this.output; + } + isEmpty(): boolean { + return false; + } + createSnapshot(): unknown { + return { + output: this.output + }; + } + loadSnapshot(_snapshot: unknown): void { + throw new Error('Method not implemented.'); + } +} + +export class FunctionTool extends Tool { + name: string; + description: string; + + inputSchema() { + return this.options.parameters ?? {}; + } + + public constructor({ name, description, ...rest }: FunctionToolOptions) { + super({ name, description, ...rest }); + this.name = name; + this.description = description ?? 'Use input schema to infer description'; + } + + private static createChannel(run: Loaded, toolCallId: string) { + return `run:${run.id}:call:${toolCallId}:output`; + } + + protected async _run(_: ToolInput, options: BaseToolRunOptions) { + const toolCall = this.options.context.toolCall; + if (!(toolCall instanceof FunctionCall)) throw new Error('Invalid tool call'); + + const client = createClient(); + return await new Promise((resolve, reject) => { + client.subscribe( + FunctionTool.createChannel(this.options.context.run, toolCall.id), + async (err) => { + if (err) { + reject(err); + } else { + this.options.context.run.requireAction( + new RequiredToolOutput({ + toolCalls: [...(this.options.context.run.requiredAction?.toolCalls ?? []), toolCall] + }) + ); + await ORM.em.flush(); + await this.options.context.publish({ + event: 'thread.run.requires_action', + data: toRunDto(this.options.context.run) + }); + await this.options.context.publish({ + event: 'done', + data: '[DONE]' + }); + } + } + ); + client.on('message', async (_, output) => { + this.options.context.run.submitAction(); + await ORM.em.flush(); + resolve(new FunctionToolOutput(output)); + }); + options.signal?.addEventListener('abort', () => { + reject(options.signal?.reason); + }); + }); + } + + static async submit( + output: string, + { run, toolCallId }: { run: Loaded; toolCallId: string } + ) { + await createClient().publish(FunctionTool.createChannel(run, toolCallId), output); + } +} diff --git a/src/runs/execution/tools/helpers.ts b/src/runs/execution/tools/helpers.ts new file mode 100644 index 0000000..928e756 --- /dev/null +++ b/src/runs/execution/tools/helpers.ts @@ -0,0 +1,400 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + AnyTool, + StringToolOutput, + Tool as FrameworkTool, + ToolOutput +} from 'bee-agent-framework/tools/base'; +import { PythonTool } from 'bee-agent-framework/tools/python/python'; +import { PythonToolOutput } from 'bee-agent-framework/tools/python/output'; +import { Loaded, ref } from '@mikro-orm/core'; +import { CustomTool } from 'bee-agent-framework/tools/custom'; +import { ArXivTool, ArXivToolOutput } from 'bee-agent-framework/tools/arxiv'; +import { OpenMeteoTool } from 'bee-agent-framework/tools/weather/openMeteo'; +import { SimilarityToolOutput } from 'bee-agent-framework/tools/similarity'; +import { GoogleSearchTool } from 'bee-agent-framework/tools/search/googleSearch'; +import { uniqueBy } from 'remeda'; +import { z } from 'zod'; +import { PromptTemplate } from 'bee-agent-framework/template'; +import { DuckDuckGoSearchTool } from 'bee-agent-framework/tools/search/duckDuckGoSearch'; +import { SearchToolOptions, SearchToolOutput } from 'bee-agent-framework/tools/search/base'; + +import { AgentContext } from '../execute.js'; +import { getRunVectorStores } from '../helpers.js'; +import { CodeInterpreterTool as CodeInterpreterUserTool } from '../../../tools/entities/tool/code-interpreter-tool.entity.js'; +import { ApiTool as ApiCallUserTool } from '../../../tools/entities/tool/api-tool.entity.js'; +import { createCodeLLM } from '../factory.js'; +import { RedisCache } from '../cache.js'; + +import { createPythonStorage } from './python-tool-storage.js'; +import { FunctionTool, FunctionToolOutput } from './function.js'; +import { FileSearchTool, FileSearchToolOutput } from './file-search-tool.js'; +import { ApiCallTool } from './api-call-tool.js'; +import { ReadFileTool } from './read-file-tool.js'; + +import { CodeInterpreterCall } from '@/tools/entities/tool-calls/code-interpreter-call.entity.js'; +import { ORM } from '@/database.js'; +import { getLogger } from '@/logger.js'; +import { Tool, ToolExecutor, ToolType } from '@/tools/entities/tool/tool.entity.js'; +import { CodeInterpreterUsage } from '@/tools/entities/tool-usages/code-interpreter-usage.entity.js'; +import { + BEE_CODE_INTERPRETER_CA_CERT, + BEE_CODE_INTERPRETER_CERT, + BEE_CODE_INTERPRETER_KEY, + BEE_CODE_INTERPRETER_URL +} from '@/config.js'; +import { FileContainer } from '@/files/entities/files-container.entity.js'; +import { FunctionUsage } from '@/tools/entities/tool-usages/function-usage.entity.js'; +import { FunctionCall } from '@/tools/entities/tool-calls/function-call.entity.js'; +import { SystemCall, SystemTools } from '@/tools/entities/tool-calls/system-call.entity.js'; +import { UserCall } from '@/tools/entities/tool-calls/user-call.entity.js'; +import { SystemUsage } from '@/tools/entities/tool-usages/system-usage.entity.js'; +import { UserUsage } from '@/tools/entities/tool-usages/user-usage.entity.js'; +import { FileSearchUsage } from '@/tools/entities/tool-usages/file-search-usage.entity.js'; +import { FileSearchCall } from '@/tools/entities/tool-calls/file-search-call.entity.js'; +import { FunctionTool as FunctionUserTool } from '@/tools/entities/tool/function-tool.entity.js'; +import { WikipediaSimilaritySearchTool } from '@/runs/execution/tools/wikipedia-similarity-search-tool.js'; +import { LoadedRun } from '@/runs/execution/types.js'; +import { CodeInterpreterResource } from '@/tools/entities/tool-resources/code-interpreter-resource.entity.js'; +import { File } from '@/files/entities/file.entity.js'; +import { Attachment } from '@/messages/attachment.entity.js'; +import { SystemResource } from '@/tools/entities/tool-resources/system-resource.entity.js'; +import { createSearchTool } from '@/runs/execution/tools/search-tool'; +import { createCacheClient } from '@/redis.js'; + +const searchCache: SearchToolOptions['cache'] = new RedisCache({ + client: createCacheClient({ + connectTimeout: 1000, + maxRetriesPerRequest: 1 + }), + keyPrefix: 'search:', + ttlSeconds: 60 * 60 +}); + +export function createCodeInterpreterConnectionOptions() { + if (!BEE_CODE_INTERPRETER_URL) throw new Error('Missing code interpreter URL'); + return { + url: BEE_CODE_INTERPRETER_URL, + connectionOptions: { + ...(BEE_CODE_INTERPRETER_CA_CERT ? { ca: BEE_CODE_INTERPRETER_CA_CERT } : {}), + ...(BEE_CODE_INTERPRETER_CERT ? { cert: BEE_CODE_INTERPRETER_CERT } : {}), + ...(BEE_CODE_INTERPRETER_KEY ? { key: BEE_CODE_INTERPRETER_KEY } : {}) + } + } as const; +} + +export async function getTools(run: LoadedRun, context: AgentContext): Promise { + const tools: FrameworkTool[] = []; + + const vectorStores = getRunVectorStores(run.assistant.$, run.thread.$); + for (const vectorStore of vectorStores) { + vectorStore.lastActiveAt = new Date(); // side effect + } + + const fileSearchUsage = run.tools.find( + (tool): tool is FileSearchUsage => tool.type === ToolType.FILE_SEARCH + ); + if (fileSearchUsage) { + if (vectorStores.length > 0) { + tools.push( + new FileSearchTool({ vectorStores, maxNumResults: fileSearchUsage.maxNumResults }) + ); + } + } + + const webSearchUsage = run.tools.find( + (tool): tool is SystemUsage => + tool.type === ToolType.SYSTEM && tool.toolId === SystemTools.WEB_SEARCH + ); + if (webSearchUsage) { + tools.push(createSearchTool({ cache: searchCache })); + } + + const wikipediaUsage = run.tools.find( + (tool): tool is SystemUsage => + tool.type === ToolType.SYSTEM && tool.toolId === SystemTools.WIKIPEDIA + ); + if (wikipediaUsage) tools.push(new WikipediaSimilaritySearchTool()); + + const weatherUsage = run.tools.find( + (tool): tool is SystemUsage => + tool.type === ToolType.SYSTEM && tool.toolId === SystemTools.WEATHER + ); + if (weatherUsage) + tools.push( + new OpenMeteoTool({ + retryOptions: { + maxRetries: 3 + } + }) + ); + + const arxivUsage = run.tools.find( + (tool): tool is SystemUsage => + tool.type === ToolType.SYSTEM && tool.toolId === SystemTools.ARXIV + ); + if (arxivUsage) tools.push(new ArXivTool()); + + const codeInterpreterUsage = run.tools.find( + (tool): tool is CodeInterpreterUsage => tool.type === ToolType.CODE_INTERPRETER + ); + const customUsages = run.tools.filter( + (toolUsage): toolUsage is Loaded => toolUsage.type === ToolType.USER + ); + + const executorId = `user-${run.createdBy.id}`; + + if (codeInterpreterUsage || customUsages.length > 0) { + if (BEE_CODE_INTERPRETER_URL) { + const codeInterpreter = createCodeInterpreterConnectionOptions(); + const files = [ + ...(run.assistant.$.toolResources ?? []), + ...(run.thread.$.toolResources ?? []) + ] + .filter( + (resource): resource is Loaded => + resource.type === ToolType.CODE_INTERPRETER + ) + .flatMap((resource) => resource.fileContainers as Loaded[]) + .flatMap((container) => container.file.$); + + if (codeInterpreterUsage) { + const codeLLM = createCodeLLM(); + tools.push( + new PythonTool({ + codeInterpreter, + executorId, + storage: createPythonStorage(files, run), + preprocess: codeLLM + ? { + llm: codeLLM, + promptTemplate: new PromptTemplate({ + schema: z.object({ input: z.string() }), + template: `Your task is to fix provided Python Code that may or may not contain a syntax error.\nIMPORTANT: the output must not contain any additional comments or explanation.\n\nInput:\n{{input}}\n\nOutput:\n` + }) + } + : undefined + }) + ); + } + tools.push( + ...customUsages.map((toolUsage) => { + switch (toolUsage.tool.$.executor) { + case ToolExecutor.CODE_INTERPRETER: + return new CustomTool({ + codeInterpreter, + executorId, + description: toolUsage.tool.$.description, + sourceCode: (toolUsage.tool.$).sourceCode, + name: toolUsage.tool.$.name, + inputSchema: (toolUsage.tool.$).jsonSchema + }); + case ToolExecutor.FUNCTION: + return new FunctionTool({ + name: toolUsage.tool.$.name, + description: toolUsage.tool.$.description, + parameters: (toolUsage.tool.$).parameters, + context + }); + case ToolExecutor.API: + return new ApiCallTool({ + name: toolUsage.tool.$.name, + description: toolUsage.tool.$.description, + openApiSchema: (toolUsage.tool.$).openApiSchema, + context, + apiKey: (toolUsage.tool.$).apiKey + }); + } + }) + ); + } else { + getLogger() + .child({ runId: run.id }) + .warn('Code execution was requested but skipped due to being disabled'); + } + } + + const readFileUsage = run.tools.find( + (tool): tool is SystemUsage => + tool.type === ToolType.SYSTEM && tool.toolId === SystemTools.READ_FILE + ); + if (readFileUsage) { + const files = [...(run.assistant.$.toolResources ?? []), ...(run.thread.$.toolResources ?? [])] + .filter( + (resource): resource is Loaded => + resource.type === ToolType.SYSTEM && resource.toolId === SystemTools.READ_FILE + ) + .flatMap((resource) => resource.fileContainers as Loaded[]) + .flatMap((container) => container.file.$); + + tools.push( + new ReadFileTool({ + fileSize: 500_000, + files, + retryOptions: { maxRetries: 0 } + }) + ); + } + + const functionUsages = run.tools.filter( + (tool): tool is FunctionUsage => tool.type === ToolType.FUNCTION + ); + functionUsages.forEach((usage) => { + tools.push( + new FunctionTool({ + name: usage.name, + description: usage.description, + parameters: usage.parameters, + context + }) + ); + }); + + return tools; +} + +export async function getAllReadableRunFiles(run: LoadedRun): Promise[]> { + const attachedFiles = run.thread.$.messages.$.map( + (message) => + message.attachments?.map((attachment) => (attachment as Loaded).file.$) ?? + [] + ).flat(); + const resourceFiles = [ + ...(run.assistant.$.toolResources ?? []), + ...(run.thread.$.toolResources ?? []) + ] + .filter((resource): resource is Loaded => 'fileContainers' in resource) + .flatMap((resource) => resource.fileContainers as Loaded[]) + .filter((fileContainer) => fileContainer.file.$.extraction) + .flatMap((container) => container.file.$); + return uniqueBy([...resourceFiles, ...attachedFiles], (file) => file.id); +} + +export async function createToolCall( + { + tool, + input + }: { + tool: AnyTool; + input: unknown; + }, + { run }: AgentContext +) { + if (tool instanceof FileSearchTool) { + return new FileSearchCall({ + input: tool.inputSchema().parse(input).query + }); + } else if (tool instanceof WikipediaSimilaritySearchTool) { + return new SystemCall({ + toolId: SystemTools.WIKIPEDIA, + input: tool.inputSchema().parse(input) + }); + } else if (tool instanceof GoogleSearchTool || tool instanceof DuckDuckGoSearchTool) { + return new SystemCall({ + toolId: SystemTools.WEB_SEARCH, + input: tool.inputSchema().parse(input) + }); + } else if (tool instanceof OpenMeteoTool) { + return new SystemCall({ + toolId: SystemTools.WEATHER, + input: tool.inputSchema().parse(input) + }); + } else if (tool instanceof ArXivTool) { + return new SystemCall({ + toolId: SystemTools.ARXIV, + input: tool.inputSchema().parse(input) + }); + } else if (tool instanceof PythonTool) { + return new CodeInterpreterCall({ + input: (await tool.inputSchema()).parse(input).code + }); + } else if (tool instanceof ReadFileTool) { + return new SystemCall({ + toolId: SystemTools.READ_FILE, + input: tool.inputSchema().parse(input) + }); + } else if (tool instanceof FunctionTool) { + return new FunctionCall({ name: tool.name, arguments: JSON.stringify(input) }); + } else if (tool instanceof CustomTool || tool instanceof ApiCallTool) { + const [toolEntity] = await ORM.em + .getRepository(Tool) + .find({ name: tool.name, project: run.project }); + return new UserCall({ + tool: ref(toolEntity), + arguments: JSON.stringify(input) + }); + } + throw new Error(`Unexpected tool ${tool.name}`); +} + +export async function finalizeToolCall( + { + result + }: { + result: ToolOutput; + }, + { toolCall }: AgentContext +) { + if (!toolCall) throw new Error(`No tool call to finalize`); + + if (toolCall instanceof SystemCall) { + switch (toolCall.toolId) { + case SystemTools.WIKIPEDIA: { + if (!(result instanceof SimilarityToolOutput)) throw new TypeError(); + toolCall.output = result.result; + break; + } + case SystemTools.WEB_SEARCH: { + if (!(result instanceof SearchToolOutput)) throw new TypeError(); + toolCall.output = result.results; + break; + } + case SystemTools.ARXIV: { + if (!(result instanceof ArXivToolOutput)) throw new TypeError(); + toolCall.output = result.result; + break; + } + case SystemTools.WEATHER: { + toolCall.output = result; + break; + } + case SystemTools.READ_FILE: { + if (!(result instanceof StringToolOutput)) throw new TypeError(); + toolCall.output = result.result; + break; + } + } + } else if (toolCall instanceof CodeInterpreterCall) { + if (!(result instanceof PythonToolOutput)) throw new TypeError(); + toolCall.logs = [result.stdout, result.stderr]; + toolCall.fileContainers = result.outputFiles?.map( + (file) => new FileContainer({ file: ref(File, file.id) }) + ); + } else if (toolCall instanceof FunctionCall) { + if (!(result instanceof FunctionToolOutput)) throw new TypeError(); + toolCall.output = result.output; + } else if (toolCall instanceof FileSearchCall) { + if (!(result instanceof FileSearchToolOutput)) throw new TypeError(); + toolCall.results = result.results; + } else if (toolCall instanceof UserCall) { + if (!(result instanceof StringToolOutput)) throw new TypeError(); + toolCall.output = result.result; + } else { + throw new Error(`Unexpected tool call`); + } +} diff --git a/src/runs/execution/tools/python-tool-storage.ts b/src/runs/execution/tools/python-tool-storage.ts new file mode 100644 index 0000000..698d5de --- /dev/null +++ b/src/runs/execution/tools/python-tool-storage.ts @@ -0,0 +1,236 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { randomUUID, UUID } from 'node:crypto'; +import { pipeline } from 'node:stream/promises'; +import path from 'node:path'; +import fs from 'node:fs'; + +import { + PythonDownloadFile, + PythonFile, + PythonStorage, + PythonUploadFile +} from 'bee-agent-framework/tools/python/storage'; +import { Loaded } from '@mikro-orm/mongodb'; + +import { LoadedRun } from '../types.js'; + +import { File, FilePurpose } from '@/files/entities/file.entity.js'; +import { ORM } from '@/database.js'; +import { s3Client } from '@/files/files.service.js'; +import { + BEE_CODE_INTERPRETER_BUCKET_FILE_STORAGE, + BEE_CODE_INTERPRETER_FILE_STORAGE_PATH, + BEE_CODE_INTERPRETER_STORAGE_BACKEND, + S3_BUCKET_FILE_STORAGE +} from '@/config.js'; +import { CodeInterpreterResource } from '@/tools/entities/tool-resources/code-interpreter-resource.entity.js'; +import { CodeInterpreterStorageBackend } from '@/runs/execution/constants'; + +async function ensureFiles( + run: LoadedRun, + files: { file: PythonDownloadFile; storageId: UUID }[] +): Promise { + const newFiles = await Promise.all( + files.map(async ({ file, storageId }) => { + const { ContentLength } = await s3Client + .headObject({ Bucket: S3_BUCKET_FILE_STORAGE, Key: storageId }) + .promise(); + if (!ContentLength) throw new Error(`Missing content length of file ${storageId}`); + + return new File({ + project: run.project, + createdBy: run.createdBy, + filename: file.filename, + dependsOn: run.thread, + storageId, + bytes: ContentLength, + purpose: FilePurpose.ASSISTANTS_OUTPUT, + contentHash: file.pythonId + }); + }) + ); + + if (newFiles.length > 0) { + ORM.em.persist(newFiles); + const thread = await run.thread.loadOrFail({ populate: ['toolResources'] }); + if (!thread.toolResources) { + thread.toolResources = []; + } + thread.toolResources.push(new CodeInterpreterResource({ files: newFiles })); + await ORM.em.flush(); + } + + return newFiles.map((file) => ({ + id: file.id, + pythonId: file.contentHash, + filename: file.filename + })); +} + +export class S3Storage extends PythonStorage { + constructor( + public readonly files: Loaded[], + public readonly run: LoadedRun | null + ) { + super(); + } + + get codeInterpreterBucket() { + if (!BEE_CODE_INTERPRETER_BUCKET_FILE_STORAGE) throw new Error('Missing bucket'); + return BEE_CODE_INTERPRETER_BUCKET_FILE_STORAGE; + } + + createSnapshot(): unknown { + return { files: this.files, run: this.run }; + } + loadSnapshot(snapshot: ReturnType): void { + Object.assign(this, snapshot); + } + + async list(): Promise { + return this.files.map((file) => ({ + id: file.id, + pythonId: file.contentHash, + filename: file.filename + })); + } + async upload(files: PythonUploadFile[]): Promise { + const uloadedFiles = await Promise.all( + files.map(async (file) => { + const dbFile = this.files.find((dbFile) => dbFile.id === file.id); + if (!dbFile) throw new Error('Missing file'); + await s3Client + .copyObject({ + CopySource: `/${S3_BUCKET_FILE_STORAGE}/${dbFile.storageId}`, + Bucket: this.codeInterpreterBucket, + Key: dbFile.contentHash + }) + .promise(); + + return dbFile; + }) + ); + + return uloadedFiles.map((file) => ({ + id: file.id, + pythonId: file.contentHash, + filename: file.filename + })); + } + async download(files: PythonDownloadFile[]): Promise { + const run = this.run; + if (!run) { + throw new Error(`Missing run.`); + } + const newFiles = await Promise.all( + files.map(async (file) => { + const storageId = randomUUID(); + await s3Client + .copyObject({ + CopySource: `/${this.codeInterpreterBucket}/${file.pythonId}`, + Bucket: S3_BUCKET_FILE_STORAGE, + Key: storageId + }) + .promise(); + return { file, storageId }; + }) + ); + return await ensureFiles(run, newFiles); + } +} + +export class FileSystemStorage extends PythonStorage { + constructor( + public readonly files: Loaded[], + public readonly run: LoadedRun | null + ) { + super(); + } + + get codeInterpreterDir() { + if (!BEE_CODE_INTERPRETER_FILE_STORAGE_PATH) throw new Error('Missing directory'); + return BEE_CODE_INTERPRETER_FILE_STORAGE_PATH; + } + + createSnapshot(): unknown { + return { files: this.files, run: this.run }; + } + + loadSnapshot(snapshot: ReturnType): void { + Object.assign(this, snapshot); + } + + async list(): Promise { + return this.files.map((file) => ({ + id: file.id, + pythonId: file.contentHash, + filename: file.filename + })); + } + + async upload(files: PythonUploadFile[]): Promise { + return await Promise.all( + files.map(async (file) => { + const dbFile = this.files.find((dbFile) => dbFile.id === file.id); + if (!dbFile) throw new Error('Missing file'); + const getObjectRequest = { Bucket: S3_BUCKET_FILE_STORAGE, Key: dbFile.storageId }; + const readStream = s3Client.getObject(getObjectRequest).createReadStream(); + const writeStream = fs.createWriteStream( + path.join(this.codeInterpreterDir, dbFile.contentHash) + ); + await pipeline(readStream, writeStream); + return { id: dbFile.id, pythonId: dbFile.contentHash, filename: dbFile.filename }; + }) + ); + } + + async download(files: PythonDownloadFile[]): Promise { + const run = this.run; + if (!run) { + throw new Error(`Missing run.`); + } + const newFiles = await Promise.all( + files.map(async (file) => { + const storageId = randomUUID(); + const readStream = fs.createReadStream(path.join(this.codeInterpreterDir, file.pythonId)); + await s3Client + .upload({ + Body: readStream, + Bucket: S3_BUCKET_FILE_STORAGE, + Key: storageId + }) + .promise(); + return { file, storageId }; + }) + ); + return await ensureFiles(run, newFiles); + } +} + +export function createPythonStorage( + files: Loaded[], + run: LoadedRun | null, + backend = BEE_CODE_INTERPRETER_STORAGE_BACKEND +) { + switch (backend) { + case CodeInterpreterStorageBackend.S3: + return new S3Storage(files, run); + case CodeInterpreterStorageBackend.FILESYSTEM: + return new FileSystemStorage(files, run); + } +} diff --git a/src/runs/execution/tools/read-file-tool.ts b/src/runs/execution/tools/read-file-tool.ts new file mode 100644 index 0000000..a1dcd28 --- /dev/null +++ b/src/runs/execution/tools/read-file-tool.ts @@ -0,0 +1,80 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + BaseToolOptions, + ToolInput, + StringToolOutput, + Tool, + ToolError +} from 'bee-agent-framework/tools/base'; +import { ZodLiteral, z } from 'zod'; + +import { getExtractedFileObject } from '@/files/files.service.js'; +import { File } from '@/files/entities/file.entity.js'; + +export interface ReadFileToolOptions extends BaseToolOptions { + fileSize: number; + files: File[]; +} + +export class ReadFileTool extends Tool { + name = `ReadFile`; + description = 'Retrieve file content.'; + inputSchema() { + return z.object({ + id: + this.options.files.length === 1 + ? z + .literal(this.options.files[0].id) + .describe(`Id of the file with name ${this.options.files[0].filename}`) + : z + .union( + this.options.files.map((file) => + z.literal(file.id).describe(`Id of the file with name ${file.filename}`) + ) as [ZodLiteral, ZodLiteral, ...ZodLiteral[]] + ) + .describe('File id.') + }); + } + + protected async _run({ id }: ToolInput): Promise { + const file = this.options.files.find((file) => file.id === id); + if (!file) { + throw new ToolError(`File ${id} not found.`); + } + try { + const fileObject = await getExtractedFileObject(file); + if ((fileObject.ContentLength ?? 0) > this.options.fileSize) { + throw new ToolError( + `The file is too big (${fileObject.ContentLength} bytes). Maximum allowed size is ${this.options.fileSize} bytes`, + [], + { + isFatal: false, + isRetryable: true + } + ); + } + + return new StringToolOutput('file content: \n' + fileObject.Body?.toString()); + } catch { + throw new ToolError('This file is not a text file and can not be read.', [], { + isFatal: false, + isRetryable: true + }); + } + } +} diff --git a/src/runs/execution/tools/search-tool.ts b/src/runs/execution/tools/search-tool.ts new file mode 100644 index 0000000..b9d4eed --- /dev/null +++ b/src/runs/execution/tools/search-tool.ts @@ -0,0 +1,39 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { GoogleSearchTool } from 'bee-agent-framework/tools/search/googleSearch'; +import { DuckDuckGoSearchTool } from 'bee-agent-framework/tools/search/duckDuckGoSearch'; +import { SearchToolOptions } from 'bee-agent-framework/tools/search/base'; + +import { SearchToolBackend } from '@/runs/execution/constants'; +import { BEE_GOOGLE_SEARCH_API_KEY, BEE_GOOGLE_SEARCH_CSE_ID, SEARCH_TOOL_BACKEND } from '@/config'; + +export function createSearchTool(options?: SearchToolOptions, backend = SEARCH_TOOL_BACKEND) { + switch (backend) { + case SearchToolBackend.GOOGLE: + if (!BEE_GOOGLE_SEARCH_API_KEY || !BEE_GOOGLE_SEARCH_CSE_ID) { + throw new Error('Google Search API key or CSE ID not provided'); + } + return new GoogleSearchTool({ + apiKey: BEE_GOOGLE_SEARCH_API_KEY, + cseId: BEE_GOOGLE_SEARCH_CSE_ID, + maxResultsPerPage: 10, + ...options + }); + case SearchToolBackend.DUCK_DUCK_GO: + return new DuckDuckGoSearchTool({ maxResultsPerPage: 10, ...options }); + } +} diff --git a/src/runs/execution/tools/wikipedia-similarity-search-tool.ts b/src/runs/execution/tools/wikipedia-similarity-search-tool.ts new file mode 100644 index 0000000..440b103 --- /dev/null +++ b/src/runs/execution/tools/wikipedia-similarity-search-tool.ts @@ -0,0 +1,106 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { z } from 'zod'; +import { Tool, ToolInput } from 'bee-agent-framework/tools/base'; +import { WikipediaTool } from 'bee-agent-framework/tools/search/wikipedia'; +import { + SimilarityTool, + SimilarityToolOptions, + SimilarityToolOutput +} from 'bee-agent-framework/tools/similarity'; +import { splitString } from 'bee-agent-framework/internals/helpers/string'; + +import { createEmbeddingAdapter } from '@/embedding/factory'; + +const MAX_CONTENT_LENGTH_CHARS = 25_000; + +// Estimate from OpenAI: https://help.openai.com/en/articles/4936856-what-are-tokens-and-how-to-count-them +const CHARS_PER_TOKEN_AVG = 4; + +export class WikipediaSimilaritySearchTool extends Tool { + name: WikipediaTool['name']; + description: WikipediaTool['description']; + + wikipediaTool: WikipediaTool; + similarityTool: SimilarityTool; + + inputSchema() { + return z.object({ + page: this.wikipediaTool.inputSchema().shape.query, + question: z.string({ + description: `The question you are trying to answer using the page, for example 'What is the population of New York?'` + }) + }); + } + + async similarityProvider({ + query, + documents + }: Parameters[0]): ReturnType< + SimilarityToolOptions['provider'] + > { + const embeddingAdapter = await createEmbeddingAdapter(); + const scores = await embeddingAdapter.similarity( + { + query, + texts: documents.map((document) => document.text) + }, + { signal: AbortSignal.timeout(60_000) } + ); + return scores; + } + + public constructor() { + super(); + + this.wikipediaTool = new WikipediaTool({ + search: { limit: 3 }, + filters: { minPageNameSimilarity: 0.25, excludeOthersOnExactMatch: false }, + extraction: { fields: { markdown: {} } }, + output: { maxSerializedLength: MAX_CONTENT_LENGTH_CHARS } + }); + this.similarityTool = new SimilarityTool({ provider: this.similarityProvider, maxResults: 5 }); + + this.name = this.wikipediaTool.name; + this.description = this.wikipediaTool.description; + } + + protected async _run({ page, question }: ToolInput) { + const wikipediaResult = await this.wikipediaTool.run({ query: page }); + + const documents = wikipediaResult.results + .map(({ fields: { markdown }, ...rest }) => { + const text = markdown as string; + return { + text: + text.length > MAX_CONTENT_LENGTH_CHARS ? text.slice(0, MAX_CONTENT_LENGTH_CHARS) : text, + ...rest + }; + }) + .flatMap((document, idx) => + [...splitString(document.text, { size: 400 * CHARS_PER_TOKEN_AVG, overlap: 100 })].map( + (text) => ({ + searchResultIndex: idx, + ...document, + text + }) + ) + ); + + return await this.similarityTool.run({ query: question, documents }); + } +} diff --git a/src/runs/execution/types.ts b/src/runs/execution/types.ts new file mode 100644 index 0000000..e756204 --- /dev/null +++ b/src/runs/execution/types.ts @@ -0,0 +1,31 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Loaded } from '@mikro-orm/core'; + +import { Run } from '@/runs/entities/run.entity.js'; + +export type LoadedRun = Loaded< + Run, + | 'thread.*' + | 'assistant.*' + | 'tools.tool' + | 'thread.messages.attachments.file' + | 'thread.toolResources.fileContainers.file' + | 'thread.toolResources.vectorStoreContainers.vectorStore.files' + | 'assistant.toolResources.fileContainers.file' + | 'assistant.toolResources.vectorStoreContainers.vectorStore.files' +>; diff --git a/src/runs/jobs/runs-cleanup.queue.ts b/src/runs/jobs/runs-cleanup.queue.ts new file mode 100644 index 0000000..9c4c54a --- /dev/null +++ b/src/runs/jobs/runs-cleanup.queue.ts @@ -0,0 +1,41 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { RequestContext } from '@mikro-orm/core'; + +import { Run, RunStatus } from '../entities/run.entity.js'; + +import { ORM } from '@/database.js'; +import { createQueue } from '@/jobs/bullmq.js'; +import { QueueName } from '@/jobs/constants.js'; + +async function jobHandler() { + return RequestContext.create(ORM.em, async () => { + await ORM.em.getRepository(Run).nativeUpdate( + { + expiresAt: { $lt: new Date() } + }, + { status: RunStatus.EXPIRED } + ); + }); +} + +export const { queue, worker } = createQueue({ + name: QueueName.RUNS_CLEANUP, + jobHandler, + jobsOptions: { attempts: 1 }, + workerOptions: { concurrency: 1 } +}); diff --git a/src/runs/jobs/runs.queue.ts b/src/runs/jobs/runs.queue.ts new file mode 100644 index 0000000..578a2c2 --- /dev/null +++ b/src/runs/jobs/runs.queue.ts @@ -0,0 +1,98 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { DelayedError, Job } from 'bullmq'; +import { RequestContext } from '@mikro-orm/core'; + +import { Run, RunStatus } from '../entities/run.entity.js'; +import { executeRun } from '../execution/execute.js'; +import { getAllReadableRunFiles } from '../execution/tools/helpers.js'; +import { toRunDto } from '../runs.service.js'; + +import { ORM } from '@/database.js'; +import { createQueue } from '@/jobs/bullmq.js'; +import { QueueName } from '@/jobs/constants.js'; +import { LoadedRun } from '@/runs/execution/types.js'; +import { waitForExtraction } from '@/files/utils/wait-for-extraction.js'; +import { createPublisher } from '@/streaming/pubsub.js'; +import { APIError, APIErrorCode } from '@/errors/error.entity.js'; + +const MAX_ACTIVE_RUNS_PER_USER = 5; + +async function jobHandler(job: Job<{ runId: string }>) { + return RequestContext.create(ORM.em, async () => { + const run = (await ORM.em.getRepository(Run).findOneOrFail( + { id: job.data.runId }, + { + populate: [ + 'thread.*', + 'assistant.*', + 'tools.tool', + 'thread.messages.attachments.file', + 'thread.toolResources.fileContainers.file', + 'thread.toolResources.vectorStoreContainers.vectorStore.files', + 'assistant.toolResources.fileContainers.file', + 'assistant.toolResources.vectorStoreContainers.vectorStore.files' + ] as any[], + filters: { deleted: false } + } + )) as LoadedRun; + + if (run.status === RunStatus.EXPIRED) return; + + const count = await ORM.em.getRepository(Run).count( + { + createdBy: run.createdBy, + status: { + $in: [RunStatus.IN_PROGRESS, RunStatus.REQUIRES_ACTION] + } + }, + { filters: { deleted: false } } + ); + if (count >= MAX_ACTIVE_RUNS_PER_USER) { + await job.moveToDelayed(Date.now() + 3000, job.token); + throw new DelayedError(); + } + + // wait for text extraction + const allFiles = await getAllReadableRunFiles(run); + await waitForExtraction(job, allFiles); + + try { + await executeRun(run); + } catch (err) { + // Safeguard for programmatic errors and not implemented code paths + // Fails the run early, othewise user would wait for expiration + run.fail( + new APIError({ message: 'Internal server error', code: APIErrorCode.INTERNAL_SERVER_ERROR }) + ); + await ORM.em.flush(); + const publish = createPublisher(run); + await publish({ event: 'thread.run.failed', data: toRunDto(run) }); + await publish({ event: 'done', data: '[DONE]' }); + throw err; + } + }); +} + +export const { queue, worker } = createQueue({ + name: QueueName.RUNS, + jobHandler, + jobsOptions: { attempts: 1 }, + workerOptions: { + concurrency: 100 + } +}); diff --git a/src/runs/runs.module.ts b/src/runs/runs.module.ts new file mode 100644 index 0000000..0cfd6c2 --- /dev/null +++ b/src/runs/runs.module.ts @@ -0,0 +1,265 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FastifyPluginAsyncJsonSchemaToTs } from '@fastify/type-provider-json-schema-to-ts'; +import { StatusCodes } from 'http-status-codes'; + +import { + RunCreateBody, + RunCreateParams, + runCreateBodySchema, + runCreateParamsSchema, + runCreateResponseSchema, + runCreateStreamSchema +} from './dtos/run-create.js'; +import { + cancelRun, + createRun, + createThreadRun, + listRuns, + readRun, + readRunTrace, + submitToolApproval, + submitToolOutput, + updateRun +} from './runs.service.js'; +import { RunReadParams, runReadParamsSchema, runReadResponseSchema } from './dtos/run-read.js'; +import { + RunsListParams, + RunsListQuery, + runsListParamsSchema, + runsListQuerySchema, + runsListResponseSchema +} from './dtos/runs-list.js'; +import { + RunCancelParams, + runCancelParamsSchema, + runCancelResponseSchema +} from './dtos/run-cancel.js'; +import { + ThreadRunCreateBody, + threadRunCreateBodySchema, + threadRunCreateResponseSchema, + threadRunCreateStreamSchema +} from './dtos/thread-run-create.js'; +import { traceReadParamsSchema, traceReadResponseSchema } from './dtos/trace-read.js'; +import { + RunSubmitToolOutputsBody, + RunSubmitToolOutputsParams, + runSubmitToolOutputsBodySchema, + runSubmitToolOutputsParamsSchema, + runSubmitToolOutputsResponseSchema, + runSubmitToolOutputsStreamSchema +} from './dtos/run-submit-tool-outputs.js'; +import { + RunUpdateBody, + runUpdateBodySchema, + RunUpdateParams, + runUpdateParamsSchema, + runUpdateResponseSchema +} from './dtos/run-update.js'; +import { + RunSubmitToolApprovalsBody, + runSubmitToolApprovalsBodySchema, + RunSubmitToolApprovalsParams, + runSubmitToolApprovalsParamsSchema, + runSubmitToolApprovalsResponseSchema, + runSubmitToolApprovalsStreamSchema +} from './dtos/run-submit-tool-approvals.js'; + +import { Tag } from '@/swagger.js'; + +export const runsModule: FastifyPluginAsyncJsonSchemaToTs = async (app) => { + app.post<{ Params: RunCreateParams; Body: RunCreateBody }>( + '/threads/:thread_id/runs', + { + schema: { + params: runCreateParamsSchema, + body: runCreateBodySchema, + response: { + [StatusCodes.OK]: { + content: { + 'application/json': { schema: runCreateResponseSchema }, + 'text/event-stream': { schema: runCreateStreamSchema } + } + } + }, + tags: [Tag.OPENAI_ASSISTANTS_API] + }, + preHandler: app.auth(), + config: { + rateLimit: { + max: 26 // global rate limit +1 for the UI + } + } + }, + async (req) => createRun({ ...req.params, ...req.body }) + ); + + app.post<{ Body: ThreadRunCreateBody }>( + '/threads/runs', + { + schema: { + body: threadRunCreateBodySchema, + response: { + [StatusCodes.OK]: { + content: { + 'application/json': { schema: threadRunCreateResponseSchema }, + 'text/event-stream': { schema: threadRunCreateStreamSchema } + } + } + }, + tags: [Tag.OPENAI_ASSISTANTS_API] + }, + preHandler: app.auth(), + config: { + rateLimit: { + max: 26 // global rate limit +1 for the UI + } + } + }, + async (req) => createThreadRun(req.body) + ); + + app.get<{ Params: RunReadParams }>( + '/threads/:thread_id/runs/:run_id', + { + schema: { + params: runReadParamsSchema, + response: { [StatusCodes.OK]: runReadResponseSchema }, + tags: [Tag.OPENAI_ASSISTANTS_API] + }, + preHandler: app.auth() + }, + async (req) => { + return readRun(req.params); + } + ); + + app.post<{ Params: RunUpdateParams; Body: RunUpdateBody }>( + '/threads/:thread_id/runs/:run_id', + { + schema: { + params: runUpdateParamsSchema, + body: runUpdateBodySchema, + response: { [StatusCodes.OK]: runUpdateResponseSchema }, + tags: [Tag.OPENAI_ASSISTANTS_API] + }, + preHandler: app.auth() + }, + async (req) => { + return updateRun({ ...req.params, ...req.body }); + } + ); + + app.get<{ Params: RunReadParams }>( + '/threads/:thread_id/runs/:run_id/trace', + { + schema: { + params: traceReadParamsSchema, + response: { [StatusCodes.OK]: traceReadResponseSchema }, + tags: [Tag.BEE_API] + }, + preHandler: app.auth() + }, + async (req) => { + return readRunTrace(req.params); + } + ); + + app.get<{ Params: RunsListParams; Querystring: RunsListQuery }>( + '/threads/:thread_id/runs', + { + schema: { + params: runsListParamsSchema, + querystring: runsListQuerySchema, + response: { [StatusCodes.OK]: runsListResponseSchema }, + tags: [Tag.OPENAI_ASSISTANTS_API] + }, + preHandler: app.auth() + }, + async (req) => { + return listRuns({ ...req.params, ...req.query }); + } + ); + + app.post<{ Params: RunCancelParams }>( + '/threads/:thread_id/runs/:run_id/cancel', + { + schema: { + params: runCancelParamsSchema, + response: { [StatusCodes.OK]: runCancelResponseSchema }, + tags: [Tag.OPENAI_ASSISTANTS_API] + }, + preHandler: app.auth() + }, + async (req) => { + return cancelRun(req.params); + } + ); + + app.post<{ Params: RunSubmitToolOutputsParams; Body: RunSubmitToolOutputsBody }>( + '/threads/:thread_id/runs/:run_id/submit_tool_outputs', + { + schema: { + params: runSubmitToolOutputsParamsSchema, + body: runSubmitToolOutputsBodySchema, + response: { + [StatusCodes.OK]: { + content: { + 'application/json': { schema: runSubmitToolOutputsResponseSchema }, + 'text/event-stream': { schema: runSubmitToolOutputsStreamSchema } + } + } + }, + tags: [Tag.OPENAI_ASSISTANTS_API] + }, + preHandler: app.auth(), + config: { + rateLimit: { + max: 26 // global rate limit +1 for the UI + } + } + }, + async (req) => submitToolOutput({ ...req.params, ...req.body }) + ); + + app.post<{ Params: RunSubmitToolApprovalsParams; Body: RunSubmitToolApprovalsBody }>( + '/threads/:thread_id/runs/:run_id/submit_tool_approvals', + { + schema: { + params: runSubmitToolApprovalsParamsSchema, + body: runSubmitToolApprovalsBodySchema, + response: { + [StatusCodes.OK]: { + content: { + 'application/json': { schema: runSubmitToolApprovalsResponseSchema }, + 'text/event-stream': { schema: runSubmitToolApprovalsStreamSchema } + } + } + }, + tags: [Tag.OPENAI_ASSISTANTS_API] + }, + preHandler: app.auth(), + config: { + rateLimit: { + max: 26 // global rate limit +1 for the UI + } + } + }, + async (req) => submitToolApproval({ ...req.params, ...req.body }) + ); +}; diff --git a/src/runs/runs.service.ts b/src/runs/runs.service.ts new file mode 100644 index 0000000..b3c4773 --- /dev/null +++ b/src/runs/runs.service.ts @@ -0,0 +1,500 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FilterQuery, Loaded, QueryOrder, ref } from '@mikro-orm/core'; +import dayjs from 'dayjs'; + +import { RunCreateBody, RunCreateParams, RunCreateResponse } from './dtos/run-create.js'; +import { Run, RunStatus } from './entities/run.entity.js'; +import type { Run as RunDto } from './dtos/run.js'; +import { RunReadParams, RunReadResponse } from './dtos/run-read.js'; +import { RunsListParams, RunsListQuery, RunsListResponse } from './dtos/runs-list.js'; +import { RunCancelParams, RunCancelResponse } from './dtos/run-cancel.js'; +import { queue } from './jobs/runs.queue.js'; +import { ThreadRunCreateBody, ThreadRunCreateResponse } from './dtos/thread-run-create.js'; +import { TraceReadResponse } from './dtos/trace-read.js'; +import { + RunSubmitToolOutputsBody, + RunSubmitToolOutputsParams, + RunSubmitToolOutputsResponse +} from './dtos/run-submit-tool-outputs.js'; +import { FunctionTool } from './execution/tools/function.js'; +import { RunUpdateBody, RunUpdateParams, RunUpdateResponse } from './dtos/run-update.js'; +import { + RunSubmitToolApprovalsBody, + RunSubmitToolApprovalsParams, + RunSubmitToolApprovalsResponse +} from './dtos/run-submit-tool-approvals.js'; +import { RequiredToolOutput } from './entities/requiredToolOutput.entity.js'; +import { RequiredToolApprove } from './entities/requiredToolApprove.entity.js'; +import { ToolApproval, ToolApprovalType } from './entities/toolApproval.entity.js'; +import { RequiredActionType } from './entities/requiredAction.entity.js'; + +import { ORM } from '@/database.js'; +import { Thread } from '@/threads/thread.entity.js'; +import { Assistant } from '@/assistants/assistant.entity.js'; +import { getServiceLogger } from '@/logger.js'; +import { createThread } from '@/threads/threads.service.js'; +import { createPaginatedResponse, getListCursor } from '@/utils/pagination.js'; +import { createPublisher, subscribeAndForward } from '@/streaming/pubsub.js'; +import { listenToSocketClose } from '@/utils/networking.js'; +import { APIError, APIErrorCode } from '@/errors/error.entity.js'; +import { toErrorDto } from '@/errors/plugin.js'; +import { createToolUsage, toToolCallDto, toToolUsageDto } from '@/tools/tools.service.js'; +import { Tool, ToolType } from '@/tools/entities/tool/tool.entity.js'; +import type { Trace as TraceDto } from '@/observe/dtos/trace.js'; +import { Trace } from '@/observe/entities/trace.entity.js'; +import { QueueName } from '@/jobs/constants.js'; +import { getRunVectorStores } from '@/runs/execution/helpers.js'; +import { getUpdatedValue } from '@/utils/update.js'; +import { RunStep } from '@/run-steps/entities/run-step.entity.js'; +import { RunStepDetailsType } from '@/run-steps/entities/details/run-step-details.entity.js'; +import { createClient } from '@/redis.js'; +import { ToolCall } from '@/tools/entities/tool-calls/tool-call.entity.js'; +import { SystemTools } from '@/tools/entities/tool-calls/system-call.entity.js'; +import { ensureRequestContextData } from '@/context.js'; + +const getRunsLogger = (runId?: string) => getServiceLogger('runs').child({ runId }); + +type RunStepWithEvent = Omit & { event: Required['event'] }; + +export function toRunDto(run: Loaded): RunDto { + return { + id: run.id, + object: 'thread.run', + thread_id: run.thread.id, + assistant_id: run.assistant.id, + status: run.status, + last_error: run.lastError ? toErrorDto(run.lastError) : null, + required_action: + run.requiredAction instanceof RequiredToolOutput + ? { + type: 'submit_tool_outputs', + submit_tool_outputs: { tool_calls: run.requiredAction.toolCalls.map(toToolCallDto) } + } + : run.requiredAction instanceof RequiredToolApprove + ? { + type: 'submit_tool_approvals', + submit_tool_approvals: { tool_calls: run.requiredAction.toolCalls.map(toToolCallDto) } + } + : null, + tools: run.tools.map(toToolUsageDto) ?? [], + instructions: run.instructions ?? null, + additional_instructions: run.additionalInstructions ?? null, + metadata: run.metadata ?? {}, + created_at: dayjs(run.createdAt).unix(), + started_at: run.startedAt ? dayjs(run.startedAt).unix() : null, + expires_at: dayjs(run.expiresAt).unix(), + cancelled_at: run.cancelledAt ? dayjs(run.cancelledAt).unix() : null, + completed_at: run.completedAt ? dayjs(run.completedAt).unix() : null, + failed_at: run.failedAt ? dayjs(run.failedAt).unix() : null, + model: run.model, + top_p: run.topP, + temperature: run.temperature + }; +} + +function toTraceDto(trace: Trace, { runSteps }: { runSteps: RunStepWithEvent[] }): TraceDto { + return { + id: trace.id, + iterations: runSteps.map((step) => ({ + id: step.id, + event: { + group_id: step.event.groupId + } + })) + }; +} + +export async function createRun({ + thread_id, + assistant_id, + tools: toolsParam, + stream, + instructions, + additional_instructions: additionalInstructions, + metadata, + model, + top_p, + temperature, + tool_approvals +}: RunCreateParams & RunCreateBody): Promise { + const thread = await ORM.em.getRepository(Thread).findOneOrFail( + { id: thread_id }, + // Incorrect MikroORM typing for embedded entities + { populate: ['toolResources.vectorStoreContainers.vectorStore'] as any[] } + ); + const assistant = await ORM.em.getRepository(Assistant).findOneOrFail( + { + id: assistant_id + }, + // Incorrect MikroORM typing for embedded entities + { populate: ['toolResources.vectorStoreContainers.vectorStore'] as any[] } + ); + const customToolIds = + toolsParam?.flatMap((toolUsage) => + toolUsage.type === ToolType.USER ? toolUsage.user.tool.id : [] + ) ?? []; + const tools = + customToolIds.length > 0 + ? await ORM.em.getRepository(Tool).find({ + id: { $in: customToolIds } + }) + : []; + + if (tools.length !== customToolIds.length) { + throw new APIError({ + message: 'Some tool not found', + code: APIErrorCode.INVALID_INPUT + }); + } + if (tool_approvals?.length) { + const databaseTools = Object.keys(tool_approvals).filter( + (id) => + ![ + ToolType.CODE_INTERPRETER, + ToolType.FILE_SEARCH, + ToolType.FUNCTION, + ...(Object.values(SystemTools) as string[]) + ].includes(id) + ); + const tools = await ORM.em.getRepository(Tool).find({ + id: { + $in: databaseTools + } + }); + + if (tools.length !== databaseTools.length) { + throw new APIError({ + message: 'Some tool in tool_approvals not found', + code: APIErrorCode.INVALID_INPUT + }); + } + } + + const run = new Run({ + thread: ref(thread), + assistant: ref(assistant), + tools: toolsParam?.map(createToolUsage) ?? assistant.tools, + instructions: instructions ?? assistant.instructions, + additionalInstructions: additionalInstructions ?? undefined, + metadata, + model: model ?? assistant.model, + topP: top_p ?? assistant.topP, + temperature: temperature ?? assistant.temperature, + toolApprovals: tool_approvals + ? Object.entries(tool_approvals).map( + ([tool, approval]) => + new ToolApproval({ + toolId: tool, + requireApproval: approval.require as ToolApprovalType + }) + ) + : undefined + }); + ORM.em.persist(run); + + for (const vectorStore of getRunVectorStores(assistant, thread)) { + if (vectorStore.expired) throw Error('The attached vector-store is expired.'); + } + + await ORM.em.flush(); + + const queueAndPublish = async () => { + const publish = createPublisher(run); + try { + await publish({ event: 'thread.run.created', data: toRunDto(run) }); + await queue.add(QueueName.RUNS, { runId: run.id }, { jobId: run.id }); + await publish({ event: 'thread.run.queued', data: toRunDto(run) }); + } catch (err) { + getRunsLogger(run.id).error({ err }, 'Failed to create run job'); + run.fail( + new APIError({ + message: 'Failed to create run job', + code: APIErrorCode.INTERNAL_SERVER_ERROR + }) + ); + await ORM.em.flush(); + await publish({ event: 'thread.run.failed', data: toRunDto(run) }); + await publish({ event: 'done', data: '[DONE]' }); + } + }; + + if (stream) { + const req = ensureRequestContextData('req'); + const res = ensureRequestContextData('res'); + const controller = new AbortController(); + const unsub = listenToSocketClose(req.socket, () => controller.abort()); + try { + await subscribeAndForward(run, res, { + signal: controller.signal, + onReady: queueAndPublish, + onFailed: queueAndPublish + }); + } finally { + unsub(); + } + } else { + await queueAndPublish(); + return toRunDto(run); + } +} + +export async function createThreadRun({ + thread, + ...rest +}: ThreadRunCreateBody): Promise { + const newThread = await createThread(thread ?? {}); + try { + return await createRun({ thread_id: newThread.id, ...rest }); + } catch (err) { + try { + await ORM.em.removeAndFlush(ORM.em.getRepository(Thread).getReference(newThread.id)); + } catch (err) { + getRunsLogger().warn({ err }, 'Thread cleanup failed'); + } + throw err; + } +} + +export async function readRun({ thread_id, run_id }: RunReadParams): Promise { + const run = await ORM.em.getRepository(Run).findOneOrFail({ + id: run_id, + thread: thread_id + }); + return toRunDto(run); +} + +export async function updateRun({ + thread_id, + run_id, + metadata +}: RunUpdateParams & RunUpdateBody): Promise { + const run = await ORM.em.getRepository(Run).findOneOrFail({ + id: run_id, + thread: thread_id + }); + run.metadata = getUpdatedValue(metadata, run.metadata); + await ORM.em.flush(); + return toRunDto(run); +} + +export async function readRunTrace({ + thread_id, + run_id +}: RunReadParams): Promise { + const run = await ORM.em.getRepository(Run).findOneOrFail({ + id: run_id, + thread: thread_id + }); + + if (!run.trace) { + throw new APIError({ + message: `The trace does not exist`, + code: APIErrorCode.NOT_FOUND + }); + } + + const runSteps = await ORM.em.getRepository(RunStep).find( + { + run: run_id, + // I cast to any because of ts problem with $in[....] + details: { + type: { $in: [RunStepDetailsType.MESSAGE_CREATION, RunStepDetailsType.TOOL_CALLS] as any[] } + }, + event: { $ne: null } + }, + { + orderBy: { createdAt: QueryOrder.ASC }, + limit: 100 // safe check: we will not load a large amount of steps + } + ); + + // double check that each step has event + const runStepsWithEvent = runSteps.filter( + (step: RunStep): step is RunStepWithEvent => !!step.event + ); + + return toTraceDto(run.trace, { runSteps: runStepsWithEvent }); +} + +export async function listRuns({ + thread_id, + limit, + after, + before, + order, + order_by, + ...rest +}: RunsListParams & RunsListQuery): Promise { + const where: FilterQuery = { thread: thread_id }; + const ids = rest['ids[]']; + if (ids) { + where.id = { $in: ids }; + } + const repo = ORM.em.getRepository(Run); + const cursor = await getListCursor(where, { limit, order, order_by, after, before }, repo); + return createPaginatedResponse(cursor, toRunDto); +} + +export async function cancelRun({ + thread_id, + run_id +}: RunCancelParams): Promise { + const run = await ORM.em.getRepository(Run).findOneOrFail({ + id: run_id, + thread: thread_id + }); + if (run.status !== RunStatus.IN_PROGRESS && run.status !== RunStatus.REQUIRES_ACTION) + throw new APIError({ + message: 'Only progressing or waiting runs can be cancelled', + code: APIErrorCode.INVALID_INPUT + }); + + run.startCancel(); + await ORM.em.flush(); + await createPublisher(run)({ event: 'thread.run.cancelling', data: toRunDto(run) }); + return toRunDto(run); +} + +export async function submitToolOutput({ + thread_id, + run_id, + tool_outputs, + stream +}: RunSubmitToolOutputsParams & + RunSubmitToolOutputsBody): Promise { + const run = await ORM.em.getRepository(Run).findOneOrFail({ id: run_id, thread: thread_id }); + + if ( + run.status !== RunStatus.REQUIRES_ACTION || + !run.requiredAction || + run.requiredAction?.type !== RequiredActionType.OUTPUT + ) + throw new APIError({ + message: 'No tool output is required for the run', + code: APIErrorCode.INVALID_INPUT + }); + + const suppliedToolCalls = tool_outputs.map(({ tool_call_id, output }) => { + const toolCall = run.requiredAction?.toolCalls.find(({ id }) => id === tool_call_id); + if (!toolCall) + throw new APIError({ + message: `Unexpected tool call ${tool_call_id}`, + code: APIErrorCode.INVALID_INPUT + }); + return { toolCall, output }; + }); + if (suppliedToolCalls.length < run.requiredAction.toolCalls.length) + throw new APIError({ + message: 'Missing tool calls', + code: APIErrorCode.INVALID_INPUT + }); + + const submit = async () => { + await Promise.all( + suppliedToolCalls.map(({ toolCall, output }) => { + switch (toolCall.type) { + case ToolType.FUNCTION: + return FunctionTool.submit(output, { run, toolCallId: toolCall.id }); + default: + throw new Error('Unexpected tool call type'); + } + }) + ); + }; + + return continueRun({ stream, run, submit }); +} + +export function createApproveChannel(run: Run, toolCall: ToolCall) { + return `run:${run.id}:call:${toolCall.id}:approve`; +} + +export async function submitToolApproval({ + thread_id, + run_id, + tool_approvals, + stream +}: RunSubmitToolApprovalsParams & + RunSubmitToolApprovalsBody): Promise { + const run = await ORM.em.getRepository(Run).findOneOrFail({ id: run_id, thread: thread_id }); + + if ( + run.status !== RunStatus.REQUIRES_ACTION || + !run.requiredAction || + run.requiredAction?.type !== RequiredActionType.APPROVE + ) + throw new APIError({ + message: 'No approval is required for the run', + code: APIErrorCode.INVALID_INPUT + }); + + const suppliedToolCalls = tool_approvals.map(({ tool_call_id, approve }) => { + const toolCall = run.requiredAction?.toolCalls.find(({ id }) => id === tool_call_id); + if (!toolCall) + throw new APIError({ + message: `Unexpected tool call ${tool_call_id}`, + code: APIErrorCode.INVALID_INPUT + }); + return { toolCall, approve }; + }); + if (suppliedToolCalls.length < run.requiredAction.toolCalls.length) + throw new APIError({ + message: 'Missing tool calls', + code: APIErrorCode.INVALID_INPUT + }); + + const redisClient = createClient(); + const submit = async () => { + await Promise.all( + suppliedToolCalls.map(({ toolCall, approve }) => { + redisClient.publish(createApproveChannel(run, toolCall), approve.toString()); + }) + ); + }; + + return continueRun({ stream, run, submit }); +} + +async function continueRun({ + stream, + run, + submit +}: { + stream: boolean | null | undefined; + run: Run; + submit: () => Promise; +}) { + if (stream) { + const req = ensureRequestContextData('req'); + const res = ensureRequestContextData('res'); + const controller = new AbortController(); + const unsub = listenToSocketClose(req.socket, () => controller.abort()); + try { + await subscribeAndForward(run, res, { + signal: controller.signal, + onReady: submit, + onFailed: submit + }); + } finally { + unsub(); + } + } else { + await submit(); + return toRunDto(run); + } +} diff --git a/src/schema.ts b/src/schema.ts new file mode 100644 index 0000000..2a2e54d --- /dev/null +++ b/src/schema.ts @@ -0,0 +1,80 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { JSONSchema } from 'json-schema-to-ts'; + +export const metadataSchema = { + type: 'object', + maxProperties: 16, + propertyNames: { + pattern: '^.{1,64}$' + }, + patternProperties: { + '.*': { type: 'string', maxLength: 512 } + }, + additionalProperties: true +} as const satisfies JSONSchema; + +export const createPaginationQuerySchema = ( + additionalOrderByColumns: T | never[] = [] +) => + ({ + type: 'object', + additionalProperties: false, + properties: { + limit: { + type: 'number', + minimum: 1, + maximum: 100, + default: 20 + }, + after: { type: 'string' }, + before: { type: 'string' }, + order: { type: 'string', enum: ['asc', 'desc'], default: 'desc' }, + order_by: { + type: 'string', + default: 'created_at', + enum: ['created_at', ...additionalOrderByColumns] + } + } + }) as const satisfies JSONSchema; + +export function withPagination(schema: T) { + return { + type: 'object', + required: ['data', 'first_id', 'last_id', 'has_more', 'total_count'], + properties: { + data: { type: 'array', items: schema }, + first_id: { type: 'string', nullable: true }, + last_id: { type: 'string', nullable: true }, + has_more: { type: 'boolean' }, + total_count: { type: 'number', nullable: false } + } + } as const satisfies JSONSchema; +} + +export const noContentSchema = { type: 'null' } as const satisfies JSONSchema; + +export const createDeleteSchema = (object: T) => + ({ + type: 'object', + required: ['id', 'object', 'deleted'], + properties: { + id: { type: 'string' }, + object: { const: `${object}.deleted` }, + deleted: { type: 'boolean', default: true } + } + }) as const satisfies JSONSchema; diff --git a/src/server.ts b/src/server.ts new file mode 100644 index 0000000..ae6fa3a --- /dev/null +++ b/src/server.ts @@ -0,0 +1,111 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import '@/ui/auth-server.js'; + +import { JsonSchemaToTsProvider } from '@fastify/type-provider-json-schema-to-ts'; +import { fastify } from 'fastify'; + +import { PORT, BEE_OBSERVE_API_URL, RUN_BULLMQ_WORKERS } from './config.js'; +import { databasePlugin } from './database.js'; +import { errorPlugin } from './errors/plugin.js'; +import { threadsModule } from './threads/threads.module.js'; +import { fastifyLogger, getCorrelationId, LogLabels } from './logger.js'; +import { swaggerPlugin } from './swagger.js'; +import { assistantsModule } from './assistants/assistants.module.js'; +import { authPlugin } from './auth/authentication.js'; +import { usersModule } from './users/users.module.js'; +import { messagesModule } from './messages/messages.module.js'; +import { requestContextPlugin } from './context.js'; +import { runsModule } from './runs/runs.module.js'; +import { toolsModule } from './tools/tools.module.js'; +import { runWorkers } from './jobs/bullmq.js'; +import { rateLimitPlugin } from './rate-limit.js'; +import { runStepsModule } from './run-steps/run-steps.module.js'; +import { vectorStoresModule } from './vector-stores/vector-stores.module.js'; +import { vectorStoreFilesModule } from './vector-store-files/vector-store-files.module.js'; +import { uiModule } from './ui/ui.module.js'; +import { terminusPlugin } from './terminus.js'; +import { filesModule } from './files/files.module.js'; +import { ajv } from './ajv.js'; +import { multipartPlugin } from './multipart.js'; +import { metricsPlugin } from './metrics.js'; +import { observeModule } from './observe/observe.module.js'; +import { createCronJobs } from './jobs/jobs.js'; +import { projectsModule } from './administration/projects.module.js'; +import { projectUsersModule } from './administration/project-users.module.js'; +import { organizationUsersModule } from './administration/organization-users.module.js'; + +const app = fastify({ + logger: fastifyLogger, + requestIdHeader: false, + genReqId: getCorrelationId, + requestIdLogLabel: LogLabels.CORRELATION_ID, + pluginTimeout: 60_000, + ajv +}).withTypeProvider(); + +app.setSerializerCompiler(() => (data) => JSON.stringify(data)); + +process.on('unhandledRejection', (reason, p) => { + app.log.fatal({ err: reason, promise: p }, 'Unhandled promise rejection'); + process.exit(1); +}); + +try { + // Plugins + app.register(requestContextPlugin); + app.register(terminusPlugin); + app.register(errorPlugin); + app.register(databasePlugin); + app.register(authPlugin); + app.register(swaggerPlugin); + app.register(multipartPlugin); + app.register(metricsPlugin); + await app.register(rateLimitPlugin); + + // Top-level modules + app.register(usersModule, { prefix: '/v1' }); + app.register(assistantsModule, { prefix: '/v1' }); + app.register(threadsModule, { prefix: '/v1' }); + app.register(messagesModule, { prefix: '/v1' }); + app.register(runsModule, { prefix: '/v1' }); + app.register(toolsModule, { prefix: '/v1' }); + app.register(runStepsModule, { prefix: '/v1' }); + app.register(filesModule, { prefix: '/v1' }); + app.register(vectorStoresModule, { prefix: '/v1' }); + app.register(vectorStoreFilesModule, { prefix: '/v1' }); + app.register(projectsModule, { prefix: '/v1' }); + app.register(projectUsersModule, { prefix: '/v1' }); + app.register(organizationUsersModule, { prefix: '/v1' }); + + app.register(uiModule, { prefix: '/v1' }); + + // bee observe proxy + if (BEE_OBSERVE_API_URL) { + app.register(observeModule, { prefix: '/observe' }); + } + + await createCronJobs(); + + // Bullmq workers + runWorkers(RUN_BULLMQ_WORKERS); + + await app.listen({ port: PORT, host: '0.0.0.0' }); +} catch (err) { + app.log.fatal({ err }, 'Failed to start server!'); + process.exit(1); +} diff --git a/src/streaming/dtos/event.ts b/src/streaming/dtos/event.ts new file mode 100644 index 0000000..5d99a81 --- /dev/null +++ b/src/streaming/dtos/event.ts @@ -0,0 +1,117 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { messageDeltaSchema } from '../../messages/dtos/message-delta.js'; + +import { threadSchema } from '@/threads/dtos/thread.js'; +import { runSchema } from '@/runs/dtos/run.js'; +import { messageSchema } from '@/messages/dtos/message.js'; +import { errorSchema } from '@/errors/dtos/error.js'; +import { runStepSchema } from '@/run-steps/dtos/run-step.js'; +import { runStepDeltaSchema } from '@/run-steps/dtos/run-step-delta.js'; + +export const eventSchema = { + type: 'object', + required: ['event', 'data'], + oneOf: [ + { + properties: { + event: { const: 'thread.created' }, + data: threadSchema + } + }, + { + properties: { + event: { + type: 'string', + enum: [ + 'thread.run.created', + 'thread.run.queued', + 'thread.run.in_progress', + 'thread.run.requires_action', + 'thread.run.requires_approve', + 'thread.run.completed', + 'thread.run.incomplete', + 'thread.run.failed', + 'thread.run.cancelling', + 'thread.run.cancelled', + 'thread.run.expired' + ] + }, + data: runSchema + } + }, + { + properties: { + event: { + type: 'string', + enum: [ + 'thread.run.step.created', + 'thread.run.step.in_progress', + 'thread.run.step.completed', + 'thread.run.step.failed', + 'thread.run.step.cancelled', + 'thread.run.step.expired' + ] + }, + data: runStepSchema + } + }, + { + properties: { + event: { const: 'thread.run.step.delta' }, + data: runStepDeltaSchema + } + }, + { + properties: { + event: { + type: 'string', + enum: [ + 'thread.message.created', + 'thread.message.in_progress', + 'thread.message.completed', + 'thread.message.incomplete' + ] + }, + data: messageSchema + } + }, + { + properties: { + event: { const: 'thread.message.delta' }, + data: messageDeltaSchema + } + }, + { + properties: { + event: { const: 'done' }, + data: { + const: '[DONE]' + } + } + }, + { + properties: { + event: { const: 'error' }, + data: errorSchema + } + } + ] +} as const satisfies JSONSchema; +export type Event = FromSchema; diff --git a/src/streaming/pubsub.ts b/src/streaming/pubsub.ts new file mode 100644 index 0000000..011291c --- /dev/null +++ b/src/streaming/pubsub.ts @@ -0,0 +1,82 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FastifyReply } from 'fastify'; +import { Loaded } from '@mikro-orm/core'; + +import { Event } from './dtos/event.js'; +import * as sse from './sse.js'; + +import { createClient } from '@/redis.js'; +import { Run } from '@/runs/entities/run.entity.js'; +import { getLogger } from '@/logger.js'; + +function createChannel(run: Loaded) { + return `run:${run.id}`; +} + +export function createPublisher(run: Loaded) { + const client = createClient(); + return async function publish(event: Event) { + await client.publish(createChannel(run), JSON.stringify(event)); + }; +} + +export async function subscribeAndForward( + run: Loaded, + res: FastifyReply, + { + signal, + onReady, + onFailed + }: { + signal: AbortSignal; + onReady: () => Promise; + onFailed: () => Promise; + } +) { + const client = createClient(); + const channel = createChannel(run); + sse.init(res); + try { + await new Promise((resolve, reject) => { + client.subscribe(channel, (err) => { + if (err) { + getLogger().error({ err, channel }, 'Subscription failed'); + onFailed().catch(reject); + reject(err); + } else { + getLogger().trace({ channel }, 'Subscribed'); + onReady().catch(reject); + } + }); + client.on('message', (_, message) => { + const event = JSON.parse(message) as Event; + sse.send(res, event); + if (event.event === 'done' || event.event === 'error') { + resolve(); + } + }); + signal.addEventListener('abort', () => { + reject(signal.reason); + }); + }); + } catch (err) { + sse.send(res, { event: 'error', data: err }); + } finally { + sse.end(res); + } +} diff --git a/src/streaming/sse.ts b/src/streaming/sse.ts new file mode 100644 index 0000000..decd85f --- /dev/null +++ b/src/streaming/sse.ts @@ -0,0 +1,41 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FastifyReply } from 'fastify'; + +import { Event } from './dtos/event.js'; + +export const init = (res: FastifyReply) => { + res.hijack(); + if (!res.raw.headersSent) { + res.raw.setHeader('Content-Type', 'text/event-stream'); + res.raw.setHeader('Connection', 'keep-alive'); + res.raw.setHeader('Cache-Control', 'no-cache,no-transform'); + res.raw.setHeader('x-no-compression', 1); + } +}; + +export const send = (res: FastifyReply, event: Event) => { + res.raw.write(createMessage(event)); +}; + +export const end = (res: FastifyReply) => { + res.raw.end(); +}; + +function createMessage(event: Event): string { + return `event: ${event.event}\ndata: ${JSON.stringify(event.data)}\n\n`; +} diff --git a/src/swagger.ts b/src/swagger.ts new file mode 100644 index 0000000..2ce03c9 --- /dev/null +++ b/src/swagger.ts @@ -0,0 +1,73 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import fp from 'fastify-plugin'; +import swagger from '@fastify/swagger'; +import swaggerUi from '@fastify/swagger-ui'; +import { unique } from 'remeda'; + +import { GIT_TAG } from './config.js'; +import { errorSchema } from './errors/dtos/error.js'; +import { errorResponseSchema } from './errors/dtos/error-response.js'; + +export const Tag = { + OPENAI_API: 'OpenAI API', + OPENAI_ASSISTANTS_API: 'OpenAI Assistants API', + BEE_API: 'Bee API' +}; +export type Tag = (typeof Tag)[keyof typeof Tag]; + +export const swaggerPlugin = fp.default(async (app) => { + app.register(swagger, { + openapi: { + info: { + title: 'Bee', + version: GIT_TAG + }, + openapi: '3.1.0', + tags: unique([ + Tag.OPENAI_ASSISTANTS_API, + Tag.OPENAI_API, + Tag.BEE_API, + ...Object.values(Tag) + ]).map((tag) => ({ name: tag })), + components: { + securitySchemes: { + bearerAuth: { + type: 'http', + scheme: 'bearer' + } + }, + schemas: { + Error: errorSchema, + ErrorResponse: errorResponseSchema + } as any // Bypass type error + }, + security: [ + { + bearerAuth: [] + } + ] + } + }); + app.register(swaggerUi, { + routePrefix: '/docs', + uiConfig: { + docExpansion: 'list', + deepLinking: false + } + }); +}); diff --git a/src/terminus.ts b/src/terminus.ts new file mode 100644 index 0000000..6dd76b0 --- /dev/null +++ b/src/terminus.ts @@ -0,0 +1,54 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { createTerminus as _createTerminus } from '@godaddy/terminus'; +import fastifyPlugin from 'fastify-plugin'; +import { RawServerBase } from 'fastify/types/utils.js'; + +import { getLogger } from './logger.js'; +import { SHUTDOWN_GRACEFUL_PERIOD } from './config.js'; + +import { closeAllWorkers } from '@/jobs/bullmq.js'; + +export function createTerminus(server: RawServerBase) { + async function beforeShutdown() { + getLogger().info('Server shutdown started...'); + closeAllWorkers(); + return new Promise((resolve) => { + setTimeout(resolve, SHUTDOWN_GRACEFUL_PERIOD); + }); + } + + async function onShutdown() { + getLogger().info('Server has successfully shut down'); + } + + _createTerminus(server, { + signals: ['SIGTERM', 'SIGINT'], + healthChecks: { + '/healthcheck': () => Promise.resolve() + }, + useExit0: true, + beforeShutdown, + onShutdown, + sendFailuresDuringShutdown: false, + logger: (msg, error) => { + getLogger().error({ error }, msg); + } + }); +} + +export const terminusPlugin = fastifyPlugin(async (app) => createTerminus(app.server)); diff --git a/src/threads/dtos/thread-create.ts b/src/threads/dtos/thread-create.ts new file mode 100644 index 0000000..c8608c8 --- /dev/null +++ b/src/threads/dtos/thread-create.ts @@ -0,0 +1,40 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { threadSchema } from './thread.js'; + +import { messageCreateBodySchema } from '@/messages/dtos/message-create.js'; +import { metadataSchema } from '@/schema.js'; +import { toolResourcesSchema } from '@/tools/dtos/tool-resources.js'; + +export const threadCreateBodySchema = { + type: 'object', + additionalProperties: false, + properties: { + messages: { + type: 'array', + items: messageCreateBodySchema + }, + metadata: metadataSchema, + tool_resources: toolResourcesSchema + } +} as const satisfies JSONSchema; +export type ThreadCreateBody = FromSchema; + +export const threadCreateResponseSchema = threadSchema; +export type ThreadCreateResponse = FromSchema; diff --git a/src/threads/dtos/thread-delete.ts b/src/threads/dtos/thread-delete.ts new file mode 100644 index 0000000..affbd06 --- /dev/null +++ b/src/threads/dtos/thread-delete.ts @@ -0,0 +1,27 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema } from 'json-schema-to-ts'; + +import { threadReadParamsSchema } from './thread-read.js'; + +import { createDeleteSchema } from '@/schema.js'; + +export const threadDeleteParamsSchema = threadReadParamsSchema; +export type ThreadDeleteParams = FromSchema; + +export const threadDeleteResponseSchema = createDeleteSchema('thread'); +export type ThreadDeleteResponse = FromSchema; diff --git a/src/threads/dtos/thread-read.ts b/src/threads/dtos/thread-read.ts new file mode 100644 index 0000000..d06e2b6 --- /dev/null +++ b/src/threads/dtos/thread-read.ts @@ -0,0 +1,32 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { threadSchema } from './thread.js'; + +export const threadReadParamsSchema = { + type: 'object', + required: ['thread_id'], + additionalProperties: false, + properties: { + thread_id: { type: 'string' } + } +} as const satisfies JSONSchema; +export type ThreadReadParams = FromSchema; + +export const threadReadResponseSchema = threadSchema; +export type ThreadReadResponse = FromSchema; diff --git a/src/threads/dtos/thread-update.ts b/src/threads/dtos/thread-update.ts new file mode 100644 index 0000000..1915332 --- /dev/null +++ b/src/threads/dtos/thread-update.ts @@ -0,0 +1,40 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema } from 'json-schema-to-ts'; + +import { threadSchema } from './thread.js'; +import { threadReadParamsSchema } from './thread-read.js'; + +import { metadataSchema } from '@/schema.js'; +import { toolResourcesSchema } from '@/tools/dtos/tool-resources.js'; +import { JSONSchema } from '@/ajv.js'; + +export const threadUpdateBodySchema = { + type: 'object', + additionalProperties: false, + properties: { + metadata: metadataSchema, + tool_resources: toolResourcesSchema + } +} as const satisfies JSONSchema; +export type ThreadUpdateBody = FromSchema; + +export const threadUpdateResponseSchema = threadSchema; +export type ThreadUpdateResponse = FromSchema; + +export const threadUpdateParamsSchema = threadReadParamsSchema; +export type ThreadUpdateParams = FromSchema; diff --git a/src/threads/dtos/thread.ts b/src/threads/dtos/thread.ts new file mode 100644 index 0000000..779645e --- /dev/null +++ b/src/threads/dtos/thread.ts @@ -0,0 +1,33 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { metadataSchema } from '@/schema.js'; +import { toolResourcesSchema } from '@/tools/dtos/tool-resources.js'; + +export const threadSchema = { + type: 'object', + required: ['id', 'metadata', 'created_at', 'object'], + properties: { + id: { type: 'string' }, + object: { const: 'thread' }, + metadata: metadataSchema, + created_at: { type: 'number' }, + tool_resources: toolResourcesSchema + } +} as const satisfies JSONSchema; +export type Thread = FromSchema; diff --git a/src/threads/dtos/threads-list.ts b/src/threads/dtos/threads-list.ts new file mode 100644 index 0000000..9d9f003 --- /dev/null +++ b/src/threads/dtos/threads-list.ts @@ -0,0 +1,27 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema } from 'json-schema-to-ts'; + +import { threadSchema } from './thread.js'; + +import { createPaginationQuerySchema, withPagination } from '@/schema.js'; + +export const threadsListQuerySchema = createPaginationQuerySchema(); +export type ThreadsListQuery = FromSchema; + +export const threadsListResponseSchema = withPagination(threadSchema); +export type ThreadsListResponse = FromSchema; diff --git a/src/threads/jobs/cleanup.queue.ts b/src/threads/jobs/cleanup.queue.ts new file mode 100644 index 0000000..c7f708b --- /dev/null +++ b/src/threads/jobs/cleanup.queue.ts @@ -0,0 +1,114 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { RequestContext } from '@mikro-orm/core'; +import dayjs from 'dayjs'; +import { unique } from 'remeda'; + +import { Thread } from '../thread.entity'; + +import { ORM } from '@/database.js'; +import { createQueue } from '@/jobs/bullmq.js'; +import { QueueName } from '@/jobs/constants.js'; +import { Run } from '@/runs/entities/run.entity'; +import { Message } from '@/messages/message.entity'; +import { RunStep } from '@/run-steps/entities/run-step.entity'; +import { File } from '@/files/entities/file.entity'; +import { VectorStore } from '@/vector-stores/entities/vector-store.entity'; +import { getJobLogger } from '@/logger'; +import { deleteVectorStoreFiles } from '@/vector-store-files/vector-store-files.service'; + +async function jobHandler() { + return RequestContext.create(ORM.em, async () => { + const runs = await ORM.em + .getRepository(Run) + .find( + { createdAt: { $lt: dayjs().subtract(15, 'days').toDate() } }, + { filters: { deleted: false }, populate: ['thread'] } + ); + + const threadsWithoutRun = await ORM.em.aggregate(Thread, [ + { $match: { createdAt: { $lt: dayjs().subtract(15, 'days').toDate() } } }, + { + $lookup: { + from: 'run', + localField: '_id', + foreignField: 'thread', + as: 'runs' + } + }, + { $match: { runs: { $size: 0 } } }, + { $set: { id: '$_id' } }, + { $project: { id: 1 } } + ]); + + const threadIds = unique([ + ...threadsWithoutRun.map((t) => t.id), + ...runs.map((r) => r.thread.id) + ]); + + await Promise.all( + threadIds.map(async (threadId) => { + RequestContext.create(ORM.em, async () => { + try { + await ORM.em + .getRepository(Message) + .nativeDelete({ thread: threadId }, { filters: { deleted: false } }); + await ORM.em + .getRepository(RunStep) + .nativeDelete({ thread: threadId }, { filters: { deleted: false } }); + const files = await ORM.em + .getRepository(File) + .find({ dependsOn: threadId }, { filters: { deleted: false } }); + files.forEach((file) => file.delete()); // files will be deleted in separate job + + const vectorStores = await ORM.em + .getRepository(VectorStore) + .find({ dependsOn: threadId }, { filters: { deleted: false } }); + await Promise.all( + vectorStores.map(async (vs) => { + await deleteVectorStoreFiles(vs.files.slice()); + ORM.em.remove(vs.files); + }) + ); + ORM.em.remove(vectorStores); + + await ORM.em + .getRepository(Run) + .nativeDelete({ thread: threadId }, { filters: { deleted: false } }); + + await ORM.em.flush(); // try to flush all delete before deleting the thread itself + + await ORM.em + .getRepository(Thread) + .nativeDelete({ id: threadId }, { filters: { deleted: false } }); + } catch (err) { + getJobLogger('threadCleanup').warn({ err }, 'Thread can not be deleted.'); + } + }); + }) + ); + }); +} + +export const { queue, worker } = createQueue({ + name: QueueName.THREADS_CLEANUP, + jobHandler, + jobsOptions: { attempts: 1 }, + workerOptions: { + concurrency: 1 + } +}); diff --git a/src/threads/thread.entity.ts b/src/threads/thread.entity.ts new file mode 100644 index 0000000..ba07598 --- /dev/null +++ b/src/threads/thread.entity.ts @@ -0,0 +1,54 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Collection, Embedded, Entity, OneToMany, QueryOrder } from '@mikro-orm/core'; + +import { Message } from '@/messages/message.entity.js'; +import { FileSearchResource } from '@/tools/entities/tool-resources/file-search-resources.entity.js'; +import { CodeInterpreterResource } from '@/tools/entities/tool-resources/code-interpreter-resource.entity.js'; +import { AnyToolResource } from '@/tools/entities/tool-resources/tool-resource.entity.js'; +import { + PrincipalScopedEntity, + PrincipalScopedEntityInput +} from '@/common/principal-scoped.entity'; +import { UserResource } from '@/tools/entities/tool-resources/user-resource.entity'; +import { SystemResource } from '@/tools/entities/tool-resources/system-resource.entity'; + +@Entity() +export class Thread extends PrincipalScopedEntity { + getIdPrefix(): string { + return 'thread'; + } + + @OneToMany({ + mappedBy: 'thread', + orderBy: [{ createdAt: QueryOrder.ASC }, { order: QueryOrder.ASC }] + }) + messages: Collection = new Collection(this); + + // Union must be defined in alphabetical order, otherwise Mikro-ORM won't discovered the auto-created virtual polymorphic entity + @Embedded({ object: true }) + toolResources?: (CodeInterpreterResource | FileSearchResource | SystemResource | UserResource)[]; + + constructor({ toolResources, ...rest }: ThreadInput) { + super(rest); + this.toolResources = toolResources; + } +} + +export type ThreadInput = PrincipalScopedEntityInput & { + toolResources?: AnyToolResource[]; +}; diff --git a/src/threads/threads.module.ts b/src/threads/threads.module.ts new file mode 100644 index 0000000..5f36c20 --- /dev/null +++ b/src/threads/threads.module.ts @@ -0,0 +1,128 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FastifyPluginAsyncJsonSchemaToTs } from '@fastify/type-provider-json-schema-to-ts'; +import { StatusCodes } from 'http-status-codes'; + +import { + createThread, + deleteThread, + listThreads, + readThread, + updateThread +} from './threads.service.js'; +import { + ThreadCreateBody, + threadCreateBodySchema, + threadCreateResponseSchema +} from './dtos/thread-create.js'; +import { + ThreadsListQuery, + threadsListQuerySchema, + threadsListResponseSchema +} from './dtos/threads-list.js'; +import { + ThreadReadParams, + threadReadParamsSchema, + threadReadResponseSchema +} from './dtos/thread-read.js'; +import { + ThreadUpdateBody, + ThreadUpdateParams, + threadUpdateBodySchema, + threadUpdateParamsSchema, + threadUpdateResponseSchema +} from './dtos/thread-update.js'; +import { + ThreadDeleteParams, + threadDeleteParamsSchema, + threadDeleteResponseSchema +} from './dtos/thread-delete.js'; + +import { Tag } from '@/swagger.js'; + +export const threadsModule: FastifyPluginAsyncJsonSchemaToTs = async (app) => { + app.post<{ Body: ThreadCreateBody }>( + '/threads', + { + schema: { + body: threadCreateBodySchema, + response: { [StatusCodes.OK]: threadCreateResponseSchema }, + tags: [Tag.OPENAI_ASSISTANTS_API] + }, + preHandler: app.auth() + }, + async (req) => createThread(req.body) + ); + + app.post<{ Body: ThreadUpdateBody; Params: ThreadUpdateParams }>( + '/threads/:thread_id', + { + schema: { + body: threadUpdateBodySchema, + params: threadUpdateParamsSchema, + response: { [StatusCodes.OK]: threadUpdateResponseSchema }, + tags: [Tag.OPENAI_ASSISTANTS_API] + }, + preHandler: app.auth() + }, + async (req) => updateThread({ ...req.body, ...req.params }) + ); + + app.get<{ Params: ThreadReadParams }>( + '/threads/:thread_id', + { + schema: { + params: threadReadParamsSchema, + response: { [StatusCodes.OK]: threadReadResponseSchema }, + tags: [Tag.OPENAI_ASSISTANTS_API] + }, + preHandler: app.auth() + }, + async (req) => { + const { thread_id } = req.params; + return readThread({ thread_id }); + } + ); + + app.get<{ Querystring: ThreadsListQuery }>( + '/threads', + { + schema: { + querystring: threadsListQuerySchema, + response: { [StatusCodes.OK]: threadsListResponseSchema }, + tags: [Tag.BEE_API] + }, + preHandler: app.auth() + }, + async (req) => listThreads(req.query) + ); + + app.delete<{ Params: ThreadDeleteParams }>( + '/threads/:thread_id', + { + preHandler: app.auth(), + schema: { + params: threadDeleteParamsSchema, + response: { + [StatusCodes.OK]: threadDeleteResponseSchema + }, + tags: [Tag.BEE_API] + } + }, + async (req) => deleteThread(req.params) + ); +}; diff --git a/src/threads/threads.service.ts b/src/threads/threads.service.ts new file mode 100644 index 0000000..4b2ef12 --- /dev/null +++ b/src/threads/threads.service.ts @@ -0,0 +1,125 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Loaded } from '@mikro-orm/core'; +import dayjs from 'dayjs'; + +import { ThreadCreateBody, ThreadCreateResponse } from './dtos/thread-create.js'; +import { Thread } from './thread.entity.js'; +import { ThreadsListQuery, ThreadsListResponse } from './dtos/threads-list.js'; +import { ThreadReadParams, ThreadReadResponse } from './dtos/thread-read.js'; +import type { Thread as ThreadDto } from './dtos/thread.js'; +import { + ThreadUpdateBody, + ThreadUpdateParams, + ThreadUpdateResponse +} from './dtos/thread-update.js'; +import { ThreadDeleteParams, ThreadDeleteResponse } from './dtos/thread-delete.js'; + +import { ORM } from '@/database.js'; +import { createPaginatedResponse, getListCursor } from '@/utils/pagination.js'; +import { createToolResources, toToolResourcesDto } from '@/tools/tools.service.js'; +import { getUpdatedValue } from '@/utils/update.js'; +import { createDeleteResponse } from '@/utils/delete.js'; +import { File } from '@/files/entities/file.entity.js'; +import { VectorStore } from '@/vector-stores/entities/vector-store.entity.js'; +import { deleteFile } from '@/files/files.service.js'; +import { deleteVectorStore } from '@/vector-stores/vector-stores.service.js'; +import { createMessageEntity } from '@/messages/messages.service.js'; + +function toDto(thread: Loaded): ThreadDto { + return { + id: thread.id, + object: 'thread', + metadata: thread.metadata ?? {}, + created_at: dayjs(thread.createdAt).unix(), + tool_resources: toToolResourcesDto(thread.toolResources) + }; +} + +export async function createThread({ + messages, + metadata, + tool_resources +}: ThreadCreateBody): Promise { + const thread = new Thread({ + toolResources: await createToolResources(tool_resources), + metadata + }); + ORM.em.persist(thread); + const threadMessages = await Promise.all( + (messages ?? []).map(async (message, idx) => + createMessageEntity({ thread_id: thread.id, ...message, order: idx }) + ) + ); + + await ORM.em.persistAndFlush(threadMessages); + return toDto(thread); +} + +export async function updateThread({ + thread_id, + metadata, + tool_resources +}: ThreadUpdateParams & ThreadUpdateBody): Promise { + const thread = await ORM.em.getRepository(Thread).findOneOrFail({ + id: thread_id + }); + thread.toolResources = getUpdatedValue( + await createToolResources(tool_resources), + thread.toolResources + ); + thread.metadata = getUpdatedValue(metadata, thread.metadata); + await ORM.em.flush(); + return toDto(thread); +} + +export async function readThread({ thread_id }: ThreadReadParams): Promise { + const thread = await ORM.em.getRepository(Thread).findOneOrFail({ id: thread_id }); + return toDto(thread); +} + +export async function listThreads({ + limit, + after, + before, + order, + order_by +}: ThreadsListQuery): Promise { + const repo = ORM.em.getRepository(Thread); + const cursor = await getListCursor({}, { limit, order, order_by, after, before }, repo); + return createPaginatedResponse(cursor, toDto); +} + +export async function deleteThread({ + thread_id +}: ThreadDeleteParams): Promise { + const thread = await ORM.em.getRepository(Thread).findOneOrFail({ id: thread_id }); + + // delete dependent entities + const files = await ORM.em.getRepository(File).find({ dependsOn: thread.id }); + await Promise.all(files.map((file) => deleteFile({ file_id: file.id }))); + + const vectorStores = await ORM.em.getRepository(VectorStore).find({ dependsOn: thread.id }); + await Promise.all( + vectorStores.map((vectorStore) => deleteVectorStore({ vector_store_id: vectorStore.id })) + ); + + thread.delete(); + await ORM.em.flush(); + + return createDeleteResponse(thread_id, 'thread'); +} diff --git a/src/tools/dtos/tool-call-delta.ts b/src/tools/dtos/tool-call-delta.ts new file mode 100644 index 0000000..f2825e6 --- /dev/null +++ b/src/tools/dtos/tool-call-delta.ts @@ -0,0 +1,153 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { ToolType } from '../entities/tool/tool.entity.js'; +import { SystemTools } from '../entities/tool-calls/system-call.entity.js'; + +export const toolCallDeltaSchema = { + oneOf: [ + { + type: 'object', + required: ['index', 'id', 'type', ToolType.CODE_INTERPRETER], + properties: { + index: { type: 'integer' }, + id: { type: 'string' }, + type: { const: ToolType.CODE_INTERPRETER }, + [ToolType.CODE_INTERPRETER]: { + type: 'object', + required: ['input', 'outputs'], + properties: { + input: { type: 'string' }, + outputs: { + type: 'array', + items: { + oneOf: [ + { + type: 'object', + required: ['index', 'type', 'logs'], + properties: { + index: { type: 'integer' }, + type: { const: 'logs' }, + logs: { type: 'string' } + } + }, + { + type: 'object', + required: ['index', 'type', 'image'], + properties: { + index: { type: 'integer' }, + type: { const: 'image' }, + image: { + type: 'object', + required: ['file_id'], + properties: { file_id: { type: 'string' } } + } + } + }, + { + type: 'object', + required: ['index', 'type', 'resource'], + properties: { + index: { type: 'integer' }, + type: { const: 'resource' }, + resource: { + type: 'object', + required: ['file_id'], + properties: { file_id: { type: 'string' } } + } + } + } + ] + } + } + } + } + } + }, + { + type: 'object', + required: ['index', 'id', 'type'], + properties: { + index: { type: 'integer' }, + id: { type: 'string' }, + type: { const: ToolType.FILE_SEARCH } + } + }, + { + type: 'object', + required: ['index', 'id', 'type', ToolType.FUNCTION], + properties: { + index: { type: 'integer' }, + id: { type: 'string' }, + type: { const: ToolType.FUNCTION }, + [ToolType.FUNCTION]: { + type: 'object', + required: ['name', 'arguments', 'output'], + properties: { + name: { type: 'string' }, + arguments: { type: 'string' }, + output: { type: 'string', nullable: true } + } + } + } + }, + { + type: 'object', + required: ['index', 'id', 'type', ToolType.USER], + properties: { + index: { type: 'integer' }, + id: { type: 'string' }, + type: { const: ToolType.USER }, + [ToolType.USER]: { + type: 'object', + required: ['tool', 'arguments', 'output'], + properties: { + tool: { + type: 'object', + required: ['id'], + properties: { + id: { type: 'string' } + } + }, + arguments: { type: 'string', nullable: true }, + output: { type: 'string', nullable: true } + } + } + } + }, + { + type: 'object', + required: ['index', 'id', 'type', ToolType.SYSTEM], + properties: { + index: { type: 'integer' }, + id: { type: 'string' }, + type: { const: ToolType.SYSTEM }, + [ToolType.SYSTEM]: { + type: 'object', + required: ['id'], + properties: { + id: { type: 'string', enum: Object.values(SystemTools) }, + input: {}, + output: {} + } + } + } + } + ] +} as const satisfies JSONSchema; +export type ToolCallDelta = FromSchema; diff --git a/src/tools/dtos/tool-call.ts b/src/tools/dtos/tool-call.ts new file mode 100644 index 0000000..53cb7e1 --- /dev/null +++ b/src/tools/dtos/tool-call.ts @@ -0,0 +1,161 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { ToolType } from '../entities/tool/tool.entity.js'; +import { SystemTools } from '../entities/tool-calls/system-call.entity.js'; + +export const toolCallSchema = { + oneOf: [ + { + type: 'object', + required: ['id', 'type', ToolType.CODE_INTERPRETER], + properties: { + id: { type: 'string' }, + type: { const: ToolType.CODE_INTERPRETER }, + [ToolType.CODE_INTERPRETER]: { + type: 'object', + required: ['input', 'outputs'], + properties: { + input: { type: 'string' }, + outputs: { + type: 'array', + items: { + oneOf: [ + { + type: 'object', + required: ['type', 'logs'], + properties: { + type: { const: 'logs' }, + logs: { type: 'string' } + } + }, + { + type: 'object', + required: ['type', 'image'], + properties: { + type: { const: 'image' }, + image: { + type: 'object', + required: ['file_id'], + properties: { file_id: { type: 'string' } } + } + } + }, + { + type: 'object', + required: ['type', 'resource'], + properties: { + type: { const: 'resource' }, + resource: { + type: 'object', + required: ['file_id'], + properties: { file_id: { type: 'string' } } + } + } + } + ] + } + } + } + } + } + }, + { + type: 'object', + required: ['id', 'type'], + properties: { + id: { type: 'string' }, + type: { const: ToolType.FILE_SEARCH }, + [ToolType.FILE_SEARCH]: { + type: 'object', + required: ['input'], + properties: { + input: { type: 'string' }, + output: { + type: 'array', + items: { + type: 'object', + additionalProperties: false, + required: ['content'], + properties: { content: { type: 'string' }, source: { type: 'string' } } + } + } + } + } + } + }, + { + type: 'object', + required: ['id', 'type', ToolType.FUNCTION], + properties: { + id: { type: 'string' }, + type: { const: ToolType.FUNCTION }, + [ToolType.FUNCTION]: { + type: 'object', + required: ['name', 'arguments', 'output'], + properties: { + name: { type: 'string' }, + arguments: { type: 'string' }, + output: { type: 'string', nullable: true } + } + } + } + }, + { + type: 'object', + required: ['id', 'type', ToolType.USER], + properties: { + id: { type: 'string' }, + type: { const: ToolType.USER }, + [ToolType.USER]: { + type: 'object', + required: ['tool', 'arguments', 'output'], + properties: { + tool: { + type: 'object', + required: ['id'], + properties: { + id: { type: 'string' } + } + }, + arguments: { type: 'string', nullable: true }, + output: { type: 'string', nullable: true } + } + } + } + }, + { + type: 'object', + required: ['id', 'type', ToolType.SYSTEM], + properties: { + id: { type: 'string' }, + type: { const: ToolType.SYSTEM }, + [ToolType.SYSTEM]: { + type: 'object', + required: ['id'], + properties: { + id: { type: 'string', enum: Object.values(SystemTools) }, + input: {}, + output: {} + } + } + } + } + ] +} as const satisfies JSONSchema; +export type ToolCall = FromSchema; diff --git a/src/tools/dtos/tool-create.ts b/src/tools/dtos/tool-create.ts new file mode 100644 index 0000000..6f6e575 --- /dev/null +++ b/src/tools/dtos/tool-create.ts @@ -0,0 +1,62 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { toolSchema } from './tool.js'; + +import { metadataSchema } from '@/schema.js'; + +export const toolCreateBodySchema = { + type: 'object', + oneOf: [ + { + additionalProperties: false, + required: ['source_code'], + properties: { + name: { type: 'string' }, + source_code: { type: 'string' }, + metadata: metadataSchema, + user_description: { type: 'string' } + } + }, + { + additionalProperties: false, + required: ['open_api_schema'], + properties: { + open_api_schema: { type: 'string' }, + api_key: { type: 'string', writeOnly: true }, + metadata: metadataSchema, + user_description: { type: 'string' } + } + }, + { + additionalProperties: false, + required: ['name'], + properties: { + name: { type: 'string' }, + description: { type: 'string' }, + parameters: { type: 'object', additionalProperties: true }, + metadata: metadataSchema, + user_description: { type: 'string' } + } + } + ] +} as const satisfies JSONSchema; +export type ToolCreateBody = FromSchema; + +export const toolCreateResponseSchema = toolSchema; +export type ToolCreateResponse = FromSchema; diff --git a/src/tools/dtos/tool-delete.ts b/src/tools/dtos/tool-delete.ts new file mode 100644 index 0000000..4163bfb --- /dev/null +++ b/src/tools/dtos/tool-delete.ts @@ -0,0 +1,27 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema } from 'json-schema-to-ts'; + +import { toolReadParamsSchema } from './tool-read.js'; + +import { createDeleteSchema } from '@/schema.js'; + +export const toolDeleteParamsSchema = toolReadParamsSchema; +export type ToolDeleteParams = FromSchema; + +export const toolDeleteResponseSchema = createDeleteSchema('tool'); +export type ToolDeleteResponse = FromSchema; diff --git a/src/tools/dtos/tool-read.ts b/src/tools/dtos/tool-read.ts new file mode 100644 index 0000000..579b3bf --- /dev/null +++ b/src/tools/dtos/tool-read.ts @@ -0,0 +1,34 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { toolSchema } from './tool.js'; + +export const toolReadParamsSchema = { + type: 'object', + additionalProperties: false, + required: ['tool_id'], + properties: { + tool_id: { + type: 'string' + } + } +} as const satisfies JSONSchema; +export type ToolReadParams = FromSchema; + +export const toolReadResponseSchema = toolSchema; +export type ToolReadResponse = FromSchema; diff --git a/src/tools/dtos/tool-resources.ts b/src/tools/dtos/tool-resources.ts new file mode 100644 index 0000000..b3fa6e4 --- /dev/null +++ b/src/tools/dtos/tool-resources.ts @@ -0,0 +1,59 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { ToolType } from '../entities/tool/tool.entity.js'; + +const fileSearchToolResourcesSchema = { + type: 'object', + additionalProperties: false, + properties: { + vector_store_ids: { + type: 'array', + description: 'The vector_store attached to this object.', + maxItems: 1, + items: { type: 'string' }, + uniqueItems: true + } + } +} as const satisfies JSONSchema; + +export const toolResourcesSchema = { + type: 'object', + nullable: true, + additionalProperties: false, + properties: { + [ToolType.CODE_INTERPRETER]: { + type: 'object', + additionalProperties: false, + properties: { + file_ids: { type: 'array', items: { type: 'string' }, uniqueItems: true, default: [] } + } + }, + [ToolType.FILE_SEARCH]: fileSearchToolResourcesSchema + }, + patternProperties: { + '^(?!.*(file_search|code_interpreter))': { + type: 'object', + additionalProperties: false, + properties: { + file_ids: { type: 'array', items: { type: 'string' }, uniqueItems: true, default: [] } + } + } + } +} as const satisfies JSONSchema; +export type ToolResources = FromSchema; diff --git a/src/tools/dtos/tool-update.ts b/src/tools/dtos/tool-update.ts new file mode 100644 index 0000000..d8facb5 --- /dev/null +++ b/src/tools/dtos/tool-update.ts @@ -0,0 +1,85 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { toolReadParamsSchema } from './tool-read.js'; +import { toolSchema } from './tool.js'; + +import { metadataSchema } from '@/schema.js'; + +export const toolUpdateBodySchema = { + type: 'object', + anyOf: [ + { + additionalProperties: false, + properties: { + name: { + type: 'string' + }, + description: { + type: 'string' + }, + source_code: { + type: 'string' + }, + metadata: metadataSchema, + user_description: { type: 'string' } + } + }, + { + additionalProperties: false, + required: ['open_api_schema'], + properties: { + name: { + type: 'string' + }, + description: { + type: 'string' + }, + open_api_schema: { + type: 'string' + }, + metadata: metadataSchema, + user_description: { type: 'string' } + } + }, + { + additionalProperties: false, + properties: { + name: { + type: 'string' + }, + description: { + type: 'string' + }, + parameters: { + type: 'object', + additionalProperties: true + }, + metadata: metadataSchema, + user_description: { type: 'string' } + } + } + ] +} as const satisfies JSONSchema; +export type ToolUpdateBody = FromSchema; + +export const toolUpdateParamsSchema = toolReadParamsSchema; +export type ToolUpdateParams = FromSchema; + +export const toolUpdateResponseSchema = toolSchema; +export type ToolUpdateResponse = FromSchema; diff --git a/src/tools/dtos/tool.ts b/src/tools/dtos/tool.ts new file mode 100644 index 0000000..e37fca9 --- /dev/null +++ b/src/tools/dtos/tool.ts @@ -0,0 +1,76 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { ToolType } from '../entities/tool/tool.entity.js'; + +import { metadataSchema } from '@/schema.js'; + +export const toolSchema = { + type: 'object', + required: [ + 'id', + 'type', + 'object', + 'name', + 'is_external', + 'source_code', + 'created_at', + 'description', + 'json_schema', + 'open_api_schema', + 'user_description', + 'metadata' + ], + properties: { + id: { + type: 'string' + }, + type: { type: 'string', enum: Object.values(ToolType) }, + object: { const: 'tool' }, + name: { + type: 'string' + }, + description: { + type: 'string' + }, + is_external: { + type: 'boolean' + }, + source_code: { + type: 'string', + nullable: true + }, + json_schema: { + type: 'string', + nullable: true + }, + open_api_schema: { + type: 'string', + nullable: true + }, + created_at: { + type: 'number' + }, + user_description: { + type: 'string', + nullable: true + }, + metadata: metadataSchema + } +} as const satisfies JSONSchema; +export type Tool = FromSchema; diff --git a/src/tools/dtos/tools-list.ts b/src/tools/dtos/tools-list.ts new file mode 100644 index 0000000..0bdeba5 --- /dev/null +++ b/src/tools/dtos/tools-list.ts @@ -0,0 +1,46 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema } from 'json-schema-to-ts'; + +import { ToolType } from '../entities/tool/tool.entity.js'; + +import { toolSchema } from './tool.js'; + +import { createPaginationQuerySchema, withPagination } from '@/schema.js'; +import { JSONSchema } from '@/ajv.js'; + +export const toolsListQuerySchema = { + type: 'object', + additionalProperties: false, + properties: { + ...createPaginationQuerySchema(['type', 'name'] as const).properties, + type: { + type: 'array', + uniqueItems: true, + items: { type: 'string', enum: Object.values(ToolType) } + }, + search: { + type: 'string', + minLength: 1, + nullable: true + } + } +} as const satisfies JSONSchema; +export type ToolsListQuery = FromSchema; + +export const toolsListResponseSchema = withPagination(toolSchema); +export type ToolsListResponse = FromSchema; diff --git a/src/tools/dtos/tools-usage.ts b/src/tools/dtos/tools-usage.ts new file mode 100644 index 0000000..545637b --- /dev/null +++ b/src/tools/dtos/tools-usage.ts @@ -0,0 +1,103 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { ToolType } from '../entities/tool/tool.entity.js'; +import { SystemTools } from '../entities/tool-calls/system-call.entity.js'; + +export const toolUsageSchema = { + oneOf: [ + { + type: 'object', + required: ['type', ToolType.USER], + properties: { + type: { const: ToolType.USER }, + [ToolType.USER]: { + type: 'object', + required: ['tool'], + properties: { + tool: { + type: 'object', + required: ['id'], + properties: { + id: { type: 'string' } + } + } + } + } + } + }, + { + type: 'object', + required: ['type', ToolType.FUNCTION], + properties: { + type: { const: ToolType.FUNCTION }, + [ToolType.FUNCTION]: { + type: 'object', + required: ['name'], + properties: { + name: { type: 'string' }, + description: { type: 'string' }, + parameters: { type: 'object', additionalProperties: true } + } + } + } + }, + { + type: 'object', + required: ['type'], + properties: { + type: { const: ToolType.CODE_INTERPRETER } + } + }, + { + type: 'object', + title: 'FileSearch tool', + required: ['type'], + properties: { + type: { const: ToolType.FILE_SEARCH }, + [ToolType.FILE_SEARCH]: { + type: 'object', + properties: { + max_num_results: { + type: 'integer', + minimum: 1, + maximum: 50, + description: + 'The maximum number of results the file search tool should output. This number should be between 1 and 50 inclusive.\n\nNote that the file search tool may output fewer than `max_num_results` results.' + } + } + } + } + }, + { + type: 'object', + required: ['type', ToolType.SYSTEM], + properties: { + type: { const: ToolType.SYSTEM }, + [ToolType.SYSTEM]: { + type: 'object', + required: ['id'], + properties: { + id: { type: 'string', enum: Object.values(SystemTools) } + } + } + } + } + ] +} as const satisfies JSONSchema; +export type ToolUsage = FromSchema; diff --git a/src/tools/entities/tool-calls/code-interpreter-call.entity.ts b/src/tools/entities/tool-calls/code-interpreter-call.entity.ts new file mode 100644 index 0000000..9e87b13 --- /dev/null +++ b/src/tools/entities/tool-calls/code-interpreter-call.entity.ts @@ -0,0 +1,44 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, Embedded, Property } from '@mikro-orm/core'; + +import { ToolType } from '../tool/tool.entity.js'; + +import { ToolCall } from './tool-call.entity.js'; + +import { FileContainer } from '@/files/entities/files-container.entity.js'; + +@Embeddable({ discriminatorValue: ToolType.CODE_INTERPRETER }) +export class CodeInterpreterCall extends ToolCall { + type = ToolType.CODE_INTERPRETER; + + @Property() + input!: string; + + @Property() + logs?: string[]; + + @Embedded({ object: true }) + fileContainers?: FileContainer[]; + + constructor({ input }: CodeInterpreterCallInput) { + super(); + this.input = input; + } +} + +export type CodeInterpreterCallInput = Pick; diff --git a/src/tools/entities/tool-calls/file-search-call.entity.ts b/src/tools/entities/tool-calls/file-search-call.entity.ts new file mode 100644 index 0000000..0425a6a --- /dev/null +++ b/src/tools/entities/tool-calls/file-search-call.entity.ts @@ -0,0 +1,41 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, Property } from '@mikro-orm/core'; + +import { ToolType } from '../tool/tool.entity.js'; + +import { ToolCall } from './tool-call.entity.js'; + +import { FileSearchToolResult } from '@/runs/execution/tools/file-search-tool.js'; + +@Embeddable({ discriminatorValue: ToolType.FILE_SEARCH }) +export class FileSearchCall extends ToolCall { + type = ToolType.FILE_SEARCH; + @Property() + input!: string; + + @Property({ type: 'json' }) + results?: FileSearchToolResult[]; + + constructor({ input, results }: FileSearchCallInput) { + super(); + this.input = input; + this.results = results; + } +} + +export type FileSearchCallInput = Pick; diff --git a/src/tools/entities/tool-calls/function-call.entity.ts b/src/tools/entities/tool-calls/function-call.entity.ts new file mode 100644 index 0000000..57bea22 --- /dev/null +++ b/src/tools/entities/tool-calls/function-call.entity.ts @@ -0,0 +1,43 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, Property } from '@mikro-orm/core'; + +import { ToolType } from '../tool/tool.entity.js'; + +import { ToolCall } from './tool-call.entity.js'; + +@Embeddable({ discriminatorValue: ToolType.FUNCTION }) +export class FunctionCall extends ToolCall { + type = ToolType.FUNCTION; + + @Property() + name!: string; + + @Property() + arguments!: string; + + @Property() + output?: string; + + constructor(input: FunctionCallInput) { + super(); + this.name = input.name; + this.arguments = input.arguments; + } +} + +export type FunctionCallInput = Pick; diff --git a/src/tools/entities/tool-calls/system-call.entity.ts b/src/tools/entities/tool-calls/system-call.entity.ts new file mode 100644 index 0000000..877495d --- /dev/null +++ b/src/tools/entities/tool-calls/system-call.entity.ts @@ -0,0 +1,52 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, Enum, Property } from '@mikro-orm/core'; + +import { ToolType } from '../tool/tool.entity.js'; + +import { ToolCall } from './tool-call.entity.js'; + +export enum SystemTools { + WEB_SEARCH = 'web_search', + WIKIPEDIA = 'wikipedia', + WEATHER = 'weather', + ARXIV = 'arxiv', + READ_FILE = 'read_file' +} + +@Embeddable({ discriminatorValue: ToolType.SYSTEM }) +export class SystemCall extends ToolCall { + type = ToolType.SYSTEM; + + @Enum() + toolId!: SystemTools; + + @Property({ type: 'json' }) + input?: unknown; + + @Property({ type: 'json' }) + output?: unknown; + + constructor({ toolId: name, input, output }: SystemCallInput) { + super(); + this.toolId = name; + this.input = input; + this.output = output; + } +} + +export type SystemCallInput = Pick; diff --git a/src/tools/entities/tool-calls/tool-call.entity.ts b/src/tools/entities/tool-calls/tool-call.entity.ts new file mode 100644 index 0000000..fde7a11 --- /dev/null +++ b/src/tools/entities/tool-calls/tool-call.entity.ts @@ -0,0 +1,43 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, Enum, Property } from '@mikro-orm/core'; + +import { ToolType } from '../tool/tool.entity.js'; + +import { CodeInterpreterCall } from './code-interpreter-call.entity.js'; +import { FileSearchCall } from './file-search-call.entity.js'; +import { FunctionCall } from './function-call.entity.js'; +import { UserCall } from './user-call.entity.js'; +import { SystemCall } from './system-call.entity.js'; + +import { generatePrefixedObjectId } from '@/utils/id.js'; + +@Embeddable({ abstract: true, discriminatorColumn: 'type' }) +export abstract class ToolCall { + @Property({ fieldName: '_id' }) + id = generatePrefixedObjectId('call'); + + @Enum(() => ToolType) + type!: ToolType; +} + +export type AnyToolCall = + | CodeInterpreterCall + | FileSearchCall + | FunctionCall + | SystemCall + | UserCall; diff --git a/src/tools/entities/tool-calls/user-call.entity.ts b/src/tools/entities/tool-calls/user-call.entity.ts new file mode 100644 index 0000000..27ae471 --- /dev/null +++ b/src/tools/entities/tool-calls/user-call.entity.ts @@ -0,0 +1,44 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, ManyToOne, Property, Ref } from '@mikro-orm/core'; + +import { Tool, ToolType } from '../tool/tool.entity.js'; + +import { ToolCall } from './tool-call.entity.js'; + +@Embeddable({ discriminatorValue: ToolType.USER }) +export class UserCall extends ToolCall { + type = ToolType.USER; + + @ManyToOne() + tool!: Ref; + + @Property() + arguments?: string; + + @Property() + output?: string; + + constructor({ tool, arguments: args, output }: UserCallInput) { + super(); + this.tool = tool; + this.arguments = args; + this.output = output; + } +} + +export type UserCallInput = Pick; diff --git a/src/tools/entities/tool-resources/code-interpreter-resource.entity.ts b/src/tools/entities/tool-resources/code-interpreter-resource.entity.ts new file mode 100644 index 0000000..119803e --- /dev/null +++ b/src/tools/entities/tool-resources/code-interpreter-resource.entity.ts @@ -0,0 +1,39 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, Embedded, Ref } from '@mikro-orm/core'; + +import { ToolType } from '../tool/tool.entity.js'; + +import { ToolResource } from './tool-resource.entity.js'; + +import { File } from '@/files/entities/file.entity.js'; +import { FileContainer } from '@/files/entities/files-container.entity.js'; + +@Embeddable({ discriminatorValue: ToolType.CODE_INTERPRETER }) +export class CodeInterpreterResource extends ToolResource { + type = ToolType.CODE_INTERPRETER; + + @Embedded({ object: true }) + fileContainers: FileContainer[]; + + constructor({ files }: CodeInterpreterResourceInput) { + super(); + this.fileContainers = files.map((file) => new FileContainer({ file })); + } +} + +export type CodeInterpreterResourceInput = { files: File[] | Ref[] }; diff --git a/src/tools/entities/tool-resources/file-search-resources.entity.ts b/src/tools/entities/tool-resources/file-search-resources.entity.ts new file mode 100644 index 0000000..2579f88 --- /dev/null +++ b/src/tools/entities/tool-resources/file-search-resources.entity.ts @@ -0,0 +1,40 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, Embedded } from '@mikro-orm/core'; + +import { ToolType } from '../tool/tool.entity.js'; + +import { ToolResource } from '@/tools/entities/tool-resources/tool-resource.entity.js'; +import { VectorStoreContainer } from '@/vector-stores/entities/vector-store-container.entity.js'; +import { VectorStore } from '@/vector-stores/entities/vector-store.entity.js'; + +@Embeddable({ discriminatorValue: ToolType.FILE_SEARCH }) +export class FileSearchResource extends ToolResource { + type = ToolType.FILE_SEARCH; + + @Embedded({ object: true }) + vectorStoreContainers: VectorStoreContainer[]; + + constructor({ vectorStores }: FileSearchResourceInput) { + super(); + this.vectorStoreContainers = vectorStores.map( + (vectorStore) => new VectorStoreContainer({ vectorStore }) + ); + } +} + +export type FileSearchResourceInput = { vectorStores: VectorStore[] }; diff --git a/src/tools/entities/tool-resources/system-resource.entity.ts b/src/tools/entities/tool-resources/system-resource.entity.ts new file mode 100644 index 0000000..6eefd5b --- /dev/null +++ b/src/tools/entities/tool-resources/system-resource.entity.ts @@ -0,0 +1,43 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, Embedded, Property, Ref } from '@mikro-orm/core'; + +import { ToolType } from '../tool/tool.entity.js'; + +import { ToolResource } from './tool-resource.entity.js'; + +import { File } from '@/files/entities/file.entity.js'; +import { FileContainer } from '@/files/entities/files-container.entity.js'; + +@Embeddable({ discriminatorValue: ToolType.SYSTEM }) +export class SystemResource extends ToolResource { + type = ToolType.SYSTEM; + + @Property() + toolId: string; + + @Embedded({ object: true }) + fileContainers: FileContainer[]; + + constructor({ files, toolId }: SystemResourceInput) { + super(); + this.toolId = toolId; + this.fileContainers = files.map((file) => new FileContainer({ file })); + } +} + +export type SystemResourceInput = Pick & { files: File[] | Ref[] }; diff --git a/src/tools/entities/tool-resources/tool-resource.entity.ts b/src/tools/entities/tool-resources/tool-resource.entity.ts new file mode 100644 index 0000000..3ae29f4 --- /dev/null +++ b/src/tools/entities/tool-resources/tool-resource.entity.ts @@ -0,0 +1,36 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, Enum } from '@mikro-orm/core'; + +import { ToolType } from '../tool/tool.entity.js'; + +import { CodeInterpreterResource } from './code-interpreter-resource.entity.js'; +import { FileSearchResource } from './file-search-resources.entity.js'; +import { UserResource } from './user-resource.entity.js'; +import { SystemResource } from './system-resource.entity.js'; + +@Embeddable({ abstract: true, discriminatorColumn: 'type' }) +export abstract class ToolResource { + @Enum(() => ToolType) + type!: ToolType; +} + +export type AnyToolResource = + | CodeInterpreterResource + | FileSearchResource + | SystemResource + | UserResource; diff --git a/src/tools/entities/tool-resources/user-resource.entity.ts b/src/tools/entities/tool-resources/user-resource.entity.ts new file mode 100644 index 0000000..bd9cd45 --- /dev/null +++ b/src/tools/entities/tool-resources/user-resource.entity.ts @@ -0,0 +1,43 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, Embedded, ManyToOne, Ref } from '@mikro-orm/core'; + +import { Tool, ToolType } from '../tool/tool.entity.js'; + +import { ToolResource } from './tool-resource.entity.js'; + +import { File } from '@/files/entities/file.entity.js'; +import { FileContainer } from '@/files/entities/files-container.entity.js'; + +@Embeddable({ discriminatorValue: ToolType.USER }) +export class UserResource extends ToolResource { + type = ToolType.USER; + + @ManyToOne() + tool: Ref; + + @Embedded({ object: true }) + fileContainers: FileContainer[]; + + constructor({ files, tool }: UserResourceInput) { + super(); + this.tool = tool; + this.fileContainers = files.map((file) => new FileContainer({ file })); + } +} + +export type UserResourceInput = Pick & { files: File[] | Ref[] }; diff --git a/src/tools/entities/tool-usages/code-interpreter-usage.entity.ts b/src/tools/entities/tool-usages/code-interpreter-usage.entity.ts new file mode 100644 index 0000000..1975bf8 --- /dev/null +++ b/src/tools/entities/tool-usages/code-interpreter-usage.entity.ts @@ -0,0 +1,26 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable } from '@mikro-orm/core'; + +import { ToolType } from '../tool/tool.entity.js'; + +import { ToolUsage } from './tool-usage.entity.js'; + +@Embeddable({ discriminatorValue: ToolType.CODE_INTERPRETER }) +export class CodeInterpreterUsage extends ToolUsage { + type = ToolType.CODE_INTERPRETER; +} diff --git a/src/tools/entities/tool-usages/file-search-usage.entity.ts b/src/tools/entities/tool-usages/file-search-usage.entity.ts new file mode 100644 index 0000000..26db07c --- /dev/null +++ b/src/tools/entities/tool-usages/file-search-usage.entity.ts @@ -0,0 +1,36 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, Property } from '@mikro-orm/core'; + +import { ToolType } from '../tool/tool.entity.js'; + +import { ToolUsage } from './tool-usage.entity.js'; + +@Embeddable({ discriminatorValue: ToolType.FILE_SEARCH }) +export class FileSearchUsage extends ToolUsage { + type = ToolType.FILE_SEARCH; + + @Property() + maxNumResults!: number; + + constructor({ maxNumResults }: FileSearchUsageInput) { + super(); + this.maxNumResults = maxNumResults; + } +} + +export type FileSearchUsageInput = Pick; diff --git a/src/tools/entities/tool-usages/function-usage.entity.ts b/src/tools/entities/tool-usages/function-usage.entity.ts new file mode 100644 index 0000000..a84316d --- /dev/null +++ b/src/tools/entities/tool-usages/function-usage.entity.ts @@ -0,0 +1,45 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, Property } from '@mikro-orm/core'; +import { SchemaObject } from 'ajv'; + +import { ToolType } from '../tool/tool.entity.js'; + +import { ToolUsage } from './tool-usage.entity.js'; + +@Embeddable({ discriminatorValue: ToolType.FUNCTION }) +export class FunctionUsage extends ToolUsage { + type = ToolType.FUNCTION; + + @Property() + description?: string; + + @Property() + name!: string; + + @Property({ type: 'json' }) + parameters?: SchemaObject; + + constructor({ name, description, parameters }: FunctionUsageInput) { + super(); + this.name = name; + this.description = description; + this.parameters = parameters; + } +} + +export type FunctionUsageInput = Pick; diff --git a/src/tools/entities/tool-usages/system-usage.entity.ts b/src/tools/entities/tool-usages/system-usage.entity.ts new file mode 100644 index 0000000..e672e90 --- /dev/null +++ b/src/tools/entities/tool-usages/system-usage.entity.ts @@ -0,0 +1,41 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, Enum, Property } from '@mikro-orm/core'; + +import { ToolType } from '../tool/tool.entity.js'; +import { SystemTools } from '../tool-calls/system-call.entity.js'; + +import { ToolUsage } from './tool-usage.entity.js'; + +@Embeddable({ discriminatorValue: ToolType.SYSTEM }) +export class SystemUsage extends ToolUsage { + type = ToolType.SYSTEM; + + @Enum() + toolId!: SystemTools; + + @Property({ type: 'json' }) + config?: any; + + constructor({ toolId, config }: SystemUsageInput) { + super(); + this.toolId = toolId; + this.config = config; + } +} + +export type SystemUsageInput = Pick; diff --git a/src/tools/entities/tool-usages/tool-usage.entity.ts b/src/tools/entities/tool-usages/tool-usage.entity.ts new file mode 100644 index 0000000..115be2e --- /dev/null +++ b/src/tools/entities/tool-usages/tool-usage.entity.ts @@ -0,0 +1,38 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, Enum } from '@mikro-orm/core'; + +import { ToolType } from '../tool/tool.entity.js'; + +import { FunctionUsage } from './function-usage.entity.js'; +import { FileSearchUsage } from './file-search-usage.entity.js'; +import { CodeInterpreterUsage } from './code-interpreter-usage.entity.js'; +import { UserUsage } from './user-usage.entity.js'; +import { SystemUsage } from './system-usage.entity.js'; + +@Embeddable({ abstract: true, discriminatorColumn: 'type' }) +export abstract class ToolUsage { + @Enum(() => ToolType) + type!: ToolType; +} + +export type AnyToolUsage = + | CodeInterpreterUsage + | FileSearchUsage + | FunctionUsage + | SystemUsage + | UserUsage; diff --git a/src/tools/entities/tool-usages/user-usage.entity.ts b/src/tools/entities/tool-usages/user-usage.entity.ts new file mode 100644 index 0000000..f6f6cff --- /dev/null +++ b/src/tools/entities/tool-usages/user-usage.entity.ts @@ -0,0 +1,36 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, ManyToOne, Ref } from '@mikro-orm/core'; + +import { Tool, ToolType } from '../tool/tool.entity.js'; + +import { ToolUsage } from './tool-usage.entity.js'; + +@Embeddable({ discriminatorValue: ToolType.USER }) +export class UserUsage extends ToolUsage { + type = ToolType.USER; + + @ManyToOne() + tool!: Ref; + + constructor({ tool }: UserUsageInput) { + super(); + this.tool = tool; + } +} + +export type UserUsageInput = Pick; diff --git a/src/tools/entities/tool/api-tool.entity.ts b/src/tools/entities/tool/api-tool.entity.ts new file mode 100644 index 0000000..2a6f7ca --- /dev/null +++ b/src/tools/entities/tool/api-tool.entity.ts @@ -0,0 +1,40 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Entity, Property } from '@mikro-orm/core'; + +import { Tool, ToolExecutor, ToolInput } from './tool.entity.js'; + +@Entity({ discriminatorValue: ToolExecutor.API }) +export class ApiTool extends Tool { + executor = ToolExecutor.API; + + @Property() + openApiSchema!: string; + + @Property() + apiKey?: string; + + constructor({ openApiSchema, apiKey, ...rest }: ApiToolInput) { + super(rest); + this.openApiSchema = openApiSchema; + this.apiKey = apiKey; + } +} + +export type ApiToolInput = ToolInput & + Pick & + Partial>; diff --git a/src/tools/entities/tool/code-interpreter-tool.entity.ts b/src/tools/entities/tool/code-interpreter-tool.entity.ts new file mode 100644 index 0000000..8ded2a3 --- /dev/null +++ b/src/tools/entities/tool/code-interpreter-tool.entity.ts @@ -0,0 +1,40 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Entity, Property } from '@mikro-orm/core'; +import { JSONSchema } from 'json-schema-to-ts'; + +import { Tool, ToolExecutor, ToolInput } from './tool.entity.js'; + +@Entity({ discriminatorValue: ToolExecutor.CODE_INTERPRETER }) +export class CodeInterpreterTool extends Tool { + executor = ToolExecutor.CODE_INTERPRETER; + + @Property() + sourceCode!: string; + + @Property({ type: 'json' }) + jsonSchema!: JSONSchema; + + constructor({ sourceCode, jsonSchema, ...rest }: CodeInterpreterToolInput) { + super(rest); + this.sourceCode = sourceCode; + this.jsonSchema = jsonSchema; + } +} + +export type CodeInterpreterToolInput = ToolInput & + Pick; diff --git a/src/tools/entities/tool/function-tool.entity.ts b/src/tools/entities/tool/function-tool.entity.ts new file mode 100644 index 0000000..d6c34db --- /dev/null +++ b/src/tools/entities/tool/function-tool.entity.ts @@ -0,0 +1,34 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Entity, Property } from '@mikro-orm/core'; + +import { Tool, ToolExecutor, ToolInput } from './tool.entity.js'; + +@Entity({ discriminatorValue: ToolExecutor.FUNCTION }) +export class FunctionTool extends Tool { + executor = ToolExecutor.FUNCTION; + + @Property() + parameters?: Record; + + constructor({ parameters, ...rest }: FunctionInput) { + super(rest); + this.parameters = parameters; + } +} + +export type FunctionInput = ToolInput & Pick; diff --git a/src/tools/entities/tool/tool.entity.ts b/src/tools/entities/tool/tool.entity.ts new file mode 100644 index 0000000..9c323dd --- /dev/null +++ b/src/tools/entities/tool/tool.entity.ts @@ -0,0 +1,88 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Entity, Enum, Index, Property } from '@mikro-orm/core'; + +import { ApiTool } from './api-tool.entity.js'; +import { CodeInterpreterTool } from './code-interpreter-tool.entity.js'; +import { FunctionTool } from './function-tool.entity.js'; + +import { ProjectScopedEntity, ProjectScopedEntityInput } from '@/common/project-scoped.entity.js'; + +export const ToolType = { + CODE_INTERPRETER: 'code_interpreter', + FILE_SEARCH: 'file_search', + FUNCTION: 'function', + USER: 'user', + SYSTEM: 'system' +} as const; +export type ToolType = (typeof ToolType)[keyof typeof ToolType]; + +export const ToolExecutor = { + FUNCTION: 'function', + CODE_INTERPRETER: 'code_interpreter', + API: 'api' +} as const; +export type ToolExecutor = (typeof ToolExecutor)[keyof typeof ToolExecutor]; + +@Entity({ abstract: true, discriminatorColumn: 'executor' }) +@Index({ + options: [ + { + name: 1, + createdBy: 1 + }, + { + unique: true, + partialFilterExpression: { deletedAt: { $in: [null] } } + } + ] +}) +export abstract class Tool extends ProjectScopedEntity { + getIdPrefix(): string { + return 'tool'; + } + + @Enum(() => ToolExecutor) + executor!: ToolExecutor; + + @Property() + name: string; + + @Property() + description: string; + + @Property() + userDescription?: string; + + @Property({ persist: false }) + public get type(): ToolType { + return ToolType.USER; + } + + constructor({ name, description, userDescription, ...rest }: ToolInput) { + super(rest); + this.name = name; + this.description = description; + this.userDescription = userDescription; + } +} + +export type ToolInput = ProjectScopedEntityInput & + Pick & + Partial>; + +export type AnyTool = ApiTool | CodeInterpreterTool | FunctionTool; diff --git a/src/tools/tools.module.ts b/src/tools/tools.module.ts new file mode 100644 index 0000000..fd1eb50 --- /dev/null +++ b/src/tools/tools.module.ts @@ -0,0 +1,123 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FastifyPluginAsyncJsonSchemaToTs } from '@fastify/type-provider-json-schema-to-ts'; +import { StatusCodes } from 'http-status-codes'; + +import { createTool, deleteTool, readTool, listTools, updateTool } from './tools.service.js'; +import { + ToolCreateBody, + toolCreateBodySchema, + toolCreateResponseSchema +} from './dtos/tool-create.js'; +import { + ToolUpdateBody, + ToolUpdateParams, + toolUpdateBodySchema, + toolUpdateParamsSchema, + toolUpdateResponseSchema +} from './dtos/tool-update.js'; +import { + ToolsListQuery, + toolsListQuerySchema, + toolsListResponseSchema +} from './dtos/tools-list.js'; +import { ToolReadParams, toolReadParamsSchema, toolReadResponseSchema } from './dtos/tool-read.js'; +import { + ToolDeleteParams, + toolDeleteParamsSchema, + toolDeleteResponseSchema +} from './dtos/tool-delete.js'; + +import { Tag } from '@/swagger.js'; + +export const toolsModule: FastifyPluginAsyncJsonSchemaToTs = async (app) => { + app.post<{ Body: ToolCreateBody }>( + '/tools', + { + preHandler: app.auth(), + schema: { + body: toolCreateBodySchema, + response: { + [StatusCodes.OK]: toolCreateResponseSchema + }, + tags: [Tag.BEE_API] + } + }, + async (req) => createTool(req.body) + ); + + app.post<{ Body: ToolUpdateBody; Params: ToolUpdateParams }>( + '/tools/:tool_id', + { + preHandler: app.auth(), + schema: { + body: toolUpdateBodySchema, + params: toolUpdateParamsSchema, + response: { + [StatusCodes.OK]: toolUpdateResponseSchema + }, + tags: [Tag.BEE_API] + } + }, + async (req) => updateTool({ ...req.body, ...req.params }) + ); + + app.get<{ Querystring: ToolsListQuery }>( + '/tools', + { + preHandler: app.auth(), + schema: { + querystring: toolsListQuerySchema, + response: { + [StatusCodes.OK]: toolsListResponseSchema + }, + tags: [Tag.BEE_API] + } + }, + async (req) => listTools(req.query) + ); + + app.get<{ Params: ToolReadParams }>( + '/tools/:tool_id', + { + preHandler: app.auth(), + schema: { + params: toolReadParamsSchema, + response: { + [StatusCodes.OK]: toolReadResponseSchema + }, + tags: [Tag.BEE_API] + } + }, + async (req) => readTool(req.params) + ); + + app.delete<{ Params: ToolDeleteParams }>( + '/tools/:tool_id', + { + preHandler: app.auth(), + schema: { + params: toolDeleteParamsSchema, + response: { + [StatusCodes.OK]: toolDeleteResponseSchema + }, + tags: [Tag.BEE_API] + } + }, + async (req) => deleteTool(req.params) + ); +}; diff --git a/src/tools/tools.service.ts b/src/tools/tools.service.ts new file mode 100644 index 0000000..8a7973a --- /dev/null +++ b/src/tools/tools.service.ts @@ -0,0 +1,774 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Loaded, ref } from '@mikro-orm/core'; +import { CustomTool, CustomToolCreateError } from 'bee-agent-framework/tools/custom'; +import dayjs from 'dayjs'; +import mime from 'mime/lite'; +import { WikipediaTool } from 'bee-agent-framework/tools/search/wikipedia'; +import { Tool as FrameworkTool } from 'bee-agent-framework/tools/base'; +import { ZodTypeAny } from 'zod'; +import { zodToJsonSchema } from 'zod-to-json-schema'; +import { drop, dropWhile, groupBy, pipe, prop, sortBy, take, takeWhile } from 'remeda'; +import { OpenMeteoTool } from 'bee-agent-framework/tools/weather/openMeteo'; +import { ArXivTool } from 'bee-agent-framework/tools/arxiv'; +import { PythonTool } from 'bee-agent-framework/tools/python/python'; +import { parse } from 'yaml'; + +import { Tool as ToolDto } from './dtos/tool.js'; +import { AnyTool, Tool, ToolExecutor, ToolType } from './entities/tool/tool.entity.js'; +import { ToolReadParams, ToolReadResponse } from './dtos/tool-read.js'; +import { ToolsListQuery, ToolsListResponse } from './dtos/tools-list.js'; +import { ToolCreateBody, ToolCreateResponse } from './dtos/tool-create.js'; +import { ToolUpdateBody, ToolUpdateParams, ToolUpdateResponse } from './dtos/tool-update.js'; +import { ToolDeleteParams, ToolDeleteResponse } from './dtos/tool-delete.js'; +import { ToolCall } from './dtos/tool-call.js'; +import { AnyToolCall } from './entities/tool-calls/tool-call.entity.js'; +import { ToolCallDelta } from './dtos/tool-call-delta.js'; +import { CodeInterpreterUsage } from './entities/tool-usages/code-interpreter-usage.entity.js'; +import { FileSearchUsage } from './entities/tool-usages/file-search-usage.entity.js'; +import { FunctionUsage } from './entities/tool-usages/function-usage.entity.js'; +import { UserUsage } from './entities/tool-usages/user-usage.entity.js'; +import { ToolUsage } from './dtos/tools-usage.js'; +import { AnyToolUsage } from './entities/tool-usages/tool-usage.entity.js'; +import { SystemUsage } from './entities/tool-usages/system-usage.entity.js'; +import { AnyToolResource } from './entities/tool-resources/tool-resource.entity.js'; +import { ToolResources } from './dtos/tool-resources.js'; +import { CodeInterpreterResource } from './entities/tool-resources/code-interpreter-resource.entity.js'; +import { SystemTools } from './entities/tool-calls/system-call.entity.js'; +import { CodeInterpreterTool } from './entities/tool/code-interpreter-tool.entity.js'; +import { ApiTool } from './entities/tool/api-tool.entity.js'; +import { FunctionTool } from './entities/tool/function-tool.entity.js'; +import { UserResource } from './entities/tool-resources/user-resource.entity.js'; +import { SystemResource } from './entities/tool-resources/system-resource.entity.js'; + +import { ORM } from '@/database.js'; +import { APIError, APIErrorCode } from '@/errors/error.entity.js'; +import { BEE_CODE_INTERPRETER_URL } from '@/config.js'; +import { createDeleteResponse } from '@/utils/delete.js'; +import { File, FilePurpose } from '@/files/entities/file.entity.js'; +import { FileContainer } from '@/files/entities/files-container.entity.js'; +import { FileSearchResource } from '@/tools/entities/tool-resources/file-search-resources.entity.js'; +import { VectorStore } from '@/vector-stores/entities/vector-store.entity.js'; +import { VECTOR_STORE_DEFAULT_MAX_NUM_RESULTS } from '@/vector-stores/constants.js'; +import { FileSearchTool } from '@/runs/execution/tools/file-search-tool.js'; +import { getUpdatedValue } from '@/utils/update.js'; +import { createPythonStorage } from '@/runs/execution/tools/python-tool-storage.js'; +import encrypt from '@/utils/crypto/encrypt.js'; +import { createCodeInterpreterConnectionOptions } from '@/runs/execution/tools/helpers.js'; +import { ReadFileTool } from '@/runs/execution/tools/read-file-tool.js'; +import { snakeToCamel } from '@/utils/strings.js'; +import { createSearchTool } from '@/runs/execution/tools/search-tool'; + +type SystemTool = Pick & { + type: ToolType; + id: string; + createdAt: Date; + isExternal: boolean; + userDescription?: string; +}; + +export function toToolCallDto(toolCall: Loaded): ToolCall { + switch (toolCall.type) { + case ToolType.CODE_INTERPRETER: + return { + id: toolCall.id, + type: ToolType.CODE_INTERPRETER, + [ToolType.CODE_INTERPRETER]: { + input: toolCall.input, + outputs: [ + ...(toolCall.logs?.map((log) => ({ type: 'logs', logs: log }) as const) ?? []), + ...(toolCall.fileContainers + ?.map((container) => container as Loaded) + .map(({ file }) => { + if (mime.getType(file.$.filename)?.startsWith('image')) { + return { type: 'image', image: { file_id: file.id } } as const; + } else { + return { type: 'resource', resource: { file_id: file.id } } as const; + } + }) ?? []) + ] + } + }; + case ToolType.FILE_SEARCH: + return { + id: toolCall.id, + type: ToolType.FILE_SEARCH, + [ToolType.FILE_SEARCH]: { + input: toolCall.input, + output: toolCall.results + } + }; + case ToolType.FUNCTION: + return { + id: toolCall.id, + type: ToolType.FUNCTION, + [ToolType.FUNCTION]: { + name: toolCall.name, + arguments: toolCall.arguments, + output: toolCall.output ?? null + } + }; + case ToolType.USER: + return { + id: toolCall.id, + type: ToolType.USER, + [ToolType.USER]: { + tool: { + id: toolCall.tool.id + }, + arguments: toolCall.arguments ?? null, + output: toolCall.output ?? null + } + }; + case ToolType.SYSTEM: + return { + id: toolCall.id, + type: ToolType.SYSTEM, + [ToolType.SYSTEM]: { + id: toolCall.toolId, + input: toolCall.input, + output: toolCall.output + } + }; + } +} + +export function toToolCallDeltaDto( + toolCall: Loaded, + index: number +): ToolCallDelta { + switch (toolCall.type) { + case ToolType.CODE_INTERPRETER: { + const logs = + toolCall.logs?.map((log, index) => ({ index, type: 'logs', logs: log }) as const) ?? []; + const outputs = + toolCall.fileContainers + ?.map((container) => container as Loaded) + .map(({ file }, index) => { + if (mime.getType(file.$.filename)?.startsWith('image')) { + return { + index: index + logs.length, + type: 'image', + image: { file_id: file.id } + } as const; + } else { + return { + index: index + logs.length, + type: 'resource', + resource: { file_id: file.id } + } as const; + } + }) ?? []; + return { + index, + id: toolCall.id, + type: ToolType.CODE_INTERPRETER, + [ToolType.CODE_INTERPRETER]: { + input: toolCall.input, + outputs: [...logs, ...outputs] + } + }; + } + case ToolType.FILE_SEARCH: + return { index, id: toolCall.id, type: ToolType.FILE_SEARCH }; + case ToolType.FUNCTION: + return { + index, + id: toolCall.id, + type: ToolType.FUNCTION, + [ToolType.FUNCTION]: { + name: toolCall.name, + arguments: toolCall.arguments, + output: toolCall.output ?? null + } + }; + case ToolType.SYSTEM: + return { + index, + id: toolCall.id, + type: ToolType.SYSTEM, + [ToolType.SYSTEM]: { + id: toolCall.toolId, + input: toolCall.input, + output: toolCall.output + } + }; + case ToolType.USER: + return { + index, + id: toolCall.id, + type: ToolType.USER, + [ToolType.USER]: { + tool: { + id: toolCall.tool.id + }, + arguments: toolCall.arguments ?? null, + output: toolCall.output ?? null + } + }; + } +} + +export function toDto(tool: AnyTool | SystemTool): ToolDto { + if (tool instanceof Tool) { + return { + id: tool.id, + object: 'tool', + type: tool.type, + name: tool.name, + is_external: true, + created_at: dayjs(tool.createdAt).unix(), + user_description: tool.userDescription ?? null, + metadata: tool.metadata ?? {}, + source_code: tool.executor === ToolExecutor.CODE_INTERPRETER ? tool.sourceCode : null, + json_schema: + tool.executor === ToolExecutor.CODE_INTERPRETER + ? JSON.stringify(tool.jsonSchema) + : tool.executor === ToolExecutor.FUNCTION + ? JSON.stringify(tool.parameters) + : null, + open_api_schema: tool.executor === ToolExecutor.API ? tool.openApiSchema : null, + description: tool.description + }; + } else { + return { + id: tool.id, + object: 'tool', + type: tool.type, + name: tool.name, + is_external: tool.isExternal, + created_at: dayjs(tool.createdAt).unix(), + user_description: tool.userDescription ?? null, + metadata: {}, + json_schema: JSON.stringify( + '_def' in tool.inputSchema() + ? zodToJsonSchema(tool.inputSchema() as ZodTypeAny) + : tool.inputSchema() + ), + source_code: '', + description: tool.description, + open_api_schema: null + }; + } +} + +export function toToolUsageDto(toolUsage: AnyToolUsage): ToolUsage { + switch (toolUsage.type) { + case ToolType.CODE_INTERPRETER: + return { + type: ToolType.CODE_INTERPRETER + }; + case ToolType.FILE_SEARCH: + return { + type: ToolType.FILE_SEARCH, + file_search: { max_num_results: toolUsage.maxNumResults } + }; + case ToolType.FUNCTION: + return { + type: ToolType.FUNCTION, + function: { + name: toolUsage.name, + description: toolUsage.description, + parameters: (toolUsage.parameters as any) ?? null + } + }; + case ToolType.SYSTEM: + return { + type: ToolType.SYSTEM, + [ToolType.SYSTEM]: { + id: toolUsage.toolId + } + }; + case ToolType.USER: + return { + type: ToolType.USER, + [ToolType.USER]: { + tool: { + id: toolUsage.tool.id + } + } + }; + } +} + +export function createToolUsage(toolUsage: ToolUsage): AnyToolUsage { + switch (toolUsage.type) { + case ToolType.CODE_INTERPRETER: + return new CodeInterpreterUsage(); + case ToolType.FILE_SEARCH: + return new FileSearchUsage({ + maxNumResults: + toolUsage.file_search?.max_num_results ?? VECTOR_STORE_DEFAULT_MAX_NUM_RESULTS + }); + case ToolType.FUNCTION: + return new FunctionUsage(toolUsage.function); + case ToolType.SYSTEM: + return new SystemUsage({ + toolId: toolUsage.system.id, + config: toolUsage.system[toolUsage.system.id] + }); + case ToolType.USER: + return new UserUsage({ + tool: ORM.em.getRepository(Tool).getReference(toolUsage.user.tool.id, { wrapped: true }) + }); + } +} + +export function toToolResourcesDto(toolResources?: AnyToolResource[]): ToolResources { + if (!toolResources) return null; + + const resources: ToolResources = {}; + + const codeInterpreterResources = toolResources.filter( + (resource): resource is CodeInterpreterResource => resource.type === ToolType.CODE_INTERPRETER + ); + if (codeInterpreterResources) { + resources[ToolType.CODE_INTERPRETER] = { + file_ids: codeInterpreterResources.flatMap((resource) => + resource.fileContainers.map((file) => file.file.id) + ) + }; + } + + const userResources = toolResources.filter( + (resource): resource is UserResource => resource.type === ToolType.USER + ); + if (userResources) { + Object.entries(groupBy(userResources, (r) => r.tool.id)).map(([toolId, toolResources]) => { + resources[toolId] = { + file_ids: toolResources.flatMap((resource) => + resource.fileContainers.map((file) => file.file.id) + ) + }; + }); + } + + const systemResources = toolResources.filter( + (resource): resource is SystemResource => resource.type === ToolType.SYSTEM + ); + if (systemResources) { + Object.entries(groupBy(systemResources, (r) => r.toolId)).map(([toolId, toolResources]) => { + resources[toolId] = { + file_ids: toolResources.flatMap((resource) => + resource.fileContainers.map((file) => file.file.id) + ) + }; + }); + } + + const fileSearchResources = toolResources.filter( + (resource): resource is FileSearchResource => resource.type === ToolType.FILE_SEARCH + ); + if (fileSearchResources) { + resources[ToolType.FILE_SEARCH] = { + vector_store_ids: fileSearchResources.flatMap((resource) => + resource.vectorStoreContainers.map((container) => container.vectorStore.id) + ) + }; + } + + return resources; +} + +export async function createToolResources( + toolResources: ToolResources | undefined +): Promise { + if (!toolResources) return; + + const resources: AnyToolResource[] = []; + if (toolResources.code_interpreter) { + const files = await ORM.em.getRepository(File).find({ + id: { $in: toolResources.code_interpreter.file_ids }, + purpose: { $in: [FilePurpose.ASSISTANTS, FilePurpose.ASSISTANTS_OUTPUT] } + }); + if (files.length !== toolResources.code_interpreter.file_ids.length) + throw new APIError({ + message: 'Not all files exist or have the right purpose', + code: APIErrorCode.INVALID_INPUT + }); + resources.push(new CodeInterpreterResource({ files })); + } + await Promise.all( + Object.entries(toolResources) + .filter(([resource]) => resource !== 'code_interpreter' && resource !== 'file_search') + .map(async ([toolId, resource]) => { + const fileIds: string[] = (resource as any).file_ids; + const files = await ORM.em.getRepository(File).find({ + id: { $in: fileIds }, + purpose: { $in: [FilePurpose.ASSISTANTS, FilePurpose.ASSISTANTS_OUTPUT] } + }); + if (files.length !== fileIds.length) + throw new APIError({ + message: 'Not all files exist or have the right purpose', + code: APIErrorCode.INVALID_INPUT + }); + if (!Object.keys(SystemTools).includes(toolId.toUpperCase())) { + const userTool = await ORM.em.getRepository(Tool).findOne({ id: toolId }); + if (!userTool) { + throw new APIError({ + message: 'Tool not found', + code: APIErrorCode.INVALID_INPUT + }); + } + resources.push(new UserResource({ tool: ref(userTool), files })); + } else { + resources.push(new SystemResource({ toolId, files })); + } + }) + ); + if (toolResources.file_search) { + const vectorStores = await ORM.em.getRepository(VectorStore).find({ + id: { $in: toolResources.file_search.vector_store_ids } + }); + if (vectorStores.length !== toolResources.file_search.vector_store_ids?.length) + throw new APIError({ + message: 'Not all vector stores exist', + code: APIErrorCode.INVALID_INPUT + }); + if (vectorStores.some((vectorStore) => vectorStore.expired)) { + throw new APIError({ + message: 'Some of the vector stores are expired', + code: APIErrorCode.INVALID_INPUT + }); + } + resources.push(new FileSearchResource({ vectorStores })); + } + return resources; +} + +export async function listTools({ + limit, + after, + before, + order, + order_by, + type, + search +}: ToolsListQuery): Promise { + const arXivTool = new ArXivTool(); + const searchTool = createSearchTool(); + const wikipediaTool = new WikipediaTool(); + const weatherTool = new OpenMeteoTool(); + const pythonTool = BEE_CODE_INTERPRETER_URL + ? new PythonTool({ + codeInterpreter: { url: BEE_CODE_INTERPRETER_URL }, + storage: createPythonStorage([], null) + }) + : null; + const fileSearch = new FileSearchTool({ vectorStores: [], maxNumResults: 0 }); + const readFile = new ReadFileTool({ files: [], fileSize: 0 }); + + const systemTools: SystemTool[] = + !type || type.includes(ToolType.SYSTEM) + ? [ + { + type: ToolType.SYSTEM, + id: SystemTools.WEB_SEARCH, + createdAt: new Date('2024-07-24'), + ...searchTool, + inputSchema: searchTool.inputSchema, + isExternal: true, + userDescription: 'Retrieve real-time search results from across the internet.' + }, + { + type: ToolType.SYSTEM, + id: SystemTools.WIKIPEDIA, + createdAt: new Date('2024-07-24'), + ...wikipediaTool, + inputSchema: wikipediaTool.inputSchema, + isExternal: true, + userDescription: + 'Retrieve detailed information from Wikipedia.org on a wide range of topics.' + }, + { + type: ToolType.SYSTEM, + id: SystemTools.WEATHER, + createdAt: new Date('2024-07-25'), + ...weatherTool, + inputSchema: weatherTool.inputSchema, + isExternal: true, + userDescription: + 'Get real-time weather forecasts for up to 16 days and past data for 30 days.' + }, + { + type: ToolType.SYSTEM, + id: SystemTools.ARXIV, + createdAt: new Date('2024-07-25'), + ...arXivTool, + inputSchema: arXivTool.inputSchema, + isExternal: true, + userDescription: + 'Retrieve abstracts of research articles published on ArXiv.org, along with their titles, authors, publication dates, and categories.' + }, + { + type: ToolType.SYSTEM, + id: 'read_file', + createdAt: new Date('2024-10-02'), + ...readFile, + inputSchema: readFile.inputSchema, + isExternal: false, + userDescription: 'Read and interpret basic files.' + } + ] + : []; + + if (!type || type.includes(ToolType.FUNCTION)) { + systemTools.push({ + type: ToolType.FUNCTION, + id: 'function', + createdAt: new Date('2024-07-31'), + description: 'Function to be executed by the user with parameters supplied by the assistant', + name: 'Function', + inputSchema: () => ({}), + isExternal: false + }); + } + + if (!type || type.includes(ToolType.FILE_SEARCH)) { + systemTools.push({ + type: ToolType.FILE_SEARCH, + id: 'file_search', + createdAt: new Date('2024-07-31'), + ...fileSearch, + inputSchema: fileSearch.inputSchema, + isExternal: false, + userDescription: 'Access and interpret file content by using advanced search techniques.' + }); + } + if (pythonTool && (!type || type.includes(ToolType.CODE_INTERPRETER))) { + systemTools.push({ + type: ToolType.CODE_INTERPRETER, + id: 'code_interpreter', + createdAt: new Date('2024-07-01'), + ...pythonTool, + inputSchema: pythonTool.inputSchema, + isExternal: true, + userDescription: + 'Execute Python code for various tasks, including data analysis, file processing, and visualizations.' + }); + } + + const userTools = + !type || type.includes(ToolType.USER) ? await ORM.em.getRepository(Tool).find({}) : []; + const tools = [...systemTools, ...userTools].filter((tool) => { + if (search) { + const regexp = new RegExp(`.*${search}.*`, 'gi'); + return regexp.test(tool.name) || regexp.test(tool.description); + } + return true; + }); + + const sortedTools = sortBy( + tools, + [(data: Tool) => prop(data, snakeToCamel(order_by)).toString().toLowerCase(), order], + [prop('createdAt'), order], + [prop('id'), order] + ); + + const trimmedTools = pipe( + sortedTools, + dropWhile((tool) => (after ? tool.id !== after : false)), + drop(after ? 1 : 0), + takeWhile((tool) => (before ? tool.id !== before : true)), + take(limit) + ); + + return { + data: trimmedTools.map(toDto), + first_id: trimmedTools.at(0)?.id ?? null, + last_id: trimmedTools.at(-1)?.id ?? null, + has_more: trimmedTools.length > 0 && sortedTools.at(-1)?.id !== trimmedTools.at(-1)?.id, + total_count: sortedTools.length + }; +} + +async function createCodeInterpreterTool( + body: Extract +): Promise { + if (!BEE_CODE_INTERPRETER_URL) { + throw new APIError({ + message: `Code interpreter url is not defined`, + code: APIErrorCode.SERVICE_UNAVAILABLE + }); + } + try { + const customTool = await CustomTool.fromSourceCode( + createCodeInterpreterConnectionOptions(), + body.source_code + ); + + const tool = new CodeInterpreterTool({ + name: body.name || customTool.name, + sourceCode: body.source_code, + jsonSchema: customTool.inputSchema(), + description: customTool.description, + metadata: body.metadata, + userDescription: body.user_description + }); + + await ORM.em.persistAndFlush(tool); + + return toDto(tool); + } catch (err) { + if (err instanceof CustomToolCreateError) { + throw new APIError({ + message: err.message, + code: APIErrorCode.INVALID_INPUT + }); + } + if (err.constructor.name === 'ConnectError') { + throw new APIError({ + message: 'Service is unavailable', + code: APIErrorCode.INTERNAL_SERVER_ERROR + }); + } + throw err; + } +} + +async function createOpenApiTool( + body: Extract +): Promise { + const schema = parse(body.open_api_schema); + const tool = new ApiTool({ + openApiSchema: body.open_api_schema, + name: schema.info.title, + description: schema.info.description, + apiKey: body.api_key ? encrypt(body.api_key) : undefined, + metadata: body.metadata, + userDescription: body.user_description + }); + + await ORM.em.persistAndFlush(tool); + + return toDto(tool); +} + +async function createFunctionTool( + body: Extract +): Promise { + const tool = new FunctionTool({ + name: body.name, + description: body.description ?? '', + parameters: body.parameters, + metadata: body.metadata, + userDescription: body.user_description + }); + + await ORM.em.persistAndFlush(tool); + + return toDto(tool); +} + +export async function createTool(body: ToolCreateBody): Promise { + if ('source_code' in body) { + return createCodeInterpreterTool(body); + } else if ('open_api_schema' in body) { + return createOpenApiTool(body); + } else if ('parameters' in body) { + return createFunctionTool(body); + } + throw new APIError({ + message: `Unsupported tools`, + code: APIErrorCode.INVALID_INPUT + }); +} + +export async function updateTool({ + tool_id, + ...body +}: ToolUpdateBody & ToolUpdateParams): Promise { + const tool = await ORM.em.getRepository(Tool).findOneOrFail({ id: tool_id }); + + tool.name = getUpdatedValue(body.name, tool.name); + tool.description = getUpdatedValue(body.description, tool.description); + tool.metadata = getUpdatedValue(body.metadata, tool.metadata); + tool.userDescription = getUpdatedValue(body.user_description, tool.userDescription); + + if ('source_code' in body) { + if (!('sourceCode' in tool)) { + throw new APIError({ + message: 'Can not change tool executor', + code: APIErrorCode.INVALID_INPUT + }); + } + + if (body.source_code) { + try { + if (!BEE_CODE_INTERPRETER_URL) { + throw new APIError({ + message: `Code interpreter url is not defined`, + code: APIErrorCode.SERVICE_UNAVAILABLE + }); + } + tool.sourceCode = body.source_code; + const newCustomTool = await CustomTool.fromSourceCode( + createCodeInterpreterConnectionOptions(), + body.source_code + ); + tool.jsonSchema = newCustomTool.inputSchema(); + tool.description = newCustomTool.description; + } catch (err) { + if (err instanceof CustomToolCreateError) { + throw new APIError({ + message: err.message, + code: APIErrorCode.INVALID_INPUT + }); + } + throw err; + } + } + } + + if ('open_api_schema' in body) { + if (!('openApiSchema' in tool)) { + throw new APIError({ + message: 'Can not change tool executor', + code: APIErrorCode.INVALID_INPUT + }); + } + tool.openApiSchema = getUpdatedValue(body.open_api_schema, tool.openApiSchema); + } + + if ('parameters' in body) { + if (!('parameters' in tool)) { + throw new APIError({ + message: 'Can not change tool executor', + code: APIErrorCode.INVALID_INPUT + }); + } + tool.parameters = getUpdatedValue(body.parameters, tool.parameters); + } + + await ORM.em.flush(); + + return toDto(tool); +} + +export async function readTool({ tool_id }: ToolReadParams): Promise { + const tool = await ORM.em.getRepository(Tool).findOneOrFail({ id: tool_id }); + return toDto(tool); +} + +export async function deleteTool({ tool_id }: ToolDeleteParams): Promise { + const tool = await ORM.em.getRepository(Tool).findOneOrFail({ id: tool_id }); + + tool.delete(); + await ORM.em.flush(); + + return createDeleteResponse(tool_id, 'tool'); +} diff --git a/src/ui/auth-server.ts b/src/ui/auth-server.ts new file mode 100644 index 0000000..d06ad4e --- /dev/null +++ b/src/ui/auth-server.ts @@ -0,0 +1,48 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { JsonSchemaToTsProvider } from '@fastify/type-provider-json-schema-to-ts'; +import { fastify } from 'fastify'; + +import { fastifyLogger } from '@/logger'; +import { AUTH_SERVER_PORT } from '@/config'; + +const startAuthServer = async () => { + if (!AUTH_SERVER_PORT) return; + + const app = fastify({ + logger: fastifyLogger + }).withTypeProvider(); + + try { + app.get('/.well-known/openid-configuration', async () => { + return { + issuer: 'https://localhost', + jwks_uri: new URL(`http://localhost:${AUTH_SERVER_PORT}/jwks`) + }; + }); + + const { default: data } = await import('./jwks.json', { assert: { type: 'json' } }); + app.get('/jwks', async () => { + return data; + }); + + await app.listen({ port: AUTH_SERVER_PORT, host: 'localhost' }); + } catch (err) { + app.log.warn({ err }, 'Failed to start auth server!'); + } +}; +await startAuthServer(); diff --git a/src/ui/dtos/last_assistant.dto.ts b/src/ui/dtos/last_assistant.dto.ts new file mode 100644 index 0000000..ed63963 --- /dev/null +++ b/src/ui/dtos/last_assistant.dto.ts @@ -0,0 +1,25 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { assistantSchema } from '@/assistants/dtos/assistant.js'; + +export const lastAssistantsSchema = { + type: 'array', + items: assistantSchema +} as const satisfies JSONSchema; +export type LastAssistants = FromSchema; diff --git a/src/ui/jwks.json b/src/ui/jwks.json new file mode 100644 index 0000000..5468d62 --- /dev/null +++ b/src/ui/jwks.json @@ -0,0 +1,13 @@ +{ + "keys": [ + { + "kty": "RSA", + "n": "wg6CJ90ELKikVpE9kfduCL-7g8GxMGISzIRgJ3fZ1lVClhMRLKixCxmm_gkZEfr9O24D16xjB6f1GZYAeIviIfZWIRT-tACrfJQq5fEGtyIPNbfmP6Abwe4weeRXHCNl6Z7m5ee2By8vfeRW9ebOEv81m8tkTvQ5nfzqJpe_ndHgonZ2rO-wDWLYF59l4IsyhERyD6T2Zjel7jkwAoit-dMyCg4qaBzTlIbIbLEF2Xpp2TMJrarT5P61ZJr-en9ceT0Ih4xCEU27qZmvdiMQa9H1ykU4orARjhYG-6kd4xJ9HJbY1JgQYQCtUONEvUmajIxIbPp3DtJ6IkB1cg74fw", + "e": "AQAB", + "ext": true, + "kid": "99810cf0f72de0891faaabf67b", + "alg": "RS256", + "use": "sig" + } + ] +} \ No newline at end of file diff --git a/src/ui/jwt.key b/src/ui/jwt.key new file mode 100644 index 0000000..facc747 --- /dev/null +++ b/src/ui/jwt.key @@ -0,0 +1 @@ +eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ0ZXN0IiwicHJlZmVycmVkX3VzZXJuYW1lIjoiVGVzdCBVc2VyIiwiZW1haWwiOiJ0ZXN0QGVtYWlsLmNvbSIsImlhdCI6MTUxNjIzOTAyMiwiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3QiLCJhdWQiOiJiZWUtdGVzdCJ9.vwkGnl7lBbzJYk6BtoW3VoA3mnNJVI-nDQU8aK7zOH-rkf2pn5cn6CKwpq7enDInIXro8WtBLNZP8Nr8GQIZKahICuP3YrPRmzv7YIW8LuXKnx1hycg5OAtj0OtQi5FYwwCxTYW9pBF2it7XwQSBcW7yYsOrvgs7jVhThCOsavX0YiAROxZIhk1idZT4Pl3egfUI_dy9iBxcn7xocTnos-94wqJNt8oCVgB8ynj75yJFHJbiQ-9Tym_V3LcMHoEyv67Jzie8KugCgdpuF6EbQqcyfYJ83q5jJpR2LiuWMuGsNSbjjDY-f1vCSMo9L9-R8KFrDylT_BzLvRBswOzW7A \ No newline at end of file diff --git a/src/ui/ui.module.ts b/src/ui/ui.module.ts new file mode 100644 index 0000000..8cd76bc --- /dev/null +++ b/src/ui/ui.module.ts @@ -0,0 +1,39 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FastifyPluginAsyncJsonSchemaToTs } from '@fastify/type-provider-json-schema-to-ts'; +import { StatusCodes } from 'http-status-codes'; + +import { lastAssistants } from './ui.service.js'; +import { lastAssistantsSchema } from './dtos/last_assistant.dto.js'; + +import { Tag } from '@/swagger.js'; + +export const uiModule: FastifyPluginAsyncJsonSchemaToTs = async (app) => { + app.get( + '/ui/last_assistants', + { + schema: { + response: { [StatusCodes.OK]: lastAssistantsSchema }, + tags: [Tag.BEE_API] + }, + preHandler: app.auth() + }, + async () => { + return lastAssistants(); + } + ); +}; diff --git a/src/ui/ui.service.ts b/src/ui/ui.service.ts new file mode 100644 index 0000000..5da43bc --- /dev/null +++ b/src/ui/ui.service.ts @@ -0,0 +1,51 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { LastAssistants } from './dtos/last_assistant.dto.js'; + +import { ORM } from '@/database.js'; +import { Assistant } from '@/assistants/assistant.entity.js'; +import { toDto } from '@/assistants/assistants.service.js'; +import { getProjectPrincipal } from '@/administration/helpers.js'; + +export async function lastAssistants(): Promise { + const projectPrincipal = getProjectPrincipal(); + const assistants = await ORM.em.aggregate(Assistant, [ + { $match: { project: projectPrincipal.project.id, deletedAt: { $exists: false } } }, + { + $lookup: { + from: 'run', + localField: '_id', + pipeline: [ + { $match: { createdBy: projectPrincipal.id } }, + { $sort: { createdAt: -1 } }, + { $limit: 1 } + ], + foreignField: 'assistant', + as: 'runs' + } + }, + { $set: { lastRun: { $arrayElemAt: ['$runs', 0] } } }, + { $match: { lastRun: { $ne: undefined } } }, + { + $sort: { 'lastRun.createdAt': -1 } + }, + { $limit: 4 }, + { $set: { id: '$_id' } } + ]); + + return assistants.map(toDto); +} diff --git a/src/users/dtos/user-create.ts b/src/users/dtos/user-create.ts new file mode 100644 index 0000000..2708b34 --- /dev/null +++ b/src/users/dtos/user-create.ts @@ -0,0 +1,30 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { userSchema } from './user.js'; + +import { metadataSchema } from '@/schema.js'; + +export const userCreateBodySchema = { + type: 'object', + properties: { metadata: metadataSchema } +} as const satisfies JSONSchema; +export type UserCreateBody = FromSchema; + +export const userCreateResponseSchema = userSchema; +export type UserCreateResponse = FromSchema; diff --git a/src/users/dtos/user-read.ts b/src/users/dtos/user-read.ts new file mode 100644 index 0000000..bd63ee4 --- /dev/null +++ b/src/users/dtos/user-read.ts @@ -0,0 +1,22 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema } from 'json-schema-to-ts'; + +import { userSchema } from './user.js'; + +export const userReadResponseSchema = userSchema; +export type UserReadResponse = FromSchema; diff --git a/src/users/dtos/user-update.ts b/src/users/dtos/user-update.ts new file mode 100644 index 0000000..1158480 --- /dev/null +++ b/src/users/dtos/user-update.ts @@ -0,0 +1,30 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { userSchema } from './user.js'; + +import { metadataSchema } from '@/schema.js'; + +export const userUpdateBodySchema = { + type: 'object', + properties: { metadata: metadataSchema } +} as const satisfies JSONSchema; +export type UserUpdateBody = FromSchema; + +export const userUpdateResponseSchema = userSchema; +export type UserUpdateResponse = FromSchema; diff --git a/src/users/dtos/user.ts b/src/users/dtos/user.ts new file mode 100644 index 0000000..cf3fd94 --- /dev/null +++ b/src/users/dtos/user.ts @@ -0,0 +1,32 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { metadataSchema } from '@/schema.js'; + +export const userSchema = { + type: 'object', + required: ['id', 'object', 'name', 'email'], + properties: { + id: { type: 'string' }, + object: { const: 'user' }, + name: { type: 'string', nullable: true }, + email: { type: 'string', nullable: true }, + metadata: metadataSchema + } +} as const satisfies JSONSchema; +export type User = FromSchema; diff --git a/src/users/entities/user.entity.ts b/src/users/entities/user.entity.ts new file mode 100644 index 0000000..92748c9 --- /dev/null +++ b/src/users/entities/user.entity.ts @@ -0,0 +1,44 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Entity, Property } from '@mikro-orm/core'; + +import { BaseEntity, BaseEntityInput } from '@/common/base.entity.js'; + +@Entity() +export class User extends BaseEntity { + getIdPrefix(): string { + return 'user'; + } + + @Property({ unique: true }) + externalId: string; // Remove after all users have migrated + + @Property({ unique: true }) + email?: string; + + @Property() + name?: string; + + constructor({ externalId, email, name, ...rest }: UserInput) { + super(rest); + this.externalId = externalId; + this.email = email; + this.name = name; + } +} + +export type UserInput = BaseEntityInput & Pick; diff --git a/src/users/helpers.ts b/src/users/helpers.ts new file mode 100644 index 0000000..ec7a923 --- /dev/null +++ b/src/users/helpers.ts @@ -0,0 +1,25 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { requestContext } from '@fastify/request-context'; + +import { APIError, APIErrorCode } from '@/errors/error.entity'; + +export function getUser() { + const user = requestContext.get('user'); + if (!user) throw new APIError({ message: 'User not found', code: APIErrorCode.NOT_FOUND }); + return user; +} diff --git a/src/users/users.module.ts b/src/users/users.module.ts new file mode 100644 index 0000000..14760cd --- /dev/null +++ b/src/users/users.module.ts @@ -0,0 +1,81 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FastifyPluginAsyncJsonSchemaToTs } from '@fastify/type-provider-json-schema-to-ts'; +import { StatusCodes } from 'http-status-codes'; + +import { + UserCreateBody, + userCreateBodySchema, + userCreateResponseSchema +} from './dtos/user-create.js'; +import { userReadResponseSchema } from './dtos/user-read.js'; +import { createUser, readUser, updateUser } from './users.service.js'; +import { + UserUpdateBody, + userUpdateBodySchema, + userUpdateResponseSchema +} from './dtos/user-update.js'; + +import { getTrustedIdentity } from '@/auth/authentication.js'; +import { Tag } from '@/swagger.js'; +import { AuthSecret } from '@/auth/utils.js'; + +export const usersModule: FastifyPluginAsyncJsonSchemaToTs = async (app) => { + app.post<{ Body: UserCreateBody }>( + '/users', + { + schema: { + body: userCreateBodySchema, + response: { [StatusCodes.OK]: userCreateResponseSchema }, + tags: [Tag.BEE_API] + } + }, + async (req) => { + const identity = await getTrustedIdentity(req); + return createUser({ + ...req.body, + externalId: identity.sub, + email: identity.email, + name: identity.preferred_username + }); + } + ); + + app.put<{ Body: UserUpdateBody }>( + '/users', + { + schema: { + body: userUpdateBodySchema, + response: { [StatusCodes.OK]: userUpdateResponseSchema }, + tags: [Tag.BEE_API] + }, + preHandler: app.auth([AuthSecret.ACCESS_TOKEN]) + }, + async (req) => { + return updateUser(req.body); + } + ); + + app.get( + '/users', + { + schema: { response: { [StatusCodes.OK]: userReadResponseSchema }, tags: [Tag.BEE_API] }, + preHandler: app.auth() + }, + async () => readUser({}) + ); +}; diff --git a/src/users/users.service.ts b/src/users/users.service.ts new file mode 100644 index 0000000..e73e182 --- /dev/null +++ b/src/users/users.service.ts @@ -0,0 +1,100 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Loaded, ref } from '@mikro-orm/core'; +import { requestContext } from '@fastify/request-context'; + +import { UserReadResponse } from './dtos/user-read.js'; +import { UserCreateBody, UserCreateResponse } from './dtos/user-create.js'; +import { User, UserInput } from './entities/user.entity.js'; +import type { User as UserDto } from './dtos/user.js'; +import { UserUpdateBody, UserUpdateResponse } from './dtos/user-update.js'; +import { getUser } from './helpers.js'; + +import { ORM } from '@/database.js'; +import { getServiceLogger } from '@/logger.js'; +import { getUpdatedValue } from '@/utils/update.js'; +import { OrganizationUser } from '@/administration/entities/organization-user.entity.js'; +import { ProjectPrincipal } from '@/administration/entities/project-principal.entity.js'; +import { UserPrincipal } from '@/administration/entities/principals/user-principal.entity.js'; +import { ORGANIZATION_OWNER_ID_DEFAULT, PROJECT_ADMIN_ID_DEFAULT } from '@/config.js'; +import { OrganizationUserRole, ProjectRole } from '@/administration/entities/constants.js'; + +const getUserLogger = (userId: string) => getServiceLogger('user').child({ userId }); + +function toDto(user: Loaded): UserDto { + return { + id: user.id, + object: 'user', + external_id: user.externalId, + email: user.email ?? null, + name: user.name ?? null, + metadata: user.metadata + }; +} + +export async function createUser({ + externalId, + email, + name, + metadata +}: Pick & UserCreateBody): Promise { + const user = new User({ externalId, email, name, metadata }); + + const defaultOrgOwner = await ORM.em + .getRepository(OrganizationUser) + .findOneOrFail( + { id: ORGANIZATION_OWNER_ID_DEFAULT }, + { filters: { orgAdministrationAccess: false } } + ); + const defaultProjectAdmin = await ORM.em + .getRepository(ProjectPrincipal) + .findOneOrFail( + { id: PROJECT_ADMIN_ID_DEFAULT }, + { filters: { projectAdministrationAccess: false } } + ); + + // Become org owner + requestContext.set('organizationUser', defaultOrgOwner); + const orgUser = new OrganizationUser({ + user: ref(user), + role: OrganizationUserRole.MEMBER + }); + + // Become project admin + requestContext.set('projectPrincipal', defaultProjectAdmin); + const projectPrincipal = new ProjectPrincipal({ + principal: new UserPrincipal({ user: ref(orgUser) }), + role: ProjectRole.READER + }); + + await ORM.em.persistAndFlush([user, orgUser, projectPrincipal]); + getUserLogger(user.id).info({ externalId, metadata }, 'User created'); + return toDto(user); +} + +export async function readUser(_: unknown): Promise { + const user = getUser(); + return toDto(user); +} + +export async function updateUser({ metadata }: UserUpdateBody): Promise { + const user = getUser(); + user.metadata = getUpdatedValue(metadata, user.metadata); + await ORM.em.flush(); + getUserLogger(user.id).info({ metadata }, 'User updated'); + return toDto(user); +} diff --git a/src/utils/crypto/config.ts b/src/utils/crypto/config.ts new file mode 100644 index 0000000..c724d8e --- /dev/null +++ b/src/utils/crypto/config.ts @@ -0,0 +1,20 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export const CRYPTO_ALGORITHM = 'aes-256-cbc'; +export const CRYPTO_INPUT_ENCODING = 'utf8'; +export const CRYPTO_OUTPUT_ENCODING = 'hex'; +export const CRYPTO_IV_LENGTH = 16; diff --git a/src/utils/crypto/decrypt.ts b/src/utils/crypto/decrypt.ts new file mode 100644 index 0000000..729b4cd --- /dev/null +++ b/src/utils/crypto/decrypt.ts @@ -0,0 +1,38 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { createDecipheriv } from 'crypto'; + +import { + CRYPTO_ALGORITHM, + CRYPTO_INPUT_ENCODING, + CRYPTO_IV_LENGTH, + CRYPTO_OUTPUT_ENCODING +} from './config.js'; + +import { CRYPTO_CIPHER_KEY } from '@/config.js'; + +const decrypt = (input: string) => { + const encrypted = Buffer.from(input, CRYPTO_OUTPUT_ENCODING); + const iv = encrypted.subarray(0, CRYPTO_IV_LENGTH); + const text = encrypted.subarray(CRYPTO_IV_LENGTH); + + const decipher = createDecipheriv(CRYPTO_ALGORITHM, CRYPTO_CIPHER_KEY, iv); + const decrypted = Buffer.concat([decipher.update(text), decipher.final()]); + return decrypted.toString(CRYPTO_INPUT_ENCODING); +}; + +export default decrypt; diff --git a/src/utils/crypto/encrypt.ts b/src/utils/crypto/encrypt.ts new file mode 100644 index 0000000..0ba6d5e --- /dev/null +++ b/src/utils/crypto/encrypt.ts @@ -0,0 +1,39 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { createCipheriv, randomBytes } from 'crypto'; + +import { + CRYPTO_ALGORITHM, + CRYPTO_INPUT_ENCODING, + CRYPTO_IV_LENGTH, + CRYPTO_OUTPUT_ENCODING +} from './config.js'; + +import { CRYPTO_CIPHER_KEY } from '@/config.js'; + +const encrypt = (input: string) => { + const iv = randomBytes(CRYPTO_IV_LENGTH); + const cipher = createCipheriv(CRYPTO_ALGORITHM, CRYPTO_CIPHER_KEY, iv); + const encrypted = Buffer.concat([ + iv, + cipher.update(input, CRYPTO_INPUT_ENCODING), + cipher.final() + ]); + return encrypted.toString(CRYPTO_OUTPUT_ENCODING); +}; + +export default encrypt; diff --git a/src/utils/delete.ts b/src/utils/delete.ts new file mode 100644 index 0000000..55e05bc --- /dev/null +++ b/src/utils/delete.ts @@ -0,0 +1,23 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export function createDeleteResponse(id: string, object: T) { + return { + id, + object: `${object}.deleted` as const, + deleted: true + }; +} diff --git a/src/utils/id.ts b/src/utils/id.ts new file mode 100644 index 0000000..aeb123f --- /dev/null +++ b/src/utils/id.ts @@ -0,0 +1,21 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ObjectId } from '@mikro-orm/mongodb'; + +export function generatePrefixedObjectId(prefix: string) { + return `${prefix}_${new ObjectId().toHexString()}`; +} diff --git a/src/utils/jobs.ts b/src/utils/jobs.ts new file mode 100644 index 0000000..2251c1e --- /dev/null +++ b/src/utils/jobs.ts @@ -0,0 +1,48 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Loaded } from '@mikro-orm/core'; + +import { BaseEntity } from '@/common/base.entity.js'; +import { ORM } from '@/database.js'; +import { getLogger } from '@/logger.js'; + +const STATUS_POLL_INTERVAL = 5 * 1000; + +type HasCancelling = 'cancelling' extends T ? T : never; + +export function watchForCancellation< + EntityType extends BaseEntity & { status: HasCancelling } +>( + entityType: new (...args: any[]) => EntityType, + { id }: Loaded, + onCancel: () => void +) { + const check = async () => { + try { + const { status, deletedAt } = await ORM.em + .getRepository(entityType) + .findOneOrFail({ id }, { refresh: true, filters: { deleted: false } }); + + if (status === 'cancelling') onCancel(); + if (deletedAt) onCancel(); // We also cancel if the entity was deleted in the meantime + } catch (err) { + getLogger().error({ err }, 'Failed to check {entity} status'); + } + }; + const intervalId = setInterval(check, STATUS_POLL_INTERVAL); + return () => clearInterval(intervalId); +} diff --git a/src/utils/networking.ts b/src/utils/networking.ts new file mode 100644 index 0000000..2554d60 --- /dev/null +++ b/src/utils/networking.ts @@ -0,0 +1,28 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Socket } from 'node:net'; + +export function listenToSocketClose(socket: Socket, onClose: () => void) { + if (socket.destroyed) { + throw new Error('Socket already closed!'); + } + + socket.once('close', onClose); + return () => { + socket.removeListener('close', onClose); + }; +} diff --git a/src/utils/pagination.ts b/src/utils/pagination.ts new file mode 100644 index 0000000..75c17ad --- /dev/null +++ b/src/utils/pagination.ts @@ -0,0 +1,74 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { + Cursor, + EntityRepository, + FilterQuery, + FindByCursorOptions, + Loaded +} from '@mikro-orm/core'; +import { FromSchema } from 'json-schema-to-ts'; + +import { snakeToCamel } from './strings.js'; + +import { BaseEntity } from '@/common/base.entity.js'; +import { createPaginationQuerySchema, withPagination } from '@/schema.js'; + +type PaginatedParameters = FromSchema>; + +export async function getListCursor( + where: FilterQuery, + { + after, + before, + limit, + order, + order_by, + populate + }: PaginatedParameters & FindByCursorOptions, + repo: EntityRepository // TODO: better typing, +): Promise> { + const aftr = after ? await repo.findOneOrFail({ id: after }) : undefined; + const bfr = before ? await repo.findOneOrFail({ id: before }) : undefined; + const cursor = await repo.findByCursor(where, { + first: limit, + before: bfr && { [snakeToCamel(order_by)]: bfr[snakeToCamel(order_by) as keyof T], id: bfr.id }, + after: aftr && { + [snakeToCamel(order_by)]: aftr[snakeToCamel(order_by) as keyof T], + id: aftr.id + }, + orderBy: [{ [snakeToCamel(order_by)]: order }, { id: order }], + populate + }); + + return cursor; +} + +type PaginatedSchema = FromSchema>; + +export async function createPaginatedResponse( + cursor: Cursor, + toDto: (entity: Loaded) => U +) { + return { + data: await Promise.all(cursor.items.map(toDto)), + first_id: cursor.items.at(0)?.id ?? null, + last_id: cursor.items.at(-1)?.id ?? null, + has_more: cursor.hasNextPage, + total_count: cursor.totalCount + } satisfies PaginatedSchema; +} diff --git a/src/utils/streams.ts b/src/utils/streams.ts new file mode 100644 index 0000000..d9b185c --- /dev/null +++ b/src/utils/streams.ts @@ -0,0 +1,40 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Transform, TransformCallback, TransformOptions, Readable } from 'node:stream'; +import { Hash } from 'node:crypto'; + +export class PassthroughHash extends Transform { + public readonly hash: Hash; + + constructor({ hash, ...opts }: { hash: Hash } & TransformOptions) { + super(opts); + this.hash = hash; + } + + _transform(chunk: any, encoding: BufferEncoding, callback: TransformCallback) { + this.hash.update(chunk); + callback(null, chunk); + } +} + +export async function toBuffer(readable: Buffer | Readable) { + const chunks: any[] = []; + for await (const chunk of readable) { + chunks.push(chunk); + } + return Buffer.concat(chunks); +} diff --git a/src/utils/strings.ts b/src/utils/strings.ts new file mode 100644 index 0000000..8111fe4 --- /dev/null +++ b/src/utils/strings.ts @@ -0,0 +1,29 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export type SnakeToCamelCase = + Key extends `${infer FirstPart}_${infer FirstLetter}${infer LastPart}` + ? `${FirstPart}${Uppercase}${SnakeToCamelCase}` + : Key; + +export function snakeToCamel(str: S) { + return str + .replace(/[^a-zA-Z0-9]/g, '_') + .replace(/(_)+/g, '_') + .replace(/([_][a-zA-Z])/g, (group) => + group.toUpperCase().replace('_', '') + ) as SnakeToCamelCase; +} diff --git a/src/utils/update.ts b/src/utils/update.ts new file mode 100644 index 0000000..d3ecb02 --- /dev/null +++ b/src/utils/update.ts @@ -0,0 +1,25 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { isDefined } from 'remeda'; + +export function getUpdatedValue(value: T | null | undefined, currentValue: T): T; +export function getUpdatedValue( + value: T | null | undefined, + currentValue: T | undefined +): T | undefined { + return isDefined(value) ? (value ?? undefined) : currentValue; +} diff --git a/src/utils/uri.ts b/src/utils/uri.ts new file mode 100644 index 0000000..3d6c47e --- /dev/null +++ b/src/utils/uri.ts @@ -0,0 +1,26 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const URN_PREFIX = `urn:peri`; + +export const Resource = { + FILE: 'file' +} as const; +export type Resource = (typeof Resource)[keyof typeof Resource]; + +export function getResourceURN(resource: Resource, resourceId: string) { + return `${URN_PREFIX}:${resource}:${resourceId}` as const; +} diff --git a/src/vector-store-files/dtos/chunking-strategy.ts b/src/vector-store-files/dtos/chunking-strategy.ts new file mode 100644 index 0000000..2193190 --- /dev/null +++ b/src/vector-store-files/dtos/chunking-strategy.ts @@ -0,0 +1,63 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +export const autoChunkingStrategySchema = { + type: 'object', + title: 'Auto Chunking Strategy', + description: + 'The default strategy. This strategy currently uses a `max_chunk_size_tokens` of `400` and `chunk_overlap_tokens` of `200`.', + additionalProperties: false, + properties: { type: { type: 'string', description: 'Always `auto`.', enum: ['auto'] } }, + required: ['type'] +} as const satisfies JSONSchema; + +export const staticChunkingStrategySchema = { + type: 'object', + title: 'Static Chunking Strategy', + additionalProperties: false, + properties: { + type: { type: 'string', description: 'Always `static`.', enum: ['static'] }, + static: { + type: 'object', + additionalProperties: false, + properties: { + max_chunk_size_tokens: { + type: 'integer', + minimum: 100, + maximum: 512, // TODO: Too low, find a better embedding model + description: 'The maximum number of tokens in each chunk.' + }, + chunk_overlap_tokens: { + type: 'integer', + description: 'The number of tokens that overlap between chunks.' + } + }, + required: ['max_chunk_size_tokens', 'chunk_overlap_tokens'] + } + }, + required: ['type', 'static'] +} as const satisfies JSONSchema; + +export const chunkingStrategyRequestParamSchema = { + type: 'object', + description: + 'The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy.', + oneOf: [autoChunkingStrategySchema, staticChunkingStrategySchema] +} as const satisfies JSONSchema; + +export type ChunkingStrategyRequestParam = FromSchema; diff --git a/src/vector-store-files/dtos/vector-store-file-create.ts b/src/vector-store-files/dtos/vector-store-file-create.ts new file mode 100644 index 0000000..fa41893 --- /dev/null +++ b/src/vector-store-files/dtos/vector-store-file-create.ts @@ -0,0 +1,47 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { vectorStoreFileSchema } from './vector-store-file.js'; +import { chunkingStrategyRequestParamSchema } from './chunking-strategy.js'; + +export const vectorStoreFileCreateParamsSchema = { + type: 'object', + additionalProperties: false, + required: ['vector_store_id'], + properties: { vector_store_id: { type: 'string' } } +} as const satisfies JSONSchema; +export type VectorStoreFileCreateParams = FromSchema; + +export const vectorStoreFileCreateBodySchema = { + type: 'object', + additionalProperties: false, + properties: { + file_id: { + description: + 'A File ID that the vector store should use. Useful for tools like `file_search` that can access files.', + type: 'string' + }, + chunking_strategy: chunkingStrategyRequestParamSchema + }, + required: ['file_id'] +} as const satisfies JSONSchema; + +export type VectorStoreFileCreateBody = FromSchema; + +export const vectorStoreFileCreateResponseSchema = vectorStoreFileSchema; +export type VectorStoreFileCreateResponse = FromSchema; diff --git a/src/vector-store-files/dtos/vector-store-file-delete.ts b/src/vector-store-files/dtos/vector-store-file-delete.ts new file mode 100644 index 0000000..0b73303 --- /dev/null +++ b/src/vector-store-files/dtos/vector-store-file-delete.ts @@ -0,0 +1,27 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema } from 'json-schema-to-ts'; + +import { vectorStoreFileReadParamsSchema } from './vector-store-file-read.js'; + +import { createDeleteSchema } from '@/schema.js'; + +export const vectorStoreFileDeleteParamsSchema = vectorStoreFileReadParamsSchema; +export type VectorStoreFileDeleteParams = FromSchema; + +export const vectorStoreFileDeleteResponseSchema = createDeleteSchema('vectorStoreFile'); +export type VectorStoreFileDeleteResponse = FromSchema; diff --git a/src/vector-store-files/dtos/vector-store-file-list.ts b/src/vector-store-files/dtos/vector-store-file-list.ts new file mode 100644 index 0000000..1a3c33b --- /dev/null +++ b/src/vector-store-files/dtos/vector-store-file-list.ts @@ -0,0 +1,31 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema } from 'json-schema-to-ts'; + +import { vectorStoreFileSchema } from './vector-store-file.js'; + +import { createPaginationQuerySchema, withPagination } from '@/schema.js'; +import { vectorStoreFileCreateParamsSchema } from '@/vector-store-files/dtos/vector-store-file-create.js'; + +export const vectorStoreFilesListParamsSchema = vectorStoreFileCreateParamsSchema; +export type VectorStoreFilesListParams = FromSchema; + +export const vectorStoreFilesListQuerySchema = createPaginationQuerySchema(); +export type VectorStoreFilesListQuery = FromSchema; + +export const vectorStoreFilesListResponseSchema = withPagination(vectorStoreFileSchema); +export type VectorStoreFilesListResponse = FromSchema; diff --git a/src/vector-store-files/dtos/vector-store-file-read.ts b/src/vector-store-files/dtos/vector-store-file-read.ts new file mode 100644 index 0000000..09bf50a --- /dev/null +++ b/src/vector-store-files/dtos/vector-store-file-read.ts @@ -0,0 +1,31 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { vectorStoreFileSchema } from './vector-store-file.js'; + +export const vectorStoreFileReadParamsSchema = { + type: 'object', + additionalProperties: false, + required: ['vector_store_id', 'file_id'], + properties: { vector_store_id: { type: 'string' }, file_id: { type: 'string' } } +} as const satisfies JSONSchema; + +export type VectorStoreFileReadParams = FromSchema; + +export const vectorStoreFileReadResponseSchema = vectorStoreFileSchema; +export type VectorStoreFileReadResponse = FromSchema; diff --git a/src/vector-store-files/dtos/vector-store-file.ts b/src/vector-store-files/dtos/vector-store-file.ts new file mode 100644 index 0000000..f91101c --- /dev/null +++ b/src/vector-store-files/dtos/vector-store-file.ts @@ -0,0 +1,68 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; +import { omit } from 'remeda'; + +import { staticChunkingStrategySchema } from './chunking-strategy.js'; + +import { VectorStoreFileStatus } from '@/vector-store-files/entities/vector-store-file.entity.js'; +import { errorSchema } from '@/errors/dtos/error.js'; + +export const vectorStoreFileSchema = { + type: 'object', + title: 'Vector store files', + description: 'A list of files attached to a vector store.', + properties: { + id: { + description: 'The identifier, which can be referenced in API endpoints.', + type: 'string' + }, + object: { + description: 'The object type, which is always `vector_store.file`.', + type: 'string', + enum: ['vector_store.file'] + }, + usage_bytes: { + description: + 'The total vector store usage in bytes. Note that this may be different from the original file size.', + type: 'integer' + }, + created_at: { + description: 'The Unix timestamp (in seconds) for when the vector store file was created.', + type: 'integer' + }, + vector_store_id: { + description: 'The ID of the vector store that the file is attached to.', + type: 'string' + }, + status: { + description: + 'The status of the vector store file, which can be either `in_progress`, `completed`, `cancelled`, or `failed`. The status `completed` indicates that the vector store file is ready for use.', + type: 'string', + enum: Object.values(omit(VectorStoreFileStatus, ['CANCELLING'])) + }, + last_error: { ...errorSchema, nullable: true }, + chunking_strategy: { + type: 'object', + description: 'The strategy used to chunk the file.', + oneOf: [staticChunkingStrategySchema] + } + }, + required: ['id', 'object', 'usage_bytes', 'created_at', 'vector_store_id', 'status', 'last_error'] +} as const satisfies JSONSchema; + +export type VectorStoreFile = FromSchema; diff --git a/src/vector-store-files/entities/chunking-strategy/chunking-strategy.entity.ts b/src/vector-store-files/entities/chunking-strategy/chunking-strategy.entity.ts new file mode 100644 index 0000000..02d3112 --- /dev/null +++ b/src/vector-store-files/entities/chunking-strategy/chunking-strategy.entity.ts @@ -0,0 +1,32 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, Enum } from '@mikro-orm/core'; + +import { StaticChunkingStrategy } from './static-chunking-strategy.entity.js'; + +export const ChunkingStrategyType = { + STATIC: 'static' +} as const; +export type ChunkingStrategyType = (typeof ChunkingStrategyType)[keyof typeof ChunkingStrategyType]; + +@Embeddable({ abstract: true, discriminatorColumn: 'type' }) +export abstract class ChunkingStrategy { + @Enum(() => ChunkingStrategyType) + type!: ChunkingStrategyType; +} + +export type AnyChunkingStrategy = StaticChunkingStrategy; diff --git a/src/vector-store-files/entities/chunking-strategy/static-chunking-strategy.entity.ts b/src/vector-store-files/entities/chunking-strategy/static-chunking-strategy.entity.ts new file mode 100644 index 0000000..95be82c --- /dev/null +++ b/src/vector-store-files/entities/chunking-strategy/static-chunking-strategy.entity.ts @@ -0,0 +1,41 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, Property } from '@mikro-orm/core'; + +import { ChunkingStrategy, ChunkingStrategyType } from './chunking-strategy.entity.js'; + +@Embeddable({ discriminatorValue: ChunkingStrategyType.STATIC }) +export class StaticChunkingStrategy extends ChunkingStrategy { + type = ChunkingStrategyType.STATIC; + + @Property() + max_chunk_size_tokens!: number; + + @Property() + chunk_overlap_tokens!: number; + + constructor(input: StaticChunkingStrategyCreationInput) { + super(); + this.max_chunk_size_tokens = input.max_chunk_size_tokens; + this.chunk_overlap_tokens = input.chunk_overlap_tokens; + } +} + +export type StaticChunkingStrategyCreationInput = Pick< + StaticChunkingStrategy, + 'max_chunk_size_tokens' | 'chunk_overlap_tokens' +>; diff --git a/src/vector-store-files/entities/vector-store-file.entity.ts b/src/vector-store-files/entities/vector-store-file.entity.ts new file mode 100644 index 0000000..e7952e5 --- /dev/null +++ b/src/vector-store-files/entities/vector-store-file.entity.ts @@ -0,0 +1,75 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embedded, Entity, Enum, Index, ManyToOne, Property, Ref } from '@mikro-orm/core'; + +import { ProjectScopedEntity, ProjectScopedEntityInput } from '@/common/project-scoped.entity'; +import { VectorStore } from '@/vector-stores/entities/vector-store.entity.js'; +import { File } from '@/files/entities/file.entity.js'; +import { APIError } from '@/errors/error.entity.js'; +import { ChunkingStrategy } from '@/vector-store-files/entities/chunking-strategy/chunking-strategy.entity.js'; + +export const VectorStoreFileStatus = { + IN_PROGRESS: 'in_progress', + COMPLETED: 'completed', + FAILED: 'failed', + CANCELLING: 'cancelling', + CANCELLED: 'cancelled' +} as const; + +export type VectorStoreFileStatus = + (typeof VectorStoreFileStatus)[keyof typeof VectorStoreFileStatus]; + +@Entity() +@Index({ + options: [ + { file: 1, vectorStore: 1 }, + { unique: true, partialFilterExpression: { deletedAt: { $in: [null] } } } + ] +}) +export class VectorStoreFile extends ProjectScopedEntity { + getIdPrefix(): string { + return 'vsf'; + } + + @Enum(() => VectorStoreFileStatus) + status: VectorStoreFileStatus = VectorStoreFileStatus.IN_PROGRESS; + + @Embedded({ object: true }) + lastError?: APIError; + + @ManyToOne() + vectorStore: Ref; + + @Property() + usageBytes: number = 0; // NOTE: We use this field for storing number of documents, not bytes + + @ManyToOne() + file: Ref; + + @Embedded({ object: true }) + chunkingStrategy: ChunkingStrategy; + + constructor({ file, vectorStore, chunkingStrategy, ...rest }: VectorStoreFileInput) { + super(rest); + this.file = file; + this.vectorStore = vectorStore; + this.chunkingStrategy = chunkingStrategy; + } +} + +export type VectorStoreFileInput = ProjectScopedEntityInput & + Pick; diff --git a/src/vector-store-files/execution/clean-up-vector-db.ts b/src/vector-store-files/execution/clean-up-vector-db.ts new file mode 100644 index 0000000..e6f01ee --- /dev/null +++ b/src/vector-store-files/execution/clean-up-vector-db.ts @@ -0,0 +1,84 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + VectorStoreFile, + VectorStoreFileStatus +} from '@/vector-store-files/entities/vector-store-file.entity.js'; +import { ORM } from '@/database.js'; +import { getLogger } from '@/logger.js'; +import { getVectorStoreClient } from '@/vector-store-files/execution/client.js'; +import { VectorStore } from '@/vector-stores/entities/vector-store.entity.js'; + +export async function cleanupExpiredVectorStores() { + const expiredVectorStores = await ORM.em.find(VectorStore, { expiresAt: { $lt: new Date() } }); + const expiredFiles = await ORM.em.find( + VectorStoreFile, + { + usageBytes: { $gt: 0 }, + vectorStore: { $in: expiredVectorStores } + }, + { filters: { deleted: false } } + ); + const expiredFileIds = expiredFiles.map((file) => file.id); + if (expiredFiles.length > 0) { + await getVectorStoreClient().dropVectorStoreFiles(expiredFileIds); + for (const file of expiredFiles) { + file.usageBytes = 0; + } + await ORM.em.flush(); + getLogger().info({ cleanedUpFiles: expiredFiles.length }, `Vector store files cleaned up.`); + } +} + +// This makes sure that there is no leaked collection storage in milvus in case vector store deletion fails +export async function cleanupDeletedVectorStores() { + const unsuccessfulDeletions = await ORM.em.getRepository(VectorStoreFile).find( + { + usageBytes: { $gt: 0 }, + $or: [ + { deletedAt: { $ne: null } }, + { + status: { + $in: [ + VectorStoreFileStatus.FAILED, + VectorStoreFileStatus.CANCELLED, + VectorStoreFileStatus.CANCELLING + ] + } + } + ] + }, + { filters: { deleted: false } } + ); + if (unsuccessfulDeletions.length > 0) { + const fileIds = unsuccessfulDeletions.map((f) => f.id); + await getVectorStoreClient().dropVectorStoreFiles(fileIds); + for (const file of unsuccessfulDeletions) { + file.usageBytes = 0; + } + await ORM.em.flush(); + getLogger().warn( + { cleanedUpFiles: unsuccessfulDeletions.length }, + `There were some unsuccessfully deleted files, this should almost never happen!` + ); + } +} + +export async function cleanupVectorStores() { + await cleanupDeletedVectorStores(); + await cleanupExpiredVectorStores(); +} diff --git a/src/vector-store-files/execution/client.ts b/src/vector-store-files/execution/client.ts new file mode 100644 index 0000000..a7fd593 --- /dev/null +++ b/src/vector-store-files/execution/client.ts @@ -0,0 +1,34 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { z } from 'zod'; + +import { MilvusVectorStore } from './vector_db/adapters/milvus.js'; +import { VectorDbDocumentSchema } from './vector_db/types.js'; +import { VectorStoreClient } from './vector_db/adapters/interface.js'; + +import { VECTOR_STORE_EMBEDDING_MODEL } from '@/vector-stores/constants.js'; + +export const DocumentSchema = VectorDbDocumentSchema.extend({}); +export type Document = z.infer; +export type DocumentType = z.ZodType; + +export function getVectorStoreClient(): VectorStoreClient { + return new MilvusVectorStore({ + modelName: VECTOR_STORE_EMBEDDING_MODEL, + documentSchema: DocumentSchema + }); +} diff --git a/src/vector-store-files/execution/process-file.ts b/src/vector-store-files/execution/process-file.ts new file mode 100644 index 0000000..647fd9d --- /dev/null +++ b/src/vector-store-files/execution/process-file.ts @@ -0,0 +1,162 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { pipeline } from 'node:stream/promises'; + +import { RecursiveCharacterTextSplitter } from 'langchain/text_splitter'; +import { Document } from 'langchain/document'; +import { Loaded } from '@mikro-orm/core'; +import { AbortError } from 'bee-agent-framework/errors'; + +import { getLogger } from '@/logger.js'; +import { + VectorStoreFile, + VectorStoreFileStatus +} from '@/vector-store-files/entities/vector-store-file.entity.js'; +import { ORM } from '@/database.js'; +import { getExtractedFileObject, getExtractedFileStats } from '@/files/files.service.js'; +import { APIError } from '@/errors/error.entity.js'; +import { getVectorStoreClient } from '@/vector-store-files/execution/client.js'; +import { watchForCancellation } from '@/utils/jobs.js'; +import { StaticChunkingStrategy } from '@/vector-store-files/entities/chunking-strategy/static-chunking-strategy.entity.js'; +import { ChunkingStrategy } from '@/vector-store-files/entities/chunking-strategy/chunking-strategy.entity.js'; +import { createEmbeddingAdapter } from '@/embedding/factory'; +import { VECTOR_STORE_EMBEDDING_MODEL } from '@/vector-stores/constants'; + +const getJobLogger = (vectorStoreId: string, fileId?: string) => + getLogger().child({ vectorStoreId, fileId }, { msgPrefix: '[vector-store-process] ' }); + +const EMBEDDINGS_BATCH_SIZE = 1000; +const MAX_NUM_TOKENS = 3_000_000; + +// Estimate from OpenAI: https://help.openai.com/en/articles/4936856-what-are-tokens-and-how-to-count-them +const CHARS_PER_TOKEN_AVG = 4; + +function checkChunkingStrategy( + chunkingStrategy: ChunkingStrategy +): asserts chunkingStrategy is StaticChunkingStrategy { + if (!(chunkingStrategy instanceof StaticChunkingStrategy)) + throw new Error(`Unsupported chunking strategy type: ${chunkingStrategy.type}`); +} + +export async function processVectorStoreFile(vectorStoreFile: Loaded) { + const controller = new AbortController(); + const unsub = watchForCancellation(VectorStoreFile, vectorStoreFile, () => controller.abort()); + const logger = getJobLogger(vectorStoreFile.vectorStore.id, vectorStoreFile.id); + + const totalDocumentStats = { totalDocuments: 0, byteUsage: 0 }; + const chunkingStrategy = vectorStoreFile.chunkingStrategy; + + async function* splitTransform(text: string) { + checkChunkingStrategy(chunkingStrategy); + let chunkOverlap = chunkingStrategy.chunk_overlap_tokens; + let chunkSize = chunkingStrategy.max_chunk_size_tokens; + + // Todo Tokenize + chunkOverlap *= CHARS_PER_TOKEN_AVG; + chunkSize *= CHARS_PER_TOKEN_AVG; + + const splitter = new RecursiveCharacterTextSplitter({ chunkSize, chunkOverlap }); + yield* await splitter.createDocuments([text], undefined); + } + + async function* chunkTransform(source: AsyncIterable) { + let buffer: Document[] = []; + for await (const item of source) { + // Check for abort (could be a separate processor, but the typing is too much effort) + if (controller.signal.aborted) throw new AbortError('File processing aborted'); + + buffer.push(item); + if (buffer.length >= EMBEDDINGS_BATCH_SIZE) { + yield buffer; + buffer = []; + } + } + if (buffer.length > 0) yield buffer; + } + + async function* embedTransform(source: AsyncIterable) { + const embeddingAdapter = await createEmbeddingAdapter(VECTOR_STORE_EMBEDDING_MODEL); + for await (const items of source) { + const embeddings = await embeddingAdapter.embedMany( + items.map((item) => item.pageContent), + { + signal: controller.signal + } + ); + yield embeddings.map((embedding, idx) => ({ + embedding: embedding, + text: items[idx].pageContent + })); + } + } + + async function storeSink(source: AsyncIterable<{ embedding: number[]; text: string }[]>) { + for await (const documents of source) { + const vectorStoreClient = getVectorStoreClient(); + const documentStats = await vectorStoreClient.addDocuments( + documents.map(({ embedding, text }) => ({ + vector: embedding, + text, + vectorStoreFileId: vectorStoreFile.id, + source: { file: { name: vectorStoreFile.file.$.filename, id: vectorStoreFile.file.id } } + })) + ); + totalDocumentStats.totalDocuments += documentStats.totalCreated; + totalDocumentStats.byteUsage += documentStats.byteUsage; + vectorStoreFile.usageBytes = totalDocumentStats.byteUsage; + await ORM.em.flush(); + } + } + + try { + const fileStats = await getExtractedFileStats(vectorStoreFile.file.$); + const maxTextLength = MAX_NUM_TOKENS * CHARS_PER_TOKEN_AVG; + const maxContentLengthBytes = maxTextLength * 1.5; //~ 2 bytes per char in utf-8 + margin of error + if ((fileStats.ContentLength ?? Infinity) > maxContentLengthBytes) { + throw Error('The file contains too much text'); // Skip downloading file + } + const fileObject = await getExtractedFileObject(vectorStoreFile.file.$); + controller.signal.throwIfAborted(); + + const text = fileObject.Body?.toString('utf-8'); + if (!text) throw new Error('Invalid Body of a file'); + if (text.length > maxTextLength) throw new Error('The file contains too much text'); + + await pipeline(text, splitTransform, chunkTransform, embedTransform, storeSink); + vectorStoreFile.status = VectorStoreFileStatus.COMPLETED; + } catch (err) { + getLogger().error({ err }, 'Vector store file processing failed'); + + if (err instanceof AbortError) { + vectorStoreFile.status = VectorStoreFileStatus.CANCELLED; + } else { + vectorStoreFile.status = VectorStoreFileStatus.FAILED; + vectorStoreFile.lastError = APIError.from(err); + } + // Cleanup partially embedded file from vector-store + try { + await getVectorStoreClient().dropVectorStoreFiles([vectorStoreFile.id]); + vectorStoreFile.usageBytes = 0; + } catch (err) { + logger.warn({ err }, 'Could not delete vector stores from vector db.'); + } + } finally { + await ORM.em.flush(); + unsub(); + } + return totalDocumentStats; +} diff --git a/src/vector-store-files/execution/vector_db/adapters/interface.ts b/src/vector-store-files/execution/vector_db/adapters/interface.ts new file mode 100644 index 0000000..0d8cd04 --- /dev/null +++ b/src/vector-store-files/execution/vector_db/adapters/interface.ts @@ -0,0 +1,44 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { z } from 'zod'; + +import { DocumentStats, VectorDbDocument } from '../types.js'; + +export interface VectorStoreClient> { + /** + * Add documents to vector store + * @param documents to be indexed + */ + addDocuments: (documents: z.infer[]) => Promise; + /** + * Search indexed documents in partitions + * @param query vector with expected dimensions (e.g. consistent with config passed in constructor) + * @param k number of documents to retrieve + * @param vectorStoreFileIds vector stores files to search in, each vectorStoreFileId represents a set of indexed documents + */ + similaritySearchVectorWithScore: ( + query: number[], + k: number, + vectorStoreFileIds: string[] + ) => Promise<{ document: z.infer; score: number }[]>; + + /** + * Delete vector stores documents created from one or more files + * @param vectorStoreFileIds vector store files to be deleted + */ + dropVectorStoreFiles(vectorStoreFileIds: string[]): Promise; +} diff --git a/src/vector-store-files/execution/vector_db/adapters/milvus.ts b/src/vector-store-files/execution/vector_db/adapters/milvus.ts new file mode 100644 index 0000000..4da611f --- /dev/null +++ b/src/vector-store-files/execution/vector_db/adapters/milvus.ts @@ -0,0 +1,276 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as path from 'node:path'; +import * as fs from 'node:fs/promises'; +import os from 'os'; + +import { + ClientConfig, + CreateIndexSimpleReq, + DataType, + ErrorCode, + FieldType, + IndexType, + MetricType, + MilvusClient, + ResStatus +} from '@zilliz/milvus2-sdk-node'; +import { z } from 'zod'; +import { sum } from 'remeda'; + +import { DocumentStats, VectorDbDocument } from '../types.js'; + +import { VectorStoreClient } from './interface.js'; + +import { + MILVUS_CA_CERT, + MILVUS_CERT, + MILVUS_DATABASE_NAME, + MILVUS_HOST, + MILVUS_KEY, + MILVUS_PASSWORD, + MILVUS_PORT, + MILVUS_USE_TLS, + MILVUS_USERNAME +} from '@/config.js'; + +export function modelNameToCollectionName(modelName: string): string { + return modelName + .replace(/[^a-zA-Z0-9_]/g, '_') + .replace(/_+/g, '_') + .replace(/^_|_$/g, '') + .toLowerCase(); +} + +interface MilvusOptions> { + modelName: string; + documentSchema: SchemaType; + textFieldMaxLength?: number; +} + +const DEFAULT_TEXT_FIELD_MAX_LENGTH = 10000; +const VECTOR_STORE_PARTITION_NAME_MAX_LENGTH = 512; +const MILVUS_TIMEOUT_MS = 60_000; // Creating new collection in the hosted Milvus is UNBELIEVABLY SLOW + +const VECTOR_FIELD_NAME: keyof Pick = 'vector'; + +export async function clientErrorWrapper( + request: Promise +): Promise { + let response: T; + try { + response = await request; + } catch (err: any) { + throw new Error(`Error occurred when calling external vector database.`, { cause: err }); + } + + const status: ResStatus = 'status' in response ? response.status : response; + if (status.error_code !== ErrorCode.SUCCESS) { + throw new Error(`Error occurred when calling external vector database.`, { cause: status }); + } + return response; +} + +export async function createMilvusClient() { + try { + let tls: ClientConfig['tls'] = undefined; + let ssl = false; + if (MILVUS_USE_TLS) { + const rootCertPath = path.join(os.tmpdir(), `milvus-ca.pem`); + const certChainPath = path.join(os.tmpdir(), `milvus-server.pem`); + const privateKeyPath = path.join(os.tmpdir(), `milvus-server.key`); + await Promise.all([ + fs.writeFile(rootCertPath, MILVUS_CA_CERT, 'utf-8'), + fs.writeFile(certChainPath, MILVUS_CERT, 'utf-8'), + fs.writeFile(privateKeyPath, MILVUS_KEY, 'utf-8') + ]); + tls = { serverName: 'localhost', rootCertPath, certChainPath, privateKeyPath }; + ssl = true; + } + const client = new MilvusClient({ + address: `${MILVUS_HOST}:${MILVUS_PORT}`, + username: MILVUS_USERNAME, + password: MILVUS_PASSWORD, + database: MILVUS_DATABASE_NAME, + ssl, + tls, + timeout: MILVUS_TIMEOUT_MS + }); + await client.connectPromise; + return client; + } catch (err: any) { + throw new Error('Error occurred when calling external vector database.', { cause: err }); + } +} + +export class MilvusVectorStore> + implements VectorStoreClient +{ + private indexSearchParams = { ef: 64 }; + private milvusCollectionSelector: { collection_name: string }; + + constructor( + private options: MilvusOptions, + private _client?: MilvusClient + ) { + this.milvusCollectionSelector = { + collection_name: modelNameToCollectionName(this.options.modelName) + }; + } + + private get indexCreateParams(): CreateIndexSimpleReq { + return { + ...this.milvusCollectionSelector, + index_type: IndexType.HNSW, + params: { M: 8, efConstruction: 64 }, + metric_type: MetricType.COSINE, + field_name: VECTOR_FIELD_NAME + }; + } + + private async getClient() { + this._client = this._client ?? (await createMilvusClient()); + return this._client; + } + + private getCollectionFields(vectorDimension: number): (FieldType & { + name: keyof VectorDbDocument | 'id'; + usageBytes: (document: VectorDbDocument) => number; + })[] { + const textFieldLength = this.options.textFieldMaxLength ?? DEFAULT_TEXT_FIELD_MAX_LENGTH; + // See https://milvus.io/docs/schema.md for byte approximates + return [ + { + name: 'id', + description: 'Primary key', + data_type: DataType.Int64, + is_primary_key: true, + autoID: true, + usageBytes: () => 8 + }, + { + name: 'vectorStoreFileId', + data_type: DataType.VarChar, + max_length: VECTOR_STORE_PARTITION_NAME_MAX_LENGTH, + is_partition_key: false, + usageBytes: (document: VectorDbDocument) => document.vectorStoreFileId.length * 2 + }, + { + name: 'text', + description: 'Text field', + data_type: DataType.VarChar, + max_length: textFieldLength.toString(), + usageBytes: (document: VectorDbDocument) => document.text.length * 2 + }, + { + name: 'vector', + description: 'Vector field', + data_type: DataType.FloatVector, + dim: vectorDimension, + element_type: DataType.None, + usageBytes: () => 4 * vectorDimension + } + ]; + } + + public getApproximateDocumentByteUsage(document: z.infer) { + return sum(this.getCollectionFields(document.vector.length).map((f) => f.usageBytes(document))); + } + + private async ensureMilvusCollection(vectorDimension: number) { + const client = await this.getClient(); + const hasCollection = await clientErrorWrapper( + client.hasCollection(this.milvusCollectionSelector) + ); + if (hasCollection.value === true) return; + try { + await clientErrorWrapper( + client.createCollection({ + ...this.milvusCollectionSelector, + fields: this.getCollectionFields(vectorDimension), + enable_dynamic_field: true + }) + ); + await clientErrorWrapper(client.createIndex(this.indexCreateParams)); + } catch (error) { + await clientErrorWrapper(client.dropCollection(this.milvusCollectionSelector)); + throw error; + } + } + + private getVectorStoreFileFilter(vectorStoreFileIds: string[]) { + return `vectorStoreFileId in [${vectorStoreFileIds.map((c) => `"${c}"`).join(', ')}]`; + } + + async addDocuments(documents: z.infer[]): Promise { + if (documents.length === 0) return { byteUsage: 0, totalCreated: 0 }; + const documentDimension = documents[0].vector.length; + const client = await this.getClient(); + await this.ensureMilvusCollection(documentDimension); + await clientErrorWrapper(client.insert({ ...this.milvusCollectionSelector, data: documents })); + + return { + byteUsage: this.getApproximateDocumentByteUsage(documents[0]) * documents.length, + totalCreated: documents.length + }; + } + + public async similaritySearchVectorWithScore( + query: number[], + k: number, + vectorStoreFileIds: string[] + ): Promise<{ score: number; document: z.infer }[]> { + if (vectorStoreFileIds.length === 0) return []; + + const client = await this.getClient(); + + await clientErrorWrapper(client.loadCollectionSync(this.milvusCollectionSelector)); + + const outputFields: string[] = this.getCollectionFields(query.length).map( + (field) => field.name + ); + outputFields.push('$meta'); + + const response = await clientErrorWrapper( + client.search({ + ...this.milvusCollectionSelector, + params: this.indexSearchParams, + limit: k, + metric_type: this.indexCreateParams.metric_type, + vector_type: DataType.FloatVector, + vector: query, + output_fields: outputFields, + filter: this.getVectorStoreFileFilter(vectorStoreFileIds) + }) + ); + + return response.results.map(({ score, $meta, ...documentUnverified }) => { + const document = this.options.documentSchema.parse({ ...documentUnverified, ...$meta }); + return { document, score }; + }); + } + + public async drop(filter: string) { + const client = await this.getClient(); + await clientErrorWrapper(client.loadCollectionSync(this.milvusCollectionSelector)); + await clientErrorWrapper(client.deleteEntities({ ...this.milvusCollectionSelector, filter })); + } + + public async dropVectorStoreFiles(vectorStoreFileIds: string[]) { + return this.drop(this.getVectorStoreFileFilter(vectorStoreFileIds)); + } +} diff --git a/src/vector-store-files/execution/vector_db/types.ts b/src/vector-store-files/execution/vector_db/types.ts new file mode 100644 index 0000000..99d925e --- /dev/null +++ b/src/vector-store-files/execution/vector_db/types.ts @@ -0,0 +1,36 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { z } from 'zod'; + +export const VectorDbDocumentSchema = z.object({ + vector: z.number().array(), + text: z.string(), + vectorStoreFileId: z.string(), + source: z + .object({ + file: z.object({ id: z.string(), name: z.string() }).optional(), + url: z.string().optional() + }) + .optional() +}); + +export type VectorDbDocument = z.infer; + +export interface DocumentStats { + byteUsage: number; + totalCreated: number; +} diff --git a/src/vector-store-files/queues/cleanup-vector-store.queue.ts b/src/vector-store-files/queues/cleanup-vector-store.queue.ts new file mode 100644 index 0000000..2f120d5 --- /dev/null +++ b/src/vector-store-files/queues/cleanup-vector-store.queue.ts @@ -0,0 +1,32 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { RequestContext } from '@mikro-orm/core'; + +import { ORM } from '@/database.js'; +import { createQueue } from '@/jobs/bullmq.js'; +import { cleanupVectorStores } from '@/vector-store-files/execution/clean-up-vector-db.js'; +import { QueueName } from '@/jobs/constants.js'; + +async function jobHandler() { + return RequestContext.create(ORM.em, async () => cleanupVectorStores()); +} + +export const { queue, worker } = createQueue({ + name: QueueName.VECTOR_STORES_CLEANUP, + jobHandler, + jobsOptions: { attempts: 1 } +}); diff --git a/src/vector-store-files/queues/process-file.queue.ts b/src/vector-store-files/queues/process-file.queue.ts new file mode 100644 index 0000000..178c109 --- /dev/null +++ b/src/vector-store-files/queues/process-file.queue.ts @@ -0,0 +1,58 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Job } from 'bullmq'; +import { RequestContext } from '@mikro-orm/core'; + +import { ORM } from '@/database.js'; +import { createQueue } from '@/jobs/bullmq.js'; +import { processVectorStoreFile } from '@/vector-store-files/execution/process-file.js'; +import { QueueName } from '@/jobs/constants.js'; +import { + VectorStoreFile, + VectorStoreFileStatus +} from '@/vector-store-files/entities/vector-store-file.entity.js'; +import { APIError } from '@/errors/error.entity.js'; +import { waitForExtraction } from '@/files/utils/wait-for-extraction.js'; + +async function jobHandler(job: Job<{ vectorStoreFileId: string }>) { + return RequestContext.create(ORM.em, async () => { + const vectorStoreFile = await ORM.em.getRepository(VectorStoreFile).findOneOrFail( + { + id: job.data.vectorStoreFileId, + deletedAt: null, + status: VectorStoreFileStatus.IN_PROGRESS + }, + { filters: { deleted: false }, populate: ['file'] } + ); + const { failed } = await waitForExtraction(job, [vectorStoreFile.file.$]); + if (failed.length > 0) { + vectorStoreFile.status = VectorStoreFileStatus.FAILED; + vectorStoreFile.lastError = APIError.from(failed[0].err); + + await ORM.em.flush(); + + throw failed[0].err; + } + await processVectorStoreFile(vectorStoreFile); + }); +} + +export const { queue, worker } = createQueue({ + name: QueueName.VECTOR_STORES_FILE_PROCESSOR, + jobHandler, + jobsOptions: { attempts: 1 } +}); diff --git a/src/vector-store-files/utils/determineChunkingStrategy.ts b/src/vector-store-files/utils/determineChunkingStrategy.ts new file mode 100644 index 0000000..2bce82f --- /dev/null +++ b/src/vector-store-files/utils/determineChunkingStrategy.ts @@ -0,0 +1,41 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ChunkingStrategyRequestParam } from '@/vector-store-files/dtos/chunking-strategy.js'; +import { StaticChunkingStrategy } from '@/vector-store-files/entities/chunking-strategy/static-chunking-strategy.entity.js'; +import { ChunkingStrategy } from '@/vector-store-files/entities/chunking-strategy/chunking-strategy.entity.js'; +import { + VECTOR_STORE_DEFAULT_CHUNK_OVERLAP_TOKENS, + VECTOR_STORE_DEFAULT_MAX_CHUNK_SIZE_TOKENS +} from '@/vector-stores/constants.js'; + +export function determineChunkingStrategy(param?: ChunkingStrategyRequestParam): ChunkingStrategy { + const defaultStrategy = new StaticChunkingStrategy({ + max_chunk_size_tokens: VECTOR_STORE_DEFAULT_MAX_CHUNK_SIZE_TOKENS, + chunk_overlap_tokens: VECTOR_STORE_DEFAULT_CHUNK_OVERLAP_TOKENS + }); + if (!param) return defaultStrategy; + + switch (param.type) { + case 'auto': + return defaultStrategy; + case 'static': + return new StaticChunkingStrategy({ + max_chunk_size_tokens: param.static.max_chunk_size_tokens, + chunk_overlap_tokens: param.static.chunk_overlap_tokens + }); + } +} diff --git a/src/vector-store-files/vector-store-files.module.ts b/src/vector-store-files/vector-store-files.module.ts new file mode 100644 index 0000000..ace5932 --- /dev/null +++ b/src/vector-store-files/vector-store-files.module.ts @@ -0,0 +1,115 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FastifyPluginAsyncJsonSchemaToTs } from '@fastify/type-provider-json-schema-to-ts'; +import { StatusCodes } from 'http-status-codes'; + +import { + createVectorStoreFile, + deleteVectorStoreFile, + listVectorStoreFiles, + readVectorStoreFile +} from './vector-store-files.service.js'; + +import { + VectorStoreFileCreateBody, + vectorStoreFileCreateBodySchema, + VectorStoreFileCreateParams, + vectorStoreFileCreateParamsSchema, + vectorStoreFileCreateResponseSchema +} from '@/vector-store-files/dtos/vector-store-file-create.js'; +import { + VectorStoreFilesListParams, + vectorStoreFilesListParamsSchema, + VectorStoreFilesListQuery, + vectorStoreFilesListQuerySchema, + vectorStoreFilesListResponseSchema +} from '@/vector-store-files/dtos/vector-store-file-list.js'; +import { + VectorStoreFileReadParams, + vectorStoreFileReadParamsSchema, + vectorStoreFileReadResponseSchema +} from '@/vector-store-files/dtos/vector-store-file-read.js'; +import { + VectorStoreFileDeleteParams, + vectorStoreFileDeleteParamsSchema +} from '@/vector-store-files/dtos/vector-store-file-delete.js'; +import { Tag } from '@/swagger.js'; +import { createDeleteSchema } from '@/schema.js'; + +export const vectorStoreFilesModule: FastifyPluginAsyncJsonSchemaToTs = async (app) => { + app.post<{ Body: VectorStoreFileCreateBody; Params: VectorStoreFileCreateParams }>( + '/vector_stores/:vector_store_id/files', + { + preHandler: app.auth(), + schema: { + body: vectorStoreFileCreateBodySchema, + params: vectorStoreFileCreateParamsSchema, + response: { + [StatusCodes.OK]: vectorStoreFileCreateResponseSchema + }, + tags: [Tag.OPENAI_ASSISTANTS_API] + } + }, + async (req) => createVectorStoreFile({ ...req.params, ...req.body }) + ); + + app.get<{ Querystring: VectorStoreFilesListQuery; Params: VectorStoreFilesListParams }>( + '/vector_stores/:vector_store_id/files', + { + preHandler: app.auth(), + schema: { + querystring: vectorStoreFilesListQuerySchema, + params: vectorStoreFilesListParamsSchema, + response: { + [StatusCodes.OK]: vectorStoreFilesListResponseSchema + }, + tags: [Tag.OPENAI_ASSISTANTS_API] + } + }, + async (req) => listVectorStoreFiles({ ...req.params, ...req.query }) + ); + + app.get<{ Params: VectorStoreFileReadParams }>( + '/vector_stores/:vector_store_id/files/:file_id', + { + preHandler: app.auth(), + schema: { + params: vectorStoreFileReadParamsSchema, + response: { + [StatusCodes.OK]: vectorStoreFileReadResponseSchema + }, + tags: [Tag.OPENAI_ASSISTANTS_API] + } + }, + async (req) => readVectorStoreFile(req.params) + ); + + app.delete<{ Params: VectorStoreFileDeleteParams }>( + '/vector_stores/:vector_store_id/files/:file_id', + { + preHandler: app.auth(), + schema: { + params: vectorStoreFileDeleteParamsSchema, + response: { + [StatusCodes.OK]: createDeleteSchema('vector_store') + }, + tags: [Tag.OPENAI_ASSISTANTS_API] + } + }, + async (req) => deleteVectorStoreFile(req.params) + ); +}; diff --git a/src/vector-store-files/vector-store-files.service.ts b/src/vector-store-files/vector-store-files.service.ts new file mode 100644 index 0000000..7438618 --- /dev/null +++ b/src/vector-store-files/vector-store-files.service.ts @@ -0,0 +1,176 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ref, RequestContext } from '@mikro-orm/core'; +import dayjs from 'dayjs'; +import { Loaded } from '@mikro-orm/mongodb'; + +import { VectorStoreFile, VectorStoreFileStatus } from './entities/vector-store-file.entity.js'; + +import { File } from '@/files/entities/file.entity.js'; +import { VectorStoreFile as VectorStoreFileDto } from '@/vector-store-files/dtos/vector-store-file.js'; +import { + VectorStoreFileReadParams, + VectorStoreFileReadResponse +} from '@/vector-store-files/dtos/vector-store-file-read.js'; +import { + VectorStoreFilesListParams, + VectorStoreFilesListQuery, + VectorStoreFilesListResponse +} from '@/vector-store-files/dtos/vector-store-file-list.js'; +import { + VectorStoreFileCreateBody, + VectorStoreFileCreateParams, + VectorStoreFileCreateResponse +} from '@/vector-store-files/dtos/vector-store-file-create.js'; +import { + VectorStoreFileDeleteParams, + VectorStoreFileDeleteResponse +} from '@/vector-store-files/dtos/vector-store-file-delete.js'; +import { ORM } from '@/database.js'; +import { createPaginatedResponse, getListCursor } from '@/utils/pagination.js'; +import { APIError, APIErrorCode } from '@/errors/error.entity.js'; +import { createDeleteResponse } from '@/utils/delete.js'; +import { VectorStore } from '@/vector-stores/entities/vector-store.entity.js'; +import { getVectorStoreClient } from '@/vector-store-files/execution/client.js'; +import { queue } from '@/vector-store-files/queues/process-file.queue.js'; +import { determineChunkingStrategy } from '@/vector-store-files/utils/determineChunkingStrategy.js'; +import { getServiceLogger } from '@/logger.js'; +import { toErrorDto } from '@/errors/plugin.js'; +import { QueueName } from '@/jobs/constants.js'; + +const getFileLogger = (vectorStoreFileIds?: string[]) => + getServiceLogger('vector-store-files').child({ vectorStoreFileIds }); + +export function toDto(vectorStoreFile: VectorStoreFile): VectorStoreFileDto { + const { file, status, vectorStore, lastError, usageBytes } = vectorStoreFile; + return { + // The ID returned to frontend is file ID. Unique Identifier is a pair (vectorStore, fileId) + id: file.id, + object: 'vector_store.file', + usage_bytes: usageBytes, + status: status == 'cancelling' ? 'cancelled' : status, + vector_store_id: vectorStore.id, + last_error: lastError ? toErrorDto(lastError) : null, + created_at: dayjs(vectorStoreFile.createdAt).unix() + }; +} + +export async function listVectorStoreFiles({ + vector_store_id, + limit, + order, + order_by, + after, + before +}: VectorStoreFilesListParams & VectorStoreFilesListQuery): Promise { + await ORM.em // check if VectorStore exists + .getRepository(VectorStore) + .findOneOrFail({ id: vector_store_id }); + + const repo = ORM.em.getRepository(VectorStoreFile); + const cursor = await getListCursor( + { vectorStore: vector_store_id }, + { limit, order, order_by, after, before }, + repo + ); + return createPaginatedResponse(cursor, toDto); +} + +export async function createVectorStoreFile({ + vector_store_id, + ...body +}: VectorStoreFileCreateParams & + VectorStoreFileCreateBody): Promise { + const vectorStore = await ORM.em + .getRepository(VectorStore) + .findOneOrFail({ id: vector_store_id }); + + if (vectorStore.expired) { + throw new APIError({ message: 'Vector store is expired', code: APIErrorCode.INVALID_INPUT }); + } + + const file = await ORM.em.getRepository(File).findOneOrFail({ id: body.file_id }); + + const vectorStoreFile = new VectorStoreFile({ + file: ref(file), + vectorStore: ref(vectorStore), + chunkingStrategy: determineChunkingStrategy(body.chunking_strategy), + dependsOn: vectorStore.dependsOn + }); + + await ORM.em.persistAndFlush(vectorStoreFile); + await queue.add( + QueueName.VECTOR_STORES_FILE_PROCESSOR, + { vectorStoreFileId: vectorStoreFile.id }, + { jobId: vectorStoreFile.id } + ); + return toDto(vectorStoreFile); +} + +export async function readVectorStoreFile({ + vector_store_id, + file_id +}: VectorStoreFileReadParams): Promise { + const vectorStoreFile = await ORM.em.getRepository(VectorStoreFile).findOneOrFail({ + vectorStore: vector_store_id, + file: file_id + }); + return toDto(vectorStoreFile); +} + +export async function deleteVectorStoreFile({ + file_id, + vector_store_id +}: VectorStoreFileDeleteParams): Promise { + const vectorStoreFile = await ORM.em.getRepository(VectorStoreFile).findOneOrFail({ + vectorStore: vector_store_id, + file: file_id + }); + await deleteVectorStoreFiles([vectorStoreFile]); + await ORM.em.flush(); + return createDeleteResponse(file_id, 'vectorStoreFile'); +} + +export async function deleteVectorStoreFiles(vectorStoreFiles: Loaded[]) { + const vectorStoreFileIds = vectorStoreFiles.map((f) => f.id); + await Promise.all(vectorStoreFileIds.map((vectorStoreFileId) => queue.remove(vectorStoreFileId))); + + const cleanupVectorDb = async () => { + RequestContext.create(ORM.em, async () => { + try { + await getVectorStoreClient().dropVectorStoreFiles(vectorStoreFiles.map((f) => f.id)); + for (const vectorStoreFile of vectorStoreFiles) { + vectorStoreFile.usageBytes = 0; + } + await ORM.em.flush(); + } catch (err) { + getFileLogger(vectorStoreFileIds).warn( + { err }, + 'Could not delete vector store files from vector db.' + ); + } + }); + }; + cleanupVectorDb(); // clean up vector db in the background + + for (const vectorStoreFile of vectorStoreFiles) { + vectorStoreFile.delete(); + if (vectorStoreFile.status === VectorStoreFileStatus.IN_PROGRESS) { + vectorStoreFile.status = VectorStoreFileStatus.CANCELLING; + } + } +} diff --git a/src/vector-stores/constants.ts b/src/vector-stores/constants.ts new file mode 100644 index 0000000..d88d626 --- /dev/null +++ b/src/vector-stores/constants.ts @@ -0,0 +1,22 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { getDefaultEmbeddingModel } from '@/embedding/factory'; + +export const VECTOR_STORE_EMBEDDING_MODEL = getDefaultEmbeddingModel(); +export const VECTOR_STORE_DEFAULT_MAX_CHUNK_SIZE_TOKENS = 400; +export const VECTOR_STORE_DEFAULT_CHUNK_OVERLAP_TOKENS = 200; +export const VECTOR_STORE_DEFAULT_MAX_NUM_RESULTS = 5; diff --git a/src/vector-stores/dtos/vector-store-create.ts b/src/vector-stores/dtos/vector-store-create.ts new file mode 100644 index 0000000..0da9189 --- /dev/null +++ b/src/vector-stores/dtos/vector-store-create.ts @@ -0,0 +1,65 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { vectorStoreSchema } from './vector-store.js'; +import { vectorStoreExpirationAfterSchema } from './vector-store-expiration-after.js'; + +import { chunkingStrategyRequestParamSchema } from '@/vector-store-files/dtos/chunking-strategy.js'; +import { metadataSchema } from '@/schema.js'; + +export const vectorStoreCreateBodySchema = { + type: 'object', + additionalProperties: false, + properties: { + file_ids: { + description: + 'A list of File IDs that the vector store should use. Useful for tools like `file_search` that can access files.', + type: 'array', + maxItems: 500, + items: { type: 'string' }, + uniqueItems: true + }, + name: { + description: 'The name of the vector store.', + type: 'string' + }, + expires_after: vectorStoreExpirationAfterSchema, + chunking_strategy: chunkingStrategyRequestParamSchema, + depends_on: { + type: 'object', + required: ['thread'], + properties: { + thread: { + type: 'object', + required: ['id'], + properties: { + id: { + type: 'string' + } + } + } + } + }, + metadata: metadataSchema + } +} as const satisfies JSONSchema; + +export type VectorStoreCreateBody = FromSchema; + +export const vectorStoreCreateResponseSchema = vectorStoreSchema; +export type VectorStoreCreateResponse = FromSchema; diff --git a/src/vector-stores/dtos/vector-store-delete.ts b/src/vector-stores/dtos/vector-store-delete.ts new file mode 100644 index 0000000..1c9f498 --- /dev/null +++ b/src/vector-stores/dtos/vector-store-delete.ts @@ -0,0 +1,27 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema } from 'json-schema-to-ts'; + +import { vectorStoreReadParamsSchema } from './vector-store-read.js'; + +import { createDeleteSchema } from '@/schema.js'; + +export const vectorStoreDeleteParamsSchema = vectorStoreReadParamsSchema; +export type VectorStoreDeleteParams = FromSchema; + +export const vectorStoreDeleteResponseSchema = createDeleteSchema('vectorStore'); +export type VectorStoreDeleteResponse = FromSchema; diff --git a/src/vector-stores/dtos/vector-store-expiration-after.ts b/src/vector-stores/dtos/vector-store-expiration-after.ts new file mode 100644 index 0000000..cb27810 --- /dev/null +++ b/src/vector-stores/dtos/vector-store-expiration-after.ts @@ -0,0 +1,40 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { JSONSchema } from 'json-schema-to-ts'; + +import { VectorStoreExpirationAfterAnchor } from '@/vector-stores/entities/vector-store-expiration-after.entity.js'; + +export const vectorStoreExpirationAfterSchema = { + type: 'object', + title: 'Vector store expiration policy', + description: 'The expiration policy for a vector store.', + properties: { + anchor: { + description: + 'Anchor timestamp after which the expiration policy applies. Supported anchors: `last_active_at`.', + type: 'string', + enum: Object.values(VectorStoreExpirationAfterAnchor) + }, + days: { + description: 'The number of days after the anchor time that the vector store will expire.', + type: 'integer', + minimum: 1, + maximum: 365 + } + }, + required: ['anchor', 'days'] +} as const satisfies JSONSchema; diff --git a/src/vector-stores/dtos/vector-store-list.ts b/src/vector-stores/dtos/vector-store-list.ts new file mode 100644 index 0000000..0eb0a5e --- /dev/null +++ b/src/vector-stores/dtos/vector-store-list.ts @@ -0,0 +1,38 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { vectorStoreSchema } from './vector-store.js'; + +import { createPaginationQuerySchema, withPagination } from '@/schema.js'; + +export const vectorStoresListQuerySchema = { + type: 'object', + additionalProperties: false, + properties: { + ...createPaginationQuerySchema(['name'] as const).properties, + search: { type: 'string', nullable: true }, + show_dependent: { + type: 'boolean', + default: true + } + } +} as const satisfies JSONSchema; +export type VectorStoresListQuery = FromSchema; + +export const vectorStoresListResponseSchema = withPagination(vectorStoreSchema); +export type VectorStoresListResponse = FromSchema; diff --git a/src/vector-stores/dtos/vector-store-read.ts b/src/vector-stores/dtos/vector-store-read.ts new file mode 100644 index 0000000..5dcca8d --- /dev/null +++ b/src/vector-stores/dtos/vector-store-read.ts @@ -0,0 +1,31 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { vectorStoreSchema } from './vector-store.js'; + +export const vectorStoreReadParamsSchema = { + type: 'object', + additionalProperties: false, + required: ['vector_store_id'], + properties: { vector_store_id: { type: 'string' } } +} as const satisfies JSONSchema; + +export type VectorStoreReadParams = FromSchema; + +export const vectorStoreReadResponseSchema = vectorStoreSchema; +export type VectorStoreReadResponse = FromSchema; diff --git a/src/vector-stores/dtos/vector-store-update.ts b/src/vector-stores/dtos/vector-store-update.ts new file mode 100644 index 0000000..fdd8147 --- /dev/null +++ b/src/vector-stores/dtos/vector-store-update.ts @@ -0,0 +1,40 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { vectorStoreReadParamsSchema } from './vector-store-read.js'; +import { vectorStoreSchema } from './vector-store.js'; + +import { vectorStoreExpirationAfterSchema } from '@/vector-stores/dtos/vector-store-expiration-after.js'; +import { metadataSchema } from '@/schema.js'; + +export const vectorStoreUpdateBodySchema = { + type: 'object', + additionalProperties: false, + properties: { + name: { description: 'The name of the vector store.', type: 'string', nullable: true }, + expires_after: { ...vectorStoreExpirationAfterSchema, nullable: true }, + metadata: metadataSchema + } +} as const satisfies JSONSchema; +export type VectorStoreUpdateBody = FromSchema; + +export const vectorStoreUpdateParamsSchema = vectorStoreReadParamsSchema; +export type VectorStoreUpdateParams = FromSchema; + +export const vectorStoreUpdateResponseSchema = vectorStoreSchema; +export type VectorStoreUpdateResponse = FromSchema; diff --git a/src/vector-stores/dtos/vector-store.ts b/src/vector-stores/dtos/vector-store.ts new file mode 100644 index 0000000..8ee8528 --- /dev/null +++ b/src/vector-stores/dtos/vector-store.ts @@ -0,0 +1,122 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FromSchema, JSONSchema } from 'json-schema-to-ts'; + +import { vectorStoreExpirationAfterSchema } from '@/vector-stores/dtos/vector-store-expiration-after.js'; +import { metadataSchema } from '@/schema.js'; + +export const vectorStoreSchema = { + type: 'object', + title: 'Vector store', + description: + 'A vector store is a collection of processed files can be used by the `file_search` tool.', + properties: { + id: { + description: 'The identifier, which can be referenced in API endpoints.', + type: 'string' + }, + object: { + description: 'The object type, which is always `vector_store`.', + type: 'string', + enum: ['vector_store'] + }, + created_at: { + description: 'The Unix timestamp (in seconds) for when the vector store was created.', + type: 'integer' + }, + name: { + description: 'The name of the vector store.', + type: 'string' + }, + usage_bytes: { + description: 'The total number of bytes used by the files in the vector store.', + type: 'integer' + }, + file_counts: { + type: 'object', + properties: { + in_progress: { + description: 'The number of files that are currently being processed.', + type: 'integer' + }, + completed: { + description: 'The number of files that have been successfully processed.', + type: 'integer' + }, + failed: { + description: 'The number of files that have failed to process.', + type: 'integer' + }, + cancelled: { + description: 'The number of files that were cancelled.', + type: 'integer' + }, + total: { + description: 'The total number of files.', + type: 'integer' + } + }, + required: ['in_progress', 'completed', 'failed', 'cancelled', 'total'] + }, + status: { + description: + 'The status of the vector store, which can be either `expired`, `in_progress`, or `completed`. A status of `completed` indicates that the vector store is ready for use.', + type: 'string', + enum: ['expired', 'in_progress', 'completed'] + }, + expires_after: vectorStoreExpirationAfterSchema, + expires_at: { + description: 'The Unix timestamp (in seconds) for when the vector store will expire.', + type: 'integer', + nullable: true + }, + last_active_at: { + description: 'The Unix timestamp (in seconds) for when the vector store was last active.', + type: 'integer', + nullable: true + }, + depends_on: { + type: 'object', + required: ['thread'], + properties: { + thread: { + type: 'object', + required: ['id'], + properties: { + id: { + type: 'string' + } + } + } + } + }, + metadata: metadataSchema + }, + required: [ + 'id', + 'object', + 'usage_bytes', + 'created_at', + 'status', + 'last_active_at', + 'name', + 'file_counts', + 'metadata' + ] +} as const satisfies JSONSchema; + +export type VectorStore = FromSchema; diff --git a/src/vector-stores/entities/vector-store-container.entity.ts b/src/vector-stores/entities/vector-store-container.entity.ts new file mode 100644 index 0000000..2216dee --- /dev/null +++ b/src/vector-stores/entities/vector-store-container.entity.ts @@ -0,0 +1,31 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, ManyToOne, Ref, ref } from '@mikro-orm/core'; + +import { VectorStore } from '@/vector-stores/entities/vector-store.entity.js'; + +@Embeddable() +export class VectorStoreContainer { + @ManyToOne() + vectorStore!: Ref; + + constructor({ vectorStore }: VectorStoreContainerInput) { + this.vectorStore = ref(vectorStore); + } +} + +export type VectorStoreContainerInput = { vectorStore: VectorStore }; diff --git a/src/vector-stores/entities/vector-store-expiration-after.entity.ts b/src/vector-stores/entities/vector-store-expiration-after.entity.ts new file mode 100644 index 0000000..e5d5037 --- /dev/null +++ b/src/vector-stores/entities/vector-store-expiration-after.entity.ts @@ -0,0 +1,39 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Embeddable, Property } from '@mikro-orm/core'; + +export const VectorStoreExpirationAfterAnchor = { + LAST_ACTIVE_AT: 'last_active_at' +}; +export type VectorStoreExpirationAfterAnchor = + (typeof VectorStoreExpirationAfterAnchor)[keyof typeof VectorStoreExpirationAfterAnchor]; + +@Embeddable() +export class VectorStoreExpirationAfter { + @Property() + anchor: VectorStoreExpirationAfterAnchor = VectorStoreExpirationAfterAnchor.LAST_ACTIVE_AT; + + @Property() + days!: number; + + constructor(input: VectorStoreExpirationAfterInput) { + this.anchor = input.anchor; + this.days = input.days; + } +} + +export type VectorStoreExpirationAfterInput = Pick; diff --git a/src/vector-stores/entities/vector-store.entity.ts b/src/vector-stores/entities/vector-store.entity.ts new file mode 100644 index 0000000..1e66685 --- /dev/null +++ b/src/vector-stores/entities/vector-store.entity.ts @@ -0,0 +1,98 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + BeforeUpdate, + Collection, + Embedded, + Entity, + OneToMany, + Property, + QueryOrder +} from '@mikro-orm/core'; +import dayjs from 'dayjs'; + +import { ProjectScopedEntity, ProjectScopedEntityInput } from '@/common/project-scoped.entity'; +import { VectorStoreExpirationAfter } from '@/vector-stores/entities/vector-store-expiration-after.entity.js'; +import { + VectorStoreFile, + VectorStoreFileStatus +} from '@/vector-store-files/entities/vector-store-file.entity.js'; + +@Entity() +export class VectorStore extends ProjectScopedEntity { + getIdPrefix(): string { + return 'vs'; + } + + @Property() + name: string; + + @Property() + description?: string; + + @Embedded({ object: true }) + expiresAfter?: VectorStoreExpirationAfter; + + @Property() + lastActiveAt: Date = new Date(); + + @Property() + expiresAt?: Date; + + @BeforeUpdate() + private updateExpiration() { + if (this.expiresAfter) { + const anchor = this.expiresAfter.anchor as keyof Pick< + VectorStore, + 'lastActiveAt' | 'createdAt' + >; + this.expiresAt = dayjs(this[anchor]).add(this.expiresAfter.days, 'day').toDate(); + } else { + this.expiresAt = undefined; + } + } + + get expired(): boolean { + return this.expiresAt ? this.expiresAt < new Date() : false; + } + + @OneToMany({ + mappedBy: 'vectorStore', + orderBy: [{ createdAt: QueryOrder.ASC }] + }) + files: Collection = new Collection(this); + + @OneToMany({ + mappedBy: 'vectorStore', + where: { status: VectorStoreFileStatus.COMPLETED } + }) + completedFiles = new Collection(this); + + constructor({ name, expiresAfter, ...rest }: VectorStoreInput) { + super(rest); + this.name = name; + this.expiresAfter = expiresAfter; + if (expiresAfter) { + this.expiresAt = dayjs(this[expiresAfter.anchor as keyof this] as Date) + .add(expiresAfter.days, 'day') + .toDate(); + } + } +} + +export type VectorStoreInput = ProjectScopedEntityInput & + Pick; diff --git a/src/vector-stores/vector-stores.module.ts b/src/vector-stores/vector-stores.module.ts new file mode 100644 index 0000000..f83b8da --- /dev/null +++ b/src/vector-stores/vector-stores.module.ts @@ -0,0 +1,133 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FastifyPluginAsyncJsonSchemaToTs } from '@fastify/type-provider-json-schema-to-ts'; +import { StatusCodes } from 'http-status-codes'; + +import { + createVectorStore, + deleteVectorStore, + readVectorStore, + listVectorStores, + updateVectorStore +} from './vector-stores.service.js'; + +import { + VectorStoreCreateBody, + vectorStoreCreateBodySchema, + vectorStoreCreateResponseSchema +} from '@/vector-stores/dtos/vector-store-create.js'; +import { + VectorStoreUpdateBody, + VectorStoreUpdateParams, + vectorStoreUpdateBodySchema, + vectorStoreUpdateParamsSchema, + vectorStoreUpdateResponseSchema +} from '@/vector-stores/dtos/vector-store-update.js'; +import { + VectorStoresListQuery, + vectorStoresListQuerySchema, + vectorStoresListResponseSchema +} from '@/vector-stores/dtos/vector-store-list.js'; +import { + VectorStoreReadParams, + vectorStoreReadParamsSchema, + vectorStoreReadResponseSchema +} from '@/vector-stores/dtos/vector-store-read.js'; +import { + VectorStoreDeleteParams, + vectorStoreDeleteParamsSchema +} from '@/vector-stores/dtos/vector-store-delete.js'; +import { Tag } from '@/swagger.js'; +import { createDeleteSchema } from '@/schema.js'; + +export const vectorStoresModule: FastifyPluginAsyncJsonSchemaToTs = async (app) => { + app.post<{ Body: VectorStoreCreateBody }>( + '/vector_stores', + { + preHandler: app.auth(), + schema: { + body: vectorStoreCreateBodySchema, + response: { + [StatusCodes.OK]: vectorStoreCreateResponseSchema + }, + tags: [Tag.OPENAI_ASSISTANTS_API] + } + }, + async (req) => createVectorStore(req.body) + ); + + app.post<{ Body: VectorStoreUpdateBody; Params: VectorStoreUpdateParams }>( + '/vector_stores/:vector_store_id', + { + preHandler: app.auth(), + schema: { + body: vectorStoreUpdateBodySchema, + params: vectorStoreUpdateParamsSchema, + response: { + [StatusCodes.OK]: vectorStoreUpdateResponseSchema + }, + tags: [Tag.OPENAI_ASSISTANTS_API] + } + }, + async (req) => updateVectorStore({ ...req.body, ...req.params }) + ); + + app.get<{ Querystring: VectorStoresListQuery }>( + '/vector_stores', + { + preHandler: app.auth(), + schema: { + querystring: vectorStoresListQuerySchema, + response: { + [StatusCodes.OK]: vectorStoresListResponseSchema + }, + tags: [Tag.OPENAI_ASSISTANTS_API] + } + }, + async (req) => listVectorStores(req.query) + ); + + app.get<{ Params: VectorStoreReadParams }>( + '/vector_stores/:vector_store_id', + { + preHandler: app.auth(), + schema: { + params: vectorStoreReadParamsSchema, + response: { + [StatusCodes.OK]: vectorStoreReadResponseSchema + }, + tags: [Tag.OPENAI_ASSISTANTS_API] + } + }, + async (req) => readVectorStore(req.params) + ); + + app.delete<{ Params: VectorStoreDeleteParams }>( + '/vector_stores/:vector_store_id', + { + preHandler: app.auth(), + schema: { + params: vectorStoreDeleteParamsSchema, + response: { + [StatusCodes.OK]: createDeleteSchema('vector_store') + }, + tags: [Tag.OPENAI_ASSISTANTS_API] + } + }, + async (req) => deleteVectorStore(req.params) + ); +}; diff --git a/src/vector-stores/vector-stores.service.ts b/src/vector-stores/vector-stores.service.ts new file mode 100644 index 0000000..d329673 --- /dev/null +++ b/src/vector-stores/vector-stores.service.ts @@ -0,0 +1,267 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FilterQuery, ref } from '@mikro-orm/core'; +import dayjs from 'dayjs'; +import { omit, sum } from 'remeda'; + +import { VectorStore } from './entities/vector-store.entity.js'; + +import { VectorStore as VectorStoreDto } from '@/vector-stores/dtos/vector-store.js'; +import { File } from '@/files/entities/file.entity.js'; +import { + VectorStoreReadParams, + VectorStoreReadResponse +} from '@/vector-stores/dtos/vector-store-read.js'; +import { + VectorStoresListQuery, + VectorStoresListResponse +} from '@/vector-stores/dtos/vector-store-list.js'; +import { + VectorStoreCreateBody, + VectorStoreCreateResponse +} from '@/vector-stores/dtos/vector-store-create.js'; +import { + VectorStoreUpdateBody, + VectorStoreUpdateParams, + VectorStoreUpdateResponse +} from '@/vector-stores/dtos/vector-store-update.js'; +import { + VectorStoreDeleteParams, + VectorStoreDeleteResponse +} from '@/vector-stores/dtos/vector-store-delete.js'; +import { ORM } from '@/database.js'; +import { createPaginatedResponse, getListCursor } from '@/utils/pagination.js'; +import { APIError, APIErrorCode } from '@/errors/error.entity.js'; +import { createDeleteResponse } from '@/utils/delete.js'; +import { + VectorStoreFile, + VectorStoreFileStatus +} from '@/vector-store-files/entities/vector-store-file.entity.js'; +import { queue } from '@/vector-store-files/queues/process-file.queue.js'; +import { getServiceLogger } from '@/logger.js'; +import { getUpdatedValue } from '@/utils/update.js'; +import { VectorStoreExpirationAfter } from '@/vector-stores/entities/vector-store-expiration-after.entity.js'; +import { determineChunkingStrategy } from '@/vector-store-files/utils/determineChunkingStrategy.js'; +import { QueueName } from '@/jobs/constants.js'; +import { deleteVectorStoreFiles } from '@/vector-store-files/vector-store-files.service.js'; +import { Thread } from '@/threads/thread.entity.js'; + +const getVectorStoreLogger = (vectorStoreId?: string, vectorStoreFileId?: string) => + getServiceLogger('vectorStore').child({ vectorStoreId, vectorStoreFileId }); + +type VectorStoreFileCounts = { [status in VectorStoreFileStatus]: number }; +type VectorStoreFileStats = { fileCounts: VectorStoreFileCounts; usageBytes: number }; + +export function toDto(vectorStore: VectorStore, fileStats: VectorStoreFileStats): VectorStoreDto { + const fileCounts = fileStats.fileCounts; + const fileProcessingStatus = fileCounts['in_progress'] > 0 ? 'in_progress' : 'completed'; + return { + id: vectorStore.id, + object: 'vector_store', + metadata: vectorStore.metadata ?? {}, + status: vectorStore.expired ? 'expired' : fileProcessingStatus, + file_counts: { + cancelled: fileCounts.cancelled + fileCounts.cancelling, + ...omit(fileCounts, ['cancelled', 'cancelling']), + total: sum(Object.values(fileCounts)) + }, + name: vectorStore.name, + usage_bytes: fileStats.usageBytes, + expires_after: vectorStore.expiresAfter ? { ...vectorStore.expiresAfter } : undefined, + expires_at: vectorStore.expiresAt && dayjs(vectorStore.expiresAt).unix(), + last_active_at: vectorStore.lastActiveAt && dayjs(vectorStore.lastActiveAt).unix(), + created_at: dayjs(vectorStore.createdAt).unix(), + description: vectorStore.description, + depends_on: vectorStore.dependsOn + ? { + thread: { + id: vectorStore.dependsOn.id + } + } + : undefined + }; +} + +async function getFileStats(vectorStores: VectorStore[]): Promise { + const vectorStoreIds = vectorStores.map((v) => v.id); + const fileCountAggregationResult = await ORM.em.aggregate(VectorStoreFile, [ + { $match: { vectorStore: { $in: vectorStoreIds }, deletedAt: null } }, + { $group: { _id: { vectorStore: '$vectorStore', status: '$status' }, count: { $sum: 1 } } }, + { $project: { _id: 0, vectorStore: '$_id.vectorStore', status: '$_id.status', count: 1 } } + ]); + const fileCounts = Object.fromEntries( + vectorStores.map((vectorStore) => [ + vectorStore.id, + { in_progress: 0, completed: 0, cancelled: 0, cancelling: 0, failed: 0 } + ]) + ); + for (const group of fileCountAggregationResult) { + fileCounts[group.vectorStore.toString()][group.status as VectorStoreFileStatus] += group.count; + } + const usageBytes: Record = {}; + + const fileUsageAggregationResult = await ORM.em.aggregate(VectorStoreFile, [ + { $match: { vectorStore: { $in: vectorStoreIds }, deletedAt: null } }, + { $group: { _id: { vectorStore: '$vectorStore' }, sum: { $sum: '$usageBytes' } } }, + { $project: { _id: 0, vectorStore: '$_id.vectorStore', sum: '$sum' } } + ]); + for (const group of fileUsageAggregationResult) { + usageBytes[group.vectorStore.toString()] = group.sum; + } + + return vectorStores.map((vectorStore) => ({ + fileCounts: fileCounts[vectorStore.id], + usageBytes: usageBytes[vectorStore.id] ?? 0 + })); +} + +export async function listVectorStores({ + limit, + order, + order_by, + after, + before, + search, + show_dependent +}: VectorStoresListQuery): Promise { + const where: FilterQuery = {}; + + if (search) { + where.name = new RegExp(search, 'i'); + } + + if (!show_dependent) { + where.dependsOn = { $exists: false }; + } + + const repo = ORM.em.getRepository(VectorStore); + const cursor = await getListCursor( + where, + { limit, order, order_by, after, before }, + repo + ); + const vectorStores = cursor.items; + const fileCounts = await getFileStats(cursor.items); + const fileStatsRecord: Record<`${(typeof vectorStores)[number]['id']}`, VectorStoreFileStats> = + Object.fromEntries(vectorStores.map((vFile, idx) => [vFile.id, fileCounts[idx]])); + + return createPaginatedResponse(cursor, (vectorStoreFile) => + toDto(vectorStoreFile, fileStatsRecord[vectorStoreFile.id]) + ); +} + +export async function createVectorStore( + body: VectorStoreCreateBody +): Promise { + const files = await ORM.em.getRepository(File).find({ id: { $in: body.file_ids ?? [] } }); + if (files.length !== (body.file_ids?.length ?? 0)) { + throw new APIError({ message: 'Some file not found', code: APIErrorCode.INVALID_INPUT }); + } + const dependsOn = body.depends_on + ? ref(await ORM.em.getRepository(Thread).findOneOrFail({ id: body.depends_on.thread.id })) + : undefined; + const vectorStore = new VectorStore({ + name: body.name ?? 'Vector store', + expiresAfter: body.expires_after && new VectorStoreExpirationAfter(body.expires_after), + dependsOn + }); + const vectorStoreFiles = files.map( + (file) => + new VectorStoreFile({ + file: ref(file), + vectorStore: ref(vectorStore), + chunkingStrategy: determineChunkingStrategy(body.chunking_strategy) + }) + ); + vectorStore.files.add(vectorStoreFiles); + // TODO: This is not atomic and can break in the middle (saving vector store and not files) + // This will fail the request, but leave entities behind, should we add support for transactions? + await ORM.em.persistAndFlush([vectorStore, ...vectorStoreFiles]); + try { + for (const vectorStoreFile of vectorStoreFiles) { + try { + await queue.add( + QueueName.VECTOR_STORES_FILE_PROCESSOR, + { vectorStoreFileId: vectorStoreFile.id }, + { jobId: vectorStoreFile.id } + ); + } catch (err) { + getVectorStoreLogger(vectorStore.id, vectorStoreFile.id).error( + { err }, + 'Failed to create vector store file job' + ); + vectorStoreFile.status = VectorStoreFileStatus.FAILED; + } + } + } catch (error) { + await ORM.em.removeAndFlush([vectorStore, ...vectorStoreFiles]); + throw error; + } finally { + await ORM.em.flush(); + } + const in_progress = vectorStoreFiles.length; + const fileCounts = { in_progress, completed: 0, cancelled: 0, cancelling: 0, failed: 0 }; + return toDto(vectorStore, { fileCounts, usageBytes: 0 }); +} + +export async function updateVectorStore({ + vector_store_id, + ...body +}: VectorStoreUpdateBody & VectorStoreUpdateParams): Promise { + const vectorStore = await ORM.em + .getRepository(VectorStore) + .findOneOrFail({ id: vector_store_id }); + + if (vectorStore.expired) { + throw new APIError({ message: 'Vector store is expired', code: APIErrorCode.INVALID_INPUT }); + } + + const { name, expires_after, metadata } = body; + + vectorStore.name = getUpdatedValue(name, vectorStore.name); + vectorStore.metadata = getUpdatedValue(metadata, vectorStore.metadata); + vectorStore.expiresAfter = getUpdatedValue( + expires_after && new VectorStoreExpirationAfter(expires_after), + vectorStore.expiresAfter + ); + await ORM.em.flush(); + const [fileCounts] = await getFileStats([vectorStore]); + return toDto(vectorStore, fileCounts); +} + +export async function readVectorStore({ + vector_store_id +}: VectorStoreReadParams): Promise { + const vectorStore = await ORM.em + .getRepository(VectorStore) + .findOneOrFail({ id: vector_store_id }); + const [fileCounts] = await getFileStats([vectorStore]); + return toDto(vectorStore, fileCounts); +} + +export async function deleteVectorStore({ + vector_store_id +}: VectorStoreDeleteParams): Promise { + const vectorStore = await ORM.em + .getRepository(VectorStore) + .findOneOrFail({ id: vector_store_id }, { populate: ['files'] }); + + vectorStore.delete(); + await deleteVectorStoreFiles(vectorStore.files.slice()); + await ORM.em.flush(); + return createDeleteResponse(vector_store_id, 'vectorStore'); +} diff --git a/tests/e2e/assistants.test.ts b/tests/e2e/assistants.test.ts new file mode 100644 index 0000000..e90a412 --- /dev/null +++ b/tests/e2e/assistants.test.ts @@ -0,0 +1,50 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { expect } from 'vitest'; +import OpenAI from 'openai'; + +import { createClient } from './utils.js'; + +describe('Assistants', () => { + let client: OpenAI; + beforeAll(async () => { + client = createClient(); + }); + + test('CRUD', async () => { + const assistant = await client.beta.assistants.create({ + model: 'meta-llama/llama-3-1-70b-instruct', + tools: [{ type: 'code_interpreter' }] + }); + try { + let retrievedAssistant = await client.beta.assistants.retrieve(assistant.id); + expect(retrievedAssistant).toEqual(assistant); + + const model = 'qwen/qwen2-72b-instruct'; + const updatedAssistant = await client.beta.assistants.update(assistant.id, { + model + }); + expect(updatedAssistant).toEqual({ ...assistant, model }); + + retrievedAssistant = await client.beta.assistants.retrieve(assistant.id); + expect(retrievedAssistant).toEqual(updatedAssistant); + } finally { + await client.beta.assistants.del(assistant.id); + await expect(client.beta.assistants.retrieve(assistant.id)).rejects.toThrow(); + } + }); +}); diff --git a/tests/e2e/files.test.ts b/tests/e2e/files.test.ts new file mode 100644 index 0000000..2af833c --- /dev/null +++ b/tests/e2e/files.test.ts @@ -0,0 +1,47 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { expect } from 'vitest'; +import OpenAI from 'openai'; + +import { createClient } from './utils.js'; + +describe('Files', () => { + let client: OpenAI; + beforeAll(async () => { + client = createClient(); + }); + + test('CRUD', async () => { + const content = 'foobar'; + const type = 'text/plain'; + const file = await client.files.create({ + purpose: 'assistants', + file: new File([content], 'test.txt', { type }) + }); + try { + const retrievedFile = await client.files.retrieve(file.id); + expect(retrievedFile).toEqual(file); + + const retrievedContentResponse = await client.files.content(file.id); + expect(retrievedContentResponse.headers.get('content-type')).toEqual(type); + expect(await retrievedContentResponse.text()).toEqual(content); + } finally { + await client.files.del(file.id); + await expect(client.files.retrieve(file.id)).rejects.toThrow(); + } + }); +}); diff --git a/tests/e2e/messages.test.ts b/tests/e2e/messages.test.ts new file mode 100644 index 0000000..015b33f --- /dev/null +++ b/tests/e2e/messages.test.ts @@ -0,0 +1,59 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { expect } from 'vitest'; +import OpenAI from 'openai'; + +import { createClient } from './utils.js'; + +describe('Messages', () => { + let client: OpenAI; + beforeAll(async () => { + client = createClient(); + }); + + let thread: OpenAI.Beta.Threads.Thread; + beforeEach(async () => { + thread = await client.beta.threads.create(); + }); + + afterEach(async () => { + await client.beta.threads.del(thread.id); + }); + + test('CRUD', async () => { + const message = await client.beta.threads.messages.create(thread.id, { + content: 'foobar', + role: 'user' + }); + try { + let retrievedMessage = await client.beta.threads.messages.retrieve(thread.id, message.id); + expect(retrievedMessage).toEqual(message); + + const metadata = { foo: 'bar' }; + const updatedMessage = await client.beta.threads.messages.update(thread.id, message.id, { + metadata + }); + expect(updatedMessage).toEqual({ ...message, metadata }); + + retrievedMessage = await client.beta.threads.messages.retrieve(thread.id, message.id); + expect(retrievedMessage).toEqual(updatedMessage); + } finally { + await client.beta.threads.messages.del(thread.id, message.id); + await expect(client.beta.threads.messages.retrieve(thread.id, message.id)).rejects.toThrow(); + } + }); +}); diff --git a/tests/e2e/runs.test.ts b/tests/e2e/runs.test.ts new file mode 100644 index 0000000..a3f6678 --- /dev/null +++ b/tests/e2e/runs.test.ts @@ -0,0 +1,228 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { expect } from 'vitest'; +import OpenAI from 'openai'; + +import { createClient } from './utils.js'; + +describe('Runs', () => { + let client: OpenAI; + let file: OpenAI.Files.FileObject; + let vectorStore: OpenAI.Beta.VectorStores.VectorStore; + let assistant: OpenAI.Beta.Assistants.Assistant; + beforeAll(async () => { + client = createClient(); + file = await client.files.create({ + purpose: 'assistants', + file: new File(['ostrich'], 'animal.txt', { type: 'text/plain' }) + }); + vectorStore = await client.beta.vectorStores.create({ file_ids: [file.id] }); + assistant = await client.beta.assistants.create({ + model: 'meta-llama/llama-3-1-70b-instruct' + }); + }); + + afterAll(async () => { + await client.beta.assistants.del(assistant.id); + await client.beta.vectorStores.del(vectorStore.id); + await client.files.del(file.id); + }); + + let thread: OpenAI.Beta.Threads.Thread; + beforeEach(async () => { + thread = await client.beta.threads.create(); + }); + + afterEach(async () => { + await client.beta.threads.del(thread.id); + }); + + test('CRU', async () => { + const run = await client.beta.threads.runs.create(thread.id, { + assistant_id: assistant.id + }); + + let retrievedRun = await client.beta.threads.runs.retrieve(thread.id, run.id); + expect(retrievedRun).toBeDefined(); + + const metadata = { foo: 'bar' }; + const updatedRun = await client.beta.threads.runs.update(thread.id, run.id, { + metadata + }); + expect(updatedRun.metadata).toEqual(metadata); + + retrievedRun = await client.beta.threads.runs.retrieve(thread.id, run.id); + expect(retrievedRun.metadata).toEqual(metadata); + }); + + test('Create run and wait for completion', { timeout: 15_000 }, async () => { + await client.beta.threads.messages.create(thread.id, { role: 'user', content: 'Howdy!' }); + const run = await client.beta.threads.runs.createAndPoll(thread.id, { + assistant_id: assistant.id + }); + expect(run.status).toEqual('completed'); + }); + + describe('Tool usage', { timeout: 30_000 }, () => { + describe('Core', () => { + if (process.env.BEE_CODE_INTERPRETER_URL) { + test('Code interpreter', { timeout: 60_000 }, async () => { + await client.beta.threads.messages.create(thread.id, { + role: 'user', + content: 'Calculate sum of first 6 fibonacci numbers' + }); + const run = await client.beta.threads.runs.createAndPoll(thread.id, { + assistant_id: assistant.id, + tools: [{ type: 'code_interpreter' }] + }); + expect(run.status).toEqual('completed'); + const steps = []; + for await (const step of client.beta.threads.runs.steps.list(run.thread_id, run.id)) { + steps.push(step); + } + expect(steps).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + status: 'completed', + step_details: expect.objectContaining({ + tool_calls: expect.arrayContaining([ + expect.objectContaining({ type: 'code_interpreter' }) + ]) + }) + }) + ]) + ); + }); + } + + test('File search', { timeout: 60_000 }, async () => { + await client.beta.threads.messages.create(thread.id, { + role: 'user', + content: 'Use File Search tool with query "animal"' + }); + await client.beta.threads.update(thread.id, { + tool_resources: { + file_search: { vector_store_ids: [vectorStore.id] } + } + }); + const run = await client.beta.threads.runs.createAndPoll(thread.id, { + assistant_id: assistant.id, + tools: [ + { + type: 'file_search' + } + ] + }); + expect(run.status).toEqual('completed'); + + const steps = []; + for await (const step of client.beta.threads.runs.steps.list(run.thread_id, run.id)) { + steps.push(step); + } + expect(steps).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + status: 'completed', + step_details: expect.objectContaining({ + tool_calls: expect.arrayContaining([ + expect.objectContaining({ type: 'file_search' }) + ]) + }) + }) + ]) + ); + }); + + test('Function', async () => { + await client.beta.threads.messages.create(thread.id, { + role: 'user', + content: 'Tell me where do I live?' + }); + let run = await client.beta.threads.runs.createAndPoll(thread.id, { + assistant_id: assistant.id, + tools: [ + { + type: 'function', + function: { + name: 'getLocation', + description: "Retrieves user's location, use function call exactly once" + } + } + ] + }); + expect(run.status).toEqual('requires_action'); + expect(run.required_action?.submit_tool_outputs.tool_calls).toHaveLength(1); + expect(run.required_action?.submit_tool_outputs.tool_calls[0].function.name).toBe( + 'getLocation' + ); + run = await client.beta.threads.runs.submitToolOutputsAndPoll(run.thread_id, run.id, { + tool_outputs: [ + { + tool_call_id: run.required_action?.submit_tool_outputs.tool_calls[0].id, + output: 'Venice' + } + ] + }); + expect(run.status).toEqual('completed'); + }); + }); + + describe('System', () => { + test('File read', async () => { + await client.beta.threads.messages.create(thread.id, { + role: 'user', + content: 'Read the full content of the attached file.', + // @ts-expect-error not supported by OpenAI + attachments: [{ file_id: file.id, tools: [{ type: 'system' as any, id: 'read_file' }] }] + }); + const run = await client.beta.threads.runs.createAndPoll(thread.id, { + assistant_id: assistant.id, + tools: [ + { + type: 'system' as any, + // @ts-expect-error not supported by OpenAI + system: { + id: 'read_file' + } + } + ] + }); + expect(run.status).toEqual('completed'); + + const steps = []; + for await (const step of client.beta.threads.runs.steps.list(run.thread_id, run.id)) { + steps.push(step); + } + expect(steps).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + status: 'completed', + step_details: expect.objectContaining({ + tool_calls: expect.arrayContaining([ + expect.objectContaining({ + type: 'system', + system: expect.objectContaining({ id: 'read_file' }) + }) + ]) + }) + }) + ]) + ); + }); + }); + }); +}); diff --git a/tests/e2e/threads.test.ts b/tests/e2e/threads.test.ts new file mode 100644 index 0000000..c2963a3 --- /dev/null +++ b/tests/e2e/threads.test.ts @@ -0,0 +1,47 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { expect } from 'vitest'; +import OpenAI from 'openai'; + +import { createClient } from './utils.js'; + +describe('Threads', () => { + let client: OpenAI; + beforeAll(async () => { + client = createClient(); + }); + + test('CRUD', async () => { + const thread = await client.beta.threads.create(); + try { + let retrievedThread = await client.beta.threads.retrieve(thread.id); + expect(retrievedThread).toEqual(thread); + + const metadata = { foo: 'bar' }; + const updatedThread = await client.beta.threads.update(thread.id, { + metadata + }); + expect(updatedThread).toEqual({ ...thread, metadata }); + + retrievedThread = await client.beta.threads.retrieve(thread.id); + expect(retrievedThread).toEqual(updatedThread); + } finally { + await client.beta.threads.del(thread.id); + await expect(client.beta.threads.retrieve(thread.id)).rejects.toThrow(); + } + }); +}); diff --git a/tests/e2e/tools.test.ts b/tests/e2e/tools.test.ts new file mode 100644 index 0000000..73279ce --- /dev/null +++ b/tests/e2e/tools.test.ts @@ -0,0 +1,74 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { expect } from 'vitest'; +import OpenAI, { NotFoundError } from 'openai'; +import { randomString } from 'remeda'; + +import { createClient } from './utils.js'; + +import { Tool } from '@/tools/dtos/tool.js'; +import { ToolDeleteResponse } from '@/tools/dtos/tool-delete.js'; + +describe('Tools', () => { + let client: OpenAI; + beforeAll(async () => { + client = createClient(); + }); + + if (process.env.BEE_CODE_INTERPRETER_URL) { + test('CRUD', async () => { + const tool: Tool = await client.post('/tools', { + body: { + source_code: `import typing +import requests + +def fun_${randomString(5)}(lat: float, lon: float): + """ + Get the current weather at a location. + + :param lat: A latitude. + :param lon: A longitude. + :return: A dictionary with the current weather. + """ + url = "https://api.open-meteo.com/v1/forecast?latitude={}&longitude={}¤t=temperature_2m,relative_humidity_2m,apparent_temperature,is_day,precipitation,rain,showers,snowfall,weather_code,cloud_cover,pressure_msl,surface_pressure,wind_speed_10m,wind_direction_10m,wind_gusts_10m".format(lat, lon) + response = requests.get(url) + response.raise_for_status() + return response.json()`, + user_description: 'Get information about current weather' + } + }); + try { + const retrievedTool: Tool = await client.get(`/tools/${tool.id}`); + expect(retrievedTool).toEqual(tool); + + const newName = `fun_${randomString(8)}`; + const updatedTool: Tool = await client.post(`/tools/${tool.id}`, { + body: { name: newName } + }); + expect(updatedTool).toHaveProperty('name', newName); + } finally { + const deleted: ToolDeleteResponse = await client.delete(`/tools/${tool.id}`); + expect(deleted.object).toEqual('tool.deleted'); + try { + await client.get(`/tools/${tool.id}`); + } catch (e) { + expect(e).toBeInstanceOf(NotFoundError); + } + } + }); + } +}); diff --git a/tests/e2e/utils.ts b/tests/e2e/utils.ts new file mode 100644 index 0000000..fc56809 --- /dev/null +++ b/tests/e2e/utils.ts @@ -0,0 +1,24 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import OpenAI from 'openai'; + +export function createClient() { + return new OpenAI({ + baseURL: new URL('/v1', process.env.BEE_URL ?? 'http://localhost').toString(), + apiKey: process.env.BEE_TOKEN + }); +} diff --git a/tests/setup.ts b/tests/setup.ts new file mode 100644 index 0000000..dd67a2a --- /dev/null +++ b/tests/setup.ts @@ -0,0 +1,22 @@ +/** + * Copyright 2024 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import dotenv from 'dotenv'; +dotenv.config(); +dotenv.config({ + path: '.env.test', + override: true +}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..4f89cd0 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,32 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "Bundler", + "types": [ + "node", + "vitest/globals" + ], + "declarationMap": false, + "declaration": false, + "resolveJsonModule": true, + "sourceMap": false, + "outDir": "./dist", + "removeComments": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "strict": true, + "skipLibCheck": true, + "paths": { + "@/*": [ + "./src/*" + ], + "@tests/*": [ + "./tests/*" + ], + }, + "useUnknownInCatchVariables": false, + } +} \ No newline at end of file diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..af9ba50 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,47 @@ +import { resolve } from 'node:path'; + +import tsConfigPaths from 'vite-tsconfig-paths'; +import { externalizeDeps } from 'vite-plugin-externalize-deps'; +import dtsPlugin from 'vite-plugin-dts'; +import { glob } from 'glob'; + +const rootDir = 'src'; + +/** @type {import('vite').UserConfig} */ +export default { + test: { + globals: true, + passWithNoTests: true, + testTimeout: 15_000, + setupFiles: ['./tests/setup.ts'], + deps: { + interopDefault: false + } + }, + build: { + minify: false, + target: 'node22.2.0', + outDir: './dist', + lib: { + entry: glob.sync(resolve(__dirname, 'src/**/*.ts')), + formats: ['es'] + }, + rollupOptions: { + output: { + preserveModules: true, + preserveModulesRoot: rootDir + } + } + }, + resolve: { + alias: { + '@/': resolve(resolve(__dirname), rootDir), + '@tests/': resolve(resolve(__dirname), 'tests') + } + }, + plugins: [ + tsConfigPaths(), + dtsPlugin({ entryRoot: rootDir, pathsToAliases: true }), + externalizeDeps() + ] +};