careervivid 1.12.24 ā 1.12.26
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/dist/commands/agent/configurator.d.ts.map +1 -1
- package/dist/commands/agent/configurator.js +31 -8
- package/dist/config.d.ts +7 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +17 -1
- package/dist/index.js +10 -0
- package/dist/postinstall.d.ts +1 -1
- package/dist/postinstall.d.ts.map +1 -1
- package/dist/postinstall.js +21 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configurator.d.ts","sourceRoot":"","sources":["../../../src/commands/agent/configurator.ts"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"configurator.d.ts","sourceRoot":"","sources":["../../../src/commands/agent/configurator.ts"],"names":[],"mappings":"AAEA,OAAO,EAA0D,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAI3G,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAKpD,CAAC;AAEF,eAAO,MAAM,SAAS;;;;;GAyBrB,CAAC;AAEF,eAAO,MAAM,UAAU;;;;;GA+BtB,CAAC;AAEF,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAsEpD;AAED,wBAAsB,mBAAmB,CAAC,OAAO,GAAE,GAAQ,GAAG,OAAO,CAAC;IACpE,gBAAgB,EAAE,WAAW,CAAC;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC,CAwJD"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import pkg from "enquirer";
|
|
3
|
-
import { loadConfig, saveConfig } from "../../config.js";
|
|
3
|
+
import { loadConfig, saveConfig, setProviderKey, getProviderKey } from "../../config.js";
|
|
4
4
|
const { prompt } = pkg;
|
|
5
5
|
export const MODEL_CREDIT_COST = {
|
|
6
6
|
"gemini-3.1-flash-lite-preview": 0.5,
|
|
@@ -165,20 +165,42 @@ export async function promptForAgentModel(options = {}) {
|
|
|
165
165
|
__custom__: "custom",
|
|
166
166
|
};
|
|
167
167
|
selectedProvider = providerMap[picked] || "openai";
|
|
168
|
-
const
|
|
169
|
-
|
|
168
|
+
const providerLabels = {
|
|
169
|
+
openai: "OpenAI",
|
|
170
|
+
anthropic: "Anthropic",
|
|
171
|
+
gemini: "Gemini (Google AI Studio)",
|
|
172
|
+
openrouter: "OpenRouter",
|
|
173
|
+
custom: "Custom endpoint",
|
|
174
|
+
};
|
|
175
|
+
const providerKeyUrls = {
|
|
176
|
+
openai: "https://platform.openai.com/api-keys",
|
|
177
|
+
anthropic: "https://console.anthropic.com/settings/keys",
|
|
178
|
+
gemini: "https://aistudio.google.com/app/apikey",
|
|
179
|
+
openrouter: "https://openrouter.ai/settings/keys",
|
|
180
|
+
custom: "your custom endpoint's documentation",
|
|
181
|
+
};
|
|
182
|
+
// Check for this specific provider's saved key ā NOT a shared key
|
|
183
|
+
const savedKey = getProviderKey(selectedProvider);
|
|
170
184
|
if (!savedKey) {
|
|
171
|
-
console.log(
|
|
172
|
-
console.log(chalk.
|
|
185
|
+
console.log();
|
|
186
|
+
console.log(chalk.bold.yellow(`š API key required for ${providerLabels[selectedProvider] ?? selectedProvider}`) +
|
|
187
|
+
chalk.dim("\n Your key will be saved locally ā you only need to enter it once."));
|
|
188
|
+
console.log(chalk.dim(`\n Get your key at: `) + chalk.cyan(providerKeyUrls[selectedProvider] ?? "the provider's website"));
|
|
189
|
+
console.log();
|
|
173
190
|
const keyAnswer = await prompt({
|
|
174
191
|
type: "password",
|
|
175
192
|
name: "key",
|
|
176
|
-
message: `Enter your ${selectedProvider} API key:`,
|
|
193
|
+
message: `Enter your ${providerLabels[selectedProvider] ?? selectedProvider} API key:`,
|
|
177
194
|
});
|
|
178
195
|
apiKey = keyAnswer.key.trim();
|
|
196
|
+
if (apiKey) {
|
|
197
|
+
setProviderKey(selectedProvider, apiKey);
|
|
198
|
+
console.log(chalk.green(`\nā Key saved for ${providerLabels[selectedProvider] ?? selectedProvider}\n`));
|
|
199
|
+
}
|
|
179
200
|
}
|
|
180
|
-
|
|
181
|
-
apiKey = savedKey;
|
|
201
|
+
else {
|
|
202
|
+
apiKey = savedKey;
|
|
203
|
+
console.log(chalk.dim(`\n Using saved ${providerLabels[selectedProvider] ?? selectedProvider} key (ā¢ā¢ā¢ā¢${savedKey.slice(-4)})\n`));
|
|
182
204
|
}
|
|
183
205
|
// Attempt to automatically fetch and display Free OpenRouter models that support tools
|
|
184
206
|
if (selectedProvider === "openrouter") {
|
|
@@ -217,6 +239,7 @@ export async function promptForAgentModel(options = {}) {
|
|
|
217
239
|
}
|
|
218
240
|
}
|
|
219
241
|
// Pre-fill with the saved model when provider matches, otherwise use sensible defaults
|
|
242
|
+
const savedCfg = loadConfig();
|
|
220
243
|
const defaultModel = savedCfg.llmProvider === selectedProvider && savedCfg.llmModel
|
|
221
244
|
? savedCfg.llmModel
|
|
222
245
|
: selectedProvider === "openai"
|
package/dist/config.d.ts
CHANGED
|
@@ -20,8 +20,10 @@ export interface CareerVividConfig {
|
|
|
20
20
|
llmProvider?: LLMProvider;
|
|
21
21
|
/** BYO model identifier (e.g. "gpt-4o", "claude-opus-4-5", "gemini-2.5-pro") */
|
|
22
22
|
llmModel?: string;
|
|
23
|
-
/**
|
|
23
|
+
/** @deprecated use llmKeys[provider] instead ā kept for migration */
|
|
24
24
|
llmApiKey?: string;
|
|
25
|
+
/** Per-provider API keys ā keyed by provider name */
|
|
26
|
+
llmKeys?: Partial<Record<LLMProvider, string>>;
|
|
25
27
|
/** Custom base URL for OpenAI-compatible endpoints (OpenRouter, Kimi, GLM, Qwen, etc.) */
|
|
26
28
|
llmBaseUrl?: string;
|
|
27
29
|
}
|
|
@@ -36,6 +38,10 @@ export declare function saveConfig(config: CareerVividConfig): void;
|
|
|
36
38
|
export declare function getApiKey(): string | undefined;
|
|
37
39
|
/** Gemini API key used by `cv agent`. Priority: GEMINI_API_KEY env var > geminiKey in config. */
|
|
38
40
|
export declare function getGeminiKey(): string | undefined;
|
|
41
|
+
/** Get the saved API key for a specific BYO provider */
|
|
42
|
+
export declare function getProviderKey(provider: LLMProvider): string | undefined;
|
|
43
|
+
/** Save the API key for a specific BYO provider */
|
|
44
|
+
export declare function setProviderKey(provider: LLMProvider, key: string): void;
|
|
39
45
|
export declare function getApiUrl(): string;
|
|
40
46
|
export declare function setConfigValue(key: keyof CareerVividConfig, value: string): void;
|
|
41
47
|
/** How long a CLI session stays valid (90 days in ms) */
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,eAAO,MAAM,WAAW,QAAyC,CAAC;AAElE,eAAO,MAAM,eAAe,gCAAgC,CAAC;AAE7D,MAAM,MAAM,WAAW,GAAG,aAAa,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,GAAG,YAAY,GAAG,QAAQ,CAAC;AAEtG,MAAM,WAAW,iBAAiB;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,wDAAwD;IACxD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kCAAkC;IAClC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,eAAO,MAAM,WAAW,QAAyC,CAAC;AAElE,eAAO,MAAM,eAAe,gCAAgC,CAAC;AAE7D,MAAM,MAAM,WAAW,GAAG,aAAa,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,GAAG,YAAY,GAAG,QAAQ,CAAC;AAEtG,MAAM,WAAW,iBAAiB;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,wDAAwD;IACxD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kCAAkC;IAClC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qDAAqD;IACrD,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;IAC/C,0FAA0F;IAC1F,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACtB,QAAQ,EAAE,WAAW,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,UAAU,IAAI,iBAAiB,CAQ9C;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAE1D;AAED,wBAAgB,SAAS,IAAI,MAAM,GAAG,SAAS,CAG9C;AAED,iGAAiG;AACjG,wBAAgB,YAAY,IAAI,MAAM,GAAG,SAAS,CAEjD;AAED,wDAAwD;AACxD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,CAIxE;AAED,mDAAmD;AACnD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAQvE;AAED,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,iBAAiB,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAIhF;AAID,yDAAyD;AACzD,eAAO,MAAM,cAAc,QAA2B,CAAC;AAEvD,wDAAwD;AACxD,wBAAgB,cAAc,IAAI,OAAO,CAMxC;AAED,mFAAmF;AACnF,wBAAgB,YAAY,IAAI,IAAI,CAInC;AAED,0CAA0C;AAC1C,wBAAgB,YAAY,IAAI,IAAI,CAMnC;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,SAAS,CAAC,EAAE;IACrC,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,SAAS,CA6BZ"}
|
package/dist/config.js
CHANGED
|
@@ -32,6 +32,22 @@ export function getApiKey() {
|
|
|
32
32
|
export function getGeminiKey() {
|
|
33
33
|
return process.env.GEMINI_API_KEY || loadConfig().geminiKey;
|
|
34
34
|
}
|
|
35
|
+
/** Get the saved API key for a specific BYO provider */
|
|
36
|
+
export function getProviderKey(provider) {
|
|
37
|
+
const cfg = loadConfig();
|
|
38
|
+
// Per-provider key takes priority, fallback to old llmApiKey (migration)
|
|
39
|
+
return cfg.llmKeys?.[provider] ?? (cfg.llmProvider === provider ? cfg.llmApiKey : undefined);
|
|
40
|
+
}
|
|
41
|
+
/** Save the API key for a specific BYO provider */
|
|
42
|
+
export function setProviderKey(provider, key) {
|
|
43
|
+
const cfg = loadConfig();
|
|
44
|
+
cfg.llmKeys = cfg.llmKeys ?? {};
|
|
45
|
+
cfg.llmKeys[provider] = key;
|
|
46
|
+
// Also write to llmApiKey for backwards compat when this is the active provider
|
|
47
|
+
cfg.llmApiKey = key;
|
|
48
|
+
cfg.llmProvider = provider;
|
|
49
|
+
saveConfig(cfg);
|
|
50
|
+
}
|
|
35
51
|
export function getApiUrl() {
|
|
36
52
|
return process.env.CV_API_URL || loadConfig().apiUrl || DEFAULT_API_URL;
|
|
37
53
|
}
|
|
@@ -83,7 +99,7 @@ export function getLlmConfig(overrides) {
|
|
|
83
99
|
'gemini-2.5-flash';
|
|
84
100
|
const apiKey = overrides?.apiKey ??
|
|
85
101
|
process.env.CV_LLM_API_KEY ??
|
|
86
|
-
|
|
102
|
+
getProviderKey(provider) ??
|
|
87
103
|
cfg.geminiKey ??
|
|
88
104
|
process.env.GEMINI_API_KEY;
|
|
89
105
|
const baseUrl = overrides?.baseUrl ??
|
package/dist/index.js
CHANGED
|
@@ -19,6 +19,16 @@
|
|
|
19
19
|
* cv update [files...] Update existing content on CareerVivid
|
|
20
20
|
* cv --help / cv --version
|
|
21
21
|
*/
|
|
22
|
+
// āā Node version guard (must be before ESM imports) āāāāāāāāāāāāāāāāāāāāāāāāā
|
|
23
|
+
// Uses only Node built-ins so it works on ANY Node version.
|
|
24
|
+
const [nodeMajor] = process.versions.node.split(".").map(Number);
|
|
25
|
+
if (nodeMajor < 18) {
|
|
26
|
+
process.stderr.write(`\nā ļø CareerVivid CLI requires Node.js v18 or higher.\n` +
|
|
27
|
+
` You are running Node ${process.versions.node}.\n\n` +
|
|
28
|
+
` Upgrade at: https://nodejs.org (download the LTS release)\n` +
|
|
29
|
+
` or: nvm install --lts && nvm use --lts\n\n`);
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
22
32
|
import { Command } from "commander";
|
|
23
33
|
import { readFileSync, existsSync } from "fs";
|
|
24
34
|
import chalk from "chalk";
|
package/dist/postinstall.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* CareerVivid CLI ā Post-install hook
|
|
3
3
|
*
|
|
4
4
|
* This script runs after 'npm install -g careervivid'.
|
|
5
|
-
* It prints a
|
|
5
|
+
* It checks Node version compatibility and prints a welcome message.
|
|
6
6
|
*/
|
|
7
7
|
export declare function printPostInstall(): void;
|
|
8
8
|
//# sourceMappingURL=postinstall.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postinstall.d.ts","sourceRoot":"","sources":["../src/postinstall.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"postinstall.d.ts","sourceRoot":"","sources":["../src/postinstall.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAiCH,wBAAgB,gBAAgB,SA4C/B"}
|
package/dist/postinstall.js
CHANGED
|
@@ -2,13 +2,33 @@
|
|
|
2
2
|
* CareerVivid CLI ā Post-install hook
|
|
3
3
|
*
|
|
4
4
|
* This script runs after 'npm install -g careervivid'.
|
|
5
|
-
* It prints a
|
|
5
|
+
* It checks Node version compatibility and prints a welcome message.
|
|
6
6
|
*/
|
|
7
7
|
import chalk from "chalk";
|
|
8
8
|
import boxen from "boxen";
|
|
9
9
|
import { getHelpHeader } from "./branding.js";
|
|
10
10
|
const VERSION = "1.1.14";
|
|
11
|
+
const MIN_NODE_MAJOR = 18;
|
|
12
|
+
function checkNodeVersion() {
|
|
13
|
+
const [major] = process.versions.node.split(".").map(Number);
|
|
14
|
+
if (major < MIN_NODE_MAJOR) {
|
|
15
|
+
console.error(boxen(`${chalk.bold.red("ā ļø Node.js version too old")}\n\n` +
|
|
16
|
+
`You have Node ${chalk.bold(process.versions.node)}, but CareerVivid CLI requires ${chalk.bold(`v${MIN_NODE_MAJOR}+`)}\n\n` +
|
|
17
|
+
`${chalk.bold("To upgrade Node.js:")}\n` +
|
|
18
|
+
` ${chalk.cyan("https://nodejs.org")} (download the LTS release)\n` +
|
|
19
|
+
` ${chalk.dim("or")} ${chalk.cyan("nvm install --lts && nvm use --lts")}\n\n` +
|
|
20
|
+
`${chalk.dim("The CLI may not work correctly until you upgrade.")}`, {
|
|
21
|
+
padding: 1,
|
|
22
|
+
borderStyle: "round",
|
|
23
|
+
borderColor: "red",
|
|
24
|
+
title: "Version Warning",
|
|
25
|
+
titleAlignment: "center",
|
|
26
|
+
}));
|
|
27
|
+
// Don't exit ā let them at least see the welcome message
|
|
28
|
+
}
|
|
29
|
+
}
|
|
11
30
|
export function printPostInstall() {
|
|
31
|
+
checkNodeVersion();
|
|
12
32
|
console.log();
|
|
13
33
|
console.log(getHelpHeader());
|
|
14
34
|
// āā Onboarding box āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "careervivid",
|
|
3
|
-
"version": "1.12.
|
|
3
|
+
"version": "1.12.26",
|
|
4
4
|
"description": "Official CLI for CareerVivid ā publish articles, diagrams, and portfolio updates from your terminal or AI agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"typescript": "^5.4.0"
|
|
44
44
|
},
|
|
45
45
|
"engines": {
|
|
46
|
-
"node": ">=
|
|
46
|
+
"node": ">=18.0.0"
|
|
47
47
|
},
|
|
48
48
|
"overrides": {
|
|
49
49
|
"braces": "3.0.3",
|