@zeke-02/tinfoil 0.0.11 → 1.1.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.
Files changed (111) hide show
  1. package/dist/ai-sdk-provider.d.ts +43 -4
  2. package/dist/ai-sdk-provider.d.ts.map +1 -0
  3. package/dist/ai-sdk-provider.js +51 -23
  4. package/dist/ai-sdk-provider.js.map +1 -0
  5. package/dist/atc.d.ts +23 -0
  6. package/dist/atc.d.ts.map +1 -0
  7. package/dist/atc.js +59 -0
  8. package/dist/atc.js.map +1 -0
  9. package/dist/config.d.ts +5 -4
  10. package/dist/config.d.ts.map +1 -0
  11. package/dist/config.js +6 -8
  12. package/dist/config.js.map +1 -0
  13. package/dist/encrypted-body-fetch.d.ts +30 -9
  14. package/dist/encrypted-body-fetch.d.ts.map +1 -0
  15. package/dist/encrypted-body-fetch.js +110 -68
  16. package/dist/encrypted-body-fetch.js.map +1 -0
  17. package/dist/env.d.ts +4 -1
  18. package/dist/env.d.ts.map +1 -0
  19. package/dist/env.js +28 -5
  20. package/dist/env.js.map +1 -0
  21. package/dist/index.browser.d.ts +13 -7
  22. package/dist/index.browser.d.ts.map +1 -0
  23. package/dist/index.browser.js +13 -29
  24. package/dist/index.browser.js.map +1 -0
  25. package/dist/index.d.ts +12 -8
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +9 -48
  28. package/dist/index.js.map +1 -0
  29. package/dist/pinned-tls-fetch.browser.d.ts +2 -0
  30. package/dist/pinned-tls-fetch.browser.d.ts.map +1 -0
  31. package/dist/pinned-tls-fetch.browser.js +13 -0
  32. package/dist/pinned-tls-fetch.browser.js.map +1 -0
  33. package/dist/pinned-tls-fetch.d.ts +2 -1
  34. package/dist/pinned-tls-fetch.d.ts.map +1 -0
  35. package/dist/pinned-tls-fetch.js +76 -33
  36. package/dist/pinned-tls-fetch.js.map +1 -0
  37. package/dist/secure-client.d.ts +155 -8
  38. package/dist/secure-client.d.ts.map +1 -0
  39. package/dist/secure-client.js +222 -136
  40. package/dist/secure-client.js.map +1 -0
  41. package/dist/secure-fetch.d.ts +12 -1
  42. package/dist/secure-fetch.d.ts.map +1 -0
  43. package/dist/secure-fetch.js +29 -10
  44. package/dist/secure-fetch.js.map +1 -0
  45. package/dist/tinfoil-ai.d.ts +145 -0
  46. package/dist/tinfoil-ai.d.ts.map +1 -0
  47. package/dist/{esm/tinfoilai.mjs → tinfoil-ai.js} +83 -45
  48. package/dist/tinfoil-ai.js.map +1 -0
  49. package/dist/unsafe.browser.d.ts +3 -0
  50. package/dist/unsafe.browser.d.ts.map +1 -0
  51. package/dist/unsafe.browser.js +3 -0
  52. package/dist/unsafe.browser.js.map +1 -0
  53. package/dist/unsafe.d.ts +3 -0
  54. package/dist/unsafe.d.ts.map +1 -0
  55. package/dist/unsafe.js +3 -0
  56. package/dist/unsafe.js.map +1 -0
  57. package/dist/unverified-client.d.ts +7 -6
  58. package/dist/unverified-client.d.ts.map +1 -0
  59. package/dist/unverified-client.js +36 -32
  60. package/dist/unverified-client.js.map +1 -0
  61. package/dist/verifier.d.ts +2 -141
  62. package/dist/verifier.d.ts.map +1 -0
  63. package/dist/verifier.js +2 -570
  64. package/dist/verifier.js.map +1 -0
  65. package/package.json +54 -64
  66. package/LICENSE +0 -661
  67. package/README.md +0 -183
  68. package/dist/__tests__/test-utils.d.ts +0 -1
  69. package/dist/__tests__/test-utils.js +0 -44
  70. package/dist/esm/__tests__/test-utils.d.ts +0 -1
  71. package/dist/esm/__tests__/test-utils.mjs +0 -38
  72. package/dist/esm/ai-sdk-provider.d.ts +0 -7
  73. package/dist/esm/ai-sdk-provider.mjs +0 -26
  74. package/dist/esm/config.d.ts +0 -13
  75. package/dist/esm/config.mjs +0 -13
  76. package/dist/esm/encrypted-body-fetch.d.ts +0 -13
  77. package/dist/esm/encrypted-body-fetch.mjs +0 -105
  78. package/dist/esm/env.d.ts +0 -5
  79. package/dist/esm/env.mjs +0 -17
  80. package/dist/esm/fetch-adapter.d.ts +0 -21
  81. package/dist/esm/fetch-adapter.mjs +0 -23
  82. package/dist/esm/index.browser.d.ts +0 -7
  83. package/dist/esm/index.browser.mjs +0 -8
  84. package/dist/esm/index.d.ts +0 -9
  85. package/dist/esm/index.mjs +0 -13
  86. package/dist/esm/pinned-tls-fetch.d.ts +0 -1
  87. package/dist/esm/pinned-tls-fetch.mjs +0 -110
  88. package/dist/esm/router.d.ts +0 -11
  89. package/dist/esm/router.mjs +0 -33
  90. package/dist/esm/secure-client.d.ts +0 -21
  91. package/dist/esm/secure-client.mjs +0 -162
  92. package/dist/esm/secure-fetch.browser.d.ts +0 -1
  93. package/dist/esm/secure-fetch.browser.mjs +0 -10
  94. package/dist/esm/secure-fetch.d.ts +0 -1
  95. package/dist/esm/secure-fetch.mjs +0 -12
  96. package/dist/esm/tinfoilai.d.ts +0 -54
  97. package/dist/esm/unverified-client.d.ts +0 -18
  98. package/dist/esm/unverified-client.mjs +0 -61
  99. package/dist/esm/verifier.d.ts +0 -141
  100. package/dist/esm/verifier.mjs +0 -532
  101. package/dist/esm/wasm-exec.js +0 -668
  102. package/dist/esm/wasm-exec.mjs +0 -668
  103. package/dist/fetch-adapter.d.ts +0 -21
  104. package/dist/fetch-adapter.js +0 -27
  105. package/dist/router.d.ts +0 -11
  106. package/dist/router.js +0 -36
  107. package/dist/secure-fetch.browser.d.ts +0 -1
  108. package/dist/secure-fetch.browser.js +0 -13
  109. package/dist/tinfoilai.d.ts +0 -54
  110. package/dist/tinfoilai.js +0 -143
  111. package/dist/wasm-exec.js +0 -668
