@chimerai/cli 0.2.88 → 0.2.90

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.
@@ -1 +1 @@
1
- {"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAiBH,UAAU,UAAU;IAClB,GAAG,EAAE,MAAM,CAAC;CACb;AAmzED,wBAAsB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,iBAyHtE"}
1
+ {"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAiBH,UAAU,UAAU;IAClB,GAAG,EAAE,MAAM,CAAC;CACb;AAk5ED,wBAAsB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,iBAyHtE"}
@@ -185,6 +185,18 @@ model ApiKey {
185
185
  @@index([keyHash])
186
186
  }
187
187
  `,
188
+ filePatches: [
189
+ {
190
+ marker: '// @chimerai component=AppPageNoAuth version=1.0',
191
+ target: 'app/page.tsx',
192
+ generator: () => templates.generateAppPage(),
193
+ },
194
+ {
195
+ marker: '// @chimerai component=MiddlewareNoAuth version=1.0',
196
+ target: 'middleware.ts',
197
+ generator: () => templates.generateMiddleware(),
198
+ },
199
+ ],
188
200
  envVars: [
189
201
  {
190
202
  key: 'DATABASE_URL',
@@ -285,6 +297,7 @@ Next steps:
285
297
  name: 'chat-ui',
286
298
  displayName: 'Chat UI',
287
299
  description: 'Full-featured chat interface with streaming, conversation management, and multi-provider support',
300
+ requiredFeatures: ['auth'],
288
301
  requiredUtils: [
289
302
  { generator: () => templates.generateUseAppNameHook(), target: 'lib/use-app-name.ts' },
290
303
  ],
@@ -774,6 +787,7 @@ Next steps:
774
787
  name: 'billing',
775
788
  displayName: 'Billing System',
776
789
  description: 'Stripe integration for subscriptions',
790
+ requiredFeatures: ['auth'],
777
791
  files: [
778
792
  {
779
793
  generator: () => templates.generateBillingPage(),
@@ -884,6 +898,7 @@ Next steps:
884
898
  name: 'audit-log',
885
899
  displayName: 'Audit Log',
886
900
  description: 'Compliance audit logging — track all admin and user actions',
901
+ requiredFeatures: ['auth', 'admin-dashboard'],
887
902
  files: [
888
903
  {
889
904
  generator: () => templates.generateAdminLogsPage(),
@@ -904,6 +919,7 @@ Next steps:
904
919
  name: 'admin-dashboard',
905
920
  displayName: 'Admin Dashboard',
906
921
  description: 'Complete admin panel with user/role management, settings, audit logs, and RBAC',
922
+ requiredFeatures: ['auth'],
907
923
  files: [
908
924
  // Admin layout with session + admin role guard
909
925
  {
@@ -1159,7 +1175,50 @@ function transformSchemaForSqlite(schema) {
1159
1175
  * Generic component addition function (PHASE 4 refactoring)
1160
1176
  * Uses inline template generators — no fs.copy(), no dependency on templates/ folder
1161
1177
  */
1178
+ /**
1179
+ * Checks if a given feature marker exists anywhere in the project's package.json
1180
+ * or in a generated file (by scanning for the @chimerai marker convention).
1181
+ * We use presence of installed packages as a proxy:
1182
+ * - 'auth' → next-auth in dependencies
1183
+ * - 'rbac' → @chimerai/rbac or lib/rbac.ts present
1184
+ * - 'admin-dashboard'→ @chimerai/admin-ui or app/admin present
1185
+ * - 'billing' → stripe in dependencies
1186
+ */
1187
+ async function hasFeature(feature, targetDir) {
1188
+ const pkgPath = path_1.default.join(targetDir, 'package.json');
1189
+ try {
1190
+ const pkg = await fs_extra_1.default.readJson(pkgPath);
1191
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
1192
+ if (feature === 'auth')
1193
+ return 'next-auth' in deps;
1194
+ if (feature === 'billing')
1195
+ return 'stripe' in deps;
1196
+ if (feature === 'rbac') {
1197
+ return '@chimerai/rbac' in deps || (await fs_extra_1.default.pathExists(path_1.default.join(targetDir, 'lib/rbac.ts')));
1198
+ }
1199
+ if (feature === 'admin-dashboard') {
1200
+ return ('@chimerai/admin-ui' in deps || (await fs_extra_1.default.pathExists(path_1.default.join(targetDir, 'app/admin'))));
1201
+ }
1202
+ }
1203
+ catch {
1204
+ // ignore — treat as missing
1205
+ }
1206
+ return false;
1207
+ }
1162
1208
  async function addComponent(config, targetDir) {
1209
+ // ── Pre-flight: check required features ────────────────────────────────
1210
+ if (config.requiredFeatures && config.requiredFeatures.length > 0) {
1211
+ const missing = [];
1212
+ for (const req of config.requiredFeatures) {
1213
+ if (!(await hasFeature(req, targetDir)))
1214
+ missing.push(req);
1215
+ }
1216
+ if (missing.length > 0) {
1217
+ console.error(chalk_1.default.red(`\n✗ Cannot add "${config.name}" — missing required feature(s): ${missing.map((f) => `"${f}"`).join(', ')}`));
1218
+ console.error(chalk_1.default.yellow(` Run first: ${missing.map((f) => `chimerai add ${f}`).join(' then ')}`));
1219
+ process.exit(1);
1220
+ }
1221
+ }
1163
1222
  const spinner = (0, ora_1.default)(`Adding ${config.displayName}...`).start();
1164
1223
  try {
1165
1224
  // 1. Generate and write all required files
@@ -1200,6 +1259,23 @@ async function addComponent(config, targetDir) {
1200
1259
  }
1201
1260
  // 1.6 (removed) — We no longer patch the user's root layout.
1202
1261
  // Instead, the postAddMessage tells the user how to add SessionProvider.
1262
+ // 1.6b Apply filePatches — upgrade existing no-auth files to auth-aware versions
1263
+ if (config.filePatches) {
1264
+ for (const patch of config.filePatches) {
1265
+ const targetPath = path_1.default.join(targetDir, patch.target);
1266
+ if (!(await fs_extra_1.default.pathExists(targetPath)))
1267
+ continue;
1268
+ const existing = await fs_extra_1.default.readFile(targetPath, 'utf-8');
1269
+ if (existing.includes(patch.marker)) {
1270
+ // File has the no-auth marker \u2014 replace it with auth-aware version
1271
+ const bakPath = targetPath + '.bak';
1272
+ await fs_extra_1.default.writeFile(bakPath, existing); // backup
1273
+ await fs_extra_1.default.writeFile(targetPath, patch.generator());
1274
+ spinner.text = `Adding ${config.displayName}... (upgraded ${patch.target})`;
1275
+ }
1276
+ // If marker absent, file is already the auth-aware version \u2014 skip
1277
+ }
1278
+ }
1203
1279
  // 1.7 Auto-write environment variables to .env
1204
1280
  if (config.envVars && config.envVars.length > 0) {
1205
1281
  const envPath = path_1.default.join(targetDir, '.env');
@@ -1 +1 @@
1
- {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAmBH,UAAU,aAAa;IACrB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AA+CD,wBAAsB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,iBAuH9E"}
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAmBH,UAAU,aAAa;IACrB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAmED,wBAAsB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,iBAyI9E"}
@@ -54,14 +54,34 @@ const license_js_1 = require("../license.js");
54
54
  /** Canonical feature definitions for `chimerai create` */
55
55
  const AVAILABLE_FEATURES = [
56
56
  { name: '🔐 Authentication (NextAuth)', value: 'auth', licenseKey: 'auth', checked: true },
57
- { name: '👥 RBAC System (Users, Roles, Permissions)', value: 'rbac', licenseKey: 'rbac', checked: true },
58
- { name: '🔌 Model Providers Management', value: 'model-providers', licenseKey: 'model-providers', checked: true },
59
- { name: '📝 Prompt Template Management', value: 'prompt-management', licenseKey: 'prompt-management', checked: true },
57
+ {
58
+ name: '👥 RBAC System (Users, Roles, Permissions)',
59
+ value: 'rbac',
60
+ licenseKey: 'rbac',
61
+ checked: true,
62
+ },
63
+ {
64
+ name: '🔌 Model Providers Management',
65
+ value: 'model-providers',
66
+ licenseKey: 'model-providers',
67
+ checked: true,
68
+ },
69
+ {
70
+ name: '📝 Prompt Template Management',
71
+ value: 'prompt-management',
72
+ licenseKey: 'prompt-management',
73
+ checked: true,
74
+ },
60
75
  { name: '💬 AI Chat Interface', value: 'ai-chat', licenseKey: 'ai-chat', checked: false },
61
76
  { name: '🔍 RAG / Vector Store (FAISS)', value: 'rag', licenseKey: 'rag', checked: false },
62
77
  { name: '💳 Billing System (Stripe)', value: 'billing', licenseKey: 'billing', checked: false },
63
78
  { name: '📊 API Usage Analytics', value: 'analytics', licenseKey: 'analytics', checked: true },
64
- { name: '🎨 Admin Dashboard', value: 'admin-dashboard', licenseKey: 'admin-dashboard', checked: true },
79
+ {
80
+ name: '🎨 Admin Dashboard',
81
+ value: 'admin-dashboard',
82
+ licenseKey: 'admin-dashboard',
83
+ checked: true,
84
+ },
65
85
  ];
66
86
  function getRequiredTierLabel(licenseKey) {
67
87
  if (license_js_1.FREE_COMPONENTS.has(licenseKey))
@@ -133,6 +153,22 @@ async function createCommand(projectName, options) {
133
153
  if (selectedFeatures.length === 0) {
134
154
  (0, utils_js_1.handleCliError)('No features selected');
135
155
  }
156
+ // Validate feature combinations and warn about missing dependencies
157
+ const featureWarnings = validateFeatureCombination(selectedFeatures);
158
+ if (featureWarnings.length > 0) {
159
+ console.warn(chalk_1.default.yellow('\n⚠️ Feature combination warnings:'));
160
+ featureWarnings.forEach((w) => console.warn(chalk_1.default.yellow(` • ${w}`)));
161
+ const answers = await inquirer_1.default.prompt([
162
+ {
163
+ type: 'confirm',
164
+ name: 'confirmed',
165
+ message: 'Continue anyway?',
166
+ default: true,
167
+ },
168
+ ]);
169
+ if (!answers.confirmed)
170
+ process.exit(0);
171
+ }
136
172
  console.log(chalk_1.default.bold.green('\n✨ Creating project with features:'));
137
173
  selectedFeatures.forEach((f) => {
138
174
  const feature = AVAILABLE_FEATURES.find((feat) => feat.value === f);
@@ -156,9 +192,11 @@ async function createCommand(projectName, options) {
156
192
  console.log(chalk_1.default.white(` cd ${projectName}`));
157
193
  console.log(chalk_1.default.white(' npm run dev'));
158
194
  console.log(chalk_1.default.gray('\n Server will run on http://localhost:3001\n'));
159
- console.log(chalk_1.default.yellow('Login with:'));
160
- console.log(chalk_1.default.white(' Email: admin@example.com'));
161
- console.log(chalk_1.default.white(' Password: admin123\n'));
195
+ if (selectedFeatures.includes('auth')) {
196
+ console.log(chalk_1.default.yellow('Login with:'));
197
+ console.log(chalk_1.default.white(' Email: admin@example.com'));
198
+ console.log(chalk_1.default.white(' Password: admin123\n'));
199
+ }
162
200
  }
163
201
  catch (error) {
164
202
  console.log(chalk_1.default.red('\n❌ Installation failed'));
@@ -187,6 +225,33 @@ async function createCommand(projectName, options) {
187
225
  }
188
226
  console.log(chalk_1.default.gray('\n Server will run on http://localhost:3001\n'));
189
227
  }
228
+ /**
229
+ * Validates that the selected feature combination makes sense.
230
+ * Returns an array of human-readable warning strings (empty = OK).
231
+ */
232
+ function validateFeatureCombination(features) {
233
+ const warnings = [];
234
+ const authRequired = [
235
+ 'rbac',
236
+ 'admin-dashboard',
237
+ 'billing',
238
+ 'mfa',
239
+ 'gdpr',
240
+ 'audit-log',
241
+ 'chat-ui',
242
+ ];
243
+ if (!features.includes('auth')) {
244
+ authRequired.forEach((f) => {
245
+ if (features.includes(f)) {
246
+ warnings.push(`"${f}" requires "auth" — it may not work correctly without it`);
247
+ }
248
+ });
249
+ }
250
+ if (features.includes('audit-log') && !features.includes('admin-dashboard')) {
251
+ warnings.push('"audit-log" works best with "admin-dashboard"');
252
+ }
253
+ return warnings;
254
+ }
190
255
  async function createProject(targetDir, projectName, features, sqlite) {
191
256
  const spinner = (0, ora_1.default)('Creating project structure...').start();
192
257
  try {
@@ -238,7 +303,7 @@ async function createProject(targetDir, projectName, features, sqlite) {
238
303
  }
239
304
  catch (error) {
240
305
  spinner.fail(chalk_1.default.red('Failed to create project'));
241
- console.error(error.message);
306
+ console.error(error instanceof Error ? error.message : String(error));
242
307
  throw error;
243
308
  }
244
309
  }
@@ -282,7 +347,9 @@ async function createBaseStructure(targetDir, projectName, features) {
282
347
  : templates.generateAppLayout(projectName);
283
348
  await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'app/layout.tsx'), layoutContent);
284
349
  // Create app/page.tsx using template generator
285
- const pageContent = templates.generateAppPage();
350
+ const pageContent = features.includes('auth')
351
+ ? templates.generateAppPage()
352
+ : templates.generateAppPageNoAuth();
286
353
  await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'app/page.tsx'), pageContent);
287
354
  // Create globals.css using template generator
288
355
  const globalsCss = templates.generateGlobalsCss();
@@ -294,18 +361,19 @@ async function createPackageJson(targetDir, projectName, features) {
294
361
  react: '^18.3.1',
295
362
  'react-dom': '^18.3.1',
296
363
  '@prisma/client': '^5.22.0',
297
- // Auth is core infrastructure — routes, middleware, and API handlers all depend on it
298
- 'next-auth': '^4.24.10',
299
- '@auth/prisma-adapter': '^2.11.1',
300
- 'bcryptjs': '^2.4.3',
301
- 'next-themes': '^0.4.4',
302
- 'sonner': '^1.7.0',
303
364
  };
365
+ // Auth dependencies — only when auth feature is selected
366
+ if (features.includes('auth')) {
367
+ dependencies['next-auth'] = '^4.24.10';
368
+ dependencies['@auth/prisma-adapter'] = '^2.11.1';
369
+ dependencies['bcryptjs'] = '^2.4.3';
370
+ dependencies['next-themes'] = '^0.4.4';
371
+ dependencies['sonner'] = '^1.7.0';
372
+ }
304
373
  const devDependencies = {
305
374
  '@types/node': '^20',
306
375
  '@types/react': '^18',
307
376
  '@types/react-dom': '^18',
308
- '@types/bcryptjs': '^2.4.6',
309
377
  typescript: '^5',
310
378
  tailwindcss: '^3.4.0',
311
379
  postcss: '^8.5.10',
@@ -313,6 +381,9 @@ async function createPackageJson(targetDir, projectName, features) {
313
381
  prisma: '^5.22.0',
314
382
  tsx: '^4.20.6',
315
383
  };
384
+ if (features.includes('auth')) {
385
+ devDependencies['@types/bcryptjs'] = '^2.4.6';
386
+ }
316
387
  // Note: ChimerAI workspace packages are not yet published to npm
317
388
  // For standalone projects, these features will need manual implementation
318
389
  // or you can use the complete starter kit with 'chimerai init'
@@ -358,10 +429,8 @@ async function createPackageJson(targetDir, projectName, features) {
358
429
  },
359
430
  dependencies,
360
431
  devDependencies,
361
- overrides: {
362
- // Force uuid@11 to suppress uuid@8 deprecation warning from next-auth@4
363
- uuid: '^11',
364
- },
432
+ // uuid override only needed when next-auth is installed (suppresses uuid@8 deprecation warning)
433
+ ...(features.includes('auth') ? { overrides: { uuid: '^11' } } : {}),
365
434
  prisma: {
366
435
  seed: 'tsx prisma/seed.ts',
367
436
  },
@@ -857,8 +926,10 @@ async function copyFeatureFiles(targetDir, features) {
857
926
  }
858
927
  // Health check endpoint (used by Docker healthcheck and monitoring)
859
928
  const healthRoute = templates.generateHealthRoute();
860
- // Next.js middleware (security headers + CORS for widget endpoints)
861
- const middleware = templates.generateMiddleware();
929
+ // Next.js middleware auth-aware version when auth selected, CORS-only otherwise
930
+ const middleware = features.includes('auth')
931
+ ? templates.generateMiddleware()
932
+ : templates.generateMiddlewareNoAuth();
862
933
  await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'middleware.ts'), middleware);
863
934
  await fs_extra_1.default.ensureDir(path_1.default.join(targetDir, 'app/api/health'));
864
935
  await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'app/api/health/route.ts'), healthRoute);
@@ -941,6 +1012,14 @@ async function copyFeatureFiles(targetDir, features) {
941
1012
  const providersPage = templates.generateModelProvidersPage();
942
1013
  await fs_extra_1.default.ensureDir(path_1.default.join(targetDir, 'app/dashboard/providers'));
943
1014
  await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'app/dashboard/providers/page.tsx'), providersPage);
1015
+ // No-auth dashboard landing page + layout (when auth is not selected)
1016
+ if (!features.includes('auth')) {
1017
+ const noAuthDashPage = templates.generateDashboardPageNoAuth(features);
1018
+ await fs_extra_1.default.ensureDir(path_1.default.join(targetDir, 'app/dashboard'));
1019
+ await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'app/dashboard/page.tsx'), noAuthDashPage);
1020
+ const noAuthDashLayout = templates.generateDashboardLayoutNoAuth();
1021
+ await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'app/dashboard/layout.tsx'), noAuthDashLayout);
1022
+ }
944
1023
  if (features.includes('admin')) {
945
1024
  // Admin layout with session check + admin role guard
946
1025
  const adminLayout = templates.generateAdminLayout();
@@ -1155,7 +1234,7 @@ async function getServerSessionWithPermissions() {
1155
1234
  ].join('\n') + '\n');
1156
1235
  // Chat page
1157
1236
  await fs_extra_1.default.ensureDir(path_1.default.join(targetDir, 'app/(app)/chat'));
1158
- await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'app/(app)/chat/page.tsx'), templates.generateChatPage());
1237
+ await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'app/(app)/chat/page.tsx'), features.includes('auth') ? templates.generateChatPage() : templates.generateChatPageNoAuth());
1159
1238
  // API routes
1160
1239
  await fs_extra_1.default.ensureDir(path_1.default.join(targetDir, 'app/api/v1/chat/stream'));
1161
1240
  await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'app/api/v1/chat/stream/route.ts'), templates.generateChatStreamRouteWithPersistence());
@@ -1214,8 +1293,20 @@ async function getServerSessionWithPermissions() {
1214
1293
  }
1215
1294
  }
1216
1295
  async function createSeedScript(targetDir, features, sqlite) {
1296
+ // Without auth there are no users/providers to seed — write a minimal placeholder
1297
+ if (!features.includes('auth')) {
1298
+ const minimalSeed = `import { PrismaClient } from '@prisma/client';
1299
+ const prisma = new PrismaClient();
1300
+ async function main() {
1301
+ console.log('🌱 No auth feature selected — nothing to seed yet.');
1302
+ console.log(' Run: chimerai add auth to add authentication.');
1303
+ }
1304
+ main().catch(console.error).finally(() => prisma.$disconnect());
1305
+ `;
1306
+ await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'prisma/seed.ts'), minimalSeed);
1307
+ return;
1308
+ }
1217
1309
  // Generate seed script with feature-specific configuration
1218
- // next-auth / bcryptjs are always installed (core infrastructure)
1219
1310
  const seedScript = `import { PrismaClient } from '@prisma/client';
