reflexive 1.0.0 → 1.0.2

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.
Files changed (49) hide show
  1. package/dashboard/out/404/index.html +1 -1
  2. package/dashboard/out/404.html +1 -1
  3. package/dashboard/out/__next.__PAGE__.txt +2 -2
  4. package/dashboard/out/__next._full.txt +3 -3
  5. package/dashboard/out/__next._head.txt +1 -1
  6. package/dashboard/out/__next._index.txt +2 -2
  7. package/dashboard/out/__next._tree.txt +2 -2
  8. package/dashboard/out/_next/static/chunks/209a165917e29ad7.css +3 -0
  9. package/dashboard/out/_next/static/chunks/{5be66f773d014294.js → 875b2f53bcfbbafb.js} +3 -3
  10. package/dashboard/out/_not-found/__next._full.txt +2 -2
  11. package/dashboard/out/_not-found/__next._head.txt +1 -1
  12. package/dashboard/out/_not-found/__next._index.txt +2 -2
  13. package/dashboard/out/_not-found/__next._not-found.__PAGE__.txt +1 -1
  14. package/dashboard/out/_not-found/__next._not-found.txt +1 -1
  15. package/dashboard/out/_not-found/__next._tree.txt +2 -2
  16. package/dashboard/out/_not-found/index.html +1 -1
  17. package/dashboard/out/_not-found/index.txt +2 -2
  18. package/dashboard/out/index.html +1 -1
  19. package/dashboard/out/index.txt +3 -3
  20. package/dist/cli.d.ts +0 -1
  21. package/dist/cli.d.ts.map +1 -1
  22. package/dist/cli.js +164 -42
  23. package/dist/cli.js.map +1 -1
  24. package/dist/index.d.ts +4 -0
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +102 -4
  27. package/dist/index.js.map +1 -1
  28. package/dist/managers/process-manager.d.ts +22 -8
  29. package/dist/managers/process-manager.d.ts.map +1 -1
  30. package/dist/managers/process-manager.js +50 -42
  31. package/dist/managers/process-manager.js.map +1 -1
  32. package/dist/mcp/knowledge-tools.d.ts +16 -0
  33. package/dist/mcp/knowledge-tools.d.ts.map +1 -0
  34. package/dist/mcp/knowledge-tools.js +206 -0
  35. package/dist/mcp/knowledge-tools.js.map +1 -0
  36. package/dist/types/index.d.ts +1 -0
  37. package/dist/types/index.d.ts.map +1 -1
  38. package/dist/types/index.js.map +1 -1
  39. package/docs/README.md +87 -0
  40. package/docs/api-reference.md +1422 -0
  41. package/docs/deployment.md +885 -0
  42. package/docs/developer-guide.md +899 -0
  43. package/docs/getting-started.md +374 -0
  44. package/docs/index.md +158 -0
  45. package/docs/user-guide.md +990 -0
  46. package/package.json +2 -1
  47. package/dashboard/out/_next/static/chunks/82bbed47af1fbb39.css +0 -3
  48. /package/dashboard/out/_next/static/{vYzD8icR4qocco4JtUfu3 → Y9FaARzAOsacwE8LNVv_4}/_buildManifest.js +0 -0
  49. /package/dashboard/out/_next/static/{vYzD8icR4qocco4JtUfu3 → Y9FaARzAOsacwE8LNVv_4}/_ssgManifest.js +0 -0
