create-chaaskit 0.1.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/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +25 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/add-infra.d.ts +6 -0
- package/dist/commands/add-infra.d.ts.map +1 -0
- package/dist/commands/add-infra.js +160 -0
- package/dist/commands/add-infra.js.map +1 -0
- package/dist/commands/build.d.ts +2 -0
- package/dist/commands/build.d.ts.map +1 -0
- package/dist/commands/build.js +63 -0
- package/dist/commands/build.js.map +1 -0
- package/dist/commands/db-sync.d.ts +13 -0
- package/dist/commands/db-sync.d.ts.map +1 -0
- package/dist/commands/db-sync.js +108 -0
- package/dist/commands/db-sync.js.map +1 -0
- package/dist/commands/dev.d.ts +7 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +61 -0
- package/dist/commands/dev.js.map +1 -0
- package/dist/commands/init.d.ts +9 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +214 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +57 -0
- package/dist/index.js.map +1 -0
- package/dist/templates/.env.example +24 -0
- package/dist/templates/README.md +81 -0
- package/dist/templates/app/components/AcceptInviteClient.tsx +10 -0
- package/dist/templates/app/components/AdminDashboardClient.tsx +10 -0
- package/dist/templates/app/components/AdminTeamClient.tsx +10 -0
- package/dist/templates/app/components/AdminTeamsClient.tsx +10 -0
- package/dist/templates/app/components/AdminUsersClient.tsx +10 -0
- package/dist/templates/app/components/ApiKeysClient.tsx +10 -0
- package/dist/templates/app/components/AutomationsClient.tsx +10 -0
- package/dist/templates/app/components/ChatClient.tsx +13 -0
- package/dist/templates/app/components/ClientOnly.tsx +6 -0
- package/dist/templates/app/components/DocumentsClient.tsx +10 -0
- package/dist/templates/app/components/OAuthConsentClient.tsx +10 -0
- package/dist/templates/app/components/PricingClient.tsx +10 -0
- package/dist/templates/app/components/TeamSettingsClient.tsx +10 -0
- package/dist/templates/app/components/VerifyEmailClient.tsx +10 -0
- package/dist/templates/app/entry.client.tsx +12 -0
- package/dist/templates/app/entry.server.tsx +67 -0
- package/dist/templates/app/root.tsx +91 -0
- package/dist/templates/app/routes/_index.tsx +82 -0
- package/dist/templates/app/routes/admin._index.tsx +57 -0
- package/dist/templates/app/routes/admin.teams.$teamId.tsx +57 -0
- package/dist/templates/app/routes/admin.teams._index.tsx +57 -0
- package/dist/templates/app/routes/admin.users.tsx +57 -0
- package/dist/templates/app/routes/api-keys.tsx +57 -0
- package/dist/templates/app/routes/automations.tsx +57 -0
- package/dist/templates/app/routes/chat._index.tsx +11 -0
- package/dist/templates/app/routes/chat.admin._index.tsx +10 -0
- package/dist/templates/app/routes/chat.admin.teams.$teamId.tsx +10 -0
- package/dist/templates/app/routes/chat.admin.teams._index.tsx +10 -0
- package/dist/templates/app/routes/chat.admin.users.tsx +10 -0
- package/dist/templates/app/routes/chat.api-keys.tsx +10 -0
- package/dist/templates/app/routes/chat.automations.tsx +10 -0
- package/dist/templates/app/routes/chat.documents.tsx +10 -0
- package/dist/templates/app/routes/chat.team.$teamId.settings.tsx +10 -0
- package/dist/templates/app/routes/chat.thread.$threadId.tsx +11 -0
- package/dist/templates/app/routes/chat.tsx +39 -0
- package/dist/templates/app/routes/documents.tsx +57 -0
- package/dist/templates/app/routes/invite.$token.tsx +10 -0
- package/dist/templates/app/routes/login.tsx +334 -0
- package/dist/templates/app/routes/oauth.consent.tsx +10 -0
- package/dist/templates/app/routes/pricing.tsx +10 -0
- package/dist/templates/app/routes/privacy.tsx +197 -0
- package/dist/templates/app/routes/register.tsx +398 -0
- package/dist/templates/app/routes/shared.$shareId.tsx +226 -0
- package/dist/templates/app/routes/team.$teamId.settings.tsx +57 -0
- package/dist/templates/app/routes/terms.tsx +173 -0
- package/dist/templates/app/routes/thread.$threadId.tsx +102 -0
- package/dist/templates/app/routes/verify-email.tsx +10 -0
- package/dist/templates/app/routes.ts +47 -0
- package/dist/templates/config/app.config.ts +216 -0
- package/dist/templates/docs/admin.md +257 -0
- package/dist/templates/docs/api-keys.md +403 -0
- package/dist/templates/docs/authentication.md +247 -0
- package/dist/templates/docs/configuration.md +1212 -0
- package/dist/templates/docs/custom-pages.md +466 -0
- package/dist/templates/docs/deployment.md +362 -0
- package/dist/templates/docs/development.md +411 -0
- package/dist/templates/docs/documents.md +293 -0
- package/dist/templates/docs/extensions.md +639 -0
- package/dist/templates/docs/index.md +139 -0
- package/dist/templates/docs/installation.md +286 -0
- package/dist/templates/docs/mcp.md +952 -0
- package/dist/templates/docs/native-tools.md +688 -0
- package/dist/templates/docs/queue.md +514 -0
- package/dist/templates/docs/scheduled-prompts.md +279 -0
- package/dist/templates/docs/settings.md +415 -0
- package/dist/templates/docs/slack.md +318 -0
- package/dist/templates/docs/styling.md +288 -0
- package/dist/templates/extensions/agents/.gitkeep +0 -0
- package/dist/templates/extensions/pages/.gitkeep +0 -0
- package/dist/templates/extensions/payment-plans/.gitkeep +0 -0
- package/dist/templates/index.html +16 -0
- package/dist/templates/infra-aws/.github/workflows/deploy.yml +95 -0
- package/dist/templates/infra-aws/README.md +207 -0
- package/dist/templates/infra-aws/bin/cdk.ts +18 -0
- package/dist/templates/infra-aws/cdk.json +43 -0
- package/dist/templates/infra-aws/config/deployment.ts +156 -0
- package/dist/templates/infra-aws/lib/chaaskit-stack.ts +419 -0
- package/dist/templates/infra-aws/package.json +27 -0
- package/dist/templates/infra-aws/scripts/build-app.sh +63 -0
- package/dist/templates/infra-aws/tsconfig.json +25 -0
- package/dist/templates/package.json +46 -0
- package/dist/templates/prisma/schema/base.prisma +584 -0
- package/dist/templates/prisma/schema/custom.prisma +24 -0
- package/dist/templates/prisma/schema.prisma +271 -0
- package/dist/templates/public/favicon.svg +4 -0
- package/dist/templates/public/logo.svg +4 -0
- package/dist/templates/react-router.config.ts +11 -0
- package/dist/templates/server.js +52 -0
- package/dist/templates/src/main.tsx +8 -0
- package/dist/templates/tsconfig.json +26 -0
- package/dist/templates/vite.config.ts +26 -0
- package/package.json +46 -0
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
# Scheduled Prompts (Automations)
|
|
2
|
+
|
|
3
|
+
Scheduled Prompts allow you to run AI prompts automatically on a schedule. Results are stored in dedicated threads and can trigger notifications via Slack and email.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
- **Schedule prompts** to run at specific times (daily, weekly, custom cron)
|
|
8
|
+
- **Store results** in dedicated threads for history and context
|
|
9
|
+
- **Get notified** via Slack or email when prompts complete
|
|
10
|
+
- **Team or personal** - create automations for yourself or your team
|
|
11
|
+
|
|
12
|
+
## Configuration
|
|
13
|
+
|
|
14
|
+
Enable scheduled prompts in your `config/app.config.ts`:
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
export const config: AppConfig = {
|
|
18
|
+
// ... other config
|
|
19
|
+
|
|
20
|
+
scheduledPrompts: {
|
|
21
|
+
enabled: true,
|
|
22
|
+
featureName: 'Automations', // Display name in UI (default: "Scheduled Prompts")
|
|
23
|
+
allowUserPrompts: true, // Allow personal automations
|
|
24
|
+
allowTeamPrompts: true, // Allow team automations
|
|
25
|
+
defaultTimezone: 'UTC',
|
|
26
|
+
|
|
27
|
+
// Plan-based limits
|
|
28
|
+
planLimits: [
|
|
29
|
+
{ plan: 'free', maxUserPrompts: 1, maxTeamPrompts: 0 },
|
|
30
|
+
{ plan: 'pro', maxUserPrompts: 5, maxTeamPrompts: 10 },
|
|
31
|
+
{ plan: 'enterprise', maxUserPrompts: 20, maxTeamPrompts: 50 },
|
|
32
|
+
],
|
|
33
|
+
defaultMaxUserPrompts: 0, // Plans not listed get no access
|
|
34
|
+
defaultMaxTeamPrompts: 0,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Configuration Options
|
|
40
|
+
|
|
41
|
+
| Option | Type | Default | Description |
|
|
42
|
+
|--------|------|---------|-------------|
|
|
43
|
+
| `enabled` | boolean | `false` | Enable the scheduled prompts feature |
|
|
44
|
+
| `featureName` | string | `"Scheduled Prompts"` | Display name in sidebar and UI |
|
|
45
|
+
| `allowUserPrompts` | boolean | `true` | Allow personal automations |
|
|
46
|
+
| `allowTeamPrompts` | boolean | `true` | Allow team automations |
|
|
47
|
+
| `defaultTimezone` | string | `"UTC"` | Default timezone for new prompts |
|
|
48
|
+
| `planLimits` | array | `[]` | Limits per subscription plan |
|
|
49
|
+
| `defaultMaxUserPrompts` | number | `0` | Fallback limit for unlisted plans |
|
|
50
|
+
| `defaultMaxTeamPrompts` | number | `0` | Fallback limit for unlisted plans |
|
|
51
|
+
|
|
52
|
+
## Email Notifications
|
|
53
|
+
|
|
54
|
+
To enable email notifications, configure the email service:
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
export const config: AppConfig = {
|
|
58
|
+
// ... other config
|
|
59
|
+
|
|
60
|
+
email: {
|
|
61
|
+
enabled: true,
|
|
62
|
+
fromAddress: 'noreply@yourapp.com',
|
|
63
|
+
fromName: 'Your App',
|
|
64
|
+
providerConfig: {
|
|
65
|
+
type: 'ses',
|
|
66
|
+
region: 'us-east-1',
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### AWS SES Setup
|
|
73
|
+
|
|
74
|
+
1. Install the AWS SDK:
|
|
75
|
+
```bash
|
|
76
|
+
pnpm add @aws-sdk/client-ses
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
2. Set AWS credentials in your environment:
|
|
80
|
+
```bash
|
|
81
|
+
AWS_ACCESS_KEY_ID=your-access-key
|
|
82
|
+
AWS_SECRET_ACCESS_KEY=your-secret-key
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
3. Verify your sender email address in the [AWS SES Console](https://console.aws.amazon.com/ses/)
|
|
86
|
+
|
|
87
|
+
4. If in sandbox mode, also verify recipient email addresses
|
|
88
|
+
|
|
89
|
+
## Queue Requirement
|
|
90
|
+
|
|
91
|
+
Scheduled prompts require the [Job Queue](./queue.md) to be enabled:
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
export const config: AppConfig = {
|
|
95
|
+
queue: {
|
|
96
|
+
enabled: true,
|
|
97
|
+
providerConfig: {
|
|
98
|
+
type: 'memory', // or 'sqs' for production
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The scheduler polls for due recurring jobs and enqueues them for execution.
|
|
105
|
+
|
|
106
|
+
## Usage
|
|
107
|
+
|
|
108
|
+
The Automations page shows prompts based on your sidebar selection:
|
|
109
|
+
- **Personal**: Shows your personal automations and usage (e.g., "2 of 5 used")
|
|
110
|
+
- **Team**: Shows the selected team's automations and usage against the team plan
|
|
111
|
+
|
|
112
|
+
### Creating a Scheduled Prompt
|
|
113
|
+
|
|
114
|
+
1. Navigate to **Automations** in the sidebar
|
|
115
|
+
2. Click **New Automation** (disabled if plan limit reached)
|
|
116
|
+
3. Fill in the form:
|
|
117
|
+
- **Name**: A descriptive name (e.g., "Daily Summary")
|
|
118
|
+
- **Prompt**: The prompt text to run
|
|
119
|
+
- **Agent**: Which AI agent to use
|
|
120
|
+
- **Schedule**: When to run (presets or custom cron)
|
|
121
|
+
- **Timezone**: Your local timezone
|
|
122
|
+
- **Notifications**: Enable Slack and/or email
|
|
123
|
+
|
|
124
|
+
### Schedule Presets
|
|
125
|
+
|
|
126
|
+
| Preset | Cron Expression |
|
|
127
|
+
|--------|-----------------|
|
|
128
|
+
| Every morning (9 AM) | `0 9 * * *` |
|
|
129
|
+
| Every evening (6 PM) | `0 18 * * *` |
|
|
130
|
+
| Weekdays at 9 AM | `0 9 * * 1-5` |
|
|
131
|
+
| Every Monday | `0 9 * * 1` |
|
|
132
|
+
| First of month | `0 9 1 * *` |
|
|
133
|
+
| Every hour | `0 * * * *` |
|
|
134
|
+
|
|
135
|
+
You can also enter custom cron expressions for more complex schedules.
|
|
136
|
+
|
|
137
|
+
### Viewing Results
|
|
138
|
+
|
|
139
|
+
Each scheduled prompt has a dedicated thread where all runs are stored:
|
|
140
|
+
- The prompt is sent as a user message
|
|
141
|
+
- The AI response is saved as an assistant message
|
|
142
|
+
- Previous context is maintained across runs
|
|
143
|
+
|
|
144
|
+
Click the thread link in the automation list to view the full history.
|
|
145
|
+
|
|
146
|
+
### Manual Execution
|
|
147
|
+
|
|
148
|
+
You can trigger a scheduled prompt immediately:
|
|
149
|
+
1. Click the **Run Now** button on any automation
|
|
150
|
+
2. The prompt executes with the current context
|
|
151
|
+
3. Results appear in the thread and trigger notifications
|
|
152
|
+
|
|
153
|
+
## API Endpoints
|
|
154
|
+
|
|
155
|
+
### List Scheduled Prompts
|
|
156
|
+
|
|
157
|
+
```http
|
|
158
|
+
GET /api/scheduled-prompts?personal=true # Personal prompts only
|
|
159
|
+
GET /api/scheduled-prompts?teamId=team_xxx # Team prompts only
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Response includes usage limits:
|
|
163
|
+
|
|
164
|
+
```json
|
|
165
|
+
{
|
|
166
|
+
"prompts": [...],
|
|
167
|
+
"limits": {
|
|
168
|
+
"context": "personal", // or "team"
|
|
169
|
+
"current": 2, // Number currently configured
|
|
170
|
+
"max": 5 // Maximum allowed by plan
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Create Scheduled Prompt
|
|
176
|
+
|
|
177
|
+
```http
|
|
178
|
+
POST /api/scheduled-prompts
|
|
179
|
+
Content-Type: application/json
|
|
180
|
+
|
|
181
|
+
{
|
|
182
|
+
"name": "Daily Summary",
|
|
183
|
+
"prompt": "Summarize the key developments from today.",
|
|
184
|
+
"agentId": "default",
|
|
185
|
+
"schedule": "0 18 * * *",
|
|
186
|
+
"timezone": "America/New_York",
|
|
187
|
+
"notifySlack": true,
|
|
188
|
+
"notifyEmail": true,
|
|
189
|
+
"emailRecipients": ["user@example.com"],
|
|
190
|
+
"teamId": "team_xxx" // Optional, for team prompts
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Update Scheduled Prompt
|
|
195
|
+
|
|
196
|
+
```http
|
|
197
|
+
PUT /api/scheduled-prompts/:id
|
|
198
|
+
Content-Type: application/json
|
|
199
|
+
|
|
200
|
+
{
|
|
201
|
+
"name": "Updated Name",
|
|
202
|
+
"enabled": false
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Delete Scheduled Prompt
|
|
207
|
+
|
|
208
|
+
```http
|
|
209
|
+
DELETE /api/scheduled-prompts/:id
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Manual Run
|
|
213
|
+
|
|
214
|
+
```http
|
|
215
|
+
POST /api/scheduled-prompts/:id/run
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Slack Notifications
|
|
219
|
+
|
|
220
|
+
If your team has [Slack integration](./slack.md) configured, scheduled prompts can post results to your notification channel.
|
|
221
|
+
|
|
222
|
+
The notification includes:
|
|
223
|
+
- Prompt name and completion time
|
|
224
|
+
- Truncated result (first 500 characters)
|
|
225
|
+
- Link to view the full thread
|
|
226
|
+
|
|
227
|
+
## Database Schema
|
|
228
|
+
|
|
229
|
+
The feature adds a `ScheduledPrompt` model:
|
|
230
|
+
|
|
231
|
+
```prisma
|
|
232
|
+
model ScheduledPrompt {
|
|
233
|
+
id String @id @default(cuid())
|
|
234
|
+
name String
|
|
235
|
+
prompt String @db.Text
|
|
236
|
+
agentId String?
|
|
237
|
+
schedule String
|
|
238
|
+
timezone String @default("UTC")
|
|
239
|
+
enabled Boolean @default(true)
|
|
240
|
+
notifySlack Boolean @default(true)
|
|
241
|
+
notifyEmail Boolean @default(false)
|
|
242
|
+
emailRecipients String? @db.Text
|
|
243
|
+
threadId String?
|
|
244
|
+
userId String?
|
|
245
|
+
teamId String?
|
|
246
|
+
lastRunAt DateTime?
|
|
247
|
+
lastRunStatus String?
|
|
248
|
+
lastError String?
|
|
249
|
+
runCount Int @default(0)
|
|
250
|
+
createdAt DateTime @default(now())
|
|
251
|
+
updatedAt DateTime @updatedAt
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## Troubleshooting
|
|
256
|
+
|
|
257
|
+
### Prompt not running
|
|
258
|
+
|
|
259
|
+
1. Check that the queue is enabled and processing jobs
|
|
260
|
+
2. Verify the prompt is enabled (not toggled off)
|
|
261
|
+
3. Check the `lastError` field for execution errors
|
|
262
|
+
4. Review server logs for job handler errors
|
|
263
|
+
|
|
264
|
+
### Email not sending
|
|
265
|
+
|
|
266
|
+
1. Verify email is enabled in config
|
|
267
|
+
2. Check AWS credentials are set correctly
|
|
268
|
+
3. Confirm sender address is verified in SES
|
|
269
|
+
4. In SES sandbox mode, recipient must also be verified
|
|
270
|
+
|
|
271
|
+
### Slack notification not appearing
|
|
272
|
+
|
|
273
|
+
1. Confirm team has active Slack integration
|
|
274
|
+
2. Check notification channel is configured
|
|
275
|
+
3. Verify the bot has permission to post to the channel
|
|
276
|
+
|
|
277
|
+
### Plan limit reached
|
|
278
|
+
|
|
279
|
+
Users see an error when creating more prompts than their plan allows. Upgrade to a higher plan or delete unused automations.
|
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
# User Settings
|
|
2
|
+
|
|
3
|
+
The ChaasKit Template includes a flexible user settings system that allows users to customize their experience and provide context to the AI.
|
|
4
|
+
|
|
5
|
+
## Configuration
|
|
6
|
+
|
|
7
|
+
Define available settings in `config/app.config.ts`:
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
userSettings: {
|
|
11
|
+
fields: [
|
|
12
|
+
{
|
|
13
|
+
key: 'name',
|
|
14
|
+
label: 'Your Name',
|
|
15
|
+
type: 'text',
|
|
16
|
+
placeholder: 'Enter your name',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
key: 'role',
|
|
20
|
+
label: 'Your Role',
|
|
21
|
+
type: 'select',
|
|
22
|
+
options: ['Developer', 'Designer', 'Manager', 'Other'],
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
key: 'context',
|
|
26
|
+
label: 'Additional Context',
|
|
27
|
+
type: 'textarea',
|
|
28
|
+
placeholder: 'Any context the AI should know about you...',
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Field Types
|
|
35
|
+
|
|
36
|
+
### Text Field
|
|
37
|
+
|
|
38
|
+
Simple single-line text input.
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
{
|
|
42
|
+
key: 'company',
|
|
43
|
+
label: 'Company',
|
|
44
|
+
type: 'text',
|
|
45
|
+
placeholder: 'Your company name',
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Select Field
|
|
50
|
+
|
|
51
|
+
Dropdown selection from predefined options.
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
{
|
|
55
|
+
key: 'experience',
|
|
56
|
+
label: 'Experience Level',
|
|
57
|
+
type: 'select',
|
|
58
|
+
options: ['Beginner', 'Intermediate', 'Expert'],
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Textarea Field
|
|
63
|
+
|
|
64
|
+
Multi-line text input for longer content.
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
{
|
|
68
|
+
key: 'bio',
|
|
69
|
+
label: 'About You',
|
|
70
|
+
type: 'textarea',
|
|
71
|
+
placeholder: 'Tell us about yourself...',
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## How Settings Work
|
|
76
|
+
|
|
77
|
+
### Storage
|
|
78
|
+
|
|
79
|
+
User settings are stored in the `settings` JSON field on the User model:
|
|
80
|
+
|
|
81
|
+
```prisma
|
|
82
|
+
model User {
|
|
83
|
+
// ...
|
|
84
|
+
settings Json @default("{}")
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### API
|
|
89
|
+
|
|
90
|
+
**Get Settings:**
|
|
91
|
+
```http
|
|
92
|
+
GET /api/user/settings
|
|
93
|
+
Authorization: Bearer <token>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**Update Settings:**
|
|
97
|
+
```http
|
|
98
|
+
PUT /api/user/settings
|
|
99
|
+
Authorization: Bearer <token>
|
|
100
|
+
Content-Type: application/json
|
|
101
|
+
|
|
102
|
+
{
|
|
103
|
+
"name": "John",
|
|
104
|
+
"role": "Developer",
|
|
105
|
+
"context": "I work with React and Node.js"
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### AI Context
|
|
110
|
+
|
|
111
|
+
Settings are automatically included in the AI's system prompt:
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
// agent.ts
|
|
115
|
+
if (options?.userContext) {
|
|
116
|
+
const contextStr = Object.entries(options.userContext)
|
|
117
|
+
.filter(([, v]) => v != null && v !== '')
|
|
118
|
+
.map(([k, v]) => `${k}: ${v}`)
|
|
119
|
+
.join('\n');
|
|
120
|
+
|
|
121
|
+
if (contextStr) {
|
|
122
|
+
systemPrompt += `\n\nUser context:\n${contextStr}`;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
This allows the AI to personalize responses based on user preferences.
|
|
128
|
+
|
|
129
|
+
## Frontend Integration
|
|
130
|
+
|
|
131
|
+
### Settings Page
|
|
132
|
+
|
|
133
|
+
The settings are displayed in a form on the settings page:
|
|
134
|
+
|
|
135
|
+
```tsx
|
|
136
|
+
import { useAuth } from '../contexts/AuthContext';
|
|
137
|
+
import { useConfig } from '../contexts/ConfigContext';
|
|
138
|
+
|
|
139
|
+
function SettingsPage() {
|
|
140
|
+
const { user } = useAuth();
|
|
141
|
+
const config = useConfig();
|
|
142
|
+
|
|
143
|
+
return (
|
|
144
|
+
<form>
|
|
145
|
+
{config.userSettings.fields.map((field) => (
|
|
146
|
+
<FormField key={field.key} field={field} />
|
|
147
|
+
))}
|
|
148
|
+
</form>
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### FormField Component
|
|
154
|
+
|
|
155
|
+
Renders appropriate input based on field type:
|
|
156
|
+
|
|
157
|
+
```tsx
|
|
158
|
+
function FormField({ field }) {
|
|
159
|
+
switch (field.type) {
|
|
160
|
+
case 'text':
|
|
161
|
+
return <input type="text" {...props} />;
|
|
162
|
+
case 'select':
|
|
163
|
+
return (
|
|
164
|
+
<select {...props}>
|
|
165
|
+
{field.options.map((opt) => (
|
|
166
|
+
<option key={opt} value={opt}>{opt}</option>
|
|
167
|
+
))}
|
|
168
|
+
</select>
|
|
169
|
+
);
|
|
170
|
+
case 'textarea':
|
|
171
|
+
return <textarea {...props} />;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## MCP Credentials
|
|
177
|
+
|
|
178
|
+
Users can manage credentials for MCP servers that require authentication directly in the Settings modal.
|
|
179
|
+
|
|
180
|
+
### Credential Types
|
|
181
|
+
|
|
182
|
+
**API Key**: For servers with `authMode: 'user-apikey'`
|
|
183
|
+
- Text input to enter/update the API key
|
|
184
|
+
- Key is encrypted and stored securely
|
|
185
|
+
|
|
186
|
+
**OAuth**: For servers with `authMode: 'user-oauth'`
|
|
187
|
+
- "Connect" button initiates OAuth flow
|
|
188
|
+
- Tokens are encrypted and stored
|
|
189
|
+
- "Disconnect" button to revoke access
|
|
190
|
+
|
|
191
|
+
### Settings Modal Section
|
|
192
|
+
|
|
193
|
+
The MCP Credentials section appears automatically when servers with user authentication are configured:
|
|
194
|
+
|
|
195
|
+
```tsx
|
|
196
|
+
// In SettingsModal
|
|
197
|
+
{mcpServers.length > 0 && (
|
|
198
|
+
<MCPCredentialsSection servers={mcpServers} />
|
|
199
|
+
)}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### API Endpoints
|
|
203
|
+
|
|
204
|
+
**Get Credential Status:**
|
|
205
|
+
```http
|
|
206
|
+
GET /api/mcp/credentials
|
|
207
|
+
Authorization: Bearer <token>
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
**Set API Key:**
|
|
211
|
+
```http
|
|
212
|
+
POST /api/mcp/credentials/:serverId/apikey
|
|
213
|
+
Authorization: Bearer <token>
|
|
214
|
+
Content-Type: application/json
|
|
215
|
+
|
|
216
|
+
{
|
|
217
|
+
"apiKey": "sk-..."
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
**Start OAuth:**
|
|
222
|
+
```http
|
|
223
|
+
GET /api/mcp/oauth/:serverId/authorize
|
|
224
|
+
Authorization: Bearer <token>
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
**Remove Credentials:**
|
|
228
|
+
```http
|
|
229
|
+
DELETE /api/mcp/credentials/:serverId
|
|
230
|
+
Authorization: Bearer <token>
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## Usage Metrics
|
|
234
|
+
|
|
235
|
+
The Settings modal displays usage metrics showing the user's message consumption:
|
|
236
|
+
|
|
237
|
+
### Display
|
|
238
|
+
|
|
239
|
+
- Progress bar showing messages used vs. limit
|
|
240
|
+
- Numerical display: "X / Y messages used"
|
|
241
|
+
- For unlimited plans: "X messages used (unlimited)"
|
|
242
|
+
|
|
243
|
+
### API Endpoint
|
|
244
|
+
|
|
245
|
+
```http
|
|
246
|
+
GET /api/user/usage
|
|
247
|
+
Authorization: Bearer <token>
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Response:
|
|
251
|
+
```json
|
|
252
|
+
{
|
|
253
|
+
"messagesUsed": 15,
|
|
254
|
+
"messagesLimit": 100,
|
|
255
|
+
"unlimited": false
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## Theme Preference
|
|
260
|
+
|
|
261
|
+
The user's theme preference is stored separately:
|
|
262
|
+
|
|
263
|
+
```prisma
|
|
264
|
+
model User {
|
|
265
|
+
themePreference String? // 'light' | 'dark' | null (system)
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### API
|
|
270
|
+
|
|
271
|
+
**Get Theme:**
|
|
272
|
+
```http
|
|
273
|
+
GET /api/user/theme
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
**Update Theme:**
|
|
277
|
+
```http
|
|
278
|
+
PUT /api/user/theme
|
|
279
|
+
Content-Type: application/json
|
|
280
|
+
|
|
281
|
+
{
|
|
282
|
+
"theme": "dark"
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Frontend
|
|
287
|
+
|
|
288
|
+
Use the ThemeContext:
|
|
289
|
+
|
|
290
|
+
```tsx
|
|
291
|
+
import { useTheme } from '../contexts/ThemeContext';
|
|
292
|
+
|
|
293
|
+
function ThemeToggle() {
|
|
294
|
+
const { theme, setTheme } = useTheme();
|
|
295
|
+
|
|
296
|
+
return (
|
|
297
|
+
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
|
|
298
|
+
Toggle Theme
|
|
299
|
+
</button>
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
## Use Cases
|
|
305
|
+
|
|
306
|
+
### Developer Context
|
|
307
|
+
|
|
308
|
+
```typescript
|
|
309
|
+
userSettings: {
|
|
310
|
+
fields: [
|
|
311
|
+
{
|
|
312
|
+
key: 'primaryLanguage',
|
|
313
|
+
label: 'Primary Language',
|
|
314
|
+
type: 'select',
|
|
315
|
+
options: ['JavaScript', 'Python', 'Go', 'Rust', 'Other'],
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
key: 'framework',
|
|
319
|
+
label: 'Preferred Framework',
|
|
320
|
+
type: 'text',
|
|
321
|
+
placeholder: 'React, Vue, Django, etc.',
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
key: 'codeStyle',
|
|
325
|
+
label: 'Code Style Preferences',
|
|
326
|
+
type: 'textarea',
|
|
327
|
+
placeholder: 'Describe your coding style preferences...',
|
|
328
|
+
},
|
|
329
|
+
],
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Customer Support
|
|
334
|
+
|
|
335
|
+
```typescript
|
|
336
|
+
userSettings: {
|
|
337
|
+
fields: [
|
|
338
|
+
{
|
|
339
|
+
key: 'accountId',
|
|
340
|
+
label: 'Account ID',
|
|
341
|
+
type: 'text',
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
key: 'department',
|
|
345
|
+
label: 'Department',
|
|
346
|
+
type: 'select',
|
|
347
|
+
options: ['Sales', 'Engineering', 'Support', 'Finance'],
|
|
348
|
+
},
|
|
349
|
+
],
|
|
350
|
+
}
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### Creative Writing
|
|
354
|
+
|
|
355
|
+
```typescript
|
|
356
|
+
userSettings: {
|
|
357
|
+
fields: [
|
|
358
|
+
{
|
|
359
|
+
key: 'writingStyle',
|
|
360
|
+
label: 'Preferred Writing Style',
|
|
361
|
+
type: 'select',
|
|
362
|
+
options: ['Formal', 'Casual', 'Technical', 'Creative'],
|
|
363
|
+
},
|
|
364
|
+
{
|
|
365
|
+
key: 'targetAudience',
|
|
366
|
+
label: 'Target Audience',
|
|
367
|
+
type: 'text',
|
|
368
|
+
placeholder: 'Who are you writing for?',
|
|
369
|
+
},
|
|
370
|
+
],
|
|
371
|
+
}
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
## Extending Settings
|
|
375
|
+
|
|
376
|
+
### Custom Field Types
|
|
377
|
+
|
|
378
|
+
Add new field types by extending the configuration:
|
|
379
|
+
|
|
380
|
+
```typescript
|
|
381
|
+
// types/config.ts
|
|
382
|
+
export interface UserSettingsField {
|
|
383
|
+
key: string;
|
|
384
|
+
label: string;
|
|
385
|
+
type: 'text' | 'select' | 'textarea' | 'number' | 'boolean';
|
|
386
|
+
// ...
|
|
387
|
+
}
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### Validation
|
|
391
|
+
|
|
392
|
+
Add validation using Zod:
|
|
393
|
+
|
|
394
|
+
```typescript
|
|
395
|
+
// validation/user.ts
|
|
396
|
+
export const settingsSchema = z.object({
|
|
397
|
+
name: z.string().optional(),
|
|
398
|
+
role: z.enum(['Developer', 'Designer', 'Manager', 'Other']).optional(),
|
|
399
|
+
context: z.string().max(1000).optional(),
|
|
400
|
+
});
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
### Computed Settings
|
|
404
|
+
|
|
405
|
+
Process settings before sending to AI:
|
|
406
|
+
|
|
407
|
+
```typescript
|
|
408
|
+
function processUserContext(settings) {
|
|
409
|
+
return {
|
|
410
|
+
...settings,
|
|
411
|
+
// Add computed fields
|
|
412
|
+
fullContext: `${settings.name} is a ${settings.role}. ${settings.context}`,
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
```
|