@nhonh/qabot 0.2.3 → 0.3.0
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/package.json +1 -1
- package/src/ai/ai-engine.js +4 -0
- package/src/cli/commands/auth.js +69 -11
- package/src/core/constants.js +1 -1
package/package.json
CHANGED
package/src/ai/ai-engine.js
CHANGED
|
@@ -34,11 +34,15 @@ export class AIEngine {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
getProviderInfo() {
|
|
37
|
+
const preview = this.apiKey
|
|
38
|
+
? this.apiKey.slice(0, 4) + "****" + this.apiKey.slice(-4)
|
|
39
|
+
: "";
|
|
37
40
|
return {
|
|
38
41
|
provider: this.provider,
|
|
39
42
|
model: this.model,
|
|
40
43
|
baseUrl: this.baseUrl,
|
|
41
44
|
hasApiKey: !!this.apiKey,
|
|
45
|
+
apiKeyPreview: preview,
|
|
42
46
|
};
|
|
43
47
|
}
|
|
44
48
|
|
package/src/cli/commands/auth.js
CHANGED
|
@@ -43,12 +43,43 @@ function showCurrentConfig(config) {
|
|
|
43
43
|
["Setting", "Value"],
|
|
44
44
|
[
|
|
45
45
|
["Provider", info.provider || "none"],
|
|
46
|
-
["Model", info.model || "
|
|
46
|
+
["Model", info.model || "(proxy default)"],
|
|
47
47
|
["Base URL", info.baseUrl || "(default)"],
|
|
48
|
-
[
|
|
48
|
+
[
|
|
49
|
+
"API Key",
|
|
50
|
+
info.hasApiKey ? `\u2713 ${info.apiKeyPreview}` : "\u2717 missing",
|
|
51
|
+
],
|
|
52
|
+
["Auth Header", engine.authHeader || "(none)"],
|
|
53
|
+
[
|
|
54
|
+
"Key Source",
|
|
55
|
+
ai.apiKey
|
|
56
|
+
? "config (apiKey)"
|
|
57
|
+
: ai.apiKeyEnv
|
|
58
|
+
? `env ($${ai.apiKeyEnv})`
|
|
59
|
+
: "auto-detect",
|
|
60
|
+
],
|
|
61
|
+
["Available", engine.isAvailable() ? "\u2713 yes" : "\u2717 no"],
|
|
49
62
|
],
|
|
50
63
|
);
|
|
51
64
|
logger.blank();
|
|
65
|
+
|
|
66
|
+
if (!engine.isAvailable()) {
|
|
67
|
+
logger.warn("AI is not available. To fix:");
|
|
68
|
+
if (info.provider === "proxy") {
|
|
69
|
+
logger.dim(" Option 1: Set apiKey directly in qabot.config.json:");
|
|
70
|
+
logger.dim(' "ai": { "apiKey": "your-key", ... }');
|
|
71
|
+
logger.dim(
|
|
72
|
+
` Option 2: Set env var: export ${ai.apiKeyEnv || "PROXY_API_KEY"}=your-key`,
|
|
73
|
+
);
|
|
74
|
+
logger.dim(
|
|
75
|
+
" Option 3: Remove auth requirement if proxy doesn't need it:",
|
|
76
|
+
);
|
|
77
|
+
logger.dim(' "ai": { "authHeader": null, ... }');
|
|
78
|
+
} else {
|
|
79
|
+
logger.dim(" Run: qabot auth");
|
|
80
|
+
}
|
|
81
|
+
logger.blank();
|
|
82
|
+
}
|
|
52
83
|
}
|
|
53
84
|
|
|
54
85
|
async function testConnection(config) {
|
|
@@ -60,7 +91,17 @@ async function testConnection(config) {
|
|
|
60
91
|
return;
|
|
61
92
|
}
|
|
62
93
|
|
|
94
|
+
const info = engine.getProviderInfo();
|
|
63
95
|
logger.info(`Testing connection to ${chalk.bold(engine.provider)}...`);
|
|
96
|
+
logger.blank();
|
|
97
|
+
logger.dim(` Provider: ${info.provider}`);
|
|
98
|
+
logger.dim(` Model: ${info.model || "(none)"}`);
|
|
99
|
+
logger.dim(` Base URL: ${info.baseUrl}`);
|
|
100
|
+
logger.dim(
|
|
101
|
+
` API Key: ${info.hasApiKey ? info.apiKeyPreview : "(none)"}`,
|
|
102
|
+
);
|
|
103
|
+
logger.dim(` Auth Header: ${engine.authHeader || "(none)"}`);
|
|
104
|
+
logger.blank();
|
|
64
105
|
|
|
65
106
|
try {
|
|
66
107
|
const response = await engine.complete("Reply with exactly: QABOT_OK");
|
|
@@ -76,6 +117,30 @@ async function testConnection(config) {
|
|
|
76
117
|
}
|
|
77
118
|
} catch (err) {
|
|
78
119
|
logger.error(`Connection failed: ${err.message}`);
|
|
120
|
+
logger.blank();
|
|
121
|
+
logger.info("Troubleshooting:");
|
|
122
|
+
if (err.message.includes("401") || err.message.includes("auth")) {
|
|
123
|
+
logger.dim(" 1. Check API key is correct");
|
|
124
|
+
logger.dim(
|
|
125
|
+
` 2. Verify env var: echo $${ai.apiKeyEnv || "PROXY_API_KEY"}`,
|
|
126
|
+
);
|
|
127
|
+
logger.dim(" 3. Or set apiKey directly in qabot.config.json:");
|
|
128
|
+
logger.dim(' "ai": { "apiKey": "your-key-here", ... }');
|
|
129
|
+
}
|
|
130
|
+
if (
|
|
131
|
+
err.message.includes("ECONNREFUSED") ||
|
|
132
|
+
err.message.includes("connect")
|
|
133
|
+
) {
|
|
134
|
+
logger.dim(` 1. Check server is running at ${info.baseUrl}`);
|
|
135
|
+
logger.dim(" 2. Verify URL is correct in qabot.config.json");
|
|
136
|
+
}
|
|
137
|
+
if (err.message.includes("500")) {
|
|
138
|
+
logger.dim(" 1. Server error — check proxy/LLM server logs");
|
|
139
|
+
logger.dim(" 2. Model name may be wrong — verify ai.model in config");
|
|
140
|
+
logger.dim(
|
|
141
|
+
` 3. Try: curl -X POST ${info.baseUrl} -H "Content-Type: application/json" -d '{"messages":[{"role":"user","content":"hi"}]}'`,
|
|
142
|
+
);
|
|
143
|
+
}
|
|
79
144
|
}
|
|
80
145
|
}
|
|
81
146
|
|
|
@@ -168,11 +233,8 @@ async function interactiveSetup(projectDir, config, isEmpty) {
|
|
|
168
233
|
}
|
|
169
234
|
|
|
170
235
|
if (proxyAnswers.apiKey) {
|
|
236
|
+
aiConfig.apiKey = proxyAnswers.apiKey;
|
|
171
237
|
aiConfig.apiKeyEnv = "PROXY_API_KEY";
|
|
172
|
-
logger.blank();
|
|
173
|
-
logger.warn("Store your API key as an environment variable:");
|
|
174
|
-
logger.dim(` export PROXY_API_KEY="${proxyAnswers.apiKey}"`);
|
|
175
|
-
logger.dim(" Or add to .env file: PROXY_API_KEY=your-key");
|
|
176
238
|
}
|
|
177
239
|
} else if (provider === "ollama") {
|
|
178
240
|
const { baseUrl, model } = await enquirer.prompt([
|
|
@@ -218,12 +280,8 @@ async function interactiveSetup(projectDir, config, isEmpty) {
|
|
|
218
280
|
|
|
219
281
|
aiConfig.model = answers.model;
|
|
220
282
|
aiConfig.apiKeyEnv = envName;
|
|
221
|
-
|
|
222
283
|
if (answers.apiKey) {
|
|
223
|
-
|
|
224
|
-
logger.warn("Store your API key as an environment variable:");
|
|
225
|
-
logger.dim(` export ${envName}="${answers.apiKey}"`);
|
|
226
|
-
logger.dim(` Or add to .env file: ${envName}=your-key`);
|
|
284
|
+
aiConfig.apiKey = answers.apiKey;
|
|
227
285
|
}
|
|
228
286
|
}
|
|
229
287
|
|
package/src/core/constants.js
CHANGED