@theihtisham/ai-agent-starter-kit 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +33 -0
- package/Dockerfile +35 -0
- package/LICENSE +21 -0
- package/README.md +73 -0
- package/docker-compose.yml +28 -0
- package/next-env.d.ts +5 -0
- package/next.config.mjs +17 -0
- package/package.json +85 -0
- package/postcss.config.js +6 -0
- package/prisma/schema.prisma +157 -0
- package/prisma/seed.ts +46 -0
- package/src/app/(auth)/forgot-password/page.tsx +56 -0
- package/src/app/(auth)/layout.tsx +7 -0
- package/src/app/(auth)/login/page.tsx +83 -0
- package/src/app/(auth)/signup/page.tsx +108 -0
- package/src/app/(dashboard)/agents/[id]/edit/page.tsx +68 -0
- package/src/app/(dashboard)/agents/[id]/page.tsx +114 -0
- package/src/app/(dashboard)/agents/new/page.tsx +43 -0
- package/src/app/(dashboard)/agents/page.tsx +63 -0
- package/src/app/(dashboard)/api-keys/page.tsx +139 -0
- package/src/app/(dashboard)/dashboard/page.tsx +79 -0
- package/src/app/(dashboard)/layout.tsx +16 -0
- package/src/app/(dashboard)/settings/billing/page.tsx +59 -0
- package/src/app/(dashboard)/settings/page.tsx +45 -0
- package/src/app/(dashboard)/usage/page.tsx +46 -0
- package/src/app/api/agents/[id]/chat/route.ts +100 -0
- package/src/app/api/agents/[id]/chats/route.ts +36 -0
- package/src/app/api/agents/[id]/route.ts +97 -0
- package/src/app/api/agents/route.ts +84 -0
- package/src/app/api/api-keys/[id]/route.ts +25 -0
- package/src/app/api/api-keys/route.ts +72 -0
- package/src/app/api/auth/[...nextauth]/route.ts +5 -0
- package/src/app/api/auth/register/route.ts +53 -0
- package/src/app/api/health/route.ts +26 -0
- package/src/app/api/stripe/checkout/route.ts +37 -0
- package/src/app/api/stripe/plans/route.ts +16 -0
- package/src/app/api/stripe/portal/route.ts +29 -0
- package/src/app/api/stripe/webhook/route.ts +45 -0
- package/src/app/api/usage/route.ts +43 -0
- package/src/app/globals.css +59 -0
- package/src/app/layout.tsx +22 -0
- package/src/app/page.tsx +32 -0
- package/src/app/pricing/page.tsx +25 -0
- package/src/components/agents/agent-form.tsx +137 -0
- package/src/components/agents/model-selector.tsx +35 -0
- package/src/components/agents/tool-selector.tsx +48 -0
- package/src/components/auth-provider.tsx +17 -0
- package/src/components/billing/plan-badge.tsx +23 -0
- package/src/components/billing/pricing-table.tsx +95 -0
- package/src/components/billing/usage-meter.tsx +39 -0
- package/src/components/chat/chat-input.tsx +68 -0
- package/src/components/chat/chat-interface.tsx +152 -0
- package/src/components/chat/chat-message.tsx +50 -0
- package/src/components/chat/chat-sidebar.tsx +49 -0
- package/src/components/chat/code-block.tsx +38 -0
- package/src/components/chat/markdown-renderer.tsx +56 -0
- package/src/components/chat/streaming-text.tsx +46 -0
- package/src/components/dashboard/agent-card.tsx +52 -0
- package/src/components/dashboard/header.tsx +75 -0
- package/src/components/dashboard/sidebar.tsx +52 -0
- package/src/components/dashboard/stat-card.tsx +42 -0
- package/src/components/dashboard/usage-chart.tsx +42 -0
- package/src/components/landing/cta.tsx +30 -0
- package/src/components/landing/features.tsx +75 -0
- package/src/components/landing/hero.tsx +42 -0
- package/src/components/landing/pricing.tsx +28 -0
- package/src/components/ui/avatar.tsx +24 -0
- package/src/components/ui/badge.tsx +24 -0
- package/src/components/ui/button.tsx +39 -0
- package/src/components/ui/card.tsx +50 -0
- package/src/components/ui/dialog.tsx +73 -0
- package/src/components/ui/dropdown.tsx +77 -0
- package/src/components/ui/input.tsx +23 -0
- package/src/components/ui/skeleton.tsx +7 -0
- package/src/components/ui/switch.tsx +31 -0
- package/src/components/ui/table.tsx +48 -0
- package/src/components/ui/tabs.tsx +66 -0
- package/src/components/ui/textarea.tsx +20 -0
- package/src/hooks/use-agent.ts +44 -0
- package/src/hooks/use-streaming.ts +82 -0
- package/src/hooks/use-subscription.ts +40 -0
- package/src/hooks/use-usage.ts +43 -0
- package/src/hooks/use-user.ts +13 -0
- package/src/lib/agents/index.ts +60 -0
- package/src/lib/agents/memory/long-term.ts +241 -0
- package/src/lib/agents/memory/manager.ts +154 -0
- package/src/lib/agents/memory/short-term.ts +155 -0
- package/src/lib/agents/memory/types.ts +68 -0
- package/src/lib/agents/orchestration/debate.ts +170 -0
- package/src/lib/agents/orchestration/index.ts +103 -0
- package/src/lib/agents/orchestration/parallel.ts +143 -0
- package/src/lib/agents/orchestration/router.ts +199 -0
- package/src/lib/agents/orchestration/sequential.ts +127 -0
- package/src/lib/agents/orchestration/types.ts +68 -0
- package/src/lib/agents/tools/calculator.ts +131 -0
- package/src/lib/agents/tools/code-executor.ts +191 -0
- package/src/lib/agents/tools/file-reader.ts +129 -0
- package/src/lib/agents/tools/index.ts +48 -0
- package/src/lib/agents/tools/registry.ts +182 -0
- package/src/lib/agents/tools/web-search.ts +83 -0
- package/src/lib/ai/agent.ts +275 -0
- package/src/lib/ai/context.ts +68 -0
- package/src/lib/ai/memory.ts +98 -0
- package/src/lib/ai/models.ts +80 -0
- package/src/lib/ai/streaming.ts +80 -0
- package/src/lib/ai/tools.ts +149 -0
- package/src/lib/auth/middleware.ts +41 -0
- package/src/lib/auth/nextauth.ts +69 -0
- package/src/lib/db/client.ts +15 -0
- package/src/lib/rate-limit/limiter.ts +93 -0
- package/src/lib/rate-limit/rules.ts +38 -0
- package/src/lib/stripe/client.ts +25 -0
- package/src/lib/stripe/plans.ts +75 -0
- package/src/lib/stripe/usage.ts +123 -0
- package/src/lib/stripe/webhooks.ts +96 -0
- package/src/lib/utils/api-response.ts +85 -0
- package/src/lib/utils/errors.ts +73 -0
- package/src/lib/utils/helpers.ts +50 -0
- package/src/lib/utils/id.ts +21 -0
- package/src/lib/utils/logger.ts +38 -0
- package/src/lib/utils/validation.ts +44 -0
- package/src/middleware.ts +13 -0
- package/src/types/agent.ts +31 -0
- package/src/types/api.ts +38 -0
- package/src/types/billing.ts +35 -0
- package/src/types/chat.ts +30 -0
- package/src/types/next-auth.d.ts +19 -0
- package/tailwind.config.ts +72 -0
- package/tsconfig.json +28 -0
- package/tsconfig.tsbuildinfo +1 -0
package/.env.example
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Database
|
|
2
|
+
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/agentkit?schema=public"
|
|
3
|
+
|
|
4
|
+
# NextAuth
|
|
5
|
+
NEXTAUTH_URL="http://localhost:3000"
|
|
6
|
+
NEXTAUTH_SECRET="your-nextauth-secret-change-this-in-production"
|
|
7
|
+
|
|
8
|
+
# OAuth Providers (at least one required)
|
|
9
|
+
GOOGLE_CLIENT_ID=""
|
|
10
|
+
GOOGLE_CLIENT_SECRET=""
|
|
11
|
+
GITHUB_CLIENT_ID=""
|
|
12
|
+
GITHUB_CLIENT_SECRET=""
|
|
13
|
+
|
|
14
|
+
# Email Provider (Resend — for magic link auth)
|
|
15
|
+
RESEND_API_KEY=""
|
|
16
|
+
EMAIL_FROM="noreply@yourdomain.com"
|
|
17
|
+
|
|
18
|
+
# AI Providers (at least one required)
|
|
19
|
+
OPENAI_API_KEY=""
|
|
20
|
+
ANTHROPIC_API_KEY=""
|
|
21
|
+
GOOGLE_AI_API_KEY=""
|
|
22
|
+
|
|
23
|
+
# Stripe (for billing)
|
|
24
|
+
STRIPE_SECRET_KEY=""
|
|
25
|
+
STRIPE_WEBHOOK_SECRET=""
|
|
26
|
+
STRIPE_PRO_PRICE_ID=""
|
|
27
|
+
STRIPE_TEAM_PRICE_ID=""
|
|
28
|
+
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=""
|
|
29
|
+
|
|
30
|
+
# Optional
|
|
31
|
+
REDIS_URL="redis://localhost:6379"
|
|
32
|
+
NEXT_PUBLIC_APP_URL="http://localhost:3000"
|
|
33
|
+
NEXT_PUBLIC_APP_NAME="AI Agent Kit"
|
package/Dockerfile
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
FROM node:20-alpine AS base
|
|
2
|
+
|
|
3
|
+
# Install dependencies only when needed
|
|
4
|
+
FROM base AS deps
|
|
5
|
+
RUN apk add --no-cache libc6-compat
|
|
6
|
+
WORKDIR /app
|
|
7
|
+
COPY package.json package-lock.json* ./
|
|
8
|
+
RUN npm ci
|
|
9
|
+
|
|
10
|
+
# Build the application
|
|
11
|
+
FROM base AS builder
|
|
12
|
+
WORKDIR /app
|
|
13
|
+
COPY --from=deps /app/node_modules ./node_modules
|
|
14
|
+
COPY . .
|
|
15
|
+
RUN npx prisma generate
|
|
16
|
+
RUN npm run build
|
|
17
|
+
|
|
18
|
+
# Production image
|
|
19
|
+
FROM base AS runner
|
|
20
|
+
WORKDIR /app
|
|
21
|
+
ENV NODE_ENV=production
|
|
22
|
+
|
|
23
|
+
RUN addgroup --system --gid 1001 nodejs
|
|
24
|
+
RUN adduser --system --uid 1001 nextjs
|
|
25
|
+
|
|
26
|
+
COPY --from=builder /app/public ./public
|
|
27
|
+
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
|
28
|
+
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
|
29
|
+
|
|
30
|
+
USER nextjs
|
|
31
|
+
EXPOSE 3000
|
|
32
|
+
ENV PORT=3000
|
|
33
|
+
ENV HOSTNAME="0.0.0.0"
|
|
34
|
+
|
|
35
|
+
CMD ["node", "server.js"]
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Ai Agent Starter Kit
|
|
2
|
+
|
|
3
|
+
Production-ready AI Agent framework with Next.js, Stripe billing, auth, and one-click deploy
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @theihtisham/ai-agent-starter-kit
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { } from '@theihtisham/ai-agent-starter-kit';
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Features
|
|
18
|
+
|
|
19
|
+
- Written in TypeScript with full type definitions
|
|
20
|
+
- Zero external dependencies (minimal footprint)
|
|
21
|
+
- Event-driven architecture
|
|
22
|
+
- Comprehensive test suite
|
|
23
|
+
|
|
24
|
+
## API
|
|
25
|
+
|
|
26
|
+
### Quick Start
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { } from '@theihtisham/ai-agent-starter-kit';
|
|
30
|
+
|
|
31
|
+
// Initialize and use the package
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Configuration
|
|
35
|
+
|
|
36
|
+
Configuration options and their defaults:
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
const config = {
|
|
40
|
+
// Add configuration options here
|
|
41
|
+
};
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Examples
|
|
45
|
+
|
|
46
|
+
See the `tests/` directory for usage examples.
|
|
47
|
+
|
|
48
|
+
## Development
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# Install dependencies
|
|
52
|
+
npm install
|
|
53
|
+
|
|
54
|
+
# Build
|
|
55
|
+
npm run build
|
|
56
|
+
|
|
57
|
+
# Run tests
|
|
58
|
+
npm test
|
|
59
|
+
|
|
60
|
+
# Lint
|
|
61
|
+
npm run lint
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## License
|
|
65
|
+
|
|
66
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
67
|
+
|
|
68
|
+
## Author
|
|
69
|
+
|
|
70
|
+
**ihtisham**
|
|
71
|
+
|
|
72
|
+
- GitHub: [https://github.com/ihtisham](https://github.com/ihtisham)
|
|
73
|
+
- npm: [@theihtisham](https://www.npmjs.com/~theihtisham)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
version: '3.8'
|
|
2
|
+
|
|
3
|
+
services:
|
|
4
|
+
postgres:
|
|
5
|
+
image: postgres:16-alpine
|
|
6
|
+
container_name: agentkit-postgres
|
|
7
|
+
restart: unless-stopped
|
|
8
|
+
environment:
|
|
9
|
+
POSTGRES_USER: postgres
|
|
10
|
+
POSTGRES_PASSWORD: postgres
|
|
11
|
+
POSTGRES_DB: agentkit
|
|
12
|
+
ports:
|
|
13
|
+
- '5432:5432'
|
|
14
|
+
volumes:
|
|
15
|
+
- postgres_data:/var/lib/postgresql/data
|
|
16
|
+
|
|
17
|
+
redis:
|
|
18
|
+
image: redis:7-alpine
|
|
19
|
+
container_name: agentkit-redis
|
|
20
|
+
restart: unless-stopped
|
|
21
|
+
ports:
|
|
22
|
+
- '6379:6379'
|
|
23
|
+
volumes:
|
|
24
|
+
- redis_data:/data
|
|
25
|
+
|
|
26
|
+
volumes:
|
|
27
|
+
postgres_data:
|
|
28
|
+
redis_data:
|
package/next-env.d.ts
ADDED
package/next.config.mjs
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** @type {import('next').NextConfig} */
|
|
2
|
+
const nextConfig = {
|
|
3
|
+
experimental: {
|
|
4
|
+
serverActions: {
|
|
5
|
+
bodySizeLimit: '2mb',
|
|
6
|
+
},
|
|
7
|
+
},
|
|
8
|
+
images: {
|
|
9
|
+
remotePatterns: [
|
|
10
|
+
{ protocol: 'https', hostname: 'lh3.googleusercontent.com' },
|
|
11
|
+
{ protocol: 'https', hostname: 'avatars.githubusercontent.com' },
|
|
12
|
+
{ protocol: 'https', hostname: '**.stripe.com' },
|
|
13
|
+
],
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export default nextConfig;
|
package/package.json
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@theihtisham/ai-agent-starter-kit",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Production-ready AI Agent framework with Next.js, Stripe billing, auth, and one-click deploy",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "next dev",
|
|
7
|
+
"build": "next build",
|
|
8
|
+
"start": "next start",
|
|
9
|
+
"lint": "next lint",
|
|
10
|
+
"db:generate": "prisma generate",
|
|
11
|
+
"db:push": "prisma db push",
|
|
12
|
+
"db:migrate": "prisma migrate dev",
|
|
13
|
+
"db:seed": "tsx prisma/seed.ts",
|
|
14
|
+
"db:studio": "prisma studio",
|
|
15
|
+
"postinstall": "prisma generate",
|
|
16
|
+
"type-check": "tsc --noEmit",
|
|
17
|
+
"test": "jest"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@next-auth/prisma-adapter": "^1.0.7",
|
|
21
|
+
"@prisma/client": "^5.20.0",
|
|
22
|
+
"@stripe/stripe-js": "^4.5.0",
|
|
23
|
+
"bcryptjs": "^2.4.3",
|
|
24
|
+
"clsx": "^2.1.1",
|
|
25
|
+
"date-fns": "^4.1.0",
|
|
26
|
+
"lucide-react": "^0.451.0",
|
|
27
|
+
"nanoid": "^5.0.7",
|
|
28
|
+
"next": "^14.2.15",
|
|
29
|
+
"next-auth": "^4.24.8",
|
|
30
|
+
"next-themes": "^0.3.0",
|
|
31
|
+
"openai": "^4.67.0",
|
|
32
|
+
"react": "^18.3.1",
|
|
33
|
+
"react-dom": "^18.3.1",
|
|
34
|
+
"react-hot-toast": "^2.4.1",
|
|
35
|
+
"react-markdown": "^9.0.1",
|
|
36
|
+
"react-syntax-highlighter": "^15.5.0",
|
|
37
|
+
"recharts": "^3.8.1",
|
|
38
|
+
"redis": "^5.11.0",
|
|
39
|
+
"remark-gfm": "^4.0.0",
|
|
40
|
+
"resend": "^4.0.0",
|
|
41
|
+
"stripe": "^17.0.0",
|
|
42
|
+
"tailwind-merge": "^2.5.3",
|
|
43
|
+
"zod": "^3.23.8"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@types/bcryptjs": "^2.4.6",
|
|
47
|
+
"@types/node": "^22.7.9",
|
|
48
|
+
"@types/react": "^18.3.12",
|
|
49
|
+
"@types/react-dom": "^18.3.1",
|
|
50
|
+
"@types/react-syntax-highlighter": "^15.5.13",
|
|
51
|
+
"autoprefixer": "^10.4.20",
|
|
52
|
+
"eslint": "^8.57.1",
|
|
53
|
+
"eslint-config-next": "^14.2.15",
|
|
54
|
+
"postcss": "^8.4.47",
|
|
55
|
+
"prisma": "^5.20.0",
|
|
56
|
+
"tailwindcss": "^3.4.14",
|
|
57
|
+
"tsx": "^4.19.1",
|
|
58
|
+
"typescript": "^5.6.3",
|
|
59
|
+
"jest": "^29.7.0",
|
|
60
|
+
"ts-jest": "^29.1.0",
|
|
61
|
+
"@types/jest": "^29.5.0"
|
|
62
|
+
},
|
|
63
|
+
"license": "MIT",
|
|
64
|
+
"publishConfig": {
|
|
65
|
+
"access": "public"
|
|
66
|
+
},
|
|
67
|
+
"repository": {
|
|
68
|
+
"type": "git",
|
|
69
|
+
"url": "git+https://github.com/theihtisham/ai-agent-starter-kit.git"
|
|
70
|
+
},
|
|
71
|
+
"keywords": [
|
|
72
|
+
"ai",
|
|
73
|
+
"agent",
|
|
74
|
+
"nextjs",
|
|
75
|
+
"starter-kit",
|
|
76
|
+
"open-source",
|
|
77
|
+
"stripe",
|
|
78
|
+
"prisma"
|
|
79
|
+
],
|
|
80
|
+
"author": "ihtisham",
|
|
81
|
+
"bugs": {
|
|
82
|
+
"url": "https://github.com/theihtisham/ai-agent-starter-kit/issues"
|
|
83
|
+
},
|
|
84
|
+
"homepage": "https://github.com/theihtisham/ai-agent-starter-kit#readme"
|
|
85
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
// This is your Prisma schema file,
|
|
2
|
+
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
|
3
|
+
|
|
4
|
+
generator client {
|
|
5
|
+
provider = "prisma-client-js"
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
datasource db {
|
|
9
|
+
provider = "postgresql"
|
|
10
|
+
url = env("DATABASE_URL")
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
model User {
|
|
14
|
+
id String @id @default(cuid())
|
|
15
|
+
name String?
|
|
16
|
+
email String? @unique
|
|
17
|
+
emailVerified DateTime?
|
|
18
|
+
image String?
|
|
19
|
+
accounts Account[]
|
|
20
|
+
sessions Session[]
|
|
21
|
+
agents Agent[]
|
|
22
|
+
apiKeys ApiKey[]
|
|
23
|
+
subscription Subscription?
|
|
24
|
+
usage Usage[]
|
|
25
|
+
createdAt DateTime @default(now())
|
|
26
|
+
updatedAt DateTime @updatedAt
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
model Account {
|
|
30
|
+
id String @id @default(cuid())
|
|
31
|
+
userId String
|
|
32
|
+
type String
|
|
33
|
+
provider String
|
|
34
|
+
providerAccountId String
|
|
35
|
+
refresh_token String? @db.Text
|
|
36
|
+
access_token String? @db.Text
|
|
37
|
+
expires_at Int?
|
|
38
|
+
token_type String?
|
|
39
|
+
scope String?
|
|
40
|
+
id_token String? @db.Text
|
|
41
|
+
session_state String?
|
|
42
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
43
|
+
|
|
44
|
+
@@unique([provider, providerAccountId])
|
|
45
|
+
@@index([userId])
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
model Session {
|
|
49
|
+
id String @id @default(cuid())
|
|
50
|
+
sessionToken String @unique
|
|
51
|
+
userId String
|
|
52
|
+
expires DateTime
|
|
53
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
54
|
+
|
|
55
|
+
@@index([userId])
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
model VerificationToken {
|
|
59
|
+
identifier String
|
|
60
|
+
token String @unique
|
|
61
|
+
expires DateTime
|
|
62
|
+
|
|
63
|
+
@@unique([identifier, token])
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
model Agent {
|
|
67
|
+
id String @id @default(cuid())
|
|
68
|
+
userId String
|
|
69
|
+
name String
|
|
70
|
+
description String?
|
|
71
|
+
systemPrompt String @db.Text
|
|
72
|
+
model String @default("gpt-4o")
|
|
73
|
+
temperature Float @default(0.7)
|
|
74
|
+
maxTokens Int @default(4096)
|
|
75
|
+
tools Json @default("[]")
|
|
76
|
+
isPublic Boolean @default(false)
|
|
77
|
+
chats Chat[]
|
|
78
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
79
|
+
createdAt DateTime @default(now())
|
|
80
|
+
updatedAt DateTime @updatedAt
|
|
81
|
+
|
|
82
|
+
@@index([userId])
|
|
83
|
+
@@index([isPublic])
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
model Chat {
|
|
87
|
+
id String @id @default(cuid())
|
|
88
|
+
agentId String
|
|
89
|
+
title String @default("New Chat")
|
|
90
|
+
messages Message[]
|
|
91
|
+
agent Agent @relation(fields: [agentId], references: [id], onDelete: Cascade)
|
|
92
|
+
createdAt DateTime @default(now())
|
|
93
|
+
updatedAt DateTime @updatedAt
|
|
94
|
+
|
|
95
|
+
@@index([agentId])
|
|
96
|
+
@@index([createdAt])
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
model Message {
|
|
100
|
+
id String @id @default(cuid())
|
|
101
|
+
chatId String
|
|
102
|
+
role String // "user" | "assistant" | "system" | "tool"
|
|
103
|
+
content String @db.Text
|
|
104
|
+
tokens Int?
|
|
105
|
+
metadata Json?
|
|
106
|
+
chat Chat @relation(fields: [chatId], references: [id], onDelete: Cascade)
|
|
107
|
+
createdAt DateTime @default(now())
|
|
108
|
+
|
|
109
|
+
@@index([chatId])
|
|
110
|
+
@@index([createdAt])
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
model ApiKey {
|
|
114
|
+
id String @id @default(cuid())
|
|
115
|
+
userId String
|
|
116
|
+
name String
|
|
117
|
+
key String @unique
|
|
118
|
+
prefix String // First 8 chars for display
|
|
119
|
+
lastUsed DateTime?
|
|
120
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
121
|
+
createdAt DateTime @default(now())
|
|
122
|
+
|
|
123
|
+
@@index([userId])
|
|
124
|
+
@@index([key])
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
model Subscription {
|
|
128
|
+
id String @id @default(cuid())
|
|
129
|
+
userId String @unique
|
|
130
|
+
stripeCustomerId String @unique
|
|
131
|
+
stripePriceId String
|
|
132
|
+
stripeSubscriptionId String @unique
|
|
133
|
+
status String // active, past_due, canceled, trialing, incomplete
|
|
134
|
+
currentPeriodStart DateTime
|
|
135
|
+
currentPeriodEnd DateTime
|
|
136
|
+
cancelAtPeriodEnd Boolean @default(false)
|
|
137
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
138
|
+
createdAt DateTime @default(now())
|
|
139
|
+
updatedAt DateTime @updatedAt
|
|
140
|
+
|
|
141
|
+
@@index([stripeCustomerId])
|
|
142
|
+
@@index([status])
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
model Usage {
|
|
146
|
+
id String @id @default(cuid())
|
|
147
|
+
userId String
|
|
148
|
+
agentId String?
|
|
149
|
+
type String // "message", "tool_call", "token_input", "token_output"
|
|
150
|
+
quantity Int
|
|
151
|
+
metadata Json?
|
|
152
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
153
|
+
createdAt DateTime @default(now())
|
|
154
|
+
|
|
155
|
+
@@index([userId, createdAt])
|
|
156
|
+
@@index([userId, type, createdAt])
|
|
157
|
+
}
|
package/prisma/seed.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { PrismaClient } from '@prisma/client';
|
|
2
|
+
|
|
3
|
+
const prisma = new PrismaClient();
|
|
4
|
+
|
|
5
|
+
async function main() {
|
|
6
|
+
console.log('Seeding database...');
|
|
7
|
+
|
|
8
|
+
// Create a demo user
|
|
9
|
+
const user = await prisma.user.upsert({
|
|
10
|
+
where: { email: 'demo@agentkit.dev' },
|
|
11
|
+
update: {},
|
|
12
|
+
create: {
|
|
13
|
+
email: 'demo@agentkit.dev',
|
|
14
|
+
name: 'Demo User',
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
// Create a demo agent
|
|
19
|
+
await prisma.agent.upsert({
|
|
20
|
+
where: { id: 'demo-agent' },
|
|
21
|
+
update: {},
|
|
22
|
+
create: {
|
|
23
|
+
id: 'demo-agent',
|
|
24
|
+
userId: user.id,
|
|
25
|
+
name: 'Demo Assistant',
|
|
26
|
+
description: 'A helpful AI assistant to get you started',
|
|
27
|
+
systemPrompt: 'You are a helpful AI assistant. Be concise, accurate, and friendly.',
|
|
28
|
+
model: 'gpt-4o-mini',
|
|
29
|
+
temperature: 0.7,
|
|
30
|
+
maxTokens: 4096,
|
|
31
|
+
tools: ['web_search', 'calculator', 'json_parser'],
|
|
32
|
+
isPublic: true,
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
console.log('Seed complete!');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
main()
|
|
40
|
+
.catch((e) => {
|
|
41
|
+
console.error(e);
|
|
42
|
+
process.exit(1);
|
|
43
|
+
})
|
|
44
|
+
.finally(async () => {
|
|
45
|
+
await prisma.$disconnect();
|
|
46
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import Link from 'next/link';
|
|
5
|
+
import { Button } from '@/components/ui/button';
|
|
6
|
+
import { Input } from '@/components/ui/input';
|
|
7
|
+
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
|
|
8
|
+
|
|
9
|
+
export default function ForgotPasswordPage() {
|
|
10
|
+
const [email, setEmail] = useState('');
|
|
11
|
+
const [sent, setSent] = useState(false);
|
|
12
|
+
const [loading, setLoading] = useState(false);
|
|
13
|
+
|
|
14
|
+
const handleSubmit = async (e: React.FormEvent) => {
|
|
15
|
+
e.preventDefault();
|
|
16
|
+
setLoading(true);
|
|
17
|
+
// Email-based password reset via NextAuth email provider
|
|
18
|
+
// In production, call your API endpoint
|
|
19
|
+
setSent(true);
|
|
20
|
+
setLoading(false);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<Card>
|
|
25
|
+
<CardHeader className="text-center">
|
|
26
|
+
<CardTitle className="text-2xl">Reset password</CardTitle>
|
|
27
|
+
<CardDescription>Enter your email to receive a reset link</CardDescription>
|
|
28
|
+
</CardHeader>
|
|
29
|
+
<CardContent>
|
|
30
|
+
{sent ? (
|
|
31
|
+
<div className="text-center space-y-4">
|
|
32
|
+
<p className="text-sm text-muted-foreground">
|
|
33
|
+
If an account exists with that email, you'll receive a reset link shortly.
|
|
34
|
+
</p>
|
|
35
|
+
<Link href="/login">
|
|
36
|
+
<Button variant="outline">Back to login</Button>
|
|
37
|
+
</Link>
|
|
38
|
+
</div>
|
|
39
|
+
) : (
|
|
40
|
+
<form onSubmit={handleSubmit} className="space-y-4">
|
|
41
|
+
<div className="space-y-2">
|
|
42
|
+
<label className="text-sm font-medium">Email</label>
|
|
43
|
+
<Input type="email" value={email} onChange={(e) => setEmail(e.target.value)} required />
|
|
44
|
+
</div>
|
|
45
|
+
<Button type="submit" className="w-full" disabled={loading}>
|
|
46
|
+
{loading ? 'Sending...' : 'Send reset link'}
|
|
47
|
+
</Button>
|
|
48
|
+
<div className="text-center">
|
|
49
|
+
<Link href="/login" className="text-sm text-primary hover:underline">Back to login</Link>
|
|
50
|
+
</div>
|
|
51
|
+
</form>
|
|
52
|
+
)}
|
|
53
|
+
</CardContent>
|
|
54
|
+
</Card>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { signIn } from 'next-auth/react';
|
|
5
|
+
import { useRouter } from 'next/navigation';
|
|
6
|
+
import Link from 'next/link';
|
|
7
|
+
import { Button } from '@/components/ui/button';
|
|
8
|
+
import { Input } from '@/components/ui/input';
|
|
9
|
+
import { Card, CardContent, CardHeader, CardTitle, CardDescription, CardFooter } from '@/components/ui/card';
|
|
10
|
+
|
|
11
|
+
export default function LoginPage() {
|
|
12
|
+
const router = useRouter();
|
|
13
|
+
const [email, setEmail] = useState('');
|
|
14
|
+
const [password, setPassword] = useState('');
|
|
15
|
+
const [error, setError] = useState('');
|
|
16
|
+
const [loading, setLoading] = useState(false);
|
|
17
|
+
|
|
18
|
+
const handleSubmit = async (e: React.FormEvent) => {
|
|
19
|
+
e.preventDefault();
|
|
20
|
+
setLoading(true);
|
|
21
|
+
setError('');
|
|
22
|
+
|
|
23
|
+
const result = await signIn('credentials', {
|
|
24
|
+
email,
|
|
25
|
+
password,
|
|
26
|
+
redirect: false,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
if (result?.error) {
|
|
30
|
+
setError('Invalid credentials');
|
|
31
|
+
setLoading(false);
|
|
32
|
+
} else {
|
|
33
|
+
router.push('/dashboard');
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<Card>
|
|
39
|
+
<CardHeader className="text-center">
|
|
40
|
+
<CardTitle className="text-2xl">Welcome back</CardTitle>
|
|
41
|
+
<CardDescription>Sign in to your AgentKit account</CardDescription>
|
|
42
|
+
</CardHeader>
|
|
43
|
+
<CardContent>
|
|
44
|
+
<div className="grid gap-4">
|
|
45
|
+
<div className="grid grid-cols-2 gap-3">
|
|
46
|
+
<Button variant="outline" onClick={() => signIn('google', { callbackUrl: '/dashboard' })}>
|
|
47
|
+
Google
|
|
48
|
+
</Button>
|
|
49
|
+
<Button variant="outline" onClick={() => signIn('github', { callbackUrl: '/dashboard' })}>
|
|
50
|
+
GitHub
|
|
51
|
+
</Button>
|
|
52
|
+
</div>
|
|
53
|
+
<div className="relative">
|
|
54
|
+
<div className="absolute inset-0 flex items-center"><span className="w-full border-t" /></div>
|
|
55
|
+
<div className="relative flex justify-center text-xs uppercase">
|
|
56
|
+
<span className="bg-card px-2 text-muted-foreground">or continue with email</span>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
<form onSubmit={handleSubmit} className="space-y-4">
|
|
60
|
+
<div className="space-y-2">
|
|
61
|
+
<label className="text-sm font-medium">Email</label>
|
|
62
|
+
<Input type="email" value={email} onChange={(e) => setEmail(e.target.value)} required />
|
|
63
|
+
</div>
|
|
64
|
+
<div className="space-y-2">
|
|
65
|
+
<label className="text-sm font-medium">Password</label>
|
|
66
|
+
<Input type="password" value={password} onChange={(e) => setPassword(e.target.value)} required />
|
|
67
|
+
</div>
|
|
68
|
+
{error && <p className="text-sm text-destructive">{error}</p>}
|
|
69
|
+
<Button type="submit" className="w-full" disabled={loading}>
|
|
70
|
+
{loading ? 'Signing in...' : 'Sign in'}
|
|
71
|
+
</Button>
|
|
72
|
+
</form>
|
|
73
|
+
</div>
|
|
74
|
+
</CardContent>
|
|
75
|
+
<CardFooter className="justify-center">
|
|
76
|
+
<p className="text-sm text-muted-foreground">
|
|
77
|
+
Don't have an account?{' '}
|
|
78
|
+
<Link href="/signup" className="text-primary hover:underline">Sign up</Link>
|
|
79
|
+
</p>
|
|
80
|
+
</CardFooter>
|
|
81
|
+
</Card>
|
|
82
|
+
);
|
|
83
|
+
}
|