@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,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
|
+
}
|
package/dist/utils.d.ts
ADDED
|
@@ -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"}
|