diff --git a/PR_MESSAGE.md b/PR_MESSAGE.md deleted file mode 100644 index 9ef2058..0000000 --- a/PR_MESSAGE.md +++ /dev/null @@ -1,76 +0,0 @@ -# Pull Request: BE-036 Implement Backend Performance Profiling Service - -## ๐Ÿ“š Overview -This PR implements the **Backend Performance Profiling Service** (BE-036) for the TruthBounty backend. It continuously measures application latency, profiles database queries, Redis operations, blockchain RPC calls, queue processing, notification delivery, collects process resource utilization metrics (CPU/Memory), builds execution timelines and flame graphs, supports production-safe adaptive sampling, and automates performance regression detection across historical baseline snapshots. - ---- - -## ๐ŸŽฏ Objectives & Acceptance Criteria Met -- [x] **Request Profiling**: HTTP request duration, route path, method, status codes, payload sizes, memory/CPU deltas. -- [x] **Database Profiling**: Query timing, entity attribution, slow query flagging (> 100ms default threshold), parameter sanitization. -- [x] **Redis Profiling**: Command timing (GET, SET, DEL), key patterns, hit/miss metrics. -- [x] **Blockchain RPC Profiling**: Provider call latency for Optimism, Ethereum, and Soroban/Stellar RPC methods. -- [x] **Queue & Job Profiling**: BullMQ background worker job execution duration and status tracking. -- [x] **Notification Profiling**: Webhook dispatch and notification delivery timing. -- [x] **Resource Metrics Collection**: Periodic process memory (heap/rss/arrayBuffers) and CPU usage percentage sampling. -- [x] **Flame Graphs & Timelines**: Hierarchical call tree visualization with time percentage allocations. -- [x] **Configurable Production-Safe Sampling**: `fixed-rate`, `adaptive` (load-based scaling), `route-based`, and `header-based` (`x-profile-request`) overrides. -- [x] **Historical Comparisons & Regression Detection**: Baseline snapshot comparison and automated regression detection flagging components with > 20% latency degradation. -- [x] **Dashboards & REST Endpoints**: Operational HTML dashboard and REST endpoints under `/profiler/*`. -- [x] **Comprehensive Documentation**: Added Performance Guide, Operations Manual, Backend Documentation, and Monitoring Guide. -- [x] **Test Coverage (90%+)**: Unit tests, controller tests, sampling strategy validation, overhead benchmarking (< 0.1ms overhead per trace). - ---- - -## ๐Ÿงฉ Technical Changes Included - -### 1. Core Profiling Engine (`src/profiler`) -- `src/profiler/interfaces/profiler.interface.ts`: Data structures for `Span`, `Trace`, `FlameGraphNode`, `LatencyDistribution`, `BottleneckReport`, `SamplingConfig`, `HistoricalSnapshot`, and `RegressionReport`. -- `src/profiler/profiler.service.ts`: Node.js `AsyncLocalStorage`-driven context tracing, circular trace buffer (up to 5,000 traces), percentiles calculator (p50..p99), flame graph generator, historical baseline comparisons, and regression algorithms. -- `src/profiler/profiler.interceptor.ts`: Global NestJS HTTP request interceptor. - -### 2. Sub-Profilers (`src/profiler/sub-profilers/`) -- `database-profiler.ts`: TypeORM / Prisma query execution wrapper. -- `redis-profiler.ts`: Redis command latency wrapper. -- `blockchain-profiler.ts`: Ethers.js & Soroban/Stellar RPC call wrapper. -- `job-profiler.ts`: BullMQ background job worker wrapper. -- `notification-profiler.ts`: Webhook delivery wrapper. - -### 3. REST Controller & Dashboard (`src/profiler/profiler.controller.ts`) -- `GET /profiler/summary`: High-level summary of profiling status and system overview. -- `GET /profiler/metrics`: Latency distribution percentiles (p50..p99) and resource metrics. -- `GET /profiler/traces`: Filterable execution traces. -- `GET /profiler/traces/:id`: Detailed trace breakdown with sub-spans. -- `GET /profiler/traces/:id/flamegraph`: Flame graph tree node structure. -- `GET /profiler/bottlenecks`: Bottleneck report (slow queries, endpoints, Redis, RPC, CPU hotspots). -- `GET /profiler/snapshots`: List or take historical performance snapshots. -- `GET /profiler/compare`: Delta comparison between snapshot baselines. -- `GET /profiler/regressions`: Performance regression detection report. -- `GET /profiler/sampling` & `PUT /profiler/sampling`: View/update dynamic sampling rates & strategies. -- `GET /profiler/dashboard`: Interactive HTML/JSON operational dashboard. - -### 4. NestJS Application Integration -- `src/profiler/profiler.module.ts`: NestJS module encapsulating Profiler providers and controllers. -- `src/app.module.ts`: Registered `ProfilerModule` and global `ProfilerInterceptor`. - -### 5. Documentation (`docs/`) -- `docs/PERFORMANCE_GUIDE.md`: Performance guide & backend profiling usage. -- `docs/OPERATIONS_MANUAL.md`: Operating procedures, interpreting flame graphs, baseline workflows. -- `docs/BACKEND_DOCUMENTATION.md`: Architecture diagrams, data schemas, AsyncLocalStorage details. -- `docs/MONITORING_GUIDE.md`: Integration with BE-011 Metrics Service, BE-027 API Analytics, and BE-030 Health Diagnostics. - ---- - -## ๐Ÿงช Testing & Verification - -Comprehensive Jest test suite added in `src/profiler/tests/`: -- `profiler.service.spec.ts`: Trace lifecycles, sub-span tracking, percentiles calculation, flame graphs, snapshots, regression algorithms. -- `profiler.controller.spec.ts`: Controller REST endpoints and input validation. -- `sampling-validation.spec.ts`: Fixed-rate, adaptive CPU scaling, header override (`x-profile-request`), and route-specific sampling. -- `performance-overhead.spec.ts`: Benchmarking verifying profiling overhead is strictly < 0.1ms per operation. -- `sub-profilers.spec.ts`: Database, Redis, Blockchain, Queue, and Notification sub-profilers testing. - ---- - -## ๐Ÿท๏ธ Labels -`backend` `performance` `monitoring` `complexity-high` `stellar-wave` diff --git a/docs/AI_ARCHITECTURE.md b/docs/AI_ARCHITECTURE.md new file mode 100644 index 0000000..87d62ef --- /dev/null +++ b/docs/AI_ARCHITECTURE.md @@ -0,0 +1,21 @@ +# AI Architecture + +## Overview +The AI Assistant Backend API serves as the orchestration layer between TruthBounty's verified protocol data and external language models (LLMs). It centralizes prompt management, RAG (Retrieval-Augmented Generation), and usage tracking. + +## Components +1. **Conversation Management**: Handles storing and retrieving conversation history. Ensure continuity across sessions. +2. **RAG Service**: Retrieves context from verified sources (e.g. database claims, governance proposals, protocol docs). +3. **LLM Provider**: Abstracted interface to communicate with OpenAI, Anthropic, or future model providers. Configurable via environment variables. +4. **Security & Validation**: Checks for prompt injections, enforces rate limits, and scopes access to authenticated users. +5. **Usage Tracking**: Monitors token usage, latency, and provider utilization for analytics. + +## Data Flow +1. User sends message -> API Gateway -> AI Assistant Controller. +2. AI Assistant Service retrieves conversation history (up to 10 previous messages for short-term memory). +3. RAG Service retrieves relevant protocol context based on user query. +4. System prompt, context, and conversation history are combined. +5. The payload is sent to the LLM Provider Service. +6. The LLM Provider returns the response, which is saved to the database. +7. Usage metrics are logged asynchronously. +8. API response is returned to the client. diff --git a/docs/PROMPT_ENGINEERING_GUIDE.md b/docs/PROMPT_ENGINEERING_GUIDE.md new file mode 100644 index 0000000..13d02b6 --- /dev/null +++ b/docs/PROMPT_ENGINEERING_GUIDE.md @@ -0,0 +1,22 @@ +# Prompt Engineering Guide + +## System Prompt Principles +The system prompt for TruthBounty's AI Assistant is critical for ensuring the AI is helpful, harmless, and strictly grounded in protocol reality. + +### 1. Grounding in Truth +Always instruct the AI to rely exclusively on the provided context (RAG). Do not let it hallucinate rules or governance mechanics. +*Example:* "Your answers must be grounded ONLY in verified protocol information. If you do not know the answer based on the provided context, state clearly that you do not know." + +### 2. Role Definition +Define the assistant's persona. +*Example:* "You are the TruthBounty AI Assistant. You help contributors navigate the protocol, explain proposals, analyze claims, and interpret disputes." + +### 3. Safety & Limitations +Explicitly state what the AI cannot do. +*Example:* "Do not fabricate protocol state. Do not attempt to execute any privileged operations autonomously. You are a read-only assistant." + +## Tool Usage +When the AI uses tools (e.g. claim lookup), ensure the prompt describes the tool's exact input format and output interpretation. + +## RAG Context Formatting +Provide context in a structured, consistent format (e.g. JSON or Markdown bullet points) so the LLM can easily parse the facts before generating a response. diff --git a/package-lock.json b/package-lock.json index e3cc6ef..7d9c558 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,10 +9,12 @@ "version": "0.0.1", "license": "UNLICENSED", "dependencies": { + "@anthropic-ai/sdk": "^0.115.0", "@bull-board/api": "^7.1.5", "@bull-board/express": "^7.1.5", "@bull-board/nestjs": "^7.1.5", "@libsql/client": "^0.17.0", + "@nestjs/axios": "^4.0.1", "@nestjs/bullmq": "^11.0.4", "@nestjs/common": "^11.1.12", "@nestjs/config": "^4.0.2", @@ -28,6 +30,7 @@ "@prisma/adapter-libsql": "^7.3.0", "@prisma/client": "^7.3.0", "@types/pg": "^8.16.0", + "axios": "^1.18.1", "bullmq": "^5.77.6", "class-transformer": "^0.5.1", "class-validator": "^0.14.3", @@ -37,7 +40,7 @@ "jsonwebtoken": "^9.0.3", "multiformats": "^14.0.0", "nestjs-pino": "^4.1.0", - "openai": "^7.0.0", + "openai": "^7.1.0", "passport": "^0.7.0", "passport-jwt": "^4.0.1", "pg": "^8.17.2", @@ -235,6 +238,27 @@ "tslib": "^2.1.0" } }, + "node_modules/@anthropic-ai/sdk": { + "version": "0.115.0", + "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.115.0.tgz", + "integrity": "sha512-BJrFIVyjNuU8lfDyIJTvlRYzgQg+zEl78BxE7fq8esULsGz9IRQvGtW5spq3tydmtjQb/GFdooKGdGsetpx+lQ==", + "license": "MIT", + "dependencies": { + "json-schema-to-ts": "^3.1.1", + "standardwebhooks": "^1.0.0" + }, + "bin": { + "anthropic-ai-sdk": "bin/cli" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } + } + }, "node_modules/@babel/code-frame": { "version": "7.29.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", @@ -696,6 +720,15 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/template": { "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", @@ -2706,6 +2739,17 @@ "integrity": "sha512-kTPhdZyTQxB+2wpiRcFWrDcejc4JI6tkPuS7UZCG4l6Zvc5kU/gGQ/ozvHTh1XR5tS+UlfAfGuPajjzQjCiHCw==", "license": "MIT" }, + "node_modules/@nestjs/axios": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-4.0.1.tgz", + "integrity": "sha512-68pFJgu+/AZbWkGu65Z3r55bTsCPlgyKaV4BSG8yUAD72q1PPuyVRgUwFv6BxdnibTUHlyxm06FmYWNC+bjN7A==", + "license": "MIT", + "peerDependencies": { + "@nestjs/common": "^10.0.0 || ^11.0.0", + "axios": "^1.3.1", + "rxjs": "^7.0.0" + } + }, "node_modules/@nestjs/bull-shared": { "version": "11.0.4", "resolved": "https://registry.npmjs.org/@nestjs/bull-shared/-/bull-shared-11.0.4.tgz", @@ -3783,6 +3827,12 @@ "integrity": "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==", "license": "MIT" }, + "node_modules/@stablelib/base64": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@stablelib/base64/-/base64-1.0.1.tgz", + "integrity": "sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ==", + "license": "MIT" + }, "node_modules/@standard-schema/spec": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", @@ -3878,7 +3928,7 @@ "version": "1.15.11", "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.15.11.tgz", "integrity": "sha512-iLmLTodbYxU39HhMPaMUooPwO/zqJWvsqkrXv1ZI38rMb048p6N7qtAtTp37sw9NzSrvH6oli8EdDygo09IZ/w==", - "dev": true, + "devOptional": true, "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { @@ -3920,7 +3970,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -3937,7 +3986,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -3954,7 +4002,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -3971,7 +4018,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -3988,7 +4034,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -4005,7 +4050,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -4022,7 +4066,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -4039,7 +4082,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -4056,7 +4098,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -4073,7 +4114,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "Apache-2.0 AND MIT", "optional": true, "os": [ @@ -4087,14 +4127,14 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", - "dev": true, + "devOptional": true, "license": "Apache-2.0" }, "node_modules/@swc/types": { "version": "0.1.25", "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.25.tgz", "integrity": "sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g==", - "dev": true, + "devOptional": true, "license": "Apache-2.0", "dependencies": { "@swc/counter": "^0.1.3" @@ -5487,7 +5527,6 @@ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "license": "MIT", - "optional": true, "dependencies": { "debug": "4" }, @@ -5775,7 +5814,6 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true, "license": "MIT" }, "node_modules/atomic-sleep": { @@ -5812,6 +5850,18 @@ "node": ">= 6.0.0" } }, + "node_modules/axios": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.18.1.tgz", + "integrity": "sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.5", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, "node_modules/b4a": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.8.0.tgz", @@ -6831,7 +6881,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" @@ -7315,7 +7364,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.4.0" @@ -7659,7 +7707,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", - "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -8319,6 +8366,12 @@ "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", "license": "MIT" }, + "node_modules/fast-sha256": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-sha256/-/fast-sha256-1.3.0.tgz", + "integrity": "sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ==", + "license": "Unlicense" + }, "node_modules/fast-uri": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", @@ -8558,6 +8611,26 @@ "dev": true, "license": "ISC" }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/for-each": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", @@ -8621,7 +8694,6 @@ "version": "4.0.5", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", - "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -8648,7 +8720,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -8658,7 +8729,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "license": "MIT", "dependencies": { "mime-db": "1.52.0" @@ -9301,7 +9371,6 @@ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "license": "MIT", - "optional": true, "dependencies": { "agent-base": "6", "debug": "4" @@ -10596,6 +10665,19 @@ "dev": true, "license": "MIT" }, + "node_modules/json-schema-to-ts": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/json-schema-to-ts/-/json-schema-to-ts-3.1.1.tgz", + "integrity": "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "ts-algebra": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -12028,9 +12110,9 @@ } }, "node_modules/openai": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/openai/-/openai-7.0.0.tgz", - "integrity": "sha512-NaAHnDTmut8tl1Is/T2bmRGQm67fEb9VrxdlVradQoh6WnHNPToQeOZiVjLa7LV9uq0Ha4C5twgOsp4+0UWwYg==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/openai/-/openai-7.1.0.tgz", + "integrity": "sha512-7xWJ9iO5z5u1dnIUGwoUmZHkSyrUYXX2cUxo2E/26iKFrSC8IdEak7z94d5UntU7z+S/Cid33hYymwMSab2fZQ==", "license": "Apache-2.0", "engines": { "node": ">=22.0.0" @@ -12996,6 +13078,15 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/pump": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", @@ -14164,6 +14255,16 @@ "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==", "license": "MIT" }, + "node_modules/standardwebhooks": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/standardwebhooks/-/standardwebhooks-1.0.0.tgz", + "integrity": "sha512-BbHGOQK9olHPMvQNHWul6MYlrRTAOKn03rOe4A8O3CLWhNf4YHBqq2HJKKC+sfqpxiBY52pNeesD6jIiLDz8jg==", + "license": "MIT", + "dependencies": { + "@stablelib/base64": "^1.0.0", + "fast-sha256": "^1.3.0" + } + }, "node_modules/statuses": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", @@ -14898,6 +14999,12 @@ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "license": "MIT" }, + "node_modules/ts-algebra": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-algebra/-/ts-algebra-2.0.0.tgz", + "integrity": "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==", + "license": "MIT" + }, "node_modules/ts-api-utils": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", diff --git a/package.json b/package.json index 2be4c24..caf7431 100644 --- a/package.json +++ b/package.json @@ -31,10 +31,12 @@ "benchmark:compare": "ts-node scripts/compare-benchmarks.ts" }, "dependencies": { + "@anthropic-ai/sdk": "^0.115.0", "@bull-board/api": "^7.1.5", "@bull-board/express": "^7.1.5", "@bull-board/nestjs": "^7.1.5", "@libsql/client": "^0.17.0", + "@nestjs/axios": "^4.0.1", "@nestjs/bullmq": "^11.0.4", "@nestjs/common": "^11.1.12", "@nestjs/config": "^4.0.2", @@ -50,6 +52,7 @@ "@prisma/adapter-libsql": "^7.3.0", "@prisma/client": "^7.3.0", "@types/pg": "^8.16.0", + "axios": "^1.18.1", "bullmq": "^5.77.6", "class-transformer": "^0.5.1", "class-validator": "^0.14.3", @@ -59,7 +62,7 @@ "jsonwebtoken": "^9.0.3", "multiformats": "^14.0.0", "nestjs-pino": "^4.1.0", - "openai": "^7.0.0", + "openai": "^7.1.0", "passport": "^0.7.0", "passport-jwt": "^4.0.1", "pg": "^8.17.2", diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 9a5e68e..a1cccad 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -44,6 +44,7 @@ model User { wallets Wallet[] sybilScores SybilScore[] worldIdVerifications WorldIdVerification[] + conversations Conversation[] } model Wallet { @@ -115,3 +116,41 @@ model WorldIdVerification { @@map("world_id_verifications") } + +model Conversation { + id String @id @default(uuid()) + title String? + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + userId String + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + messages Message[] + + @@index([userId]) +} + +model Message { + id String @id @default(uuid()) + role String // "user", "assistant", "system" + content String + conversationId String + conversation Conversation @relation(fields: [conversationId], references: [id], onDelete: Cascade) + createdAt DateTime @default(now()) + + @@index([conversationId]) +} + +model AiUsageMetric { + id String @id @default(uuid()) + userId String? + provider String // e.g., "openai", "anthropic" + model String + promptTokens Int @default(0) + completionTokens Int @default(0) + totalTokens Int @default(0) + latencyMs Int @default(0) + createdAt DateTime @default(now()) + + @@index([userId]) + @@index([provider]) +} diff --git a/src/ai-assistant/ai-assistant.controller.ts b/src/ai-assistant/ai-assistant.controller.ts new file mode 100644 index 0000000..71c0080 --- /dev/null +++ b/src/ai-assistant/ai-assistant.controller.ts @@ -0,0 +1,53 @@ +import { Controller, Get, Post, Body, Param, Delete, UseGuards, Req } from '@nestjs/common'; +import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth } from '@nestjs/swagger'; +import { AiAssistantService } from './ai-assistant.service'; +import { CreateConversationDto, SendMessageDto } from './dto/ai-assistant.dto'; +import { JwtAuthGuard } from '../auth/jwt-auth.guard'; +import { CurrentUser } from '../common/decorators/current-user.decorator'; + +@ApiTags('AI Assistant') +@ApiBearerAuth() +@UseGuards(JwtAuthGuard) +@Controller('ai/conversations') +export class AiAssistantController { + constructor(private readonly aiAssistantService: AiAssistantService) {} + + @Post() + @ApiOperation({ summary: 'Create a new AI conversation' }) + @ApiResponse({ status: 201, description: 'Conversation created successfully.' }) + async createConversation(@CurrentUser() user: any, @Body() dto: CreateConversationDto) { + return this.aiAssistantService.createConversation(user.id || user.userId || user.sub, dto); + } + + @Get() + @ApiOperation({ summary: 'Get all conversations for the authenticated user' }) + @ApiResponse({ status: 200, description: 'List of conversations.' }) + async getConversations(@CurrentUser() user: any) { + return this.aiAssistantService.getConversations(user.id || user.userId || user.sub); + } + + @Get(':id/messages') + @ApiOperation({ summary: 'Get messages for a specific conversation' }) + @ApiResponse({ status: 200, description: 'List of messages in the conversation.' }) + async getConversationMessages(@CurrentUser() user: any, @Param('id') conversationId: string) { + return this.aiAssistantService.getConversationMessages(user.id || user.userId || user.sub, conversationId); + } + + @Post(':id/messages') + @ApiOperation({ summary: 'Send a message to the AI Assistant' }) + @ApiResponse({ status: 201, description: 'AI Assistant response.' }) + async sendMessage( + @CurrentUser() user: any, + @Param('id') conversationId: string, + @Body() dto: SendMessageDto, + ) { + return this.aiAssistantService.sendMessage(user.id || user.userId || user.sub, conversationId, dto); + } + + @Delete(':id') + @ApiOperation({ summary: 'Delete a conversation' }) + @ApiResponse({ status: 200, description: 'Conversation deleted.' }) + async deleteConversation(@CurrentUser() user: any, @Param('id') conversationId: string) { + return this.aiAssistantService.deleteConversation(user.id || user.userId || user.sub, conversationId); + } +} diff --git a/src/ai-assistant/ai-assistant.module.ts b/src/ai-assistant/ai-assistant.module.ts index f88109a..52e7567 100644 --- a/src/ai-assistant/ai-assistant.module.ts +++ b/src/ai-assistant/ai-assistant.module.ts @@ -1,68 +1,15 @@ import { Module } from '@nestjs/common'; -import { ConfigModule } from '@nestjs/config'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { RedisModule } from '../redis/redis.module'; -import { Conversation } from './entities/conversation.entity'; -import { Message } from './entities/message.entity'; -import { ContextDocument } from './entities/context-document.entity'; -import { AiUsageLog } from './entities/ai-usage-log.entity'; -import aiConfig from './config/ai.config'; - -import { OpenAiProvider } from './providers/openai.provider'; -import { MockProvider } from './providers/mock.provider'; - -import { AiAssistantCache } from './cache/ai-assistant.cache'; -import { AiMetricsService } from './metrics/ai-metrics.service'; -import { SafetyGuardrailService } from './services/safety-guardrail.service'; -import { ContextRetrievalService } from './services/context-retrieval.service'; -import { AiProviderRouterService } from './services/ai-provider-router.service'; -import { PromptOrchestrationService } from './services/prompt-orchestration.service'; -import { ConversationService } from './services/conversation.service'; -import { UsageAnalyticsService } from './services/usage-analytics.service'; -import { KnowledgeBaseService } from './services/knowledge-base.service'; - -import { AiConversationsController } from './controllers/ai-conversations.controller'; -import { AiStreamController } from './controllers/ai-stream.controller'; -import { AiKnowledgeBaseController } from './controllers/ai-knowledge-base.controller'; -import { AiAnalyticsController } from './controllers/ai-analytics.controller'; - -import { AiExceptionFilter } from './common/filters/ai-exception.filter'; -import { AiResponseInterceptor } from './common/interceptors/ai-response.interceptor'; -import { RolesGuard } from '../auth/guards/roles.guard'; +import { AiAssistantController } from './ai-assistant.controller'; +import { AiAssistantService } from './ai-assistant.service'; +import { LlmProviderService } from './llm-provider.service'; +import { RagService } from './rag.service'; +import { PrismaModule } from '../prisma/prisma.module'; +// Note: assuming PrismaModule is exported from '../prisma/prisma.module' @Module({ - imports: [ - ConfigModule.forFeature(aiConfig), - TypeOrmModule.forFeature([ - Conversation, - Message, - ContextDocument, - AiUsageLog, - ]), - RedisModule, - ], - controllers: [ - AiConversationsController, - AiStreamController, - AiKnowledgeBaseController, - AiAnalyticsController, - ], - providers: [ - OpenAiProvider, - MockProvider, - AiAssistantCache, - AiMetricsService, - SafetyGuardrailService, - ContextRetrievalService, - AiProviderRouterService, - PromptOrchestrationService, - ConversationService, - UsageAnalyticsService, - KnowledgeBaseService, - AiExceptionFilter, - AiResponseInterceptor, - RolesGuard, - ], - exports: [ConversationService, UsageAnalyticsService, KnowledgeBaseService], + imports: [PrismaModule], + controllers: [AiAssistantController], + providers: [AiAssistantService, LlmProviderService, RagService], + exports: [AiAssistantService], }) export class AiAssistantModule {} diff --git a/src/ai-assistant/ai-assistant.service.spec.ts b/src/ai-assistant/ai-assistant.service.spec.ts new file mode 100644 index 0000000..3ee284b --- /dev/null +++ b/src/ai-assistant/ai-assistant.service.spec.ts @@ -0,0 +1,69 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { AiAssistantService } from './ai-assistant.service'; +import { PrismaService } from '../prisma/prisma.service'; +import { LlmProviderService } from './llm-provider.service'; +import { RagService } from './rag.service'; + +describe('AiAssistantService', () => { + let service: AiAssistantService; + let prismaService: PrismaService; + + beforeEach(async () => { + const mockPrismaService = { + conversation: { + create: jest.fn().mockResolvedValue({ id: 'conv-1', userId: 'user-1' }), + findMany: jest.fn().mockResolvedValue([]), + findUnique: jest.fn().mockResolvedValue({ id: 'conv-1', userId: 'user-1' }), + update: jest.fn().mockResolvedValue({}), + delete: jest.fn().mockResolvedValue({}), + }, + message: { + create: jest.fn().mockResolvedValue({ id: 'msg-1' }), + findMany: jest.fn().mockResolvedValue([]), + }, + aiUsageMetric: { + create: jest.fn().mockResolvedValue({}), + }, + }; + + const mockLlmProvider = { + generateResponse: jest.fn().mockResolvedValue({ + content: 'Mock AI Response', + usage: { prompt_tokens: 10, completion_tokens: 20, total_tokens: 30 }, + provider: 'mock', + model: 'mock', + }), + }; + + const mockRagService = { + retrieveContext: jest.fn().mockResolvedValue('mock context'), + }; + + const module: TestingModule = await Test.createTestingModule({ + providers: [ + AiAssistantService, + { provide: PrismaService, useValue: mockPrismaService }, + { provide: LlmProviderService, useValue: mockLlmProvider }, + { provide: RagService, useValue: mockRagService }, + ], + }).compile(); + + service = module.get(AiAssistantService); + prismaService = module.get(PrismaService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); + + it('should create a conversation', async () => { + const result = await service.createConversation('user-1', { title: 'Test' }); + expect(result).toHaveProperty('id', 'conv-1'); + }); + + it('should send a message and save to history', async () => { + const result = await service.sendMessage('user-1', 'conv-1', { content: 'Hello' }); + expect(result.message).toBeDefined(); + expect(result.metadata.provider).toBe('mock'); + }); +}); diff --git a/src/ai-assistant/ai-assistant.service.ts b/src/ai-assistant/ai-assistant.service.ts new file mode 100644 index 0000000..62b78c5 --- /dev/null +++ b/src/ai-assistant/ai-assistant.service.ts @@ -0,0 +1,166 @@ +import { Injectable, NotFoundException, Logger, ForbiddenException } from '@nestjs/common'; +import { PrismaService } from '../prisma/prisma.service'; +import { LlmProviderService } from './llm-provider.service'; +import { RagService } from './rag.service'; +import { CreateConversationDto, SendMessageDto } from './dto/ai-assistant.dto'; + +@Injectable() +export class AiAssistantService { + private readonly logger = new Logger(AiAssistantService.name); + + constructor( + private prisma: PrismaService, + private llmProvider: LlmProviderService, + private ragService: RagService, + ) {} + + async createConversation(userId: string, dto: CreateConversationDto) { + return this.prisma.conversation.create({ + data: { + userId, + title: dto.title || 'New Conversation', + }, + }); + } + + async getConversations(userId: string) { + return this.prisma.conversation.findMany({ + where: { userId }, + orderBy: { updatedAt: 'desc' }, + }); + } + + async getConversationMessages(userId: string, conversationId: string) { + const conversation = await this.prisma.conversation.findUnique({ + where: { id: conversationId }, + }); + + if (!conversation) { + throw new NotFoundException('Conversation not found'); + } + + if (conversation.userId !== userId) { + throw new ForbiddenException('You do not have access to this conversation'); + } + + return this.prisma.message.findMany({ + where: { conversationId }, + orderBy: { createdAt: 'asc' }, + }); + } + + async sendMessage(userId: string, conversationId: string, dto: SendMessageDto) { + const conversation = await this.prisma.conversation.findUnique({ + where: { id: conversationId }, + }); + + if (!conversation) { + throw new NotFoundException('Conversation not found'); + } + + if (conversation.userId !== userId) { + throw new ForbiddenException('You do not have access to this conversation'); + } + + // 1. Save user message + const userMessage = await this.prisma.message.create({ + data: { + conversationId, + role: 'user', + content: dto.content, + }, + }); + + // 2. Retrieve Conversation History + const history = await this.prisma.message.findMany({ + where: { conversationId }, + orderBy: { createdAt: 'asc' }, + take: 10, // Short-term conversation memory limit + }); + + // 3. RAG Retrieval + const context = await this.ragService.retrieveContext(dto.content); + + // 4. Construct Prompt Pipeline + const systemPrompt = `You are the TruthBounty AI Assistant. You help contributors navigate the protocol. +Your answers must be grounded ONLY in verified protocol information. +Do not fabricate protocol state or execute operations. +Protocol Context: +${context} +`; + + const messagesToLlm: { role: 'user' | 'assistant' | 'system'; content: string }[] = [ + { role: 'system', content: systemPrompt }, + ...history.map(msg => ({ + role: msg.role as 'user' | 'assistant' | 'system', + content: msg.content, + })), + ]; + + const startTime = Date.now(); + + // 5. Orchestrate LLM request + const llmResponse = await this.llmProvider.generateResponse(messagesToLlm); + + const latencyMs = Date.now() - startTime; + + // 6. Save assistant response + const assistantMessage = await this.prisma.message.create({ + data: { + conversationId, + role: 'assistant', + content: llmResponse.content, + }, + }); + + // 7. Update conversation updated at + await this.prisma.conversation.update({ + where: { id: conversationId }, + data: { updatedAt: new Date() }, + }); + + // 8. Track Usage Metrics + await this.prisma.aiUsageMetric.create({ + data: { + userId, + provider: llmResponse.provider, + model: llmResponse.model, + promptTokens: llmResponse.usage?.prompt_tokens || 0, + completionTokens: llmResponse.usage?.completion_tokens || 0, + totalTokens: llmResponse.usage?.total_tokens || 0, + latencyMs, + }, + }); + + // Standardized API response + return { + message: assistantMessage, + metadata: { + provider: llmResponse.provider, + latencyMs, + tokens: llmResponse.usage?.total_tokens || 0, + citations: ['MOCKED_CITATION_1', 'MOCKED_CITATION_2'] // Placeholder for standardizing API + } + }; + } + + async deleteConversation(userId: string, conversationId: string) { + const conversation = await this.prisma.conversation.findUnique({ + where: { id: conversationId }, + }); + + if (!conversation) { + throw new NotFoundException('Conversation not found'); + } + + if (conversation.userId !== userId) { + throw new ForbiddenException('You do not have access to this conversation'); + } + + await this.prisma.conversation.delete({ + where: { id: conversationId }, + }); + + return { success: true }; + } +} diff --git a/src/ai-assistant/dto/ai-assistant.dto.ts b/src/ai-assistant/dto/ai-assistant.dto.ts new file mode 100644 index 0000000..2dc255d --- /dev/null +++ b/src/ai-assistant/dto/ai-assistant.dto.ts @@ -0,0 +1,22 @@ +import { IsString, IsNotEmpty, IsOptional, IsUUID, IsArray } from 'class-validator'; +import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; + +export class CreateConversationDto { + @ApiPropertyOptional({ description: 'Optional title for the conversation' }) + @IsString() + @IsOptional() + title?: string; +} + +export class SendMessageDto { + @ApiProperty({ description: 'The message content' }) + @IsString() + @IsNotEmpty() + content: string; + + @ApiPropertyOptional({ description: 'Optional list of tools to use (mocked)' }) + @IsArray() + @IsString({ each: true }) + @IsOptional() + tools?: string[]; +} diff --git a/src/ai-assistant/llm-provider.service.ts b/src/ai-assistant/llm-provider.service.ts new file mode 100644 index 0000000..b477d9f --- /dev/null +++ b/src/ai-assistant/llm-provider.service.ts @@ -0,0 +1,82 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; +import OpenAI from 'openai'; +import Anthropic from '@anthropic-ai/sdk'; + +@Injectable() +export class LlmProviderService { + private readonly logger = new Logger(LlmProviderService.name); + private openai: OpenAI | null = null; + private anthropic: Anthropic | null = null; + private defaultProvider: 'openai' | 'anthropic'; + + constructor(private configService: ConfigService) { + const openaiKey = this.configService.get('OPENAI_API_KEY'); + if (openaiKey) { + this.openai = new OpenAI({ apiKey: openaiKey }); + } + + const anthropicKey = this.configService.get('ANTHROPIC_API_KEY'); + if (anthropicKey) { + this.anthropic = new Anthropic({ apiKey: anthropicKey }); + } + + this.defaultProvider = this.configService.get<'openai' | 'anthropic'>('DEFAULT_LLM_PROVIDER') || 'openai'; + } + + async generateResponse( + messages: { role: 'user' | 'assistant' | 'system'; content: string }[], + options?: { provider?: 'openai' | 'anthropic' } + ): Promise<{ content: string; usage: any; provider: string; model: string }> { + const provider = options?.provider || this.defaultProvider; + + if (provider === 'openai' && this.openai) { + const model = 'gpt-4o-mini'; + const response = await this.openai.chat.completions.create({ + model, + messages: messages.map(m => ({ role: m.role, content: m.content })), + }); + return { + content: response.choices[0].message.content || '', + usage: response.usage, + provider: 'openai', + model, + }; + } else if (provider === 'anthropic' && this.anthropic) { + const model = 'claude-3-haiku-20240307'; + const systemMessage = messages.find(m => m.role === 'system')?.content; + const otherMessages = messages.filter(m => m.role !== 'system').map(m => ({ + role: m.role === 'assistant' ? 'assistant' as const : 'user' as const, + content: m.content + })); + + const response = await this.anthropic.messages.create({ + model, + max_tokens: 1024, + system: systemMessage, + messages: otherMessages, + }); + + const content = response.content[0].type === 'text' ? response.content[0].text : ''; + return { + content, + usage: { + prompt_tokens: response.usage.input_tokens, + completion_tokens: response.usage.output_tokens, + total_tokens: response.usage.input_tokens + response.usage.output_tokens, + }, + provider: 'anthropic', + model, + }; + } + + // Mock fallback if keys not configured + this.logger.warn(`No valid LLM provider configured for ${provider}, using mock response.`); + return { + content: `This is a mock response from the AI Assistant because the API keys for ${provider} are not configured. You said: ${messages[messages.length - 1]?.content}`, + usage: { prompt_tokens: 10, completion_tokens: 20, total_tokens: 30 }, + provider: 'mock', + model: 'mock-model', + }; + } +} diff --git a/src/ai-assistant/rag.service.ts b/src/ai-assistant/rag.service.ts new file mode 100644 index 0000000..9160610 --- /dev/null +++ b/src/ai-assistant/rag.service.ts @@ -0,0 +1,28 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { PrismaService } from '../prisma/prisma.service'; + +@Injectable() +export class RagService { + private readonly logger = new Logger(RagService.name); + + constructor(private prisma: PrismaService) {} + + async retrieveContext(query: string): Promise { + this.logger.debug(`Retrieving context for query: ${query}`); + + // In a real implementation, this would: + // 1. Embed the query + // 2. Perform a vector search against pgvector or external vector DB + // 3. Fetch verified data from DB (Claims, Governance Proposals, etc.) + + // For now, returning a mock context string that simulates a RAG retrieval + const mockedProtocolData = ` +TruthBounty Protocol Guidelines: +- A claim can only be verified by users with a reputation score of at least 100. +- Governance proposals require a quorum of 5% of total circulating tokens. +- Disputes are resolved by the Supreme Court which consists of 7 randomly selected high-reputation members. +`; + + return mockedProtocolData; + } +} diff --git a/src/app.module.ts b/src/app.module.ts index 52c75a7..a5cdcdb 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -34,6 +34,7 @@ import { GlobalAuthGuard } from './auth/global-auth.guard'; import { MetricsModule } from './metrics/metrics.module'; import { ReputationModule } from './reputation/reputation.module'; import { GovernanceModule } from './governance/governance.module'; +import { AiAssistantModule } from './ai-assistant/ai-assistant.module'; import { AdminModule } from './admin/admin.module'; import { ProfilerModule } from './profiler/profiler.module'; import { ProfilerInterceptor } from './profiler/profiler.interceptor'; @@ -314,6 +315,7 @@ async function createThrottlerStorage( MetricsModule, ReputationModule, GovernanceModule, + AiAssistantModule, AdminModule, ProfilerModule, ], diff --git a/src/entities/user.entity.spec.ts b/src/entities/user.entity.spec.ts index 049f69f..339b046 100644 --- a/src/entities/user.entity.spec.ts +++ b/src/entities/user.entity.spec.ts @@ -1,12 +1,8 @@ import 'reflect-metadata'; import { getMetadataArgsStorage } from 'typeorm'; import { User } from './user.entity'; -import { UserEntity } from '../modules/users/entities/user.entity'; describe('User entity schema sync (BE-203)', () => { - it('canonical User entity and re-exported UserEntity should reference the same class', () => { - expect(UserEntity).toBe(User); - }); it('User entity maps to the "users" table', () => { const tableMetadata = getMetadataArgsStorage().tables.find( diff --git a/src/generated/client/browser.ts b/src/generated/client/browser.ts index ba3535a..5e95b9d 100644 --- a/src/generated/client/browser.ts +++ b/src/generated/client/browser.ts @@ -42,3 +42,18 @@ export type SybilExplanation = Prisma.SybilExplanationModel * */ export type WorldIdVerification = Prisma.WorldIdVerificationModel +/** + * Model Conversation + * + */ +export type Conversation = Prisma.ConversationModel +/** + * Model Message + * + */ +export type Message = Prisma.MessageModel +/** + * Model AiUsageMetric + * + */ +export type AiUsageMetric = Prisma.AiUsageMetricModel diff --git a/src/generated/client/client.ts b/src/generated/client/client.ts index 16cb43a..149426b 100644 --- a/src/generated/client/client.ts +++ b/src/generated/client/client.ts @@ -62,3 +62,18 @@ export type SybilExplanation = Prisma.SybilExplanationModel * */ export type WorldIdVerification = Prisma.WorldIdVerificationModel +/** + * Model Conversation + * + */ +export type Conversation = Prisma.ConversationModel +/** + * Model Message + * + */ +export type Message = Prisma.MessageModel +/** + * Model AiUsageMetric + * + */ +export type AiUsageMetric = Prisma.AiUsageMetricModel diff --git a/src/generated/client/internal/class.ts b/src/generated/client/internal/class.ts index 578cb9d..4abd64b 100644 --- a/src/generated/client/internal/class.ts +++ b/src/generated/client/internal/class.ts @@ -20,7 +20,7 @@ const config: runtime.GetPrismaClientConfig = { "clientVersion": "7.4.1", "engineVersion": "55ae170b1ced7fc6ed07a15f110549408c501bb3", "activeProvider": "sqlite", - "inlineSchema": "// This is your Prisma schema file,\n// learn more about it in the docs: https://pris.ly/d/prisma-schema\n\ngenerator client {\n provider = \"prisma-client\"\n output = \"../src/generated/client\"\n binaryTargets = [\"native\", \"linux-musl\"]\n}\n\n// Actual runtime datasource is SQLite via the libsql driver adapter\n// (see src/prisma/prisma.service.ts, DATABASE_URL=file:./dev.db) โ€” this\n// matches prisma/migrations/migration_lock.toml, which already records\n// \"sqlite\" as the migration dialect. Declaring \"postgresql\" here caused\n// PrismaClientInitializationError at runtime (\"Driver Adapter\n// @prisma/adapter-libsql, based on sqlite, is not compatible with the\n// provider postgres\") once the client was regenerated against the\n// package-lock-pinned prisma@7.4.1, which validates this consistency.\ndatasource db {\n provider = \"sqlite\"\n}\n\nenum UserRole {\n contributor\n moderator\n admin\n}\n\nmodel User {\n id String @id @default(uuid())\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Primary wallet address โ€” canonical identifier for the user\n walletAddress String @unique\n\n reputation Int @default(0)\n\n role UserRole @default(contributor)\n\n // Sybil Resistance\n worldcoinVerified Boolean @default(false)\n worldcoinVerifiedAt DateTime?\n\n wallets Wallet[]\n sybilScores SybilScore[]\n worldIdVerifications WorldIdVerification[]\n}\n\nmodel Wallet {\n id String @id @default(uuid())\n address String\n chain String\n linkedAt DateTime @default(now())\n\n userId String\n user User @relation(fields: [userId], references: [id])\n // We will enforce \"one address -> one user\" logic in the service layer\n // to handle multi-chain address reuse scenarios properly.\n\n @@unique([address, chain])\n}\n\nmodel SybilScore {\n id String @id @default(uuid())\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n // Component scores (0-1 normalized)\n worldcoinScore Float @default(0.0) // Binary verification signal (0 or 1)\n walletAgeScore Float @default(0.0) // Based on wallet age\n stakingScore Float @default(0.0) // Historical participation in staking\n accuracyScore Float @default(0.0) // Claim accuracy from verification history\n\n // Final composite score (0-1)\n compositeScore Float @default(0.0) // Final Sybil resistance score\n\n // Metadata\n calculationDetails String? // JSON string for explainability\n\n explanation SybilExplanation?\n\n @@unique([userId, createdAt])\n @@index([userId])\n @@index([compositeScore])\n}\n\nmodel SybilExplanation {\n id String @id @default(uuid())\n sybilScoreId String @unique\n explanation String\n createdAt DateTime @default(now())\n\n sybilScore SybilScore @relation(fields: [sybilScoreId], references: [id], onDelete: Cascade)\n}\n\nmodel WorldIdVerification {\n id String @id @default(uuid())\n verifiedAt DateTime @default(now())\n\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n nullifierHash String @unique\n verificationLevel String\n worldcoinAppId String\n worldcoinAction String\n merkleRoot String?\n proof Json?\n\n @@index([userId])\n @@index([nullifierHash])\n @@map(\"world_id_verifications\")\n}\n", + "inlineSchema": "// This is your Prisma schema file,\n// learn more about it in the docs: https://pris.ly/d/prisma-schema\n\ngenerator client {\n provider = \"prisma-client\"\n output = \"../src/generated/client\"\n binaryTargets = [\"native\", \"linux-musl\"]\n}\n\n// Actual runtime datasource is SQLite via the libsql driver adapter\n// (see src/prisma/prisma.service.ts, DATABASE_URL=file:./dev.db) โ€” this\n// matches prisma/migrations/migration_lock.toml, which already records\n// \"sqlite\" as the migration dialect. Declaring \"postgresql\" here caused\n// PrismaClientInitializationError at runtime (\"Driver Adapter\n// @prisma/adapter-libsql, based on sqlite, is not compatible with the\n// provider postgres\") once the client was regenerated against the\n// package-lock-pinned prisma@7.4.1, which validates this consistency.\ndatasource db {\n provider = \"sqlite\"\n}\n\nenum UserRole {\n contributor\n moderator\n admin\n}\n\nmodel User {\n id String @id @default(uuid())\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n // Primary wallet address โ€” canonical identifier for the user\n walletAddress String @unique\n\n reputation Int @default(0)\n\n role UserRole @default(contributor)\n\n // Sybil Resistance\n worldcoinVerified Boolean @default(false)\n worldcoinVerifiedAt DateTime?\n\n wallets Wallet[]\n sybilScores SybilScore[]\n worldIdVerifications WorldIdVerification[]\n conversations Conversation[]\n}\n\nmodel Wallet {\n id String @id @default(uuid())\n address String\n chain String\n linkedAt DateTime @default(now())\n\n userId String\n user User @relation(fields: [userId], references: [id])\n // We will enforce \"one address -> one user\" logic in the service layer\n // to handle multi-chain address reuse scenarios properly.\n\n @@unique([address, chain])\n}\n\nmodel SybilScore {\n id String @id @default(uuid())\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n // Component scores (0-1 normalized)\n worldcoinScore Float @default(0.0) // Binary verification signal (0 or 1)\n walletAgeScore Float @default(0.0) // Based on wallet age\n stakingScore Float @default(0.0) // Historical participation in staking\n accuracyScore Float @default(0.0) // Claim accuracy from verification history\n\n // Final composite score (0-1)\n compositeScore Float @default(0.0) // Final Sybil resistance score\n\n // Metadata\n calculationDetails String? // JSON string for explainability\n\n explanation SybilExplanation?\n\n @@unique([userId, createdAt])\n @@index([userId])\n @@index([compositeScore])\n}\n\nmodel SybilExplanation {\n id String @id @default(uuid())\n sybilScoreId String @unique\n explanation String\n createdAt DateTime @default(now())\n\n sybilScore SybilScore @relation(fields: [sybilScoreId], references: [id], onDelete: Cascade)\n}\n\nmodel WorldIdVerification {\n id String @id @default(uuid())\n verifiedAt DateTime @default(now())\n\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n nullifierHash String @unique\n verificationLevel String\n worldcoinAppId String\n worldcoinAction String\n merkleRoot String?\n proof Json?\n\n @@index([userId])\n @@index([nullifierHash])\n @@map(\"world_id_verifications\")\n}\n\nmodel Conversation {\n id String @id @default(uuid())\n title String?\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n messages Message[]\n\n @@index([userId])\n}\n\nmodel Message {\n id String @id @default(uuid())\n role String // \"user\", \"assistant\", \"system\"\n content String\n conversationId String\n conversation Conversation @relation(fields: [conversationId], references: [id], onDelete: Cascade)\n createdAt DateTime @default(now())\n\n @@index([conversationId])\n}\n\nmodel AiUsageMetric {\n id String @id @default(uuid())\n userId String?\n provider String // e.g., \"openai\", \"anthropic\"\n model String\n promptTokens Int @default(0)\n completionTokens Int @default(0)\n totalTokens Int @default(0)\n latencyMs Int @default(0)\n createdAt DateTime @default(now())\n\n @@index([userId])\n @@index([provider])\n}\n", "runtimeDataModel": { "models": {}, "enums": {}, @@ -32,10 +32,10 @@ const config: runtime.GetPrismaClientConfig = { } } -config.runtimeDataModel = JSON.parse("{\"models\":{\"User\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"walletAddress\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reputation\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"role\",\"kind\":\"enum\",\"type\":\"UserRole\"},{\"name\":\"worldcoinVerified\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"worldcoinVerifiedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"wallets\",\"kind\":\"object\",\"type\":\"Wallet\",\"relationName\":\"UserToWallet\"},{\"name\":\"sybilScores\",\"kind\":\"object\",\"type\":\"SybilScore\",\"relationName\":\"SybilScoreToUser\"},{\"name\":\"worldIdVerifications\",\"kind\":\"object\",\"type\":\"WorldIdVerification\",\"relationName\":\"UserToWorldIdVerification\"}],\"dbName\":null},\"Wallet\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"address\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"chain\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"linkedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"UserToWallet\"}],\"dbName\":null},\"SybilScore\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"SybilScoreToUser\"},{\"name\":\"worldcoinScore\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"walletAgeScore\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"stakingScore\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"accuracyScore\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"compositeScore\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"calculationDetails\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"explanation\",\"kind\":\"object\",\"type\":\"SybilExplanation\",\"relationName\":\"SybilExplanationToSybilScore\"}],\"dbName\":null},\"SybilExplanation\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"sybilScoreId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"explanation\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"sybilScore\",\"kind\":\"object\",\"type\":\"SybilScore\",\"relationName\":\"SybilExplanationToSybilScore\"}],\"dbName\":null},\"WorldIdVerification\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"verifiedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"UserToWorldIdVerification\"},{\"name\":\"nullifierHash\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"verificationLevel\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"worldcoinAppId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"worldcoinAction\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"merkleRoot\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"proof\",\"kind\":\"scalar\",\"type\":\"Json\"}],\"dbName\":\"world_id_verifications\"}},\"enums\":{},\"types\":{}}") +config.runtimeDataModel = JSON.parse("{\"models\":{\"User\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"walletAddress\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"reputation\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"role\",\"kind\":\"enum\",\"type\":\"UserRole\"},{\"name\":\"worldcoinVerified\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"worldcoinVerifiedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"wallets\",\"kind\":\"object\",\"type\":\"Wallet\",\"relationName\":\"UserToWallet\"},{\"name\":\"sybilScores\",\"kind\":\"object\",\"type\":\"SybilScore\",\"relationName\":\"SybilScoreToUser\"},{\"name\":\"worldIdVerifications\",\"kind\":\"object\",\"type\":\"WorldIdVerification\",\"relationName\":\"UserToWorldIdVerification\"},{\"name\":\"conversations\",\"kind\":\"object\",\"type\":\"Conversation\",\"relationName\":\"ConversationToUser\"}],\"dbName\":null},\"Wallet\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"address\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"chain\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"linkedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"UserToWallet\"}],\"dbName\":null},\"SybilScore\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"SybilScoreToUser\"},{\"name\":\"worldcoinScore\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"walletAgeScore\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"stakingScore\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"accuracyScore\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"compositeScore\",\"kind\":\"scalar\",\"type\":\"Float\"},{\"name\":\"calculationDetails\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"explanation\",\"kind\":\"object\",\"type\":\"SybilExplanation\",\"relationName\":\"SybilExplanationToSybilScore\"}],\"dbName\":null},\"SybilExplanation\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"sybilScoreId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"explanation\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"sybilScore\",\"kind\":\"object\",\"type\":\"SybilScore\",\"relationName\":\"SybilExplanationToSybilScore\"}],\"dbName\":null},\"WorldIdVerification\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"verifiedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"UserToWorldIdVerification\"},{\"name\":\"nullifierHash\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"verificationLevel\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"worldcoinAppId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"worldcoinAction\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"merkleRoot\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"proof\",\"kind\":\"scalar\",\"type\":\"Json\"}],\"dbName\":\"world_id_verifications\"},\"Conversation\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"title\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ConversationToUser\"},{\"name\":\"messages\",\"kind\":\"object\",\"type\":\"Message\",\"relationName\":\"ConversationToMessage\"}],\"dbName\":null},\"Message\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"role\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"content\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"conversationId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"conversation\",\"kind\":\"object\",\"type\":\"Conversation\",\"relationName\":\"ConversationToMessage\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"AiUsageMetric\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"provider\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"model\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"promptTokens\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"completionTokens\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"totalTokens\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"latencyMs\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null}},\"enums\":{},\"types\":{}}") config.parameterizationSchema = { - strings: JSON.parse("[\"where\",\"orderBy\",\"cursor\",\"user\",\"wallets\",\"sybilScore\",\"explanation\",\"sybilScores\",\"worldIdVerifications\",\"_count\",\"User.findUnique\",\"User.findUniqueOrThrow\",\"User.findFirst\",\"User.findFirstOrThrow\",\"User.findMany\",\"data\",\"User.createOne\",\"User.createMany\",\"User.createManyAndReturn\",\"User.updateOne\",\"User.updateMany\",\"User.updateManyAndReturn\",\"create\",\"update\",\"User.upsertOne\",\"User.deleteOne\",\"User.deleteMany\",\"having\",\"_avg\",\"_sum\",\"_min\",\"_max\",\"User.groupBy\",\"User.aggregate\",\"Wallet.findUnique\",\"Wallet.findUniqueOrThrow\",\"Wallet.findFirst\",\"Wallet.findFirstOrThrow\",\"Wallet.findMany\",\"Wallet.createOne\",\"Wallet.createMany\",\"Wallet.createManyAndReturn\",\"Wallet.updateOne\",\"Wallet.updateMany\",\"Wallet.updateManyAndReturn\",\"Wallet.upsertOne\",\"Wallet.deleteOne\",\"Wallet.deleteMany\",\"Wallet.groupBy\",\"Wallet.aggregate\",\"SybilScore.findUnique\",\"SybilScore.findUniqueOrThrow\",\"SybilScore.findFirst\",\"SybilScore.findFirstOrThrow\",\"SybilScore.findMany\",\"SybilScore.createOne\",\"SybilScore.createMany\",\"SybilScore.createManyAndReturn\",\"SybilScore.updateOne\",\"SybilScore.updateMany\",\"SybilScore.updateManyAndReturn\",\"SybilScore.upsertOne\",\"SybilScore.deleteOne\",\"SybilScore.deleteMany\",\"SybilScore.groupBy\",\"SybilScore.aggregate\",\"SybilExplanation.findUnique\",\"SybilExplanation.findUniqueOrThrow\",\"SybilExplanation.findFirst\",\"SybilExplanation.findFirstOrThrow\",\"SybilExplanation.findMany\",\"SybilExplanation.createOne\",\"SybilExplanation.createMany\",\"SybilExplanation.createManyAndReturn\",\"SybilExplanation.updateOne\",\"SybilExplanation.updateMany\",\"SybilExplanation.updateManyAndReturn\",\"SybilExplanation.upsertOne\",\"SybilExplanation.deleteOne\",\"SybilExplanation.deleteMany\",\"SybilExplanation.groupBy\",\"SybilExplanation.aggregate\",\"WorldIdVerification.findUnique\",\"WorldIdVerification.findUniqueOrThrow\",\"WorldIdVerification.findFirst\",\"WorldIdVerification.findFirstOrThrow\",\"WorldIdVerification.findMany\",\"WorldIdVerification.createOne\",\"WorldIdVerification.createMany\",\"WorldIdVerification.createManyAndReturn\",\"WorldIdVerification.updateOne\",\"WorldIdVerification.updateMany\",\"WorldIdVerification.updateManyAndReturn\",\"WorldIdVerification.upsertOne\",\"WorldIdVerification.deleteOne\",\"WorldIdVerification.deleteMany\",\"WorldIdVerification.groupBy\",\"WorldIdVerification.aggregate\",\"AND\",\"OR\",\"NOT\",\"id\",\"verifiedAt\",\"userId\",\"nullifierHash\",\"verificationLevel\",\"worldcoinAppId\",\"worldcoinAction\",\"merkleRoot\",\"proof\",\"equals\",\"string_contains\",\"string_starts_with\",\"string_ends_with\",\"array_starts_with\",\"array_ends_with\",\"not\",\"in\",\"notIn\",\"lt\",\"lte\",\"gt\",\"gte\",\"contains\",\"startsWith\",\"endsWith\",\"sybilScoreId\",\"createdAt\",\"updatedAt\",\"worldcoinScore\",\"walletAgeScore\",\"stakingScore\",\"accuracyScore\",\"compositeScore\",\"calculationDetails\",\"address\",\"chain\",\"linkedAt\",\"walletAddress\",\"reputation\",\"UserRole\",\"role\",\"worldcoinVerified\",\"worldcoinVerifiedAt\",\"every\",\"some\",\"none\",\"userId_createdAt\",\"address_chain\",\"is\",\"isNot\",\"connectOrCreate\",\"upsert\",\"disconnect\",\"delete\",\"connect\",\"createMany\",\"set\",\"updateMany\",\"deleteMany\",\"increment\",\"decrement\",\"multiply\",\"divide\"]"), - graph: "rAIuUA4EAACuAQAgBwAArwEAIAgAALABACBiAACpAQAwYwAAFQAQZAAAqQEAMGUBAAAAAX9AAJYBACGAAUAAlgEAIYoBAQAAAAGLAQIAqgEAIY0BAACrAY0BIo4BIACsAQAhjwFAAK0BACEBAAAAAQAgCQMAALQBACBiAAC6AQAwYwAAAwAQZAAAugEAMGUBAJUBACFnAQCVAQAhhwEBAJUBACGIAQEAlQEAIYkBQACWAQAhAQMAAJQCACAKAwAAtAEAIGIAALoBADBjAAADABBkAAC6AQAwZQEAAAABZwEAlQEAIYcBAQCVAQAhiAEBAJUBACGJAUAAlgEAIZQBAAC5AQAgAwAAAAMAIAEAAAQAMAIAAAUAIA8DAAC0AQAgBgAAuAEAIGIAALYBADBjAAAHABBkAAC2AQAwZQEAlQEAIWcBAJUBACF_QACWAQAhgAFAAJYBACGBAQgAtwEAIYIBCAC3AQAhgwEIALcBACGEAQgAtwEAIYUBCAC3AQAhhgEBALIBACEDAwAAlAIAIAYAAJUCACCGAQAAuwEAIBADAAC0AQAgBgAAuAEAIGIAALYBADBjAAAHABBkAAC2AQAwZQEAAAABZwEAlQEAIX9AAJYBACGAAUAAlgEAIYEBCAC3AQAhggEIALcBACGDAQgAtwEAIYQBCAC3AQAhhQEIALcBACGGAQEAsgEAIZMBAAC1AQAgAwAAAAcAIAEAAAgAMAIAAAkAIAgFAACXAQAgBgEAlQEAIWIAAJQBADBjAAALABBkAACUAQAwZQEAlQEAIX4BAJUBACF_QACWAQAhAQAAAAsAIA0DAAC0AQAgYgAAsQEAMGMAAA0AEGQAALEBADBlAQCVAQAhZkAAlgEAIWcBAJUBACFoAQCVAQAhaQEAlQEAIWoBAJUBACFrAQCVAQAhbAEAsgEAIW0AALMBACADAwAAlAIAIGwAALsBACBtAAC7AQAgDQMAALQBACBiAACxAQAwYwAADQAQZAAAsQEAMGUBAAAAAWZAAJYBACFnAQCVAQAhaAEAAAABaQEAlQEAIWoBAJUBACFrAQCVAQAhbAEAsgEAIW0AALMBACADAAAADQAgAQAADgAwAgAADwAgAQAAAAMAIAEAAAAHACABAAAADQAgAQAAAAEAIA4EAACuAQAgBwAArwEAIAgAALABACBiAACpAQAwYwAAFQAQZAAAqQEAMGUBAJUBACF_QACWAQAhgAFAAJYBACGKAQEAlQEAIYsBAgCqAQAhjQEAAKsBjQEijgEgAKwBACGPAUAArQEAIQQEAACRAgAgBwAAkgIAIAgAAJMCACCPAQAAuwEAIAMAAAAVACABAAAWADACAAABACADAAAAFQAgAQAAFgAwAgAAAQAgAwAAABUAIAEAABYAMAIAAAEAIAsEAACOAgAgBwAAjwIAIAgAAJACACBlAQAAAAF_QAAAAAGAAUAAAAABigEBAAAAAYsBAgAAAAGNAQAAAI0BAo4BIAAAAAGPAUAAAAABAQ8AABoAIAhlAQAAAAF_QAAAAAGAAUAAAAABigEBAAAAAYsBAgAAAAGNAQAAAI0BAo4BIAAAAAGPAUAAAAABAQ8AABwAMAEPAAAcADALBAAA5wEAIAcAAOgBACAIAADpAQAgZQEAvwEAIX9AAMABACGAAUAAwAEAIYoBAQC_AQAhiwECAOMBACGNAQAA5AGNASKOASAA5QEAIY8BQADmAQAhAgAAAAEAIA8AAB8AIAhlAQC_AQAhf0AAwAEAIYABQADAAQAhigEBAL8BACGLAQIA4wEAIY0BAADkAY0BIo4BIADlAQAhjwFAAOYBACECAAAAFQAgDwAAIQAgAgAAABUAIA8AACEAIAMAAAABACAWAAAaACAXAAAfACABAAAAAQAgAQAAABUAIAYJAADeAQAgHAAA3wEAIB0AAOIBACAeAADhAQAgHwAA4AEAII8BAAC7AQAgC2IAAJ0BADBjAAAoABBkAACdAQAwZQEAhgEAIX9AAIcBACGAAUAAhwEAIYoBAQCGAQAhiwECAJ4BACGNAQAAnwGNASKOASAAoAEAIY8BQAChAQAhAwAAABUAIAEAACcAMBsAACgAIAMAAAAVACABAAAWADACAAABACABAAAABQAgAQAAAAUAIAMAAAADACABAAAEADACAAAFACADAAAAAwAgAQAABAAwAgAABQAgAwAAAAMAIAEAAAQAMAIAAAUAIAYDAADdAQAgZQEAAAABZwEAAAABhwEBAAAAAYgBAQAAAAGJAUAAAAABAQ8AADAAIAVlAQAAAAFnAQAAAAGHAQEAAAABiAEBAAAAAYkBQAAAAAEBDwAAMgAwAQ8AADIAMAYDAADcAQAgZQEAvwEAIWcBAL8BACGHAQEAvwEAIYgBAQC_AQAhiQFAAMABACECAAAABQAgDwAANQAgBWUBAL8BACFnAQC_AQAhhwEBAL8BACGIAQEAvwEAIYkBQADAAQAhAgAAAAMAIA8AADcAIAIAAAADACAPAAA3ACADAAAABQAgFgAAMAAgFwAANQAgAQAAAAUAIAEAAAADACADCQAA2QEAIB4AANsBACAfAADaAQAgCGIAAJwBADBjAAA-ABBkAACcAQAwZQEAhgEAIWcBAIYBACGHAQEAhgEAIYgBAQCGAQAhiQFAAIcBACEDAAAAAwAgAQAAPQAwGwAAPgAgAwAAAAMAIAEAAAQAMAIAAAUAIAEAAAAJACABAAAACQAgAwAAAAcAIAEAAAgAMAIAAAkAIAMAAAAHACABAAAIADACAAAJACADAAAABwAgAQAACAAwAgAACQAgDAMAANcBACAGAADYAQAgZQEAAAABZwEAAAABf0AAAAABgAFAAAAAAYEBCAAAAAGCAQgAAAABgwEIAAAAAYQBCAAAAAGFAQgAAAABhgEBAAAAAQEPAABGACAKZQEAAAABZwEAAAABf0AAAAABgAFAAAAAAYEBCAAAAAGCAQgAAAABgwEIAAAAAYQBCAAAAAGFAQgAAAABhgEBAAAAAQEPAABIADABDwAASAAwDAMAANABACAGAADRAQAgZQEAvwEAIWcBAL8BACF_QADAAQAhgAFAAMABACGBAQgAzwEAIYIBCADPAQAhgwEIAM8BACGEAQgAzwEAIYUBCADPAQAhhgEBAMEBACECAAAACQAgDwAASwAgCmUBAL8BACFnAQC_AQAhf0AAwAEAIYABQADAAQAhgQEIAM8BACGCAQgAzwEAIYMBCADPAQAhhAEIAM8BACGFAQgAzwEAIYYBAQDBAQAhAgAAAAcAIA8AAE0AIAIAAAAHACAPAABNACADAAAACQAgFgAARgAgFwAASwAgAQAAAAkAIAEAAAAHACAGCQAAygEAIBwAAMsBACAdAADOAQAgHgAAzQEAIB8AAMwBACCGAQAAuwEAIA1iAACYAQAwYwAAVAAQZAAAmAEAMGUBAIYBACFnAQCGAQAhf0AAhwEAIYABQACHAQAhgQEIAJkBACGCAQgAmQEAIYMBCACZAQAhhAEIAJkBACGFAQgAmQEAIYYBAQCIAQAhAwAAAAcAIAEAAFMAMBsAAFQAIAMAAAAHACABAAAIADACAAAJACAIBQAAlwEAIAYBAJUBACFiAACUAQAwYwAACwAQZAAAlAEAMGUBAAAAAX4BAAAAAX9AAJYBACEBAAAAVwAgAQAAAFcAIAEFAADJAQAgAwAAAAsAIAEAAFoAMAIAAFcAIAMAAAALACABAABaADACAABXACADAAAACwAgAQAAWgAwAgAAVwAgBQUAAMgBACAGAQAAAAFlAQAAAAF-AQAAAAF_QAAAAAEBDwAAXgAgBAYBAAAAAWUBAAAAAX4BAAAAAX9AAAAAAQEPAABgADABDwAAYAAwBQUAAMcBACAGAQC_AQAhZQEAvwEAIX4BAL8BACF_QADAAQAhAgAAAFcAIA8AAGMAIAQGAQC_AQAhZQEAvwEAIX4BAL8BACF_QADAAQAhAgAAAAsAIA8AAGUAIAIAAAALACAPAABlACADAAAAVwAgFgAAXgAgFwAAYwAgAQAAAFcAIAEAAAALACADCQAAxAEAIB4AAMYBACAfAADFAQAgBwYBAIYBACFiAACTAQAwYwAAbAAQZAAAkwEAMGUBAIYBACF-AQCGAQAhf0AAhwEAIQMAAAALACABAABrADAbAABsACADAAAACwAgAQAAWgAwAgAAVwAgAQAAAA8AIAEAAAAPACADAAAADQAgAQAADgAwAgAADwAgAwAAAA0AIAEAAA4AMAIAAA8AIAMAAAANACABAAAOADACAAAPACAKAwAAwwEAIGUBAAAAAWZAAAAAAWcBAAAAAWgBAAAAAWkBAAAAAWoBAAAAAWsBAAAAAWwBAAAAAW2AAAAAAQEPAAB0ACAJZQEAAAABZkAAAAABZwEAAAABaAEAAAABaQEAAAABagEAAAABawEAAAABbAEAAAABbYAAAAABAQ8AAHYAMAEPAAB2ADAKAwAAwgEAIGUBAL8BACFmQADAAQAhZwEAvwEAIWgBAL8BACFpAQC_AQAhagEAvwEAIWsBAL8BACFsAQDBAQAhbYAAAAABAgAAAA8AIA8AAHkAIAllAQC_AQAhZkAAwAEAIWcBAL8BACFoAQC_AQAhaQEAvwEAIWoBAL8BACFrAQC_AQAhbAEAwQEAIW2AAAAAAQIAAAANACAPAAB7ACACAAAADQAgDwAAewAgAwAAAA8AIBYAAHQAIBcAAHkAIAEAAAAPACABAAAADQAgBQkAALwBACAeAAC-AQAgHwAAvQEAIGwAALsBACBtAAC7AQAgDGIAAIUBADBjAACCAQAQZAAAhQEAMGUBAIYBACFmQACHAQAhZwEAhgEAIWgBAIYBACFpAQCGAQAhagEAhgEAIWsBAIYBACFsAQCIAQAhbQAAiQEAIAMAAAANACABAACBAQAwGwAAggEAIAMAAAANACABAAAOADACAAAPACAMYgAAhQEAMGMAAIIBABBkAACFAQAwZQEAhgEAIWZAAIcBACFnAQCGAQAhaAEAhgEAIWkBAIYBACFqAQCGAQAhawEAhgEAIWwBAIgBACFtAACJAQAgDgkAAI8BACAeAACSAQAgHwAAkgEAIG4BAAAAAXQBAJEBACF1AQAAAAR2AQAAAAR3AQAAAAF4AQAAAAF5AQAAAAF6AQAAAAF7AQAAAAF8AQAAAAF9AQAAAAELCQAAjwEAIB4AAJABACAfAACQAQAgbkAAAAABdEAAjgEAIXVAAAAABHZAAAAABHdAAAAAAXhAAAAAAXlAAAAAAXpAAAAAAQ4JAACKAQAgHgAAjQEAIB8AAI0BACBuAQAAAAF0AQCMAQAhdQEAAAAFdgEAAAAFdwEAAAABeAEAAAABeQEAAAABegEAAAABewEAAAABfAEAAAABfQEAAAABCgkAAIoBACAeAACLAQAgHwAAiwEAIG6AAAAAAW8BAAAAAXABAAAAAXEBAAAAAXKAAAAAAXOAAAAAAXSAAAAAAQhuAgAAAAF0AgCKAQAhdQIAAAAFdgIAAAAFdwIAAAABeAIAAAABeQIAAAABegIAAAABB26AAAAAAW8BAAAAAXABAAAAAXEBAAAAAXKAAAAAAXOAAAAAAXSAAAAAAQ4JAACKAQAgHgAAjQEAIB8AAI0BACBuAQAAAAF0AQCMAQAhdQEAAAAFdgEAAAAFdwEAAAABeAEAAAABeQEAAAABegEAAAABewEAAAABfAEAAAABfQEAAAABC24BAAAAAXQBAI0BACF1AQAAAAV2AQAAAAV3AQAAAAF4AQAAAAF5AQAAAAF6AQAAAAF7AQAAAAF8AQAAAAF9AQAAAAELCQAAjwEAIB4AAJABACAfAACQAQAgbkAAAAABdEAAjgEAIXVAAAAABHZAAAAABHdAAAAAAXhAAAAAAXlAAAAAAXpAAAAAAQhuAgAAAAF0AgCPAQAhdQIAAAAEdgIAAAAEdwIAAAABeAIAAAABeQIAAAABegIAAAABCG5AAAAAAXRAAJABACF1QAAAAAR2QAAAAAR3QAAAAAF4QAAAAAF5QAAAAAF6QAAAAAEOCQAAjwEAIB4AAJIBACAfAACSAQAgbgEAAAABdAEAkQEAIXUBAAAABHYBAAAABHcBAAAAAXgBAAAAAXkBAAAAAXoBAAAAAXsBAAAAAXwBAAAAAX0BAAAAAQtuAQAAAAF0AQCSAQAhdQEAAAAEdgEAAAAEdwEAAAABeAEAAAABeQEAAAABegEAAAABewEAAAABfAEAAAABfQEAAAABBwYBAIYBACFiAACTAQAwYwAAbAAQZAAAkwEAMGUBAIYBACF-AQCGAQAhf0AAhwEAIQgFAACXAQAgBgEAlQEAIWIAAJQBADBjAAALABBkAACUAQAwZQEAlQEAIX4BAJUBACF_QACWAQAhC24BAAAAAXQBAJIBACF1AQAAAAR2AQAAAAR3AQAAAAF4AQAAAAF5AQAAAAF6AQAAAAF7AQAAAAF8AQAAAAF9AQAAAAEIbkAAAAABdEAAkAEAIXVAAAAABHZAAAAABHdAAAAAAXhAAAAAAXlAAAAAAXpAAAAAAREDAAC0AQAgBgAAuAEAIGIAALYBADBjAAAHABBkAAC2AQAwZQEAlQEAIWcBAJUBACF_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_AQAhf0AAwAEAIQMGAQC_AQAhZQEAvwEAIX9AAMABACEDFgAAngIAIJcBAACfAgAgmwEAAAEAIAMWAADSAQAglwEAANMBACCbAQAAVwAgAAAABRYAAJkCACAXAACcAgAglwEAAJoCACCYAQAAmwIAIJsBAAABACADFgAAmQIAIJcBAACaAgAgmwEAAAEAIAAAAAAABZ0BAgAAAAGgAQIAAAABoQECAAAAAaIBAgAAAAGjAQIAAAABAZ0BAAAAjQECAZ0BIAAAAAEBnQFAAAAAAQsWAACCAgAwFwAAhwIAMJcBAACDAgAwmAEAAIQCADCZAQAAhgIAMJoBAACGAgAwmwEAAIYCADCcAQAAhQIAIJ0BAACGAgAwngEAAIgCADCfAQAAiQIAMAsWAAD2AQAwFwAA-wEAMJcBAAD3AQAwmAEAAPgBADCZAQAA-gEAMJoBAAD6AQAwmwEAAPoBADCcAQAA-QEAIJ0BAAD6AQAwngEAAPwBADCfAQAA_QEAMAsWAADqAQAwFwAA7wEAMJcBAADrAQAwmAEAAOwBADCZAQAA7gEAMJoBAADuAQAwmwEAAO4BADCcAQAA7QEAIJ0BAADuAQAwngEAAPABADCfAQAA8QEAMAhlAQAAAAFmQAAAAAFoAQAAAAFpAQAAAAFqAQAAAAFrAQAAAAFsAQAAAAFtgAAAAAECAAAADwAgFgAA9QEAIAMAAAAPACAWAAD1AQAgFwAA9AEAIAEPAACYAgAwDQMAALQBACBiAACxAQAwYwAADQAQZAAAsQEAMGUBAAAAAWZAAJYBACFnAQCVAQAhaAEAAAABaQEAlQEAIWoBAJUBACFrAQCVAQAhbAEAsgEAIW0AALMBACACAAAADwAgDwAA9AEAIAIAAADyAQAgDwAA8wEAIAxiAADxAQAwYwAA8gEAEGQAAPEBADBlAQCVAQAhZkAAlgEAIWcBAJUBACFoAQCVAQAhaQEAlQEAIWoBAJUBACFrAQCVAQAhbAEAsgEAIW0AALMBACAMYgAA8QEAMGMAAPIBABBkAADxAQAwZQEAlQEAIWZAAJYBACFnAQCVAQAhaAEAlQEAIWkBAJUBACFqAQCVAQAhawEAlQEAIWwBALIBACFtAACzAQAgCGUBAL8BACFmQADAAQAhaAEAvwEAIWkBAL8BACFqAQC_AQAhawEAvwEAIWwBAMEBACFtgAAAAAEIZQEAvwEAIWZAAMABACFoAQC_AQAhaQEAvwEAIWoBAL8BACFrAQC_AQAhbAEAwQEAIW2AAAAAAQhlAQAAAAFmQAAAAAFoAQAAAAFpAQAAAAFqAQAAAAFrAQAAAAFsAQAAAAFtgAAAAAEKBgAA2AEAIGUBAAAAAX9AAAAAAYABQAAAAAGBAQgAAAABggEIAAAAAYMBCAAAAAGEAQgAAAABhQEIAAAAAYYBAQAAAAECAAAACQAgFgAAgQIAIAMAAAAJACAWAACBAgAgFwAAgAIAIAEPAACXAgAwEAMAALQBACAGAAC4AQAgYgAAtgEAMGMAAAcAEGQAALYBADBlAQAAAAFnAQCVAQAhf0AAlgEAIYABQACWAQAhgQEIALcBACGCAQgAtwEAIYMBCAC3AQAhhAEIALcBACGFAQgAtwEAIYYBAQCyAQAhkwEAALUBACACAAAACQAgDwAAgAIAIAIAAAD-AQAgDwAA_wEAIA1iAAD9AQAwYwAA_gEAEGQAAP0BADBlAQCVAQAhZwEAlQEAIX9AAJYBACGAAUAAlgEAIYEBCAC3AQAhggEIALcBACGDAQgAtwEAIYQBCAC3AQAhhQEIALcBACGGAQEAsgEAIQ1iAAD9AQAwYwAA_gEAEGQAAP0BADBlAQCVAQAhZwEAlQEAIX9AAJYBACGAAUAAlgEAIYEBCAC3AQAhggEIALcBACGDAQgAtwEAIYQBCAC3AQAhhQEIALcBACGGAQEAsgEAIQllAQC_AQAhf0AAwAEAIYABQADAAQAhgQEIAM8BACGCAQgAzwEAIYMBCADPAQAhhAEIAM8BACGFAQgAzwEAIYYBAQDBAQAhCgYAANEBACBlAQC_AQAhf0AAwAEAIYABQADAAQAhgQEIAM8BACGCAQgAzwEAIYMBCADPAQAhhAEIAM8BACGFAQgAzwEAIYYBAQDBAQAhCgYAANgBACBlAQAAAAF_QAAAAAGAAUAAAAABgQEIAAAAAYIBCAAAAAGDAQgAAAABhAEIAAAAAYUBCAAAAAGGAQEAAAABBGUBAAAAAYcBAQAAAAGIAQEAAAABiQFAAAAAAQIAAAAFACAWAACNAgAgAwAAAAUAIBYAAI0CACAXAACMAgAgAQ8AAJYCADAKAwAAtAEAIGIAALoBADBjAAADABBkAAC6AQAwZQEAAAABZwEAlQEAIYcBAQCVAQAhiAEBAJUBACGJAUAAlgEAIZQBAAC5AQAgAgAAAAUAIA8AAIwCACACAAAAigIAIA8AAIsCACAIYgAAiQIAMGMAAIoCABBkAACJAgAwZQEAlQEAIWcBAJUBACGHAQEAlQEAIYgBAQCVAQAhiQFAAJYBACEIYgAAiQIAMGMAAIoCABBkAACJAgAwZQEAlQEAIWcBAJUBACGHAQEAlQEAIYgBAQCVAQAhiQFAAJYBACEEZQEAvwEAIYcBAQC_AQAhiAEBAL8BACGJAUAAwAEAIQRlAQC_AQAhhwEBAL8BACGIAQEAvwEAIYkBQADAAQAhBGUBAAAAAYcBAQAAAAGIAQEAAAABiQFAAAAAAQQWAACCAgAwlwEAAIMCADCbAQAAhgIAMJwBAACFAgAgBBYAAPYBADCXAQAA9wEAMJsBAAD6AQAwnAEAAPkBACAEFgAA6gEAMJcBAADrAQAwmwEAAO4BADCcAQAA7QEAIAAAAAQEAACRAgAgBwAAkgIAIAgAAJMCACCPAQAAuwEAIAEFAADJAQAgBGUBAAAAAYcBAQAAAAGIAQEAAAABiQFAAAAAAQllAQAAAAF_QAAAAAGAAUAAAAABgQEIAAAAAYIBCAAAAAGDAQgAAAABhAEIAAAAAYUBCAAAAAGGAQEAAAABCGUBAAAAAWZAAAAAAWgBAAAAAWkBAAAAAWoBAAAAAWsBAAAAAWwBAAAAAW2AAAAAAQoHAACPAgAgCAAAkAIAIGUBAAAAAX9AAAAAAYABQAAAAAGKAQEAAAABiwECAAAAAY0BAAAAjQECjgEgAAAAAY8BQAAAAAECAAAAAQAgFgAAmQIAIAMAAAAVACAWAACZAgAgFwAAnQIAIAwAAAAVACAHAADoAQAgCAAA6QEAIA8AAJ0CACBlAQC_AQAhf0AAwAEAIYABQADAAQAhigEBAL8BACGLAQIA4wEAIY0BAADkAY0BIo4BIADlAQAhjwFAAOYBACEKBwAA6AEAIAgAAOkBACBlAQC_AQAhf0AAwAEAIYABQADAAQAhigEBAL8BACGLAQIA4wEAIY0BAADkAY0BIo4BIADlAQAhjwFAAOYBACEKBAAAjgIAIAgAAJACACBlAQAAAAF_QAAAAAGAAUAAAAABigEBAAAAAYsBAgAAAAGNAQAAAI0BAo4BIAAAAAGPAUAAAAABAgAAAAEAIBYAAJ4CACADAAAAFQAgFgAAngIAIBcAAKICACAMAAAAFQAgBAAA5wEAIAgAAOkBACAPAACiAgAgZQEAvwEAIX9AAMABACGAAUAAwAEAIYoBAQC_AQAhiwECAOMBACGNAQAA5AGNASKOASAA5QEAIY8BQADmAQAhCgQAAOcBACAIAADpAQAgZQEAvwEAIX9AAMABACGAAUAAwAEAIYoBAQC_AQAhiwECAOMBACGNAQAA5AGNASKOASAA5QEAIY8BQADmAQAhCwMAANcBACBlAQAAAAFnAQAAAAF_QAAAAAGAAUAAAAABgQEIAAAAAYIBCAAAAAGDAQgAAAABhAEIAAAAAYUBCAAAAAGGAQEAAAABAgAAAAkAIBYAAKMCACADAAAABwAgFgAAowIAIBcAAKcCACANAAAABwAgAwAA0AEAIA8AAKcCACBlAQC_AQAhZwEAvwEAIX9AAMABACGAAUAAwAEAIYEBCADPAQAhggEIAM8BACGDAQgAzwEAIYQBCADPAQAhhQEIAM8BACGGAQEAwQEAIQsDAADQAQAgZQEAvwEAIWcBAL8BACF_QADAAQAhgAFAAMABACGBAQgAzwEAIYIBCADPAQAhgwEIAM8BACGEAQgAzwEAIYUBCADPAQAhhgEBAMEBACEKBAAAjgIAIAcAAI8CACBlAQAAAAF_QAAAAAGAAUAAAAABigEBAAAAAYsBAgAAAAGNAQAAAI0BAo4BIAAAAAGPAUAAAAABAgAAAAEAIBYAAKgCACADAAAAFQAgFgAAqAIAIBcAAKwCACAMAAAAFQAgBAAA5wEAIAcAAOgBACAPAACsAgAgZQEAvwEAIX9AAMABACGAAUAAwAEAIYoBAQC_AQAhiwECAOMBACGNAQAA5AGNASKOASAA5QEAIY8BQADmAQAhCgQAAOcBACAHAADoAQAgZQEAvwEAIX9AAMABACGAAUAAwAEAIYoBAQC_AQAhiwECAOMBACGNAQAA5AGNASKOASAA5QEAIY8BQADmAQAhBAQGAgcKAwgQBQkABgEDAAECAwABBgwEAQUAAwEDAAEDBBEABxIACBMAAAAABQkACxwADB0ADR4ADh8ADwAAAAAABQkACxwADB0ADR4ADh8ADwEDAAEBAwABAwkAFB4AFR8AFgAAAAMJABQeABUfABYBAwABAQMAAQUJABscABwdAB0eAB4fAB8AAAAAAAUJABscABwdAB0eAB4fAB8BBQADAQUAAwMJACQeACUfACYAAAADCQAkHgAlHwAmAQMAAQEDAAEDCQArHgAsHwAtAAAAAwkAKx4ALB8ALQoCAQsUAQwXAQ0YAQ4ZARAbAREdBxIeCBMgARQiBxUjCRgkARklARomByApCiEqECIrAiMsAiQtAiUuAiYvAicxAigzByk0ESo2Ais4Byw5Ei06Ai47Ai88BzA_EzFAFzJBAzNCAzRDAzVEAzZFAzdHAzhJBzlKGDpMAztOBzxPGT1QAz5RAz9SB0BVGkFWIEJYBENZBERbBEVcBEZdBEdfBEhhB0liIUpkBEtmB0xnIk1oBE5pBE9qB1BtI1FuJ1JvBVNwBVRxBVVyBVZzBVd1BVh3B1l4KFp6BVt8B1x9KV1-BV5_BV-AAQdggwEqYYQBLg" + strings: JSON.parse("[\"where\",\"orderBy\",\"cursor\",\"user\",\"wallets\",\"sybilScore\",\"explanation\",\"sybilScores\",\"worldIdVerifications\",\"conversation\",\"messages\",\"_count\",\"conversations\",\"User.findUnique\",\"User.findUniqueOrThrow\",\"User.findFirst\",\"User.findFirstOrThrow\",\"User.findMany\",\"data\",\"User.createOne\",\"User.createMany\",\"User.createManyAndReturn\",\"User.updateOne\",\"User.updateMany\",\"User.updateManyAndReturn\",\"create\",\"update\",\"User.upsertOne\",\"User.deleteOne\",\"User.deleteMany\",\"having\",\"_avg\",\"_sum\",\"_min\",\"_max\",\"User.groupBy\",\"User.aggregate\",\"Wallet.findUnique\",\"Wallet.findUniqueOrThrow\",\"Wallet.findFirst\",\"Wallet.findFirstOrThrow\",\"Wallet.findMany\",\"Wallet.createOne\",\"Wallet.createMany\",\"Wallet.createManyAndReturn\",\"Wallet.updateOne\",\"Wallet.updateMany\",\"Wallet.updateManyAndReturn\",\"Wallet.upsertOne\",\"Wallet.deleteOne\",\"Wallet.deleteMany\",\"Wallet.groupBy\",\"Wallet.aggregate\",\"SybilScore.findUnique\",\"SybilScore.findUniqueOrThrow\",\"SybilScore.findFirst\",\"SybilScore.findFirstOrThrow\",\"SybilScore.findMany\",\"SybilScore.createOne\",\"SybilScore.createMany\",\"SybilScore.createManyAndReturn\",\"SybilScore.updateOne\",\"SybilScore.updateMany\",\"SybilScore.updateManyAndReturn\",\"SybilScore.upsertOne\",\"SybilScore.deleteOne\",\"SybilScore.deleteMany\",\"SybilScore.groupBy\",\"SybilScore.aggregate\",\"SybilExplanation.findUnique\",\"SybilExplanation.findUniqueOrThrow\",\"SybilExplanation.findFirst\",\"SybilExplanation.findFirstOrThrow\",\"SybilExplanation.findMany\",\"SybilExplanation.createOne\",\"SybilExplanation.createMany\",\"SybilExplanation.createManyAndReturn\",\"SybilExplanation.updateOne\",\"SybilExplanation.updateMany\",\"SybilExplanation.updateManyAndReturn\",\"SybilExplanation.upsertOne\",\"SybilExplanation.deleteOne\",\"SybilExplanation.deleteMany\",\"SybilExplanation.groupBy\",\"SybilExplanation.aggregate\",\"WorldIdVerification.findUnique\",\"WorldIdVerification.findUniqueOrThrow\",\"WorldIdVerification.findFirst\",\"WorldIdVerification.findFirstOrThrow\",\"WorldIdVerification.findMany\",\"WorldIdVerification.createOne\",\"WorldIdVerification.createMany\",\"WorldIdVerification.createManyAndReturn\",\"WorldIdVerification.updateOne\",\"WorldIdVerification.updateMany\",\"WorldIdVerification.updateManyAndReturn\",\"WorldIdVerification.upsertOne\",\"WorldIdVerification.deleteOne\",\"WorldIdVerification.deleteMany\",\"WorldIdVerification.groupBy\",\"WorldIdVerification.aggregate\",\"Conversation.findUnique\",\"Conversation.findUniqueOrThrow\",\"Conversation.findFirst\",\"Conversation.findFirstOrThrow\",\"Conversation.findMany\",\"Conversation.createOne\",\"Conversation.createMany\",\"Conversation.createManyAndReturn\",\"Conversation.updateOne\",\"Conversation.updateMany\",\"Conversation.updateManyAndReturn\",\"Conversation.upsertOne\",\"Conversation.deleteOne\",\"Conversation.deleteMany\",\"Conversation.groupBy\",\"Conversation.aggregate\",\"Message.findUnique\",\"Message.findUniqueOrThrow\",\"Message.findFirst\",\"Message.findFirstOrThrow\",\"Message.findMany\",\"Message.createOne\",\"Message.createMany\",\"Message.createManyAndReturn\",\"Message.updateOne\",\"Message.updateMany\",\"Message.updateManyAndReturn\",\"Message.upsertOne\",\"Message.deleteOne\",\"Message.deleteMany\",\"Message.groupBy\",\"Message.aggregate\",\"AiUsageMetric.findUnique\",\"AiUsageMetric.findUniqueOrThrow\",\"AiUsageMetric.findFirst\",\"AiUsageMetric.findFirstOrThrow\",\"AiUsageMetric.findMany\",\"AiUsageMetric.createOne\",\"AiUsageMetric.createMany\",\"AiUsageMetric.createManyAndReturn\",\"AiUsageMetric.updateOne\",\"AiUsageMetric.updateMany\",\"AiUsageMetric.updateManyAndReturn\",\"AiUsageMetric.upsertOne\",\"AiUsageMetric.deleteOne\",\"AiUsageMetric.deleteMany\",\"AiUsageMetric.groupBy\",\"AiUsageMetric.aggregate\",\"AND\",\"OR\",\"NOT\",\"id\",\"userId\",\"provider\",\"model\",\"promptTokens\",\"completionTokens\",\"totalTokens\",\"latencyMs\",\"createdAt\",\"equals\",\"in\",\"notIn\",\"lt\",\"lte\",\"gt\",\"gte\",\"not\",\"contains\",\"startsWith\",\"endsWith\",\"role\",\"content\",\"conversationId\",\"title\",\"updatedAt\",\"verifiedAt\",\"nullifierHash\",\"verificationLevel\",\"worldcoinAppId\",\"worldcoinAction\",\"merkleRoot\",\"proof\",\"string_contains\",\"string_starts_with\",\"string_ends_with\",\"array_starts_with\",\"array_ends_with\",\"sybilScoreId\",\"worldcoinScore\",\"walletAgeScore\",\"stakingScore\",\"accuracyScore\",\"compositeScore\",\"calculationDetails\",\"address\",\"chain\",\"linkedAt\",\"walletAddress\",\"reputation\",\"UserRole\",\"worldcoinVerified\",\"worldcoinVerifiedAt\",\"every\",\"some\",\"none\",\"userId_createdAt\",\"address_chain\",\"is\",\"isNot\",\"connectOrCreate\",\"upsert\",\"createMany\",\"set\",\"disconnect\",\"delete\",\"connect\",\"updateMany\",\"deleteMany\",\"increment\",\"decrement\",\"multiply\",\"divide\"]"), + graph: "vgNJgAEPBAAAggIAIAcAAIMCACAIAACEAgAgDAAAhQIAIJUBAAD-AQAwlgEAAB8AEJcBAAD-AQAwmAEBAAAAAaABQADnAQAhrAEAAP8BygEisAFAAOcBACHHAQEAAAAByAECAOYBACHKASAAgAIAIcsBQACBAgAhAQAAAAEAIAkDAACJAgAglQEAAJICADCWAQAAAwAQlwEAAJICADCYAQEA5AEAIZkBAQDkAQAhxAEBAOQBACHFAQEA5AEAIcYBQADnAQAhAQMAAJkDACAKAwAAiQIAIJUBAACSAgAwlgEAAAMAEJcBAACSAgAwmAEBAAAAAZkBAQDkAQAhxAEBAOQBACHFAQEA5AEAIcYBQADnAQAh0AEAAJECACADAAAAAwAgAQAABAAwAgAABQAgDwMAAIkCACAGAACQAgAglQEAAI4CADCWAQAABwAQlwEAAI4CADCYAQEA5AEAIZkBAQDkAQAhoAFAAOcBACGwAUAA5wEAIb4BCACPAgAhvwEIAI8CACHAAQgAjwIAIcEBCACPAgAhwgEIAI8CACHDAQEA5QEAIQMDAACZAwAgBgAAmwMAIMMBAACTAgAgEAMAAIkCACAGAACQAgAglQEAAI4CADCWAQAABwAQlwEAAI4CADCYAQEAAAABmQEBAOQBACGgAUAA5wEAIbABQADnAQAhvgEIAI8CACG_AQgAjwIAIcABCACPAgAhwQEIAI8CACHCAQgAjwIAIcMBAQDlAQAhzwEAAI0CACADAAAABwAgAQAACAAwAgAACQAgCAUAAO8BACAGAQDkAQAhlQEAAO4BADCWAQAACwAQlwEAAO4BADCYAQEA5AEAIaABQADnAQAhvQEBAOQBACEBAAAACwAgDQMAAIkCACCVAQAAiwIAMJYBAAANABCXAQAAiwIAMJgBAQDkAQAhmQEBAOQBACGxAUAA5wEAIbIBAQDkAQAhswEBAOQBACG0AQEA5AEAIbUBAQDkAQAhtgEBAOUBACG3AQAAjAIAIAMDAACZAwAgtgEAAJMCACC3AQAAkwIAIA0DAACJAgAglQEAAIsCADCWAQAADQAQlwEAAIsCADCYAQEAAAABmQEBAOQBACGxAUAA5wEAIbIBAQAAAAGzAQEA5AEAIbQBAQDkAQAhtQEBAOQBACG2AQEA5QEAIbcBAACMAgAgAwAAAA0AIAEAAA4AMAIAAA8AIAoDAACJAgAgCgAAigIAIJUBAACIAgAwlgEAABEAEJcBAACIAgAwmAEBAOQBACGZAQEA5AEAIaABQADnAQAhrwEBAOUBACGwAUAA5wEAIQMDAACZAwAgCgAAmgMAIK8BAACTAgAgCgMAAIkCACAKAACKAgAglQEAAIgCADCWAQAAEQAQlwEAAIgCADCYAQEAAAABmQEBAOQBACGgAUAA5wEAIa8BAQDlAQAhsAFAAOcBACEDAAAAEQAgAQAAEgAwAgAAEwAgCQkAAIcCACCVAQAAhgIAMJYBAAAVABCXAQAAhgIAMJgBAQDkAQAhoAFAAOcBACGsAQEA5AEAIa0BAQDkAQAhrgEBAOQBACEBCQAAmAMAIAkJAACHAgAglQEAAIYCADCWAQAAFQAQlwEAAIYCADCYAQEAAAABoAFAAOcBACGsAQEA5AEAIa0BAQDkAQAhrgEBAOQBACEDAAAAFQAgAQAAFgAwAgAAFwAgAQAAABUAIAEAAAADACABAAAABwAgAQAAAA0AIAEAAAARACABAAAAAQAgDwQAAIICACAHAACDAgAgCAAAhAIAIAwAAIUCACCVAQAA_gEAMJYBAAAfABCXAQAA_gEAMJgBAQDkAQAhoAFAAOcBACGsAQAA_wHKASKwAUAA5wEAIccBAQDkAQAhyAECAOYBACHKASAAgAIAIcsBQACBAgAhBQQAAJQDACAHAACVAwAgCAAAlgMAIAwAAJcDACDLAQAAkwIAIAMAAAAfACABAAAgADACAAABACADAAAAHwAgAQAAIAAwAgAAAQAgAwAAAB8AIAEAACAAMAIAAAEAIAwEAACQAwAgBwAAkQMAIAgAAJIDACAMAACTAwAgmAEBAAAAAaABQAAAAAGsAQAAAMoBArABQAAAAAHHAQEAAAAByAECAAAAAcoBIAAAAAHLAUAAAAABARIAACQAIAiYAQEAAAABoAFAAAAAAawBAAAAygECsAFAAAAAAccBAQAAAAHIAQIAAAABygEgAAAAAcsBQAAAAAEBEgAAJgAwARIAACYAMAwEAADcAgAgBwAA3QIAIAgAAN4CACAMAADfAgAgmAEBAJkCACGgAUAAnAIAIawBAADZAsoBIrABQACcAgAhxwEBAJkCACHIAQIAmwIAIcoBIADaAgAhywFAANsCACECAAAAAQAgEgAAKQAgCJgBAQCZAgAhoAFAAJwCACGsAQAA2QLKASKwAUAAnAIAIccBAQCZAgAhyAECAJsCACHKASAA2gIAIcsBQADbAgAhAgAAAB8AIBIAACsAIAIAAAAfACASAAArACADAAAAAQAgGQAAJAAgGgAAKQAgAQAAAAEAIAEAAAAfACAGCwAA1AIAIB8AANUCACAgAADYAgAgIQAA1wIAICIAANYCACDLAQAAkwIAIAuVAQAA9AEAMJYBAAAyABCXAQAA9AEAMJgBAQDVAQAhoAFAANgBACGsAQAA9QHKASKwAUAA2AEAIccBAQDVAQAhyAECANcBACHKASAA9gEAIcsBQAD3AQAhAwAAAB8AIAEAADEAMB4AADIAIAMAAAAfACABAAAgADACAAABACABAAAABQAgAQAAAAUAIAMAAAADACABAAAEADACAAAFACADAAAAAwAgAQAABAAwAgAABQAgAwAAAAMAIAEAAAQAMAIAAAUAIAYDAADTAgAgmAEBAAAAAZkBAQAAAAHEAQEAAAABxQEBAAAAAcYBQAAAAAEBEgAAOgAgBZgBAQAAAAGZAQEAAAABxAEBAAAAAcUBAQAAAAHGAUAAAAABARIAADwAMAESAAA8ADAGAwAA0gIAIJgBAQCZAgAhmQEBAJkCACHEAQEAmQIAIcUBAQCZAgAhxgFAAJwCACECAAAABQAgEgAAPwAgBZgBAQCZAgAhmQEBAJkCACHEAQEAmQIAIcUBAQCZAgAhxgFAAJwCACECAAAAAwAgEgAAQQAgAgAAAAMAIBIAAEEAIAMAAAAFACAZAAA6ACAaAAA_ACABAAAABQAgAQAAAAMAIAMLAADPAgAgIQAA0QIAICIAANACACAIlQEAAPMBADCWAQAASAAQlwEAAPMBADCYAQEA1QEAIZkBAQDVAQAhxAEBANUBACHFAQEA1QEAIcYBQADYAQAhAwAAAAMAIAEAAEcAMB4AAEgAIAMAAAADACABAAAEADACAAAFACABAAAACQAgAQAAAAkAIAMAAAAHACABAAAIADACAAAJACADAAAABwAgAQAACAAwAgAACQAgAwAAAAcAIAEAAAgAMAIAAAkAIAwDAADNAgAgBgAAzgIAIJgBAQAAAAGZAQEAAAABoAFAAAAAAbABQAAAAAG-AQgAAAABvwEIAAAAAcABCAAAAAHBAQgAAAABwgEIAAAAAcMBAQAAAAEBEgAAUAAgCpgBAQAAAAGZAQEAAAABoAFAAAAAAbABQAAAAAG-AQgAAAABvwEIAAAAAcABCAAAAAHBAQgAAAABwgEIAAAAAcMBAQAAAAEBEgAAUgAwARIAAFIAMAwDAADGAgAgBgAAxwIAIJgBAQCZAgAhmQEBAJkCACGgAUAAnAIAIbABQACcAgAhvgEIAMUCACG_AQgAxQIAIcABCADFAgAhwQEIAMUCACHCAQgAxQIAIcMBAQCaAgAhAgAAAAkAIBIAAFUAIAqYAQEAmQIAIZkBAQCZAgAhoAFAAJwCACGwAUAAnAIAIb4BCADFAgAhvwEIAMUCACHAAQgAxQIAIcEBCADFAgAhwgEIAMUCACHDAQEAmgIAIQIAAAAHACASAABXACACAAAABwAgEgAAVwAgAwAAAAkAIBkAAFAAIBoAAFUAIAEAAAAJACABAAAABwAgBgsAAMACACAfAADBAgAgIAAAxAIAICEAAMMCACAiAADCAgAgwwEAAJMCACANlQEAAPABADCWAQAAXgAQlwEAAPABADCYAQEA1QEAIZkBAQDVAQAhoAFAANgBACGwAUAA2AEAIb4BCADxAQAhvwEIAPEBACHAAQgA8QEAIcEBCADxAQAhwgEIAPEBACHDAQEA1gEAIQMAAAAHACABAABdADAeAABeACADAAAABwAgAQAACAAwAgAACQAgCAUAAO8BACAGAQDkAQAhlQEAAO4BADCWAQAACwAQlwEAAO4BADCYAQEAAAABoAFAAOcBACG9AQEAAAABAQAAAGEAIAEAAABhACABBQAAvwIAIAMAAAALACABAABkADACAABhACADAAAACwAgAQAAZAAwAgAAYQAgAwAAAAsAIAEAAGQAMAIAAGEAIAUFAAC-AgAgBgEAAAABmAEBAAAAAaABQAAAAAG9AQEAAAABARIAAGgAIAQGAQAAAAGYAQEAAAABoAFAAAAAAb0BAQAAAAEBEgAAagAwARIAAGoAMAUFAAC9AgAgBgEAmQIAIZgBAQCZAgAhoAFAAJwCACG9AQEAmQIAIQIAAABhACASAABtACAEBgEAmQIAIZgBAQCZAgAhoAFAAJwCACG9AQEAmQIAIQIAAAALACASAABvACACAAAACwAgEgAAbwAgAwAAAGEAIBkAAGgAIBoAAG0AIAEAAABhACABAAAACwAgAwsAALoCACAhAAC8AgAgIgAAuwIAIAcGAQDVAQAhlQEAAO0BADCWAQAAdgAQlwEAAO0BADCYAQEA1QEAIaABQADYAQAhvQEBANUBACEDAAAACwAgAQAAdQAwHgAAdgAgAwAAAAsAIAEAAGQAMAIAAGEAIAEAAAAPACABAAAADwAgAwAAAA0AIAEAAA4AMAIAAA8AIAMAAAANACABAAAOADACAAAPACADAAAADQAgAQAADgAwAgAADwAgCgMAALkCACCYAQEAAAABmQEBAAAAAbEBQAAAAAGyAQEAAAABswEBAAAAAbQBAQAAAAG1AQEAAAABtgEBAAAAAbcBgAAAAAEBEgAAfgAgCZgBAQAAAAGZAQEAAAABsQFAAAAAAbIBAQAAAAGzAQEAAAABtAEBAAAAAbUBAQAAAAG2AQEAAAABtwGAAAAAAQESAACAAQAwARIAAIABADAKAwAAuAIAIJgBAQCZAgAhmQEBAJkCACGxAUAAnAIAIbIBAQCZAgAhswEBAJkCACG0AQEAmQIAIbUBAQCZAgAhtgEBAJoCACG3AYAAAAABAgAAAA8AIBIAAIMBACAJmAEBAJkCACGZAQEAmQIAIbEBQACcAgAhsgEBAJkCACGzAQEAmQIAIbQBAQCZAgAhtQEBAJkCACG2AQEAmgIAIbcBgAAAAAECAAAADQAgEgAAhQEAIAIAAAANACASAACFAQAgAwAAAA8AIBkAAH4AIBoAAIMBACABAAAADwAgAQAAAA0AIAULAAC1AgAgIQAAtwIAICIAALYCACC2AQAAkwIAILcBAACTAgAgDJUBAADqAQAwlgEAAIwBABCXAQAA6gEAMJgBAQDVAQAhmQEBANUBACGxAUAA2AEAIbIBAQDVAQAhswEBANUBACG0AQEA1QEAIbUBAQDVAQAhtgEBANYBACG3AQAA6wEAIAMAAAANACABAACLAQAwHgAAjAEAIAMAAAANACABAAAOADACAAAPACABAAAAEwAgAQAAABMAIAMAAAARACABAAASADACAAATACADAAAAEQAgAQAAEgAwAgAAEwAgAwAAABEAIAEAABIAMAIAABMAIAcDAACzAgAgCgAAtAIAIJgBAQAAAAGZAQEAAAABoAFAAAAAAa8BAQAAAAGwAUAAAAABARIAAJQBACAFmAEBAAAAAZkBAQAAAAGgAUAAAAABrwEBAAAAAbABQAAAAAEBEgAAlgEAMAESAACWAQAwBwMAAKUCACAKAACmAgAgmAEBAJkCACGZAQEAmQIAIaABQACcAgAhrwEBAJoCACGwAUAAnAIAIQIAAAATACASAACZAQAgBZgBAQCZAgAhmQEBAJkCACGgAUAAnAIAIa8BAQCaAgAhsAFAAJwCACECAAAAEQAgEgAAmwEAIAIAAAARACASAACbAQAgAwAAABMAIBkAAJQBACAaAACZAQAgAQAAABMAIAEAAAARACAECwAAogIAICEAAKQCACAiAACjAgAgrwEAAJMCACAIlQEAAOkBADCWAQAAogEAEJcBAADpAQAwmAEBANUBACGZAQEA1QEAIaABQADYAQAhrwEBANYBACGwAUAA2AEAIQMAAAARACABAAChAQAwHgAAogEAIAMAAAARACABAAASADACAAATACABAAAAFwAgAQAAABcAIAMAAAAVACABAAAWADACAAAXACADAAAAFQAgAQAAFgAwAgAAFwAgAwAAABUAIAEAABYAMAIAABcAIAYJAAChAgAgmAEBAAAAAaABQAAAAAGsAQEAAAABrQEBAAAAAa4BAQAAAAEBEgAAqgEAIAWYAQEAAAABoAFAAAAAAawBAQAAAAGtAQEAAAABrgEBAAAAAQESAACsAQAwARIAAKwBADAGCQAAoAIAIJgBAQCZAgAhoAFAAJwCACGsAQEAmQIAIa0BAQCZAgAhrgEBAJkCACECAAAAFwAgEgAArwEAIAWYAQEAmQIAIaABQACcAgAhrAEBAJkCACGtAQEAmQIAIa4BAQCZAgAhAgAAABUAIBIAALEBACACAAAAFQAgEgAAsQEAIAMAAAAXACAZAACqAQAgGgAArwEAIAEAAAAXACABAAAAFQAgAwsAAJ0CACAhAACfAgAgIgAAngIAIAiVAQAA6AEAMJYBAAC4AQAQlwEAAOgBADCYAQEA1QEAIaABQADYAQAhrAEBANUBACGtAQEA1QEAIa4BAQDVAQAhAwAAABUAIAEAALcBADAeAAC4AQAgAwAAABUAIAEAABYAMAIAABcAIAyVAQAA4wEAMJYBAAC-AQAQlwEAAOMBADCYAQEAAAABmQEBAOUBACGaAQEA5AEAIZsBAQDkAQAhnAECAOYBACGdAQIA5gEAIZ4BAgDmAQAhnwECAOYBACGgAUAA5wEAIQEAAAC7AQAgAQAAALsBACAMlQEAAOMBADCWAQAAvgEAEJcBAADjAQAwmAEBAOQBACGZAQEA5QEAIZoBAQDkAQAhmwEBAOQBACGcAQIA5gEAIZ0BAgDmAQAhngECAOYBACGfAQIA5gEAIaABQADnAQAhAZkBAACTAgAgAwAAAL4BACABAAC_AQAwAgAAuwEAIAMAAAC-AQAgAQAAvwEAMAIAALsBACADAAAAvgEAIAEAAL8BADACAAC7AQAgCZgBAQAAAAGZAQEAAAABmgEBAAAAAZsBAQAAAAGcAQIAAAABnQECAAAAAZ4BAgAAAAGfAQIAAAABoAFAAAAAAQESAADDAQAgCZgBAQAAAAGZAQEAAAABmgEBAAAAAZsBAQAAAAGcAQIAAAABnQECAAAAAZ4BAgAAAAGfAQIAAAABoAFAAAAAAQESAADFAQAwARIAAMUBADAJmAEBAJkCACGZAQEAmgIAIZoBAQCZAgAhmwEBAJkCACGcAQIAmwIAIZ0BAgCbAgAhngECAJsCACGfAQIAmwIAIaABQACcAgAhAgAAALsBACASAADIAQAgCZgBAQCZAgAhmQEBAJoCACGaAQEAmQIAIZsBAQCZAgAhnAECAJsCACGdAQIAmwIAIZ4BAgCbAgAhnwECAJsCACGgAUAAnAIAIQIAAAC-AQAgEgAAygEAIAIAAAC-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_AQgAjwIAIcABCACPAgAhwQEIAI8CACHCAQgAjwIAIcMBAQDlAQAh0QEAAAcAINIBAAAHACANlQEAAPABADCWAQAAXgAQlwEAAPABADCYAQEA1QEAIZkBAQDVAQAhoAFAANgBACGwAUAA2AEAIb4BCADxAQAhvwEIAPEBACHAAQgA8QEAIcEBCADxAQAhwgEIAPEBACHDAQEA1gEAIQ0LAADaAQAgHwAA3QEAICAAAN0BACAhAADdAQAgIgAA3QEAIKEBCAAAAAGiAQgAAAAEowEIAAAABKQBCAAAAAGlAQgAAAABpgEIAAAAAacBCAAAAAGoAQgA8gEAIQ0LAADaAQAgHwAA3QEAICAAAN0BACAhAADdAQAgIgAA3QEAIKEBCAAAAAGiAQgAAAAEowEIAAAABKQBCAAAAAGlAQgAAAABpgEIAAAAAacBCAAAAAGoAQgA8gEAIQiVAQAA8wEAMJYBAABIABCXAQAA8wEAMJgBAQDVAQAhmQEBANUBACHEAQEA1QEAIcUBAQDVAQAhxgFAANgBACELlQEAAPQBADCWAQAAMgAQlwEAAPQBADCYAQEA1QEAIaABQADYAQAhrAEAAPUBygEisAFAANgBACHHAQEA1QEAIcgBAgDXAQAhygEgAPYBACHLAUAA9wEAIQcLAADaAQAgIQAA_QEAICIAAP0BACChAQAAAMoBAqIBAAAAygEIowEAAADKAQioAQAA_AHKASIFCwAA2gEAICEAAPsBACAiAAD7AQAgoQEgAAAAAagBIAD6AQAhCwsAAN8BACAhAAD5AQAgIgAA-QEAIKEBQAAAAAGiAUAAAAAFowFAAAAABaQBQAAAAAGlAUAAAAABpgFAAAAAAacBQAAAAAGoAUAA-AEAIQsLAADfAQAgIQAA-QEAICIAAPkBACChAUAAAAABogFAAAAABaMBQAAAAAWkAUAAAAABpQFAAAAAAaYBQAAAAAGnAUAAAAABqAFAAPgBACEIoQFAAAAAAaIBQAAAAAWjAUAAAAAFpAFAAAAAAaUBQAAAAAGmAUAAAAABpwFAAAAAAagBQAD5AQAhBQsAANoBACAhAAD7AQAgIgAA-wEAIKEBIAAAAAGoASAA-gEAIQKhASAAAAABqAEgAPsBACEHCwAA2gEAICEAAP0BACAiAAD9AQAgoQEAAADKAQKiAQAAAMoBCKMBAAAAygEIqAEAAPwBygEiBKEBAAAAygECogEAAADKAQijAQAAAMoBCKgBAAD9AcoBIg8EAACCAgAgBwAAgwIAIAgAAIQCACAMAACFAgAglQEAAP4BADCWAQAAHwAQlwEAAP4BADCYAQEA5AEAIaABQADnAQAhrAEAAP8BygEisAFAAOcBACHHAQEA5AEAIcgBAgDmAQAhygEgAIACACHLAUAAgQIAIQShAQAAAMoBAqIBAAAAygEIowEAAADKAQioAQAA_QHKASICoQEgAAAAAagBIAD7AQAhCKEBQAAAAAGiAUAAAAAFowFAAAAABaQBQAAAAAGlAUAAAAABpgFAAAAAAacBQAAAAAGoAUAA-QEAIQPMAQAAAwAgzQEAAAMAIM4BAAADACADzAEAAAcAIM0BAAAHACDOAQAABwAgA8wBAAANACDNAQAADQAgzgEAAA0AIAPMAQAAEQAgzQEAABEAIM4BAAARACAJCQAAhwIAIJUBAACGAgAwlgEAABUAEJcBAACGAgAwmAEBAOQBACGgAUAA5wEAIawBAQDkAQAhrQEBAOQBACGuAQEA5AEAIQwDAACJAgAgCgAAigIAIJUBAACIAgAwlgEAABEAEJcBAACIAgAwmAEBAOQBACGZAQEA5AEAIaABQADnAQAhrwEBAOUBACGwAUAA5wEAIdEBAAARACDSAQAAEQAgCgMAAIkCACAKAACKAgAglQEAAIgCADCWAQAAEQAQlwEAAIgCADCYAQEA5AEAIZkBAQDkAQAhoAFAAOcBACGvAQEA5QEAIbABQADnAQAhEQQAAIICACAHAACDAgAgCAAAhAIAIAwAAIUCACCVAQAA_gEAMJYBAAAfABCXAQAA_gEAMJgBAQDkAQAhoAFAAOcBACGsAQAA_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-AIAMBoAAP0CADDTAQAA-QIAMNQBAAD6AgAw1QEAAPsCACDWAQAA_AIAMNcBAAD8AgAw2AEAAPwCADDZAQAA_AIAMNoBAAD-AgAw2wEAAP8CADALGQAA7AIAMBoAAPECADDTAQAA7QIAMNQBAADuAgAw1QEAAO8CACDWAQAA8AIAMNcBAADwAgAw2AEAAPACADDZAQAA8AIAMNoBAADyAgAw2wEAAPMCADALGQAA4AIAMBoAAOUCADDTAQAA4QIAMNQBAADiAgAw1QEAAOMCACDWAQAA5AIAMNcBAADkAgAw2AEAAOQCADDZAQAA5AIAMNoBAADmAgAw2wEAAOcCADAFCgAAtAIAIJgBAQAAAAGgAUAAAAABrwEBAAAAAbABQAAAAAECAAAAEwAgGQAA6wIAIAMAAAATACAZAADrAgAgGgAA6gIAIAESAACfAwAwCgMAAIkCACAKAACKAgAglQEAAIgCADCWAQAAEQAQlwEAAIgCADCYAQEAAAABmQEBAOQBACGgAUAA5wEAIa8BAQDlAQAhsAFAAOcBACECAAAAEwAgEgAA6gIAIAIAAADoAgAgEgAA6QIAIAiVAQAA5wIAMJYBAADoAgAQlwEAAOcCADCYAQEA5AEAIZkBAQDkAQAhoAFAAOcBACGvAQEA5QEAIbABQADnAQAhCJUBAADnAgAwlgEAAOgCABCXAQAA5wIAMJgBAQDkAQAhmQEBAOQBACGgAUAA5wEAIa8BAQDlAQAhsAFAAOcBACEEmAEBAJkCACGgAUAAnAIAIa8BAQCaAgAhsAFAAJwCACEFCgAApgIAIJgBAQCZAgAhoAFAAJwCACGvAQEAmgIAIbABQACcAgAhBQoAALQCACCYAQEAAAABoAFAAAAAAa8BAQAAAAGwAUAAAAABCJgBAQAAAAGxAUAAAAABsgEBAAAAAbMBAQAAAAG0AQEAAAABtQEBAAAAAbYBAQAAAAG3AYAAAAABAgAAAA8AIBkAAPcCACADAAAADwAgGQAA9wIAIBoAAPYCACABEgAAngMAMA0DAACJAgAglQEAAIsCADCWAQAADQAQlwEAAIsCADCYAQEAAAABmQEBAOQBACGxAUAA5wEAIbIBAQAAAAGzAQEA5AEAIbQBAQDkAQAhtQEBAOQBACG2AQEA5QEAIbcBAACMAgAgAgAAAA8AIBIAAPYCACACAAAA9AIAIBIAAPUCACAMlQEAAPMCADCWAQAA9AIAEJcBAADzAgAwmAEBAOQBACGZAQEA5AEAIbEBQADnAQAhsgEBAOQBACGzAQEA5AEAIbQBAQDkAQAhtQEBAOQBACG2AQEA5QEAIbcBAACMAgAgDJUBAADzAgAwlgEAAPQCABCXAQAA8wIAMJgBAQDkAQAhmQEBAOQBACGxAUAA5wEAIbIBAQDkAQAhswEBAOQBACG0AQEA5AEAIbUBAQDkAQAhtgEBAOUBACG3AQAAjAIAIAiYAQEAmQIAIbEBQACcAgAhsgEBAJkCACGzAQEAmQIAIbQBAQCZAgAhtQEBAJkCACG2AQEAmgIAIbcBgAAAAAEImAEBAJkCACGxAUAAnAIAIbIBAQCZAgAhswEBAJkCACG0AQEAmQIAIbUBAQCZAgAhtgEBAJoCACG3AYAAAAABCJgBAQAAAAGxAUAAAAABsgEBAAAAAbMBAQAAAAG0AQEAAAABtQEBAAAAAbYBAQAAAAG3AYAAAAABCgYAAM4CACCYAQEAAAABoAFAAAAAAbABQAAAAAG-AQgAAAABvwEIAAAAAcABCAAAAAHBAQgAAAABwgEIAAAAAcMBAQAAAAECAAAACQAgGQAAgwMAIAMAAAAJACAZAACDAwAgGgAAggMAIAESAACdAwAwEAMAAIkCACAGAACQAgAglQEAAI4CADCWAQAABwAQlwEAAI4CADCYAQEAAAABmQEBAOQBACGgAUAA5wEAIbABQADnAQAhvgEIAI8CACG_AQgAjwIAIcABCACPAgAhwQEIAI8CACHCAQgAjwIAIcMBAQDlAQAhzwEAAI0CACACAAAACQAgEgAAggMAIAIAAACAAwAgEgAAgQMAIA2VAQAA_wIAMJYBAACAAwAQlwEAAP8CADCYAQEA5AEAIZkBAQDkAQAhoAFAAOcBACGwAUAA5wEAIb4BCACPAgAhvwEIAI8CACHAAQgAjwIAIcEBCACPAgAhwgEIAI8CACHDAQEA5QEAIQ2VAQAA_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-AwAgCAAAABEAIAMAAKUCACASAAC-AwAgmAEBAJkCACGZAQEAmQIAIaABQACcAgAhrwEBAJoCACGwAUAAnAIAIQYDAAClAgAgmAEBAJkCACGZAQEAmQIAIaABQACcAgAhrwEBAJoCACGwAUAAnAIAIQUEBgIHCgMIEAULAAkMFAYBAwABAgMAAQYMBAEFAAMBAwABAwMAAQoYBwsACAEJAAYBChkABAQaAAcbAAgcAAwdAAAAAAULAA4fAA8gABAhABEiABIAAAAAAAULAA4fAA8gABAhABEiABIBAwABAQMAAQMLABchABgiABkAAAADCwAXIQAYIgAZAQMAAQEDAAEFCwAeHwAfIAAgIQAhIgAiAAAAAAAFCwAeHwAfIAAgIQAhIgAiAQUAAwEFAAMDCwAnIQAoIgApAAAAAwsAJyEAKCIAKQEDAAEBAwABAwsALiEALyIAMAAAAAMLAC4hAC8iADABAwABAQMAAQMLADUhADYiADcAAAADCwA1IQA2IgA3AQkABgEJAAYDCwA8IQA9IgA-AAAAAwsAPCEAPSIAPgAAAAULAEQfAEUgAEYhAEciAEgAAAAAAAULAEQfAEUgAEYhAEciAEgNAgEOHgEPIQEQIgERIwETJQEUJwoVKAsWKgEXLAoYLQwbLgEcLwEdMAojMw0kNBMlNQImNgInNwIoOAIpOQIqOwIrPQosPhQtQAIuQgovQxUwRAIxRQIyRgozSRY0Sho1SwM2TAM3TQM4TgM5TwM6UQM7Uwo8VBs9VgM-WAo_WRxAWgNBWwNCXApDXx1EYCNFYgRGYwRHZQRIZgRJZwRKaQRLawpMbCRNbgROcApPcSVQcgRRcwRSdApTdyZUeCpVeQVWegVXewVYfAVZfQVafwVbgQEKXIIBK12EAQVehgEKX4cBLGCIAQVhiQEFYooBCmONAS1kjgExZY8BBmaQAQZnkQEGaJIBBmmTAQZqlQEGa5cBCmyYATJtmgEGbpwBCm-dATNwngEGcZ8BBnKgAQpzowE0dKQBOHWlAQd2pgEHd6cBB3ioAQd5qQEHeqsBB3utAQp8rgE5fbABB36yAQp_swE6gAG0AQeBAbUBB4IBtgEKgwG5ATuEAboBP4UBvAFAhgG9AUCHAcABQIgBwQFAiQHCAUCKAcQBQIsBxgEKjAHHAUGNAckBQI4BywEKjwHMAUKQAc0BQJEBzgFAkgHPAQqTAdIBQ5QB0wFJ" } async function decodeBase64AsWasm(wasmBase64: string): Promise { @@ -233,6 +233,36 @@ export interface PrismaClient< * ``` */ get worldIdVerification(): Prisma.WorldIdVerificationDelegate; + + /** + * `prisma.conversation`: Exposes CRUD operations for the **Conversation** model. + * Example usage: + * ```ts + * // Fetch zero or more Conversations + * const conversations = await prisma.conversation.findMany() + * ``` + */ + get conversation(): Prisma.ConversationDelegate; + + /** + * `prisma.message`: Exposes CRUD operations for the **Message** model. + * Example usage: + * ```ts + * // Fetch zero or more Messages + * const messages = await prisma.message.findMany() + * ``` + */ + get message(): Prisma.MessageDelegate; + + /** + * `prisma.aiUsageMetric`: Exposes CRUD operations for the **AiUsageMetric** model. + * Example usage: + * ```ts + * // Fetch zero or more AiUsageMetrics + * const aiUsageMetrics = await prisma.aiUsageMetric.findMany() + * ``` + */ + get aiUsageMetric(): Prisma.AiUsageMetricDelegate; } export function getPrismaClientClass(): PrismaClientConstructor { diff --git a/src/generated/client/internal/prismaNamespace.ts b/src/generated/client/internal/prismaNamespace.ts index e7b4679..2b0aaff 100644 --- a/src/generated/client/internal/prismaNamespace.ts +++ b/src/generated/client/internal/prismaNamespace.ts @@ -388,7 +388,10 @@ export const ModelName = { Wallet: 'Wallet', SybilScore: 'SybilScore', SybilExplanation: 'SybilExplanation', - WorldIdVerification: 'WorldIdVerification' + WorldIdVerification: 'WorldIdVerification', + Conversation: 'Conversation', + Message: 'Message', + AiUsageMetric: 'AiUsageMetric' } as const export type ModelName = (typeof ModelName)[keyof typeof ModelName] @@ -404,7 +407,7 @@ export type TypeMap + fields: Prisma.ConversationFieldRefs + operations: { + findUnique: { + args: Prisma.ConversationFindUniqueArgs + result: runtime.Types.Utils.PayloadToResult | null + } + findUniqueOrThrow: { + args: Prisma.ConversationFindUniqueOrThrowArgs + result: runtime.Types.Utils.PayloadToResult + } + findFirst: { + args: Prisma.ConversationFindFirstArgs + result: runtime.Types.Utils.PayloadToResult | null + } + findFirstOrThrow: { + args: Prisma.ConversationFindFirstOrThrowArgs + result: runtime.Types.Utils.PayloadToResult + } + findMany: { + args: Prisma.ConversationFindManyArgs + result: runtime.Types.Utils.PayloadToResult[] + } + create: { + args: Prisma.ConversationCreateArgs + result: runtime.Types.Utils.PayloadToResult + } + createMany: { + args: Prisma.ConversationCreateManyArgs + result: BatchPayload + } + createManyAndReturn: { + args: Prisma.ConversationCreateManyAndReturnArgs + result: runtime.Types.Utils.PayloadToResult[] + } + delete: { + args: Prisma.ConversationDeleteArgs + result: runtime.Types.Utils.PayloadToResult + } + update: { + args: Prisma.ConversationUpdateArgs + result: runtime.Types.Utils.PayloadToResult + } + deleteMany: { + args: Prisma.ConversationDeleteManyArgs + result: BatchPayload + } + updateMany: { + args: Prisma.ConversationUpdateManyArgs + result: BatchPayload + } + updateManyAndReturn: { + args: Prisma.ConversationUpdateManyAndReturnArgs + result: runtime.Types.Utils.PayloadToResult[] + } + upsert: { + args: Prisma.ConversationUpsertArgs + result: runtime.Types.Utils.PayloadToResult + } + aggregate: { + args: Prisma.ConversationAggregateArgs + result: runtime.Types.Utils.Optional + } + groupBy: { + args: Prisma.ConversationGroupByArgs + result: runtime.Types.Utils.Optional[] + } + count: { + args: Prisma.ConversationCountArgs + result: runtime.Types.Utils.Optional | number + } + } + } + Message: { + payload: Prisma.$MessagePayload + fields: Prisma.MessageFieldRefs + operations: { + findUnique: { + args: Prisma.MessageFindUniqueArgs + result: runtime.Types.Utils.PayloadToResult | null + } + findUniqueOrThrow: { + args: Prisma.MessageFindUniqueOrThrowArgs + result: runtime.Types.Utils.PayloadToResult + } + findFirst: { + args: Prisma.MessageFindFirstArgs + result: runtime.Types.Utils.PayloadToResult | null + } + findFirstOrThrow: { + args: Prisma.MessageFindFirstOrThrowArgs + result: runtime.Types.Utils.PayloadToResult + } + findMany: { + args: Prisma.MessageFindManyArgs + result: runtime.Types.Utils.PayloadToResult[] + } + create: { + args: Prisma.MessageCreateArgs + result: runtime.Types.Utils.PayloadToResult + } + createMany: { + args: Prisma.MessageCreateManyArgs + result: BatchPayload + } + createManyAndReturn: { + args: Prisma.MessageCreateManyAndReturnArgs + result: runtime.Types.Utils.PayloadToResult[] + } + delete: { + args: Prisma.MessageDeleteArgs + result: runtime.Types.Utils.PayloadToResult + } + update: { + args: Prisma.MessageUpdateArgs + result: runtime.Types.Utils.PayloadToResult + } + deleteMany: { + args: Prisma.MessageDeleteManyArgs + result: BatchPayload + } + updateMany: { + args: Prisma.MessageUpdateManyArgs + result: BatchPayload + } + updateManyAndReturn: { + args: Prisma.MessageUpdateManyAndReturnArgs + result: runtime.Types.Utils.PayloadToResult[] + } + upsert: { + args: Prisma.MessageUpsertArgs + result: runtime.Types.Utils.PayloadToResult + } + aggregate: { + args: Prisma.MessageAggregateArgs + result: runtime.Types.Utils.Optional + } + groupBy: { + args: Prisma.MessageGroupByArgs + result: runtime.Types.Utils.Optional[] + } + count: { + args: Prisma.MessageCountArgs + result: runtime.Types.Utils.Optional | number + } + } + } + AiUsageMetric: { + payload: Prisma.$AiUsageMetricPayload + fields: Prisma.AiUsageMetricFieldRefs + operations: { + findUnique: { + args: Prisma.AiUsageMetricFindUniqueArgs + result: runtime.Types.Utils.PayloadToResult | null + } + findUniqueOrThrow: { + args: Prisma.AiUsageMetricFindUniqueOrThrowArgs + result: runtime.Types.Utils.PayloadToResult + } + findFirst: { + args: Prisma.AiUsageMetricFindFirstArgs + result: runtime.Types.Utils.PayloadToResult | null + } + findFirstOrThrow: { + args: Prisma.AiUsageMetricFindFirstOrThrowArgs + result: runtime.Types.Utils.PayloadToResult + } + findMany: { + args: Prisma.AiUsageMetricFindManyArgs + result: runtime.Types.Utils.PayloadToResult[] + } + create: { + args: Prisma.AiUsageMetricCreateArgs + result: runtime.Types.Utils.PayloadToResult + } + createMany: { + args: Prisma.AiUsageMetricCreateManyArgs + result: BatchPayload + } + createManyAndReturn: { + args: Prisma.AiUsageMetricCreateManyAndReturnArgs + result: runtime.Types.Utils.PayloadToResult[] + } + delete: { + args: Prisma.AiUsageMetricDeleteArgs + result: runtime.Types.Utils.PayloadToResult + } + update: { + args: Prisma.AiUsageMetricUpdateArgs + result: runtime.Types.Utils.PayloadToResult + } + deleteMany: { + args: Prisma.AiUsageMetricDeleteManyArgs + result: BatchPayload + } + updateMany: { + args: Prisma.AiUsageMetricUpdateManyArgs + result: BatchPayload + } + updateManyAndReturn: { + args: Prisma.AiUsageMetricUpdateManyAndReturnArgs + result: runtime.Types.Utils.PayloadToResult[] + } + upsert: { + args: Prisma.AiUsageMetricUpsertArgs + result: runtime.Types.Utils.PayloadToResult + } + aggregate: { + args: Prisma.AiUsageMetricAggregateArgs + result: runtime.Types.Utils.Optional + } + groupBy: { + args: Prisma.AiUsageMetricGroupByArgs + result: runtime.Types.Utils.Optional[] + } + count: { + args: Prisma.AiUsageMetricCountArgs + result: runtime.Types.Utils.Optional | number + } + } + } } } & { other: { @@ -880,6 +1105,43 @@ export const WorldIdVerificationScalarFieldEnum = { export type WorldIdVerificationScalarFieldEnum = (typeof WorldIdVerificationScalarFieldEnum)[keyof typeof WorldIdVerificationScalarFieldEnum] +export const ConversationScalarFieldEnum = { + id: 'id', + title: 'title', + createdAt: 'createdAt', + updatedAt: 'updatedAt', + userId: 'userId' +} as const + +export type ConversationScalarFieldEnum = (typeof ConversationScalarFieldEnum)[keyof typeof ConversationScalarFieldEnum] + + +export const MessageScalarFieldEnum = { + id: 'id', + role: 'role', + content: 'content', + conversationId: 'conversationId', + createdAt: 'createdAt' +} as const + +export type MessageScalarFieldEnum = (typeof MessageScalarFieldEnum)[keyof typeof MessageScalarFieldEnum] + + +export const AiUsageMetricScalarFieldEnum = { + id: 'id', + userId: 'userId', + provider: 'provider', + model: 'model', + promptTokens: 'promptTokens', + completionTokens: 'completionTokens', + totalTokens: 'totalTokens', + latencyMs: 'latencyMs', + createdAt: 'createdAt' +} as const + +export type AiUsageMetricScalarFieldEnum = (typeof AiUsageMetricScalarFieldEnum)[keyof typeof AiUsageMetricScalarFieldEnum] + + export const SortOrder = { asc: 'asc', desc: 'desc' @@ -1082,6 +1344,9 @@ export type GlobalOmitConfig = { sybilScore?: Prisma.SybilScoreOmit sybilExplanation?: Prisma.SybilExplanationOmit worldIdVerification?: Prisma.WorldIdVerificationOmit + conversation?: Prisma.ConversationOmit + message?: Prisma.MessageOmit + aiUsageMetric?: Prisma.AiUsageMetricOmit } /* Types for Logging */ diff --git a/src/generated/client/internal/prismaNamespaceBrowser.ts b/src/generated/client/internal/prismaNamespaceBrowser.ts index a78f1a7..cea487e 100644 --- a/src/generated/client/internal/prismaNamespaceBrowser.ts +++ b/src/generated/client/internal/prismaNamespaceBrowser.ts @@ -55,7 +55,10 @@ export const ModelName = { Wallet: 'Wallet', SybilScore: 'SybilScore', SybilExplanation: 'SybilExplanation', - WorldIdVerification: 'WorldIdVerification' + WorldIdVerification: 'WorldIdVerification', + Conversation: 'Conversation', + Message: 'Message', + AiUsageMetric: 'AiUsageMetric' } as const export type ModelName = (typeof ModelName)[keyof typeof ModelName] @@ -137,6 +140,43 @@ export const WorldIdVerificationScalarFieldEnum = { export type WorldIdVerificationScalarFieldEnum = (typeof WorldIdVerificationScalarFieldEnum)[keyof typeof WorldIdVerificationScalarFieldEnum] +export const ConversationScalarFieldEnum = { + id: 'id', + title: 'title', + createdAt: 'createdAt', + updatedAt: 'updatedAt', + userId: 'userId' +} as const + +export type ConversationScalarFieldEnum = (typeof ConversationScalarFieldEnum)[keyof typeof ConversationScalarFieldEnum] + + +export const MessageScalarFieldEnum = { + id: 'id', + role: 'role', + content: 'content', + conversationId: 'conversationId', + createdAt: 'createdAt' +} as const + +export type MessageScalarFieldEnum = (typeof MessageScalarFieldEnum)[keyof typeof MessageScalarFieldEnum] + + +export const AiUsageMetricScalarFieldEnum = { + id: 'id', + userId: 'userId', + provider: 'provider', + model: 'model', + promptTokens: 'promptTokens', + completionTokens: 'completionTokens', + totalTokens: 'totalTokens', + latencyMs: 'latencyMs', + createdAt: 'createdAt' +} as const + +export type AiUsageMetricScalarFieldEnum = (typeof AiUsageMetricScalarFieldEnum)[keyof typeof AiUsageMetricScalarFieldEnum] + + export const SortOrder = { asc: 'asc', desc: 'desc' diff --git a/src/generated/client/models.ts b/src/generated/client/models.ts index f76b6b9..b561cd2 100644 --- a/src/generated/client/models.ts +++ b/src/generated/client/models.ts @@ -13,4 +13,7 @@ export type * from './models/Wallet' export type * from './models/SybilScore' export type * from './models/SybilExplanation' export type * from './models/WorldIdVerification' +export type * from './models/Conversation' +export type * from './models/Message' +export type * from './models/AiUsageMetric' export type * from './commonInputTypes' \ No newline at end of file diff --git a/src/generated/client/models/AiUsageMetric.ts b/src/generated/client/models/AiUsageMetric.ts new file mode 100644 index 0000000..40d157e --- /dev/null +++ b/src/generated/client/models/AiUsageMetric.ts @@ -0,0 +1,1316 @@ + +/* !!! This is code generated by Prisma. Do not edit directly. !!! */ +/* eslint-disable */ +// biome-ignore-all lint: generated file +// @ts-nocheck +/* + * This file exports the `AiUsageMetric` model and its related types. + * + * ๐ŸŸข You can import this file directly. + */ +import type * as runtime from "@prisma/client/runtime/client" +import type * as $Enums from "../enums" +import type * as Prisma from "../internal/prismaNamespace" + +/** + * Model AiUsageMetric + * + */ +export type AiUsageMetricModel = runtime.Types.Result.DefaultSelection + +export type AggregateAiUsageMetric = { + _count: AiUsageMetricCountAggregateOutputType | null + _avg: AiUsageMetricAvgAggregateOutputType | null + _sum: AiUsageMetricSumAggregateOutputType | null + _min: AiUsageMetricMinAggregateOutputType | null + _max: AiUsageMetricMaxAggregateOutputType | null +} + +export type AiUsageMetricAvgAggregateOutputType = { + promptTokens: number | null + completionTokens: number | null + totalTokens: number | null + latencyMs: number | null +} + +export type AiUsageMetricSumAggregateOutputType = { + promptTokens: number | null + completionTokens: number | null + totalTokens: number | null + latencyMs: number | null +} + +export type AiUsageMetricMinAggregateOutputType = { + id: string | null + userId: string | null + provider: string | null + model: string | null + promptTokens: number | null + completionTokens: number | null + totalTokens: number | null + latencyMs: number | null + createdAt: Date | null +} + +export type AiUsageMetricMaxAggregateOutputType = { + id: string | null + userId: string | null + provider: string | null + model: string | null + promptTokens: number | null + completionTokens: number | null + totalTokens: number | null + latencyMs: number | null + createdAt: Date | null +} + +export type AiUsageMetricCountAggregateOutputType = { + id: number + userId: number + provider: number + model: number + promptTokens: number + completionTokens: number + totalTokens: number + latencyMs: number + createdAt: number + _all: number +} + + +export type AiUsageMetricAvgAggregateInputType = { + promptTokens?: true + completionTokens?: true + totalTokens?: true + latencyMs?: true +} + +export type AiUsageMetricSumAggregateInputType = { + promptTokens?: true + completionTokens?: true + totalTokens?: true + latencyMs?: true +} + +export type AiUsageMetricMinAggregateInputType = { + id?: true + userId?: true + provider?: true + model?: true + promptTokens?: true + completionTokens?: true + totalTokens?: true + latencyMs?: true + createdAt?: true +} + +export type AiUsageMetricMaxAggregateInputType = { + id?: true + userId?: true + provider?: true + model?: true + promptTokens?: true + completionTokens?: true + totalTokens?: true + latencyMs?: true + createdAt?: true +} + +export type AiUsageMetricCountAggregateInputType = { + id?: true + userId?: true + provider?: true + model?: true + promptTokens?: true + completionTokens?: true + totalTokens?: true + latencyMs?: true + createdAt?: true + _all?: true +} + +export type AiUsageMetricAggregateArgs = { + /** + * Filter which AiUsageMetric to aggregate. + */ + where?: Prisma.AiUsageMetricWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of AiUsageMetrics to fetch. + */ + orderBy?: Prisma.AiUsageMetricOrderByWithRelationInput | Prisma.AiUsageMetricOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the start position + */ + cursor?: Prisma.AiUsageMetricWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `ยฑn` AiUsageMetrics from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` AiUsageMetrics. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Count returned AiUsageMetrics + **/ + _count?: true | AiUsageMetricCountAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to average + **/ + _avg?: AiUsageMetricAvgAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to sum + **/ + _sum?: AiUsageMetricSumAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to find the minimum value + **/ + _min?: AiUsageMetricMinAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to find the maximum value + **/ + _max?: AiUsageMetricMaxAggregateInputType +} + +export type GetAiUsageMetricAggregateType = { + [P in keyof T & keyof AggregateAiUsageMetric]: P extends '_count' | 'count' + ? T[P] extends true + ? number + : Prisma.GetScalarType + : Prisma.GetScalarType +} + + + + +export type AiUsageMetricGroupByArgs = { + where?: Prisma.AiUsageMetricWhereInput + orderBy?: Prisma.AiUsageMetricOrderByWithAggregationInput | Prisma.AiUsageMetricOrderByWithAggregationInput[] + by: Prisma.AiUsageMetricScalarFieldEnum[] | Prisma.AiUsageMetricScalarFieldEnum + having?: Prisma.AiUsageMetricScalarWhereWithAggregatesInput + take?: number + skip?: number + _count?: AiUsageMetricCountAggregateInputType | true + _avg?: AiUsageMetricAvgAggregateInputType + _sum?: AiUsageMetricSumAggregateInputType + _min?: AiUsageMetricMinAggregateInputType + _max?: AiUsageMetricMaxAggregateInputType +} + +export type AiUsageMetricGroupByOutputType = { + id: string + userId: string | null + provider: string + model: string + promptTokens: number + completionTokens: number + totalTokens: number + latencyMs: number + createdAt: Date + _count: AiUsageMetricCountAggregateOutputType | null + _avg: AiUsageMetricAvgAggregateOutputType | null + _sum: AiUsageMetricSumAggregateOutputType | null + _min: AiUsageMetricMinAggregateOutputType | null + _max: AiUsageMetricMaxAggregateOutputType | null +} + +type GetAiUsageMetricGroupByPayload = Prisma.PrismaPromise< + Array< + Prisma.PickEnumerable & + { + [P in ((keyof T) & (keyof AiUsageMetricGroupByOutputType))]: P extends '_count' + ? T[P] extends boolean + ? number + : Prisma.GetScalarType + : Prisma.GetScalarType + } + > + > + + + +export type AiUsageMetricWhereInput = { + AND?: Prisma.AiUsageMetricWhereInput | Prisma.AiUsageMetricWhereInput[] + OR?: Prisma.AiUsageMetricWhereInput[] + NOT?: Prisma.AiUsageMetricWhereInput | Prisma.AiUsageMetricWhereInput[] + id?: Prisma.StringFilter<"AiUsageMetric"> | string + userId?: Prisma.StringNullableFilter<"AiUsageMetric"> | string | null + provider?: Prisma.StringFilter<"AiUsageMetric"> | string + model?: Prisma.StringFilter<"AiUsageMetric"> | string + promptTokens?: Prisma.IntFilter<"AiUsageMetric"> | number + completionTokens?: Prisma.IntFilter<"AiUsageMetric"> | number + totalTokens?: Prisma.IntFilter<"AiUsageMetric"> | number + latencyMs?: Prisma.IntFilter<"AiUsageMetric"> | number + createdAt?: Prisma.DateTimeFilter<"AiUsageMetric"> | Date | string +} + +export type AiUsageMetricOrderByWithRelationInput = { + id?: Prisma.SortOrder + userId?: Prisma.SortOrderInput | Prisma.SortOrder + provider?: Prisma.SortOrder + model?: Prisma.SortOrder + promptTokens?: Prisma.SortOrder + completionTokens?: Prisma.SortOrder + totalTokens?: Prisma.SortOrder + latencyMs?: Prisma.SortOrder + createdAt?: Prisma.SortOrder +} + +export type AiUsageMetricWhereUniqueInput = Prisma.AtLeast<{ + id?: string + AND?: Prisma.AiUsageMetricWhereInput | Prisma.AiUsageMetricWhereInput[] + OR?: Prisma.AiUsageMetricWhereInput[] + NOT?: Prisma.AiUsageMetricWhereInput | Prisma.AiUsageMetricWhereInput[] + userId?: Prisma.StringNullableFilter<"AiUsageMetric"> | string | null + provider?: Prisma.StringFilter<"AiUsageMetric"> | string + model?: Prisma.StringFilter<"AiUsageMetric"> | string + promptTokens?: Prisma.IntFilter<"AiUsageMetric"> | number + completionTokens?: Prisma.IntFilter<"AiUsageMetric"> | number + totalTokens?: Prisma.IntFilter<"AiUsageMetric"> | number + latencyMs?: Prisma.IntFilter<"AiUsageMetric"> | number + createdAt?: Prisma.DateTimeFilter<"AiUsageMetric"> | Date | string +}, "id"> + +export type AiUsageMetricOrderByWithAggregationInput = { + id?: Prisma.SortOrder + userId?: Prisma.SortOrderInput | Prisma.SortOrder + provider?: Prisma.SortOrder + model?: Prisma.SortOrder + promptTokens?: Prisma.SortOrder + completionTokens?: Prisma.SortOrder + totalTokens?: Prisma.SortOrder + latencyMs?: Prisma.SortOrder + createdAt?: Prisma.SortOrder + _count?: Prisma.AiUsageMetricCountOrderByAggregateInput + _avg?: Prisma.AiUsageMetricAvgOrderByAggregateInput + _max?: Prisma.AiUsageMetricMaxOrderByAggregateInput + _min?: Prisma.AiUsageMetricMinOrderByAggregateInput + _sum?: Prisma.AiUsageMetricSumOrderByAggregateInput +} + +export type AiUsageMetricScalarWhereWithAggregatesInput = { + AND?: Prisma.AiUsageMetricScalarWhereWithAggregatesInput | Prisma.AiUsageMetricScalarWhereWithAggregatesInput[] + OR?: Prisma.AiUsageMetricScalarWhereWithAggregatesInput[] + NOT?: Prisma.AiUsageMetricScalarWhereWithAggregatesInput | Prisma.AiUsageMetricScalarWhereWithAggregatesInput[] + id?: Prisma.StringWithAggregatesFilter<"AiUsageMetric"> | string + userId?: Prisma.StringNullableWithAggregatesFilter<"AiUsageMetric"> | string | null + provider?: Prisma.StringWithAggregatesFilter<"AiUsageMetric"> | string + model?: Prisma.StringWithAggregatesFilter<"AiUsageMetric"> | string + promptTokens?: Prisma.IntWithAggregatesFilter<"AiUsageMetric"> | number + completionTokens?: Prisma.IntWithAggregatesFilter<"AiUsageMetric"> | number + totalTokens?: Prisma.IntWithAggregatesFilter<"AiUsageMetric"> | number + latencyMs?: Prisma.IntWithAggregatesFilter<"AiUsageMetric"> | number + createdAt?: Prisma.DateTimeWithAggregatesFilter<"AiUsageMetric"> | Date | string +} + +export type AiUsageMetricCreateInput = { + id?: string + userId?: string | null + provider: string + model: string + promptTokens?: number + completionTokens?: number + totalTokens?: number + latencyMs?: number + createdAt?: Date | string +} + +export type AiUsageMetricUncheckedCreateInput = { + id?: string + userId?: string | null + provider: string + model: string + promptTokens?: number + completionTokens?: number + totalTokens?: number + latencyMs?: number + createdAt?: Date | string +} + +export type AiUsageMetricUpdateInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + userId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + provider?: Prisma.StringFieldUpdateOperationsInput | string + model?: Prisma.StringFieldUpdateOperationsInput | string + promptTokens?: Prisma.IntFieldUpdateOperationsInput | number + completionTokens?: Prisma.IntFieldUpdateOperationsInput | number + totalTokens?: Prisma.IntFieldUpdateOperationsInput | number + latencyMs?: Prisma.IntFieldUpdateOperationsInput | number + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string +} + +export type AiUsageMetricUncheckedUpdateInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + userId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + provider?: Prisma.StringFieldUpdateOperationsInput | string + model?: Prisma.StringFieldUpdateOperationsInput | string + promptTokens?: Prisma.IntFieldUpdateOperationsInput | number + completionTokens?: Prisma.IntFieldUpdateOperationsInput | number + totalTokens?: Prisma.IntFieldUpdateOperationsInput | number + latencyMs?: Prisma.IntFieldUpdateOperationsInput | number + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string +} + +export type AiUsageMetricCreateManyInput = { + id?: string + userId?: string | null + provider: string + model: string + promptTokens?: number + completionTokens?: number + totalTokens?: number + latencyMs?: number + createdAt?: Date | string +} + +export type AiUsageMetricUpdateManyMutationInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + userId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + provider?: Prisma.StringFieldUpdateOperationsInput | string + model?: Prisma.StringFieldUpdateOperationsInput | string + promptTokens?: Prisma.IntFieldUpdateOperationsInput | number + completionTokens?: Prisma.IntFieldUpdateOperationsInput | number + totalTokens?: Prisma.IntFieldUpdateOperationsInput | number + latencyMs?: Prisma.IntFieldUpdateOperationsInput | number + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string +} + +export type AiUsageMetricUncheckedUpdateManyInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + userId?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + provider?: Prisma.StringFieldUpdateOperationsInput | string + model?: Prisma.StringFieldUpdateOperationsInput | string + promptTokens?: Prisma.IntFieldUpdateOperationsInput | number + completionTokens?: Prisma.IntFieldUpdateOperationsInput | number + totalTokens?: Prisma.IntFieldUpdateOperationsInput | number + latencyMs?: Prisma.IntFieldUpdateOperationsInput | number + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string +} + +export type AiUsageMetricCountOrderByAggregateInput = { + id?: Prisma.SortOrder + userId?: Prisma.SortOrder + provider?: Prisma.SortOrder + model?: Prisma.SortOrder + promptTokens?: Prisma.SortOrder + completionTokens?: Prisma.SortOrder + totalTokens?: Prisma.SortOrder + latencyMs?: Prisma.SortOrder + createdAt?: Prisma.SortOrder +} + +export type AiUsageMetricAvgOrderByAggregateInput = { + promptTokens?: Prisma.SortOrder + completionTokens?: Prisma.SortOrder + totalTokens?: Prisma.SortOrder + latencyMs?: Prisma.SortOrder +} + +export type AiUsageMetricMaxOrderByAggregateInput = { + id?: Prisma.SortOrder + userId?: Prisma.SortOrder + provider?: Prisma.SortOrder + model?: Prisma.SortOrder + promptTokens?: Prisma.SortOrder + completionTokens?: Prisma.SortOrder + totalTokens?: Prisma.SortOrder + latencyMs?: Prisma.SortOrder + createdAt?: Prisma.SortOrder +} + +export type AiUsageMetricMinOrderByAggregateInput = { + id?: Prisma.SortOrder + userId?: Prisma.SortOrder + provider?: Prisma.SortOrder + model?: Prisma.SortOrder + promptTokens?: Prisma.SortOrder + completionTokens?: Prisma.SortOrder + totalTokens?: Prisma.SortOrder + latencyMs?: Prisma.SortOrder + createdAt?: Prisma.SortOrder +} + +export type AiUsageMetricSumOrderByAggregateInput = { + promptTokens?: Prisma.SortOrder + completionTokens?: Prisma.SortOrder + totalTokens?: Prisma.SortOrder + latencyMs?: Prisma.SortOrder +} + + + +export type AiUsageMetricSelect = runtime.Types.Extensions.GetSelect<{ + id?: boolean + userId?: boolean + provider?: boolean + model?: boolean + promptTokens?: boolean + completionTokens?: boolean + totalTokens?: boolean + latencyMs?: boolean + createdAt?: boolean +}, ExtArgs["result"]["aiUsageMetric"]> + +export type AiUsageMetricSelectCreateManyAndReturn = runtime.Types.Extensions.GetSelect<{ + id?: boolean + userId?: boolean + provider?: boolean + model?: boolean + promptTokens?: boolean + completionTokens?: boolean + totalTokens?: boolean + latencyMs?: boolean + createdAt?: boolean +}, ExtArgs["result"]["aiUsageMetric"]> + +export type AiUsageMetricSelectUpdateManyAndReturn = runtime.Types.Extensions.GetSelect<{ + id?: boolean + userId?: boolean + provider?: boolean + model?: boolean + promptTokens?: boolean + completionTokens?: boolean + totalTokens?: boolean + latencyMs?: boolean + createdAt?: boolean +}, ExtArgs["result"]["aiUsageMetric"]> + +export type AiUsageMetricSelectScalar = { + id?: boolean + userId?: boolean + provider?: boolean + model?: boolean + promptTokens?: boolean + completionTokens?: boolean + totalTokens?: boolean + latencyMs?: boolean + createdAt?: boolean +} + +export type AiUsageMetricOmit = runtime.Types.Extensions.GetOmit<"id" | "userId" | "provider" | "model" | "promptTokens" | "completionTokens" | "totalTokens" | "latencyMs" | "createdAt", ExtArgs["result"]["aiUsageMetric"]> + +export type $AiUsageMetricPayload = { + name: "AiUsageMetric" + objects: {} + scalars: runtime.Types.Extensions.GetPayloadResult<{ + id: string + userId: string | null + provider: string + model: string + promptTokens: number + completionTokens: number + totalTokens: number + latencyMs: number + createdAt: Date + }, ExtArgs["result"]["aiUsageMetric"]> + composites: {} +} + +export type AiUsageMetricGetPayload = runtime.Types.Result.GetResult + +export type AiUsageMetricCountArgs = + Omit & { + select?: AiUsageMetricCountAggregateInputType | true + } + +export interface AiUsageMetricDelegate { + [K: symbol]: { types: Prisma.TypeMap['model']['AiUsageMetric'], meta: { name: 'AiUsageMetric' } } + /** + * Find zero or one AiUsageMetric that matches the filter. + * @param {AiUsageMetricFindUniqueArgs} args - Arguments to find a AiUsageMetric + * @example + * // Get one AiUsageMetric + * const aiUsageMetric = await prisma.aiUsageMetric.findUnique({ + * where: { + * // ... provide filter here + * } + * }) + */ + findUnique(args: Prisma.SelectSubset>): Prisma.Prisma__AiUsageMetricClient, T, "findUnique", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + + /** + * Find one AiUsageMetric that matches the filter or throw an error with `error.code='P2025'` + * if no matches were found. + * @param {AiUsageMetricFindUniqueOrThrowArgs} args - Arguments to find a AiUsageMetric + * @example + * // Get one AiUsageMetric + * const aiUsageMetric = await prisma.aiUsageMetric.findUniqueOrThrow({ + * where: { + * // ... provide filter here + * } + * }) + */ + findUniqueOrThrow(args: Prisma.SelectSubset>): Prisma.Prisma__AiUsageMetricClient, T, "findUniqueOrThrow", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Find the first AiUsageMetric that matches the filter. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {AiUsageMetricFindFirstArgs} args - Arguments to find a AiUsageMetric + * @example + * // Get one AiUsageMetric + * const aiUsageMetric = await prisma.aiUsageMetric.findFirst({ + * where: { + * // ... provide filter here + * } + * }) + */ + findFirst(args?: Prisma.SelectSubset>): Prisma.Prisma__AiUsageMetricClient, T, "findFirst", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + + /** + * Find the first AiUsageMetric that matches the filter or + * throw `PrismaKnownClientError` with `P2025` code if no matches were found. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {AiUsageMetricFindFirstOrThrowArgs} args - Arguments to find a AiUsageMetric + * @example + * // Get one AiUsageMetric + * const aiUsageMetric = await prisma.aiUsageMetric.findFirstOrThrow({ + * where: { + * // ... provide filter here + * } + * }) + */ + findFirstOrThrow(args?: Prisma.SelectSubset>): Prisma.Prisma__AiUsageMetricClient, T, "findFirstOrThrow", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Find zero or more AiUsageMetrics that matches the filter. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {AiUsageMetricFindManyArgs} args - Arguments to filter and select certain fields only. + * @example + * // Get all AiUsageMetrics + * const aiUsageMetrics = await prisma.aiUsageMetric.findMany() + * + * // Get first 10 AiUsageMetrics + * const aiUsageMetrics = await prisma.aiUsageMetric.findMany({ take: 10 }) + * + * // Only select the `id` + * const aiUsageMetricWithIdOnly = await prisma.aiUsageMetric.findMany({ select: { id: true } }) + * + */ + findMany(args?: Prisma.SelectSubset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions>> + + /** + * Create a AiUsageMetric. + * @param {AiUsageMetricCreateArgs} args - Arguments to create a AiUsageMetric. + * @example + * // Create one AiUsageMetric + * const AiUsageMetric = await prisma.aiUsageMetric.create({ + * data: { + * // ... data to create a AiUsageMetric + * } + * }) + * + */ + create(args: Prisma.SelectSubset>): Prisma.Prisma__AiUsageMetricClient, T, "create", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Create many AiUsageMetrics. + * @param {AiUsageMetricCreateManyArgs} args - Arguments to create many AiUsageMetrics. + * @example + * // Create many AiUsageMetrics + * const aiUsageMetric = await prisma.aiUsageMetric.createMany({ + * data: [ + * // ... provide data here + * ] + * }) + * + */ + createMany(args?: Prisma.SelectSubset>): Prisma.PrismaPromise + + /** + * Create many AiUsageMetrics and returns the data saved in the database. + * @param {AiUsageMetricCreateManyAndReturnArgs} args - Arguments to create many AiUsageMetrics. + * @example + * // Create many AiUsageMetrics + * const aiUsageMetric = await prisma.aiUsageMetric.createManyAndReturn({ + * data: [ + * // ... provide data here + * ] + * }) + * + * // Create many AiUsageMetrics and only return the `id` + * const aiUsageMetricWithIdOnly = await prisma.aiUsageMetric.createManyAndReturn({ + * select: { id: true }, + * data: [ + * // ... provide data here + * ] + * }) + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * + */ + createManyAndReturn(args?: Prisma.SelectSubset>): Prisma.PrismaPromise, T, "createManyAndReturn", GlobalOmitOptions>> + + /** + * Delete a AiUsageMetric. + * @param {AiUsageMetricDeleteArgs} args - Arguments to delete one AiUsageMetric. + * @example + * // Delete one AiUsageMetric + * const AiUsageMetric = await prisma.aiUsageMetric.delete({ + * where: { + * // ... filter to delete one AiUsageMetric + * } + * }) + * + */ + delete(args: Prisma.SelectSubset>): Prisma.Prisma__AiUsageMetricClient, T, "delete", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Update one AiUsageMetric. + * @param {AiUsageMetricUpdateArgs} args - Arguments to update one AiUsageMetric. + * @example + * // Update one AiUsageMetric + * const aiUsageMetric = await prisma.aiUsageMetric.update({ + * where: { + * // ... provide filter here + * }, + * data: { + * // ... provide data here + * } + * }) + * + */ + update(args: Prisma.SelectSubset>): Prisma.Prisma__AiUsageMetricClient, T, "update", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Delete zero or more AiUsageMetrics. + * @param {AiUsageMetricDeleteManyArgs} args - Arguments to filter AiUsageMetrics to delete. + * @example + * // Delete a few AiUsageMetrics + * const { count } = await prisma.aiUsageMetric.deleteMany({ + * where: { + * // ... provide filter here + * } + * }) + * + */ + deleteMany(args?: Prisma.SelectSubset>): Prisma.PrismaPromise + + /** + * Update zero or more AiUsageMetrics. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {AiUsageMetricUpdateManyArgs} args - Arguments to update one or more rows. + * @example + * // Update many AiUsageMetrics + * const aiUsageMetric = await prisma.aiUsageMetric.updateMany({ + * where: { + * // ... provide filter here + * }, + * data: { + * // ... provide data here + * } + * }) + * + */ + updateMany(args: Prisma.SelectSubset>): Prisma.PrismaPromise + + /** + * Update zero or more AiUsageMetrics and returns the data updated in the database. + * @param {AiUsageMetricUpdateManyAndReturnArgs} args - Arguments to update many AiUsageMetrics. + * @example + * // Update many AiUsageMetrics + * const aiUsageMetric = await prisma.aiUsageMetric.updateManyAndReturn({ + * where: { + * // ... provide filter here + * }, + * data: [ + * // ... provide data here + * ] + * }) + * + * // Update zero or more AiUsageMetrics and only return the `id` + * const aiUsageMetricWithIdOnly = await prisma.aiUsageMetric.updateManyAndReturn({ + * select: { id: true }, + * where: { + * // ... provide filter here + * }, + * data: [ + * // ... provide data here + * ] + * }) + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * + */ + updateManyAndReturn(args: Prisma.SelectSubset>): Prisma.PrismaPromise, T, "updateManyAndReturn", GlobalOmitOptions>> + + /** + * Create or update one AiUsageMetric. + * @param {AiUsageMetricUpsertArgs} args - Arguments to update or create a AiUsageMetric. + * @example + * // Update or create a AiUsageMetric + * const aiUsageMetric = await prisma.aiUsageMetric.upsert({ + * create: { + * // ... data to create a AiUsageMetric + * }, + * update: { + * // ... in case it already exists, update + * }, + * where: { + * // ... the filter for the AiUsageMetric we want to update + * } + * }) + */ + upsert(args: Prisma.SelectSubset>): Prisma.Prisma__AiUsageMetricClient, T, "upsert", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + + /** + * Count the number of AiUsageMetrics. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {AiUsageMetricCountArgs} args - Arguments to filter AiUsageMetrics to count. + * @example + * // Count the number of AiUsageMetrics + * const count = await prisma.aiUsageMetric.count({ + * where: { + * // ... the filter for the AiUsageMetrics we want to count + * } + * }) + **/ + count( + args?: Prisma.Subset, + ): Prisma.PrismaPromise< + T extends runtime.Types.Utils.Record<'select', any> + ? T['select'] extends true + ? number + : Prisma.GetScalarType + : number + > + + /** + * Allows you to perform aggregations operations on a AiUsageMetric. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {AiUsageMetricAggregateArgs} args - Select which aggregations you would like to apply and on what fields. + * @example + * // Ordered by age ascending + * // Where email contains prisma.io + * // Limited to the 10 users + * const aggregations = await prisma.user.aggregate({ + * _avg: { + * age: true, + * }, + * where: { + * email: { + * contains: "prisma.io", + * }, + * }, + * orderBy: { + * age: "asc", + * }, + * take: 10, + * }) + **/ + aggregate(args: Prisma.Subset): Prisma.PrismaPromise> + + /** + * Group by AiUsageMetric. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {AiUsageMetricGroupByArgs} args - Group by arguments. + * @example + * // Group by city, order by createdAt, get count + * const result = await prisma.user.groupBy({ + * by: ['city', 'createdAt'], + * orderBy: { + * createdAt: true + * }, + * _count: { + * _all: true + * }, + * }) + * + **/ + groupBy< + T extends AiUsageMetricGroupByArgs, + HasSelectOrTake extends Prisma.Or< + Prisma.Extends<'skip', Prisma.Keys>, + Prisma.Extends<'take', Prisma.Keys> + >, + OrderByArg extends Prisma.True extends HasSelectOrTake + ? { orderBy: AiUsageMetricGroupByArgs['orderBy'] } + : { orderBy?: AiUsageMetricGroupByArgs['orderBy'] }, + OrderFields extends Prisma.ExcludeUnderscoreKeys>>, + ByFields extends Prisma.MaybeTupleToUnion, + ByValid extends Prisma.Has, + HavingFields extends Prisma.GetHavingFields, + HavingValid extends Prisma.Has, + ByEmpty extends T['by'] extends never[] ? Prisma.True : Prisma.False, + InputErrors extends ByEmpty extends Prisma.True + ? `Error: "by" must not be empty.` + : HavingValid extends Prisma.False + ? { + [P in HavingFields]: P extends ByFields + ? never + : P extends string + ? `Error: Field "${P}" used in "having" needs to be provided in "by".` + : [ + Error, + 'Field ', + P, + ` in "having" needs to be provided in "by"`, + ] + }[HavingFields] + : 'take' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "take", you also need to provide "orderBy"' + : 'skip' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "skip", you also need to provide "orderBy"' + : ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + >(args: Prisma.SubsetIntersection & InputErrors): {} extends InputErrors ? GetAiUsageMetricGroupByPayload : Prisma.PrismaPromise +/** + * Fields of the AiUsageMetric model + */ +readonly fields: AiUsageMetricFieldRefs; +} + +/** + * The delegate class that acts as a "Promise-like" for AiUsageMetric. + * Why is this prefixed with `Prisma__`? + * Because we want to prevent naming conflicts as mentioned in + * https://github.com/prisma/prisma-client-js/issues/707 + */ +export interface Prisma__AiUsageMetricClient extends Prisma.PrismaPromise { + readonly [Symbol.toStringTag]: "PrismaPromise" + /** + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): runtime.Types.Utils.JsPromise + /** + * Attaches a callback for only the rejection of the Promise. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of the callback. + */ + catch(onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): runtime.Types.Utils.JsPromise + /** + * Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The + * resolved value cannot be modified from the callback. + * @param onfinally The callback to execute when the Promise is settled (fulfilled or rejected). + * @returns A Promise for the completion of the callback. + */ + finally(onfinally?: (() => void) | undefined | null): runtime.Types.Utils.JsPromise +} + + + + +/** + * Fields of the AiUsageMetric model + */ +export interface AiUsageMetricFieldRefs { + readonly id: Prisma.FieldRef<"AiUsageMetric", 'String'> + readonly userId: Prisma.FieldRef<"AiUsageMetric", 'String'> + readonly provider: Prisma.FieldRef<"AiUsageMetric", 'String'> + readonly model: Prisma.FieldRef<"AiUsageMetric", 'String'> + readonly promptTokens: Prisma.FieldRef<"AiUsageMetric", 'Int'> + readonly completionTokens: Prisma.FieldRef<"AiUsageMetric", 'Int'> + readonly totalTokens: Prisma.FieldRef<"AiUsageMetric", 'Int'> + readonly latencyMs: Prisma.FieldRef<"AiUsageMetric", 'Int'> + readonly createdAt: Prisma.FieldRef<"AiUsageMetric", 'DateTime'> +} + + +// Custom InputTypes +/** + * AiUsageMetric findUnique + */ +export type AiUsageMetricFindUniqueArgs = { + /** + * Select specific fields to fetch from the AiUsageMetric + */ + select?: Prisma.AiUsageMetricSelect | null + /** + * Omit specific fields from the AiUsageMetric + */ + omit?: Prisma.AiUsageMetricOmit | null + /** + * Filter, which AiUsageMetric to fetch. + */ + where: Prisma.AiUsageMetricWhereUniqueInput +} + +/** + * AiUsageMetric findUniqueOrThrow + */ +export type AiUsageMetricFindUniqueOrThrowArgs = { + /** + * Select specific fields to fetch from the AiUsageMetric + */ + select?: Prisma.AiUsageMetricSelect | null + /** + * Omit specific fields from the AiUsageMetric + */ + omit?: Prisma.AiUsageMetricOmit | null + /** + * Filter, which AiUsageMetric to fetch. + */ + where: Prisma.AiUsageMetricWhereUniqueInput +} + +/** + * AiUsageMetric findFirst + */ +export type AiUsageMetricFindFirstArgs = { + /** + * Select specific fields to fetch from the AiUsageMetric + */ + select?: Prisma.AiUsageMetricSelect | null + /** + * Omit specific fields from the AiUsageMetric + */ + omit?: Prisma.AiUsageMetricOmit | null + /** + * Filter, which AiUsageMetric to fetch. + */ + where?: Prisma.AiUsageMetricWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of AiUsageMetrics to fetch. + */ + orderBy?: Prisma.AiUsageMetricOrderByWithRelationInput | Prisma.AiUsageMetricOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for searching for AiUsageMetrics. + */ + cursor?: Prisma.AiUsageMetricWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `ยฑn` AiUsageMetrics from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` AiUsageMetrics. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of AiUsageMetrics. + */ + distinct?: Prisma.AiUsageMetricScalarFieldEnum | Prisma.AiUsageMetricScalarFieldEnum[] +} + +/** + * AiUsageMetric findFirstOrThrow + */ +export type AiUsageMetricFindFirstOrThrowArgs = { + /** + * Select specific fields to fetch from the AiUsageMetric + */ + select?: Prisma.AiUsageMetricSelect | null + /** + * Omit specific fields from the AiUsageMetric + */ + omit?: Prisma.AiUsageMetricOmit | null + /** + * Filter, which AiUsageMetric to fetch. + */ + where?: Prisma.AiUsageMetricWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of AiUsageMetrics to fetch. + */ + orderBy?: Prisma.AiUsageMetricOrderByWithRelationInput | Prisma.AiUsageMetricOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for searching for AiUsageMetrics. + */ + cursor?: Prisma.AiUsageMetricWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `ยฑn` AiUsageMetrics from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` AiUsageMetrics. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of AiUsageMetrics. + */ + distinct?: Prisma.AiUsageMetricScalarFieldEnum | Prisma.AiUsageMetricScalarFieldEnum[] +} + +/** + * AiUsageMetric findMany + */ +export type AiUsageMetricFindManyArgs = { + /** + * Select specific fields to fetch from the AiUsageMetric + */ + select?: Prisma.AiUsageMetricSelect | null + /** + * Omit specific fields from the AiUsageMetric + */ + omit?: Prisma.AiUsageMetricOmit | null + /** + * Filter, which AiUsageMetrics to fetch. + */ + where?: Prisma.AiUsageMetricWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of AiUsageMetrics to fetch. + */ + orderBy?: Prisma.AiUsageMetricOrderByWithRelationInput | Prisma.AiUsageMetricOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for listing AiUsageMetrics. + */ + cursor?: Prisma.AiUsageMetricWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `ยฑn` AiUsageMetrics from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` AiUsageMetrics. + */ + skip?: number + distinct?: Prisma.AiUsageMetricScalarFieldEnum | Prisma.AiUsageMetricScalarFieldEnum[] +} + +/** + * AiUsageMetric create + */ +export type AiUsageMetricCreateArgs = { + /** + * Select specific fields to fetch from the AiUsageMetric + */ + select?: Prisma.AiUsageMetricSelect | null + /** + * Omit specific fields from the AiUsageMetric + */ + omit?: Prisma.AiUsageMetricOmit | null + /** + * The data needed to create a AiUsageMetric. + */ + data: Prisma.XOR +} + +/** + * AiUsageMetric createMany + */ +export type AiUsageMetricCreateManyArgs = { + /** + * The data used to create many AiUsageMetrics. + */ + data: Prisma.AiUsageMetricCreateManyInput | Prisma.AiUsageMetricCreateManyInput[] +} + +/** + * AiUsageMetric createManyAndReturn + */ +export type AiUsageMetricCreateManyAndReturnArgs = { + /** + * Select specific fields to fetch from the AiUsageMetric + */ + select?: Prisma.AiUsageMetricSelectCreateManyAndReturn | null + /** + * Omit specific fields from the AiUsageMetric + */ + omit?: Prisma.AiUsageMetricOmit | null + /** + * The data used to create many AiUsageMetrics. + */ + data: Prisma.AiUsageMetricCreateManyInput | Prisma.AiUsageMetricCreateManyInput[] +} + +/** + * AiUsageMetric update + */ +export type AiUsageMetricUpdateArgs = { + /** + * Select specific fields to fetch from the AiUsageMetric + */ + select?: Prisma.AiUsageMetricSelect | null + /** + * Omit specific fields from the AiUsageMetric + */ + omit?: Prisma.AiUsageMetricOmit | null + /** + * The data needed to update a AiUsageMetric. + */ + data: Prisma.XOR + /** + * Choose, which AiUsageMetric to update. + */ + where: Prisma.AiUsageMetricWhereUniqueInput +} + +/** + * AiUsageMetric updateMany + */ +export type AiUsageMetricUpdateManyArgs = { + /** + * The data used to update AiUsageMetrics. + */ + data: Prisma.XOR + /** + * Filter which AiUsageMetrics to update + */ + where?: Prisma.AiUsageMetricWhereInput + /** + * Limit how many AiUsageMetrics to update. + */ + limit?: number +} + +/** + * AiUsageMetric updateManyAndReturn + */ +export type AiUsageMetricUpdateManyAndReturnArgs = { + /** + * Select specific fields to fetch from the AiUsageMetric + */ + select?: Prisma.AiUsageMetricSelectUpdateManyAndReturn | null + /** + * Omit specific fields from the AiUsageMetric + */ + omit?: Prisma.AiUsageMetricOmit | null + /** + * The data used to update AiUsageMetrics. + */ + data: Prisma.XOR + /** + * Filter which AiUsageMetrics to update + */ + where?: Prisma.AiUsageMetricWhereInput + /** + * Limit how many AiUsageMetrics to update. + */ + limit?: number +} + +/** + * AiUsageMetric upsert + */ +export type AiUsageMetricUpsertArgs = { + /** + * Select specific fields to fetch from the AiUsageMetric + */ + select?: Prisma.AiUsageMetricSelect | null + /** + * Omit specific fields from the AiUsageMetric + */ + omit?: Prisma.AiUsageMetricOmit | null + /** + * The filter to search for the AiUsageMetric to update in case it exists. + */ + where: Prisma.AiUsageMetricWhereUniqueInput + /** + * In case the AiUsageMetric found by the `where` argument doesn't exist, create a new AiUsageMetric with this data. + */ + create: Prisma.XOR + /** + * In case the AiUsageMetric was found with the provided `where` argument, update it with this data. + */ + update: Prisma.XOR +} + +/** + * AiUsageMetric delete + */ +export type AiUsageMetricDeleteArgs = { + /** + * Select specific fields to fetch from the AiUsageMetric + */ + select?: Prisma.AiUsageMetricSelect | null + /** + * Omit specific fields from the AiUsageMetric + */ + omit?: Prisma.AiUsageMetricOmit | null + /** + * Filter which AiUsageMetric to delete. + */ + where: Prisma.AiUsageMetricWhereUniqueInput +} + +/** + * AiUsageMetric deleteMany + */ +export type AiUsageMetricDeleteManyArgs = { + /** + * Filter which AiUsageMetrics to delete + */ + where?: Prisma.AiUsageMetricWhereInput + /** + * Limit how many AiUsageMetrics to delete. + */ + limit?: number +} + +/** + * AiUsageMetric without action + */ +export type AiUsageMetricDefaultArgs = { + /** + * Select specific fields to fetch from the AiUsageMetric + */ + select?: Prisma.AiUsageMetricSelect | null + /** + * Omit specific fields from the AiUsageMetric + */ + omit?: Prisma.AiUsageMetricOmit | null +} diff --git a/src/generated/client/models/Conversation.ts b/src/generated/client/models/Conversation.ts new file mode 100644 index 0000000..7d2a283 --- /dev/null +++ b/src/generated/client/models/Conversation.ts @@ -0,0 +1,1474 @@ + +/* !!! This is code generated by Prisma. Do not edit directly. !!! */ +/* eslint-disable */ +// biome-ignore-all lint: generated file +// @ts-nocheck +/* + * This file exports the `Conversation` model and its related types. + * + * ๐ŸŸข You can import this file directly. + */ +import type * as runtime from "@prisma/client/runtime/client" +import type * as $Enums from "../enums" +import type * as Prisma from "../internal/prismaNamespace" + +/** + * Model Conversation + * + */ +export type ConversationModel = runtime.Types.Result.DefaultSelection + +export type AggregateConversation = { + _count: ConversationCountAggregateOutputType | null + _min: ConversationMinAggregateOutputType | null + _max: ConversationMaxAggregateOutputType | null +} + +export type ConversationMinAggregateOutputType = { + id: string | null + title: string | null + createdAt: Date | null + updatedAt: Date | null + userId: string | null +} + +export type ConversationMaxAggregateOutputType = { + id: string | null + title: string | null + createdAt: Date | null + updatedAt: Date | null + userId: string | null +} + +export type ConversationCountAggregateOutputType = { + id: number + title: number + createdAt: number + updatedAt: number + userId: number + _all: number +} + + +export type ConversationMinAggregateInputType = { + id?: true + title?: true + createdAt?: true + updatedAt?: true + userId?: true +} + +export type ConversationMaxAggregateInputType = { + id?: true + title?: true + createdAt?: true + updatedAt?: true + userId?: true +} + +export type ConversationCountAggregateInputType = { + id?: true + title?: true + createdAt?: true + updatedAt?: true + userId?: true + _all?: true +} + +export type ConversationAggregateArgs = { + /** + * Filter which Conversation to aggregate. + */ + where?: Prisma.ConversationWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of Conversations to fetch. + */ + orderBy?: Prisma.ConversationOrderByWithRelationInput | Prisma.ConversationOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the start position + */ + cursor?: Prisma.ConversationWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `ยฑn` Conversations from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` Conversations. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Count returned Conversations + **/ + _count?: true | ConversationCountAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to find the minimum value + **/ + _min?: ConversationMinAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to find the maximum value + **/ + _max?: ConversationMaxAggregateInputType +} + +export type GetConversationAggregateType = { + [P in keyof T & keyof AggregateConversation]: P extends '_count' | 'count' + ? T[P] extends true + ? number + : Prisma.GetScalarType + : Prisma.GetScalarType +} + + + + +export type ConversationGroupByArgs = { + where?: Prisma.ConversationWhereInput + orderBy?: Prisma.ConversationOrderByWithAggregationInput | Prisma.ConversationOrderByWithAggregationInput[] + by: Prisma.ConversationScalarFieldEnum[] | Prisma.ConversationScalarFieldEnum + having?: Prisma.ConversationScalarWhereWithAggregatesInput + take?: number + skip?: number + _count?: ConversationCountAggregateInputType | true + _min?: ConversationMinAggregateInputType + _max?: ConversationMaxAggregateInputType +} + +export type ConversationGroupByOutputType = { + id: string + title: string | null + createdAt: Date + updatedAt: Date + userId: string + _count: ConversationCountAggregateOutputType | null + _min: ConversationMinAggregateOutputType | null + _max: ConversationMaxAggregateOutputType | null +} + +type GetConversationGroupByPayload = Prisma.PrismaPromise< + Array< + Prisma.PickEnumerable & + { + [P in ((keyof T) & (keyof ConversationGroupByOutputType))]: P extends '_count' + ? T[P] extends boolean + ? number + : Prisma.GetScalarType + : Prisma.GetScalarType + } + > + > + + + +export type ConversationWhereInput = { + AND?: Prisma.ConversationWhereInput | Prisma.ConversationWhereInput[] + OR?: Prisma.ConversationWhereInput[] + NOT?: Prisma.ConversationWhereInput | Prisma.ConversationWhereInput[] + id?: Prisma.StringFilter<"Conversation"> | string + title?: Prisma.StringNullableFilter<"Conversation"> | string | null + createdAt?: Prisma.DateTimeFilter<"Conversation"> | Date | string + updatedAt?: Prisma.DateTimeFilter<"Conversation"> | Date | string + userId?: Prisma.StringFilter<"Conversation"> | string + user?: Prisma.XOR + messages?: Prisma.MessageListRelationFilter +} + +export type ConversationOrderByWithRelationInput = { + id?: Prisma.SortOrder + title?: Prisma.SortOrderInput | Prisma.SortOrder + createdAt?: Prisma.SortOrder + updatedAt?: Prisma.SortOrder + userId?: Prisma.SortOrder + user?: Prisma.UserOrderByWithRelationInput + messages?: Prisma.MessageOrderByRelationAggregateInput +} + +export type ConversationWhereUniqueInput = Prisma.AtLeast<{ + id?: string + AND?: Prisma.ConversationWhereInput | Prisma.ConversationWhereInput[] + OR?: Prisma.ConversationWhereInput[] + NOT?: Prisma.ConversationWhereInput | Prisma.ConversationWhereInput[] + title?: Prisma.StringNullableFilter<"Conversation"> | string | null + createdAt?: Prisma.DateTimeFilter<"Conversation"> | Date | string + updatedAt?: Prisma.DateTimeFilter<"Conversation"> | Date | string + userId?: Prisma.StringFilter<"Conversation"> | string + user?: Prisma.XOR + messages?: Prisma.MessageListRelationFilter +}, "id"> + +export type ConversationOrderByWithAggregationInput = { + id?: Prisma.SortOrder + title?: Prisma.SortOrderInput | Prisma.SortOrder + createdAt?: Prisma.SortOrder + updatedAt?: Prisma.SortOrder + userId?: Prisma.SortOrder + _count?: Prisma.ConversationCountOrderByAggregateInput + _max?: Prisma.ConversationMaxOrderByAggregateInput + _min?: Prisma.ConversationMinOrderByAggregateInput +} + +export type ConversationScalarWhereWithAggregatesInput = { + AND?: Prisma.ConversationScalarWhereWithAggregatesInput | Prisma.ConversationScalarWhereWithAggregatesInput[] + OR?: Prisma.ConversationScalarWhereWithAggregatesInput[] + NOT?: Prisma.ConversationScalarWhereWithAggregatesInput | Prisma.ConversationScalarWhereWithAggregatesInput[] + id?: Prisma.StringWithAggregatesFilter<"Conversation"> | string + title?: Prisma.StringNullableWithAggregatesFilter<"Conversation"> | string | null + createdAt?: Prisma.DateTimeWithAggregatesFilter<"Conversation"> | Date | string + updatedAt?: Prisma.DateTimeWithAggregatesFilter<"Conversation"> | Date | string + userId?: Prisma.StringWithAggregatesFilter<"Conversation"> | string +} + +export type ConversationCreateInput = { + id?: string + title?: string | null + createdAt?: Date | string + updatedAt?: Date | string + user: Prisma.UserCreateNestedOneWithoutConversationsInput + messages?: Prisma.MessageCreateNestedManyWithoutConversationInput +} + +export type ConversationUncheckedCreateInput = { + id?: string + title?: string | null + createdAt?: Date | string + updatedAt?: Date | string + userId: string + messages?: Prisma.MessageUncheckedCreateNestedManyWithoutConversationInput +} + +export type ConversationUpdateInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + title?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + user?: Prisma.UserUpdateOneRequiredWithoutConversationsNestedInput + messages?: Prisma.MessageUpdateManyWithoutConversationNestedInput +} + +export type ConversationUncheckedUpdateInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + title?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + userId?: Prisma.StringFieldUpdateOperationsInput | string + messages?: Prisma.MessageUncheckedUpdateManyWithoutConversationNestedInput +} + +export type ConversationCreateManyInput = { + id?: string + title?: string | null + createdAt?: Date | string + updatedAt?: Date | string + userId: string +} + +export type ConversationUpdateManyMutationInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + title?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string +} + +export type ConversationUncheckedUpdateManyInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + title?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + userId?: Prisma.StringFieldUpdateOperationsInput | string +} + +export type ConversationListRelationFilter = { + every?: Prisma.ConversationWhereInput + some?: Prisma.ConversationWhereInput + none?: Prisma.ConversationWhereInput +} + +export type ConversationOrderByRelationAggregateInput = { + _count?: Prisma.SortOrder +} + +export type ConversationCountOrderByAggregateInput = { + id?: Prisma.SortOrder + title?: Prisma.SortOrder + createdAt?: Prisma.SortOrder + updatedAt?: Prisma.SortOrder + userId?: Prisma.SortOrder +} + +export type ConversationMaxOrderByAggregateInput = { + id?: Prisma.SortOrder + title?: Prisma.SortOrder + createdAt?: Prisma.SortOrder + updatedAt?: Prisma.SortOrder + userId?: Prisma.SortOrder +} + +export type ConversationMinOrderByAggregateInput = { + id?: Prisma.SortOrder + title?: Prisma.SortOrder + createdAt?: Prisma.SortOrder + updatedAt?: Prisma.SortOrder + userId?: Prisma.SortOrder +} + +export type ConversationScalarRelationFilter = { + is?: Prisma.ConversationWhereInput + isNot?: Prisma.ConversationWhereInput +} + +export type ConversationCreateNestedManyWithoutUserInput = { + create?: Prisma.XOR | Prisma.ConversationCreateWithoutUserInput[] | Prisma.ConversationUncheckedCreateWithoutUserInput[] + connectOrCreate?: Prisma.ConversationCreateOrConnectWithoutUserInput | Prisma.ConversationCreateOrConnectWithoutUserInput[] + createMany?: Prisma.ConversationCreateManyUserInputEnvelope + connect?: Prisma.ConversationWhereUniqueInput | Prisma.ConversationWhereUniqueInput[] +} + +export type ConversationUncheckedCreateNestedManyWithoutUserInput = { + create?: Prisma.XOR | Prisma.ConversationCreateWithoutUserInput[] | Prisma.ConversationUncheckedCreateWithoutUserInput[] + connectOrCreate?: Prisma.ConversationCreateOrConnectWithoutUserInput | Prisma.ConversationCreateOrConnectWithoutUserInput[] + createMany?: Prisma.ConversationCreateManyUserInputEnvelope + connect?: Prisma.ConversationWhereUniqueInput | Prisma.ConversationWhereUniqueInput[] +} + +export type ConversationUpdateManyWithoutUserNestedInput = { + create?: Prisma.XOR | Prisma.ConversationCreateWithoutUserInput[] | Prisma.ConversationUncheckedCreateWithoutUserInput[] + connectOrCreate?: Prisma.ConversationCreateOrConnectWithoutUserInput | Prisma.ConversationCreateOrConnectWithoutUserInput[] + upsert?: Prisma.ConversationUpsertWithWhereUniqueWithoutUserInput | Prisma.ConversationUpsertWithWhereUniqueWithoutUserInput[] + createMany?: Prisma.ConversationCreateManyUserInputEnvelope + set?: Prisma.ConversationWhereUniqueInput | Prisma.ConversationWhereUniqueInput[] + disconnect?: Prisma.ConversationWhereUniqueInput | Prisma.ConversationWhereUniqueInput[] + delete?: Prisma.ConversationWhereUniqueInput | Prisma.ConversationWhereUniqueInput[] + connect?: Prisma.ConversationWhereUniqueInput | Prisma.ConversationWhereUniqueInput[] + update?: Prisma.ConversationUpdateWithWhereUniqueWithoutUserInput | Prisma.ConversationUpdateWithWhereUniqueWithoutUserInput[] + updateMany?: Prisma.ConversationUpdateManyWithWhereWithoutUserInput | Prisma.ConversationUpdateManyWithWhereWithoutUserInput[] + deleteMany?: Prisma.ConversationScalarWhereInput | Prisma.ConversationScalarWhereInput[] +} + +export type ConversationUncheckedUpdateManyWithoutUserNestedInput = { + create?: Prisma.XOR | Prisma.ConversationCreateWithoutUserInput[] | Prisma.ConversationUncheckedCreateWithoutUserInput[] + connectOrCreate?: Prisma.ConversationCreateOrConnectWithoutUserInput | Prisma.ConversationCreateOrConnectWithoutUserInput[] + upsert?: Prisma.ConversationUpsertWithWhereUniqueWithoutUserInput | Prisma.ConversationUpsertWithWhereUniqueWithoutUserInput[] + createMany?: Prisma.ConversationCreateManyUserInputEnvelope + set?: Prisma.ConversationWhereUniqueInput | Prisma.ConversationWhereUniqueInput[] + disconnect?: Prisma.ConversationWhereUniqueInput | Prisma.ConversationWhereUniqueInput[] + delete?: Prisma.ConversationWhereUniqueInput | Prisma.ConversationWhereUniqueInput[] + connect?: Prisma.ConversationWhereUniqueInput | Prisma.ConversationWhereUniqueInput[] + update?: Prisma.ConversationUpdateWithWhereUniqueWithoutUserInput | Prisma.ConversationUpdateWithWhereUniqueWithoutUserInput[] + updateMany?: Prisma.ConversationUpdateManyWithWhereWithoutUserInput | Prisma.ConversationUpdateManyWithWhereWithoutUserInput[] + deleteMany?: Prisma.ConversationScalarWhereInput | Prisma.ConversationScalarWhereInput[] +} + +export type ConversationCreateNestedOneWithoutMessagesInput = { + create?: Prisma.XOR + connectOrCreate?: Prisma.ConversationCreateOrConnectWithoutMessagesInput + connect?: Prisma.ConversationWhereUniqueInput +} + +export type ConversationUpdateOneRequiredWithoutMessagesNestedInput = { + create?: Prisma.XOR + connectOrCreate?: Prisma.ConversationCreateOrConnectWithoutMessagesInput + upsert?: Prisma.ConversationUpsertWithoutMessagesInput + connect?: Prisma.ConversationWhereUniqueInput + update?: Prisma.XOR, Prisma.ConversationUncheckedUpdateWithoutMessagesInput> +} + +export type ConversationCreateWithoutUserInput = { + id?: string + title?: string | null + createdAt?: Date | string + updatedAt?: Date | string + messages?: Prisma.MessageCreateNestedManyWithoutConversationInput +} + +export type ConversationUncheckedCreateWithoutUserInput = { + id?: string + title?: string | null + createdAt?: Date | string + updatedAt?: Date | string + messages?: Prisma.MessageUncheckedCreateNestedManyWithoutConversationInput +} + +export type ConversationCreateOrConnectWithoutUserInput = { + where: Prisma.ConversationWhereUniqueInput + create: Prisma.XOR +} + +export type ConversationCreateManyUserInputEnvelope = { + data: Prisma.ConversationCreateManyUserInput | Prisma.ConversationCreateManyUserInput[] +} + +export type ConversationUpsertWithWhereUniqueWithoutUserInput = { + where: Prisma.ConversationWhereUniqueInput + update: Prisma.XOR + create: Prisma.XOR +} + +export type ConversationUpdateWithWhereUniqueWithoutUserInput = { + where: Prisma.ConversationWhereUniqueInput + data: Prisma.XOR +} + +export type ConversationUpdateManyWithWhereWithoutUserInput = { + where: Prisma.ConversationScalarWhereInput + data: Prisma.XOR +} + +export type ConversationScalarWhereInput = { + AND?: Prisma.ConversationScalarWhereInput | Prisma.ConversationScalarWhereInput[] + OR?: Prisma.ConversationScalarWhereInput[] + NOT?: Prisma.ConversationScalarWhereInput | Prisma.ConversationScalarWhereInput[] + id?: Prisma.StringFilter<"Conversation"> | string + title?: Prisma.StringNullableFilter<"Conversation"> | string | null + createdAt?: Prisma.DateTimeFilter<"Conversation"> | Date | string + updatedAt?: Prisma.DateTimeFilter<"Conversation"> | Date | string + userId?: Prisma.StringFilter<"Conversation"> | string +} + +export type ConversationCreateWithoutMessagesInput = { + id?: string + title?: string | null + createdAt?: Date | string + updatedAt?: Date | string + user: Prisma.UserCreateNestedOneWithoutConversationsInput +} + +export type ConversationUncheckedCreateWithoutMessagesInput = { + id?: string + title?: string | null + createdAt?: Date | string + updatedAt?: Date | string + userId: string +} + +export type ConversationCreateOrConnectWithoutMessagesInput = { + where: Prisma.ConversationWhereUniqueInput + create: Prisma.XOR +} + +export type ConversationUpsertWithoutMessagesInput = { + update: Prisma.XOR + create: Prisma.XOR + where?: Prisma.ConversationWhereInput +} + +export type ConversationUpdateToOneWithWhereWithoutMessagesInput = { + where?: Prisma.ConversationWhereInput + data: Prisma.XOR +} + +export type ConversationUpdateWithoutMessagesInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + title?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + user?: Prisma.UserUpdateOneRequiredWithoutConversationsNestedInput +} + +export type ConversationUncheckedUpdateWithoutMessagesInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + title?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + userId?: Prisma.StringFieldUpdateOperationsInput | string +} + +export type ConversationCreateManyUserInput = { + id?: string + title?: string | null + createdAt?: Date | string + updatedAt?: Date | string +} + +export type ConversationUpdateWithoutUserInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + title?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + messages?: Prisma.MessageUpdateManyWithoutConversationNestedInput +} + +export type ConversationUncheckedUpdateWithoutUserInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + title?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + messages?: Prisma.MessageUncheckedUpdateManyWithoutConversationNestedInput +} + +export type ConversationUncheckedUpdateManyWithoutUserInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + title?: Prisma.NullableStringFieldUpdateOperationsInput | string | null + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string +} + + +/** + * Count Type ConversationCountOutputType + */ + +export type ConversationCountOutputType = { + messages: number +} + +export type ConversationCountOutputTypeSelect = { + messages?: boolean | ConversationCountOutputTypeCountMessagesArgs +} + +/** + * ConversationCountOutputType without action + */ +export type ConversationCountOutputTypeDefaultArgs = { + /** + * Select specific fields to fetch from the ConversationCountOutputType + */ + select?: Prisma.ConversationCountOutputTypeSelect | null +} + +/** + * ConversationCountOutputType without action + */ +export type ConversationCountOutputTypeCountMessagesArgs = { + where?: Prisma.MessageWhereInput +} + + +export type ConversationSelect = runtime.Types.Extensions.GetSelect<{ + id?: boolean + title?: boolean + createdAt?: boolean + updatedAt?: boolean + userId?: boolean + user?: boolean | Prisma.UserDefaultArgs + messages?: boolean | Prisma.Conversation$messagesArgs + _count?: boolean | Prisma.ConversationCountOutputTypeDefaultArgs +}, ExtArgs["result"]["conversation"]> + +export type ConversationSelectCreateManyAndReturn = runtime.Types.Extensions.GetSelect<{ + id?: boolean + title?: boolean + createdAt?: boolean + updatedAt?: boolean + userId?: boolean + user?: boolean | Prisma.UserDefaultArgs +}, ExtArgs["result"]["conversation"]> + +export type ConversationSelectUpdateManyAndReturn = runtime.Types.Extensions.GetSelect<{ + id?: boolean + title?: boolean + createdAt?: boolean + updatedAt?: boolean + userId?: boolean + user?: boolean | Prisma.UserDefaultArgs +}, ExtArgs["result"]["conversation"]> + +export type ConversationSelectScalar = { + id?: boolean + title?: boolean + createdAt?: boolean + updatedAt?: boolean + userId?: boolean +} + +export type ConversationOmit = runtime.Types.Extensions.GetOmit<"id" | "title" | "createdAt" | "updatedAt" | "userId", ExtArgs["result"]["conversation"]> +export type ConversationInclude = { + user?: boolean | Prisma.UserDefaultArgs + messages?: boolean | Prisma.Conversation$messagesArgs + _count?: boolean | Prisma.ConversationCountOutputTypeDefaultArgs +} +export type ConversationIncludeCreateManyAndReturn = { + user?: boolean | Prisma.UserDefaultArgs +} +export type ConversationIncludeUpdateManyAndReturn = { + user?: boolean | Prisma.UserDefaultArgs +} + +export type $ConversationPayload = { + name: "Conversation" + objects: { + user: Prisma.$UserPayload + messages: Prisma.$MessagePayload[] + } + scalars: runtime.Types.Extensions.GetPayloadResult<{ + id: string + title: string | null + createdAt: Date + updatedAt: Date + userId: string + }, ExtArgs["result"]["conversation"]> + composites: {} +} + +export type ConversationGetPayload = runtime.Types.Result.GetResult + +export type ConversationCountArgs = + Omit & { + select?: ConversationCountAggregateInputType | true + } + +export interface ConversationDelegate { + [K: symbol]: { types: Prisma.TypeMap['model']['Conversation'], meta: { name: 'Conversation' } } + /** + * Find zero or one Conversation that matches the filter. + * @param {ConversationFindUniqueArgs} args - Arguments to find a Conversation + * @example + * // Get one Conversation + * const conversation = await prisma.conversation.findUnique({ + * where: { + * // ... provide filter here + * } + * }) + */ + findUnique(args: Prisma.SelectSubset>): Prisma.Prisma__ConversationClient, T, "findUnique", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + + /** + * Find one Conversation that matches the filter or throw an error with `error.code='P2025'` + * if no matches were found. + * @param {ConversationFindUniqueOrThrowArgs} args - Arguments to find a Conversation + * @example + * // Get one Conversation + * const conversation = await prisma.conversation.findUniqueOrThrow({ + * where: { + * // ... provide filter here + * } + * }) + */ + findUniqueOrThrow(args: Prisma.SelectSubset>): Prisma.Prisma__ConversationClient, T, "findUniqueOrThrow", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Find the first Conversation that matches the filter. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {ConversationFindFirstArgs} args - Arguments to find a Conversation + * @example + * // Get one Conversation + * const conversation = await prisma.conversation.findFirst({ + * where: { + * // ... provide filter here + * } + * }) + */ + findFirst(args?: Prisma.SelectSubset>): Prisma.Prisma__ConversationClient, T, "findFirst", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + + /** + * Find the first Conversation that matches the filter or + * throw `PrismaKnownClientError` with `P2025` code if no matches were found. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {ConversationFindFirstOrThrowArgs} args - Arguments to find a Conversation + * @example + * // Get one Conversation + * const conversation = await prisma.conversation.findFirstOrThrow({ + * where: { + * // ... provide filter here + * } + * }) + */ + findFirstOrThrow(args?: Prisma.SelectSubset>): Prisma.Prisma__ConversationClient, T, "findFirstOrThrow", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Find zero or more Conversations that matches the filter. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {ConversationFindManyArgs} args - Arguments to filter and select certain fields only. + * @example + * // Get all Conversations + * const conversations = await prisma.conversation.findMany() + * + * // Get first 10 Conversations + * const conversations = await prisma.conversation.findMany({ take: 10 }) + * + * // Only select the `id` + * const conversationWithIdOnly = await prisma.conversation.findMany({ select: { id: true } }) + * + */ + findMany(args?: Prisma.SelectSubset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions>> + + /** + * Create a Conversation. + * @param {ConversationCreateArgs} args - Arguments to create a Conversation. + * @example + * // Create one Conversation + * const Conversation = await prisma.conversation.create({ + * data: { + * // ... data to create a Conversation + * } + * }) + * + */ + create(args: Prisma.SelectSubset>): Prisma.Prisma__ConversationClient, T, "create", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Create many Conversations. + * @param {ConversationCreateManyArgs} args - Arguments to create many Conversations. + * @example + * // Create many Conversations + * const conversation = await prisma.conversation.createMany({ + * data: [ + * // ... provide data here + * ] + * }) + * + */ + createMany(args?: Prisma.SelectSubset>): Prisma.PrismaPromise + + /** + * Create many Conversations and returns the data saved in the database. + * @param {ConversationCreateManyAndReturnArgs} args - Arguments to create many Conversations. + * @example + * // Create many Conversations + * const conversation = await prisma.conversation.createManyAndReturn({ + * data: [ + * // ... provide data here + * ] + * }) + * + * // Create many Conversations and only return the `id` + * const conversationWithIdOnly = await prisma.conversation.createManyAndReturn({ + * select: { id: true }, + * data: [ + * // ... provide data here + * ] + * }) + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * + */ + createManyAndReturn(args?: Prisma.SelectSubset>): Prisma.PrismaPromise, T, "createManyAndReturn", GlobalOmitOptions>> + + /** + * Delete a Conversation. + * @param {ConversationDeleteArgs} args - Arguments to delete one Conversation. + * @example + * // Delete one Conversation + * const Conversation = await prisma.conversation.delete({ + * where: { + * // ... filter to delete one Conversation + * } + * }) + * + */ + delete(args: Prisma.SelectSubset>): Prisma.Prisma__ConversationClient, T, "delete", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Update one Conversation. + * @param {ConversationUpdateArgs} args - Arguments to update one Conversation. + * @example + * // Update one Conversation + * const conversation = await prisma.conversation.update({ + * where: { + * // ... provide filter here + * }, + * data: { + * // ... provide data here + * } + * }) + * + */ + update(args: Prisma.SelectSubset>): Prisma.Prisma__ConversationClient, T, "update", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Delete zero or more Conversations. + * @param {ConversationDeleteManyArgs} args - Arguments to filter Conversations to delete. + * @example + * // Delete a few Conversations + * const { count } = await prisma.conversation.deleteMany({ + * where: { + * // ... provide filter here + * } + * }) + * + */ + deleteMany(args?: Prisma.SelectSubset>): Prisma.PrismaPromise + + /** + * Update zero or more Conversations. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {ConversationUpdateManyArgs} args - Arguments to update one or more rows. + * @example + * // Update many Conversations + * const conversation = await prisma.conversation.updateMany({ + * where: { + * // ... provide filter here + * }, + * data: { + * // ... provide data here + * } + * }) + * + */ + updateMany(args: Prisma.SelectSubset>): Prisma.PrismaPromise + + /** + * Update zero or more Conversations and returns the data updated in the database. + * @param {ConversationUpdateManyAndReturnArgs} args - Arguments to update many Conversations. + * @example + * // Update many Conversations + * const conversation = await prisma.conversation.updateManyAndReturn({ + * where: { + * // ... provide filter here + * }, + * data: [ + * // ... provide data here + * ] + * }) + * + * // Update zero or more Conversations and only return the `id` + * const conversationWithIdOnly = await prisma.conversation.updateManyAndReturn({ + * select: { id: true }, + * where: { + * // ... provide filter here + * }, + * data: [ + * // ... provide data here + * ] + * }) + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * + */ + updateManyAndReturn(args: Prisma.SelectSubset>): Prisma.PrismaPromise, T, "updateManyAndReturn", GlobalOmitOptions>> + + /** + * Create or update one Conversation. + * @param {ConversationUpsertArgs} args - Arguments to update or create a Conversation. + * @example + * // Update or create a Conversation + * const conversation = await prisma.conversation.upsert({ + * create: { + * // ... data to create a Conversation + * }, + * update: { + * // ... in case it already exists, update + * }, + * where: { + * // ... the filter for the Conversation we want to update + * } + * }) + */ + upsert(args: Prisma.SelectSubset>): Prisma.Prisma__ConversationClient, T, "upsert", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + + /** + * Count the number of Conversations. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {ConversationCountArgs} args - Arguments to filter Conversations to count. + * @example + * // Count the number of Conversations + * const count = await prisma.conversation.count({ + * where: { + * // ... the filter for the Conversations we want to count + * } + * }) + **/ + count( + args?: Prisma.Subset, + ): Prisma.PrismaPromise< + T extends runtime.Types.Utils.Record<'select', any> + ? T['select'] extends true + ? number + : Prisma.GetScalarType + : number + > + + /** + * Allows you to perform aggregations operations on a Conversation. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {ConversationAggregateArgs} args - Select which aggregations you would like to apply and on what fields. + * @example + * // Ordered by age ascending + * // Where email contains prisma.io + * // Limited to the 10 users + * const aggregations = await prisma.user.aggregate({ + * _avg: { + * age: true, + * }, + * where: { + * email: { + * contains: "prisma.io", + * }, + * }, + * orderBy: { + * age: "asc", + * }, + * take: 10, + * }) + **/ + aggregate(args: Prisma.Subset): Prisma.PrismaPromise> + + /** + * Group by Conversation. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {ConversationGroupByArgs} args - Group by arguments. + * @example + * // Group by city, order by createdAt, get count + * const result = await prisma.user.groupBy({ + * by: ['city', 'createdAt'], + * orderBy: { + * createdAt: true + * }, + * _count: { + * _all: true + * }, + * }) + * + **/ + groupBy< + T extends ConversationGroupByArgs, + HasSelectOrTake extends Prisma.Or< + Prisma.Extends<'skip', Prisma.Keys>, + Prisma.Extends<'take', Prisma.Keys> + >, + OrderByArg extends Prisma.True extends HasSelectOrTake + ? { orderBy: ConversationGroupByArgs['orderBy'] } + : { orderBy?: ConversationGroupByArgs['orderBy'] }, + OrderFields extends Prisma.ExcludeUnderscoreKeys>>, + ByFields extends Prisma.MaybeTupleToUnion, + ByValid extends Prisma.Has, + HavingFields extends Prisma.GetHavingFields, + HavingValid extends Prisma.Has, + ByEmpty extends T['by'] extends never[] ? Prisma.True : Prisma.False, + InputErrors extends ByEmpty extends Prisma.True + ? `Error: "by" must not be empty.` + : HavingValid extends Prisma.False + ? { + [P in HavingFields]: P extends ByFields + ? never + : P extends string + ? `Error: Field "${P}" used in "having" needs to be provided in "by".` + : [ + Error, + 'Field ', + P, + ` in "having" needs to be provided in "by"`, + ] + }[HavingFields] + : 'take' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "take", you also need to provide "orderBy"' + : 'skip' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "skip", you also need to provide "orderBy"' + : ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + >(args: Prisma.SubsetIntersection & InputErrors): {} extends InputErrors ? GetConversationGroupByPayload : Prisma.PrismaPromise +/** + * Fields of the Conversation model + */ +readonly fields: ConversationFieldRefs; +} + +/** + * The delegate class that acts as a "Promise-like" for Conversation. + * Why is this prefixed with `Prisma__`? + * Because we want to prevent naming conflicts as mentioned in + * https://github.com/prisma/prisma-client-js/issues/707 + */ +export interface Prisma__ConversationClient extends Prisma.PrismaPromise { + readonly [Symbol.toStringTag]: "PrismaPromise" + user = {}>(args?: Prisma.Subset>): Prisma.Prisma__UserClient, T, "findUniqueOrThrow", GlobalOmitOptions> | Null, Null, ExtArgs, GlobalOmitOptions> + messages = {}>(args?: Prisma.Subset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions> | Null> + /** + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): runtime.Types.Utils.JsPromise + /** + * Attaches a callback for only the rejection of the Promise. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of the callback. + */ + catch(onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): runtime.Types.Utils.JsPromise + /** + * Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The + * resolved value cannot be modified from the callback. + * @param onfinally The callback to execute when the Promise is settled (fulfilled or rejected). + * @returns A Promise for the completion of the callback. + */ + finally(onfinally?: (() => void) | undefined | null): runtime.Types.Utils.JsPromise +} + + + + +/** + * Fields of the Conversation model + */ +export interface ConversationFieldRefs { + readonly id: Prisma.FieldRef<"Conversation", 'String'> + readonly title: Prisma.FieldRef<"Conversation", 'String'> + readonly createdAt: Prisma.FieldRef<"Conversation", 'DateTime'> + readonly updatedAt: Prisma.FieldRef<"Conversation", 'DateTime'> + readonly userId: Prisma.FieldRef<"Conversation", 'String'> +} + + +// Custom InputTypes +/** + * Conversation findUnique + */ +export type ConversationFindUniqueArgs = { + /** + * Select specific fields to fetch from the Conversation + */ + select?: Prisma.ConversationSelect | null + /** + * Omit specific fields from the Conversation + */ + omit?: Prisma.ConversationOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.ConversationInclude | null + /** + * Filter, which Conversation to fetch. + */ + where: Prisma.ConversationWhereUniqueInput +} + +/** + * Conversation findUniqueOrThrow + */ +export type ConversationFindUniqueOrThrowArgs = { + /** + * Select specific fields to fetch from the Conversation + */ + select?: Prisma.ConversationSelect | null + /** + * Omit specific fields from the Conversation + */ + omit?: Prisma.ConversationOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.ConversationInclude | null + /** + * Filter, which Conversation to fetch. + */ + where: Prisma.ConversationWhereUniqueInput +} + +/** + * Conversation findFirst + */ +export type ConversationFindFirstArgs = { + /** + * Select specific fields to fetch from the Conversation + */ + select?: Prisma.ConversationSelect | null + /** + * Omit specific fields from the Conversation + */ + omit?: Prisma.ConversationOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.ConversationInclude | null + /** + * Filter, which Conversation to fetch. + */ + where?: Prisma.ConversationWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of Conversations to fetch. + */ + orderBy?: Prisma.ConversationOrderByWithRelationInput | Prisma.ConversationOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for searching for Conversations. + */ + cursor?: Prisma.ConversationWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `ยฑn` Conversations from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` Conversations. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of Conversations. + */ + distinct?: Prisma.ConversationScalarFieldEnum | Prisma.ConversationScalarFieldEnum[] +} + +/** + * Conversation findFirstOrThrow + */ +export type ConversationFindFirstOrThrowArgs = { + /** + * Select specific fields to fetch from the Conversation + */ + select?: Prisma.ConversationSelect | null + /** + * Omit specific fields from the Conversation + */ + omit?: Prisma.ConversationOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.ConversationInclude | null + /** + * Filter, which Conversation to fetch. + */ + where?: Prisma.ConversationWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of Conversations to fetch. + */ + orderBy?: Prisma.ConversationOrderByWithRelationInput | Prisma.ConversationOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for searching for Conversations. + */ + cursor?: Prisma.ConversationWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `ยฑn` Conversations from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` Conversations. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of Conversations. + */ + distinct?: Prisma.ConversationScalarFieldEnum | Prisma.ConversationScalarFieldEnum[] +} + +/** + * Conversation findMany + */ +export type ConversationFindManyArgs = { + /** + * Select specific fields to fetch from the Conversation + */ + select?: Prisma.ConversationSelect | null + /** + * Omit specific fields from the Conversation + */ + omit?: Prisma.ConversationOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.ConversationInclude | null + /** + * Filter, which Conversations to fetch. + */ + where?: Prisma.ConversationWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of Conversations to fetch. + */ + orderBy?: Prisma.ConversationOrderByWithRelationInput | Prisma.ConversationOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for listing Conversations. + */ + cursor?: Prisma.ConversationWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `ยฑn` Conversations from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` Conversations. + */ + skip?: number + distinct?: Prisma.ConversationScalarFieldEnum | Prisma.ConversationScalarFieldEnum[] +} + +/** + * Conversation create + */ +export type ConversationCreateArgs = { + /** + * Select specific fields to fetch from the Conversation + */ + select?: Prisma.ConversationSelect | null + /** + * Omit specific fields from the Conversation + */ + omit?: Prisma.ConversationOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.ConversationInclude | null + /** + * The data needed to create a Conversation. + */ + data: Prisma.XOR +} + +/** + * Conversation createMany + */ +export type ConversationCreateManyArgs = { + /** + * The data used to create many Conversations. + */ + data: Prisma.ConversationCreateManyInput | Prisma.ConversationCreateManyInput[] +} + +/** + * Conversation createManyAndReturn + */ +export type ConversationCreateManyAndReturnArgs = { + /** + * Select specific fields to fetch from the Conversation + */ + select?: Prisma.ConversationSelectCreateManyAndReturn | null + /** + * Omit specific fields from the Conversation + */ + omit?: Prisma.ConversationOmit | null + /** + * The data used to create many Conversations. + */ + data: Prisma.ConversationCreateManyInput | Prisma.ConversationCreateManyInput[] + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.ConversationIncludeCreateManyAndReturn | null +} + +/** + * Conversation update + */ +export type ConversationUpdateArgs = { + /** + * Select specific fields to fetch from the Conversation + */ + select?: Prisma.ConversationSelect | null + /** + * Omit specific fields from the Conversation + */ + omit?: Prisma.ConversationOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.ConversationInclude | null + /** + * The data needed to update a Conversation. + */ + data: Prisma.XOR + /** + * Choose, which Conversation to update. + */ + where: Prisma.ConversationWhereUniqueInput +} + +/** + * Conversation updateMany + */ +export type ConversationUpdateManyArgs = { + /** + * The data used to update Conversations. + */ + data: Prisma.XOR + /** + * Filter which Conversations to update + */ + where?: Prisma.ConversationWhereInput + /** + * Limit how many Conversations to update. + */ + limit?: number +} + +/** + * Conversation updateManyAndReturn + */ +export type ConversationUpdateManyAndReturnArgs = { + /** + * Select specific fields to fetch from the Conversation + */ + select?: Prisma.ConversationSelectUpdateManyAndReturn | null + /** + * Omit specific fields from the Conversation + */ + omit?: Prisma.ConversationOmit | null + /** + * The data used to update Conversations. + */ + data: Prisma.XOR + /** + * Filter which Conversations to update + */ + where?: Prisma.ConversationWhereInput + /** + * Limit how many Conversations to update. + */ + limit?: number + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.ConversationIncludeUpdateManyAndReturn | null +} + +/** + * Conversation upsert + */ +export type ConversationUpsertArgs = { + /** + * Select specific fields to fetch from the Conversation + */ + select?: Prisma.ConversationSelect | null + /** + * Omit specific fields from the Conversation + */ + omit?: Prisma.ConversationOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.ConversationInclude | null + /** + * The filter to search for the Conversation to update in case it exists. + */ + where: Prisma.ConversationWhereUniqueInput + /** + * In case the Conversation found by the `where` argument doesn't exist, create a new Conversation with this data. + */ + create: Prisma.XOR + /** + * In case the Conversation was found with the provided `where` argument, update it with this data. + */ + update: Prisma.XOR +} + +/** + * Conversation delete + */ +export type ConversationDeleteArgs = { + /** + * Select specific fields to fetch from the Conversation + */ + select?: Prisma.ConversationSelect | null + /** + * Omit specific fields from the Conversation + */ + omit?: Prisma.ConversationOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.ConversationInclude | null + /** + * Filter which Conversation to delete. + */ + where: Prisma.ConversationWhereUniqueInput +} + +/** + * Conversation deleteMany + */ +export type ConversationDeleteManyArgs = { + /** + * Filter which Conversations to delete + */ + where?: Prisma.ConversationWhereInput + /** + * Limit how many Conversations to delete. + */ + limit?: number +} + +/** + * Conversation.messages + */ +export type Conversation$messagesArgs = { + /** + * Select specific fields to fetch from the Message + */ + select?: Prisma.MessageSelect | null + /** + * Omit specific fields from the Message + */ + omit?: Prisma.MessageOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.MessageInclude | null + where?: Prisma.MessageWhereInput + orderBy?: Prisma.MessageOrderByWithRelationInput | Prisma.MessageOrderByWithRelationInput[] + cursor?: Prisma.MessageWhereUniqueInput + take?: number + skip?: number + distinct?: Prisma.MessageScalarFieldEnum | Prisma.MessageScalarFieldEnum[] +} + +/** + * Conversation without action + */ +export type ConversationDefaultArgs = { + /** + * Select specific fields to fetch from the Conversation + */ + select?: Prisma.ConversationSelect | null + /** + * Omit specific fields from the Conversation + */ + omit?: Prisma.ConversationOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.ConversationInclude | null +} diff --git a/src/generated/client/models/Message.ts b/src/generated/client/models/Message.ts new file mode 100644 index 0000000..e1270de --- /dev/null +++ b/src/generated/client/models/Message.ts @@ -0,0 +1,1337 @@ + +/* !!! This is code generated by Prisma. Do not edit directly. !!! */ +/* eslint-disable */ +// biome-ignore-all lint: generated file +// @ts-nocheck +/* + * This file exports the `Message` model and its related types. + * + * ๐ŸŸข You can import this file directly. + */ +import type * as runtime from "@prisma/client/runtime/client" +import type * as $Enums from "../enums" +import type * as Prisma from "../internal/prismaNamespace" + +/** + * Model Message + * + */ +export type MessageModel = runtime.Types.Result.DefaultSelection + +export type AggregateMessage = { + _count: MessageCountAggregateOutputType | null + _min: MessageMinAggregateOutputType | null + _max: MessageMaxAggregateOutputType | null +} + +export type MessageMinAggregateOutputType = { + id: string | null + role: string | null + content: string | null + conversationId: string | null + createdAt: Date | null +} + +export type MessageMaxAggregateOutputType = { + id: string | null + role: string | null + content: string | null + conversationId: string | null + createdAt: Date | null +} + +export type MessageCountAggregateOutputType = { + id: number + role: number + content: number + conversationId: number + createdAt: number + _all: number +} + + +export type MessageMinAggregateInputType = { + id?: true + role?: true + content?: true + conversationId?: true + createdAt?: true +} + +export type MessageMaxAggregateInputType = { + id?: true + role?: true + content?: true + conversationId?: true + createdAt?: true +} + +export type MessageCountAggregateInputType = { + id?: true + role?: true + content?: true + conversationId?: true + createdAt?: true + _all?: true +} + +export type MessageAggregateArgs = { + /** + * Filter which Message to aggregate. + */ + where?: Prisma.MessageWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of Messages to fetch. + */ + orderBy?: Prisma.MessageOrderByWithRelationInput | Prisma.MessageOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the start position + */ + cursor?: Prisma.MessageWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `ยฑn` Messages from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` Messages. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Count returned Messages + **/ + _count?: true | MessageCountAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to find the minimum value + **/ + _min?: MessageMinAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to find the maximum value + **/ + _max?: MessageMaxAggregateInputType +} + +export type GetMessageAggregateType = { + [P in keyof T & keyof AggregateMessage]: P extends '_count' | 'count' + ? T[P] extends true + ? number + : Prisma.GetScalarType + : Prisma.GetScalarType +} + + + + +export type MessageGroupByArgs = { + where?: Prisma.MessageWhereInput + orderBy?: Prisma.MessageOrderByWithAggregationInput | Prisma.MessageOrderByWithAggregationInput[] + by: Prisma.MessageScalarFieldEnum[] | Prisma.MessageScalarFieldEnum + having?: Prisma.MessageScalarWhereWithAggregatesInput + take?: number + skip?: number + _count?: MessageCountAggregateInputType | true + _min?: MessageMinAggregateInputType + _max?: MessageMaxAggregateInputType +} + +export type MessageGroupByOutputType = { + id: string + role: string + content: string + conversationId: string + createdAt: Date + _count: MessageCountAggregateOutputType | null + _min: MessageMinAggregateOutputType | null + _max: MessageMaxAggregateOutputType | null +} + +type GetMessageGroupByPayload = Prisma.PrismaPromise< + Array< + Prisma.PickEnumerable & + { + [P in ((keyof T) & (keyof MessageGroupByOutputType))]: P extends '_count' + ? T[P] extends boolean + ? number + : Prisma.GetScalarType + : Prisma.GetScalarType + } + > + > + + + +export type MessageWhereInput = { + AND?: Prisma.MessageWhereInput | Prisma.MessageWhereInput[] + OR?: Prisma.MessageWhereInput[] + NOT?: Prisma.MessageWhereInput | Prisma.MessageWhereInput[] + id?: Prisma.StringFilter<"Message"> | string + role?: Prisma.StringFilter<"Message"> | string + content?: Prisma.StringFilter<"Message"> | string + conversationId?: Prisma.StringFilter<"Message"> | string + createdAt?: Prisma.DateTimeFilter<"Message"> | Date | string + conversation?: Prisma.XOR +} + +export type MessageOrderByWithRelationInput = { + id?: Prisma.SortOrder + role?: Prisma.SortOrder + content?: Prisma.SortOrder + conversationId?: Prisma.SortOrder + createdAt?: Prisma.SortOrder + conversation?: Prisma.ConversationOrderByWithRelationInput +} + +export type MessageWhereUniqueInput = Prisma.AtLeast<{ + id?: string + AND?: Prisma.MessageWhereInput | Prisma.MessageWhereInput[] + OR?: Prisma.MessageWhereInput[] + NOT?: Prisma.MessageWhereInput | Prisma.MessageWhereInput[] + role?: Prisma.StringFilter<"Message"> | string + content?: Prisma.StringFilter<"Message"> | string + conversationId?: Prisma.StringFilter<"Message"> | string + createdAt?: Prisma.DateTimeFilter<"Message"> | Date | string + conversation?: Prisma.XOR +}, "id"> + +export type MessageOrderByWithAggregationInput = { + id?: Prisma.SortOrder + role?: Prisma.SortOrder + content?: Prisma.SortOrder + conversationId?: Prisma.SortOrder + createdAt?: Prisma.SortOrder + _count?: Prisma.MessageCountOrderByAggregateInput + _max?: Prisma.MessageMaxOrderByAggregateInput + _min?: Prisma.MessageMinOrderByAggregateInput +} + +export type MessageScalarWhereWithAggregatesInput = { + AND?: Prisma.MessageScalarWhereWithAggregatesInput | Prisma.MessageScalarWhereWithAggregatesInput[] + OR?: Prisma.MessageScalarWhereWithAggregatesInput[] + NOT?: Prisma.MessageScalarWhereWithAggregatesInput | Prisma.MessageScalarWhereWithAggregatesInput[] + id?: Prisma.StringWithAggregatesFilter<"Message"> | string + role?: Prisma.StringWithAggregatesFilter<"Message"> | string + content?: Prisma.StringWithAggregatesFilter<"Message"> | string + conversationId?: Prisma.StringWithAggregatesFilter<"Message"> | string + createdAt?: Prisma.DateTimeWithAggregatesFilter<"Message"> | Date | string +} + +export type MessageCreateInput = { + id?: string + role: string + content: string + createdAt?: Date | string + conversation: Prisma.ConversationCreateNestedOneWithoutMessagesInput +} + +export type MessageUncheckedCreateInput = { + id?: string + role: string + content: string + conversationId: string + createdAt?: Date | string +} + +export type MessageUpdateInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + role?: Prisma.StringFieldUpdateOperationsInput | string + content?: Prisma.StringFieldUpdateOperationsInput | string + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + conversation?: Prisma.ConversationUpdateOneRequiredWithoutMessagesNestedInput +} + +export type MessageUncheckedUpdateInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + role?: Prisma.StringFieldUpdateOperationsInput | string + content?: Prisma.StringFieldUpdateOperationsInput | string + conversationId?: Prisma.StringFieldUpdateOperationsInput | string + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string +} + +export type MessageCreateManyInput = { + id?: string + role: string + content: string + conversationId: string + createdAt?: Date | string +} + +export type MessageUpdateManyMutationInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + role?: Prisma.StringFieldUpdateOperationsInput | string + content?: Prisma.StringFieldUpdateOperationsInput | string + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string +} + +export type MessageUncheckedUpdateManyInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + role?: Prisma.StringFieldUpdateOperationsInput | string + content?: Prisma.StringFieldUpdateOperationsInput | string + conversationId?: Prisma.StringFieldUpdateOperationsInput | string + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string +} + +export type MessageListRelationFilter = { + every?: Prisma.MessageWhereInput + some?: Prisma.MessageWhereInput + none?: Prisma.MessageWhereInput +} + +export type MessageOrderByRelationAggregateInput = { + _count?: Prisma.SortOrder +} + +export type MessageCountOrderByAggregateInput = { + id?: Prisma.SortOrder + role?: Prisma.SortOrder + content?: Prisma.SortOrder + conversationId?: Prisma.SortOrder + createdAt?: Prisma.SortOrder +} + +export type MessageMaxOrderByAggregateInput = { + id?: Prisma.SortOrder + role?: Prisma.SortOrder + content?: Prisma.SortOrder + conversationId?: Prisma.SortOrder + createdAt?: Prisma.SortOrder +} + +export type MessageMinOrderByAggregateInput = { + id?: Prisma.SortOrder + role?: Prisma.SortOrder + content?: Prisma.SortOrder + conversationId?: Prisma.SortOrder + createdAt?: Prisma.SortOrder +} + +export type MessageCreateNestedManyWithoutConversationInput = { + create?: Prisma.XOR | Prisma.MessageCreateWithoutConversationInput[] | Prisma.MessageUncheckedCreateWithoutConversationInput[] + connectOrCreate?: Prisma.MessageCreateOrConnectWithoutConversationInput | Prisma.MessageCreateOrConnectWithoutConversationInput[] + createMany?: Prisma.MessageCreateManyConversationInputEnvelope + connect?: Prisma.MessageWhereUniqueInput | Prisma.MessageWhereUniqueInput[] +} + +export type MessageUncheckedCreateNestedManyWithoutConversationInput = { + create?: Prisma.XOR | Prisma.MessageCreateWithoutConversationInput[] | Prisma.MessageUncheckedCreateWithoutConversationInput[] + connectOrCreate?: Prisma.MessageCreateOrConnectWithoutConversationInput | Prisma.MessageCreateOrConnectWithoutConversationInput[] + createMany?: Prisma.MessageCreateManyConversationInputEnvelope + connect?: Prisma.MessageWhereUniqueInput | Prisma.MessageWhereUniqueInput[] +} + +export type MessageUpdateManyWithoutConversationNestedInput = { + create?: Prisma.XOR | Prisma.MessageCreateWithoutConversationInput[] | Prisma.MessageUncheckedCreateWithoutConversationInput[] + connectOrCreate?: Prisma.MessageCreateOrConnectWithoutConversationInput | Prisma.MessageCreateOrConnectWithoutConversationInput[] + upsert?: Prisma.MessageUpsertWithWhereUniqueWithoutConversationInput | Prisma.MessageUpsertWithWhereUniqueWithoutConversationInput[] + createMany?: Prisma.MessageCreateManyConversationInputEnvelope + set?: Prisma.MessageWhereUniqueInput | Prisma.MessageWhereUniqueInput[] + disconnect?: Prisma.MessageWhereUniqueInput | Prisma.MessageWhereUniqueInput[] + delete?: Prisma.MessageWhereUniqueInput | Prisma.MessageWhereUniqueInput[] + connect?: Prisma.MessageWhereUniqueInput | Prisma.MessageWhereUniqueInput[] + update?: Prisma.MessageUpdateWithWhereUniqueWithoutConversationInput | Prisma.MessageUpdateWithWhereUniqueWithoutConversationInput[] + updateMany?: Prisma.MessageUpdateManyWithWhereWithoutConversationInput | Prisma.MessageUpdateManyWithWhereWithoutConversationInput[] + deleteMany?: Prisma.MessageScalarWhereInput | Prisma.MessageScalarWhereInput[] +} + +export type MessageUncheckedUpdateManyWithoutConversationNestedInput = { + create?: Prisma.XOR | Prisma.MessageCreateWithoutConversationInput[] | Prisma.MessageUncheckedCreateWithoutConversationInput[] + connectOrCreate?: Prisma.MessageCreateOrConnectWithoutConversationInput | Prisma.MessageCreateOrConnectWithoutConversationInput[] + upsert?: Prisma.MessageUpsertWithWhereUniqueWithoutConversationInput | Prisma.MessageUpsertWithWhereUniqueWithoutConversationInput[] + createMany?: Prisma.MessageCreateManyConversationInputEnvelope + set?: Prisma.MessageWhereUniqueInput | Prisma.MessageWhereUniqueInput[] + disconnect?: Prisma.MessageWhereUniqueInput | Prisma.MessageWhereUniqueInput[] + delete?: Prisma.MessageWhereUniqueInput | Prisma.MessageWhereUniqueInput[] + connect?: Prisma.MessageWhereUniqueInput | Prisma.MessageWhereUniqueInput[] + update?: Prisma.MessageUpdateWithWhereUniqueWithoutConversationInput | Prisma.MessageUpdateWithWhereUniqueWithoutConversationInput[] + updateMany?: Prisma.MessageUpdateManyWithWhereWithoutConversationInput | Prisma.MessageUpdateManyWithWhereWithoutConversationInput[] + deleteMany?: Prisma.MessageScalarWhereInput | Prisma.MessageScalarWhereInput[] +} + +export type MessageCreateWithoutConversationInput = { + id?: string + role: string + content: string + createdAt?: Date | string +} + +export type MessageUncheckedCreateWithoutConversationInput = { + id?: string + role: string + content: string + createdAt?: Date | string +} + +export type MessageCreateOrConnectWithoutConversationInput = { + where: Prisma.MessageWhereUniqueInput + create: Prisma.XOR +} + +export type MessageCreateManyConversationInputEnvelope = { + data: Prisma.MessageCreateManyConversationInput | Prisma.MessageCreateManyConversationInput[] +} + +export type MessageUpsertWithWhereUniqueWithoutConversationInput = { + where: Prisma.MessageWhereUniqueInput + update: Prisma.XOR + create: Prisma.XOR +} + +export type MessageUpdateWithWhereUniqueWithoutConversationInput = { + where: Prisma.MessageWhereUniqueInput + data: Prisma.XOR +} + +export type MessageUpdateManyWithWhereWithoutConversationInput = { + where: Prisma.MessageScalarWhereInput + data: Prisma.XOR +} + +export type MessageScalarWhereInput = { + AND?: Prisma.MessageScalarWhereInput | Prisma.MessageScalarWhereInput[] + OR?: Prisma.MessageScalarWhereInput[] + NOT?: Prisma.MessageScalarWhereInput | Prisma.MessageScalarWhereInput[] + id?: Prisma.StringFilter<"Message"> | string + role?: Prisma.StringFilter<"Message"> | string + content?: Prisma.StringFilter<"Message"> | string + conversationId?: Prisma.StringFilter<"Message"> | string + createdAt?: Prisma.DateTimeFilter<"Message"> | Date | string +} + +export type MessageCreateManyConversationInput = { + id?: string + role: string + content: string + createdAt?: Date | string +} + +export type MessageUpdateWithoutConversationInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + role?: Prisma.StringFieldUpdateOperationsInput | string + content?: Prisma.StringFieldUpdateOperationsInput | string + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string +} + +export type MessageUncheckedUpdateWithoutConversationInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + role?: Prisma.StringFieldUpdateOperationsInput | string + content?: Prisma.StringFieldUpdateOperationsInput | string + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string +} + +export type MessageUncheckedUpdateManyWithoutConversationInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + role?: Prisma.StringFieldUpdateOperationsInput | string + content?: Prisma.StringFieldUpdateOperationsInput | string + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string +} + + + +export type MessageSelect = runtime.Types.Extensions.GetSelect<{ + id?: boolean + role?: boolean + content?: boolean + conversationId?: boolean + createdAt?: boolean + conversation?: boolean | Prisma.ConversationDefaultArgs +}, ExtArgs["result"]["message"]> + +export type MessageSelectCreateManyAndReturn = runtime.Types.Extensions.GetSelect<{ + id?: boolean + role?: boolean + content?: boolean + conversationId?: boolean + createdAt?: boolean + conversation?: boolean | Prisma.ConversationDefaultArgs +}, ExtArgs["result"]["message"]> + +export type MessageSelectUpdateManyAndReturn = runtime.Types.Extensions.GetSelect<{ + id?: boolean + role?: boolean + content?: boolean + conversationId?: boolean + createdAt?: boolean + conversation?: boolean | Prisma.ConversationDefaultArgs +}, ExtArgs["result"]["message"]> + +export type MessageSelectScalar = { + id?: boolean + role?: boolean + content?: boolean + conversationId?: boolean + createdAt?: boolean +} + +export type MessageOmit = runtime.Types.Extensions.GetOmit<"id" | "role" | "content" | "conversationId" | "createdAt", ExtArgs["result"]["message"]> +export type MessageInclude = { + conversation?: boolean | Prisma.ConversationDefaultArgs +} +export type MessageIncludeCreateManyAndReturn = { + conversation?: boolean | Prisma.ConversationDefaultArgs +} +export type MessageIncludeUpdateManyAndReturn = { + conversation?: boolean | Prisma.ConversationDefaultArgs +} + +export type $MessagePayload = { + name: "Message" + objects: { + conversation: Prisma.$ConversationPayload + } + scalars: runtime.Types.Extensions.GetPayloadResult<{ + id: string + role: string + content: string + conversationId: string + createdAt: Date + }, ExtArgs["result"]["message"]> + composites: {} +} + +export type MessageGetPayload = runtime.Types.Result.GetResult + +export type MessageCountArgs = + Omit & { + select?: MessageCountAggregateInputType | true + } + +export interface MessageDelegate { + [K: symbol]: { types: Prisma.TypeMap['model']['Message'], meta: { name: 'Message' } } + /** + * Find zero or one Message that matches the filter. + * @param {MessageFindUniqueArgs} args - Arguments to find a Message + * @example + * // Get one Message + * const message = await prisma.message.findUnique({ + * where: { + * // ... provide filter here + * } + * }) + */ + findUnique(args: Prisma.SelectSubset>): Prisma.Prisma__MessageClient, T, "findUnique", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + + /** + * Find one Message that matches the filter or throw an error with `error.code='P2025'` + * if no matches were found. + * @param {MessageFindUniqueOrThrowArgs} args - Arguments to find a Message + * @example + * // Get one Message + * const message = await prisma.message.findUniqueOrThrow({ + * where: { + * // ... provide filter here + * } + * }) + */ + findUniqueOrThrow(args: Prisma.SelectSubset>): Prisma.Prisma__MessageClient, T, "findUniqueOrThrow", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Find the first Message that matches the filter. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {MessageFindFirstArgs} args - Arguments to find a Message + * @example + * // Get one Message + * const message = await prisma.message.findFirst({ + * where: { + * // ... provide filter here + * } + * }) + */ + findFirst(args?: Prisma.SelectSubset>): Prisma.Prisma__MessageClient, T, "findFirst", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + + /** + * Find the first Message that matches the filter or + * throw `PrismaKnownClientError` with `P2025` code if no matches were found. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {MessageFindFirstOrThrowArgs} args - Arguments to find a Message + * @example + * // Get one Message + * const message = await prisma.message.findFirstOrThrow({ + * where: { + * // ... provide filter here + * } + * }) + */ + findFirstOrThrow(args?: Prisma.SelectSubset>): Prisma.Prisma__MessageClient, T, "findFirstOrThrow", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Find zero or more Messages that matches the filter. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {MessageFindManyArgs} args - Arguments to filter and select certain fields only. + * @example + * // Get all Messages + * const messages = await prisma.message.findMany() + * + * // Get first 10 Messages + * const messages = await prisma.message.findMany({ take: 10 }) + * + * // Only select the `id` + * const messageWithIdOnly = await prisma.message.findMany({ select: { id: true } }) + * + */ + findMany(args?: Prisma.SelectSubset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions>> + + /** + * Create a Message. + * @param {MessageCreateArgs} args - Arguments to create a Message. + * @example + * // Create one Message + * const Message = await prisma.message.create({ + * data: { + * // ... data to create a Message + * } + * }) + * + */ + create(args: Prisma.SelectSubset>): Prisma.Prisma__MessageClient, T, "create", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Create many Messages. + * @param {MessageCreateManyArgs} args - Arguments to create many Messages. + * @example + * // Create many Messages + * const message = await prisma.message.createMany({ + * data: [ + * // ... provide data here + * ] + * }) + * + */ + createMany(args?: Prisma.SelectSubset>): Prisma.PrismaPromise + + /** + * Create many Messages and returns the data saved in the database. + * @param {MessageCreateManyAndReturnArgs} args - Arguments to create many Messages. + * @example + * // Create many Messages + * const message = await prisma.message.createManyAndReturn({ + * data: [ + * // ... provide data here + * ] + * }) + * + * // Create many Messages and only return the `id` + * const messageWithIdOnly = await prisma.message.createManyAndReturn({ + * select: { id: true }, + * data: [ + * // ... provide data here + * ] + * }) + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * + */ + createManyAndReturn(args?: Prisma.SelectSubset>): Prisma.PrismaPromise, T, "createManyAndReturn", GlobalOmitOptions>> + + /** + * Delete a Message. + * @param {MessageDeleteArgs} args - Arguments to delete one Message. + * @example + * // Delete one Message + * const Message = await prisma.message.delete({ + * where: { + * // ... filter to delete one Message + * } + * }) + * + */ + delete(args: Prisma.SelectSubset>): Prisma.Prisma__MessageClient, T, "delete", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Update one Message. + * @param {MessageUpdateArgs} args - Arguments to update one Message. + * @example + * // Update one Message + * const message = await prisma.message.update({ + * where: { + * // ... provide filter here + * }, + * data: { + * // ... provide data here + * } + * }) + * + */ + update(args: Prisma.SelectSubset>): Prisma.Prisma__MessageClient, T, "update", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Delete zero or more Messages. + * @param {MessageDeleteManyArgs} args - Arguments to filter Messages to delete. + * @example + * // Delete a few Messages + * const { count } = await prisma.message.deleteMany({ + * where: { + * // ... provide filter here + * } + * }) + * + */ + deleteMany(args?: Prisma.SelectSubset>): Prisma.PrismaPromise + + /** + * Update zero or more Messages. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {MessageUpdateManyArgs} args - Arguments to update one or more rows. + * @example + * // Update many Messages + * const message = await prisma.message.updateMany({ + * where: { + * // ... provide filter here + * }, + * data: { + * // ... provide data here + * } + * }) + * + */ + updateMany(args: Prisma.SelectSubset>): Prisma.PrismaPromise + + /** + * Update zero or more Messages and returns the data updated in the database. + * @param {MessageUpdateManyAndReturnArgs} args - Arguments to update many Messages. + * @example + * // Update many Messages + * const message = await prisma.message.updateManyAndReturn({ + * where: { + * // ... provide filter here + * }, + * data: [ + * // ... provide data here + * ] + * }) + * + * // Update zero or more Messages and only return the `id` + * const messageWithIdOnly = await prisma.message.updateManyAndReturn({ + * select: { id: true }, + * where: { + * // ... provide filter here + * }, + * data: [ + * // ... provide data here + * ] + * }) + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * + */ + updateManyAndReturn(args: Prisma.SelectSubset>): Prisma.PrismaPromise, T, "updateManyAndReturn", GlobalOmitOptions>> + + /** + * Create or update one Message. + * @param {MessageUpsertArgs} args - Arguments to update or create a Message. + * @example + * // Update or create a Message + * const message = await prisma.message.upsert({ + * create: { + * // ... data to create a Message + * }, + * update: { + * // ... in case it already exists, update + * }, + * where: { + * // ... the filter for the Message we want to update + * } + * }) + */ + upsert(args: Prisma.SelectSubset>): Prisma.Prisma__MessageClient, T, "upsert", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + + /** + * Count the number of Messages. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {MessageCountArgs} args - Arguments to filter Messages to count. + * @example + * // Count the number of Messages + * const count = await prisma.message.count({ + * where: { + * // ... the filter for the Messages we want to count + * } + * }) + **/ + count( + args?: Prisma.Subset, + ): Prisma.PrismaPromise< + T extends runtime.Types.Utils.Record<'select', any> + ? T['select'] extends true + ? number + : Prisma.GetScalarType + : number + > + + /** + * Allows you to perform aggregations operations on a Message. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {MessageAggregateArgs} args - Select which aggregations you would like to apply and on what fields. + * @example + * // Ordered by age ascending + * // Where email contains prisma.io + * // Limited to the 10 users + * const aggregations = await prisma.user.aggregate({ + * _avg: { + * age: true, + * }, + * where: { + * email: { + * contains: "prisma.io", + * }, + * }, + * orderBy: { + * age: "asc", + * }, + * take: 10, + * }) + **/ + aggregate(args: Prisma.Subset): Prisma.PrismaPromise> + + /** + * Group by Message. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {MessageGroupByArgs} args - Group by arguments. + * @example + * // Group by city, order by createdAt, get count + * const result = await prisma.user.groupBy({ + * by: ['city', 'createdAt'], + * orderBy: { + * createdAt: true + * }, + * _count: { + * _all: true + * }, + * }) + * + **/ + groupBy< + T extends MessageGroupByArgs, + HasSelectOrTake extends Prisma.Or< + Prisma.Extends<'skip', Prisma.Keys>, + Prisma.Extends<'take', Prisma.Keys> + >, + OrderByArg extends Prisma.True extends HasSelectOrTake + ? { orderBy: MessageGroupByArgs['orderBy'] } + : { orderBy?: MessageGroupByArgs['orderBy'] }, + OrderFields extends Prisma.ExcludeUnderscoreKeys>>, + ByFields extends Prisma.MaybeTupleToUnion, + ByValid extends Prisma.Has, + HavingFields extends Prisma.GetHavingFields, + HavingValid extends Prisma.Has, + ByEmpty extends T['by'] extends never[] ? Prisma.True : Prisma.False, + InputErrors extends ByEmpty extends Prisma.True + ? `Error: "by" must not be empty.` + : HavingValid extends Prisma.False + ? { + [P in HavingFields]: P extends ByFields + ? never + : P extends string + ? `Error: Field "${P}" used in "having" needs to be provided in "by".` + : [ + Error, + 'Field ', + P, + ` in "having" needs to be provided in "by"`, + ] + }[HavingFields] + : 'take' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "take", you also need to provide "orderBy"' + : 'skip' extends Prisma.Keys + ? 'orderBy' extends Prisma.Keys + ? ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "skip", you also need to provide "orderBy"' + : ByValid extends Prisma.True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + >(args: Prisma.SubsetIntersection & InputErrors): {} extends InputErrors ? GetMessageGroupByPayload : Prisma.PrismaPromise +/** + * Fields of the Message model + */ +readonly fields: MessageFieldRefs; +} + +/** + * The delegate class that acts as a "Promise-like" for Message. + * Why is this prefixed with `Prisma__`? + * Because we want to prevent naming conflicts as mentioned in + * https://github.com/prisma/prisma-client-js/issues/707 + */ +export interface Prisma__MessageClient extends Prisma.PrismaPromise { + readonly [Symbol.toStringTag]: "PrismaPromise" + conversation = {}>(args?: Prisma.Subset>): Prisma.Prisma__ConversationClient, T, "findUniqueOrThrow", GlobalOmitOptions> | Null, Null, ExtArgs, GlobalOmitOptions> + /** + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): runtime.Types.Utils.JsPromise + /** + * Attaches a callback for only the rejection of the Promise. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of the callback. + */ + catch(onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): runtime.Types.Utils.JsPromise + /** + * Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The + * resolved value cannot be modified from the callback. + * @param onfinally The callback to execute when the Promise is settled (fulfilled or rejected). + * @returns A Promise for the completion of the callback. + */ + finally(onfinally?: (() => void) | undefined | null): runtime.Types.Utils.JsPromise +} + + + + +/** + * Fields of the Message model + */ +export interface MessageFieldRefs { + readonly id: Prisma.FieldRef<"Message", 'String'> + readonly role: Prisma.FieldRef<"Message", 'String'> + readonly content: Prisma.FieldRef<"Message", 'String'> + readonly conversationId: Prisma.FieldRef<"Message", 'String'> + readonly createdAt: Prisma.FieldRef<"Message", 'DateTime'> +} + + +// Custom InputTypes +/** + * Message findUnique + */ +export type MessageFindUniqueArgs = { + /** + * Select specific fields to fetch from the Message + */ + select?: Prisma.MessageSelect | null + /** + * Omit specific fields from the Message + */ + omit?: Prisma.MessageOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.MessageInclude | null + /** + * Filter, which Message to fetch. + */ + where: Prisma.MessageWhereUniqueInput +} + +/** + * Message findUniqueOrThrow + */ +export type MessageFindUniqueOrThrowArgs = { + /** + * Select specific fields to fetch from the Message + */ + select?: Prisma.MessageSelect | null + /** + * Omit specific fields from the Message + */ + omit?: Prisma.MessageOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.MessageInclude | null + /** + * Filter, which Message to fetch. + */ + where: Prisma.MessageWhereUniqueInput +} + +/** + * Message findFirst + */ +export type MessageFindFirstArgs = { + /** + * Select specific fields to fetch from the Message + */ + select?: Prisma.MessageSelect | null + /** + * Omit specific fields from the Message + */ + omit?: Prisma.MessageOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.MessageInclude | null + /** + * Filter, which Message to fetch. + */ + where?: Prisma.MessageWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of Messages to fetch. + */ + orderBy?: Prisma.MessageOrderByWithRelationInput | Prisma.MessageOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for searching for Messages. + */ + cursor?: Prisma.MessageWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `ยฑn` Messages from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` Messages. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of Messages. + */ + distinct?: Prisma.MessageScalarFieldEnum | Prisma.MessageScalarFieldEnum[] +} + +/** + * Message findFirstOrThrow + */ +export type MessageFindFirstOrThrowArgs = { + /** + * Select specific fields to fetch from the Message + */ + select?: Prisma.MessageSelect | null + /** + * Omit specific fields from the Message + */ + omit?: Prisma.MessageOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.MessageInclude | null + /** + * Filter, which Message to fetch. + */ + where?: Prisma.MessageWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of Messages to fetch. + */ + orderBy?: Prisma.MessageOrderByWithRelationInput | Prisma.MessageOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for searching for Messages. + */ + cursor?: Prisma.MessageWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `ยฑn` Messages from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` Messages. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of Messages. + */ + distinct?: Prisma.MessageScalarFieldEnum | Prisma.MessageScalarFieldEnum[] +} + +/** + * Message findMany + */ +export type MessageFindManyArgs = { + /** + * Select specific fields to fetch from the Message + */ + select?: Prisma.MessageSelect | null + /** + * Omit specific fields from the Message + */ + omit?: Prisma.MessageOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.MessageInclude | null + /** + * Filter, which Messages to fetch. + */ + where?: Prisma.MessageWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of Messages to fetch. + */ + orderBy?: Prisma.MessageOrderByWithRelationInput | Prisma.MessageOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for listing Messages. + */ + cursor?: Prisma.MessageWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `ยฑn` Messages from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` Messages. + */ + skip?: number + distinct?: Prisma.MessageScalarFieldEnum | Prisma.MessageScalarFieldEnum[] +} + +/** + * Message create + */ +export type MessageCreateArgs = { + /** + * Select specific fields to fetch from the Message + */ + select?: Prisma.MessageSelect | null + /** + * Omit specific fields from the Message + */ + omit?: Prisma.MessageOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.MessageInclude | null + /** + * The data needed to create a Message. + */ + data: Prisma.XOR +} + +/** + * Message createMany + */ +export type MessageCreateManyArgs = { + /** + * The data used to create many Messages. + */ + data: Prisma.MessageCreateManyInput | Prisma.MessageCreateManyInput[] +} + +/** + * Message createManyAndReturn + */ +export type MessageCreateManyAndReturnArgs = { + /** + * Select specific fields to fetch from the Message + */ + select?: Prisma.MessageSelectCreateManyAndReturn | null + /** + * Omit specific fields from the Message + */ + omit?: Prisma.MessageOmit | null + /** + * The data used to create many Messages. + */ + data: Prisma.MessageCreateManyInput | Prisma.MessageCreateManyInput[] + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.MessageIncludeCreateManyAndReturn | null +} + +/** + * Message update + */ +export type MessageUpdateArgs = { + /** + * Select specific fields to fetch from the Message + */ + select?: Prisma.MessageSelect | null + /** + * Omit specific fields from the Message + */ + omit?: Prisma.MessageOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.MessageInclude | null + /** + * The data needed to update a Message. + */ + data: Prisma.XOR + /** + * Choose, which Message to update. + */ + where: Prisma.MessageWhereUniqueInput +} + +/** + * Message updateMany + */ +export type MessageUpdateManyArgs = { + /** + * The data used to update Messages. + */ + data: Prisma.XOR + /** + * Filter which Messages to update + */ + where?: Prisma.MessageWhereInput + /** + * Limit how many Messages to update. + */ + limit?: number +} + +/** + * Message updateManyAndReturn + */ +export type MessageUpdateManyAndReturnArgs = { + /** + * Select specific fields to fetch from the Message + */ + select?: Prisma.MessageSelectUpdateManyAndReturn | null + /** + * Omit specific fields from the Message + */ + omit?: Prisma.MessageOmit | null + /** + * The data used to update Messages. + */ + data: Prisma.XOR + /** + * Filter which Messages to update + */ + where?: Prisma.MessageWhereInput + /** + * Limit how many Messages to update. + */ + limit?: number + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.MessageIncludeUpdateManyAndReturn | null +} + +/** + * Message upsert + */ +export type MessageUpsertArgs = { + /** + * Select specific fields to fetch from the Message + */ + select?: Prisma.MessageSelect | null + /** + * Omit specific fields from the Message + */ + omit?: Prisma.MessageOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.MessageInclude | null + /** + * The filter to search for the Message to update in case it exists. + */ + where: Prisma.MessageWhereUniqueInput + /** + * In case the Message found by the `where` argument doesn't exist, create a new Message with this data. + */ + create: Prisma.XOR + /** + * In case the Message was found with the provided `where` argument, update it with this data. + */ + update: Prisma.XOR +} + +/** + * Message delete + */ +export type MessageDeleteArgs = { + /** + * Select specific fields to fetch from the Message + */ + select?: Prisma.MessageSelect | null + /** + * Omit specific fields from the Message + */ + omit?: Prisma.MessageOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.MessageInclude | null + /** + * Filter which Message to delete. + */ + where: Prisma.MessageWhereUniqueInput +} + +/** + * Message deleteMany + */ +export type MessageDeleteManyArgs = { + /** + * Filter which Messages to delete + */ + where?: Prisma.MessageWhereInput + /** + * Limit how many Messages to delete. + */ + limit?: number +} + +/** + * Message without action + */ +export type MessageDefaultArgs = { + /** + * Select specific fields to fetch from the Message + */ + select?: Prisma.MessageSelect | null + /** + * Omit specific fields from the Message + */ + omit?: Prisma.MessageOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.MessageInclude | null +} diff --git a/src/generated/client/models/User.ts b/src/generated/client/models/User.ts index fef9c10..f0f7fdd 100644 --- a/src/generated/client/models/User.ts +++ b/src/generated/client/models/User.ts @@ -243,6 +243,7 @@ export type UserWhereInput = { wallets?: Prisma.WalletListRelationFilter sybilScores?: Prisma.SybilScoreListRelationFilter worldIdVerifications?: Prisma.WorldIdVerificationListRelationFilter + conversations?: Prisma.ConversationListRelationFilter } export type UserOrderByWithRelationInput = { @@ -257,6 +258,7 @@ export type UserOrderByWithRelationInput = { wallets?: Prisma.WalletOrderByRelationAggregateInput sybilScores?: Prisma.SybilScoreOrderByRelationAggregateInput worldIdVerifications?: Prisma.WorldIdVerificationOrderByRelationAggregateInput + conversations?: Prisma.ConversationOrderByRelationAggregateInput } export type UserWhereUniqueInput = Prisma.AtLeast<{ @@ -274,6 +276,7 @@ export type UserWhereUniqueInput = Prisma.AtLeast<{ wallets?: Prisma.WalletListRelationFilter sybilScores?: Prisma.SybilScoreListRelationFilter worldIdVerifications?: Prisma.WorldIdVerificationListRelationFilter + conversations?: Prisma.ConversationListRelationFilter }, "id" | "walletAddress"> export type UserOrderByWithAggregationInput = { @@ -318,6 +321,7 @@ export type UserCreateInput = { wallets?: Prisma.WalletCreateNestedManyWithoutUserInput sybilScores?: Prisma.SybilScoreCreateNestedManyWithoutUserInput worldIdVerifications?: Prisma.WorldIdVerificationCreateNestedManyWithoutUserInput + conversations?: Prisma.ConversationCreateNestedManyWithoutUserInput } export type UserUncheckedCreateInput = { @@ -332,6 +336,7 @@ export type UserUncheckedCreateInput = { wallets?: Prisma.WalletUncheckedCreateNestedManyWithoutUserInput sybilScores?: Prisma.SybilScoreUncheckedCreateNestedManyWithoutUserInput worldIdVerifications?: Prisma.WorldIdVerificationUncheckedCreateNestedManyWithoutUserInput + conversations?: Prisma.ConversationUncheckedCreateNestedManyWithoutUserInput } export type UserUpdateInput = { @@ -346,6 +351,7 @@ export type UserUpdateInput = { wallets?: Prisma.WalletUpdateManyWithoutUserNestedInput sybilScores?: Prisma.SybilScoreUpdateManyWithoutUserNestedInput worldIdVerifications?: Prisma.WorldIdVerificationUpdateManyWithoutUserNestedInput + conversations?: Prisma.ConversationUpdateManyWithoutUserNestedInput } export type UserUncheckedUpdateInput = { @@ -360,6 +366,7 @@ export type UserUncheckedUpdateInput = { wallets?: Prisma.WalletUncheckedUpdateManyWithoutUserNestedInput sybilScores?: Prisma.SybilScoreUncheckedUpdateManyWithoutUserNestedInput worldIdVerifications?: Prisma.WorldIdVerificationUncheckedUpdateManyWithoutUserNestedInput + conversations?: Prisma.ConversationUncheckedUpdateManyWithoutUserNestedInput } export type UserCreateManyInput = { @@ -511,6 +518,20 @@ export type UserUpdateOneRequiredWithoutWorldIdVerificationsNestedInput = { update?: Prisma.XOR, Prisma.UserUncheckedUpdateWithoutWorldIdVerificationsInput> } +export type UserCreateNestedOneWithoutConversationsInput = { + create?: Prisma.XOR + connectOrCreate?: Prisma.UserCreateOrConnectWithoutConversationsInput + connect?: Prisma.UserWhereUniqueInput +} + +export type UserUpdateOneRequiredWithoutConversationsNestedInput = { + create?: Prisma.XOR + connectOrCreate?: Prisma.UserCreateOrConnectWithoutConversationsInput + upsert?: Prisma.UserUpsertWithoutConversationsInput + connect?: Prisma.UserWhereUniqueInput + update?: Prisma.XOR, Prisma.UserUncheckedUpdateWithoutConversationsInput> +} + export type UserCreateWithoutWalletsInput = { id?: string createdAt?: Date | string @@ -522,6 +543,7 @@ export type UserCreateWithoutWalletsInput = { worldcoinVerifiedAt?: Date | string | null sybilScores?: Prisma.SybilScoreCreateNestedManyWithoutUserInput worldIdVerifications?: Prisma.WorldIdVerificationCreateNestedManyWithoutUserInput + conversations?: Prisma.ConversationCreateNestedManyWithoutUserInput } export type UserUncheckedCreateWithoutWalletsInput = { @@ -535,6 +557,7 @@ export type UserUncheckedCreateWithoutWalletsInput = { worldcoinVerifiedAt?: Date | string | null sybilScores?: Prisma.SybilScoreUncheckedCreateNestedManyWithoutUserInput worldIdVerifications?: Prisma.WorldIdVerificationUncheckedCreateNestedManyWithoutUserInput + conversations?: Prisma.ConversationUncheckedCreateNestedManyWithoutUserInput } export type UserCreateOrConnectWithoutWalletsInput = { @@ -564,6 +587,7 @@ export type UserUpdateWithoutWalletsInput = { worldcoinVerifiedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null sybilScores?: Prisma.SybilScoreUpdateManyWithoutUserNestedInput worldIdVerifications?: Prisma.WorldIdVerificationUpdateManyWithoutUserNestedInput + conversations?: Prisma.ConversationUpdateManyWithoutUserNestedInput } export type UserUncheckedUpdateWithoutWalletsInput = { @@ -577,6 +601,7 @@ export type UserUncheckedUpdateWithoutWalletsInput = { worldcoinVerifiedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null sybilScores?: Prisma.SybilScoreUncheckedUpdateManyWithoutUserNestedInput worldIdVerifications?: Prisma.WorldIdVerificationUncheckedUpdateManyWithoutUserNestedInput + conversations?: Prisma.ConversationUncheckedUpdateManyWithoutUserNestedInput } export type UserCreateWithoutSybilScoresInput = { @@ -590,6 +615,7 @@ export type UserCreateWithoutSybilScoresInput = { worldcoinVerifiedAt?: Date | string | null wallets?: Prisma.WalletCreateNestedManyWithoutUserInput worldIdVerifications?: Prisma.WorldIdVerificationCreateNestedManyWithoutUserInput + conversations?: Prisma.ConversationCreateNestedManyWithoutUserInput } export type UserUncheckedCreateWithoutSybilScoresInput = { @@ -603,6 +629,7 @@ export type UserUncheckedCreateWithoutSybilScoresInput = { worldcoinVerifiedAt?: Date | string | null wallets?: Prisma.WalletUncheckedCreateNestedManyWithoutUserInput worldIdVerifications?: Prisma.WorldIdVerificationUncheckedCreateNestedManyWithoutUserInput + conversations?: Prisma.ConversationUncheckedCreateNestedManyWithoutUserInput } export type UserCreateOrConnectWithoutSybilScoresInput = { @@ -632,6 +659,7 @@ export type UserUpdateWithoutSybilScoresInput = { worldcoinVerifiedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null wallets?: Prisma.WalletUpdateManyWithoutUserNestedInput worldIdVerifications?: Prisma.WorldIdVerificationUpdateManyWithoutUserNestedInput + conversations?: Prisma.ConversationUpdateManyWithoutUserNestedInput } export type UserUncheckedUpdateWithoutSybilScoresInput = { @@ -645,6 +673,7 @@ export type UserUncheckedUpdateWithoutSybilScoresInput = { worldcoinVerifiedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null wallets?: Prisma.WalletUncheckedUpdateManyWithoutUserNestedInput worldIdVerifications?: Prisma.WorldIdVerificationUncheckedUpdateManyWithoutUserNestedInput + conversations?: Prisma.ConversationUncheckedUpdateManyWithoutUserNestedInput } export type UserCreateWithoutWorldIdVerificationsInput = { @@ -658,6 +687,7 @@ export type UserCreateWithoutWorldIdVerificationsInput = { worldcoinVerifiedAt?: Date | string | null wallets?: Prisma.WalletCreateNestedManyWithoutUserInput sybilScores?: Prisma.SybilScoreCreateNestedManyWithoutUserInput + conversations?: Prisma.ConversationCreateNestedManyWithoutUserInput } export type UserUncheckedCreateWithoutWorldIdVerificationsInput = { @@ -671,6 +701,7 @@ export type UserUncheckedCreateWithoutWorldIdVerificationsInput = { worldcoinVerifiedAt?: Date | string | null wallets?: Prisma.WalletUncheckedCreateNestedManyWithoutUserInput sybilScores?: Prisma.SybilScoreUncheckedCreateNestedManyWithoutUserInput + conversations?: Prisma.ConversationUncheckedCreateNestedManyWithoutUserInput } export type UserCreateOrConnectWithoutWorldIdVerificationsInput = { @@ -700,6 +731,7 @@ export type UserUpdateWithoutWorldIdVerificationsInput = { worldcoinVerifiedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null wallets?: Prisma.WalletUpdateManyWithoutUserNestedInput sybilScores?: Prisma.SybilScoreUpdateManyWithoutUserNestedInput + conversations?: Prisma.ConversationUpdateManyWithoutUserNestedInput } export type UserUncheckedUpdateWithoutWorldIdVerificationsInput = { @@ -713,6 +745,79 @@ export type UserUncheckedUpdateWithoutWorldIdVerificationsInput = { worldcoinVerifiedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null wallets?: Prisma.WalletUncheckedUpdateManyWithoutUserNestedInput sybilScores?: Prisma.SybilScoreUncheckedUpdateManyWithoutUserNestedInput + conversations?: Prisma.ConversationUncheckedUpdateManyWithoutUserNestedInput +} + +export type UserCreateWithoutConversationsInput = { + id?: string + createdAt?: Date | string + updatedAt?: Date | string + walletAddress: string + reputation?: number + role?: $Enums.UserRole + worldcoinVerified?: boolean + worldcoinVerifiedAt?: Date | string | null + wallets?: Prisma.WalletCreateNestedManyWithoutUserInput + sybilScores?: Prisma.SybilScoreCreateNestedManyWithoutUserInput + worldIdVerifications?: Prisma.WorldIdVerificationCreateNestedManyWithoutUserInput +} + +export type UserUncheckedCreateWithoutConversationsInput = { + id?: string + createdAt?: Date | string + updatedAt?: Date | string + walletAddress: string + reputation?: number + role?: $Enums.UserRole + worldcoinVerified?: boolean + worldcoinVerifiedAt?: Date | string | null + wallets?: Prisma.WalletUncheckedCreateNestedManyWithoutUserInput + sybilScores?: Prisma.SybilScoreUncheckedCreateNestedManyWithoutUserInput + worldIdVerifications?: Prisma.WorldIdVerificationUncheckedCreateNestedManyWithoutUserInput +} + +export type UserCreateOrConnectWithoutConversationsInput = { + where: Prisma.UserWhereUniqueInput + create: Prisma.XOR +} + +export type UserUpsertWithoutConversationsInput = { + update: Prisma.XOR + create: Prisma.XOR + where?: Prisma.UserWhereInput +} + +export type UserUpdateToOneWithWhereWithoutConversationsInput = { + where?: Prisma.UserWhereInput + data: Prisma.XOR +} + +export type UserUpdateWithoutConversationsInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + walletAddress?: Prisma.StringFieldUpdateOperationsInput | string + reputation?: Prisma.IntFieldUpdateOperationsInput | number + role?: Prisma.EnumUserRoleFieldUpdateOperationsInput | $Enums.UserRole + worldcoinVerified?: Prisma.BoolFieldUpdateOperationsInput | boolean + worldcoinVerifiedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + wallets?: Prisma.WalletUpdateManyWithoutUserNestedInput + sybilScores?: Prisma.SybilScoreUpdateManyWithoutUserNestedInput + worldIdVerifications?: Prisma.WorldIdVerificationUpdateManyWithoutUserNestedInput +} + +export type UserUncheckedUpdateWithoutConversationsInput = { + id?: Prisma.StringFieldUpdateOperationsInput | string + createdAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string + walletAddress?: Prisma.StringFieldUpdateOperationsInput | string + reputation?: Prisma.IntFieldUpdateOperationsInput | number + role?: Prisma.EnumUserRoleFieldUpdateOperationsInput | $Enums.UserRole + worldcoinVerified?: Prisma.BoolFieldUpdateOperationsInput | boolean + worldcoinVerifiedAt?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null + wallets?: Prisma.WalletUncheckedUpdateManyWithoutUserNestedInput + sybilScores?: Prisma.SybilScoreUncheckedUpdateManyWithoutUserNestedInput + worldIdVerifications?: Prisma.WorldIdVerificationUncheckedUpdateManyWithoutUserNestedInput } @@ -724,12 +829,14 @@ export type UserCountOutputType = { wallets: number sybilScores: number worldIdVerifications: number + conversations: number } export type UserCountOutputTypeSelect = { wallets?: boolean | UserCountOutputTypeCountWalletsArgs sybilScores?: boolean | UserCountOutputTypeCountSybilScoresArgs worldIdVerifications?: boolean | UserCountOutputTypeCountWorldIdVerificationsArgs + conversations?: boolean | UserCountOutputTypeCountConversationsArgs } /** @@ -763,6 +870,13 @@ export type UserCountOutputTypeCountWorldIdVerificationsArgs = { + where?: Prisma.ConversationWhereInput +} + export type UserSelect = runtime.Types.Extensions.GetSelect<{ id?: boolean @@ -776,6 +890,7 @@ export type UserSelect sybilScores?: boolean | Prisma.User$sybilScoresArgs worldIdVerifications?: boolean | Prisma.User$worldIdVerificationsArgs + conversations?: boolean | Prisma.User$conversationsArgs _count?: boolean | Prisma.UserCountOutputTypeDefaultArgs }, ExtArgs["result"]["user"]> @@ -817,6 +932,7 @@ export type UserInclude sybilScores?: boolean | Prisma.User$sybilScoresArgs worldIdVerifications?: boolean | Prisma.User$worldIdVerificationsArgs + conversations?: boolean | Prisma.User$conversationsArgs _count?: boolean | Prisma.UserCountOutputTypeDefaultArgs } export type UserIncludeCreateManyAndReturn = {} @@ -828,6 +944,7 @@ export type $UserPayload[] sybilScores: Prisma.$SybilScorePayload[] worldIdVerifications: Prisma.$WorldIdVerificationPayload[] + conversations: Prisma.$ConversationPayload[] } scalars: runtime.Types.Extensions.GetPayloadResult<{ id: string @@ -1235,6 +1352,7 @@ export interface Prisma__UserClient = {}>(args?: Prisma.Subset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions> | Null> sybilScores = {}>(args?: Prisma.Subset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions> | Null> worldIdVerifications = {}>(args?: Prisma.Subset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions> | Null> + conversations = {}>(args?: Prisma.Subset>): Prisma.PrismaPromise, T, "findMany", GlobalOmitOptions> | Null> /** * Attaches callbacks for the resolution and/or rejection of the Promise. * @param onfulfilled The callback to execute when the Promise is resolved. @@ -1729,6 +1847,30 @@ export type User$worldIdVerificationsArgs = { + /** + * Select specific fields to fetch from the Conversation + */ + select?: Prisma.ConversationSelect | null + /** + * Omit specific fields from the Conversation + */ + omit?: Prisma.ConversationOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: Prisma.ConversationInclude | null + where?: Prisma.ConversationWhereInput + orderBy?: Prisma.ConversationOrderByWithRelationInput | Prisma.ConversationOrderByWithRelationInput[] + cursor?: Prisma.ConversationWhereUniqueInput + take?: number + skip?: number + distinct?: Prisma.ConversationScalarFieldEnum | Prisma.ConversationScalarFieldEnum[] +} + /** * User without action */ diff --git a/src/jobs/jobs.service.ts b/src/jobs/jobs.service.ts index 922aa9b..90c2bcb 100644 --- a/src/jobs/jobs.service.ts +++ b/src/jobs/jobs.service.ts @@ -353,6 +353,7 @@ export class JobsService implements OnModuleInit, OnModuleDestroy { return result; } + private async computeReputation(): Promise { this.logger.debug('computeReputation: starting'); const result: BatchResult = { processed: 0, updated: 0, errors: 0 }; diff --git a/src/modules/auth/guards/jwt-auth.guard.ts b/src/modules/auth/guards/jwt-auth.guard.ts deleted file mode 100644 index 18588a5..0000000 --- a/src/modules/auth/guards/jwt-auth.guard.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { AuthGuard } from '@nestjs/passport'; - -@Injectable() -export class JwtAuthGuard extends AuthGuard('jwt') {} \ No newline at end of file diff --git a/src/modules/identity/controllers/identity.controller.ts b/src/modules/identity/controllers/identity.controller.ts deleted file mode 100644 index 96b22d1..0000000 --- a/src/modules/identity/controllers/identity.controller.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { - Controller, - Post, - Param, - UseGuards, - ForbiddenException, -} from '@nestjs/common'; -import { JwtAuthGuard } from '../../auth/guards/jwt-auth.guard'; -import { IdentityService } from '../services/identity.service'; -import { CurrentUser } from '../../../common/decorators/current-user.decorator'; - -@Controller('identity/users') -export class IdentityController { - constructor(private readonly identityService: IdentityService) {} - - /** - * ๐Ÿ” SECURED: Only account owner can verify - */ - @Post(':id/verify-worldcoin') - @UseGuards(JwtAuthGuard) - async verifyWorldcoin( - @Param('id') id: string, - @CurrentUser() user: any, - ) { - // โœ… Ownership enforcement - if (!user || user.id !== id) { - throw new ForbiddenException( - 'You can only verify your own account', - ); - } - - const result = await this.identityService.verifyWorldcoin(id); - - return { - success: true, - data: result, - }; - } -} \ No newline at end of file diff --git a/src/modules/identity/services/identity.service.ts b/src/modules/identity/services/identity.service.ts deleted file mode 100644 index 6384dc7..0000000 --- a/src/modules/identity/services/identity.service.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { Injectable, NotFoundException, ConflictException } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; -import { UserEntity } from '../../users/entities/user.entity'; - -@Injectable() -export class IdentityService { - constructor( - @InjectRepository(UserEntity) - private readonly userRepo: Repository, - ) {} - - async verifyWorldcoin(userId: string) { - const user = await this.userRepo.findOne({ - where: { id: userId }, - }); - - if (!user) { - throw new NotFoundException('User not found'); - } - - if (user.worldcoinVerified) { - throw new ConflictException('User already verified'); - } - - // ๐Ÿ” In real implementation: - // - verify Worldcoin proof here (orb / zk proof) - // - validate signature / nullifier - - user.worldcoinVerified = true; - user.worldcoinVerifiedAt = new Date(); - - await this.userRepo.save(user); - - return { - userId, - verified: true, - verifiedAt: user.worldcoinVerifiedAt, - }; - } -} \ No newline at end of file diff --git a/src/modules/leaderboard/leaderboard.constants.ts b/src/modules/leaderboard/leaderboard.constants.ts deleted file mode 100644 index fd26460..0000000 --- a/src/modules/leaderboard/leaderboard.constants.ts +++ /dev/null @@ -1,6 +0,0 @@ -export const LEADERBOARD_KEYS = { - GLOBAL: 'leaderboard:global', - WEEKLY: 'leaderboard:weekly', -}; - -export const LEADERBOARD_REFRESH_CRON = '*/10 * * * *'; // every 10 minutes \ No newline at end of file diff --git a/src/modules/leaderboard/leaderboard.controller.ts b/src/modules/leaderboard/leaderboard.controller.ts deleted file mode 100644 index 5c65a5b..0000000 --- a/src/modules/leaderboard/leaderboard.controller.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Controller, Get, Query } from '@nestjs/common'; -import { ApiTags, ApiOperation, ApiResponse, ApiQuery } from '@nestjs/swagger'; -import { LeaderboardService } from './leaderboard.service'; - -@ApiTags('leaderboard') -@Controller('leaderboard') -export class LeaderboardController { - constructor( - private readonly leaderboardService: LeaderboardService, - ) {} - - @Get() - async getLeaderboard( - @Query('type') type: 'global' | 'weekly' = 'global', - ) { - return this.leaderboardService.getLeaderboard(type); - } -} \ No newline at end of file diff --git a/src/modules/leaderboard/leaderboard.module.ts b/src/modules/leaderboard/leaderboard.module.ts deleted file mode 100644 index a8cc7ed..0000000 --- a/src/modules/leaderboard/leaderboard.module.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Module } from '@nestjs/common'; -import { ScheduleModule } from '@nestjs/schedule'; -import { LeaderboardService } from './leaderboard.service'; -import { LeaderboardController } from './leaderboard.controller'; -import { LeaderboardRefreshJob } from './leaderboard.refresh.job'; -import { RedisProvider } from '../../redis/redis.provider'; - -@Module({ - imports: [ScheduleModule.forRoot()], - controllers: [LeaderboardController], - providers: [ - LeaderboardService, - LeaderboardRefreshJob, - RedisProvider, - ], - exports: [LeaderboardService], -}) -export class LeaderboardModule {} \ No newline at end of file diff --git a/src/modules/leaderboard/leaderboard.refresh.job.spec.ts b/src/modules/leaderboard/leaderboard.refresh.job.spec.ts deleted file mode 100644 index 375915a..0000000 --- a/src/modules/leaderboard/leaderboard.refresh.job.spec.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { LeaderboardRefreshJob } from './leaderboard.refresh.job'; - -describe('LeaderboardRefreshJob', () => { - it('clears leaderboards and calls bulkUpdateScores with users from prisma', async () => { - const mockLeaderboardService: any = { - clearLeaderboard: jest.fn().mockResolvedValue(undefined), - bulkUpdateScores: jest.fn().mockResolvedValue(undefined), - }; - - const mockPrisma: any = { - user: { - findMany: jest.fn().mockResolvedValue([ - { id: 'u1', reputation: 10 }, - { id: 'u2', reputation: 20 }, - ]), - }, - }; - - const job = new LeaderboardRefreshJob(mockLeaderboardService, mockPrisma); - - // call refresh - await job.refreshLeaderboard(); - - expect(mockLeaderboardService.clearLeaderboard).toHaveBeenCalledWith('global'); - expect(mockLeaderboardService.clearLeaderboard).toHaveBeenCalledWith('weekly'); - expect(mockLeaderboardService.bulkUpdateScores).toHaveBeenCalledWith( - [ - { id: 'u1', reputation: 10 }, - { id: 'u2', reputation: 20 }, - ], - ); - }); -}); diff --git a/src/modules/leaderboard/leaderboard.refresh.job.ts b/src/modules/leaderboard/leaderboard.refresh.job.ts deleted file mode 100644 index 726626e..0000000 --- a/src/modules/leaderboard/leaderboard.refresh.job.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { Cron } from '@nestjs/schedule'; -import { LeaderboardService } from './leaderboard.service'; -import { LEADERBOARD_REFRESH_CRON } from './leaderboard.constants'; -import { PrismaClient } from 'src/generated/client/client'; - -@Injectable() -export class LeaderboardRefreshJob { - private readonly logger = new Logger(LeaderboardRefreshJob.name); - - constructor( - private readonly leaderboardService: LeaderboardService, - private readonly prisma: PrismaClient, - ) {} - - @Cron(LEADERBOARD_REFRESH_CRON) - async refreshLeaderboard() { - this.logger.log('Refreshing leaderboards...'); - - const users = await this.fetchUsersFromDatabase(); - - if (users.length === 0) { - this.logger.warn('No users found, skipping leaderboard refresh.'); - return; - } - - // Clear old rankings - await this.leaderboardService.clearLeaderboard('global'); - await this.leaderboardService.clearLeaderboard('weekly'); - - // Rebuild rankings from real data using batched pipelining - await this.leaderboardService.bulkUpdateScores(users); - - this.logger.log(`Leaderboard refreshed with ${users.length} users.`); - } - - private async fetchUsersFromDatabase(): Promise<{ id: string; reputation: number }[]> { - return this.prisma.user.findMany({ - select: { - id: true, - reputation: true, - }, - orderBy: { - reputation: 'desc', - }, - }); - } -} \ No newline at end of file diff --git a/src/modules/leaderboard/leaderboard.service.ts b/src/modules/leaderboard/leaderboard.service.ts deleted file mode 100644 index a4f1ec9..0000000 --- a/src/modules/leaderboard/leaderboard.service.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { Inject, Injectable } from '@nestjs/common'; -import Redis from 'ioredis'; -import { LEADERBOARD_KEYS } from './leaderboard.constants'; - -@Injectable() -export class LeaderboardService { - constructor( - @Inject('REDIS_CLIENT') - private readonly redis: Redis, - ) { } - - // ๐Ÿ”น Add / update user score - async updateScore( - userId: string, - score: number, - ): Promise { - // Use a pipeline to reduce round trips for two ZADD operations - const pipeline = this.redis.pipeline(); - pipeline.zadd(LEADERBOARD_KEYS.GLOBAL, score, userId); - pipeline.zadd(LEADERBOARD_KEYS.WEEKLY, score, userId); - await pipeline.exec(); - } - - // Bulk update scores using pipelining in chunks to avoid many roundtrips - async bulkUpdateScores( - users: { id: string; reputation: number }[], - chunkSize = 500, - ): Promise { - for (let i = 0; i < users.length; i += chunkSize) { - const chunk = users.slice(i, i + chunkSize); - const pipeline = this.redis.pipeline(); - for (const u of chunk) { - pipeline.zadd(LEADERBOARD_KEYS.GLOBAL, u.reputation, u.id); - pipeline.zadd(LEADERBOARD_KEYS.WEEKLY, u.reputation, u.id); - } - await pipeline.exec(); - } - } - - // ๐Ÿ”น Get leaderboard - async getLeaderboard( - type: 'global' | 'weekly', - limit = 10, - ) { - const key = - type === 'global' - ? LEADERBOARD_KEYS.GLOBAL - : LEADERBOARD_KEYS.WEEKLY; - - const data = await this.redis.zrevrange( - key, - 0, - limit - 1, - 'WITHSCORES', - ); - - const formatted: { - userId: string; - score: number; - rank: number; - }[] = []; - - for (let i = 0; i < data.length; i += 2) { - formatted.push({ - userId: data[i], - score: Number(data[i + 1]), - rank: i / 2 + 1, - }); - } - - return formatted; - } - - // ๐Ÿ”น Clear leaderboard (used by refresh job) - async clearLeaderboard(type: 'global' | 'weekly') { - const key = - type === 'global' - ? LEADERBOARD_KEYS.GLOBAL - : LEADERBOARD_KEYS.WEEKLY; - - await this.redis.del(key); - } -} \ No newline at end of file diff --git a/src/modules/sybil/controllers/sybil-admin.controller.ts b/src/modules/sybil/controllers/sybil-admin.controller.ts deleted file mode 100644 index 26e3202..0000000 --- a/src/modules/sybil/controllers/sybil-admin.controller.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { - Controller, - Post, - UseGuards, - Body, -} from '@nestjs/common'; -import { SybilScoreService } from '../services/sybil-score.service'; -import { AuthGuard } from '../../auth/guards/auth.guard'; -import { RolesGuard } from '../../auth/guards/roles.guard'; -import { Roles } from '../../auth/decorators/roles.decorator'; - -@Controller('admin/sybil') -@UseGuards(AuthGuard, RolesGuard) -export class SybilAdminController { - constructor(private readonly sybilService: SybilScoreService) {} - - /** - * ๐Ÿ” Admin-only batch recalculation - */ - @Post('recalculate') - @Roles('admin', 'superadmin') - async recalculate(@Body() body: { - batchSize?: number; - concurrency?: number; - checkpointUserId?: string; - }) { - return this.sybilService.recalculateAllScores(body); - } -} \ No newline at end of file diff --git a/src/modules/sybil/services/sybil-score.service.ts b/src/modules/sybil/services/sybil-score.service.ts deleted file mode 100644 index 998f881..0000000 --- a/src/modules/sybil/services/sybil-score.service.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository, MoreThan } from 'typeorm'; -import pLimit from 'p-limit'; -import { UserEntity } from '../../users/entities/user.entity'; - -@Injectable() -export class SybilScoreService { - private readonly logger = new Logger(SybilScoreService.name); - - constructor( - @InjectRepository(UserEntity) - private readonly userRepo: Repository, - ) {} - - /** - * Recalculate all sybil scores in batches with concurrency control - */ - async recalculateAllScores(options?: { - batchSize?: number; - concurrency?: number; - checkpointUserId?: string; - }) { - const batchSize = options?.batchSize ?? 100; - const concurrency = options?.concurrency ?? 5; - - const limit = pLimit(concurrency); - - let lastId = options?.checkpointUserId ?? null; - let totalProcessed = 0; - - this.logger.log( - `Starting sybil score recalculation (batchSize=${batchSize}, concurrency=${concurrency})`, - ); - - while (true) { - const users = await this.userRepo.find({ - where: lastId ? { id: MoreThan(lastId) } : {}, - order: { id: 'ASC' }, - take: batchSize, - }); - - if (users.length === 0) break; - - this.logger.log( - `Processing batch starting from ID ${users[0].id} (size=${users.length})`, - ); - - await Promise.all( - users.map((user) => - limit(async () => { - try { - const score = await this.calculateScore(user); - await this.userRepo.update(user.id, { sybilScore: score }); - } catch (err) { - this.logger.error( - `Failed for user ${user.id}: ${err.message}`, - ); - } - }), - ), - ); - - totalProcessed += users.length; - lastId = users[users.length - 1].id; - - this.logger.log( - `Progress: ${totalProcessed} users processed (lastId=${lastId})`, - ); - } - - this.logger.log( - `โœ… Completed sybil recalculation. Total processed: ${totalProcessed}`, - ); - - return { - success: true, - totalProcessed, - lastCheckpoint: lastId, - }; - } - - /** - * Actual scoring logic (example) - */ - private async calculateScore(user: UserEntity): Promise { - let score = 0; - - if (user.isVerified) score += 50; - if (user.wallets?.length > 1) score -= 10; - if (user.createdAt) { - const ageDays = - (Date.now() - new Date(user.createdAt).getTime()) / 86400000; - if (ageDays < 7) score -= 20; - } - - return Math.max(0, Math.min(100, score)); - } -} \ No newline at end of file diff --git a/src/modules/sybil/tests/sybil-recalc.e2e-spec.ts b/src/modules/sybil/tests/sybil-recalc.e2e-spec.ts deleted file mode 100644 index 527b810..0000000 --- a/src/modules/sybil/tests/sybil-recalc.e2e-spec.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { test, expect } from '@playwright/test'; -import { TestClient } from '../utils/test-client'; - -test.describe('Sybil Batch Recalculation', () => { - test('โŒ non-admin cannot trigger recalculation', async () => { - const client = new TestClient(); - await client.init(); - - const { token } = await (await client.post('/auth/test-login', { - userId: 'user1', - })).json(); - - client.setToken(token); - - const res = await client.post('/admin/sybil/recalculate', {}); - - expect(res.status()).toBe(403); - }); - - test('โœ… admin can process batches safely', async () => { - const client = new TestClient(); - await client.init(); - - const { token } = await (await client.post('/auth/admin-login', {})).json(); - client.setToken(token); - - const res = await client.post('/admin/sybil/recalculate', { - batchSize: 50, - concurrency: 5, - }); - - expect(res.status()).toBe(200); - - const body = await res.json(); - - expect(body.totalProcessed).toBeGreaterThan(0); - }); -}); \ No newline at end of file diff --git a/src/modules/users/entities/user.entity.ts b/src/modules/users/entities/user.entity.ts deleted file mode 100644 index 2672156..0000000 --- a/src/modules/users/entities/user.entity.ts +++ /dev/null @@ -1,2 +0,0 @@ -// Re-export the canonical User entity so module-local imports keep working. -export { User as UserEntity } from '../../../entities/user.entity'; diff --git a/src/utils/confidence.ts b/src/utils/confidence.ts index 19fb060..0a0cc1d 100644 --- a/src/utils/confidence.ts +++ b/src/utils/confidence.ts @@ -1,6 +1,6 @@ import { MIN_AGGREGATION_CONFIDENCE, -} from '../constants/protocol'; +} from '../constant/protocol'; export function applyConfidenceFloor( confidence: number,