@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.
- package/LICENSE +21 -0
- package/README.md +293 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +317 -0
- package/dist/commands/add.d.ts +11 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +2126 -0
- package/dist/commands/create.d.ts +12 -0
- package/dist/commands/create.d.ts.map +1 -0
- package/dist/commands/create.js +1703 -0
- package/dist/commands/deploy.d.ts +11 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +219 -0
- package/dist/commands/dev.d.ts +17 -0
- package/dist/commands/dev.d.ts.map +1 -0
- package/dist/commands/dev.js +206 -0
- package/dist/commands/doctor.d.ts +11 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +728 -0
- package/dist/commands/generate.d.ts +19 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/generate.js +429 -0
- package/dist/commands/init.d.ts +11 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +269 -0
- package/dist/commands/list.d.ts +12 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +328 -0
- package/dist/commands/migrate.d.ts +14 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +197 -0
- package/dist/commands/plugin.d.ts +10 -0
- package/dist/commands/plugin.d.ts.map +1 -0
- package/dist/commands/plugin.js +239 -0
- package/dist/commands/remove.d.ts +11 -0
- package/dist/commands/remove.d.ts.map +1 -0
- package/dist/commands/remove.js +472 -0
- package/dist/commands/secret.d.ts +12 -0
- package/dist/commands/secret.d.ts.map +1 -0
- package/dist/commands/secret.js +102 -0
- package/dist/commands/setup.d.ts +9 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +788 -0
- package/dist/commands/update.d.ts +14 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +211 -0
- package/dist/commands/use.d.ts +9 -0
- package/dist/commands/use.d.ts.map +1 -0
- package/dist/commands/use.js +51 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +45 -0
- package/dist/license.d.ts +55 -0
- package/dist/license.d.ts.map +1 -0
- package/dist/license.js +258 -0
- package/dist/scanner.d.ts +31 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +113 -0
- package/dist/schema-manager.d.ts +26 -0
- package/dist/schema-manager.d.ts.map +1 -0
- package/dist/schema-manager.js +132 -0
- package/dist/templates/admin.d.ts +49 -0
- package/dist/templates/admin.d.ts.map +1 -0
- package/dist/templates/admin.js +1358 -0
- package/dist/templates/ai-routes.d.ts +17 -0
- package/dist/templates/ai-routes.d.ts.map +1 -0
- package/dist/templates/ai-routes.js +1130 -0
- package/dist/templates/ai-service-tools.d.ts +22 -0
- package/dist/templates/ai-service-tools.d.ts.map +1 -0
- package/dist/templates/ai-service-tools.js +1424 -0
- package/dist/templates/ai-service.d.ts +66 -0
- package/dist/templates/ai-service.d.ts.map +1 -0
- package/dist/templates/ai-service.js +2202 -0
- package/dist/templates/api-routes.d.ts +108 -0
- package/dist/templates/api-routes.d.ts.map +1 -0
- package/dist/templates/api-routes.js +1219 -0
- package/dist/templates/auth.d.ts +48 -0
- package/dist/templates/auth.d.ts.map +1 -0
- package/dist/templates/auth.js +381 -0
- package/dist/templates/billing.d.ts +44 -0
- package/dist/templates/billing.d.ts.map +1 -0
- package/dist/templates/billing.js +551 -0
- package/dist/templates/chat.d.ts +63 -0
- package/dist/templates/chat.d.ts.map +1 -0
- package/dist/templates/chat.js +1979 -0
- package/dist/templates/components.d.ts +22 -0
- package/dist/templates/components.d.ts.map +1 -0
- package/dist/templates/components.js +672 -0
- package/dist/templates/config.d.ts +6 -0
- package/dist/templates/config.d.ts.map +1 -0
- package/dist/templates/config.js +86 -0
- package/dist/templates/docker.d.ts +25 -0
- package/dist/templates/docker.d.ts.map +1 -0
- package/dist/templates/docker.js +165 -0
- package/dist/templates/gdpr.d.ts +16 -0
- package/dist/templates/gdpr.d.ts.map +1 -0
- package/dist/templates/gdpr.js +259 -0
- package/dist/templates/index.d.ts +77 -0
- package/dist/templates/index.d.ts.map +1 -0
- package/dist/templates/index.js +339 -0
- package/dist/templates/layout.d.ts +67 -0
- package/dist/templates/layout.d.ts.map +1 -0
- package/dist/templates/layout.js +670 -0
- package/dist/templates/mfa.d.ts +23 -0
- package/dist/templates/mfa.d.ts.map +1 -0
- package/dist/templates/mfa.js +353 -0
- package/dist/templates/middleware.d.ts +12 -0
- package/dist/templates/middleware.d.ts.map +1 -0
- package/dist/templates/middleware.js +116 -0
- package/dist/templates/prisma.d.ts +35 -0
- package/dist/templates/prisma.d.ts.map +1 -0
- package/dist/templates/prisma.js +724 -0
- package/dist/templates/provider-routes.d.ts +21 -0
- package/dist/templates/provider-routes.d.ts.map +1 -0
- package/dist/templates/provider-routes.js +1203 -0
- package/dist/templates/rag.d.ts +48 -0
- package/dist/templates/rag.d.ts.map +1 -0
- package/dist/templates/rag.js +532 -0
- package/dist/templates/widget.d.ts +64 -0
- package/dist/templates/widget.d.ts.map +1 -0
- package/dist/templates/widget.js +1360 -0
- package/dist/utils/provider-db.d.ts +63 -0
- package/dist/utils/provider-db.d.ts.map +1 -0
- package/dist/utils/provider-db.js +300 -0
- package/dist/utils.d.ts +78 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +330 -0
- 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"}
|