@hilbras/omnihilbras 0.1.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.
Files changed (54) hide show
  1. package/README.md +57 -0
  2. package/dist/adapters/anthropic.d.ts +38 -0
  3. package/dist/adapters/anthropic.d.ts.map +1 -0
  4. package/dist/adapters/anthropic.js +298 -0
  5. package/dist/adapters/anthropic.js.map +1 -0
  6. package/dist/adapters/gemini.d.ts +35 -0
  7. package/dist/adapters/gemini.d.ts.map +1 -0
  8. package/dist/adapters/gemini.js +322 -0
  9. package/dist/adapters/gemini.js.map +1 -0
  10. package/dist/adapters/openai-compatible.d.ts +52 -0
  11. package/dist/adapters/openai-compatible.d.ts.map +1 -0
  12. package/dist/adapters/openai-compatible.js +246 -0
  13. package/dist/adapters/openai-compatible.js.map +1 -0
  14. package/dist/adapters/openai.d.ts +10 -0
  15. package/dist/adapters/openai.d.ts.map +1 -0
  16. package/dist/adapters/openai.js +17 -0
  17. package/dist/adapters/openai.js.map +1 -0
  18. package/dist/adapters/openrouter.d.ts +32 -0
  19. package/dist/adapters/openrouter.d.ts.map +1 -0
  20. package/dist/adapters/openrouter.js +171 -0
  21. package/dist/adapters/openrouter.js.map +1 -0
  22. package/dist/errors.d.ts +28 -0
  23. package/dist/errors.d.ts.map +1 -0
  24. package/dist/errors.js +60 -0
  25. package/dist/errors.js.map +1 -0
  26. package/dist/index.d.ts +13 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +13 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/registry.d.ts +12 -0
  31. package/dist/registry.d.ts.map +1 -0
  32. package/dist/registry.js +45 -0
  33. package/dist/registry.js.map +1 -0
  34. package/dist/secret-store.d.ts +12 -0
  35. package/dist/secret-store.d.ts.map +1 -0
  36. package/dist/secret-store.js +18 -0
  37. package/dist/secret-store.js.map +1 -0
  38. package/dist/streaming.d.ts +11 -0
  39. package/dist/streaming.d.ts.map +1 -0
  40. package/dist/streaming.js +87 -0
  41. package/dist/streaming.js.map +1 -0
  42. package/dist/transport.d.ts +44 -0
  43. package/dist/transport.d.ts.map +1 -0
  44. package/dist/transport.js +239 -0
  45. package/dist/transport.js.map +1 -0
  46. package/dist/types.d.ts +132 -0
  47. package/dist/types.d.ts.map +1 -0
  48. package/dist/types.js +2 -0
  49. package/dist/types.js.map +1 -0
  50. package/dist/url.d.ts +12 -0
  51. package/dist/url.d.ts.map +1 -0
  52. package/dist/url.js +104 -0
  53. package/dist/url.js.map +1 -0
  54. package/package.json +57 -0
