@chimerai/cli 0.2.73

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 (129) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +293 -0
  3. package/dist/cli.d.ts +7 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +317 -0
  6. package/dist/commands/add.d.ts +11 -0
  7. package/dist/commands/add.d.ts.map +1 -0
  8. package/dist/commands/add.js +2126 -0
  9. package/dist/commands/create.d.ts +12 -0
  10. package/dist/commands/create.d.ts.map +1 -0
  11. package/dist/commands/create.js +1703 -0
  12. package/dist/commands/deploy.d.ts +11 -0
  13. package/dist/commands/deploy.d.ts.map +1 -0
  14. package/dist/commands/deploy.js +219 -0
  15. package/dist/commands/dev.d.ts +17 -0
  16. package/dist/commands/dev.d.ts.map +1 -0
  17. package/dist/commands/dev.js +206 -0
  18. package/dist/commands/doctor.d.ts +11 -0
  19. package/dist/commands/doctor.d.ts.map +1 -0
  20. package/dist/commands/doctor.js +728 -0
  21. package/dist/commands/generate.d.ts +19 -0
  22. package/dist/commands/generate.d.ts.map +1 -0
  23. package/dist/commands/generate.js +429 -0
  24. package/dist/commands/init.d.ts +11 -0
  25. package/dist/commands/init.d.ts.map +1 -0
  26. package/dist/commands/init.js +269 -0
  27. package/dist/commands/list.d.ts +12 -0
  28. package/dist/commands/list.d.ts.map +1 -0
  29. package/dist/commands/list.js +328 -0
  30. package/dist/commands/migrate.d.ts +14 -0
  31. package/dist/commands/migrate.d.ts.map +1 -0
  32. package/dist/commands/migrate.js +197 -0
  33. package/dist/commands/plugin.d.ts +10 -0
  34. package/dist/commands/plugin.d.ts.map +1 -0
  35. package/dist/commands/plugin.js +239 -0
  36. package/dist/commands/remove.d.ts +11 -0
  37. package/dist/commands/remove.d.ts.map +1 -0
  38. package/dist/commands/remove.js +472 -0
  39. package/dist/commands/secret.d.ts +12 -0
  40. package/dist/commands/secret.d.ts.map +1 -0
  41. package/dist/commands/secret.js +102 -0
  42. package/dist/commands/setup.d.ts +9 -0
  43. package/dist/commands/setup.d.ts.map +1 -0
  44. package/dist/commands/setup.js +788 -0
  45. package/dist/commands/update.d.ts +14 -0
  46. package/dist/commands/update.d.ts.map +1 -0
  47. package/dist/commands/update.js +211 -0
  48. package/dist/commands/use.d.ts +9 -0
  49. package/dist/commands/use.d.ts.map +1 -0
  50. package/dist/commands/use.js +51 -0
  51. package/dist/index.d.ts +22 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +45 -0
  54. package/dist/license.d.ts +55 -0
  55. package/dist/license.d.ts.map +1 -0
  56. package/dist/license.js +258 -0
  57. package/dist/scanner.d.ts +31 -0
  58. package/dist/scanner.d.ts.map +1 -0
  59. package/dist/scanner.js +113 -0
  60. package/dist/schema-manager.d.ts +26 -0
  61. package/dist/schema-manager.d.ts.map +1 -0
  62. package/dist/schema-manager.js +132 -0
  63. package/dist/templates/admin.d.ts +49 -0
  64. package/dist/templates/admin.d.ts.map +1 -0
  65. package/dist/templates/admin.js +1358 -0
  66. package/dist/templates/ai-routes.d.ts +17 -0
  67. package/dist/templates/ai-routes.d.ts.map +1 -0
  68. package/dist/templates/ai-routes.js +1130 -0
  69. package/dist/templates/ai-service-tools.d.ts +22 -0
  70. package/dist/templates/ai-service-tools.d.ts.map +1 -0
  71. package/dist/templates/ai-service-tools.js +1424 -0
  72. package/dist/templates/ai-service.d.ts +66 -0
  73. package/dist/templates/ai-service.d.ts.map +1 -0
  74. package/dist/templates/ai-service.js +2202 -0
  75. package/dist/templates/api-routes.d.ts +108 -0
  76. package/dist/templates/api-routes.d.ts.map +1 -0
  77. package/dist/templates/api-routes.js +1219 -0
  78. package/dist/templates/auth.d.ts +48 -0
  79. package/dist/templates/auth.d.ts.map +1 -0
  80. package/dist/templates/auth.js +381 -0
  81. package/dist/templates/billing.d.ts +44 -0
  82. package/dist/templates/billing.d.ts.map +1 -0
  83. package/dist/templates/billing.js +551 -0
  84. package/dist/templates/chat.d.ts +63 -0
  85. package/dist/templates/chat.d.ts.map +1 -0
  86. package/dist/templates/chat.js +1979 -0
  87. package/dist/templates/components.d.ts +22 -0
  88. package/dist/templates/components.d.ts.map +1 -0
  89. package/dist/templates/components.js +672 -0
  90. package/dist/templates/config.d.ts +6 -0
  91. package/dist/templates/config.d.ts.map +1 -0
  92. package/dist/templates/config.js +86 -0
  93. package/dist/templates/docker.d.ts +25 -0
  94. package/dist/templates/docker.d.ts.map +1 -0
  95. package/dist/templates/docker.js +165 -0
  96. package/dist/templates/gdpr.d.ts +16 -0
  97. package/dist/templates/gdpr.d.ts.map +1 -0
  98. package/dist/templates/gdpr.js +259 -0
  99. package/dist/templates/index.d.ts +77 -0
  100. package/dist/templates/index.d.ts.map +1 -0
  101. package/dist/templates/index.js +339 -0
  102. package/dist/templates/layout.d.ts +67 -0
  103. package/dist/templates/layout.d.ts.map +1 -0
  104. package/dist/templates/layout.js +670 -0
  105. package/dist/templates/mfa.d.ts +23 -0
  106. package/dist/templates/mfa.d.ts.map +1 -0
  107. package/dist/templates/mfa.js +353 -0
  108. package/dist/templates/middleware.d.ts +12 -0
  109. package/dist/templates/middleware.d.ts.map +1 -0
  110. package/dist/templates/middleware.js +116 -0
  111. package/dist/templates/prisma.d.ts +35 -0
  112. package/dist/templates/prisma.d.ts.map +1 -0
  113. package/dist/templates/prisma.js +724 -0
  114. package/dist/templates/provider-routes.d.ts +21 -0
  115. package/dist/templates/provider-routes.d.ts.map +1 -0
  116. package/dist/templates/provider-routes.js +1203 -0
  117. package/dist/templates/rag.d.ts +48 -0
  118. package/dist/templates/rag.d.ts.map +1 -0
  119. package/dist/templates/rag.js +532 -0
  120. package/dist/templates/widget.d.ts +64 -0
  121. package/dist/templates/widget.d.ts.map +1 -0
  122. package/dist/templates/widget.js +1360 -0
  123. package/dist/utils/provider-db.d.ts +63 -0
  124. package/dist/utils/provider-db.d.ts.map +1 -0
  125. package/dist/utils/provider-db.js +300 -0
  126. package/dist/utils.d.ts +78 -0
  127. package/dist/utils.d.ts.map +1 -0
  128. package/dist/utils.js +330 -0
  129. package/package.json +60 -0
