@zeke-02/tinfoil 0.0.2 → 0.0.3
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/ai-sdk-provider.js +8 -3
- package/dist/config.d.ts +4 -8
- package/dist/config.js +4 -8
- package/dist/encrypted-body-fetch.d.ts +3 -2
- package/dist/encrypted-body-fetch.js +31 -16
- package/dist/esm/ai-sdk-provider.js +8 -3
- package/dist/esm/config.d.ts +4 -8
- package/dist/esm/config.js +4 -8
- package/dist/esm/encrypted-body-fetch.d.ts +3 -2
- package/dist/esm/encrypted-body-fetch.js +31 -16
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/router.d.ts +11 -0
- package/dist/esm/router.js +33 -0
- package/dist/esm/secure-client.d.ts +3 -2
- package/dist/esm/secure-client.js +33 -2
- package/dist/esm/tinfoilai.js +5 -3
- package/dist/esm/unverified-client.d.ts +2 -2
- package/dist/esm/unverified-client.js +30 -2
- package/dist/esm/verifier.d.ts +1 -1
- package/dist/esm/verifier.js +7 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -1
- package/dist/router.d.ts +11 -0
- package/dist/router.js +36 -0
- package/dist/secure-client.d.ts +3 -2
- package/dist/secure-client.js +33 -2
- package/dist/tinfoilai.js +5 -3
- package/dist/unverified-client.d.ts +2 -2
- package/dist/unverified-client.js +30 -2
- package/dist/verifier.d.ts +1 -1
- package/dist/verifier.js +7 -4
- package/package.json +1 -1
package/dist/ai-sdk-provider.js
CHANGED
|
@@ -5,8 +5,8 @@ const openai_compatible_1 = require("@ai-sdk/openai-compatible");
|
|
|
5
5
|
const config_1 = require("./config");
|
|
6
6
|
const secure_client_1 = require("./secure-client");
|
|
7
7
|
async function createTinfoilAI(apiKey, options = {}) {
|
|
8
|
-
const baseURL = options.baseURL
|
|
9
|
-
const enclaveURL = options.enclaveURL
|
|
8
|
+
const baseURL = options.baseURL;
|
|
9
|
+
const enclaveURL = options.enclaveURL;
|
|
10
10
|
const configRepo = options.configRepo || config_1.TINFOIL_CONFIG.INFERENCE_PROXY_REPO;
|
|
11
11
|
const secureClient = new secure_client_1.SecureClient({
|
|
12
12
|
baseURL,
|
|
@@ -14,9 +14,14 @@ async function createTinfoilAI(apiKey, options = {}) {
|
|
|
14
14
|
configRepo,
|
|
15
15
|
});
|
|
16
16
|
await secureClient.ready();
|
|
17
|
+
// Get the baseURL from SecureClient after initialization
|
|
18
|
+
const finalBaseURL = baseURL || secureClient.getBaseURL();
|
|
19
|
+
if (!finalBaseURL) {
|
|
20
|
+
throw new Error("Unable to determine baseURL for AI SDK provider");
|
|
21
|
+
}
|
|
17
22
|
return (0, openai_compatible_1.createOpenAICompatible)({
|
|
18
23
|
name: "tinfoil",
|
|
19
|
-
baseURL:
|
|
24
|
+
baseURL: finalBaseURL,
|
|
20
25
|
apiKey: apiKey,
|
|
21
26
|
fetch: secureClient.fetch,
|
|
22
27
|
});
|
package/dist/config.d.ts
CHANGED
|
@@ -2,16 +2,12 @@
|
|
|
2
2
|
* Configuration constants for the Tinfoil Node SDK
|
|
3
3
|
*/
|
|
4
4
|
export declare const TINFOIL_CONFIG: {
|
|
5
|
-
/**
|
|
6
|
-
* The base URL for the Tinfoil router API
|
|
7
|
-
*/
|
|
8
|
-
readonly INFERENCE_BASE_URL: "https://router.inf6.tinfoil.sh/v1/";
|
|
9
|
-
/**
|
|
10
|
-
* The URL for enclave key discovery and attestation endpoints
|
|
11
|
-
*/
|
|
12
|
-
readonly ENCLAVE_URL: "https://router.inf6.tinfoil.sh";
|
|
13
5
|
/**
|
|
14
6
|
* The GitHub repository for code attestation verification
|
|
15
7
|
*/
|
|
16
8
|
readonly INFERENCE_PROXY_REPO: "tinfoilsh/confidential-model-router";
|
|
9
|
+
/**
|
|
10
|
+
* The ATC (Attestation and Trust Center) API URL for fetching available routers
|
|
11
|
+
*/
|
|
12
|
+
readonly ATC_API_URL: "https://atc.tinfoil.sh/routers";
|
|
17
13
|
};
|
package/dist/config.js
CHANGED
|
@@ -5,16 +5,12 @@ exports.TINFOIL_CONFIG = void 0;
|
|
|
5
5
|
* Configuration constants for the Tinfoil Node SDK
|
|
6
6
|
*/
|
|
7
7
|
exports.TINFOIL_CONFIG = {
|
|
8
|
-
/**
|
|
9
|
-
* The base URL for the Tinfoil router API
|
|
10
|
-
*/
|
|
11
|
-
INFERENCE_BASE_URL: "https://router.inf6.tinfoil.sh/v1/",
|
|
12
|
-
/**
|
|
13
|
-
* The URL for enclave key discovery and attestation endpoints
|
|
14
|
-
*/
|
|
15
|
-
ENCLAVE_URL: "https://router.inf6.tinfoil.sh",
|
|
16
8
|
/**
|
|
17
9
|
* The GitHub repository for code attestation verification
|
|
18
10
|
*/
|
|
19
11
|
INFERENCE_PROXY_REPO: "tinfoilsh/confidential-model-router",
|
|
12
|
+
/**
|
|
13
|
+
* The ATC (Attestation and Trust Center) API URL for fetching available routers
|
|
14
|
+
*/
|
|
15
|
+
ATC_API_URL: "https://atc.tinfoil.sh/routers",
|
|
20
16
|
};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import type { Transport as EhbpTransport } from "@zeke-02/ehbp";
|
|
1
2
|
export declare function getHPKEKey(enclaveURL: string): Promise<CryptoKey>;
|
|
2
3
|
export declare function normalizeEncryptedBodyRequestArgs(input: RequestInfo | URL, init?: RequestInit): {
|
|
3
4
|
url: string;
|
|
4
5
|
init?: RequestInit;
|
|
5
6
|
};
|
|
6
|
-
export declare function encryptedBodyRequest(input: RequestInfo | URL, hpkePublicKey?: string, init?: RequestInit, enclaveURL?: string): Promise<Response>;
|
|
7
|
+
export declare function encryptedBodyRequest(input: RequestInfo | URL, hpkePublicKey?: string, init?: RequestInit, enclaveURL?: string, transportInstance?: EhbpTransport): Promise<Response>;
|
|
7
8
|
export declare function createEncryptedBodyFetch(baseURL: string, hpkePublicKey?: string, enclaveURL?: string): typeof fetch;
|
|
8
|
-
export declare function
|
|
9
|
+
export declare function getTransportForOrigin(origin: string, keyOrigin: string): Promise<EhbpTransport>;
|
|
@@ -4,12 +4,12 @@ exports.getHPKEKey = getHPKEKey;
|
|
|
4
4
|
exports.normalizeEncryptedBodyRequestArgs = normalizeEncryptedBodyRequestArgs;
|
|
5
5
|
exports.encryptedBodyRequest = encryptedBodyRequest;
|
|
6
6
|
exports.createEncryptedBodyFetch = createEncryptedBodyFetch;
|
|
7
|
-
exports.
|
|
7
|
+
exports.getTransportForOrigin = getTransportForOrigin;
|
|
8
8
|
const ehbp_1 = require("@zeke-02/ehbp");
|
|
9
9
|
const fetch_adapter_1 = require("./fetch-adapter");
|
|
10
|
-
let transport = null;
|
|
11
10
|
// Public API
|
|
12
11
|
async function getHPKEKey(enclaveURL) {
|
|
12
|
+
const url = new URL(enclaveURL);
|
|
13
13
|
const keysURL = new URL(ehbp_1.PROTOCOL.KEYS_PATH, enclaveURL);
|
|
14
14
|
if (keysURL.protocol !== "https:") {
|
|
15
15
|
throw new Error(`HTTPS is required for remote key retrieval. Invalid protocol: ${keysURL.protocol}`);
|
|
@@ -47,34 +47,49 @@ function normalizeEncryptedBodyRequestArgs(input, init) {
|
|
|
47
47
|
init: { ...derivedInit, ...init },
|
|
48
48
|
};
|
|
49
49
|
}
|
|
50
|
-
async function encryptedBodyRequest(input, hpkePublicKey, init, enclaveURL) {
|
|
50
|
+
async function encryptedBodyRequest(input, hpkePublicKey, init, enclaveURL, transportInstance) {
|
|
51
51
|
const { url: requestUrl, init: requestInit } = normalizeEncryptedBodyRequestArgs(input, init);
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
52
|
+
let actualTransport;
|
|
53
|
+
if (transportInstance) {
|
|
54
|
+
// Use provided transport instance
|
|
55
|
+
actualTransport = transportInstance;
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
// Create a new transport for this request
|
|
59
|
+
const u = new URL(requestUrl);
|
|
60
|
+
const { origin } = u;
|
|
61
|
+
const keyOrigin = enclaveURL ? new URL(enclaveURL).origin : origin;
|
|
62
|
+
actualTransport = await getTransportForOrigin(origin, keyOrigin);
|
|
57
63
|
}
|
|
58
|
-
const transportInstance = await transport;
|
|
59
64
|
if (hpkePublicKey) {
|
|
60
|
-
const transportKeyHash = await
|
|
65
|
+
const transportKeyHash = await actualTransport.getServerPublicKeyHex();
|
|
61
66
|
if (transportKeyHash !== hpkePublicKey) {
|
|
62
|
-
transport = null;
|
|
63
67
|
throw new Error(`HPKE public key mismatch. Expected: ${hpkePublicKey}, Got: ${transportKeyHash}`);
|
|
64
68
|
}
|
|
65
69
|
}
|
|
66
|
-
return
|
|
70
|
+
return actualTransport.request(requestUrl, requestInit);
|
|
67
71
|
}
|
|
68
72
|
function createEncryptedBodyFetch(baseURL, hpkePublicKey, enclaveURL) {
|
|
73
|
+
// Create a dedicated transport instance for this fetch function
|
|
74
|
+
let transportPromise = null;
|
|
75
|
+
const getOrCreateTransport = async () => {
|
|
76
|
+
if (!transportPromise) {
|
|
77
|
+
const baseUrl = new URL(baseURL);
|
|
78
|
+
const keyOrigin = enclaveURL
|
|
79
|
+
? new URL(enclaveURL).origin
|
|
80
|
+
: baseUrl.origin;
|
|
81
|
+
transportPromise = getTransportForOrigin(baseUrl.origin, keyOrigin);
|
|
82
|
+
}
|
|
83
|
+
return transportPromise;
|
|
84
|
+
};
|
|
69
85
|
return (async (input, init) => {
|
|
70
86
|
const normalized = normalizeEncryptedBodyRequestArgs(input, init);
|
|
71
87
|
const targetUrl = new URL(normalized.url, baseURL);
|
|
72
|
-
|
|
88
|
+
// Get the dedicated transport instance for this fetch function
|
|
89
|
+
const transportInstance = await getOrCreateTransport();
|
|
90
|
+
return encryptedBodyRequest(targetUrl.toString(), hpkePublicKey, normalized.init, enclaveURL, transportInstance);
|
|
73
91
|
});
|
|
74
92
|
}
|
|
75
|
-
function resetTransport() {
|
|
76
|
-
transport = null;
|
|
77
|
-
}
|
|
78
93
|
async function getTransportForOrigin(origin, keyOrigin) {
|
|
79
94
|
if (typeof globalThis !== "undefined") {
|
|
80
95
|
const isSecure = globalThis.isSecureContext !== false;
|
|
@@ -2,8 +2,8 @@ import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
|
|
|
2
2
|
import { TINFOIL_CONFIG } from "./config";
|
|
3
3
|
import { SecureClient } from "./secure-client";
|
|
4
4
|
export async function createTinfoilAI(apiKey, options = {}) {
|
|
5
|
-
const baseURL = options.baseURL
|
|
6
|
-
const enclaveURL = options.enclaveURL
|
|
5
|
+
const baseURL = options.baseURL;
|
|
6
|
+
const enclaveURL = options.enclaveURL;
|
|
7
7
|
const configRepo = options.configRepo || TINFOIL_CONFIG.INFERENCE_PROXY_REPO;
|
|
8
8
|
const secureClient = new SecureClient({
|
|
9
9
|
baseURL,
|
|
@@ -11,9 +11,14 @@ export async function createTinfoilAI(apiKey, options = {}) {
|
|
|
11
11
|
configRepo,
|
|
12
12
|
});
|
|
13
13
|
await secureClient.ready();
|
|
14
|
+
// Get the baseURL from SecureClient after initialization
|
|
15
|
+
const finalBaseURL = baseURL || secureClient.getBaseURL();
|
|
16
|
+
if (!finalBaseURL) {
|
|
17
|
+
throw new Error("Unable to determine baseURL for AI SDK provider");
|
|
18
|
+
}
|
|
14
19
|
return createOpenAICompatible({
|
|
15
20
|
name: "tinfoil",
|
|
16
|
-
baseURL:
|
|
21
|
+
baseURL: finalBaseURL,
|
|
17
22
|
apiKey: apiKey,
|
|
18
23
|
fetch: secureClient.fetch,
|
|
19
24
|
});
|
package/dist/esm/config.d.ts
CHANGED
|
@@ -2,16 +2,12 @@
|
|
|
2
2
|
* Configuration constants for the Tinfoil Node SDK
|
|
3
3
|
*/
|
|
4
4
|
export declare const TINFOIL_CONFIG: {
|
|
5
|
-
/**
|
|
6
|
-
* The base URL for the Tinfoil router API
|
|
7
|
-
*/
|
|
8
|
-
readonly INFERENCE_BASE_URL: "https://router.inf6.tinfoil.sh/v1/";
|
|
9
|
-
/**
|
|
10
|
-
* The URL for enclave key discovery and attestation endpoints
|
|
11
|
-
*/
|
|
12
|
-
readonly ENCLAVE_URL: "https://router.inf6.tinfoil.sh";
|
|
13
5
|
/**
|
|
14
6
|
* The GitHub repository for code attestation verification
|
|
15
7
|
*/
|
|
16
8
|
readonly INFERENCE_PROXY_REPO: "tinfoilsh/confidential-model-router";
|
|
9
|
+
/**
|
|
10
|
+
* The ATC (Attestation and Trust Center) API URL for fetching available routers
|
|
11
|
+
*/
|
|
12
|
+
readonly ATC_API_URL: "https://atc.tinfoil.sh/routers";
|
|
17
13
|
};
|
package/dist/esm/config.js
CHANGED
|
@@ -2,16 +2,12 @@
|
|
|
2
2
|
* Configuration constants for the Tinfoil Node SDK
|
|
3
3
|
*/
|
|
4
4
|
export const TINFOIL_CONFIG = {
|
|
5
|
-
/**
|
|
6
|
-
* The base URL for the Tinfoil router API
|
|
7
|
-
*/
|
|
8
|
-
INFERENCE_BASE_URL: "https://router.inf6.tinfoil.sh/v1/",
|
|
9
|
-
/**
|
|
10
|
-
* The URL for enclave key discovery and attestation endpoints
|
|
11
|
-
*/
|
|
12
|
-
ENCLAVE_URL: "https://router.inf6.tinfoil.sh",
|
|
13
5
|
/**
|
|
14
6
|
* The GitHub repository for code attestation verification
|
|
15
7
|
*/
|
|
16
8
|
INFERENCE_PROXY_REPO: "tinfoilsh/confidential-model-router",
|
|
9
|
+
/**
|
|
10
|
+
* The ATC (Attestation and Trust Center) API URL for fetching available routers
|
|
11
|
+
*/
|
|
12
|
+
ATC_API_URL: "https://atc.tinfoil.sh/routers",
|
|
17
13
|
};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import type { Transport as EhbpTransport } from "@zeke-02/ehbp";
|
|
1
2
|
export declare function getHPKEKey(enclaveURL: string): Promise<CryptoKey>;
|
|
2
3
|
export declare function normalizeEncryptedBodyRequestArgs(input: RequestInfo | URL, init?: RequestInit): {
|
|
3
4
|
url: string;
|
|
4
5
|
init?: RequestInit;
|
|
5
6
|
};
|
|
6
|
-
export declare function encryptedBodyRequest(input: RequestInfo | URL, hpkePublicKey?: string, init?: RequestInit, enclaveURL?: string): Promise<Response>;
|
|
7
|
+
export declare function encryptedBodyRequest(input: RequestInfo | URL, hpkePublicKey?: string, init?: RequestInit, enclaveURL?: string, transportInstance?: EhbpTransport): Promise<Response>;
|
|
7
8
|
export declare function createEncryptedBodyFetch(baseURL: string, hpkePublicKey?: string, enclaveURL?: string): typeof fetch;
|
|
8
|
-
export declare function
|
|
9
|
+
export declare function getTransportForOrigin(origin: string, keyOrigin: string): Promise<EhbpTransport>;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Identity, Transport, PROTOCOL } from "@zeke-02/ehbp";
|
|
2
2
|
import { getFetch } from "./fetch-adapter";
|
|
3
|
-
let transport = null;
|
|
4
3
|
// Public API
|
|
5
4
|
export async function getHPKEKey(enclaveURL) {
|
|
5
|
+
const url = new URL(enclaveURL);
|
|
6
6
|
const keysURL = new URL(PROTOCOL.KEYS_PATH, enclaveURL);
|
|
7
7
|
if (keysURL.protocol !== "https:") {
|
|
8
8
|
throw new Error(`HTTPS is required for remote key retrieval. Invalid protocol: ${keysURL.protocol}`);
|
|
@@ -40,35 +40,50 @@ export function normalizeEncryptedBodyRequestArgs(input, init) {
|
|
|
40
40
|
init: { ...derivedInit, ...init },
|
|
41
41
|
};
|
|
42
42
|
}
|
|
43
|
-
export async function encryptedBodyRequest(input, hpkePublicKey, init, enclaveURL) {
|
|
43
|
+
export async function encryptedBodyRequest(input, hpkePublicKey, init, enclaveURL, transportInstance) {
|
|
44
44
|
const { url: requestUrl, init: requestInit } = normalizeEncryptedBodyRequestArgs(input, init);
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
let actualTransport;
|
|
46
|
+
if (transportInstance) {
|
|
47
|
+
// Use provided transport instance
|
|
48
|
+
actualTransport = transportInstance;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
// Create a new transport for this request
|
|
52
|
+
const u = new URL(requestUrl);
|
|
53
|
+
const { origin } = u;
|
|
54
|
+
const keyOrigin = enclaveURL ? new URL(enclaveURL).origin : origin;
|
|
55
|
+
actualTransport = await getTransportForOrigin(origin, keyOrigin);
|
|
50
56
|
}
|
|
51
|
-
const transportInstance = await transport;
|
|
52
57
|
if (hpkePublicKey) {
|
|
53
|
-
const transportKeyHash = await
|
|
58
|
+
const transportKeyHash = await actualTransport.getServerPublicKeyHex();
|
|
54
59
|
if (transportKeyHash !== hpkePublicKey) {
|
|
55
|
-
transport = null;
|
|
56
60
|
throw new Error(`HPKE public key mismatch. Expected: ${hpkePublicKey}, Got: ${transportKeyHash}`);
|
|
57
61
|
}
|
|
58
62
|
}
|
|
59
|
-
return
|
|
63
|
+
return actualTransport.request(requestUrl, requestInit);
|
|
60
64
|
}
|
|
61
65
|
export function createEncryptedBodyFetch(baseURL, hpkePublicKey, enclaveURL) {
|
|
66
|
+
// Create a dedicated transport instance for this fetch function
|
|
67
|
+
let transportPromise = null;
|
|
68
|
+
const getOrCreateTransport = async () => {
|
|
69
|
+
if (!transportPromise) {
|
|
70
|
+
const baseUrl = new URL(baseURL);
|
|
71
|
+
const keyOrigin = enclaveURL
|
|
72
|
+
? new URL(enclaveURL).origin
|
|
73
|
+
: baseUrl.origin;
|
|
74
|
+
transportPromise = getTransportForOrigin(baseUrl.origin, keyOrigin);
|
|
75
|
+
}
|
|
76
|
+
return transportPromise;
|
|
77
|
+
};
|
|
62
78
|
return (async (input, init) => {
|
|
63
79
|
const normalized = normalizeEncryptedBodyRequestArgs(input, init);
|
|
64
80
|
const targetUrl = new URL(normalized.url, baseURL);
|
|
65
|
-
|
|
81
|
+
// Get the dedicated transport instance for this fetch function
|
|
82
|
+
const transportInstance = await getOrCreateTransport();
|
|
83
|
+
return encryptedBodyRequest(targetUrl.toString(), hpkePublicKey, normalized.init, enclaveURL, transportInstance);
|
|
66
84
|
});
|
|
67
85
|
}
|
|
68
|
-
export function
|
|
69
|
-
transport = null;
|
|
70
|
-
}
|
|
71
|
-
async function getTransportForOrigin(origin, keyOrigin) {
|
|
86
|
+
export async function getTransportForOrigin(origin, keyOrigin) {
|
|
72
87
|
if (typeof globalThis !== "undefined") {
|
|
73
88
|
const isSecure = globalThis.isSecureContext !== false;
|
|
74
89
|
const hasSubtle = !!(globalThis.crypto && globalThis.crypto.subtle);
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -5,4 +5,5 @@ export * from "./ai-sdk-provider";
|
|
|
5
5
|
export * from "./config";
|
|
6
6
|
export { SecureClient } from "./secure-client";
|
|
7
7
|
export { UnverifiedClient } from "./unverified-client";
|
|
8
|
+
export { fetchRouter } from "./router";
|
|
8
9
|
export { type Uploadable, toFile, APIPromise, PagePromise, OpenAIError, APIError, APIConnectionError, APIConnectionTimeoutError, APIUserAbortError, NotFoundError, ConflictError, RateLimitError, BadRequestError, AuthenticationError, InternalServerError, PermissionDeniedError, UnprocessableEntityError, } from "openai";
|
package/dist/esm/index.js
CHANGED
|
@@ -7,6 +7,7 @@ export * from "./ai-sdk-provider";
|
|
|
7
7
|
export * from "./config";
|
|
8
8
|
export { SecureClient } from "./secure-client";
|
|
9
9
|
export { UnverifiedClient } from "./unverified-client";
|
|
10
|
+
export { fetchRouter } from "./router";
|
|
10
11
|
// Re-export OpenAI utility types and classes that users might need
|
|
11
12
|
// Using public exports from the main OpenAI package instead of deep imports
|
|
12
13
|
export { toFile, APIPromise, PagePromise, OpenAIError, APIError, APIConnectionError, APIConnectionTimeoutError, APIUserAbortError, NotFoundError, ConflictError, RateLimitError, BadRequestError, AuthenticationError, InternalServerError, PermissionDeniedError, UnprocessableEntityError, } from "openai";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Router utilities for fetching available Tinfoil routers
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Fetches the list of available routers from the ATC API
|
|
6
|
+
* and returns a randomly selected address.
|
|
7
|
+
*
|
|
8
|
+
* @returns Promise<string> A randomly selected router address
|
|
9
|
+
* @throws Error if no routers are found or if the request fails
|
|
10
|
+
*/
|
|
11
|
+
export declare function fetchRouter(): Promise<string>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { TINFOIL_CONFIG } from "./config";
|
|
2
|
+
/**
|
|
3
|
+
* Router utilities for fetching available Tinfoil routers
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Fetches the list of available routers from the ATC API
|
|
7
|
+
* and returns a randomly selected address.
|
|
8
|
+
*
|
|
9
|
+
* @returns Promise<string> A randomly selected router address
|
|
10
|
+
* @throws Error if no routers are found or if the request fails
|
|
11
|
+
*/
|
|
12
|
+
export async function fetchRouter() {
|
|
13
|
+
const routersUrl = TINFOIL_CONFIG.ATC_API_URL;
|
|
14
|
+
try {
|
|
15
|
+
const response = await fetch(routersUrl);
|
|
16
|
+
if (!response.ok) {
|
|
17
|
+
throw new Error(`Failed to fetch routers: ${response.status} ${response.statusText}`);
|
|
18
|
+
}
|
|
19
|
+
const routers = await response.json();
|
|
20
|
+
if (!Array.isArray(routers) || routers.length === 0) {
|
|
21
|
+
throw new Error("No routers found in the response");
|
|
22
|
+
}
|
|
23
|
+
// Return a randomly selected router
|
|
24
|
+
const randomIndex = Math.floor(Math.random() * routers.length);
|
|
25
|
+
return routers[randomIndex];
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
if (error instanceof Error) {
|
|
29
|
+
throw new Error(`Failed to fetch router: ${error.message}`);
|
|
30
|
+
}
|
|
31
|
+
throw new Error("Failed to fetch router: Unknown error");
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -8,13 +8,14 @@ export declare class SecureClient {
|
|
|
8
8
|
private initPromise;
|
|
9
9
|
private verificationDocument;
|
|
10
10
|
private _fetch;
|
|
11
|
-
private
|
|
12
|
-
private
|
|
11
|
+
private baseURL?;
|
|
12
|
+
private enclaveURL?;
|
|
13
13
|
private readonly configRepo?;
|
|
14
14
|
constructor(options?: SecureClientOptions);
|
|
15
15
|
ready(): Promise<void>;
|
|
16
16
|
private initSecureClient;
|
|
17
17
|
getVerificationDocument(): Promise<VerificationDocument>;
|
|
18
|
+
getBaseURL(): string | undefined;
|
|
18
19
|
get fetch(): typeof fetch;
|
|
19
20
|
}
|
|
20
21
|
export {};
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { Verifier } from "./verifier";
|
|
2
2
|
import { TINFOIL_CONFIG } from "./config";
|
|
3
3
|
import { createSecureFetch } from "./secure-fetch";
|
|
4
|
+
import { fetchRouter } from "./router";
|
|
4
5
|
export class SecureClient {
|
|
5
6
|
constructor(options = {}) {
|
|
6
7
|
this.initPromise = null;
|
|
7
8
|
this.verificationDocument = null;
|
|
8
9
|
this._fetch = null;
|
|
9
|
-
this.baseURL = options.baseURL
|
|
10
|
-
this.enclaveURL = options.enclaveURL
|
|
10
|
+
this.baseURL = options.baseURL;
|
|
11
|
+
this.enclaveURL = options.enclaveURL;
|
|
11
12
|
this.configRepo = options.configRepo || TINFOIL_CONFIG.INFERENCE_PROXY_REPO;
|
|
12
13
|
}
|
|
13
14
|
async ready() {
|
|
@@ -17,6 +18,33 @@ export class SecureClient {
|
|
|
17
18
|
return this.initPromise;
|
|
18
19
|
}
|
|
19
20
|
async initSecureClient() {
|
|
21
|
+
// Only fetch router if neither baseURL nor enclaveURL is provided
|
|
22
|
+
if (!this.baseURL && !this.enclaveURL) {
|
|
23
|
+
const routerAddress = await fetchRouter();
|
|
24
|
+
this.enclaveURL = `https://${routerAddress}`;
|
|
25
|
+
this.baseURL = `https://${routerAddress}/v1/`;
|
|
26
|
+
}
|
|
27
|
+
// Ensure both baseURL and enclaveURL are initialized
|
|
28
|
+
if (!this.baseURL) {
|
|
29
|
+
if (this.enclaveURL) {
|
|
30
|
+
// If enclaveURL is provided but baseURL is not, derive baseURL from enclaveURL
|
|
31
|
+
const enclaveUrl = new URL(this.enclaveURL);
|
|
32
|
+
this.baseURL = `${enclaveUrl.origin}/v1/`;
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
throw new Error("Unable to determine baseURL: neither baseURL nor enclaveURL provided");
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (!this.enclaveURL) {
|
|
39
|
+
if (this.baseURL) {
|
|
40
|
+
// If baseURL is provided but enclaveURL is not, derive enclaveURL from baseURL
|
|
41
|
+
const baseUrl = new URL(this.baseURL);
|
|
42
|
+
this.enclaveURL = baseUrl.origin;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
throw new Error("Unable to determine enclaveURL: neither baseURL nor enclaveURL provided");
|
|
46
|
+
}
|
|
47
|
+
}
|
|
20
48
|
const verifier = new Verifier({
|
|
21
49
|
serverURL: this.enclaveURL,
|
|
22
50
|
configRepo: this.configRepo,
|
|
@@ -77,6 +105,9 @@ export class SecureClient {
|
|
|
77
105
|
}
|
|
78
106
|
return this.verificationDocument;
|
|
79
107
|
}
|
|
108
|
+
getBaseURL() {
|
|
109
|
+
return this.baseURL;
|
|
110
|
+
}
|
|
80
111
|
get fetch() {
|
|
81
112
|
return async (input, init) => {
|
|
82
113
|
await this.ready();
|
package/dist/esm/tinfoilai.js
CHANGED
|
@@ -36,8 +36,8 @@ export class TinfoilAI {
|
|
|
36
36
|
openAIOptions.apiKey = process.env.TINFOIL_API_KEY;
|
|
37
37
|
}
|
|
38
38
|
this.apiKey = openAIOptions.apiKey;
|
|
39
|
-
this.baseURL = options.baseURL
|
|
40
|
-
this.enclaveURL = options.enclaveURL
|
|
39
|
+
this.baseURL = options.baseURL;
|
|
40
|
+
this.enclaveURL = options.enclaveURL;
|
|
41
41
|
this.configRepo = options.configRepo || TINFOIL_CONFIG.INFERENCE_PROXY_REPO;
|
|
42
42
|
this.secureClient = new SecureClient({
|
|
43
43
|
baseURL: this.baseURL,
|
|
@@ -63,9 +63,11 @@ export class TinfoilAI {
|
|
|
63
63
|
if (!this.verificationDocument) {
|
|
64
64
|
throw new Error("Verification document not available after successful verification");
|
|
65
65
|
}
|
|
66
|
+
// Use the provided baseURL, or get it from SecureClient after initialization
|
|
67
|
+
const baseURL = this.baseURL || this.secureClient.getBaseURL();
|
|
66
68
|
const clientOptions = {
|
|
67
69
|
...options,
|
|
68
|
-
baseURL:
|
|
70
|
+
baseURL: baseURL,
|
|
69
71
|
fetch: this.secureClient.fetch,
|
|
70
72
|
};
|
|
71
73
|
if (isRealBrowser() || options.dangerouslyAllowBrowser === true) {
|
|
@@ -6,8 +6,8 @@ interface UnverifiedClientOptions {
|
|
|
6
6
|
export declare class UnverifiedClient {
|
|
7
7
|
private initPromise;
|
|
8
8
|
private _fetch;
|
|
9
|
-
private
|
|
10
|
-
private
|
|
9
|
+
private baseURL?;
|
|
10
|
+
private enclaveURL?;
|
|
11
11
|
private readonly configRepo;
|
|
12
12
|
constructor(options?: UnverifiedClientOptions);
|
|
13
13
|
ready(): Promise<void>;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { TINFOIL_CONFIG } from "./config";
|
|
2
2
|
import { createEncryptedBodyFetch } from "./encrypted-body-fetch";
|
|
3
|
+
import { fetchRouter } from "./router";
|
|
3
4
|
export class UnverifiedClient {
|
|
4
5
|
constructor(options = {}) {
|
|
5
6
|
this.initPromise = null;
|
|
6
7
|
this._fetch = null;
|
|
7
|
-
this.baseURL = options.baseURL
|
|
8
|
-
this.enclaveURL = options.enclaveURL
|
|
8
|
+
this.baseURL = options.baseURL;
|
|
9
|
+
this.enclaveURL = options.enclaveURL;
|
|
9
10
|
this.configRepo = options.configRepo || TINFOIL_CONFIG.INFERENCE_PROXY_REPO;
|
|
10
11
|
}
|
|
11
12
|
async ready() {
|
|
@@ -15,6 +16,33 @@ export class UnverifiedClient {
|
|
|
15
16
|
return this.initPromise;
|
|
16
17
|
}
|
|
17
18
|
async initUnverifiedClient() {
|
|
19
|
+
// Only fetch router if neither baseURL nor enclaveURL is provided
|
|
20
|
+
if (!this.baseURL && !this.enclaveURL) {
|
|
21
|
+
const routerAddress = await fetchRouter();
|
|
22
|
+
this.enclaveURL = `https://${routerAddress}`;
|
|
23
|
+
this.baseURL = `https://${routerAddress}/v1/`;
|
|
24
|
+
}
|
|
25
|
+
// Ensure both baseURL and enclaveURL are initialized
|
|
26
|
+
if (!this.baseURL) {
|
|
27
|
+
if (this.enclaveURL) {
|
|
28
|
+
// If enclaveURL is provided but baseURL is not, derive baseURL from enclaveURL
|
|
29
|
+
const enclaveUrl = new URL(this.enclaveURL);
|
|
30
|
+
this.baseURL = `${enclaveUrl.origin}/v1/`;
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
throw new Error("Unable to determine baseURL: neither baseURL nor enclaveURL provided");
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (!this.enclaveURL) {
|
|
37
|
+
if (this.baseURL) {
|
|
38
|
+
// If baseURL is provided but enclaveURL is not, derive enclaveURL from baseURL
|
|
39
|
+
const baseUrl = new URL(this.baseURL);
|
|
40
|
+
this.enclaveURL = baseUrl.origin;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
throw new Error("Unable to determine enclaveURL: neither baseURL nor enclaveURL provided");
|
|
44
|
+
}
|
|
45
|
+
}
|
|
18
46
|
this._fetch = createEncryptedBodyFetch(this.baseURL, undefined, this.enclaveURL);
|
|
19
47
|
}
|
|
20
48
|
async getVerificationDocument() {
|
package/dist/esm/verifier.d.ts
CHANGED
|
@@ -87,7 +87,7 @@ export declare class Verifier {
|
|
|
87
87
|
private static executeWithWasm;
|
|
88
88
|
/**
|
|
89
89
|
* Fetch the latest release digest from GitHub
|
|
90
|
-
* @param configRepo - Repository name (e.g., "tinfoilsh/confidential-
|
|
90
|
+
* @param configRepo - Repository name (e.g., "tinfoilsh/confidential-model-router")
|
|
91
91
|
* @returns The digest hash
|
|
92
92
|
*/
|
|
93
93
|
fetchLatestDigest(configRepo?: string): Promise<string>;
|
package/dist/esm/verifier.js
CHANGED
|
@@ -112,7 +112,8 @@ function compareMeasurementsError(codeMeasurement, runtimeMeasurement) {
|
|
|
112
112
|
}
|
|
113
113
|
if (codeMeasurement.type === PLATFORM_TYPES.SNP_TDX_MULTI_PLATFORM_V1) {
|
|
114
114
|
switch (runtimeMeasurement.type) {
|
|
115
|
-
case PLATFORM_TYPES.TDX_GUEST_V1:
|
|
115
|
+
case PLATFORM_TYPES.TDX_GUEST_V1:
|
|
116
|
+
case PLATFORM_TYPES.TDX_GUEST_V2: {
|
|
116
117
|
if (codeMeasurement.registers.length < 3 ||
|
|
117
118
|
runtimeMeasurement.registers.length < 4) {
|
|
118
119
|
return new Error(MEASUREMENT_ERROR_MESSAGES.FEW_REGISTERS);
|
|
@@ -184,8 +185,10 @@ export function compareMeasurements(codeMeasurement, runtimeMeasurement) {
|
|
|
184
185
|
*/
|
|
185
186
|
export class Verifier {
|
|
186
187
|
constructor(options) {
|
|
187
|
-
|
|
188
|
-
|
|
188
|
+
if (!options?.serverURL) {
|
|
189
|
+
throw new Error("serverURL is required for Verifier");
|
|
190
|
+
}
|
|
191
|
+
this.serverURL = new URL(options.serverURL).hostname;
|
|
189
192
|
this.configRepo =
|
|
190
193
|
options?.configRepo ?? TINFOIL_CONFIG.INFERENCE_PROXY_REPO;
|
|
191
194
|
}
|
|
@@ -248,7 +251,7 @@ export class Verifier {
|
|
|
248
251
|
}
|
|
249
252
|
/**
|
|
250
253
|
* Fetch the latest release digest from GitHub
|
|
251
|
-
* @param configRepo - Repository name (e.g., "tinfoilsh/confidential-
|
|
254
|
+
* @param configRepo - Repository name (e.g., "tinfoilsh/confidential-model-router")
|
|
252
255
|
* @returns The digest hash
|
|
253
256
|
*/
|
|
254
257
|
async fetchLatestDigest(configRepo) {
|
package/dist/index.d.ts
CHANGED
|
@@ -5,4 +5,5 @@ export * from "./ai-sdk-provider";
|
|
|
5
5
|
export * from "./config";
|
|
6
6
|
export { SecureClient } from "./secure-client";
|
|
7
7
|
export { UnverifiedClient } from "./unverified-client";
|
|
8
|
+
export { fetchRouter } from "./router";
|
|
8
9
|
export { type Uploadable, toFile, APIPromise, PagePromise, OpenAIError, APIError, APIConnectionError, APIConnectionTimeoutError, APIUserAbortError, NotFoundError, ConflictError, RateLimitError, BadRequestError, AuthenticationError, InternalServerError, PermissionDeniedError, UnprocessableEntityError, } from "openai";
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.UnprocessableEntityError = exports.PermissionDeniedError = exports.InternalServerError = exports.AuthenticationError = exports.BadRequestError = exports.RateLimitError = exports.ConflictError = exports.NotFoundError = exports.APIUserAbortError = exports.APIConnectionTimeoutError = exports.APIConnectionError = exports.APIError = exports.OpenAIError = exports.PagePromise = exports.APIPromise = exports.toFile = exports.UnverifiedClient = exports.SecureClient = exports.default = exports.TinfoilAI = void 0;
|
|
17
|
+
exports.UnprocessableEntityError = exports.PermissionDeniedError = exports.InternalServerError = exports.AuthenticationError = exports.BadRequestError = exports.RateLimitError = exports.ConflictError = exports.NotFoundError = exports.APIUserAbortError = exports.APIConnectionTimeoutError = exports.APIConnectionError = exports.APIError = exports.OpenAIError = exports.PagePromise = exports.APIPromise = exports.toFile = exports.fetchRouter = exports.UnverifiedClient = exports.SecureClient = exports.default = exports.TinfoilAI = void 0;
|
|
18
18
|
// Re-export the TinfoilAI class
|
|
19
19
|
var tinfoilai_1 = require("./tinfoilai");
|
|
20
20
|
Object.defineProperty(exports, "TinfoilAI", { enumerable: true, get: function () { return tinfoilai_1.TinfoilAI; } });
|
|
@@ -28,6 +28,8 @@ var secure_client_1 = require("./secure-client");
|
|
|
28
28
|
Object.defineProperty(exports, "SecureClient", { enumerable: true, get: function () { return secure_client_1.SecureClient; } });
|
|
29
29
|
var unverified_client_1 = require("./unverified-client");
|
|
30
30
|
Object.defineProperty(exports, "UnverifiedClient", { enumerable: true, get: function () { return unverified_client_1.UnverifiedClient; } });
|
|
31
|
+
var router_1 = require("./router");
|
|
32
|
+
Object.defineProperty(exports, "fetchRouter", { enumerable: true, get: function () { return router_1.fetchRouter; } });
|
|
31
33
|
// Re-export OpenAI utility types and classes that users might need
|
|
32
34
|
// Using public exports from the main OpenAI package instead of deep imports
|
|
33
35
|
var openai_1 = require("openai");
|
package/dist/router.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Router utilities for fetching available Tinfoil routers
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Fetches the list of available routers from the ATC API
|
|
6
|
+
* and returns a randomly selected address.
|
|
7
|
+
*
|
|
8
|
+
* @returns Promise<string> A randomly selected router address
|
|
9
|
+
* @throws Error if no routers are found or if the request fails
|
|
10
|
+
*/
|
|
11
|
+
export declare function fetchRouter(): Promise<string>;
|
package/dist/router.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fetchRouter = fetchRouter;
|
|
4
|
+
const config_1 = require("./config");
|
|
5
|
+
/**
|
|
6
|
+
* Router utilities for fetching available Tinfoil routers
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Fetches the list of available routers from the ATC API
|
|
10
|
+
* and returns a randomly selected address.
|
|
11
|
+
*
|
|
12
|
+
* @returns Promise<string> A randomly selected router address
|
|
13
|
+
* @throws Error if no routers are found or if the request fails
|
|
14
|
+
*/
|
|
15
|
+
async function fetchRouter() {
|
|
16
|
+
const routersUrl = config_1.TINFOIL_CONFIG.ATC_API_URL;
|
|
17
|
+
try {
|
|
18
|
+
const response = await fetch(routersUrl);
|
|
19
|
+
if (!response.ok) {
|
|
20
|
+
throw new Error(`Failed to fetch routers: ${response.status} ${response.statusText}`);
|
|
21
|
+
}
|
|
22
|
+
const routers = await response.json();
|
|
23
|
+
if (!Array.isArray(routers) || routers.length === 0) {
|
|
24
|
+
throw new Error("No routers found in the response");
|
|
25
|
+
}
|
|
26
|
+
// Return a randomly selected router
|
|
27
|
+
const randomIndex = Math.floor(Math.random() * routers.length);
|
|
28
|
+
return routers[randomIndex];
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
if (error instanceof Error) {
|
|
32
|
+
throw new Error(`Failed to fetch router: ${error.message}`);
|
|
33
|
+
}
|
|
34
|
+
throw new Error("Failed to fetch router: Unknown error");
|
|
35
|
+
}
|
|
36
|
+
}
|
package/dist/secure-client.d.ts
CHANGED
|
@@ -8,13 +8,14 @@ export declare class SecureClient {
|
|
|
8
8
|
private initPromise;
|
|
9
9
|
private verificationDocument;
|
|
10
10
|
private _fetch;
|
|
11
|
-
private
|
|
12
|
-
private
|
|
11
|
+
private baseURL?;
|
|
12
|
+
private enclaveURL?;
|
|
13
13
|
private readonly configRepo?;
|
|
14
14
|
constructor(options?: SecureClientOptions);
|
|
15
15
|
ready(): Promise<void>;
|
|
16
16
|
private initSecureClient;
|
|
17
17
|
getVerificationDocument(): Promise<VerificationDocument>;
|
|
18
|
+
getBaseURL(): string | undefined;
|
|
18
19
|
get fetch(): typeof fetch;
|
|
19
20
|
}
|
|
20
21
|
export {};
|
package/dist/secure-client.js
CHANGED
|
@@ -4,13 +4,14 @@ exports.SecureClient = void 0;
|
|
|
4
4
|
const verifier_1 = require("./verifier");
|
|
5
5
|
const config_1 = require("./config");
|
|
6
6
|
const secure_fetch_1 = require("./secure-fetch");
|
|
7
|
+
const router_1 = require("./router");
|
|
7
8
|
class SecureClient {
|
|
8
9
|
constructor(options = {}) {
|
|
9
10
|
this.initPromise = null;
|
|
10
11
|
this.verificationDocument = null;
|
|
11
12
|
this._fetch = null;
|
|
12
|
-
this.baseURL = options.baseURL
|
|
13
|
-
this.enclaveURL = options.enclaveURL
|
|
13
|
+
this.baseURL = options.baseURL;
|
|
14
|
+
this.enclaveURL = options.enclaveURL;
|
|
14
15
|
this.configRepo = options.configRepo || config_1.TINFOIL_CONFIG.INFERENCE_PROXY_REPO;
|
|
15
16
|
}
|
|
16
17
|
async ready() {
|
|
@@ -20,6 +21,33 @@ class SecureClient {
|
|
|
20
21
|
return this.initPromise;
|
|
21
22
|
}
|
|
22
23
|
async initSecureClient() {
|
|
24
|
+
// Only fetch router if neither baseURL nor enclaveURL is provided
|
|
25
|
+
if (!this.baseURL && !this.enclaveURL) {
|
|
26
|
+
const routerAddress = await (0, router_1.fetchRouter)();
|
|
27
|
+
this.enclaveURL = `https://${routerAddress}`;
|
|
28
|
+
this.baseURL = `https://${routerAddress}/v1/`;
|
|
29
|
+
}
|
|
30
|
+
// Ensure both baseURL and enclaveURL are initialized
|
|
31
|
+
if (!this.baseURL) {
|
|
32
|
+
if (this.enclaveURL) {
|
|
33
|
+
// If enclaveURL is provided but baseURL is not, derive baseURL from enclaveURL
|
|
34
|
+
const enclaveUrl = new URL(this.enclaveURL);
|
|
35
|
+
this.baseURL = `${enclaveUrl.origin}/v1/`;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
throw new Error("Unable to determine baseURL: neither baseURL nor enclaveURL provided");
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (!this.enclaveURL) {
|
|
42
|
+
if (this.baseURL) {
|
|
43
|
+
// If baseURL is provided but enclaveURL is not, derive enclaveURL from baseURL
|
|
44
|
+
const baseUrl = new URL(this.baseURL);
|
|
45
|
+
this.enclaveURL = baseUrl.origin;
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
throw new Error("Unable to determine enclaveURL: neither baseURL nor enclaveURL provided");
|
|
49
|
+
}
|
|
50
|
+
}
|
|
23
51
|
const verifier = new verifier_1.Verifier({
|
|
24
52
|
serverURL: this.enclaveURL,
|
|
25
53
|
configRepo: this.configRepo,
|
|
@@ -80,6 +108,9 @@ class SecureClient {
|
|
|
80
108
|
}
|
|
81
109
|
return this.verificationDocument;
|
|
82
110
|
}
|
|
111
|
+
getBaseURL() {
|
|
112
|
+
return this.baseURL;
|
|
113
|
+
}
|
|
83
114
|
get fetch() {
|
|
84
115
|
return async (input, init) => {
|
|
85
116
|
await this.ready();
|
package/dist/tinfoilai.js
CHANGED
|
@@ -42,8 +42,8 @@ class TinfoilAI {
|
|
|
42
42
|
openAIOptions.apiKey = process.env.TINFOIL_API_KEY;
|
|
43
43
|
}
|
|
44
44
|
this.apiKey = openAIOptions.apiKey;
|
|
45
|
-
this.baseURL = options.baseURL
|
|
46
|
-
this.enclaveURL = options.enclaveURL
|
|
45
|
+
this.baseURL = options.baseURL;
|
|
46
|
+
this.enclaveURL = options.enclaveURL;
|
|
47
47
|
this.configRepo = options.configRepo || config_1.TINFOIL_CONFIG.INFERENCE_PROXY_REPO;
|
|
48
48
|
this.secureClient = new secure_client_1.SecureClient({
|
|
49
49
|
baseURL: this.baseURL,
|
|
@@ -69,9 +69,11 @@ class TinfoilAI {
|
|
|
69
69
|
if (!this.verificationDocument) {
|
|
70
70
|
throw new Error("Verification document not available after successful verification");
|
|
71
71
|
}
|
|
72
|
+
// Use the provided baseURL, or get it from SecureClient after initialization
|
|
73
|
+
const baseURL = this.baseURL || this.secureClient.getBaseURL();
|
|
72
74
|
const clientOptions = {
|
|
73
75
|
...options,
|
|
74
|
-
baseURL:
|
|
76
|
+
baseURL: baseURL,
|
|
75
77
|
fetch: this.secureClient.fetch,
|
|
76
78
|
};
|
|
77
79
|
if ((0, env_1.isRealBrowser)() || options.dangerouslyAllowBrowser === true) {
|
|
@@ -6,8 +6,8 @@ interface UnverifiedClientOptions {
|
|
|
6
6
|
export declare class UnverifiedClient {
|
|
7
7
|
private initPromise;
|
|
8
8
|
private _fetch;
|
|
9
|
-
private
|
|
10
|
-
private
|
|
9
|
+
private baseURL?;
|
|
10
|
+
private enclaveURL?;
|
|
11
11
|
private readonly configRepo;
|
|
12
12
|
constructor(options?: UnverifiedClientOptions);
|
|
13
13
|
ready(): Promise<void>;
|
|
@@ -3,12 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.UnverifiedClient = void 0;
|
|
4
4
|
const config_1 = require("./config");
|
|
5
5
|
const encrypted_body_fetch_1 = require("./encrypted-body-fetch");
|
|
6
|
+
const router_1 = require("./router");
|
|
6
7
|
class UnverifiedClient {
|
|
7
8
|
constructor(options = {}) {
|
|
8
9
|
this.initPromise = null;
|
|
9
10
|
this._fetch = null;
|
|
10
|
-
this.baseURL = options.baseURL
|
|
11
|
-
this.enclaveURL = options.enclaveURL
|
|
11
|
+
this.baseURL = options.baseURL;
|
|
12
|
+
this.enclaveURL = options.enclaveURL;
|
|
12
13
|
this.configRepo = options.configRepo || config_1.TINFOIL_CONFIG.INFERENCE_PROXY_REPO;
|
|
13
14
|
}
|
|
14
15
|
async ready() {
|
|
@@ -18,6 +19,33 @@ class UnverifiedClient {
|
|
|
18
19
|
return this.initPromise;
|
|
19
20
|
}
|
|
20
21
|
async initUnverifiedClient() {
|
|
22
|
+
// Only fetch router if neither baseURL nor enclaveURL is provided
|
|
23
|
+
if (!this.baseURL && !this.enclaveURL) {
|
|
24
|
+
const routerAddress = await (0, router_1.fetchRouter)();
|
|
25
|
+
this.enclaveURL = `https://${routerAddress}`;
|
|
26
|
+
this.baseURL = `https://${routerAddress}/v1/`;
|
|
27
|
+
}
|
|
28
|
+
// Ensure both baseURL and enclaveURL are initialized
|
|
29
|
+
if (!this.baseURL) {
|
|
30
|
+
if (this.enclaveURL) {
|
|
31
|
+
// If enclaveURL is provided but baseURL is not, derive baseURL from enclaveURL
|
|
32
|
+
const enclaveUrl = new URL(this.enclaveURL);
|
|
33
|
+
this.baseURL = `${enclaveUrl.origin}/v1/`;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
throw new Error("Unable to determine baseURL: neither baseURL nor enclaveURL provided");
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (!this.enclaveURL) {
|
|
40
|
+
if (this.baseURL) {
|
|
41
|
+
// If baseURL is provided but enclaveURL is not, derive enclaveURL from baseURL
|
|
42
|
+
const baseUrl = new URL(this.baseURL);
|
|
43
|
+
this.enclaveURL = baseUrl.origin;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
throw new Error("Unable to determine enclaveURL: neither baseURL nor enclaveURL provided");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
21
49
|
this._fetch = (0, encrypted_body_fetch_1.createEncryptedBodyFetch)(this.baseURL, undefined, this.enclaveURL);
|
|
22
50
|
}
|
|
23
51
|
async getVerificationDocument() {
|
package/dist/verifier.d.ts
CHANGED
|
@@ -87,7 +87,7 @@ export declare class Verifier {
|
|
|
87
87
|
private static executeWithWasm;
|
|
88
88
|
/**
|
|
89
89
|
* Fetch the latest release digest from GitHub
|
|
90
|
-
* @param configRepo - Repository name (e.g., "tinfoilsh/confidential-
|
|
90
|
+
* @param configRepo - Repository name (e.g., "tinfoilsh/confidential-model-router")
|
|
91
91
|
* @returns The digest hash
|
|
92
92
|
*/
|
|
93
93
|
fetchLatestDigest(configRepo?: string): Promise<string>;
|
package/dist/verifier.js
CHANGED
|
@@ -151,7 +151,8 @@ function compareMeasurementsError(codeMeasurement, runtimeMeasurement) {
|
|
|
151
151
|
}
|
|
152
152
|
if (codeMeasurement.type === PLATFORM_TYPES.SNP_TDX_MULTI_PLATFORM_V1) {
|
|
153
153
|
switch (runtimeMeasurement.type) {
|
|
154
|
-
case PLATFORM_TYPES.TDX_GUEST_V1:
|
|
154
|
+
case PLATFORM_TYPES.TDX_GUEST_V1:
|
|
155
|
+
case PLATFORM_TYPES.TDX_GUEST_V2: {
|
|
155
156
|
if (codeMeasurement.registers.length < 3 ||
|
|
156
157
|
runtimeMeasurement.registers.length < 4) {
|
|
157
158
|
return new Error(MEASUREMENT_ERROR_MESSAGES.FEW_REGISTERS);
|
|
@@ -223,8 +224,10 @@ function compareMeasurements(codeMeasurement, runtimeMeasurement) {
|
|
|
223
224
|
*/
|
|
224
225
|
class Verifier {
|
|
225
226
|
constructor(options) {
|
|
226
|
-
|
|
227
|
-
|
|
227
|
+
if (!options?.serverURL) {
|
|
228
|
+
throw new Error("serverURL is required for Verifier");
|
|
229
|
+
}
|
|
230
|
+
this.serverURL = new URL(options.serverURL).hostname;
|
|
228
231
|
this.configRepo =
|
|
229
232
|
options?.configRepo ?? config_1.TINFOIL_CONFIG.INFERENCE_PROXY_REPO;
|
|
230
233
|
}
|
|
@@ -287,7 +290,7 @@ class Verifier {
|
|
|
287
290
|
}
|
|
288
291
|
/**
|
|
289
292
|
* Fetch the latest release digest from GitHub
|
|
290
|
-
* @param configRepo - Repository name (e.g., "tinfoilsh/confidential-
|
|
293
|
+
* @param configRepo - Repository name (e.g., "tinfoilsh/confidential-model-router")
|
|
291
294
|
* @returns The digest hash
|
|
292
295
|
*/
|
|
293
296
|
async fetchLatestDigest(configRepo) {
|