diff --git a/chat-agent/dev/.env.example b/chat-agent/dev/.env.example new file mode 100644 index 00000000..f914770b --- /dev/null +++ b/chat-agent/dev/.env.example @@ -0,0 +1,13 @@ +# MongoDB connection string. Local dev defaults to +# mongodb://localhost:27017/chat-agent-dev when unset. For Vercel deployments +# point this at a MongoDB Atlas cluster (SRV URI). +DATABASE_URI=mongodb://127.0.0.1/chat-agent-dev + +# Secret used to sign Payload tokens. Generate with `openssl rand -hex 32`. +PAYLOAD_SECRET=YOUR_SECRET_HERE + +# Provider keys for the chat agent. Only the providers you actually use need +# to be set — resolveModel in payload.config.ts will throw a clear error if a +# selected model references a missing key. +ANTHROPIC_API_KEY= +OPENAI_API_KEY= diff --git a/chat-agent/dev/package.json b/chat-agent/dev/package.json index 06872384..3549ef7f 100644 --- a/chat-agent/dev/package.json +++ b/chat-agent/dev/package.json @@ -23,6 +23,7 @@ "@payloadcms/next": "^3.83.0", "@payloadcms/richtext-lexical": "^3.83.0", "@payloadcms/ui": "^3.83.0", + "@vercel/functions": "^3.1.5", "ai": "^6.0.164", "next": "15.4.11", "payload": "^3.83.0", diff --git a/chat-agent/dev/src/payload.config.ts b/chat-agent/dev/src/payload.config.ts index da88b2ff..be444fdc 100644 --- a/chat-agent/dev/src/payload.config.ts +++ b/chat-agent/dev/src/payload.config.ts @@ -16,6 +16,7 @@ import { UnorderedListFeature, UploadFeature, } from '@payloadcms/richtext-lexical' +import { attachDatabasePool } from '@vercel/functions' import path from 'path' import { buildConfig } from 'payload' import { fileURLToPath } from 'url' @@ -321,6 +322,20 @@ export default buildConfig({ ], db: mongooseAdapter({ url: process.env.DATABASE_URI || 'mongodb://localhost:27017/chat-agent-dev', + connectOptions: { + // Close sockets quickly so Fluid Compute can drain the pool between + // invocations instead of keeping idle Atlas connections open. + maxIdleTimeMS: 5_000, + maxPoolSize: 10, + }, + // On Vercel Fluid Compute, hand the underlying MongoClient to + // @vercel/functions so idle connections are released when the function + // suspends. Guarded by VERCEL so local dev/tests aren't affected. + afterOpenConnection: (adapter) => { + if (process.env.VERCEL) { + attachDatabasePool(adapter.connection.getClient()) + } + }, }), editor: lexicalEditor(), endpoints: rootEndpoints, diff --git a/chat-agent/dev/vercel.json b/chat-agent/dev/vercel.json new file mode 100644 index 00000000..8f65d6c1 --- /dev/null +++ b/chat-agent/dev/vercel.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://openapi.vercel.sh/vercel.json", + "framework": "nextjs", + "installCommand": "cd .. && pnpm install --frozen-lockfile", + "buildCommand": "pnpm build", + "outputDirectory": ".next", + "functions": { + "src/app/(payload)/api/[...slug]/route.ts": { + "maxDuration": 300 + } + } +} diff --git a/chat-agent/pnpm-lock.yaml b/chat-agent/pnpm-lock.yaml index 6cbbf508..a2dbe209 100644 --- a/chat-agent/pnpm-lock.yaml +++ b/chat-agent/pnpm-lock.yaml @@ -108,6 +108,9 @@ importers: '@payloadcms/ui': specifier: ^3.83.0 version: 3.83.0(@types/react@19.2.14)(monaco-editor@0.55.1)(next@15.4.11(@opentelemetry/api@1.9.0)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(sass@1.77.4))(payload@3.83.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(typescript@5.9.3) + '@vercel/functions': + specifier: ^3.1.5 + version: 3.4.3 ai: specifier: ^6.0.164 version: 6.0.164(zod@4.3.6) @@ -1651,10 +1654,23 @@ packages: '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + '@vercel/functions@3.4.3': + resolution: {integrity: sha512-kA14KIUVgAY6VXbhZ5jjY+s0883cV3cZqIU3WhrSRxuJ9KvxatMjtmzl0K23HK59oOUjYl7HaE/eYMmhmqpZzw==} + engines: {node: '>= 20'} + peerDependencies: + '@aws-sdk/credential-provider-web-identity': '*' + peerDependenciesMeta: + '@aws-sdk/credential-provider-web-identity': + optional: true + '@vercel/oidc@3.1.0': resolution: {integrity: sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w==} engines: {node: '>= 20'} + '@vercel/oidc@3.2.0': + resolution: {integrity: sha512-UycprH3T6n3jH0k44NHMa7pnFHGu/N05MjojYr+Mc6I7obkoLIJujSWwin1pCvdy/eOxrI/l3uDLQsmcrOb4ug==} + engines: {node: '>= 20'} + '@vitest/expect@4.1.4': resolution: {integrity: sha512-iPBpra+VDuXmBFI3FMKHSFXp3Gx5HfmSCE8X67Dn+bwephCnQCaB7qWK2ldHa+8ncN8hJU8VTMcxjPpyMkUjww==} @@ -6253,8 +6269,14 @@ snapshots: '@ungap/structured-clone@1.3.0': {} + '@vercel/functions@3.4.3': + dependencies: + '@vercel/oidc': 3.2.0 + '@vercel/oidc@3.1.0': {} + '@vercel/oidc@3.2.0': {} + '@vitest/expect@4.1.4': dependencies: '@standard-schema/spec': 1.1.0