@@ -1,7 +1,46 @@
1
- interface CreateTinfoilAIOptions {
1
+ /**
2
+ * Options for creating a Tinfoil AI SDK provider.
3
+ */
4
+ export interface CreateTinfoilAIOptions {
5
+ /**
6
+ * Override the base URL for API requests.
7
+ * Useful for proxying requests through your own backend.
8
+ */
2
9
  baseURL?: string;
3
- enclaveURL?: string;
10
+ /** GitHub repo for code verification. */
4
11
  configRepo?: string;
12
+ /** URL to fetch the attestation bundle from. */
13
+ attestationBundleURL?: string;
5
14
  }
6
- export declare function createTinfoilAI(apiKey: string, options?: CreateTinfoilAIOptions, headers?: Record<string, string>): Promise<import("@ai-sdk/openai-compatible").OpenAICompatibleProvider<string, string, string, string>>;
7
- export {};
15
+ /**
16
+ * Create a Tinfoil provider for the Vercel AI SDK.
17
+ *
18
+ * This performs enclave verification and returns an OpenAI-compatible provider
19
+ * that can be used with Vercel AI SDK functions like `generateText` and `streamText`.
20
+ *
21
+ * @param apiKey - Your Tinfoil API key. Falls back to TINFOIL_API_KEY env var if not provided.
22
+ * @param options - Optional configuration
23
+ * @returns An AI SDK provider for Tinfoil
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * import { createTinfoilAI } from "tinfoil";
28
+ * import { generateText } from "ai";
29
+ *
30
+ * // Uses TINFOIL_API_KEY env var
31
+ * const tinfoil = await createTinfoilAI();
32
+ *
33
+ * // Or pass API key explicitly
34
+ * const tinfoil = await createTinfoilAI("your-api-key");
35
+ *
36
+ * const { text } = await generateText({
37
+ * model: tinfoil("llama3-3-70b"),
38
+ * prompt: "Hello!",
39
+ * });
40
+ * ```
41
+ *
42
+ * @see https://docs.tinfoil.sh/sdk/javascript-sdk
43
+ * @see https://sdk.vercel.ai/ - Vercel AI SDK documentation
44
+ */
45
+ export declare function createTinfoilAI(apiKey?: string, options?: CreateTinfoilAIOptions): Promise<import("@ai-sdk/openai-compatible").OpenAICompatibleProvider<string, string, string, string>>;
46
+ //# sourceMappingURL=ai-sdk-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-sdk-provider.d.ts","sourceRoot":"","sources":["../src/ai-sdk-provider.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,yCAAyC;IACzC,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,gDAAgD;IAChD,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAsB,eAAe,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,OAAO,GAAE,sBAA2B,yGAwB1F"}
@@ -1,29 +1,57 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createTinfoilAI = createTinfoilAI;
4
- const openai_compatible_1 = require("@ai-sdk/openai-compatible");
5
- const config_1 = require("./config");
6
- const secure_client_1 = require("./secure-client");
7
- async function createTinfoilAI(apiKey, options = {}, headers = {}) {
8
- const baseURL = options.baseURL;
9
- const enclaveURL = options.enclaveURL;
10
- const configRepo = options.configRepo || config_1.TINFOIL_CONFIG.INFERENCE_PROXY_REPO;
11
- const secureClient = new secure_client_1.SecureClient({
12
- baseURL,
13
- enclaveURL,
14
- configRepo,
1
+ import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
2
+ import { SecureClient } from "./secure-client.js";
3
+ import { isRealBrowser } from "./env.js";
4
+ import { ConfigurationError } from "./verifier.js";
5
+ /**
6
+ * Create a Tinfoil provider for the Vercel AI SDK.
7
+ *
8
+ * This performs enclave verification and returns an OpenAI-compatible provider
9
+ * that can be used with Vercel AI SDK functions like `generateText` and `streamText`.
10
+ *
11
+ * @param apiKey - Your Tinfoil API key. Falls back to TINFOIL_API_KEY env var if not provided.
12
+ * @param options - Optional configuration
13
+ * @returns An AI SDK provider for Tinfoil
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * import { createTinfoilAI } from "tinfoil";
18
+ * import { generateText } from "ai";
19
+ *
20
+ * // Uses TINFOIL_API_KEY env var
21
+ * const tinfoil = await createTinfoilAI();
22
+ *
23
+ * // Or pass API key explicitly
24
+ * const tinfoil = await createTinfoilAI("your-api-key");
25
+ *
26
+ * const { text } = await generateText({
27
+ * model: tinfoil("llama3-3-70b"),
28
+ * prompt: "Hello!",
29
+ * });
30
+ * ```
31
+ *
32
+ * @see https://docs.tinfoil.sh/sdk/javascript-sdk
33
+ * @see https://sdk.vercel.ai/ - Vercel AI SDK documentation
34
+ */
35
+ export async function createTinfoilAI(apiKey, options = {}) {
36
+ // Resolve API key: use provided value, or fall back to env var (non-browser only)
37
+ let resolvedApiKey = apiKey;
38
+ if (!resolvedApiKey && !isRealBrowser() && typeof process !== 'undefined' && process.env.TINFOIL_API_KEY) {
39
+ resolvedApiKey = process.env.TINFOIL_API_KEY;
40
+ }
41
+ if (!resolvedApiKey) {
42
+ throw new ConfigurationError("API key is required. Provide apiKey parameter or set TINFOIL_API_KEY environment variable.");
43
+ }
44
+ const secureClient = new SecureClient({
45
+ baseURL: options.baseURL,
46
+ configRepo: options.configRepo,
47
+ attestationBundleURL: options.attestationBundleURL,
15
48
  });
16
49
  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
- }
22
- return (0, openai_compatible_1.createOpenAICompatible)({
50
+ return createOpenAICompatible({
23
51
  name: "tinfoil",
24
- baseURL: finalBaseURL,
25
- apiKey: apiKey,
52
+ baseURL: secureClient.getBaseURL(),
53
+ apiKey: resolvedApiKey,
26
54
  fetch: secureClient.fetch,
27
- headers,
28
55
  });
29
56
  }
57
+ //# sourceMappingURL=ai-sdk-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-sdk-provider.js","sourceRoot":"","sources":["../src/ai-sdk-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAmBnD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAe,EAAE,UAAkC,EAAE;IACzF,kFAAkF;IAClF,IAAI,cAAc,GAAG,MAAM,CAAC;IAC5B,IAAI,CAAC,cAAc,IAAI,CAAC,aAAa,EAAE,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC;QACzG,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;IAC/C,CAAC;IACD,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,IAAI,kBAAkB,CAAC,4FAA4F,CAAC,CAAC;IAC7H,CAAC;IAED,MAAM,YAAY,GAAG,IAAI,YAAY,CAAC;QACpC,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,oBAAoB,EAAE,OAAO,CAAC,oBAAoB;KACnD,CAAC,CAAC;IAEH,MAAM,YAAY,CAAC,KAAK,EAAE,CAAC;IAE3B,OAAO,sBAAsB,CAAC;QAC5B,IAAI,EAAE,SAAS;QACf,OAAO,EAAE,YAAY,CAAC,UAAU,EAAG;QACnC,MAAM,EAAE,cAAc;QACtB,KAAK,EAAE,YAAY,CAAC,KAAK;KAC1B,CAAC,CAAC;AACL,CAAC"}
package/dist/atc.d.ts ADDED
@@ -0,0 +1,23 @@
1
+ import type { AttestationBundle } from "./verifier.js";
2
+ export interface FetchAttestationBundleOptions {
3
+ atcBaseUrl?: string;
4
+ enclaveURL?: string;
5
+ configRepo?: string;
6
+ }
7
+ /**
8
+ * Fetches a complete attestation bundle from ATC.
9
+ *
10
+ * When enclaveURL or configRepo are provided, issues a POST so ATC builds a
11
+ * bundle for the specified enclave/repo. Otherwise issues a GET for the
12
+ * default router behaviour.
13
+ */
14
+ export declare function fetchAttestationBundle(options?: FetchAttestationBundleOptions): Promise<AttestationBundle>;
15
+ /**
16
+ * Fetches the list of available routers and returns a randomly selected address.
17
+ *
18
+ * @param atcBaseUrl - Base URL for the attestation endpoint (defaults to TINFOIL_CONFIG.ATC_BASE_URL)
19
+ * @returns A randomly selected router address
20
+ * @throws Error if no routers are found or if the request fails
21
+ */
22
+ export declare function fetchRouter(atcBaseUrl?: string): Promise<string>;
23
+ //# sourceMappingURL=atc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atc.d.ts","sourceRoot":"","sources":["../src/atc.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGvD,MAAM,WAAW,6BAA6B;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CAAC,OAAO,GAAE,6BAAkC,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAkCpH;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,UAAU,GAAE,MAAoC,GAAG,OAAO,CAAC,MAAM,CAAC,CAgBnG"}
package/dist/atc.js ADDED
@@ -0,0 +1,59 @@
1
+ import { TINFOIL_CONFIG } from "./config.js";
2
+ import { FetchError } from "./verifier.js";
3
+ /**
4
+ * Fetches a complete attestation bundle from ATC.
5
+ *
6
+ * When enclaveURL or configRepo are provided, issues a POST so ATC builds a
7
+ * bundle for the specified enclave/repo. Otherwise issues a GET for the
8
+ * default router behaviour.
9
+ */
10
+ export async function fetchAttestationBundle(options = {}) {
11
+ const baseUrl = options.atcBaseUrl ?? TINFOIL_CONFIG.ATC_BASE_URL;
12
+ const url = `${baseUrl}/attestation`;
13
+ const usePost = !!(options.enclaveURL || options.configRepo);
14
+ const response = usePost
15
+ ? await fetch(url, {
16
+ method: 'POST',
17
+ headers: { 'Content-Type': 'application/json' },
18
+ body: JSON.stringify({
19
+ enclaveUrl: options.enclaveURL,
20
+ repo: options.configRepo,
21
+ }),
22
+ })
23
+ : await fetch(url);
24
+ if (!response.ok) {
25
+ throw new FetchError(`Failed to fetch attestation bundle from ${baseUrl}: HTTP ${response.status} ${response.statusText}`);
26
+ }
27
+ const bundle = await response.json();
28
+ return {
29
+ domain: bundle.domain,
30
+ enclaveAttestationReport: {
31
+ format: bundle.enclaveAttestationReport.format,
32
+ body: bundle.enclaveAttestationReport.body,
33
+ },
34
+ digest: bundle.digest,
35
+ sigstoreBundle: bundle.sigstoreBundle,
36
+ vcek: bundle.vcek,
37
+ enclaveCert: bundle.enclaveCert,
38
+ };
39
+ }
40
+ /**
41
+ * Fetches the list of available routers and returns a randomly selected address.
42
+ *
43
+ * @param atcBaseUrl - Base URL for the attestation endpoint (defaults to TINFOIL_CONFIG.ATC_BASE_URL)
44
+ * @returns A randomly selected router address
45
+ * @throws Error if no routers are found or if the request fails
46
+ */
47
+ export async function fetchRouter(atcBaseUrl = TINFOIL_CONFIG.ATC_BASE_URL) {
48
+ const routersUrl = `${atcBaseUrl}/routers?platform=snp`;
49
+ const response = await fetch(routersUrl);
50
+ if (!response.ok) {
51
+ throw new FetchError(`Failed to fetch router list from ${atcBaseUrl}: HTTP ${response.status} ${response.statusText}`);
52
+ }
53
+ const routers = await response.json();
54
+ if (!Array.isArray(routers) || routers.length === 0) {
55
+ throw new FetchError("No available routers found in the response");
56
+ }
57
+ return routers[Math.floor(Math.random() * routers.length)];
58
+ }
59
+ //# sourceMappingURL=atc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atc.js","sourceRoot":"","sources":["../src/atc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAQ3C;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,UAAyC,EAAE;IACtF,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,IAAI,cAAc,CAAC,YAAY,CAAC;IAClE,MAAM,GAAG,GAAG,GAAG,OAAO,cAAc,CAAC;IAErC,MAAM,OAAO,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC;IAE7D,MAAM,QAAQ,GAAG,OAAO;QACtB,CAAC,CAAC,MAAM,KAAK,CAAC,GAAG,EAAE;YACf,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,IAAI,EAAE,OAAO,CAAC,UAAU;aACzB,CAAC;SACH,CAAC;QACJ,CAAC,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;IAErB,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,UAAU,CAAC,2CAA2C,OAAO,UAAU,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;IAC7H,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAErC,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,wBAAwB,EAAE;YACxB,MAAM,EAAE,MAAM,CAAC,wBAAwB,CAAC,MAAM;YAC9C,IAAI,EAAE,MAAM,CAAC,wBAAwB,CAAC,IAAI;SAC3C;QACD,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,WAAW,EAAE,MAAM,CAAC,WAAW;KAChC,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,aAAqB,cAAc,CAAC,YAAY;IAChF,MAAM,UAAU,GAAG,GAAG,UAAU,uBAAuB,CAAC;IAExD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC,CAAC;IAEzC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,UAAU,CAAC,oCAAoC,UAAU,UAAU,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;IACzH,CAAC;IAED,MAAM,OAAO,GAAa,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAEhD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpD,MAAM,IAAI,UAAU,CAAC,4CAA4C,CAAC,CAAC;IACrE,CAAC;IAED,OAAO,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;AAC7D,CAAC"}
package/dist/config.d.ts CHANGED
@@ -3,11 +3,12 @@
3
3
  */
4
4
  export declare const TINFOIL_CONFIG: {
5
5
  /**
6
- * The GitHub repository for code attestation verification
6
+ * Base URL for the attestation endpoint
7
7
  */
8
- readonly INFERENCE_PROXY_REPO: "tinfoilsh/confidential-model-router";
8
+ readonly ATC_BASE_URL: "https://atc.tinfoil.sh";
9
9
  /**
10
- * The ATC (Attestation and Trust Center) API URL for fetching available routers
10
+ * The GitHub repository for the router code attestation
11
11
  */
12
- readonly ATC_API_URL: "https://atc.tinfoil.sh/routers";
12
+ readonly DEFAULT_ROUTER_REPO: "tinfoilsh/confidential-model-router";
13
13
  };
14
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,cAAc;IACzB;;OAEG;;IAGH;;OAEG;;CAEK,CAAC"}
package/dist/config.js CHANGED
@@ -1,16 +1,14 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TINFOIL_CONFIG = void 0;
4
1
  /**
5
2
  * Configuration constants for the Tinfoil Node SDK
6
3
  */
7
- exports.TINFOIL_CONFIG = {
4
+ export const TINFOIL_CONFIG = {
8
5
  /**
9
- * The GitHub repository for code attestation verification
6
+ * Base URL for the attestation endpoint
10
7
  */
11
- INFERENCE_PROXY_REPO: "tinfoilsh/confidential-model-router",
8
+ ATC_BASE_URL: "https://atc.tinfoil.sh",
12
9
  /**
13
- * The ATC (Attestation and Trust Center) API URL for fetching available routers
10
+ * The GitHub repository for the router code attestation
14
11
  */
15
- ATC_API_URL: "https://atc.tinfoil.sh/routers",
12
+ DEFAULT_ROUTER_REPO: "tinfoilsh/confidential-model-router",
16
13
  };
14
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B;;OAEG;IACH,YAAY,EAAE,wBAAwB;IAEtC;;OAEG;IACH,mBAAmB,EAAE,qCAAqC;CAClD,CAAC"}
@@ -1,13 +1,34 @@
1
- import type { Transport as EhbpTransport } from "@zeke-02/ehbp";
2
- export declare function getHPKEKey(enclaveURL: string): Promise<CryptoKey>;
1
+ import { Identity, Transport, type SessionRecoveryToken } from "ehbp";
2
+ export type { SessionRecoveryToken } from "ehbp";
3
+ export { decryptResponseWithToken } from "ehbp";
4
+ export interface SecureTransport {
5
+ fetch: typeof fetch;
6
+ getSessionRecoveryToken(): Promise<SessionRecoveryToken>;
7
+ }
8
+ /**
9
+ * Fetch and parse server identity from the HPKE keys endpoint.
10
+ * Returns the server Identity which can be used to create a Transport.
11
+ */
12
+ export declare function getServerIdentity(enclaveURL: string): Promise<Identity>;
3
13
  export declare function normalizeEncryptedBodyRequestArgs(input: RequestInfo | URL, init?: RequestInit): {
4
14
  url: string;
5
15
  init?: RequestInit;
6
16
  };
7
- export declare function encryptedBodyRequest(input: RequestInfo | URL, hpkePublicKey?: string, init?: RequestInit, enclaveURL?: string, transportInstance?: EhbpTransport): Promise<Response>;
8
- type FetchWithResponse = typeof fetch & {
9
- Response: typeof Response;
10
- };
11
- export declare function createEncryptedBodyFetch(baseURL: string, hpkePublicKey?: string, enclaveURL?: string): FetchWithResponse;
12
- export declare function getTransportForOrigin(origin: string, keyOrigin: string): Promise<EhbpTransport>;
13
- export {};
17
+ export declare function encryptedBodyRequest(input: RequestInfo | URL, hpkePublicKey: string, init?: RequestInit, transportInstance?: Transport): Promise<Response>;
18
+ export declare function createEncryptedBodyFetch(baseURL: string, hpkePublicKey: string, enclaveURL?: string): SecureTransport;
19
+ /**
20
+ * WARNING: THIS FUNCTION IS INSECURE.
21
+ *
22
+ * Creates an encrypted body fetch that fetches the HPKE key from the server without
23
+ * attestation verification. This is vulnerable to man-in-the-middle attacks where
24
+ * a malicious server could provide its own key.
25
+ *
26
+ * This function is useful for testing the EHBP protocol against a local development
27
+ * server that doesn't have attestation set up. For production, use createEncryptedBodyFetch
28
+ * with a key obtained through attestation verification.
29
+ *
30
+ * @param baseURL - Base URL for API requests
31
+ * @param keyOrigin - Origin URL for fetching the HPKE public key. If not provided, derived from baseURL.
32
+ */
33
+ export declare function createUnverifiedEncryptedBodyFetch(baseURL: string, keyOrigin?: string): SecureTransport;
34
+ //# sourceMappingURL=encrypted-body-fetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encrypted-body-fetch.d.ts","sourceRoot":"","sources":["../src/encrypted-body-fetch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAY,KAAK,oBAAoB,EAAE,MAAM,MAAM,CAAC;AAGhF,YAAY,EAAE,oBAAoB,EAAE,MAAM,MAAM,CAAC;AACjD,OAAO,EAAE,wBAAwB,EAAE,MAAM,MAAM,CAAC;AAEhD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,OAAO,KAAK,CAAC;IACpB,uBAAuB,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAAC;CAC1D;AAUD;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAoB7E;AAED,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,WAAW,GAAG,GAAG,EACxB,IAAI,CAAC,EAAE,WAAW,GACjB;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,WAAW,CAAA;CAAE,CAuBrC;AAED,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,WAAW,GAAG,GAAG,EACxB,aAAa,EAAE,MAAM,EACrB,IAAI,CAAC,EAAE,WAAW,EAClB,iBAAiB,CAAC,EAAE,SAAS,GAC5B,OAAO,CAAC,QAAQ,CAAC,CAgBnB;AAID,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,eAAe,CAoCrH;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kCAAkC,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,eAAe,CA2CvG"}
@@ -1,33 +1,34 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getHPKEKey = getHPKEKey;
4
- exports.normalizeEncryptedBodyRequestArgs = normalizeEncryptedBodyRequestArgs;
5
- exports.encryptedBodyRequest = encryptedBodyRequest;
6
- exports.createEncryptedBodyFetch = createEncryptedBodyFetch;
7
- exports.getTransportForOrigin = getTransportForOrigin;
8
- const ehbp_1 = require("@zeke-02/ehbp");
9
- const fetch_adapter_1 = require("./fetch-adapter");
10
- // Public API
11
- async function getHPKEKey(enclaveURL) {
12
- const url = new URL(enclaveURL);
13
- const keysURL = new URL(ehbp_1.PROTOCOL.KEYS_PATH, enclaveURL);
14
- if (keysURL.protocol !== "https:") {
15
- throw new Error(`HTTPS is required for remote key retrieval. Invalid protocol: ${keysURL.protocol}`);
1
+ import { Identity, Transport, PROTOCOL } from "ehbp";
2
+ import { ConfigurationError, FetchError } from "./verifier.js";
3
+ export { decryptResponseWithToken } from "ehbp";
4
+ /**
5
+ * Create an Identity from a raw public key hex string.
6
+ * This avoids fetching from the server when the key is already known.
7
+ */
8
+ async function createIdentityFromPublicKeyHex(publicKeyHex) {
9
+ return Identity.fromPublicKeyHex(publicKeyHex);
10
+ }
11
+ /**
12
+ * Fetch and parse server identity from the HPKE keys endpoint.
13
+ * Returns the server Identity which can be used to create a Transport.
14
+ */
15
+ export async function getServerIdentity(enclaveURL) {
16
+ const keysURL = new URL(PROTOCOL.KEYS_PATH, enclaveURL);
17
+ if (keysURL.protocol !== 'https:') {
18
+ throw new ConfigurationError(`HTTPS is required for key retrieval. Got ${keysURL.protocol}`);
16
19
  }
17
- const fetchFn = (0, fetch_adapter_1.getFetch)();
18
- const response = await fetchFn(keysURL.toString());
20
+ const response = await fetch(keysURL.toString());
19
21
  if (!response.ok) {
20
- throw new Error(`Failed to get server public key: ${response.status}`);
22
+ throw new FetchError(`Failed to fetch HPKE public key from enclave: HTTP ${response.status}`);
21
23
  }
22
- const contentType = response.headers.get("content-type");
23
- if (contentType !== ehbp_1.PROTOCOL.KEYS_MEDIA_TYPE) {
24
- throw new Error(`Invalid content type: ${contentType}`);
24
+ const contentType = response.headers.get('content-type');
25
+ if (contentType !== PROTOCOL.KEYS_MEDIA_TYPE) {
26
+ throw new FetchError(`Invalid response from HPKE key endpoint: Expected content-type "${PROTOCOL.KEYS_MEDIA_TYPE}", got "${contentType}"`);
25
27
  }
26
28
  const keysData = new Uint8Array(await response.arrayBuffer());
27
- const serverIdentity = await ehbp_1.Identity.unmarshalPublicConfig(keysData);
28
- return serverIdentity.getPublicKey();
29
+ return await Identity.unmarshalPublicConfig(keysData);
29
30
  }
30
- function normalizeEncryptedBodyRequestArgs(input, init) {
31
+ export function normalizeEncryptedBodyRequestArgs(input, init) {
31
32
  if (typeof input === "string") {
32
33
  return { url: input, init };
33
34
  }
@@ -47,66 +48,107 @@ function normalizeEncryptedBodyRequestArgs(input, init) {
47
48
  init: { ...derivedInit, ...init },
48
49
  };
49
50
  }
50
- async function encryptedBodyRequest(input, hpkePublicKey, init, enclaveURL, transportInstance) {
51
+ export async function encryptedBodyRequest(input, hpkePublicKey, init, transportInstance) {
51
52
  const { url: requestUrl, init: requestInit } = normalizeEncryptedBodyRequestArgs(input, init);
52
53
  let actualTransport;
53
54
  if (transportInstance) {
54
- // Use provided transport instance
55
55
  actualTransport = transportInstance;
56
56
  }
57
57
  else {
58
- // Create a new transport for this request
59
58
  const u = new URL(requestUrl);
60
- const { origin } = u;
61
- const keyOrigin = enclaveURL ? new URL(enclaveURL).origin : origin;
62
- actualTransport = await getTransportForOrigin(origin, keyOrigin);
63
- }
64
- if (hpkePublicKey) {
65
- const transportKeyHash = await actualTransport.getServerPublicKeyHex();
66
- if (transportKeyHash !== hpkePublicKey) {
67
- throw new Error(`HPKE public key mismatch. Expected: ${hpkePublicKey}, Got: ${transportKeyHash}`);
68
- }
59
+ actualTransport = await getTransportForOrigin(u.origin, hpkePublicKey);
69
60
  }
70
61
  return actualTransport.request(requestUrl, requestInit);
71
62
  }
72
- function createEncryptedBodyFetch(baseURL, hpkePublicKey, enclaveURL) {
73
- // Create a dedicated transport instance for this fetch function
63
+ const ENCLAVE_URL_HEADER = 'X-Tinfoil-Enclave-Url';
64
+ export function createEncryptedBodyFetch(baseURL, hpkePublicKey, enclaveURL) {
65
+ const baseOrigin = new URL(baseURL).origin;
66
+ const needsEnclaveHeader = !!enclaveURL && new URL(enclaveURL).origin !== baseOrigin;
74
67
  let transportPromise = null;
75
- const getOrCreateTransport = async () => {
68
+ const getOrCreateTransport = () => {
76
69
  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);
70
+ transportPromise = getTransportForOrigin(baseOrigin, hpkePublicKey);
82
71
  }
83
72
  return transportPromise;
84
73
  };
85
- const secureFetch = (async (input, init) => {
86
- const normalized = normalizeEncryptedBodyRequestArgs(input, init);
87
- const targetUrl = new URL(normalized.url, baseURL);
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);
91
- });
92
- // Expose Response constructor for OpenAI SDK's FormData support detection
93
- // This prevents the SDK from making a test request to 'data:,' which would fail through EHBP
94
- secureFetch.Response = Response;
95
- return secureFetch;
74
+ return {
75
+ fetch: async (input, init) => {
76
+ const normalized = normalizeEncryptedBodyRequestArgs(input, init);
77
+ const targetUrl = new URL(normalized.url, baseURL);
78
+ const headers = new Headers(normalized.init?.headers);
79
+ if (needsEnclaveHeader) {
80
+ headers.set(ENCLAVE_URL_HEADER, enclaveURL);
81
+ }
82
+ const initWithHeader = { ...normalized.init, headers };
83
+ const transportInstance = await getOrCreateTransport();
84
+ return encryptedBodyRequest(targetUrl.toString(), hpkePublicKey, initWithHeader, transportInstance);
85
+ },
86
+ async getSessionRecoveryToken() {
87
+ if (!transportPromise) {
88
+ throw new Error('No session recovery token available — no request has been made yet');
89
+ }
90
+ const transport = await transportPromise;
91
+ return transport.getSessionRecoveryToken();
92
+ },
93
+ };
96
94
  }
97
- async function getTransportForOrigin(origin, keyOrigin) {
98
- if (typeof globalThis !== "undefined") {
99
- const isSecure = globalThis.isSecureContext !== false;
100
- const hasSubtle = !!(globalThis.crypto && globalThis.crypto.subtle);
101
- if (!isSecure || !hasSubtle) {
102
- const reason = !isSecure
103
- ? "insecure context (use HTTPS or localhost)"
104
- : "missing WebCrypto SubtleCrypto";
105
- throw new Error(`EHBP requires a secure browser context: ${reason}`);
95
+ /**
96
+ * WARNING: THIS FUNCTION IS INSECURE.
97
+ *
98
+ * Creates an encrypted body fetch that fetches the HPKE key from the server without
99
+ * attestation verification. This is vulnerable to man-in-the-middle attacks where
100
+ * a malicious server could provide its own key.
101
+ *
102
+ * This function is useful for testing the EHBP protocol against a local development
103
+ * server that doesn't have attestation set up. For production, use createEncryptedBodyFetch
104
+ * with a key obtained through attestation verification.
105
+ *
106
+ * @param baseURL - Base URL for API requests
107
+ * @param keyOrigin - Origin URL for fetching the HPKE public key. If not provided, derived from baseURL.
108
+ */
109
+ export function createUnverifiedEncryptedBodyFetch(baseURL, keyOrigin) {
110
+ console.warn("[tinfoil] WARNING: createUnverifiedEncryptedBodyFetch is insecure. " +
111
+ "The HPKE key is fetched from the server without attestation verification. " +
112
+ "Only use for local development and testing of the EHBP protocol.");
113
+ const baseOrigin = new URL(baseURL).origin;
114
+ const resolvedKeyOrigin = keyOrigin ? new URL(keyOrigin).origin : baseOrigin;
115
+ const needsEnclaveHeader = !!keyOrigin && resolvedKeyOrigin !== baseOrigin;
116
+ let transportPromise = null;
117
+ const getOrCreateTransport = async () => {
118
+ if (!transportPromise) {
119
+ transportPromise = getUnverifiedTransportForOrigin(baseOrigin, resolvedKeyOrigin);
106
120
  }
107
- }
108
- const clientIdentity = await ehbp_1.Identity.generate();
109
- const serverPublicKey = await getHPKEKey(keyOrigin);
121
+ return transportPromise;
122
+ };
123
+ return {
124
+ fetch: async (input, init) => {
125
+ const normalized = normalizeEncryptedBodyRequestArgs(input, init);
126
+ const targetUrl = new URL(normalized.url, baseURL);
127
+ const headers = new Headers(normalized.init?.headers);
128
+ if (needsEnclaveHeader) {
129
+ headers.set(ENCLAVE_URL_HEADER, keyOrigin);
130
+ }
131
+ const initWithEnclaveHeader = { ...normalized.init, headers };
132
+ const transportInstance = await getOrCreateTransport();
133
+ return transportInstance.request(targetUrl.toString(), initWithEnclaveHeader);
134
+ },
135
+ async getSessionRecoveryToken() {
136
+ if (!transportPromise) {
137
+ throw new Error('No session recovery token available — no request has been made yet');
138
+ }
139
+ const transport = await transportPromise;
140
+ return transport.getSessionRecoveryToken();
141
+ },
142
+ };
143
+ }
144
+ async function getUnverifiedTransportForOrigin(origin, keyOrigin) {
145
+ const serverIdentity = await getServerIdentity(keyOrigin);
146
+ const requestHost = new URL(origin).host;
147
+ return new Transport(serverIdentity, requestHost);
148
+ }
149
+ async function getTransportForOrigin(origin, hpkePublicKeyHex) {
150
+ const serverIdentity = await createIdentityFromPublicKeyHex(hpkePublicKeyHex);
110
151
  const requestHost = new URL(origin).host;
111
- return new ehbp_1.Transport(clientIdentity, requestHost, serverPublicKey);
152
+ return new Transport(serverIdentity, requestHost);
112
153
  }
154
+ //# sourceMappingURL=encrypted-body-fetch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encrypted-body-fetch.js","sourceRoot":"","sources":["../src/encrypted-body-fetch.ts"],"names":[],"mappings":"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"}
package/dist/env.d.ts CHANGED
@@ -1,5 +1,8 @@
1
+ export declare function isBun(): boolean;
1
2
  /**
2
3
  * Detects if the code is running in a real browser environment.
3
- * Returns false for Node.js environments, even with WASM loaded.
4
+ * Returns false for server-side runtimes (Node.js, Bun, Deno, edge runtimes).
5
+ * Only returns true when we can positively identify a browser environment.
4
6
  */
5
7
  export declare function isRealBrowser(): boolean;
8
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA,wBAAgB,KAAK,IAAI,OAAO,CAI/B;AAED;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAuCvC"}
package/dist/env.js CHANGED
@@ -1,20 +1,43 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isRealBrowser = isRealBrowser;
1
+ export function isBun() {
2
+ return typeof process !== "undefined" &&
3
+ !!process.versions &&
4
+ !!process.versions.bun;
5
+ }
4
6
  /**
5
7
  * Detects if the code is running in a real browser environment.
6
- * Returns false for Node.js environments, even with WASM loaded.
8
+ * Returns false for server-side runtimes (Node.js, Bun, Deno, edge runtimes).
9
+ * Only returns true when we can positively identify a browser environment.
7
10
  */
8
- function isRealBrowser() {
11
+ export function isRealBrowser() {
12
+ // Check for Node.js
9
13
  if (typeof process !== "undefined" &&
10
14
  process.versions &&
11
15
  process.versions.node) {
12
16
  return false;
13
17
  }
18
+ // Check for Bun
19
+ if (isBun()) {
20
+ return false;
21
+ }
22
+ // Check for Deno
23
+ if (typeof globalThis.Deno !== "undefined") {
24
+ return false;
25
+ }
26
+ // Check for Cloudflare Workers (has 'Cloudflare-Workers' userAgent when global_navigator flag is set)
27
+ if (typeof navigator !== "undefined" && navigator.userAgent === "Cloudflare-Workers") {
28
+ return false;
29
+ }
30
+ // Check for Cloudflare Workers via caches.default (alternative detection)
31
+ if (typeof caches !== "undefined" && caches.default !== undefined) {
32
+ return false;
33
+ }
34
+ // Check for real browser: must have window, document, and a real userAgent
14
35
  if (typeof window !== "undefined" && typeof window.document !== "undefined") {
15
36
  if (typeof navigator !== "undefined" && navigator.userAgent) {
16
37
  return true;
17
38
  }
18
39
  }
40
+ // Unknown runtime - treat as server-side (safer default)
19
41
  return false;
20
42
  }
43
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,KAAK;IACnB,OAAO,OAAO,OAAO,KAAK,WAAW;QACnC,CAAC,CAAE,OAAe,CAAC,QAAQ;QAC3B,CAAC,CAAE,OAAe,CAAC,QAAQ,CAAC,GAAG,CAAC;AACpC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa;IAC3B,oBAAoB;IACpB,IACE,OAAO,OAAO,KAAK,WAAW;QAC7B,OAAe,CAAC,QAAQ;QACxB,OAAe,CAAC,QAAQ,CAAC,IAAI,EAC9B,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,gBAAgB;IAChB,IAAI,KAAK,EAAE,EAAE,CAAC;QACZ,OAAO,KAAK,CAAC;IACf,CAAC;IAED,iBAAiB;IACjB,IAAI,OAAQ,UAAkB,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QACpD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,sGAAsG;IACtG,IAAI,OAAO,SAAS,KAAK,WAAW,IAAI,SAAS,CAAC,SAAS,KAAK,oBAAoB,EAAE,CAAC;QACrF,OAAO,KAAK,CAAC;IACf,CAAC;IAED,0EAA0E;IAC1E,IAAI,OAAO,MAAM,KAAK,WAAW,IAAK,MAAc,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAC3E,OAAO,KAAK,CAAC;IACf,CAAC;IAED,2EAA2E;IAC3E,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,MAAM,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC;QAC5E,IAAI,OAAO,SAAS,KAAK,WAAW,IAAI,SAAS,CAAC,SAAS,EAAE,CAAC;YAC5D,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,yDAAyD;IACzD,OAAO,KAAK,CAAC;AACf,CAAC"}