vexi-cli 0.9.0 → 0.9.1
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/providers/detect.js
CHANGED
|
@@ -38,11 +38,19 @@ export const PROVIDER_PATTERNS = [
|
|
|
38
38
|
// they always fall back to the interactive provider-selection list.
|
|
39
39
|
];
|
|
40
40
|
/**
|
|
41
|
-
* Sanitize a pasted API key:
|
|
42
|
-
*
|
|
41
|
+
* Sanitize a pasted API key: strip characters that can't be sent in an HTTP
|
|
42
|
+
* header, trim whitespace/newlines, and strip surrounding quotes.
|
|
43
|
+
*
|
|
44
|
+
* API keys are always printable ASCII, but pasting one — especially on an
|
|
45
|
+
* RTL/multilingual system — can silently pull in invisible bidi marks
|
|
46
|
+
* (U+200E/U+200F), a non-breaking space, smart quotes, or a stray newline.
|
|
47
|
+
* `fetch()` then rejects the Authorization header with a cryptic
|
|
48
|
+
* "character … has a value greater than 255" error on *every* request. We
|
|
49
|
+
* drop anything outside printable ASCII up front so that never happens.
|
|
43
50
|
*/
|
|
44
51
|
export function sanitizeKey(raw) {
|
|
45
|
-
|
|
52
|
+
// Keep only space + printable ASCII (0x20–0x7E); trim() handles edge spaces.
|
|
53
|
+
let key = raw.replace(/[^\x20-\x7E]/g, '').trim();
|
|
46
54
|
// Strip matching surrounding quotes ("key", 'key', `key`)
|
|
47
55
|
while (key.length >= 2 && `"'\``.includes(key[0]) && key[0] === key[key.length - 1]) {
|
|
48
56
|
key = key.slice(1, -1).trim();
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { sanitizeKey, detectProvider } from './detect.js';
|
|
3
|
+
describe('sanitizeKey', () => {
|
|
4
|
+
it('trims surrounding whitespace and quotes', () => {
|
|
5
|
+
expect(sanitizeKey(' gsk_abc123 ')).toBe('gsk_abc123');
|
|
6
|
+
expect(sanitizeKey('"gsk_abc123"')).toBe('gsk_abc123');
|
|
7
|
+
expect(sanitizeKey("'gsk_abc123'")).toBe('gsk_abc123');
|
|
8
|
+
});
|
|
9
|
+
it('strips invisible bidi marks pasted on RTL systems', () => {
|
|
10
|
+
// U+200F RIGHT-TO-LEFT MARK embedded around the key — the exact class of
|
|
11
|
+
// char that makes fetch() throw "value greater than 255" on the header.
|
|
12
|
+
expect(sanitizeKey('gsk_abc123')).toBe('gsk_abc123');
|
|
13
|
+
expect(sanitizeKey('gsk_abc123')).toBe('gsk_abc123');
|
|
14
|
+
});
|
|
15
|
+
it('strips non-breaking spaces, newlines, and smart quotes', () => {
|
|
16
|
+
expect(sanitizeKey('gsk_abc 123')).toBe('gsk_abc123');
|
|
17
|
+
expect(sanitizeKey('gsk_abc123\n')).toBe('gsk_abc123');
|
|
18
|
+
expect(sanitizeKey('“gsk_abc123”')).toBe('gsk_abc123');
|
|
19
|
+
});
|
|
20
|
+
it('produces a header-safe (all printable ASCII) result', () => {
|
|
21
|
+
const cleaned = sanitizeKey('gsk_ab c123');
|
|
22
|
+
expect([...cleaned].every((ch) => ch.charCodeAt(0) >= 0x21 && ch.charCodeAt(0) <= 0x7e)).toBe(true);
|
|
23
|
+
});
|
|
24
|
+
it('leaves a clean key untouched and still auto-detects the provider', () => {
|
|
25
|
+
const key = sanitizeKey('gsk_1234567890');
|
|
26
|
+
expect(key).toBe('gsk_1234567890');
|
|
27
|
+
expect(detectProvider(key)).toBe('groq');
|
|
28
|
+
});
|
|
29
|
+
});
|