@qverisai/cli 0.1.0 → 0.2.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/README.md +24 -2
- package/package.json +1 -1
- package/src/client/api.mjs +7 -10
- package/src/config/region.mjs +64 -0
package/README.md
CHANGED
|
@@ -242,6 +242,28 @@ qveris discover "weather" --api-key "sk-1_..."
|
|
|
242
242
|
|
|
243
243
|
**Resolution order:** `--api-key` flag > `QVERIS_API_KEY` env > config file
|
|
244
244
|
|
|
245
|
+
### Region
|
|
246
|
+
|
|
247
|
+
The API region is auto-detected from your key prefix:
|
|
248
|
+
|
|
249
|
+
| Key prefix | Region | Base URL |
|
|
250
|
+
|------------|--------|----------|
|
|
251
|
+
| `sk-xxx` | Global | `https://qveris.ai/api/v1` |
|
|
252
|
+
| `sk-cn-xxx` | China | `https://qveris.cn/api/v1` |
|
|
253
|
+
|
|
254
|
+
No extra configuration needed. To override manually:
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
# Via environment variable
|
|
258
|
+
export QVERIS_REGION=cn
|
|
259
|
+
|
|
260
|
+
# Or set a custom base URL
|
|
261
|
+
export QVERIS_BASE_URL=https://custom.endpoint/api/v1
|
|
262
|
+
|
|
263
|
+
# Or per-command
|
|
264
|
+
qveris discover "weather" --base-url https://qveris.cn/api/v1
|
|
265
|
+
```
|
|
266
|
+
|
|
245
267
|
### Config File
|
|
246
268
|
|
|
247
269
|
Located at `~/.config/qveris/config.json` (respects `XDG_CONFIG_HOME`).
|
|
@@ -313,9 +335,9 @@ QVeris CLI uses only Node.js built-in APIs. No `chalk`, no `commander`, no `yarg
|
|
|
313
335
|
|
|
314
336
|
## Links
|
|
315
337
|
|
|
316
|
-
- Website: https://qveris.ai
|
|
338
|
+
- Website: https://qveris.ai (global) / https://qveris.cn (China)
|
|
317
339
|
- API Docs: https://qveris.ai/docs
|
|
318
|
-
- Get API Key: https://qveris.ai/account?page=api-keys
|
|
340
|
+
- Get API Key: https://qveris.ai/account?page=api-keys (global) / https://qveris.cn/account?page=api-keys (China)
|
|
319
341
|
- GitHub: https://github.com/QVerisAI/QVerisAI
|
|
320
342
|
|
|
321
343
|
## License
|
package/package.json
CHANGED
package/src/client/api.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { resolveBaseUrl } from "../config/region.mjs";
|
|
2
2
|
import { CliError } from "../errors/handler.mjs";
|
|
3
3
|
|
|
4
|
-
function getBaseUrl(
|
|
5
|
-
return
|
|
4
|
+
function getBaseUrl(baseUrlFlag, apiKey) {
|
|
5
|
+
return resolveBaseUrl({ baseUrlFlag, apiKey }).baseUrl;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
async function requestJson(path, { method = "POST", query = {}, body, timeoutMs = 30000, apiKey, baseUrl }) {
|
|
@@ -10,7 +10,7 @@ async function requestJson(path, { method = "POST", query = {}, body, timeoutMs
|
|
|
10
10
|
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
11
11
|
|
|
12
12
|
try {
|
|
13
|
-
const url = new URL(baseUrl.replace(
|
|
13
|
+
const url = new URL(baseUrl.replace(/\/+$/, "") + path);
|
|
14
14
|
for (const [key, value] of Object.entries(query)) {
|
|
15
15
|
if (value !== undefined && value !== null) {
|
|
16
16
|
url.searchParams.set(key, String(value));
|
|
@@ -35,8 +35,6 @@ async function requestJson(path, { method = "POST", query = {}, body, timeoutMs
|
|
|
35
35
|
jsonBody = JSON.parse(rawText);
|
|
36
36
|
errorDetail = jsonBody.error_message || jsonBody.message || null;
|
|
37
37
|
} catch { /* not JSON */ }
|
|
38
|
-
// For known error codes, pass errorDetail only if it's a meaningful message
|
|
39
|
-
// (not raw JSON); otherwise let the CliError template message apply
|
|
40
38
|
if (status === 401 || status === 403) throw new CliError("AUTH_INVALID_KEY", errorDetail);
|
|
41
39
|
if (status === 402) throw new CliError("CREDITS_INSUFFICIENT", errorDetail);
|
|
42
40
|
if (status === 429) throw new CliError("RATE_LIMITED", errorDetail);
|
|
@@ -60,12 +58,12 @@ async function requestJson(path, { method = "POST", query = {}, body, timeoutMs
|
|
|
60
58
|
}
|
|
61
59
|
|
|
62
60
|
export async function discoverTools({ apiKey, baseUrl: baseUrlFlag, query, limit = 5, timeoutMs = 30000 }) {
|
|
63
|
-
const baseUrl = getBaseUrl(baseUrlFlag);
|
|
61
|
+
const baseUrl = getBaseUrl(baseUrlFlag, apiKey);
|
|
64
62
|
return requestJson("/search", { apiKey, baseUrl, body: { query, limit }, timeoutMs });
|
|
65
63
|
}
|
|
66
64
|
|
|
67
65
|
export async function inspectToolsByIds({ apiKey, baseUrl: baseUrlFlag, toolIds, discoveryId, timeoutMs = 30000 }) {
|
|
68
|
-
const baseUrl = getBaseUrl(baseUrlFlag);
|
|
66
|
+
const baseUrl = getBaseUrl(baseUrlFlag, apiKey);
|
|
69
67
|
const body = { tool_ids: toolIds };
|
|
70
68
|
if (discoveryId) body.search_id = discoveryId;
|
|
71
69
|
return requestJson("/tools/by-ids", { apiKey, baseUrl, body, timeoutMs });
|
|
@@ -80,7 +78,7 @@ export async function callTool({
|
|
|
80
78
|
maxResponseSize = 102400,
|
|
81
79
|
timeoutMs = 120000,
|
|
82
80
|
}) {
|
|
83
|
-
const baseUrl = getBaseUrl(baseUrlFlag);
|
|
81
|
+
const baseUrl = getBaseUrl(baseUrlFlag, apiKey);
|
|
84
82
|
return requestJson("/tools/execute", {
|
|
85
83
|
apiKey,
|
|
86
84
|
baseUrl,
|
|
@@ -93,4 +91,3 @@ export async function callTool({
|
|
|
93
91
|
timeoutMs,
|
|
94
92
|
});
|
|
95
93
|
}
|
|
96
|
-
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Region resolution for QVeris API.
|
|
3
|
+
*
|
|
4
|
+
* Priority: --base-url flag > QVERIS_BASE_URL env > QVERIS_REGION env > key prefix auto-detect > default (global)
|
|
5
|
+
*
|
|
6
|
+
* Key prefix convention:
|
|
7
|
+
* sk-cn-xxx → cn region (qveris.cn)
|
|
8
|
+
* sk-xxx → global (qveris.ai)
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const REGION_URLS = {
|
|
12
|
+
global: "https://qveris.ai/api/v1",
|
|
13
|
+
cn: "https://qveris.cn/api/v1",
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Detect region from API key prefix.
|
|
18
|
+
* @param {string} apiKey
|
|
19
|
+
* @returns {"cn"|"global"}
|
|
20
|
+
*/
|
|
21
|
+
export function detectRegionFromKey(apiKey) {
|
|
22
|
+
if (typeof apiKey === "string" && apiKey.startsWith("sk-cn-")) return "cn";
|
|
23
|
+
return "global";
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Resolve the base URL for the QVeris API.
|
|
28
|
+
*
|
|
29
|
+
* Priority:
|
|
30
|
+
* 1. Explicit base URL (--base-url flag or QVERIS_BASE_URL env)
|
|
31
|
+
* 2. Explicit region (QVERIS_REGION env or config)
|
|
32
|
+
* 3. Auto-detect from API key prefix
|
|
33
|
+
* 4. Default: global (qveris.ai)
|
|
34
|
+
*
|
|
35
|
+
* @param {{ baseUrlFlag?: string, apiKey?: string }} options
|
|
36
|
+
* @returns {{ baseUrl: string, region: string, source: string }}
|
|
37
|
+
*/
|
|
38
|
+
export function resolveBaseUrl({ baseUrlFlag, apiKey } = {}) {
|
|
39
|
+
// 1. Explicit base URL flag or env var
|
|
40
|
+
if (baseUrlFlag) {
|
|
41
|
+
return { baseUrl: baseUrlFlag.replace(/\/+$/, ""), region: "custom", source: "flag" };
|
|
42
|
+
}
|
|
43
|
+
if (process.env.QVERIS_BASE_URL) {
|
|
44
|
+
return { baseUrl: process.env.QVERIS_BASE_URL.replace(/\/+$/, ""), region: "custom", source: "env (QVERIS_BASE_URL)" };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// 2. Explicit region env var
|
|
48
|
+
if (process.env.QVERIS_REGION) {
|
|
49
|
+
const region = process.env.QVERIS_REGION.toLowerCase();
|
|
50
|
+
const url = REGION_URLS[region] || REGION_URLS.global;
|
|
51
|
+
return { baseUrl: url, region, source: "env (QVERIS_REGION)" };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// 3. Auto-detect from API key prefix
|
|
55
|
+
if (apiKey) {
|
|
56
|
+
const region = detectRegionFromKey(apiKey);
|
|
57
|
+
return { baseUrl: REGION_URLS[region], region, source: "auto (key prefix)" };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// 4. Default
|
|
61
|
+
return { baseUrl: REGION_URLS.global, region: "global", source: "default" };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export { REGION_URLS };
|