@@ -0,0 +1,885 @@
1
+ # Deployment Guide
2
+
3
+ Guide for deploying Reflexive in production environments, particularly hosted mode.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Deployment Options](#deployment-options)
8
+ - [Railway Deployment](#railway-deployment)
9
+ - [One-Click Deploy](#one-click-deploy)
10
+ - [Manual Setup](#manual-setup)
11
+ - [Environment Variables](#environment-variables)
12
+ - [Monitoring](#monitoring)
13
+ - [Docker Deployment](#docker-deployment)
14
+ - [Using Pre-built Image](#using-pre-built-image)
15
+ - [Building Custom Image](#building-custom-image)
16
+ - [Docker Compose](#docker-compose)
17
+ - [Kubernetes](#kubernetes)
18
+ - [Manual Deployment](#manual-deployment)
19
+ - [Build and Deploy](#build-and-deploy)
20
+ - [Process Management](#process-management)
21
+ - [Reverse Proxy](#reverse-proxy)
22
+ - [Security Considerations](#security-considerations)
23
+ - [API Authentication](#api-authentication)
24
+ - [Rate Limiting](#rate-limiting)
25
+ - [Sandbox Isolation](#sandbox-isolation)
26
+ - [Secrets Management](#secrets-management)
27
+ - [Storage Configuration](#storage-configuration)
28
+ - [S3 Storage](#s3-storage)
29
+ - [Cloudflare R2](#cloudflare-r2)
30
+ - [Memory Storage](#memory-storage)
31
+ - [Monitoring and Logging](#monitoring-and-logging)
32
+ - [Health Checks](#health-checks)
33
+ - [Metrics](#metrics)
34
+ - [Log Aggregation](#log-aggregation)
35
+ - [Scaling](#scaling)
36
+ - [Horizontal Scaling](#horizontal-scaling)
37
+ - [Resource Limits](#resource-limits)
38
+ - [Troubleshooting](#troubleshooting)
39
+
40
+ ## Deployment Options
41
+
42
+ Reflexive can be deployed in several ways depending on your needs:
43
+
44
+ | Option | Best For | Complexity | Cost |
45
+ |--------|----------|------------|------|
46
+ | Railway | Quick deployment, managed infrastructure | Low | $ |
47
+ | Docker | Containerized deployment, cloud-agnostic | Medium | $$ |
48
+ | Manual | Full control, custom infrastructure | High | $$$ |
49
+
50
+ ## Railway Deployment
51
+
52
+ Railway provides the easiest way to deploy Reflexive with minimal configuration.
53
+
54
+ ### One-Click Deploy
55
+
56
+ [![Deploy on Railway](https://railway.app/button.svg)](https://railway.app/new/template?template=reflexive)
57
+
58
+ Click the button above or use the CLI:
59
+
60
+ ```bash
61
+ # Install Railway CLI
62
+ npm install -g @railway/cli
63
+
64
+ # Login
65
+ railway login
66
+
67
+ # Deploy from directory
68
+ cd reflexive
69
+ railway up
70
+ ```
71
+
72
+ ### Manual Setup
73
+
74
+ **Step 1: Create Project**
75
+
76
+ ```bash
77
+ railway login
78
+ railway init
79
+ railway link
80
+ ```
81
+
82
+ **Step 2: Set Environment Variables**
83
+
84
+ ```bash
85
+ railway variables set ANTHROPIC_API_KEY=sk-ant-xxxxx
86
+ railway variables set REFLEXIVE_API_KEY=your-secure-key
87
+ railway variables set NODE_ENV=production
88
+ railway variables set PORT=3099
89
+ ```
90
+
91
+ **Step 3: Configure Snapshot Storage**
92
+
93
+ For S3:
94
+ ```bash
95
+ railway variables set AWS_ACCESS_KEY_ID=your-access-key
96
+ railway variables set AWS_SECRET_ACCESS_KEY=your-secret-key
97
+ railway variables set REFLEXIVE_SNAPSHOT_BUCKET=reflexive-snapshots
98
+ railway variables set AWS_REGION=us-east-1
99
+ ```
100
+
101
+ For Cloudflare R2:
102
+ ```bash
103
+ railway variables set AWS_ACCESS_KEY_ID=your-r2-access-key
104
+ railway variables set AWS_SECRET_ACCESS_KEY=your-r2-secret-key
105
+ railway variables set REFLEXIVE_S3_ENDPOINT=https://account.r2.cloudflarestorage.com
106
+ railway variables set REFLEXIVE_SNAPSHOT_BUCKET=reflexive-snapshots
107
+ ```
108
+
109
+ **Step 4: Deploy**
110
+
111
+ ```bash
112
+ railway up
113
+ ```
114
+
115
+ **Step 5: Get URL**
116
+
117
+ ```bash
118
+ railway domain
119
+ # Returns: https://reflexive-production.up.railway.app
120
+ ```
121
+
122
+ ### Environment Variables
123
+
124
+ Required variables for Railway deployment:
125
+
126
+ ```bash
127
+ # Authentication
128
+ ANTHROPIC_API_KEY=sk-ant-xxxxx # Claude API key
129
+ REFLEXIVE_API_KEY=your-secure-key # API key for REST endpoints
130
+
131
+ # Server
132
+ NODE_ENV=production
133
+ PORT=3099 # Railway auto-sets PORT
134
+
135
+ # Snapshot Storage (choose one)
136
+ # Option 1: AWS S3
137
+ AWS_ACCESS_KEY_ID=xxx
138
+ AWS_SECRET_ACCESS_KEY=xxx
139
+ REFLEXIVE_SNAPSHOT_BUCKET=bucket-name
140
+ AWS_REGION=us-east-1
141
+
142
+ # Option 2: Cloudflare R2
143
+ AWS_ACCESS_KEY_ID=xxx
144
+ AWS_SECRET_ACCESS_KEY=xxx
145
+ REFLEXIVE_S3_ENDPOINT=https://xxx.r2.cloudflarestorage.com
146
+ REFLEXIVE_SNAPSHOT_BUCKET=bucket-name
147
+
148
+ # Optional: Vercel Sandbox
149
+ VERCEL_TOKEN=xxx # For sandbox mode
150
+ ```
151
+
152
+ ### Monitoring
153
+
154
+ Railway provides built-in monitoring:
155
+
156
+ ```bash
157
+ # View logs
158
+ railway logs
159
+
160
+ # View metrics
161
+ railway status
162
+
163
+ # Open dashboard
164
+ railway open
165
+ ```
166
+
167
+ ## Docker Deployment
168
+
169
+ ### Using Pre-built Image
170
+
171
+ Pull and run the official image:
172
+
173
+ ```bash
174
+ docker pull reflexive/reflexive:latest
175
+
176
+ docker run -d \
177
+ --name reflexive \
178
+ -p 3099:3099 \
179
+ -e ANTHROPIC_API_KEY=sk-ant-xxx \
180
+ -e REFLEXIVE_API_KEY=your-key \
181
+ -e AWS_ACCESS_KEY_ID=xxx \
182
+ -e AWS_SECRET_ACCESS_KEY=xxx \
183
+ -e REFLEXIVE_SNAPSHOT_BUCKET=snapshots \
184
+ reflexive/reflexive:latest
185
+ ```
186
+
187
+ ### Building Custom Image
188
+
189
+ **Create Dockerfile**:
190
+
191
+ ```dockerfile
192
+ # Dockerfile
193
+ FROM node:18-alpine
194
+
195
+ # Install dependencies for native modules
196
+ RUN apk add --no-cache python3 make g++
197
+
198
+ WORKDIR /app
199
+
200
+ # Copy package files
201
+ COPY package*.json ./
202
+
203
+ # Install production dependencies
204
+ RUN npm ci --only=production
205
+
206
+ # Copy source
207
+ COPY . .
208
+
209
+ # Build TypeScript
210
+ RUN npm run build
211
+
212
+ # Remove dev dependencies
213
+ RUN npm prune --production
214
+
215
+ # Expose port
216
+ EXPOSE 3099
217
+
218
+ # Health check
219
+ HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
220
+ CMD node -e "require('http').get('http://localhost:3099/api/health', (r) => { process.exit(r.statusCode === 200 ? 0 : 1) })"
221
+
222
+ # Run
223
+ CMD ["node", "dist/cli.js", "--mode", "hosted"]
224
+ ```
225
+
226
+ **Build and Run**:
227
+
228
+ ```bash
229
+ # Build
230
+ docker build -t reflexive:latest .
231
+
232
+ # Run
233
+ docker run -d \
234
+ --name reflexive \
235
+ -p 3099:3099 \
236
+ --env-file .env \
237
+ reflexive:latest
238
+ ```
239
+
240
+ ### Docker Compose
241
+
242
+ **docker-compose.yml**:
243
+
244
+ ```yaml
245
+ version: '3.8'
246
+
247
+ services:
248
+ reflexive:
249
+ build: .
250
+ ports:
251
+ - "3099:3099"
252
+ environment:
253
+ - NODE_ENV=production
254
+ - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
255
+ - REFLEXIVE_API_KEY=${REFLEXIVE_API_KEY}
256
+ - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
257
+ - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
258
+ - REFLEXIVE_SNAPSHOT_BUCKET=${REFLEXIVE_SNAPSHOT_BUCKET}
259
+ - REFLEXIVE_S3_ENDPOINT=${REFLEXIVE_S3_ENDPOINT}
260
+ restart: unless-stopped
261
+ healthcheck:
262
+ test: ["CMD", "node", "-e", "require('http').get('http://localhost:3099/api/health', (r) => { process.exit(r.statusCode === 200 ? 0 : 1) })"]
263
+ interval: 30s
264
+ timeout: 3s
265
+ retries: 3
266
+ start_period: 5s
267
+ volumes:
268
+ - ./config:/app/config:ro
269
+ networks:
270
+ - reflexive-net
271
+
272
+ # Optional: Redis for rate limiting
273
+ redis:
274
+ image: redis:7-alpine
275
+ restart: unless-stopped
276
+ networks:
277
+ - reflexive-net
278
+
279
+ networks:
280
+ reflexive-net:
281
+ driver: bridge
282
+ ```
283
+
284
+ **Start services**:
285
+
286
+ ```bash
287
+ docker-compose up -d
288
+
289
+ # View logs
290
+ docker-compose logs -f reflexive
291
+
292
+ # Stop
293
+ docker-compose down
294
+ ```
295
+
296
+ ### Kubernetes
297
+
298
+ **deployment.yaml**:
299
+
300
+ ```yaml
301
+ apiVersion: apps/v1
302
+ kind: Deployment
303
+ metadata:
304
+ name: reflexive
305
+ spec:
306
+ replicas: 3
307
+ selector:
308
+ matchLabels:
309
+ app: reflexive
310
+ template:
311
+ metadata:
312
+ labels:
313
+ app: reflexive
314
+ spec:
315
+ containers:
316
+ - name: reflexive
317
+ image: reflexive/reflexive:latest
318
+ ports:
319
+ - containerPort: 3099
320
+ env:
321
+ - name: NODE_ENV
322
+ value: "production"
323
+ - name: ANTHROPIC_API_KEY
324
+ valueFrom:
325
+ secretKeyRef:
326
+ name: reflexive-secrets
327
+ key: anthropic-api-key
328
+ - name: REFLEXIVE_API_KEY
329
+ valueFrom:
330
+ secretKeyRef:
331
+ name: reflexive-secrets
332
+ key: reflexive-api-key
333
+ - name: AWS_ACCESS_KEY_ID
334
+ valueFrom:
335
+ secretKeyRef:
336
+ name: aws-secrets
337
+ key: access-key-id
338
+ - name: AWS_SECRET_ACCESS_KEY
339
+ valueFrom:
340
+ secretKeyRef:
341
+ name: aws-secrets
342
+ key: secret-access-key
343
+ - name: REFLEXIVE_SNAPSHOT_BUCKET
344
+ value: "reflexive-snapshots"
345
+ resources:
346
+ requests:
347
+ memory: "512Mi"
348
+ cpu: "500m"
349
+ limits:
350
+ memory: "2Gi"
351
+ cpu: "2000m"
352
+ livenessProbe:
353
+ httpGet:
354
+ path: /api/health
355
+ port: 3099
356
+ initialDelaySeconds: 5
357
+ periodSeconds: 10
358
+ readinessProbe:
359
+ httpGet:
360
+ path: /api/health
361
+ port: 3099
362
+ initialDelaySeconds: 5
363
+ periodSeconds: 5
364
+ ---
365
+ apiVersion: v1
366
+ kind: Service
367
+ metadata:
368
+ name: reflexive
369
+ spec:
370
+ selector:
371
+ app: reflexive
372
+ ports:
373
+ - protocol: TCP
374
+ port: 80
375
+ targetPort: 3099
376
+ type: LoadBalancer
377
+ ```
378
+
379
+ **Deploy**:
380
+
381
+ ```bash
382
+ # Create secrets
383
+ kubectl create secret generic reflexive-secrets \
384
+ --from-literal=anthropic-api-key=sk-ant-xxx \
385
+ --from-literal=reflexive-api-key=your-key
386
+
387
+ kubectl create secret generic aws-secrets \
388
+ --from-literal=access-key-id=xxx \
389
+ --from-literal=secret-access-key=xxx
390
+
391
+ # Apply deployment
392
+ kubectl apply -f deployment.yaml
393
+
394
+ # Check status
395
+ kubectl get pods
396
+ kubectl get services
397
+ ```
398
+
399
+ ## Manual Deployment
400
+
401
+ ### Build and Deploy
402
+
403
+ **On your server**:
404
+
405
+ ```bash
406
+ # Clone repository
407
+ git clone https://github.com/yourusername/reflexive.git
408
+ cd reflexive
409
+
410
+ # Install dependencies
411
+ npm ci
412
+
413
+ # Build
414
+ npm run build
415
+
416
+ # Test
417
+ npm test
418
+
419
+ # Start
420
+ NODE_ENV=production node dist/cli.js --mode hosted
421
+ ```
422
+
423
+ ### Process Management
424
+
425
+ Use PM2 for process management:
426
+
427
+ ```bash
428
+ # Install PM2
429
+ npm install -g pm2
430
+
431
+ # Create ecosystem file
432
+ cat > ecosystem.config.js << 'EOF'
433
+ module.exports = {
434
+ apps: [{
435
+ name: 'reflexive',
436
+ script: './dist/cli.js',
437
+ args: '--mode hosted',
438
+ instances: 1,
439
+ autorestart: true,
440
+ watch: false,
441
+ max_memory_restart: '2G',
442
+ env: {
443
+ NODE_ENV: 'production',
444
+ PORT: 3099
445
+ }
446
+ }]
447
+ }
448
+ EOF
449
+
450
+ # Start with PM2
451
+ pm2 start ecosystem.config.js
452
+
453
+ # Setup startup script
454
+ pm2 startup
455
+ pm2 save
456
+
457
+ # Monitor
458
+ pm2 monit
459
+ pm2 logs reflexive
460
+ ```
461
+
462
+ ### Reverse Proxy
463
+
464
+ **Nginx configuration**:
465
+
466
+ ```nginx
467
+ # /etc/nginx/sites-available/reflexive
468
+ upstream reflexive {
469
+ server localhost:3099;
470
+ }
471
+
472
+ server {
473
+ listen 80;
474
+ server_name reflexive.yourdomain.com;
475
+
476
+ # Redirect to HTTPS
477
+ return 301 https://$server_name$request_uri;
478
+ }
479
+
480
+ server {
481
+ listen 443 ssl http2;
482
+ server_name reflexive.yourdomain.com;
483
+
484
+ # SSL certificates
485
+ ssl_certificate /etc/letsencrypt/live/reflexive.yourdomain.com/fullchain.pem;
486
+ ssl_certificate_key /etc/letsencrypt/live/reflexive.yourdomain.com/privkey.pem;
487
+
488
+ # Security headers
489
+ add_header X-Frame-Options "SAMEORIGIN" always;
490
+ add_header X-Content-Type-Options "nosniff" always;
491
+ add_header X-XSS-Protection "1; mode=block" always;
492
+
493
+ # Proxy settings
494
+ location / {
495
+ proxy_pass http://reflexive;
496
+ proxy_http_version 1.1;
497
+ proxy_set_header Upgrade $http_upgrade;
498
+ proxy_set_header Connection "upgrade";
499
+ proxy_set_header Host $host;
500
+ proxy_set_header X-Real-IP $remote_addr;
501
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
502
+ proxy_set_header X-Forwarded-Proto $scheme;
503
+
504
+ # SSE support
505
+ proxy_buffering off;
506
+ proxy_cache off;
507
+ proxy_read_timeout 24h;
508
+ }
509
+ }
510
+ ```
511
+
512
+ Enable and reload:
513
+ ```bash
514
+ ln -s /etc/nginx/sites-available/reflexive /etc/nginx/sites-enabled/
515
+ nginx -t
516
+ systemctl reload nginx
517
+ ```
518
+
519
+ ## Security Considerations
520
+
521
+ ### API Authentication
522
+
523
+ **Generate strong API key**:
524
+
525
+ ```bash
526
+ # Generate random key
527
+ openssl rand -base64 32
528
+
529
+ # Set as environment variable
530
+ export REFLEXIVE_API_KEY="generated-key-here"
531
+ ```
532
+
533
+ **Use in requests**:
534
+
535
+ ```bash
536
+ curl -H "Authorization: Bearer generated-key-here" \
537
+ https://your-reflexive.app/api/sandboxes
538
+ ```
539
+
540
+ ### Rate Limiting
541
+
542
+ Rate limiting is built-in. Configure in `reflexive.config.js`:
543
+
544
+ ```javascript
545
+ export default {
546
+ mode: 'hosted',
547
+ rateLimit: {
548
+ maxRequests: 100, // Max requests
549
+ windowMs: 60000, // Per minute
550
+ skipPublicPaths: true // Skip /api/health
551
+ }
552
+ };
553
+ ```
554
+
555
+ ### Sandbox Isolation
556
+
557
+ Sandboxes are isolated by Vercel's infrastructure:
558
+ - Separate filesystems
559
+ - Network isolation
560
+ - Resource limits (CPU, memory)
561
+ - Automatic cleanup
562
+
563
+ ### Secrets Management
564
+
565
+ **Never commit secrets**. Use environment variables or secret managers.
566
+
567
+ **AWS Secrets Manager**:
568
+
569
+ ```bash
570
+ # Store secret
571
+ aws secretsmanager create-secret \
572
+ --name reflexive/anthropic-key \
573
+ --secret-string "sk-ant-xxx"
574
+
575
+ # Retrieve in app
576
+ const secret = await secretsManager.getSecretValue({
577
+ SecretId: 'reflexive/anthropic-key'
578
+ }).promise();
579
+ ```
580
+
581
+ **Kubernetes Secrets**:
582
+
583
+ ```bash
584
+ kubectl create secret generic reflexive-secrets \
585
+ --from-literal=anthropic-api-key=sk-ant-xxx
586
+ ```
587
+
588
+ ## Storage Configuration
589
+
590
+ ### S3 Storage
591
+
592
+ **Create S3 bucket**:
593
+
594
+ ```bash
595
+ aws s3 mb s3://reflexive-snapshots --region us-east-1
596
+ ```
597
+
598
+ **Set bucket policy** (private):
599
+
600
+ ```json
601
+ {
602
+ "Version": "2012-10-17",
603
+ "Statement": [{
604
+ "Effect": "Deny",
605
+ "Principal": "*",
606
+ "Action": "s3:GetObject",
607
+ "Resource": "arn:aws:s3:::reflexive-snapshots/*",
608
+ "Condition": {
609
+ "StringNotEquals": {
610
+ "aws:PrincipalArn": "arn:aws:iam::ACCOUNT:user/reflexive"
611
+ }
612
+ }
613
+ }]
614
+ }
615
+ ```
616
+
617
+ **Configure**:
618
+
619
+ ```bash
620
+ export AWS_ACCESS_KEY_ID=xxx
621
+ export AWS_SECRET_ACCESS_KEY=xxx
622
+ export REFLEXIVE_SNAPSHOT_BUCKET=reflexive-snapshots
623
+ export AWS_REGION=us-east-1
624
+ ```
625
+
626
+ ### Cloudflare R2
627
+
628
+ **Create R2 bucket**:
629
+ 1. Go to Cloudflare dashboard
630
+ 2. Navigate to R2
631
+ 3. Create bucket: `reflexive-snapshots`
632
+
633
+ **Create API token**:
634
+ 1. R2 > Manage R2 API Tokens
635
+ 2. Create token with read/write permissions
636
+
637
+ **Configure**:
638
+
639
+ ```bash
640
+ export AWS_ACCESS_KEY_ID=r2-access-key-id
641
+ export AWS_SECRET_ACCESS_KEY=r2-secret-key
642
+ export REFLEXIVE_S3_ENDPOINT=https://account.r2.cloudflarestorage.com
643
+ export REFLEXIVE_SNAPSHOT_BUCKET=reflexive-snapshots
644
+ ```
645
+
646
+ ### Memory Storage
647
+
648
+ For development or testing (not persistent):
649
+
650
+ ```javascript
651
+ // reflexive.config.js
652
+ export default {
653
+ mode: 'hosted',
654
+ hosted: {
655
+ snapshotStorage: {
656
+ provider: 'memory'
657
+ }
658
+ }
659
+ };
660
+ ```
661
+
662
+ **Warning**: Snapshots are lost on restart.
663
+
664
+ ## Monitoring and Logging
665
+
666
+ ### Health Checks
667
+
668
+ **HTTP health endpoint**:
669
+
670
+ ```bash
671
+ curl https://your-reflexive.app/api/health
672
+ ```
673
+
674
+ Response:
675
+ ```json
676
+ {
677
+ "status": "ok",
678
+ "sandboxes": 5,
679
+ "running": 3
680
+ }
681
+ ```
682
+
683
+ **Use in monitoring**:
684
+
685
+ ```yaml
686
+ # Kubernetes liveness probe
687
+ livenessProbe:
688
+ httpGet:
689
+ path: /api/health
690
+ port: 3099
691
+ initialDelaySeconds: 5
692
+ periodSeconds: 10
693
+ ```
694
+
695
+ ### Metrics
696
+
697
+ Export metrics for monitoring:
698
+
699
+ ```javascript
700
+ // In your app
701
+ import { makeReflexive } from 'reflexive';
702
+
703
+ const r = makeReflexive({
704
+ tools: [
705
+ {
706
+ name: 'get_metrics',
707
+ description: 'Get application metrics',
708
+ schema: { type: 'object', properties: {} },
709
+ handler: async () => ({
710
+ content: [{
711
+ type: 'text',
712
+ text: JSON.stringify({
713
+ uptime: process.uptime(),
714
+ memory: process.memoryUsage(),
715
+ sandboxes: manager.count()
716
+ })
717
+ }]
718
+ })
719
+ }
720
+ ]
721
+ });
722
+ ```
723
+
724
+ ### Log Aggregation
725
+
726
+ **Send logs to external service**:
727
+
728
+ ```javascript
729
+ // Using Winston
730
+ import winston from 'winston';
731
+
732
+ const logger = winston.createLogger({
733
+ transports: [
734
+ new winston.transports.File({ filename: 'app.log' }),
735
+ new winston.transports.Http({
736
+ host: 'logs.example.com',
737
+ port: 8080,
738
+ path: '/logs'
739
+ })
740
+ ]
741
+ });
742
+
743
+ appState.on('log', (entry) => {
744
+ logger.log({
745
+ level: entry.type,
746
+ message: entry.message,
747
+ timestamp: entry.timestamp
748
+ });
749
+ });
750
+ ```
751
+
752
+ ## Scaling
753
+
754
+ ### Horizontal Scaling
755
+
756
+ Reflexive can be scaled horizontally with some considerations:
757
+
758
+ **Stateless design**: Each instance manages its own sandboxes
759
+ **Shared storage**: Use S3/R2 for snapshot persistence
760
+ **Load balancing**: Round-robin or least-connections
761
+
762
+ **Example with multiple instances**:
763
+
764
+ ```yaml
765
+ # docker-compose.yml
766
+ services:
767
+ reflexive-1:
768
+ build: .
769
+ ports:
770
+ - "3099:3099"
771
+ environment:
772
+ - INSTANCE_ID=1
773
+
774
+ reflexive-2:
775
+ build: .
776
+ ports:
777
+ - "3100:3099"
778
+ environment:
779
+ - INSTANCE_ID=2
780
+
781
+ nginx:
782
+ image: nginx
783
+ ports:
784
+ - "80:80"
785
+ volumes:
786
+ - ./nginx.conf:/etc/nginx/nginx.conf
787
+ depends_on:
788
+ - reflexive-1
789
+ - reflexive-2
790
+ ```
791
+
792
+ ### Resource Limits
793
+
794
+ Configure per deployment:
795
+
796
+ **Docker**:
797
+ ```bash
798
+ docker run \
799
+ --memory="2g" \
800
+ --cpus="2" \
801
+ reflexive:latest
802
+ ```
803
+
804
+ **Kubernetes**:
805
+ ```yaml
806
+ resources:
807
+ requests:
808
+ memory: "512Mi"
809
+ cpu: "500m"
810
+ limits:
811
+ memory: "2Gi"
812
+ cpu: "2000m"
813
+ ```
814
+
815
+ **Per-sandbox limits** (in config):
816
+ ```javascript
817
+ export default {
818
+ sandbox: {
819
+ vcpus: 2,
820
+ memory: 2048, // MB
821
+ timeout: '30m'
822
+ }
823
+ };
824
+ ```
825
+
826
+ ## Troubleshooting
827
+
828
+ ### Common Issues
829
+
830
+ **Port already in use**:
831
+ ```bash
832
+ # Find process
833
+ lsof -i :3099
834
+
835
+ # Kill process
836
+ kill -9 PID
837
+
838
+ # Or use different port
839
+ PORT=3100 node dist/cli.js
840
+ ```
841
+
842
+ **Sandbox creation fails**:
843
+ ```bash
844
+ # Check Vercel token
845
+ echo $VERCEL_TOKEN
846
+
847
+ # Test sandbox creation
848
+ curl -H "Authorization: Bearer $VERCEL_TOKEN" \
849
+ https://api.vercel.com/v1/sandbox
850
+ ```
851
+
852
+ **Storage errors**:
853
+ ```bash
854
+ # Test S3 access
855
+ aws s3 ls s3://reflexive-snapshots
856
+
857
+ # Check credentials
858
+ aws sts get-caller-identity
859
+ ```
860
+
861
+ **Memory issues**:
862
+ ```bash
863
+ # Increase Node.js memory
864
+ NODE_OPTIONS="--max-old-space-size=4096" node dist/cli.js
865
+
866
+ # Or in PM2
867
+ pm2 start dist/cli.js --node-args="--max-old-space-size=4096"
868
+ ```
869
+
870
+ ### Debug Mode
871
+
872
+ Enable verbose logging:
873
+
874
+ ```bash
875
+ DEBUG=reflexive:* node dist/cli.js --mode hosted
876
+ ```
877
+
878
+ Or set in environment:
879
+ ```bash
880
+ export DEBUG=reflexive:*
881
+ ```
882
+
883
+ ---
884
+
885
+ **Next**: Check [Examples](./examples.md) for usage patterns and integrations.