package/dist/url.js ADDED
@@ -0,0 +1,104 @@
1
+ import { ProviderError } from './errors.js';
2
+ export function normalizeProviderBaseUrl(value, providerId) {
3
+ try {
4
+ const url = new URL(value);
5
+ if (url.search || url.hash)
6
+ throw new Error('URL query and fragment are not allowed');
7
+ assertSafeProviderRequestUrl(url.toString(), providerId);
8
+ return url.toString().replace(/\/$/, '');
9
+ }
10
+ catch (error) {
11
+ throw new ProviderError('CONFIGURATION_ERROR', `Invalid base URL for provider ${providerId}.`, { providerId, cause: error });
12
+ }
13
+ }
14
+ export function assertSafeProviderRequestUrl(value, providerId) {
15
+ try {
16
+ const url = new URL(value);
17
+ if (url.username || url.password)
18
+ throw new Error('URL userinfo is not allowed');
19
+ if (url.protocol !== 'https:' && !(url.protocol === 'http:' && isLoopbackHostname(url.hostname))) {
20
+ throw new Error('Remote provider URLs must use HTTPS');
21
+ }
22
+ if (url.protocol === 'https:' && isPrivateHostname(url.hostname))
23
+ throw new Error('Private provider destinations are not allowed.');
24
+ return url.toString();
25
+ }
26
+ catch (error) {
27
+ throw new ProviderError('CONFIGURATION_ERROR', `Invalid provider URL for ${providerId}.`, { providerId, cause: error });
28
+ }
29
+ }
30
+ export function resolveProviderUrl(baseUrl, path, providerId) {
31
+ const normalizedPath = path.trim();
32
+ if (!normalizedPath || /^[a-z][a-z\d+.-]*:/i.test(normalizedPath) || normalizedPath.startsWith('//') || normalizedPath.includes('\\')) {
33
+ throw new ProviderError('CONFIGURATION_ERROR', `Invalid provider path for ${providerId}.`, { providerId });
34
+ }
35
+ assertSafeProviderRequestUrl(baseUrl, providerId);
36
+ const base = new URL(`${baseUrl}/`);
37
+ if (base.search || base.hash)
38
+ throw new ProviderError('CONFIGURATION_ERROR', `Provider base URL cannot contain a query or fragment for ${providerId}.`, { providerId });
39
+ const resolved = new URL(normalizedPath.replace(/^\/+/, ''), base);
40
+ const basePath = base.pathname.replace(/\/$/, '');
41
+ if (resolved.origin !== base.origin || (basePath && resolved.pathname !== basePath && !resolved.pathname.startsWith(`${basePath}/`))) {
42
+ throw new ProviderError('CONFIGURATION_ERROR', `Provider path escaped the configured base URL for ${providerId}.`, { providerId });
43
+ }
44
+ return resolved.toString();
45
+ }
46
+ const credentialHeaderNames = new Set(['authorization', 'proxy-authorization', 'cookie', 'set-cookie', 'x-api-key', 'x-goog-api-key']);
47
+ const transportHeaderNames = new Set(['host', 'content-length', 'connection', 'transfer-encoding', 'upgrade', 'te', 'trailer']);
48
+ export function assertSafeProviderHeaderName(name, providerId, options = {}) {
49
+ const normalized = name.toLowerCase();
50
+ if (!/^[!#$%&'*+\-.^_`|~0-9a-z]+$/i.test(name) || transportHeaderNames.has(normalized) || (!options.allowCredential && credentialHeaderNames.has(normalized))) {
51
+ throw new ProviderError('CONFIGURATION_ERROR', `Header ${name} is not allowed for provider ${providerId}.`, { providerId });
52
+ }
53
+ }
54
+ export function assertSafeProviderHeaderValue(name, value, providerId) {
55
+ if (/[\r\n\0]/.test(value)) {
56
+ throw new ProviderError('CONFIGURATION_ERROR', `Header ${name} contains an unsafe value for provider ${providerId}.`, { providerId });
57
+ }
58
+ }
59
+ export function sanitizeProviderHeaders(headers, providerId) {
60
+ const safe = {};
61
+ for (const [name, value] of Object.entries(headers ?? {})) {
62
+ assertSafeProviderHeaderName(name, providerId);
63
+ assertSafeProviderHeaderValue(name, value, providerId);
64
+ safe[name] = value;
65
+ }
66
+ return safe;
67
+ }
68
+ export function isPrivateHostname(hostname) {
69
+ const normalized = hostname.trim().toLowerCase().replace(/^\[|\]$/g, '');
70
+ if (normalized === 'localhost' || normalized.endsWith('.local') || normalized.endsWith('.internal'))
71
+ return true;
72
+ if (isStrictIpv4(normalized)) {
73
+ const parts = normalized.split('.').map(Number);
74
+ const first = parts[0] ?? -1;
75
+ const second = parts[1] ?? -1;
76
+ return first === 0 || first === 10 || first === 127 || (first === 172 && second >= 16 && second <= 31) || (first === 192 && second === 168) || (first === 169 && second === 254) || (first === 100 && second >= 64 && second <= 127);
77
+ }
78
+ if (!normalized.includes(':'))
79
+ return false;
80
+ return normalized === '::1' || normalized.startsWith('fc') || normalized.startsWith('fd') || normalized.startsWith('fe8') || normalized.startsWith('fe9') || normalized.startsWith('fea') || normalized.startsWith('feb');
81
+ }
82
+ export function isLoopbackHostname(hostname) {
83
+ const normalized = hostname.trim().toLowerCase().replace(/^\[|\]$/g, '');
84
+ if (normalized === 'localhost')
85
+ return true;
86
+ if (isStrictIpv4(normalized))
87
+ return normalized.split('.')[0] === '127';
88
+ return normalized === '::1' || normalized === '0:0:0:0:0:0:0:1';
89
+ }
90
+ export function canonicalLoopbackHost(hostname) {
91
+ const normalized = hostname.trim().toLowerCase().replace(/^\[|\]$/g, '');
92
+ if (normalized === 'localhost')
93
+ return '127.0.0.1';
94
+ if (isStrictIpv4(normalized) && normalized.split('.')[0] === '127')
95
+ return normalized;
96
+ if (normalized === '::1' || normalized === '0:0:0:0:0:0:0:1')
97
+ return '::1';
98
+ throw new Error('Host must be a loopback address.');
99
+ }
100
+ function isStrictIpv4(value) {
101
+ const parts = value.split('.');
102
+ return parts.length === 4 && parts.every((part) => /^(0|[1-9]\d{0,2})$/.test(part) && Number(part) <= 255);
103
+ }
104
+ //# sourceMappingURL=url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.js","sourceRoot":"","sources":["../src/url.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@hilbras/omnihilbras",
3
+ "version": "0.1.0",
4
+ "description": "Typed provider SDK for the OmniHilbras gateway: normalized chat, streaming, model listing, and capability contracts for OpenAI, Anthropic, Gemini, and OpenAI-compatible providers.",
5
+ "license": "MIT",
6
+ "author": "Hilbras",
7
+ "homepage": "https://github.com/Hilbras/OmniHilbras#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/Hilbras/OmniHilbras.git",
11
+ "directory": "packages/omnihilbras-sdk"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/Hilbras/OmniHilbras/issues"
15
+ },
16
+ "keywords": [
17
+ "omnihilbras",
18
+ "ai-gateway",
19
+ "llm",
20
+ "openai",
21
+ "anthropic",
22
+ "gemini",
23
+ "openrouter",
24
+ "provider-abstraction",
25
+ "streaming"
26
+ ],
27
+ "type": "module",
28
+ "main": "./dist/index.js",
29
+ "types": "./dist/index.d.ts",
30
+ "exports": {
31
+ ".": {
32
+ "types": "./dist/index.d.ts",
33
+ "import": "./dist/index.js"
34
+ }
35
+ },
36
+ "files": [
37
+ "dist",
38
+ "README.md"
39
+ ],
40
+ "engines": {
41
+ "node": ">=20"
42
+ },
43
+ "publishConfig": {
44
+ "access": "public"
45
+ },
46
+ "sideEffects": false,
47
+ "scripts": {
48
+ "build": "tsc -p tsconfig.json",
49
+ "typecheck": "tsc -p tsconfig.json --noEmit",
50
+ "test": "pnpm build && node --test test/*.test.js",
51
+ "prepublishOnly": "pnpm build"
52
+ },
53
+ "devDependencies": {
54
+ "@types/node": "^26.6.2",
55
+ "typescript": "^5.9.0"
56
+ }
57
+ }