@@ -0,0 +1,472 @@
1
+ "use strict";
2
+ /**
3
+ * Remove Command - Remove components from a ChimerAI project
4
+ */
5
+ var __importDefault = (this && this.__importDefault) || function (mod) {
6
+ return (mod && mod.__esModule) ? mod : { "default": mod };
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.removeCommand = removeCommand;
10
+ const inquirer_1 = __importDefault(require("inquirer"));
11
+ const chalk_1 = __importDefault(require("chalk"));
12
+ const ora_1 = __importDefault(require("ora"));
13
+ const fs_extra_1 = __importDefault(require("fs-extra"));
14
+ const path_1 = __importDefault(require("path"));
15
+ const utils_js_1 = require("../utils.js");
16
+ const ai_service_js_1 = require("../templates/ai-service.js");
17
+ const index_js_1 = require("../templates/index.js");
18
+ const ai_service_tools_js_1 = require("../templates/ai-service-tools.js");
19
+ const COMPONENT_FILES = {
20
+ auth: {
21
+ files: [
22
+ 'app/api/auth/[...nextauth]/route.ts',
23
+ 'app/login/page.tsx',
24
+ 'components/SessionProvider.tsx',
25
+ 'components/LogoutButton.tsx',
26
+ 'types/next-auth.d.ts',
27
+ ],
28
+ directories: ['app/api/auth', 'app/login'],
29
+ dependencies: ['next-auth', '@auth/prisma-adapter'],
30
+ description: 'NextAuth authentication system',
31
+ },
32
+ 'users-table': {
33
+ files: [
34
+ 'app/admin/users/page.tsx',
35
+ 'app/api/admin/users/route.ts',
36
+ 'app/api/admin/users/[id]/route.ts',
37
+ ],
38
+ directories: ['app/admin/users', 'app/api/admin/users'],
39
+ dependencies: [],
40
+ description: 'Users management CRUD',
41
+ },
42
+ 'roles-table': {
43
+ files: [
44
+ 'app/admin/roles/page.tsx',
45
+ 'app/api/admin/roles/route.ts',
46
+ 'app/api/admin/roles/[id]/route.ts',
47
+ ],
48
+ directories: ['app/admin/roles', 'app/api/admin/roles'],
49
+ dependencies: [],
50
+ description: 'Roles management CRUD',
51
+ },
52
+ 'chat-ui': {
53
+ files: [
54
+ 'app/chat/page.tsx',
55
+ 'components/StreamingChat.tsx',
56
+ 'app/api/v1/chat/stream/route.ts',
57
+ 'app/api/chat/route.ts',
58
+ 'app/api/conversations/route.ts',
59
+ ],
60
+ directories: [
61
+ 'app/api/v1/chat/stream',
62
+ 'app/api/v1/chat',
63
+ 'app/api/v1',
64
+ 'app/api/chat',
65
+ 'app/api/conversations',
66
+ ],
67
+ dependencies: ['openai', '@anthropic-ai/sdk'],
68
+ description: 'Chat interface with streaming',
69
+ },
70
+ 'chat-widget': {
71
+ files: [
72
+ 'public/widget/chat.js',
73
+ 'public/widget/loader.js',
74
+ 'app/(app)/settings/api-keys/page.tsx',
75
+ 'app/api/v1/api-keys/route.ts',
76
+ 'app/api/v1/api-keys/[id]/route.ts',
77
+ 'lib/rate-limit.ts',
78
+ ],
79
+ directories: ['public/widget', 'app/(app)/settings/api-keys', 'app/api/v1/api-keys'],
80
+ dependencies: [],
81
+ description: 'Embeddable chat widget + API-key management',
82
+ },
83
+ 'model-providers': {
84
+ files: ['app/providers-demo/page.tsx', 'app/api/providers/route.ts'],
85
+ directories: ['app/providers-demo', 'app/api/providers'],
86
+ dependencies: [],
87
+ description: 'AI provider management',
88
+ },
89
+ 'prompt-management': {
90
+ files: [
91
+ 'app/dashboard/prompts/page.tsx',
92
+ 'app/(app)/dashboard/prompts/page.tsx',
93
+ 'app/api/prompts/route.ts',
94
+ 'app/api/prompts/[id]/route.ts',
95
+ 'app/api/prompts/[id]/set-default/route.ts',
96
+ 'components/chat/prompt-selector.tsx',
97
+ ],
98
+ directories: ['app/dashboard/prompts', 'app/(app)/dashboard/prompts', 'app/api/prompts'],
99
+ dependencies: [],
100
+ description: 'Prompt template system',
101
+ },
102
+ billing: {
103
+ files: [
104
+ 'app/billing/page.tsx',
105
+ 'lib/stripe.ts',
106
+ 'app/api/billing/subscription/route.ts',
107
+ 'app/api/billing/checkout/route.ts',
108
+ 'app/api/billing/portal/route.ts',
109
+ 'app/api/billing/usage/route.ts',
110
+ 'app/api/webhooks/stripe/route.ts',
111
+ ],
112
+ directories: ['app/billing', 'app/api/billing', 'app/api/webhooks/stripe'],
113
+ dependencies: ['stripe'],
114
+ description: 'Stripe billing & subscriptions',
115
+ },
116
+ 'admin-dashboard': {
117
+ files: ['app/admin/page.tsx', 'app/admin/settings/page.tsx', 'app/admin/logs/page.tsx'],
118
+ directories: ['app/admin/settings', 'app/admin/logs'],
119
+ dependencies: [],
120
+ description: 'Admin dashboard overview',
121
+ },
122
+ webhooks: {
123
+ files: ['lib/webhook-dispatcher.ts'],
124
+ directories: [],
125
+ dependencies: [],
126
+ description: 'Webhook dispatch system',
127
+ },
128
+ gdpr: {
129
+ files: ['lib/gdpr.ts'],
130
+ directories: [],
131
+ dependencies: [],
132
+ description: 'GDPR compliance utilities',
133
+ },
134
+ mfa: {
135
+ files: ['lib/mfa.ts'],
136
+ directories: [],
137
+ dependencies: ['otplib', 'qrcode'],
138
+ description: 'Multi-factor authentication',
139
+ },
140
+ 'audit-log': {
141
+ files: ['lib/audit-log.ts'],
142
+ directories: [],
143
+ dependencies: [],
144
+ description: 'Audit logging system',
145
+ },
146
+ theming: {
147
+ files: ['lib/theme-engine.ts'],
148
+ directories: [],
149
+ dependencies: [],
150
+ description: 'Dynamic theme engine',
151
+ },
152
+ analytics: {
153
+ files: ['lib/analytics.ts'],
154
+ directories: [],
155
+ dependencies: [],
156
+ description: 'API usage analytics',
157
+ },
158
+ sentry: {
159
+ files: ['sentry.client.config.ts', 'sentry.server.config.ts'],
160
+ directories: [],
161
+ dependencies: ['@sentry/nextjs'],
162
+ description: 'Error tracking & monitoring',
163
+ },
164
+ // AI Service modules
165
+ 'ai-chat': {
166
+ files: [
167
+ 'services/ai/services/chat_service.py',
168
+ 'services/ai/services/model_service.py',
169
+ 'services/ai/services/moderation_service.py',
170
+ 'services/ai/routes/chat_routes.py',
171
+ ],
172
+ directories: [],
173
+ dependencies: [],
174
+ description: 'AI Chat module (chat, model, moderation services)',
175
+ },
176
+ rag: {
177
+ files: [
178
+ 'services/ai/services/rag_service.py',
179
+ 'services/ai/services/vector_store.py',
180
+ 'services/ai/services/embedding_service.py',
181
+ 'services/ai/routes/rag_routes.py',
182
+ 'app/rag/page.tsx',
183
+ 'app/(app)/rag/page.tsx',
184
+ 'lib/rag.ts',
185
+ 'app/api/rag/route.ts',
186
+ 'app/api/rag/query/route.ts',
187
+ 'app/api/rag/stats/route.ts',
188
+ 'app/api/rag/clear/route.ts',
189
+ 'app/api/rag/delete/route.ts',
190
+ ],
191
+ directories: ['services/ai/data'],
192
+ dependencies: [],
193
+ description: 'RAG module (embeddings, vector store, retrieval)',
194
+ },
195
+ guardrails: {
196
+ files: [
197
+ 'services/ai/services/guardrails_service.py',
198
+ 'services/ai/routes/guardrails_routes.py',
199
+ ],
200
+ directories: [],
201
+ dependencies: [],
202
+ description: 'AI Guardrails (content moderation & safety)',
203
+ },
204
+ 'ai-tools': {
205
+ files: ['services/ai/routes/tools_routes.py'],
206
+ directories: ['services/ai/services/tools'],
207
+ dependencies: [],
208
+ description: 'AI Tools (web, NLP, vision, integrations)',
209
+ },
210
+ };
211
+ /**
212
+ * Determine which other components depend on a given dependency package.
213
+ * Returns the component names that use the same dependency (excluding the one being removed).
214
+ */
215
+ function findDependencyUsers(dep, excludeComponent) {
216
+ return Object.entries(COMPONENT_FILES)
217
+ .filter(([name, map]) => name !== excludeComponent && map.dependencies.includes(dep))
218
+ .map(([name]) => name);
219
+ }
220
+ async function removeCommand(component, options) {
221
+ console.log(chalk_1.default.bold.cyan(`\nšŸ—‘ļø Removing ${component} from your project\n`));
222
+ const targetDir = (0, utils_js_1.resolveTargetDir)(options.dir);
223
+ if (!COMPONENT_FILES[component]) {
224
+ console.log(chalk_1.default.red(`āŒ Unknown component: ${component}`));
225
+ console.log(chalk_1.default.yellow('\nRemovable components:'));
226
+ for (const [name, map] of Object.entries(COMPONENT_FILES)) {
227
+ console.log(chalk_1.default.white(` - ${name.padEnd(22)} ${chalk_1.default.gray(map.description)}`));
228
+ }
229
+ (0, utils_js_1.handleCliError)(`Unknown component: ${component}`);
230
+ }
231
+ const compMap = COMPONENT_FILES[component];
232
+ // Check which files actually exist
233
+ const existingFiles = compMap.files.filter((f) => fs_extra_1.default.existsSync(path_1.default.join(targetDir, f)));
234
+ if (existingFiles.length === 0) {
235
+ console.log(chalk_1.default.yellow(` āš ļø Component '${component}' does not appear to be installed.`));
236
+ console.log(chalk_1.default.gray(' No matching files found.\n'));
237
+ if (component !== 'prompt-management') {
238
+ return;
239
+ }
240
+ console.log(chalk_1.default.gray(' Continuing anyway to clean up optional prompt-management patches...\n'));
241
+ }
242
+ // Show what will be removed
243
+ if (existingFiles.length > 0) {
244
+ console.log(chalk_1.default.bold(' Files to remove:'));
245
+ for (const f of existingFiles) {
246
+ console.log(chalk_1.default.red(` āœ— ${f}`));
247
+ }
248
+ }
249
+ // Show dependencies that will be cleaned up
250
+ const depsToRemove = [];
251
+ if (compMap.dependencies.length > 0) {
252
+ console.log(chalk_1.default.bold('\n Dependencies to check:'));
253
+ for (const dep of compMap.dependencies) {
254
+ const otherUsers = findDependencyUsers(dep, component);
255
+ // Only remove dependency if no other installed component needs it
256
+ const otherInstalled = otherUsers.filter((u) => COMPONENT_FILES[u].files.some((f) => fs_extra_1.default.existsSync(path_1.default.join(targetDir, f))));
257
+ if (otherInstalled.length === 0) {
258
+ depsToRemove.push(dep);
259
+ console.log(chalk_1.default.red(` āœ— ${dep} ${chalk_1.default.gray('(no other component needs it)')}`));
260
+ }
261
+ else {
262
+ console.log(chalk_1.default.yellow(` ⚠ ${dep} ${chalk_1.default.gray(`(still needed by: ${otherInstalled.join(', ')})`)}`));
263
+ }
264
+ }
265
+ }
266
+ if (!options.keepData) {
267
+ console.log(chalk_1.default.yellow('\n āš ļø Database tables will NOT be removed automatically.'));
268
+ console.log(chalk_1.default.gray(' Remove models from prisma/schema.prisma manually if needed.'));
269
+ }
270
+ // Confirm
271
+ if (!options.yes) {
272
+ const { confirm } = await inquirer_1.default.prompt([
273
+ {
274
+ type: 'confirm',
275
+ name: 'confirm',
276
+ message: `Remove ${component}? (${existingFiles.length} files)`,
277
+ default: false,
278
+ },
279
+ ]);
280
+ if (!confirm) {
281
+ console.log(chalk_1.default.gray('\n Cancelled.\n'));
282
+ return;
283
+ }
284
+ }
285
+ // Perform removal
286
+ const spinner = (0, ora_1.default)('Removing files...').start();
287
+ try {
288
+ // Remove files
289
+ let removed = 0;
290
+ for (const f of existingFiles) {
291
+ const fullPath = path_1.default.join(targetDir, f);
292
+ await fs_extra_1.default.remove(fullPath);
293
+ removed++;
294
+ }
295
+ spinner.succeed(`Removed ${removed} file(s)`);
296
+ // Clean up empty directories
297
+ spinner.start('Cleaning up directories...');
298
+ let dirsRemoved = 0;
299
+ for (const dir of compMap.directories) {
300
+ const fullDir = path_1.default.join(targetDir, dir);
301
+ if (fs_extra_1.default.existsSync(fullDir)) {
302
+ const entries = await fs_extra_1.default.readdir(fullDir);
303
+ if (entries.length === 0) {
304
+ await fs_extra_1.default.remove(fullDir);
305
+ dirsRemoved++;
306
+ }
307
+ }
308
+ }
309
+ if (dirsRemoved > 0) {
310
+ spinner.succeed(`Cleaned up ${dirsRemoved} empty directory(ies)`);
311
+ }
312
+ else {
313
+ spinner.info('No empty directories to clean up');
314
+ }
315
+ // Remove dependencies from package.json
316
+ if (depsToRemove.length > 0) {
317
+ spinner.start('Updating package.json...');
318
+ const pkgPath = path_1.default.join(targetDir, 'package.json');
319
+ if (fs_extra_1.default.existsSync(pkgPath)) {
320
+ try {
321
+ const pkg = await fs_extra_1.default.readJson(pkgPath);
322
+ for (const dep of depsToRemove) {
323
+ if (pkg.dependencies?.[dep])
324
+ delete pkg.dependencies[dep];
325
+ if (pkg.devDependencies?.[dep])
326
+ delete pkg.devDependencies[dep];
327
+ }
328
+ await fs_extra_1.default.writeJson(pkgPath, pkg, { spaces: 2 });
329
+ spinner.succeed(`Removed ${depsToRemove.length} dependency(ies) from package.json`);
330
+ }
331
+ catch {
332
+ spinner.warn('Could not update package.json');
333
+ }
334
+ }
335
+ }
336
+ console.log(chalk_1.default.bold.green(`\nāœ… ${component} removed successfully!\n`));
337
+ // Post-removal instructions
338
+ if (depsToRemove.length > 0) {
339
+ console.log(chalk_1.default.cyan(' šŸ’” Run `pnpm install` to clean up node_modules.\n'));
340
+ }
341
+ // prompt-management removal: undo optional chat integration patches
342
+ if (component === 'prompt-management') {
343
+ // 1) Remove PromptSelector wiring from chat page if present
344
+ const chatPageCandidates = [
345
+ path_1.default.join(targetDir, 'app', '(app)', 'chat', 'page.tsx'),
346
+ path_1.default.join(targetDir, 'app', 'chat', 'page.tsx'),
347
+ ];
348
+ for (const chatPagePath of chatPageCandidates) {
349
+ if (await fs_extra_1.default.pathExists(chatPagePath)) {
350
+ let chatPage = await fs_extra_1.default.readFile(chatPagePath, 'utf-8');
351
+ const original = chatPage;
352
+ chatPage = chatPage.replace(`import { PromptSelector } from '@/components/chat/prompt-selector';\n`, '');
353
+ chatPage = chatPage.replace(` selectedPromptId,\n setSelectedPromptId,\n`, '');
354
+ chatPage = chatPage.replace(/\n\s*<PromptSelector\n\s*value=\{selectedPromptId\}\n\s*onChange=\{setSelectedPromptId\}\n\s*category="system"\n\s*placeholder="No system prompt"\n\s*\/>/, '');
355
+ if (chatPage !== original) {
356
+ await fs_extra_1.default.writeFile(chatPagePath, chatPage, 'utf-8');
357
+ console.log(chalk_1.default.green(` āœ“ Unpatched ${path_1.default.relative(targetDir, chatPagePath)} — PromptSelector removed`));
358
+ }
359
+ break;
360
+ }
361
+ }
362
+ // 2) Remove selectedPromptId support from use-chat.ts if present
363
+ const useChatPath = path_1.default.join(targetDir, 'components', 'chat', 'use-chat.ts');
364
+ if (await fs_extra_1.default.pathExists(useChatPath)) {
365
+ let useChat = await fs_extra_1.default.readFile(useChatPath, 'utf-8');
366
+ const original = useChat;
367
+ useChat = useChat.replace(` selectedPromptId: string | null;\n setSelectedPromptId: (id: string | null) => void;\n`, '');
368
+ useChat = useChat.replace(` const [selectedPromptId, setSelectedPromptId] = useState<string | null>(null);\n`, '');
369
+ useChat = useChat.replace(` ...(selectedPromptId ? { promptId: selectedPromptId } : {}),\n`, '');
370
+ useChat = useChat.replace(` selectedPromptId,\n setSelectedPromptId,\n`, '');
371
+ useChat = useChat.replace(` [isStreaming, messages, models, selectedModelId, selectedPromptId, systemPrompt, options, refreshConversations, fetchCreditBalance]`, ` [isStreaming, messages, models, selectedModelId, systemPrompt, options, refreshConversations, fetchCreditBalance]`);
372
+ if (useChat !== original) {
373
+ await fs_extra_1.default.writeFile(useChatPath, useChat, 'utf-8');
374
+ console.log(chalk_1.default.green(' āœ“ Unpatched components/chat/use-chat.ts — selectedPromptId removed'));
375
+ }
376
+ }
377
+ // 3) Remove promptId/template injection from chat stream route if present
378
+ const streamRoutePath = path_1.default.join(targetDir, 'app', 'api', 'v1', 'chat', 'stream', 'route.ts');
379
+ if (await fs_extra_1.default.pathExists(streamRoutePath)) {
380
+ let route = await fs_extra_1.default.readFile(streamRoutePath, 'utf-8');
381
+ const original = route;
382
+ // 3a) payload destructuring: remove promptId safely
383
+ route = route
384
+ .replace(`const { messages, model, providerId, conversationId, promptId } = payload;`, `const { messages, model, providerId, conversationId } = payload;`)
385
+ .replace(`const { messages, model, providerId, conversationId,promptId } = payload;`, `const { messages, model, providerId, conversationId } = payload;`);
386
+ // 3b) remove any injected step-2.5 prompt block (old/new variants)
387
+ route = route.replace(/\n\s*\/\/ --- 2\.5 Load system prompt template ---[\s\S]*?\n\s*\/\/ --- 3\. Load provider and decrypt API key ---/m, `\n // --- 3. Load provider and decrypt API key ---`);
388
+ // 3c) revert provider payload fields
389
+ route = route.replace(`system: systemPromptContent || messages.find((m: any) => m.role === 'system')?.content || undefined,`, `system: messages.find((m: any) => m.role === 'system')?.content || undefined,`);
390
+ route = route.replace(/messages:\s*systemPromptContent[\s\S]*?:\s*messages,?/g, `messages,`);
391
+ if (route !== original) {
392
+ await fs_extra_1.default.writeFile(streamRoutePath, route, 'utf-8');
393
+ console.log(chalk_1.default.green(' āœ“ Unpatched app/api/v1/chat/stream/route.ts — promptId support removed'));
394
+ }
395
+ }
396
+ // 4) Remove sidebar link to prompts if present
397
+ const dashboardLayoutPath = path_1.default.join(targetDir, 'app', 'dashboard', 'layout.tsx');
398
+ if (await fs_extra_1.default.pathExists(dashboardLayoutPath)) {
399
+ let layout = await fs_extra_1.default.readFile(dashboardLayoutPath, 'utf-8');
400
+ const original = layout;
401
+ layout = layout.replace(/\n\s*<Link href="\/dashboard\/prompts" onClick=\{\(\) => setSidebarOpen\(false\)\} className="block px-4 py-2 rounded hover:bg-gray-200 dark:hover:bg-gray-700 dark:text-gray-200">\n\s*Prompt Templates\n\s*<\/Link>/, '');
402
+ if (layout !== original) {
403
+ await fs_extra_1.default.writeFile(dashboardLayoutPath, layout, 'utf-8');
404
+ console.log(chalk_1.default.green(' āœ“ Unpatched app/dashboard/layout.tsx — Prompt Templates link removed'));
405
+ }
406
+ }
407
+ // 5) Remove dashboard tile to prompts if present
408
+ const dashboardPagePath = path_1.default.join(targetDir, 'app', 'dashboard', 'page.tsx');
409
+ if (await fs_extra_1.default.pathExists(dashboardPagePath)) {
410
+ let dashboardPage = await fs_extra_1.default.readFile(dashboardPagePath, 'utf-8');
411
+ const original = dashboardPage;
412
+ dashboardPage = dashboardPage.replace(/\s*\{ href: '\/dashboard\/prompts', label: 'Prompt Templates', icon: 'šŸ“', description: 'Create and manage system prompts' \},?/g, '');
413
+ if (dashboardPage !== original) {
414
+ await fs_extra_1.default.writeFile(dashboardPagePath, dashboardPage, 'utf-8');
415
+ console.log(chalk_1.default.green(' āœ“ Unpatched app/dashboard/page.tsx — Prompt Templates tile removed'));
416
+ }
417
+ }
418
+ }
419
+ // AI module removal: update manifest and regenerate dynamic files
420
+ const AI_MODULES = ['ai-chat', 'rag', 'guardrails', 'ai-tools'];
421
+ if (AI_MODULES.includes(component)) {
422
+ const manifest = (0, ai_service_js_1.readAiManifest)(targetDir);
423
+ if (manifest) {
424
+ const moduleMap = {
425
+ 'ai-chat': 'chat',
426
+ rag: 'rag',
427
+ guardrails: 'guardrails',
428
+ 'ai-tools': 'tools',
429
+ };
430
+ const moduleName = moduleMap[component];
431
+ if (moduleName === 'tools') {
432
+ manifest.tools = [];
433
+ manifest.modules = manifest.modules.filter((m) => m !== 'tools');
434
+ }
435
+ else if (moduleName) {
436
+ manifest.modules = manifest.modules.filter((m) => m !== moduleName);
437
+ }
438
+ const aiDir = path_1.default.join(targetDir, 'services', 'ai');
439
+ // Regenerate dynamic files
440
+ if (manifest.modules.length > 0) {
441
+ await fs_extra_1.default.writeFile(path_1.default.join(aiDir, 'main.py'), (0, index_js_1.generateAiServiceMain)(manifest.modules, manifest.tools));
442
+ await fs_extra_1.default.writeFile(path_1.default.join(aiDir, 'models.py'), (0, index_js_1.generateAiServiceModels)(manifest.modules));
443
+ await fs_extra_1.default.writeFile(path_1.default.join(aiDir, 'requirements.txt'), (0, index_js_1.generateAiServiceRequirements)(manifest.modules, manifest.tools));
444
+ await fs_extra_1.default.writeFile(path_1.default.join(aiDir, 'config.py'), (0, index_js_1.generateAiServiceConfig)(manifest.modules));
445
+ await fs_extra_1.default.writeFile(path_1.default.join(aiDir, 'README.md'), (0, index_js_1.generateAiServiceReadme)(manifest.modules, manifest.tools));
446
+ await fs_extra_1.default.writeFile(path_1.default.join(aiDir, 'routes', '__init__.py'), (0, index_js_1.generateRoutesInit)());
447
+ if (manifest.tools.length > 0) {
448
+ await fs_extra_1.default.writeFile(path_1.default.join(aiDir, 'routes', 'tools_routes.py'), (0, index_js_1.generateToolsRoutes)(manifest.tools));
449
+ await fs_extra_1.default.writeFile(path_1.default.join(aiDir, 'services', 'tools', '__init__.py'), (0, ai_service_tools_js_1.generateToolsInit)(manifest.tools));
450
+ }
451
+ (0, ai_service_js_1.writeAiManifest)(targetDir, manifest);
452
+ console.log(chalk_1.default.cyan(' šŸ”„ AI service files regenerated based on remaining modules.\n'));
453
+ }
454
+ else {
455
+ // No modules left — offer to remove entire AI service
456
+ console.log(chalk_1.default.yellow(' āš ļø No AI modules remaining. Consider removing services/ai/ entirely.\n'));
457
+ (0, ai_service_js_1.writeAiManifest)(targetDir, manifest);
458
+ }
459
+ }
460
+ }
461
+ // Warn about dependent components
462
+ const dependents = Object.entries(COMPONENT_FILES).filter(([, map]) => {
463
+ // This is a heuristic: check if any component lists this one as a directory prefix
464
+ // A more robust approach would use a proper dependency graph
465
+ return false; // Simplified for now
466
+ });
467
+ }
468
+ catch (error) {
469
+ spinner.fail('Failed to remove component');
470
+ console.error(chalk_1.default.red(error.message));
471
+ }
472
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Secret Command - Generate cryptographic secrets for ChimerAI projects
3
+ * Helps users create secure NEXTAUTH_SECRET, encryption keys, and API tokens
4
+ */
5
+ interface SecretOptions {
6
+ length?: string;
7
+ update?: boolean;
8
+ dir?: string;
9
+ }
10
+ export declare function secretCommand(type: string | undefined, options: SecretOptions): Promise<void>;
11
+ export {};
12
+ //# sourceMappingURL=secret.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret.d.ts","sourceRoot":"","sources":["../../src/commands/secret.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,UAAU,aAAa;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAsCD,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,IAAI,CAAC,CAwEf"}
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ /**
3
+ * Secret Command - Generate cryptographic secrets for ChimerAI projects
4
+ * Helps users create secure NEXTAUTH_SECRET, encryption keys, and API tokens
5
+ */
6
+ var __importDefault = (this && this.__importDefault) || function (mod) {
7
+ return (mod && mod.__esModule) ? mod : { "default": mod };
8
+ };
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.secretCommand = secretCommand;
11
+ const chalk_1 = __importDefault(require("chalk"));
12
+ const crypto_1 = __importDefault(require("crypto"));
13
+ const fs_extra_1 = __importDefault(require("fs-extra"));
14
+ const path_1 = __importDefault(require("path"));
15
+ /**
16
+ * Available secret types with descriptions and generators
17
+ */
18
+ const SECRET_TYPES = {
19
+ nextauth: {
20
+ envKey: 'NEXTAUTH_SECRET',
21
+ description: 'NextAuth.js JWT signing secret',
22
+ generate: (len) => crypto_1.default.randomBytes(len).toString('hex'),
23
+ defaultLength: 32,
24
+ hint: 'Used to encrypt/sign JWT tokens. Required for authentication.',
25
+ },
26
+ encryption: {
27
+ envKey: 'PROVIDER_ENCRYPTION_KEY',
28
+ description: 'AES-256-GCM encryption key for API key storage',
29
+ generate: (len) => crypto_1.default.randomBytes(len).toString('hex'),
30
+ defaultLength: 32,
31
+ hint: 'Used to encrypt provider API keys in the database (64 hex chars = 32 bytes).',
32
+ },
33
+ token: {
34
+ envKey: 'INTERNAL_API_TOKEN',
35
+ description: 'Internal API token for service-to-service communication',
36
+ generate: (len) => 'chimerai_internal_' + crypto_1.default.randomBytes(len).toString('hex'),
37
+ defaultLength: 32,
38
+ hint: 'Secures communication between Frontend and AI Service.',
39
+ },
40
+ };
41
+ async function secretCommand(type, options) {
42
+ console.log(chalk_1.default.bold.cyan('\nšŸ” ChimerAI Secret Generator\n'));
43
+ // If no type given → generate all and show overview
44
+ if (!type || type === 'all') {
45
+ console.log(chalk_1.default.gray('Generate cryptographically secure secrets for your .env file.\n'));
46
+ for (const [key, config] of Object.entries(SECRET_TYPES)) {
47
+ const secret = config.generate(config.defaultLength);
48
+ console.log(chalk_1.default.bold.yellow(` ${config.envKey}`));
49
+ console.log(chalk_1.default.gray(` ${config.hint}`));
50
+ console.log(chalk_1.default.green(` ${config.envKey}=${secret}`));
51
+ console.log('');
52
+ }
53
+ console.log(chalk_1.default.gray('─'.repeat(60)));
54
+ console.log(chalk_1.default.cyan(' Tipp: ') + chalk_1.default.white('Copy the values above into your .env file.'));
55
+ console.log(chalk_1.default.cyan(' Auto-update: ') + chalk_1.default.white('chimerai secret nextauth --update'));
56
+ console.log(chalk_1.default.cyan(' Specific type: ') +
57
+ chalk_1.default.white('chimerai secret nextauth | encryption | token\n'));
58
+ return;
59
+ }
60
+ // Validate type
61
+ const config = SECRET_TYPES[type];
62
+ if (!config) {
63
+ console.log(chalk_1.default.red(` āŒ Unknown secret type: "${type}"\n`));
64
+ console.log(chalk_1.default.white(' Available types:'));
65
+ for (const [key, cfg] of Object.entries(SECRET_TYPES)) {
66
+ console.log(chalk_1.default.cyan(` ${key.padEnd(12)} `) + chalk_1.default.gray(cfg.description));
67
+ }
68
+ console.log(chalk_1.default.cyan(` ${'all'.padEnd(12)} `) + chalk_1.default.gray('Generate all secrets'));
69
+ console.log('');
70
+ process.exit(1);
71
+ }
72
+ const length = options.length ? parseInt(options.length, 10) : config.defaultLength;
73
+ const secret = config.generate(length);
74
+ console.log(chalk_1.default.bold.yellow(` ${config.description}\n`));
75
+ console.log(chalk_1.default.gray(` ${config.hint}\n`));
76
+ console.log(chalk_1.default.green(` ${config.envKey}=${secret}\n`));
77
+ // --update flag: write directly into .env
78
+ if (options.update) {
79
+ const dir = options.dir || '.';
80
+ const envPath = path_1.default.resolve(dir, '.env');
81
+ if (!fs_extra_1.default.existsSync(envPath)) {
82
+ console.log(chalk_1.default.red(` āŒ .env file not found at ${envPath}`));
83
+ console.log(chalk_1.default.gray(' Run this from your project root, or use --dir <path>\n'));
84
+ process.exit(1);
85
+ }
86
+ let envContent = fs_extra_1.default.readFileSync(envPath, 'utf-8');
87
+ const regex = new RegExp(`^${config.envKey}=.*$`, 'm');
88
+ if (regex.test(envContent)) {
89
+ envContent = envContent.replace(regex, `${config.envKey}=${secret}`);
90
+ console.log(chalk_1.default.green(` āœ… Updated ${config.envKey} in ${envPath}`));
91
+ }
92
+ else {
93
+ envContent += `\n${config.envKey}=${secret}\n`;
94
+ console.log(chalk_1.default.green(` āœ… Added ${config.envKey} to ${envPath}`));
95
+ }
96
+ fs_extra_1.default.writeFileSync(envPath, envContent);
97
+ console.log(chalk_1.default.yellow(' āš ļø Restart your dev server for changes to take effect.\n'));
98
+ }
99
+ else {
100
+ console.log(chalk_1.default.gray(' Tipp: Add --update to write directly to .env\n'));
101
+ }
102
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Setup Command - Configure integrations
3
+ * REFACTORED: Provider setup creates DB entries (Phase 2), falls back to .env
4
+ * REFACTORED PHASE 4: Uses shared updateEnvFile() from utils
5
+ */
6
+ export declare function setupCommand(service: string, options?: {
7
+ dir: string;
8
+ }): Promise<void>;
9
+ //# sourceMappingURL=setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAmBH,wBAAsB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,GAAG,EAAE,MAAM,CAAA;CAAiB,iBAiD1F"}