@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,63 @@
1
+ /**
2
+ * Provider Database Utilities for CLI
3
+ *
4
+ * Handles creating/upserting providers in the Prisma database.
5
+ * Uses dynamic imports so the CLI works even if the project DB isn't available.
6
+ * Falls back to .env when DB operations fail.
7
+ */
8
+ export declare function encryptApiKey(apiKey: string, targetDir: string): string;
9
+ export interface ProviderModelDef {
10
+ modelId: string;
11
+ name: string;
12
+ capabilities: string[];
13
+ contextWindow: number;
14
+ inputCost: number;
15
+ outputCost: number;
16
+ }
17
+ export declare const OPENAI_MODELS: ProviderModelDef[];
18
+ export declare const ANTHROPIC_MODELS: ProviderModelDef[];
19
+ export declare function validateOpenAIKey(apiKey: string): Promise<{
20
+ valid: boolean;
21
+ modelCount: number;
22
+ }>;
23
+ export declare function validateAnthropicKey(apiKey: string): Promise<{
24
+ valid: boolean;
25
+ }>;
26
+ export declare function validateOllamaConnection(baseUrl: string): Promise<{
27
+ valid: boolean;
28
+ models: string[];
29
+ }>;
30
+ interface CreateProviderOptions {
31
+ targetDir: string;
32
+ providerId: string;
33
+ name: string;
34
+ type: string;
35
+ description: string;
36
+ apiKey?: string;
37
+ baseUrl?: string;
38
+ isDefault: boolean;
39
+ priority: number;
40
+ models: ProviderModelDef[];
41
+ }
42
+ /**
43
+ * Try to create/upsert a provider in the Prisma database.
44
+ * Returns true if successful, false if DB is not available.
45
+ */
46
+ export declare function createProviderInDB(options: CreateProviderOptions): Promise<boolean>;
47
+ /**
48
+ * Check if providers exist in the database and return their info.
49
+ */
50
+ export declare function getProvidersFromDB(targetDir: string): Promise<{
51
+ found: boolean;
52
+ providers: any[];
53
+ }>;
54
+ /**
55
+ * Check which .env API keys are NOT in the database (for migration).
56
+ */
57
+ export declare function findUnmigratedEnvKeys(targetDir: string): Promise<Array<{
58
+ envKey: string;
59
+ type: string;
60
+ value: string;
61
+ }>>;
62
+ export {};
63
+ //# sourceMappingURL=provider-db.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-db.d.ts","sourceRoot":"","sources":["../../src/utils/provider-db.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA0BH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CASvE;AAID,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,aAAa,EAAE,gBAAgB,EAiD3C,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,gBAAgB,EAyB9C,CAAC;AAIF,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAWjD;AAED,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC,CAqBtF;AAED,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAU/C;AAID,UAAU,qBAAqB;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,gBAAgB,EAAE,CAAC;CAC5B;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,OAAO,CAAC,CAwEzF;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,GAAG,EAAE,CAAA;CAAE,CAAC,CAuB/C;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,KAAK,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAwBjE"}
@@ -0,0 +1,300 @@
1
+ "use strict";
2
+ /**
3
+ * Provider Database Utilities for CLI
4
+ *
5
+ * Handles creating/upserting providers in the Prisma database.
6
+ * Uses dynamic imports so the CLI works even if the project DB isn't available.
7
+ * Falls back to .env when DB operations fail.
8
+ */
9
+ var __importDefault = (this && this.__importDefault) || function (mod) {
10
+ return (mod && mod.__esModule) ? mod : { "default": mod };
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.ANTHROPIC_MODELS = exports.OPENAI_MODELS = void 0;
14
+ exports.encryptApiKey = encryptApiKey;
15
+ exports.validateOpenAIKey = validateOpenAIKey;
16
+ exports.validateAnthropicKey = validateAnthropicKey;
17
+ exports.validateOllamaConnection = validateOllamaConnection;
18
+ exports.createProviderInDB = createProviderInDB;
19
+ exports.getProvidersFromDB = getProvidersFromDB;
20
+ exports.findUnmigratedEnvKeys = findUnmigratedEnvKeys;
21
+ const crypto_1 = require("crypto");
22
+ const path_1 = __importDefault(require("path"));
23
+ const fs_extra_1 = __importDefault(require("fs-extra"));
24
+ // ─── Encryption (standalone, same algorithm as @chimerai/model-providers) ────
25
+ const ALGORITHM = 'aes-256-gcm';
26
+ function getEncryptionKey(targetDir) {
27
+ // Try to read PROVIDER_ENCRYPTION_KEY from project .env
28
+ const envPath = path_1.default.join(targetDir, '.env');
29
+ let secret = 'default-secret-key-change-me-in-production';
30
+ if (fs_extra_1.default.existsSync(envPath)) {
31
+ const envContent = fs_extra_1.default.readFileSync(envPath, 'utf-8');
32
+ const match = envContent.match(/PROVIDER_ENCRYPTION_KEY=["']?([^"'\n]+)["']?/);
33
+ if (match?.[1]) {
34
+ secret = match[1];
35
+ }
36
+ }
37
+ return (0, crypto_1.createHash)('sha256').update(secret).digest();
38
+ }
39
+ function encryptApiKey(apiKey, targetDir) {
40
+ if (!apiKey)
41
+ return '';
42
+ const key = getEncryptionKey(targetDir);
43
+ const iv = (0, crypto_1.randomBytes)(16);
44
+ const cipher = (0, crypto_1.createCipheriv)(ALGORITHM, key, iv);
45
+ let encrypted = cipher.update(apiKey, 'utf8', 'base64');
46
+ encrypted += cipher.final('base64');
47
+ const authTag = cipher.getAuthTag();
48
+ return `${iv.toString('base64')}:${authTag.toString('base64')}:${encrypted}`;
49
+ }
50
+ exports.OPENAI_MODELS = [
51
+ {
52
+ modelId: 'gpt-4o',
53
+ name: 'GPT-4o',
54
+ capabilities: ['chat', 'vision'],
55
+ contextWindow: 128000,
56
+ inputCost: 5,
57
+ outputCost: 15,
58
+ },
59
+ {
60
+ modelId: 'gpt-4o-mini',
61
+ name: 'GPT-4o Mini',
62
+ capabilities: ['chat', 'vision'],
63
+ contextWindow: 128000,
64
+ inputCost: 0.15,
65
+ outputCost: 0.6,
66
+ },
67
+ {
68
+ modelId: 'gpt-4-turbo',
69
+ name: 'GPT-4 Turbo',
70
+ capabilities: ['chat', 'vision'],
71
+ contextWindow: 128000,
72
+ inputCost: 10,
73
+ outputCost: 30,
74
+ },
75
+ {
76
+ modelId: 'gpt-3.5-turbo',
77
+ name: 'GPT-3.5 Turbo',
78
+ capabilities: ['chat'],
79
+ contextWindow: 16384,
80
+ inputCost: 0.5,
81
+ outputCost: 1.5,
82
+ },
83
+ {
84
+ modelId: 'text-embedding-3-small',
85
+ name: 'Embedding 3 Small',
86
+ capabilities: ['embedding'],
87
+ contextWindow: 8191,
88
+ inputCost: 0.02,
89
+ outputCost: 0,
90
+ },
91
+ {
92
+ modelId: 'text-embedding-3-large',
93
+ name: 'Embedding 3 Large',
94
+ capabilities: ['embedding'],
95
+ contextWindow: 8191,
96
+ inputCost: 0.13,
97
+ outputCost: 0,
98
+ },
99
+ ];
100
+ exports.ANTHROPIC_MODELS = [
101
+ {
102
+ modelId: 'claude-3-5-sonnet-20241022',
103
+ name: 'Claude 3.5 Sonnet',
104
+ capabilities: ['chat', 'vision'],
105
+ contextWindow: 200000,
106
+ inputCost: 3,
107
+ outputCost: 15,
108
+ },
109
+ {
110
+ modelId: 'claude-3-opus-20240229',
111
+ name: 'Claude 3 Opus',
112
+ capabilities: ['chat', 'vision'],
113
+ contextWindow: 200000,
114
+ inputCost: 15,
115
+ outputCost: 75,
116
+ },
117
+ {
118
+ modelId: 'claude-3-haiku-20240307',
119
+ name: 'Claude 3 Haiku',
120
+ capabilities: ['chat', 'vision'],
121
+ contextWindow: 200000,
122
+ inputCost: 0.25,
123
+ outputCost: 1.25,
124
+ },
125
+ ];
126
+ // ─── Validation Helpers ─────────────────────────────────────────────────────
127
+ async function validateOpenAIKey(apiKey) {
128
+ try {
129
+ const response = await fetch('https://api.openai.com/v1/models', {
130
+ headers: { Authorization: `Bearer ${apiKey}` },
131
+ });
132
+ if (!response.ok)
133
+ return { valid: false, modelCount: 0 };
134
+ const data = (await response.json());
135
+ return { valid: true, modelCount: data.data?.length || 0 };
136
+ }
137
+ catch {
138
+ return { valid: false, modelCount: 0 };
139
+ }
140
+ }
141
+ async function validateAnthropicKey(apiKey) {
142
+ try {
143
+ const response = await fetch('https://api.anthropic.com/v1/messages', {
144
+ method: 'POST',
145
+ headers: {
146
+ 'x-api-key': apiKey,
147
+ 'anthropic-version': '2023-06-01',
148
+ 'Content-Type': 'application/json',
149
+ },
150
+ body: JSON.stringify({
151
+ model: 'claude-3-haiku-20240307',
152
+ max_tokens: 1,
153
+ messages: [{ role: 'user', content: 'hi' }],
154
+ }),
155
+ });
156
+ // 200 or 400 (bad request but valid key) means key is valid
157
+ // 401 means invalid key
158
+ return { valid: response.status !== 401 };
159
+ }
160
+ catch {
161
+ return { valid: false };
162
+ }
163
+ }
164
+ async function validateOllamaConnection(baseUrl) {
165
+ try {
166
+ const response = await fetch(`${baseUrl}/api/tags`);
167
+ if (!response.ok)
168
+ return { valid: false, models: [] };
169
+ const data = (await response.json());
170
+ const models = (data.models || []).map((m) => m.name || m.model);
171
+ return { valid: true, models };
172
+ }
173
+ catch {
174
+ return { valid: false, models: [] };
175
+ }
176
+ }
177
+ /**
178
+ * Try to create/upsert a provider in the Prisma database.
179
+ * Returns true if successful, false if DB is not available.
180
+ */
181
+ async function createProviderInDB(options) {
182
+ try {
183
+ // Dynamically load PrismaClient from the project's node_modules
184
+ const prismaClientPath = path_1.default.join(options.targetDir, 'node_modules', '@prisma', 'client');
185
+ if (!fs_extra_1.default.existsSync(prismaClientPath)) {
186
+ return false;
187
+ }
188
+ const { PrismaClient } = require(prismaClientPath);
189
+ const prisma = new PrismaClient();
190
+ try {
191
+ // Test connection
192
+ await prisma.$connect();
193
+ // Encrypt API key
194
+ const encryptedKey = options.apiKey ? encryptApiKey(options.apiKey, options.targetDir) : '';
195
+ // If setting as default, unset other defaults of same type
196
+ if (options.isDefault) {
197
+ await prisma.provider.updateMany({
198
+ where: { type: options.type, isDefault: true },
199
+ data: { isDefault: false },
200
+ });
201
+ }
202
+ // Upsert provider
203
+ await prisma.provider.upsert({
204
+ where: { id: options.providerId },
205
+ update: {
206
+ apiKey: encryptedKey,
207
+ baseUrl: options.baseUrl || null,
208
+ status: 'active',
209
+ isDefault: options.isDefault,
210
+ updatedAt: new Date(),
211
+ },
212
+ create: {
213
+ id: options.providerId,
214
+ name: options.name,
215
+ type: options.type,
216
+ description: options.description,
217
+ apiKey: encryptedKey,
218
+ baseUrl: options.baseUrl || null,
219
+ isDefault: options.isDefault,
220
+ priority: options.priority,
221
+ config: {},
222
+ tags: [],
223
+ models: {
224
+ create: options.models.map((m) => ({
225
+ modelId: m.modelId,
226
+ name: m.name,
227
+ capabilities: m.capabilities,
228
+ contextWindow: m.contextWindow,
229
+ inputCost: m.inputCost,
230
+ outputCost: m.outputCost,
231
+ isAvailable: true,
232
+ isDeprecated: false,
233
+ })),
234
+ },
235
+ },
236
+ });
237
+ await prisma.$disconnect();
238
+ return true;
239
+ }
240
+ catch (error) {
241
+ await prisma.$disconnect().catch(() => { });
242
+ return false;
243
+ }
244
+ }
245
+ catch {
246
+ return false;
247
+ }
248
+ }
249
+ /**
250
+ * Check if providers exist in the database and return their info.
251
+ */
252
+ async function getProvidersFromDB(targetDir) {
253
+ try {
254
+ const prismaClientPath = path_1.default.join(targetDir, 'node_modules', '@prisma', 'client');
255
+ if (!fs_extra_1.default.existsSync(prismaClientPath))
256
+ return { found: false, providers: [] };
257
+ const { PrismaClient } = require(prismaClientPath);
258
+ const prisma = new PrismaClient();
259
+ try {
260
+ await prisma.$connect();
261
+ const providers = await prisma.provider.findMany({
262
+ include: { models: true, health: true },
263
+ orderBy: [{ isDefault: 'desc' }, { priority: 'asc' }],
264
+ });
265
+ await prisma.$disconnect();
266
+ return { found: true, providers };
267
+ }
268
+ catch {
269
+ await prisma.$disconnect().catch(() => { });
270
+ return { found: false, providers: [] };
271
+ }
272
+ }
273
+ catch {
274
+ return { found: false, providers: [] };
275
+ }
276
+ }
277
+ /**
278
+ * Check which .env API keys are NOT in the database (for migration).
279
+ */
280
+ async function findUnmigratedEnvKeys(targetDir) {
281
+ const envPath = path_1.default.join(targetDir, '.env');
282
+ if (!fs_extra_1.default.existsSync(envPath))
283
+ return [];
284
+ const envContent = fs_extra_1.default.readFileSync(envPath, 'utf-8');
285
+ const unmigrated = [];
286
+ const keyMappings = [
287
+ { envKey: 'OPENAI_API_KEY', type: 'openai' },
288
+ { envKey: 'ANTHROPIC_API_KEY', type: 'anthropic' },
289
+ { envKey: 'AZURE_OPENAI_API_KEY', type: 'azure' },
290
+ ];
291
+ const { found, providers } = await getProvidersFromDB(targetDir);
292
+ const providerTypes = found ? providers.map((p) => p.type) : [];
293
+ for (const mapping of keyMappings) {
294
+ const match = envContent.match(new RegExp(`${mapping.envKey}=["']?([^"'\\n]+)["']?`));
295
+ if (match?.[1] && match[1] !== '' && !providerTypes.includes(mapping.type)) {
296
+ unmigrated.push({ envKey: mapping.envKey, type: mapping.type, value: match[1] });
297
+ }
298
+ }
299
+ return unmigrated;
300
+ }
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Shared CLI utilities - Validation, error handling, workspace checks, env file management
3
+ */
4
+ /**
5
+ * Validates a project or plugin name.
6
+ * - lowercase alphanumeric + hyphens only
7
+ * - max 214 chars (npm limit)
8
+ * - no leading/trailing hyphens
9
+ * - no reserved names
10
+ * - no path traversal sequences
11
+ */
12
+ export declare function validateName(name: string, label?: string): {
13
+ valid: boolean;
14
+ error?: string;
15
+ };
16
+ /**
17
+ * Validates and exits on failure. For use in Commander actions.
18
+ */
19
+ export declare function assertValidName(name: string, label?: string): void;
20
+ /**
21
+ * Checks that targetDir is a valid ChimerAI project directory.
22
+ * Verifies package.json exists.
23
+ */
24
+ export declare function validateWorkspace(targetDir: string): boolean;
25
+ /**
26
+ * Standard CLI error handler — prints message and exits with code.
27
+ */
28
+ export declare function handleCliError(message: string, code?: number): never;
29
+ /**
30
+ * Generic environment file updater utility (PHASE 2.2 / PHASE 4)
31
+ * Shared across setup.ts and other commands that need to update .env files.
32
+ * Replaces repetitive fs read/write patterns.
33
+ *
34
+ * @param envVars - Object with key-value pairs to add/update
35
+ * @param envPath - Path to .env file (default: '.env')
36
+ */
37
+ export declare function updateEnvFile(envVars: Record<string, string>, envPath?: string): Promise<void>;
38
+ interface ProjectRegistry {
39
+ projects: Record<string, string>;
40
+ default: string | null;
41
+ }
42
+ /**
43
+ * Checks if a directory is a valid ChimerAI project.
44
+ */
45
+ export declare function isChimeraiProject(dir: string): boolean;
46
+ /**
47
+ * Finds the ChimerAI project root directory.
48
+ *
49
+ * Search order (first match wins):
50
+ * 1. Directory tree walking (.chimerai marker or package.json + Next.js/Prisma)
51
+ * 2. CHIMERAI_PROJECT environment variable
52
+ * 3. Global registry default (~/.chimerai/projects.json)
53
+ * 4. Error with helpful guidance
54
+ */
55
+ export declare function findProjectRoot(startDir?: string): string;
56
+ /**
57
+ * Resolves the target directory for a command.
58
+ *
59
+ * Priority:
60
+ * 1. --dir explicitly provided (not '.')
61
+ * 2. Automatic search via findProjectRoot()
62
+ */
63
+ export declare function resolveTargetDir(dirOption: string): string;
64
+ /**
65
+ * Registers a project in the global registry.
66
+ * Called by create and init commands.
67
+ */
68
+ export declare function registerProject(name: string, absolutePath: string): void;
69
+ /**
70
+ * Sets the default project in the global registry.
71
+ */
72
+ export declare function setDefaultProject(name: string): boolean;
73
+ /**
74
+ * Lists all registered projects.
75
+ */
76
+ export declare function listRegisteredProjects(): ProjectRegistry;
77
+ export {};
78
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAmCH;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,SAAS,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CA8B7F;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,SAAS,GAAG,IAAI,CAKlE;AAMD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAY5D;AAMD;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,SAAI,GAAG,KAAK,CAG/D;AAMD;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,OAAO,GAAE,MAAe,GACvB,OAAO,CAAC,IAAI,CAAC,CAcf;AAMD,UAAU,eAAe;IACvB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAgDD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CActD;AAoBD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAiCzD;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAa1D;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAoBxE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAYvD;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,eAAe,CASxD"}