1220
1311
  import * as bcrypt from 'bcryptjs';
1221
1312
  import crypto from 'crypto';
@@ -1472,10 +1563,7 @@ echo Next steps:
1472
1563
  echo npm run dev
1473
1564
  echo Open: http://localhost:3001
1474
1565
  echo.
1475
- echo Login with:
1476
- echo Email: admin@example.com
1477
- echo Password: admin123
1478
- echo.
1566
+ ${features.includes('auth') ? 'echo Login with:\necho Email: admin@example.com\necho Password: admin123\necho.' : ''}
1479
1567
  pause
1480
1568
  `
1481
1569
  : `@echo off
@@ -1544,10 +1632,7 @@ echo Next steps:
1544
1632
  echo npm run dev
1545
1633
  echo Open: http://localhost:3001
1546
1634
  echo.
1547
- echo Login with:
1548
- echo Email: admin@example.com
1549
- echo Password: admin123
1550
- echo.
1635
+ ${features.includes('auth') ? 'echo Login with:\necho Email: admin@example.com\necho Password: admin123\necho.' : ''}
1551
1636
  pause
1552
1637
  `;
1553
1638
  // Linux/macOS install.sh
@@ -1585,10 +1670,7 @@ echo "Next steps:"
1585
1670
  echo " npm run dev"
1586
1671
  echo " Open: http://localhost:3001"
1587
1672
  echo ""
1588
- echo "Login with:"
1589
- echo " Email: admin@example.com"
1590
- echo " Password: admin123"
1591
- echo ""
1673
+ ${features.includes('auth') ? 'echo "Login with:"\necho " Email: admin@example.com"\necho " Password: admin123"\necho ""' : ''}
1592
1674
  `
1593
1675
  : `#!/bin/bash
1594
1676
  set -e
@@ -1635,10 +1717,7 @@ echo "Next steps:"
1635
1717
  echo " npm run dev"
1636
1718
  echo " Open: http://localhost:3001"
1637
1719
  echo ""
1638
- echo "Login with:"
1639
- echo " Email: admin@example.com"
1640
- echo " Password: admin123"
1641
- echo ""
1720
+ ${features.includes('auth') ? 'echo "Login with:"\necho " Email: admin@example.com"\necho " Password: admin123"\necho ""' : ''}
1642
1721
  `;
1643
1722
  await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'install.bat'), installBat);
1644
1723
  await fs_extra_1.default.writeFile(path_1.default.join(targetDir, 'install.sh'), installSh);
@@ -1723,12 +1802,7 @@ npm run dev
1723
1802
 
1724
1803
  Open [http://localhost:3001](http://localhost:3001) in your browser.
1725
1804
 
1726
- ### Default Admin Credentials
1727
-
1728
- - Email: admin@example.com
1729
- - Password: admin123
1730
-
1731
- ⚠️ Change these in production!
1805
+ ${features.includes('auth') ? `### Default Admin Credentials\n\n- Email: admin@example.com\n- Password: admin123\n\n⚠️ Change these in production!` : ''}
1732
1806
 
1733
1807
  ## Available Scripts
1734
1808
 
@@ -1790,8 +1864,7 @@ Commercial License - See LICENSE file
1790
1864
  5. \`pnpm dev\`
1791
1865
 
1792
1866
  ## Default Login
1793
- - Email: admin@example.com
1794
- - Password: admin123
1867
+ ${features.includes('auth') ? '- Email: admin@example.com\n- Password: admin123' : '- No auth configured. Run: `chimerai add auth`'}
1795
1868
 
1796
1869
  ## CLI Commands
1797
1870
  - \`chimerai add <component>\` — Add features
@@ -7,6 +7,7 @@
7
7
  * Displays conversations, allows provider selection, integrates StreamingChat component
8
8
  * @returns TypeScript/JSX content for app/dashboard/chat/page.tsx
9
9
  */
10
+ export declare function generateChatPageNoAuth(): string;
10
11
  export declare function generateChatPage(): string;
11
12
  /**
12
13
  * Generates the streaming Chat API route — Direct LLM provider communication with DB persistence
@@ -1 +1 @@
1
- {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../src/templates/chat.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAuLzC;AAED;;;;GAIG;AACH,wBAAgB,sCAAsC,IAAI,MAAM,CAwa/D;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,IAAI,MAAM,CAwEnD;AAMD;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAkb5C;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAuQ5C;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAwH1C;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CA+O5C;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CA+D9C;AAED;;;GAGG;AACH,wBAAgB,+BAA+B,IAAI,MAAM,CAyGxD"}
1
+ {"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../src/templates/chat.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAqI/C;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAuLzC;AAED;;;;GAIG;AACH,wBAAgB,sCAAsC,IAAI,MAAM,CAwa/D;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,IAAI,MAAM,CAwEnD;AAMD;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAkb5C;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAuQ5C;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAwH1C;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CA+O5C;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CA+D9C;AAED;;;GAGG;AACH,wBAAgB,+BAA+B,IAAI,MAAM,CAyGxD"}
@@ -4,6 +4,7 @@
4
4
  * Generates streaming chat UI, conversation management, and AI model integration
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.generateChatPageNoAuth = generateChatPageNoAuth;
7
8
  exports.generateChatPage = generateChatPage;
8
9
  exports.generateChatStreamRouteWithPersistence = generateChatStreamRouteWithPersistence;
9
10
  exports.generateConversationsRoute = generateConversationsRoute;
@@ -18,6 +19,140 @@ exports.generateConversationDetailRoute = generateConversationDetailRoute;
18
19
  * Displays conversations, allows provider selection, integrates StreamingChat component
19
20
  * @returns TypeScript/JSX content for app/dashboard/chat/page.tsx
20
21
  */
22
+ function generateChatPageNoAuth() {
23
+ return `// @chimerai component=ChatPageNoAuth version=1.0
24
+ 'use client';
25
+
26
+ import { useRef, useState } from 'react';
27
+ import { useAppName } from '@/lib/use-app-name';
28
+ import { useChat } from '@/components/chat/use-chat';
29
+ import { ChatMessage } from '@/components/chat/chat-message';
30
+ import { ChatInput } from '@/components/chat/chat-input';
31
+ import { ChatSidebar } from '@/components/chat/chat-sidebar';
32
+ import { ModelSelector } from '@/components/chat/model-selector';
33
+ import type { MessageActions } from '@/components/chat/chat-message';
34
+
35
+ export default function ChatPage() {
36
+ const messagesEndRef = useRef<HTMLDivElement>(null);
37
+ const [sidebarOpen, setSidebarOpen] = useState(false);
38
+ const appName = useAppName();
39
+
40
+ const {
41
+ messages,
42
+ isStreaming,
43
+ conversations,
44
+ selectedConversationId,
45
+ models,
46
+ selectedModelId,
47
+ creditBalance,
48
+ isLoadingConversation,
49
+ sendMessage,
50
+ stopStreaming,
51
+ selectConversation,
52
+ startNewChat,
53
+ deleteConversation,
54
+ renameConversation,
55
+ setSelectedModelId,
56
+ regenerateMessage,
57
+ editMessage,
58
+ deleteMessage,
59
+ } = useChat();
60
+
61
+ const handleSelectConversation = (id: string) => {
62
+ selectConversation(id);
63
+ setSidebarOpen(false);
64
+ };
65
+
66
+ const handleNewChat = () => {
67
+ startNewChat();
68
+ setSidebarOpen(false);
69
+ };
70
+
71
+ const messageActions: MessageActions = {
72
+ onRegenerate: regenerateMessage,
73
+ onEdit: editMessage,
74
+ onDelete: deleteMessage,
75
+ };
76
+
77
+ return (
78
+ <div className="flex h-screen bg-white dark:bg-gray-950 relative">
79
+ {sidebarOpen && (
80
+ <div
81
+ className="fixed inset-0 bg-black/50 z-30 md:hidden"
82
+ onClick={() => setSidebarOpen(false)}
83
+ />
84
+ )}
85
+ <aside className={\`fixed inset-y-0 left-0 z-40 w-72 border-r border-gray-200 dark:border-gray-800 transform transition-transform duration-200 ease-in-out
86
+ \${sidebarOpen ? 'translate-x-0' : '-translate-x-full'}
87
+ md:relative md:translate-x-0 md:z-auto\`}>
88
+ <ChatSidebar
89
+ conversations={conversations}
90
+ selectedId={selectedConversationId}
91
+ onSelect={handleSelectConversation}
92
+ onNewChat={handleNewChat}
93
+ onDelete={deleteConversation}
94
+ onRename={renameConversation}
95
+ />
96
+ </aside>
97
+ <main className="flex-1 flex flex-col min-w-0">
98
+ <div className="flex items-center gap-3 border-b border-gray-200 dark:border-gray-800 px-4 py-2">
99
+ <button
100
+ onClick={() => setSidebarOpen(!sidebarOpen)}
101
+ className="p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 text-gray-500 md:hidden"
102
+ aria-label="Toggle sidebar"
103
+ >
104
+ <svg className="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
105
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
106
+ </svg>
107
+ </button>
108
+ <ModelSelector
109
+ models={models}
110
+ value={selectedModelId}
111
+ onValueChange={setSelectedModelId}
112
+ disabled={isStreaming}
113
+ />
114
+ <div className="flex-1" />
115
+ <span className="text-xs text-gray-400">{appName}</span>
116
+ </div>
117
+ <div className="flex-1 overflow-y-auto">
118
+ {isLoadingConversation ? (
119
+ <div className="flex items-center justify-center h-full">
120
+ <div className="text-gray-400">Loading conversation...</div>
121
+ </div>
122
+ ) : messages.length === 0 ? (
123
+ <div className="flex flex-col items-center justify-center h-full text-center px-4">
124
+ <svg className="h-12 w-12 text-gray-300 mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
125
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z" />
126
+ </svg>
127
+ <h2 className="text-lg font-medium text-gray-700 dark:text-gray-300 mb-1">Start a conversation</h2>
128
+ <p className="text-sm text-gray-400">Send a message to begin chatting with AI</p>
129
+ </div>
130
+ ) : (
131
+ <div className="max-w-3xl mx-auto">
132
+ {messages.map((msg, idx) => (
133
+ <ChatMessage
134
+ key={msg.id || idx}
135
+ message={msg}
136
+ index={idx}
137
+ actions={messageActions}
138
+ />
139
+ ))}
140
+ <div ref={messagesEndRef} />
141
+ </div>
142
+ )}
143
+ </div>
144
+ <ChatInput
145
+ onSend={sendMessage}
146
+ onStop={stopStreaming}
147
+ isStreaming={isStreaming}
148
+ creditBalance={creditBalance}
149
+ />
150
+ </main>
151
+ </div>
152
+ );
153
+ }
154
+ `;
155
+ }
21
156
  function generateChatPage() {
22
157
  return `// @chimerai component=ChatPage version=2.0
23
158
  'use client';
@@ -1 +1 @@
1
- {"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../src/templates/components.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;GAIG;AACH,wBAAgB,0BAA0B,IAAI,MAAM,CA+TnD;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,IAAI,MAAM,CA2QrD;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CA4D/C"}
1
+ {"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../src/templates/components.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;GAIG;AACH,wBAAgB,0BAA0B,IAAI,MAAM,CAyTnD;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,IAAI,MAAM,CA2QrD;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CA4D/C"}
@@ -18,7 +18,6 @@ function generateModelProvidersPage() {
18
18
  'use client';
19
19
 
20
20
  import { useState, useEffect, useCallback } from 'react';
21
- import { useSession } from 'next-auth/react';
22
21
 
23
22
  interface ProviderModel {
24
23
  id: string;
@@ -64,7 +63,6 @@ const PROVIDER_TYPES = [
64
63
  const emptyForm: ProviderFormData = { name: '', type: 'openai', apiKey: '', baseUrl: '', defaultModel: '' };
65
64
 
66
65
  export default function ProvidersPage() {
67
- const { data: session } = useSession();
68
66
  const [providers, setProviders] = useState<Provider[]>([]);
69
67
  const [loading, setLoading] = useState(true);
70
68
  const [showForm, setShowForm] = useState(false);
@@ -190,10 +188,6 @@ export default function ProvidersPage() {
190
188
  setShowForm(true);
191
189
  };
192
190
 
193
- if (!session?.user?.id) {
194
- return <div className="container mx-auto py-8"><p className="text-center text-gray-500">Please sign in to manage model providers.</p></div>;
195
- }
196
-
197
191
  return (
198
192
  <div className="container mx-auto py-8 max-w-5xl">
199
193
  <div className="flex items-center justify-between mb-6">
@@ -6,15 +6,15 @@
6
6
  * written to a file in the generated project.
7
7
  */
8
8
  export { generateNextConfig, generateTsConfig, generateTailwindConfig, generatePostcssConfig, generateGlobalsCss, } from './config.js';
9
- export { generateAppLayout, generateAppLayoutWithAuth, generateAppPage, generateAuthBasicLayout, generateDashboardLayout, generateDashboardPage, generateProfilePage, generateUserProfileRoute, generateSettingsPage, generateUseAppNameHook, } from './layout.js';
9
+ export { generateAppLayout, generateAppLayoutWithAuth, generateAppPage, generateAppPageNoAuth, generateAuthBasicLayout, generateDashboardLayout, generateDashboardLayoutNoAuth, generateDashboardPage, generateDashboardPageNoAuth, generateProfilePage, generateUserProfileRoute, generateSettingsPage, generateUseAppNameHook, } from './layout.js';
10
10
  export { generateNextAuthRoute, generateLoginPage, generateSessionProvider, generateLogoutButton, generateNextAuthTypes, generateAuthLib, generateResolveAuth, } from './auth.js';
11
- export { generateChatPage, generateUseChatHook, generateChatMessage, generateChatInput, generateChatSidebar, generateModelSelector, generateChatStreamRouteWithPersistence, generateConversationsRoute, generateConversationDetailRoute, } from './chat.js';
11
+ export { generateChatPage, generateChatPageNoAuth, generateUseChatHook, generateChatMessage, generateChatInput, generateChatSidebar, generateModelSelector, generateChatStreamRouteWithPersistence, generateConversationsRoute, generateConversationDetailRoute, } from './chat.js';
12
12
  export { generateAdminLayout, generateAdminDashboardPage, generateAdminUsersPage, generateAdminRolesPage, generateAdminSettingsPage, generateAdminLogsPage, generateAuditLogHelper, generatePermissionsLib, generateRequirePermissionLib, } from './admin.js';
13
- export { generateModelProvidersPage, generatePromptManagementPage, generatePromptSelector } from './components.js';
13
+ export { generateModelProvidersPage, generatePromptManagementPage, generatePromptSelector, } from './components.js';
14
14
  export { generateAdminUsersRoute, generateAdminUsersIdRoute, generateAdminRolesRoute, generateAdminRolesIdRoute, generatePromptsRoute, generatePromptsIdRoute, generatePromptsSetDefaultRoute, generateHealthRoute, generateModelsRoute, generateV1ModelsRoute, generateAuditLogRoute, generateGdprDataExportRoute, generateGdprAccountDeleteRoute, generateAdminSettingsRoute, generateAppSettingsRoute, } from './api-routes.js';
15
15
  export { generateProviderCrudRoute, generateProviderIdRoute, generateProviderTestRoute, generateProviderSyncRoute, generateInternalProvidersRoute, generateInternalProviderIdRoute, generateInternalProviderUsageRoute, generateNotifyProviderChangeLib, } from './provider-routes.js';
16
16
  export { generatePrismaLib, generateEncryptionLib, generateApiKeyAuthLib, generateApiProtectionLib, generatePrismaSchema, } from './prisma.js';
17
- export { generateMiddleware } from './middleware.js';
17
+ export { generateMiddleware, generateMiddlewareNoAuth } from './middleware.js';
18
18
  export { generateStripeLib, generateBillingPage, generateCheckoutRoute, generatePortalRoute, generateSubscriptionRoute, generateStripeWebhookRoute, } from './billing.js';
19
19
  export { generateRagLib, generateRagPage, generateRagUploadRoute, generateRagQueryRoute, generateRagStatsRoute, generateRagClearRoute, generateRagDeleteRoute, } from './rag.js';
20
20
  export { generateWidgetBundle, generateWidgetLoader, generateApiKeyManagementPage, generateApiKeysRoute, generateApiKeyIdRoute, generateRateLimiter, } from './widget.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"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"}
@@ -7,9 +7,9 @@
7
7
  * written to a file in the generated project.
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.generatePromptsSetDefaultRoute = exports.generatePromptsIdRoute = exports.generatePromptsRoute = exports.generateAdminRolesIdRoute = exports.generateAdminRolesRoute = exports.generateAdminUsersIdRoute = exports.generateAdminUsersRoute = exports.generatePromptSelector = exports.generatePromptManagementPage = exports.generateModelProvidersPage = exports.generateRequirePermissionLib = exports.generatePermissionsLib = exports.generateAuditLogHelper = exports.generateAdminLogsPage = exports.generateAdminSettingsPage = exports.generateAdminRolesPage = exports.generateAdminUsersPage = exports.generateAdminDashboardPage = exports.generateAdminLayout = exports.generateConversationDetailRoute = exports.generateConversationsRoute = exports.generateChatStreamRouteWithPersistence = exports.generateModelSelector = exports.generateChatSidebar = exports.generateChatInput = exports.generateChatMessage = exports.generateUseChatHook = exports.generateChatPage = exports.generateResolveAuth = exports.generateAuthLib = exports.generateNextAuthTypes = exports.generateLogoutButton = exports.generateSessionProvider = exports.generateLoginPage = exports.generateNextAuthRoute = exports.generateUseAppNameHook = exports.generateSettingsPage = exports.generateUserProfileRoute = exports.generateProfilePage = exports.generateDashboardPage = exports.generateDashboardLayout = exports.generateAuthBasicLayout = exports.generateAppPage = exports.generateAppLayoutWithAuth = exports.generateAppLayout = exports.generateGlobalsCss = exports.generatePostcssConfig = exports.generateTailwindConfig = exports.generateTsConfig = exports.generateNextConfig = void 0;
11
- exports.generateGdprPage = exports.generateGdprLib = exports.MFA_USER_FIELDS = exports.MFA_SCHEMA_EXTENSION = exports.generateMfaPage = exports.generateMfaDisableRoute = exports.generateMfaVerifyRoute = exports.generateMfaSetupRoute = exports.generateMfaLib = exports.generateRateLimiter = exports.generateApiKeyIdRoute = exports.generateApiKeysRoute = exports.generateApiKeyManagementPage = exports.generateWidgetLoader = exports.generateWidgetBundle = exports.generateRagDeleteRoute = exports.generateRagClearRoute = exports.generateRagStatsRoute = exports.generateRagQueryRoute = exports.generateRagUploadRoute = exports.generateRagPage = exports.generateRagLib = exports.generateStripeWebhookRoute = exports.generateSubscriptionRoute = exports.generatePortalRoute = exports.generateCheckoutRoute = exports.generateBillingPage = exports.generateStripeLib = exports.generateMiddleware = exports.generatePrismaSchema = exports.generateApiProtectionLib = exports.generateApiKeyAuthLib = exports.generateEncryptionLib = exports.generatePrismaLib = exports.generateNotifyProviderChangeLib = exports.generateInternalProviderUsageRoute = exports.generateInternalProviderIdRoute = exports.generateInternalProvidersRoute = exports.generateProviderSyncRoute = exports.generateProviderTestRoute = exports.generateProviderIdRoute = exports.generateProviderCrudRoute = exports.generateAppSettingsRoute = exports.generateAdminSettingsRoute = exports.generateGdprAccountDeleteRoute = exports.generateGdprDataExportRoute = exports.generateAuditLogRoute = exports.generateV1ModelsRoute = exports.generateModelsRoute = exports.generateHealthRoute = void 0;
12
- exports.FEATURE_TEMPLATES = exports.ALL_TEMPLATES = exports.TOOL_GENERATORS = exports.generateToolsInit = exports.generateWebhookTools = exports.generateDeeplTools = exports.generateAirtableTools = exports.generateGoogleSheetsTools = exports.generateVisionTools = exports.generateNlpTools = exports.generateCodeTools = exports.generateDocumentTools = exports.generateWebTools = exports.generateRoutesInit = exports.generateToolsRoutes = exports.generateGuardrailsRoutes = exports.generateRagRoutes = exports.generateChatRoutes = exports.generateFileExtractor = exports.generateDockerComposeAiService = exports.generateAiServiceReadme = exports.generateAiServiceDockerfile = exports.generateAiServiceRequirements = exports.generateAiServiceModels = exports.generateAiServiceConfig = exports.generateAiServiceMain = exports.generateGuardrailsService = exports.generateVectorStore = exports.generateRagService = exports.generateEmbeddingService = exports.generateModerationService = exports.generateModelService = exports.generateChatService = exports.generateServicesInit = exports.generateProviderClient = exports.TOOL_INFO = exports.writeAiManifest = exports.readAiManifest = exports.generateDockerComposeDev = exports.generateDockerComposeProd = exports.generateDockerignore = exports.generateDockerfile = exports.GDPR_SCHEMA_EXTENSION = exports.generateGdprConsentRoute = void 0;
10
+ exports.generateAdminRolesRoute = exports.generateAdminUsersIdRoute = exports.generateAdminUsersRoute = exports.generatePromptSelector = exports.generatePromptManagementPage = exports.generateModelProvidersPage = exports.generateRequirePermissionLib = exports.generatePermissionsLib = exports.generateAuditLogHelper = exports.generateAdminLogsPage = exports.generateAdminSettingsPage = exports.generateAdminRolesPage = exports.generateAdminUsersPage = exports.generateAdminDashboardPage = exports.generateAdminLayout = exports.generateConversationDetailRoute = exports.generateConversationsRoute = exports.generateChatStreamRouteWithPersistence = exports.generateModelSelector = exports.generateChatSidebar = exports.generateChatInput = exports.generateChatMessage = exports.generateUseChatHook = exports.generateChatPageNoAuth = exports.generateChatPage = exports.generateResolveAuth = exports.generateAuthLib = exports.generateNextAuthTypes = exports.generateLogoutButton = exports.generateSessionProvider = exports.generateLoginPage = exports.generateNextAuthRoute = exports.generateUseAppNameHook = exports.generateSettingsPage = exports.generateUserProfileRoute = exports.generateProfilePage = exports.generateDashboardPageNoAuth = exports.generateDashboardPage = exports.generateDashboardLayoutNoAuth = exports.generateDashboardLayout = exports.generateAuthBasicLayout = exports.generateAppPageNoAuth = exports.generateAppPage = exports.generateAppLayoutWithAuth = exports.generateAppLayout = exports.generateGlobalsCss = exports.generatePostcssConfig = exports.generateTailwindConfig = exports.generateTsConfig = exports.generateNextConfig = void 0;
11
+ exports.generateMfaDisableRoute = exports.generateMfaVerifyRoute = exports.generateMfaSetupRoute = exports.generateMfaLib = exports.generateRateLimiter = exports.generateApiKeyIdRoute = exports.generateApiKeysRoute = exports.generateApiKeyManagementPage = exports.generateWidgetLoader = exports.generateWidgetBundle = exports.generateRagDeleteRoute = exports.generateRagClearRoute = exports.generateRagStatsRoute = exports.generateRagQueryRoute = exports.generateRagUploadRoute = exports.generateRagPage = exports.generateRagLib = exports.generateStripeWebhookRoute = exports.generateSubscriptionRoute = exports.generatePortalRoute = exports.generateCheckoutRoute = exports.generateBillingPage = exports.generateStripeLib = exports.generateMiddlewareNoAuth = exports.generateMiddleware = exports.generatePrismaSchema = exports.generateApiProtectionLib = exports.generateApiKeyAuthLib = exports.generateEncryptionLib = exports.generatePrismaLib = exports.generateNotifyProviderChangeLib = exports.generateInternalProviderUsageRoute = exports.generateInternalProviderIdRoute = exports.generateInternalProvidersRoute = exports.generateProviderSyncRoute = exports.generateProviderTestRoute = exports.generateProviderIdRoute = exports.generateProviderCrudRoute = exports.generateAppSettingsRoute = exports.generateAdminSettingsRoute = exports.generateGdprAccountDeleteRoute = exports.generateGdprDataExportRoute = exports.generateAuditLogRoute = exports.generateV1ModelsRoute = exports.generateModelsRoute = exports.generateHealthRoute = exports.generatePromptsSetDefaultRoute = exports.generatePromptsIdRoute = exports.generatePromptsRoute = exports.generateAdminRolesIdRoute = void 0;
12
+ exports.FEATURE_TEMPLATES = exports.ALL_TEMPLATES = exports.TOOL_GENERATORS = exports.generateToolsInit = exports.generateWebhookTools = exports.generateDeeplTools = exports.generateAirtableTools = exports.generateGoogleSheetsTools = exports.generateVisionTools = exports.generateNlpTools = exports.generateCodeTools = exports.generateDocumentTools = exports.generateWebTools = exports.generateRoutesInit = exports.generateToolsRoutes = exports.generateGuardrailsRoutes = exports.generateRagRoutes = exports.generateChatRoutes = exports.generateFileExtractor = exports.generateDockerComposeAiService = exports.generateAiServiceReadme = exports.generateAiServiceDockerfile = exports.generateAiServiceRequirements = exports.generateAiServiceModels = exports.generateAiServiceConfig = exports.generateAiServiceMain = exports.generateGuardrailsService = exports.generateVectorStore = exports.generateRagService = exports.generateEmbeddingService = exports.generateModerationService = exports.generateModelService = exports.generateChatService = exports.generateServicesInit = exports.generateProviderClient = exports.TOOL_INFO = exports.writeAiManifest = exports.readAiManifest = exports.generateDockerComposeDev = exports.generateDockerComposeProd = exports.generateDockerignore = exports.generateDockerfile = exports.GDPR_SCHEMA_EXTENSION = exports.generateGdprConsentRoute = exports.generateGdprPage = exports.generateGdprLib = exports.MFA_USER_FIELDS = exports.MFA_SCHEMA_EXTENSION = exports.generateMfaPage = void 0;
13
13
  // Config templates
14
14
  var config_js_1 = require("./config.js");
15
15
  Object.defineProperty(exports, "generateNextConfig", { enumerable: true, get: function () { return config_js_1.generateNextConfig; } });
@@ -22,9 +22,12 @@ var layout_js_1 = require("./layout.js");
22
22
  Object.defineProperty(exports, "generateAppLayout", { enumerable: true, get: function () { return layout_js_1.generateAppLayout; } });
23
23
  Object.defineProperty(exports, "generateAppLayoutWithAuth", { enumerable: true, get: function () { return layout_js_1.generateAppLayoutWithAuth; } });
24
24
  Object.defineProperty(exports, "generateAppPage", { enumerable: true, get: function () { return layout_js_1.generateAppPage; } });
25
+ Object.defineProperty(exports, "generateAppPageNoAuth", { enumerable: true, get: function () { return layout_js_1.generateAppPageNoAuth; } });
25
26
  Object.defineProperty(exports, "generateAuthBasicLayout", { enumerable: true, get: function () { return layout_js_1.generateAuthBasicLayout; } });
26
27
  Object.defineProperty(exports, "generateDashboardLayout", { enumerable: true, get: function () { return layout_js_1.generateDashboardLayout; } });
28
+ Object.defineProperty(exports, "generateDashboardLayoutNoAuth", { enumerable: true, get: function () { return layout_js_1.generateDashboardLayoutNoAuth; } });
27
29
  Object.defineProperty(exports, "generateDashboardPage", { enumerable: true, get: function () { return layout_js_1.generateDashboardPage; } });
30
+ Object.defineProperty(exports, "generateDashboardPageNoAuth", { enumerable: true, get: function () { return layout_js_1.generateDashboardPageNoAuth; } });
28
31
  Object.defineProperty(exports, "generateProfilePage", { enumerable: true, get: function () { return layout_js_1.generateProfilePage; } });
29
32
  Object.defineProperty(exports, "generateUserProfileRoute", { enumerable: true, get: function () { return layout_js_1.generateUserProfileRoute; } });
30
33
  Object.defineProperty(exports, "generateSettingsPage", { enumerable: true, get: function () { return layout_js_1.generateSettingsPage; } });
@@ -41,6 +44,7 @@ Object.defineProperty(exports, "generateResolveAuth", { enumerable: true, get: f
41
44
  // Chat templates
42
45
  var chat_js_1 = require("./chat.js");
43
46
  Object.defineProperty(exports, "generateChatPage", { enumerable: true, get: function () { return chat_js_1.generateChatPage; } });
47
+ Object.defineProperty(exports, "generateChatPageNoAuth", { enumerable: true, get: function () { return chat_js_1.generateChatPageNoAuth; } });
44
48
  Object.defineProperty(exports, "generateUseChatHook", { enumerable: true, get: function () { return chat_js_1.generateUseChatHook; } });
45
49
  Object.defineProperty(exports, "generateChatMessage", { enumerable: true, get: function () { return chat_js_1.generateChatMessage; } });
46
50
  Object.defineProperty(exports, "generateChatInput", { enumerable: true, get: function () { return chat_js_1.generateChatInput; } });
@@ -102,6 +106,7 @@ Object.defineProperty(exports, "generatePrismaSchema", { enumerable: true, get:
102
106
  // Middleware template
103
107
  var middleware_js_1 = require("./middleware.js");
104
108
  Object.defineProperty(exports, "generateMiddleware", { enumerable: true, get: function () { return middleware_js_1.generateMiddleware; } });
109
+ Object.defineProperty(exports, "generateMiddlewareNoAuth", { enumerable: true, get: function () { return middleware_js_1.generateMiddlewareNoAuth; } });
105
110
  // Billing templates
106
111
  var billing_js_1 = require("./billing.js");
107
112
  Object.defineProperty(exports, "generateStripeLib", { enumerable: true, get: function () { return billing_js_1.generateStripeLib; } });
@@ -16,6 +16,12 @@ export declare function generateAppLayout(projectName?: string): string;
16
16
  * @returns TypeScript/JSX content for app/layout.tsx with SessionProvider
17
17
  */
18
18
  export declare function generateAppLayoutWithAuth(projectName?: string): string;
19
+ /**
20
+ * Generates a simple landing page for projects WITHOUT auth.
21
+ * No useSession, no redirect — just renders immediately.
22
+ * @returns TypeScript/JSX content for app/page.tsx
23
+ */
24
+ export declare function generateAppPageNoAuth(): string;
19
25
  /**
20
26
  * Generates the home page component that handles session-based routing
21
27
  * Redirects unauthenticated users to /login, authenticated users to /dashboard
@@ -34,6 +40,8 @@ export declare function generateAuthBasicLayout(): string;
34
40
  * Provides structure for authenticated application pages
35
41
  * @returns TypeScript/JSX content for app/(dashboard)/layout.tsx
36
42
  */
43
+ export declare function generateDashboardLayoutNoAuth(): string;
44
+ export declare function generateDashboardPageNoAuth(features?: string[]): string;
37
45
  export declare function generateDashboardLayout(): string;
38
46
  /**
39
47
  * Generates the main dashboard page shown after login
@@ -1 +1 @@
1
- {"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../src/templates/layout.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,GAAE,MAAuB,GAAG,MAAM,CAyB9E;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,GAAE,MAAuB,GAAG,MAAM,CAmCtF;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAiCxC;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CA2BhD;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAuGhD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,GAAE,MAAM,EAAO,GAAG,MAAM,CAgErE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAkG5C;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CA6BjD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAyJ7C;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAkC/C"}
1
+ {"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../src/templates/layout.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,GAAE,MAAuB,GAAG,MAAM,CAyB9E;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,GAAE,MAAuB,GAAG,MAAM,CAmCtF;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAkC9C;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAiCxC;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CA2BhD;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,IAAI,MAAM,CA4DtD;AAED,wBAAgB,2BAA2B,CAAC,QAAQ,GAAE,MAAM,EAAO,GAAG,MAAM,CA+C3E;AAED,wBAAgB,uBAAuB,IAAI,MAAM,CAuGhD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,GAAE,MAAM,EAAO,GAAG,MAAM,CAgErE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAkG5C;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CA6BjD;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAyJ7C;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAkC/C"}
@@ -6,8 +6,11 @@
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.generateAppLayout = generateAppLayout;
8
8
  exports.generateAppLayoutWithAuth = generateAppLayoutWithAuth;
9
+ exports.generateAppPageNoAuth = generateAppPageNoAuth;
9
10
  exports.generateAppPage = generateAppPage;
10
11
  exports.generateAuthBasicLayout = generateAuthBasicLayout;
12
+ exports.generateDashboardLayoutNoAuth = generateDashboardLayoutNoAuth;
13
+ exports.generateDashboardPageNoAuth = generateDashboardPageNoAuth;
11
14
  exports.generateDashboardLayout = generateDashboardLayout;
12
15
  exports.generateDashboardPage = generateDashboardPage;
13
16
  exports.generateProfilePage = generateProfilePage;
@@ -88,6 +91,46 @@ export default function RootLayout({
88
91
  }
89
92
  `;
90
93
  }
94
+ /**
95
+ * Generates a simple landing page for projects WITHOUT auth.
96
+ * No useSession, no redirect — just renders immediately.
97
+ * @returns TypeScript/JSX content for app/page.tsx
98
+ */
99
+ function generateAppPageNoAuth() {
100
+ return `// @chimerai component=AppPageNoAuth version=1.0
101
+ import Link from 'next/link';
102
+
103
+ export default function Home() {
104
+ return (
105
+ <main className="flex min-h-screen flex-col items-center justify-center p-24">
106
+ <div className="text-center">
107
+ <h1 className="text-4xl font-bold mb-4">Welcome</h1>
108
+ <p className="text-muted-foreground mb-8">
109
+ Your ChimerAI application is running.
110
+ </p>
111
+ <div className="flex gap-4 justify-center flex-wrap">
112
+ <Link
113
+ href="/chat"
114
+ className="px-6 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors font-medium"
115
+ >
116
+ 💬 Open Chat
117
+ </Link>
118
+ <Link
119
+ href="/dashboard/providers"
120
+ className="px-6 py-3 border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors font-medium"
121
+ >
122
+ 🔌 Manage Providers
123
+ </Link>
124
+ </div>
125
+ <p className="text-xs text-muted-foreground mt-8">
126
+ To add authentication later, run: <code className="bg-gray-100 px-1 rounded">chimerai add auth</code>
127
+ </p>
128
+ </div>
129
+ </main>
130
+ );
131
+ }
132
+ `;
133
+ }
91
134
  /**
92
135
  * Generates the home page component that handles session-based routing
93
136
  * Redirects unauthenticated users to /login, authenticated users to /dashboard
@@ -166,6 +209,112 @@ export default function AuthLayout({
166
209
  * Provides structure for authenticated application pages
167
210
  * @returns TypeScript/JSX content for app/(dashboard)/layout.tsx
168
211
  */
212
+ function generateDashboardLayoutNoAuth() {
213
+ return `// @chimerai component=DashboardLayoutNoAuth version=1.0
214
+ 'use client';
215
+
216
+ import { useState } from 'react';
217
+ import Link from 'next/link';
218
+ import { useAppName } from '@/lib/use-app-name';
219
+
220
+ export default function DashboardLayout({
221
+ children,
222
+ }: {
223
+ children: React.ReactNode;
224
+ }) {
225
+ const [sidebarOpen, setSidebarOpen] = useState(false);
226
+ const appName = useAppName();
227
+
228
+ return (
229
+ <div className="flex min-h-screen bg-white dark:bg-gray-900">
230
+ <button
231
+ onClick={() => setSidebarOpen(!sidebarOpen)}
232
+ className="fixed top-4 left-4 z-50 md:hidden p-2 rounded-lg bg-gray-100 dark:bg-gray-800 shadow"
233
+ aria-label="Toggle menu"
234
+ >
235
+ <svg className="h-5 w-5 dark:text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
236
+ {sidebarOpen ? (
237
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
238
+ ) : (
239
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
240
+ )}
241
+ </svg>
242
+ </button>
243
+ {sidebarOpen && (
244
+ <div className="fixed inset-0 z-30 bg-black/50 md:hidden" onClick={() => setSidebarOpen(false)} />
245
+ )}
246
+ <aside className={\`fixed z-40 inset-y-0 left-0 w-64 border-r border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800 p-4 flex flex-col transform transition-transform duration-200 ease-in-out md:relative md:translate-x-0 \${sidebarOpen ? 'translate-x-0' : '-translate-x-full'}\`}>
247
+ <div className="mb-4 mt-12 md:mt-0">
248
+ <h2 className="text-lg font-bold dark:text-white">{appName}</h2>
249
+ </div>
250
+ <nav className="space-y-2 flex-1">
251
+ <Link href="/dashboard" onClick={() => setSidebarOpen(false)} className="block px-4 py-2 rounded hover:bg-gray-200 dark:hover:bg-gray-700 dark:text-gray-200">
252
+ Dashboard
253
+ </Link>
254
+ <Link href="/chat" onClick={() => setSidebarOpen(false)} className="block px-4 py-2 rounded hover:bg-gray-200 dark:hover:bg-gray-700 dark:text-gray-200">
255
+ 💬 Chat
256
+ </Link>
257
+ <Link href="/dashboard/providers" onClick={() => setSidebarOpen(false)} className="block px-4 py-2 rounded hover:bg-gray-200 dark:hover:bg-gray-700 dark:text-gray-200">
258
+ 🔌 AI Providers
259
+ </Link>
260
+ </nav>
261
+ <div className="border-t border-gray-200 dark:border-gray-700 pt-3 text-xs text-gray-400 px-2">
262
+ <code>chimerai add auth</code> to add login
263
+ </div>
264
+ </aside>
265
+ <main className="flex-1 p-8 pt-16 md:pt-8 dark:text-white">
266
+ {children}
267
+ </main>
268
+ </div>
269
+ );
270
+ }
271
+ `;
272
+ }
273
+ function generateDashboardPageNoAuth(features = []) {
274
+ const links = [
275
+ ` { href: '/chat', label: 'Chat', icon: '💬', description: 'AI-powered chat conversations' },`,
276
+ ` { href: '/dashboard/providers', label: 'AI Providers', icon: '🔌', description: 'Manage AI model providers and API keys' },`,
277
+ ];
278
+ if (features.includes('prompts')) {
279
+ links.push(` { href: '/dashboard/prompts', label: 'Prompt Templates', icon: '📝', description: 'Create and manage system prompts' },`);
280
+ }
281
+ return `// @chimerai component=DashboardPageNoAuth version=1.0
282
+ 'use client';
283
+
284
+ import Link from 'next/link';
285
+
286
+ export default function DashboardPage() {
287
+ const links = [
288
+ ${links.join('\n')}
289
+ ];
290
+
291
+ return (
292
+ <div className="container mx-auto py-8 px-4">
293
+ <div className="mb-8">
294
+ <h1 className="text-3xl font-bold mb-2 dark:text-white">Dashboard</h1>
295
+ <p className="text-gray-600 dark:text-gray-400">Your ChimerAI Application</p>
296
+ </div>
297
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
298
+ {links.map((link) => (
299
+ <Link
300
+ key={link.href}
301
+ href={link.href}
302
+ className="block p-6 bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 shadow-sm hover:shadow-md hover:border-blue-300 dark:hover:border-blue-600 transition-all"
303
+ >
304
+ <div className="text-3xl mb-3">{link.icon}</div>
305
+ <h2 className="text-xl font-semibold mb-2 dark:text-white">{link.label}</h2>
306
+ <p className="text-gray-600 dark:text-gray-400 text-sm">{link.description}</p>
307
+ </Link>
308
+ ))}
309
+ </div>
310
+ <p className="mt-8 text-sm text-gray-400">
311
+ Run <code className="bg-gray-100 dark:bg-gray-700 px-1 rounded">chimerai add auth</code> to enable authentication.
312
+ </p>
313
+ </div>
314
+ );
315
+ }
316
+ `;
317
+ }
169
318
  function generateDashboardLayout() {
170
319
  return `// @chimerai component=DashboardLayout version=1.2
171
320
  'use client';
@@ -2,6 +2,13 @@
2
2
  * Next.js middleware template with security headers and CORS for widget endpoints.
3
3
  * Generates middleware.ts for the root of the Next.js project.
4
4
  */
5
+ /**
6
+ * Generates a minimal Next.js middleware WITHOUT auth enforcement.
7
+ * Used when auth feature is not selected — only CORS + security headers.
8
+ * No getToken / next-auth/jwt import.
9
+ * @returns TypeScript content for middleware.ts
10
+ */
11
+ export declare function generateMiddlewareNoAuth(): string;
5
12
  /**
6
13
  * Generates the Next.js middleware with security headers and CORS.
7
14
  * Widget endpoints (/api/v1/*) get CORS headers from CORS_ALLOWED_ORIGINS env.
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/templates/middleware.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAsG3C"}
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/templates/middleware.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;GAKG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,CAuDjD;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAsG3C"}
@@ -4,7 +4,70 @@
4
4
  * Generates middleware.ts for the root of the Next.js project.
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.generateMiddlewareNoAuth = generateMiddlewareNoAuth;
7
8
  exports.generateMiddleware = generateMiddleware;
9
+ /**
10
+ * Generates a minimal Next.js middleware WITHOUT auth enforcement.
11
+ * Used when auth feature is not selected — only CORS + security headers.
12
+ * No getToken / next-auth/jwt import.
13
+ * @returns TypeScript content for middleware.ts
14
+ */
15
+ function generateMiddlewareNoAuth() {
16
+ return `// @chimerai component=MiddlewareNoAuth version=1.0
17
+ import { NextResponse } from 'next/server';
18
+ import type { NextRequest } from 'next/server';
19
+
20
+ /** Merge CORS_ALLOWED_ORIGINS + WIDGET_ALLOWED_ORIGINS (legacy alias) */
21
+ function getAllowedOrigins(): string[] {
22
+ const raw = [
23
+ process.env.CORS_ALLOWED_ORIGINS || '',
24
+ process.env.WIDGET_ALLOWED_ORIGINS || '',
25
+ ].filter(Boolean).join(',');
26
+ if (!raw) return ['*'];
27
+ return raw.split(',').map(o => o.trim()).filter(Boolean);
28
+ }
29
+
30
+ export async function middleware(request: NextRequest) {
31
+ const { pathname } = request.nextUrl;
32
+
33
+ // --- CORS for Widget/Public API Endpoints (/api/v1/*) ---
34
+ if (pathname.startsWith('/api/v1/')) {
35
+ const allowedOrigins = getAllowedOrigins();
36
+ const origin = request.headers.get('origin') || '';
37
+
38
+ if (request.method === 'OPTIONS') {
39
+ const res = new NextResponse(null, { status: 204 });
40
+ const allowOrigin = allowedOrigins.includes('*') ? '*' : (allowedOrigins.includes(origin) ? origin : '');
41
+ if (allowOrigin) res.headers.set('Access-Control-Allow-Origin', allowOrigin);
42
+ res.headers.set('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
43
+ res.headers.set('Access-Control-Allow-Headers', 'Content-Type, x-api-key, Authorization');
44
+ res.headers.set('Access-Control-Max-Age', '86400');
45
+ return res;
46
+ }
47
+
48
+ const response = NextResponse.next();
49
+ const allowOrigin = allowedOrigins.includes('*') ? '*' : (allowedOrigins.includes(origin) ? origin : '');
50
+ if (allowOrigin) response.headers.set('Access-Control-Allow-Origin', allowOrigin);
51
+ return response;
52
+ }
53
+
54
+ // --- Standard security headers for all routes ---
55
+ const response = NextResponse.next();
56
+ response.headers.set('X-Frame-Options', 'DENY');
57
+ response.headers.set('X-Content-Type-Options', 'nosniff');
58
+ response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin');
59
+ response.headers.set('Permissions-Policy', 'camera=(), microphone=(), geolocation=()');
60
+ if (process.env.NODE_ENV === 'production') {
61
+ response.headers.set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload');
62
+ }
63
+ return response;
64
+ }
65
+
66
+ export const config = {
67
+ matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
68
+ };
69
+ `;
70
+ }
8
71
  /**
9
72
  * Generates the Next.js middleware with security headers and CORS.
10
73
  * Widget endpoints (/api/v1/*) get CORS headers from CORS_ALLOWED_ORIGINS env.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chimerai/cli",
3
- "version": "0.2.88",
3
+ "version": "0.2.90",
4
4
  "description": "CLI wizard for ChimerAI starter kit — scaffold auth, RBAC, AI chat, billing and more into any Next.js project",
5
5
  "main": "./dist/index.js",
6
6
  "bin": {