From c9686e69d9f93d9edb74b01ef7d6bffbd7cfa984 Mon Sep 17 00:00:00 2001
From: SachaMorard <2254275+SachaMorard@users.noreply.github.com>
Date: Wed, 14 Jan 2026 07:16:44 +0100
Subject: [PATCH] feat: sdk full documentation
---
api-reference/authentication.mdx | 29 +-
api-reference/caching/purge-cache.mdx | 8 -
api-reference/chat-completion.mdx | 7 +
api-reference/errors.mdx | 236 +++++++--
api-reference/index.mdx | 53 +-
api-reference/models.mdx | 7 +
api-reference/openapi.json | 670 +++++++++++++++++++++++--
docs.json | 71 ++-
images/byok-dark.png | Bin 0 -> 310286 bytes
images/byok-light.png | Bin 0 -> 312128 bytes
introduction.mdx | 127 ++---
introduction/why-edgee.mdx | 66 ++-
package-lock.json | 203 ++++----
package.json | 2 +-
proxy/components/overview.mdx | 1 -
proxy/services/performance/caching.mdx | 10 -
sdk/go/configuration.mdx | 193 +++++++
sdk/go/index.mdx | 484 +-----------------
sdk/go/send.mdx | 257 ++++++++++
sdk/go/stream.mdx | 300 +++++++++++
sdk/go/tools.mdx | 618 +++++++++++++++++++++++
sdk/index.mdx | 67 ++-
sdk/python/configuration.mdx | 146 ++++++
sdk/python/index.mdx | 384 +-------------
sdk/python/send.mdx | 236 +++++++++
sdk/python/stream.mdx | 200 ++++++++
sdk/python/tools.mdx | 560 +++++++++++++++++++++
sdk/rust/configuration.mdx | 191 +++++++
sdk/rust/index.mdx | 540 +-------------------
sdk/rust/send.mdx | 251 +++++++++
sdk/rust/stream.mdx | 280 +++++++++++
sdk/rust/tools.mdx | 548 ++++++++++++++++++++
sdk/typescript/configuration.mdx | 173 +++++++
sdk/typescript/index.mdx | 368 +-------------
sdk/typescript/send.mdx | 233 +++++++++
sdk/typescript/stream.mdx | 213 ++++++++
sdk/typescript/tools.mdx | 499 ++++++++++++++++++
37 files changed, 6132 insertions(+), 2099 deletions(-)
delete mode 100644 api-reference/caching/purge-cache.mdx
create mode 100644 api-reference/chat-completion.mdx
create mode 100644 api-reference/models.mdx
create mode 100644 images/byok-dark.png
create mode 100644 images/byok-light.png
create mode 100644 sdk/go/configuration.mdx
create mode 100644 sdk/go/send.mdx
create mode 100644 sdk/go/stream.mdx
create mode 100644 sdk/go/tools.mdx
create mode 100644 sdk/python/configuration.mdx
create mode 100644 sdk/python/send.mdx
create mode 100644 sdk/python/stream.mdx
create mode 100644 sdk/python/tools.mdx
create mode 100644 sdk/rust/configuration.mdx
create mode 100644 sdk/rust/send.mdx
create mode 100644 sdk/rust/stream.mdx
create mode 100644 sdk/rust/tools.mdx
create mode 100644 sdk/typescript/configuration.mdx
create mode 100644 sdk/typescript/send.mdx
create mode 100644 sdk/typescript/stream.mdx
create mode 100644 sdk/typescript/tools.mdx
diff --git a/api-reference/authentication.mdx b/api-reference/authentication.mdx
index 632f8f9..75c6d47 100644
--- a/api-reference/authentication.mdx
+++ b/api-reference/authentication.mdx
@@ -1,40 +1,35 @@
---
title: "Authentication"
description: "How to authenticate to the Edgee API"
+icon: key-round
---
-The Edgee API uses API tokens to authenticate requests. You can view and manage your API token in the
-Edgee [Console](https://www.edgee.cloud/settings/tokens).
+The Edgee API uses API keys to authenticate requests. You can view and manage your API keys in the
+Edgee [Console](https://www.edgee.cloud/). Please refer to the [Create an API Key](/quickstart/api-key) guide to know more about how to create an API key.
-Your API tokens carry many privileges, so be sure to keep them secure! Do not share your tokens in
-publicly accessible areas such as GitHub, client-side code, and so forth.
+
+ Your API keys carry many privileges, so be sure to keep them secure!
+
+ Do not share your API keys in publicly accessible areas such as GitHub, client-side code, and so forth.
+
Authentication to the API is performed via Bearer authentication (also called token authentication).
It is an HTTP authentication scheme that involves security tokens called bearer tokens. The client must send this token
in the Authorization header when making requests to protected resources:
```bash
-Authorization: Bearer
+Authorization: Bearer
```
-If you need to authenticate via HTTP Basic Auth,
-use `-u {{token}}:` instead of `-H "Authorization: Bearer {{token}}"`.
-
All API requests must be made over HTTPS. Calls made over plain HTTP will fail. API requests without authentication
will also fail.
```bash cURL with Bearer
- curl 'https://api.edgee.ai/v1/projects' \
- -H 'Authorization: Bearer '
+ curl 'https://api.edgee.ai/v1/models' \
+ -H 'Authorization: Bearer '
```
-
- ```bash cURL with Basic Auth
- curl 'https://api.edgee.ai/v1/projects' \
- -u ':'
- # The colon prevents curl from asking for a password.
- ```
-
+
diff --git a/api-reference/caching/purge-cache.mdx b/api-reference/caching/purge-cache.mdx
deleted file mode 100644
index 34852c3..0000000
--- a/api-reference/caching/purge-cache.mdx
+++ /dev/null
@@ -1,8 +0,0 @@
----
-title: 'Purge Cache'
-openapi: 'POST /v1/projects/{id}/purge-cache'
----
-
-When you purge cache, Edgee will remove the specified cached content from all edge locations worldwide, which is useful when you need to update cached content, clear stale data after deployments, force fresh content to be served to users, or troubleshoot caching issues.
-
-Query strings are automatically removed from the path before purging and cache is purged for all domains associated with the project across all edge locations worldwide.
diff --git a/api-reference/chat-completion.mdx b/api-reference/chat-completion.mdx
new file mode 100644
index 0000000..9e66622
--- /dev/null
+++ b/api-reference/chat-completion.mdx
@@ -0,0 +1,7 @@
+---
+title: 'Chat Completion'
+description: 'Create chat completions using the Edgee AI Gateway API'
+openapi: 'POST /v1/chat/completions'
+---
+
+Creates a completion for the chat message. The Edgee API is OpenAI-compatible and works with any model and provider. Supports both streaming and non-streaming responses.
diff --git a/api-reference/errors.mdx b/api-reference/errors.mdx
index b424790..abc6195 100644
--- a/api-reference/errors.mdx
+++ b/api-reference/errors.mdx
@@ -1,64 +1,222 @@
---
title: "Errors"
description: "How Edgee API responds when errors occur."
+icon: circle-x
---
-Edgee uses conventional HTTP response codes to indicate the success or failure of an API request.
-In general: Codes in the 2xx range indicate success.
-Codes in the 4xx range indicate an error that failed given the information provided (e.g., a required parameter
-was omitted, a charge failed, etc.).
-Codes in the 5xx range indicate an error with Edgee's servers.
+Edgee uses conventional HTTP response codes to indicate the success or failure of an API request. In general: Codes in the 2xx range indicate success. Codes in the 4xx range indicate an error that failed given the information provided (e.g., a required parameter was omitted, authentication failed, etc.). Codes in the 5xx range indicate an error with Edgee's servers.
-Some 4xx errors that could be handled programmatically include
-an error code that briefly explains the error reported.
+When an error occurs, the API returns a JSON object with an `error` field containing details about what went wrong.
-### Parameters
+## Error Response Format
-
- The type of error returned.
+
+ The error object.
- One of invalid_request_error, not_found_error, creation_error,
- update_error, deletion_error, forbidden_error, or authentication_error.
+
+ A machine-readable error code that briefly explains the error reported.
+
+
+
+ A human-readable message providing more details about the error.
+
-
- A human-readable message providing more details about the error.
+
+```json Error Response Example
+{
+ "error": {
+ "code": "bad_model_id",
+ "message": "Invalid model ID: 'invalid-model'"
+ }
+}
+```
+
+
+## HTTP Status Code Summary
+
+Below is a summary of the HTTP status codes that Edgee API uses.
+
+| HTTP Code | Status | Description |
+| --------- | ------ | ----------- |
+| 200 | OK | Everything worked as expected. |
+| 400 | Bad Request | The request was unacceptable, often due to missing a required parameter, invalid model ID, model not found, or provider not supported. |
+| 401 | Unauthorized | No valid API key provided, or the Authorization header is missing or malformed. |
+| 403 | Forbidden | The API key doesn't have permissions to perform the request. This can occur if the key is inactive, expired, or the requested model is not allowed for this key. |
+| 404 | Not Found | The requested resource doesn't exist. |
+| 429 | Too Many Requests | Too many requests hit the API too quickly, or usage limit exceeded. We recommend an exponential backoff of your requests. |
+| 500, 502, 503, 504 | Server Errors | Something went wrong on Edgee's end. (These are rare.) |
+
+## Error Codes
+
+### 400 Bad Request
+
+
+ One of the following error codes:
+
+ - `bad_model_id`: The model ID format is invalid
+ - `model_not_found`: The requested model does not exist or is not available
+ - `provider_not_supported`: The requested provider is not supported for the specified model
-
- If the error is parameter-specific, this will contain a list of the parameters that were invalid.
+
+```json Bad Model ID
+{
+ "error": {
+ "code": "bad_model_id",
+ "message": "Invalid model ID: 'invalid-model'"
+ }
+}
+```
+
+```json Model Not Found
+{
+ "error": {
+ "code": "model_not_found",
+ "message": "Model 'openai/gpt-1' not found"
+ }
+}
+```
+
+```json Provider Not Supported
+{
+ "error": {
+ "code": "provider_not_supported",
+ "message": "Provider 'anthropic' is not supported for model 'openai/gpt-4o'"
+ }
+}
+```
+
+
+### 401 Unauthorized
+
+
+ Always `"unauthorized"`.
-## HTTP Status Code Summary
+
+```json Missing Authorization Header
+{
+ "error": {
+ "code": "unauthorized",
+ "message": "Missing Authorization header"
+ }
+}
+```
-Bellow is a summary of the HTTP status codes that Edgee API uses.
-
-| HTTP Code | Status | Description |
-| ------------------ | ------ | ----------- |
-| 200 | OK | Everything worked as expected. |
-| 400 | Bad Request | The request was unacceptable, often due to missing a required parameter. |
-| 401 | Unauthorized | No valid API key provided. |
-| 402 | Request Failed | The parameters were valid but the request failed. |
-| 403 | Forbidden | The API key doesn't have permissions to perform the request. |
-| 404 | Not Found | The requested resource doesn't exist. |
-| 409 | Conflict | The request conflicts with another request (perhaps due to using the same idempotent key). |
-| 429 | Too Many Requests | Too many requests hit the API too quickly. We recommend an exponential backoff of your requests. |
-| 500, 502, 503, 504 | Server Errors | Something went wrong on Edgee's end. (These are rare.) |
+```json Invalid Authorization Format
+{
+ "error": {
+ "code": "unauthorized",
+ "message": "Invalid Authorization header format"
+ }
+}
+```
+
+```json Failed to Retrieve API Key
+{
+ "error": {
+ "code": "unauthorized",
+ "message": "Failed to retrieve API key: "
+ }
+}
+```
+
+
+### 403 Forbidden
+
+
+ Always `"forbidden"`.
+
+
+
+```json Inactive Key
+{
+ "error": {
+ "code": "forbidden",
+ "message": "API key is inactive"
+ }
+}
+```
+
+```json Expired Key
+{
+ "error": {
+ "code": "forbidden",
+ "message": "API key has expired"
+ }
+}
+```
+
+```json Model Not Allowed
+{
+ "error": {
+ "code": "forbidden",
+ "message": "Model 'openai/gpt-4o' is not allowed for this API key"
+ }
+}
+```
+
+
+### 429 Too Many Requests
+
+
+ Always `"usage_limit_exceeded"`.
+
+
+
+```json Usage Limit Exceeded
+{
+ "error": {
+ "code": "usage_limit_exceeded",
+ "message": "Usage limit exceeded: 1000.00 / 1000 tokens used"
+ }
+}
+```
+
+```json No Credits Remaining
+{
+ "error": {
+ "code": "usage_limit_exceeded",
+ "message": "Organization has no credits remaining"
+ }
+}
+```
+
+
+### 500 Internal Server Error
+
+When a server error occurs, the API may return a generic error response. These errors are rare and typically indicate an issue on Edgee's side.
-```json Response Example
+```json Server Error
{
"error": {
- "type": "invalid_request_error",
- "params": [
- {
- "param": "name",
- "message": "This field is required"
- }
- ],
- "message": "Parameter error"
+ "code": "internal_error",
+ "message": "An internal error occurred. Please try again later."
}
}
```
+## Handling Errors
+
+When you receive an error response:
+
+1. **Check the HTTP status code** to understand the general category of the error
+2. **Read the error code** (`error.code`) to understand the specific issue
+3. **Review the error message** (`error.message`) for additional context
+4. **Take appropriate action**:
+ - **400 errors**: Fix the request parameters and retry
+ - **401 errors**: Check your API key and authentication headers
+ - **403 errors**: Verify your API key permissions and status
+ - **429 errors**: Implement exponential backoff and retry logic
+ - **5xx errors**: Retry after a delay, or contact support if the issue persists
+
+## Rate Limiting
+
+If you exceed the rate limits, you will receive a `429 Too Many Requests` response. We recommend implementing exponential backoff when you encounter rate limit errors:
+
+1. Wait for the time specified in the `Retry-After` header (if present)
+2. Retry the request with exponential backoff
+3. Reduce the rate of requests to stay within limits
diff --git a/api-reference/index.mdx b/api-reference/index.mdx
index d8be12b..72d73f6 100644
--- a/api-reference/index.mdx
+++ b/api-reference/index.mdx
@@ -1,11 +1,12 @@
---
-title: 'Introduction'
-description: 'A brief introduction to the Edgee API.'
+title: 'Overview'
+description: 'A brief introduction to the Edgee AI Gateway API.'
+icon: book
---
-Welcome to the Edgee API documentation. This guide will help you understand how to interact with the Edgee API to create,
-retrieve, update, and delete Edgee resources through HTTP requests.
+Welcome to the Edgee AI Gateway API documentation. This guide will help you understand how to interact with the Edgee API to create chat completions and manage models through HTTP requests.
+Edgee is an edge-native AI Gateway with private model hosting, automatic model selection, cost audits/alerts, and edge tools. The API is **OpenAI-compatible**, providing one API for any model and any provider.
## Base URL
@@ -17,20 +18,46 @@ https://api.edgee.ai
## Authentication
-The Edgee API uses bearer authentication. When making requests, you must include your API token in the `Authorization`
-header in the format `Bearer `. For more details, please refer to the [Authentication](./authentication) page.
+The Edgee API uses bearer authentication. When making requests, you must include your API Key in the `Authorization` header in the format `Bearer `. For more details, please refer to the [Authentication](./authentication) page.
## Errors
-When an error occurs, the Edgee API responds with a conventional HTTP response code and a JSON object containing more
-details about the error. For more information, please refer to the [Errors](./errors) page.
+When an error occurs, the Edgee API responds with a conventional HTTP response code and a JSON object containing more details about the error. For more information, please refer to the [Errors](./errors) page.
## Rate Limiting
-Please note that the Edgee API has rate limits to prevent abuse and ensure service stability. If you exceed these limits,
-your requests will be throttled and you will receive a `429 Too Many Requests` response.
+Please note that the Edgee has its own rate limit technology to prevent abuse and ensure service stability.
+If you exceed these limits, your requests will be throttled and you will receive a `429 Too Many Requests` response.
+Additionally, usage limits may be enforced based on your API key configuration.
+
+## Features
+
+
+
+ **OpenAI-Compatible API**
+
+ Fully compatible with the OpenAI API format, making it easy to switch between providers or use multiple providers through a single interface.
+
+
+ **Multi-Provider Support**
+
+ Access models from multiple providers (OpenAI, Anthropic, etc.) through a single API endpoint. Simply specify the model using the format `{author_id}/{model_id}`.
+
+
+ **Streaming Support**
+
+ Both streaming and non-streaming responses are supported. Enable streaming by setting `stream: true` to receive Server-Sent Events (SSE) with partial message deltas.
+
+
+ **Function Calling**
+
+ The API supports function calling (tools) that allows models to call external functions, enabling more interactive and powerful applications.
+
+
+ **Usage Tracking**
+
+ Every response includes detailed usage statistics: token counts (prompt, completion, total), cached tokens, and reasoning tokens.
+
+
----
-We hope this guide helps you get started with the Edgee API. If you have any questions, please don't hesitate to reach
-out to our support team.
diff --git a/api-reference/models.mdx b/api-reference/models.mdx
new file mode 100644
index 0000000..8c0dfb2
--- /dev/null
+++ b/api-reference/models.mdx
@@ -0,0 +1,7 @@
+---
+title: 'Models'
+description: 'List all available models in the Edgee AI Gateway'
+openapi: 'GET /v1/models'
+---
+
+Lists the currently available models, and provides basic information about each one such as the owner and availability. Returns only active models.
diff --git a/api-reference/openapi.json b/api-reference/openapi.json
index ca4d9a3..8ed12bf 100644
--- a/api-reference/openapi.json
+++ b/api-reference/openapi.json
@@ -2,11 +2,17 @@
"openapi": "3.0.1",
"info": {
"title": "Edgee API",
- "version": "1"
+ "version": "1.0.0",
+ "description": "Edgee is an edge-native AI Gateway with private model hosting, automatic model selection, cost audits/alerts, and edge tools. This API is OpenAI-compatible, providing one API for any model and any provider."
},
"servers": [
{
- "url": "https://api.edgee.ai"
+ "url": "https://api.edgee.ai",
+ "description": "Edgee AI Gateway"
+ },
+ {
+ "url": "http://localhost:7676",
+ "description": "Edgee AI Gateway (Local Development)"
}
],
"security": [
@@ -15,46 +21,75 @@
}
],
"paths": {
- "/v1/projects/{id}/purge-cache": {
+ "/v1/chat/completions": {
"post": {
- "operationId": "purgeProjectCache",
- "summary": "Purge cache for a project",
- "description": "Purge the cache for a specific project. You can purge all cache or purge cache for a specific path. When purging by path, the cache for all domains associated with the project will be purged for that path.",
- "parameters": [
- {
- "name": "id",
- "in": "path",
- "required": true,
- "schema": {
- "type": "string"
- },
- "description": "The project ID"
- }
- ],
+ "operationId": "createChatCompletion",
+ "summary": "Create chat completion",
+ "description": "Creates a completion for the chat message. Supports both streaming and non-streaming responses. The API is OpenAI-compatible and works with any model and provider.",
+ "tags": ["Chat"],
"requestBody": {
+ "required": true,
"content": {
"application/json": {
"schema": {
- "$ref": "#/components/schemas/PurgeCacheInput"
+ "$ref": "#/components/schemas/ChatCompletionRequest"
}
}
- },
- "required": true
+ }
},
"responses": {
"200": {
- "description": "Cache purged successfully",
+ "description": "Chat completion created successfully",
"content": {
"application/json": {
"schema": {
- "type": "object",
- "properties": {
- "message": {
- "type": "string",
- "example": "Cache purged"
+ "$ref": "#/components/schemas/ChatCompletionResponse"
+ },
+ "example": {
+ "id": "chatcmpl-123",
+ "object": "chat.completion",
+ "created": 1677652288,
+ "model": "openai/gpt-4o",
+ "choices": [
+ {
+ "index": 0,
+ "message": {
+ "role": "assistant",
+ "content": "Hello! How can I assist you today?"
+ },
+ "finish_reason": "stop"
+ }
+ ],
+ "usage": {
+ "prompt_tokens": 10,
+ "completion_tokens": 10,
+ "total_tokens": 20,
+ "input_tokens_details": {
+ "cached_tokens": 0
+ },
+ "output_tokens_details": {
+ "reasoning_tokens": 0
}
}
}
+ },
+ "text/event-stream": {
+ "schema": {
+ "type": "string",
+ "format": "binary",
+ "description": "Server-Sent Events stream. Each event is a JSON object prefixed with 'data: ' and followed by two newlines. The stream consists of multiple `ChatCompletionChunk` objects, and optionally a final chunk with usage statistics if `stream_options.include_usage` is true."
+ },
+ "examples": {
+ "contentChunk": {
+ "value": "data: {\"id\":\"chatcmpl-123\",\"object\":\"chat.completion.chunk\",\"created\":1677652288,\"model\":\"openai/gpt-4o\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"Hello\"},\"finish_reason\":null}]}\n\n"
+ },
+ "roleChunk": {
+ "value": "data: {\"id\":\"chatcmpl-123\",\"object\":\"chat.completion.chunk\",\"created\":1677652288,\"model\":\"openai/gpt-4o\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\"},\"finish_reason\":null}]}\n\n"
+ },
+ "finalChunk": {
+ "value": "data: {\"id\":\"chatcmpl-123\",\"object\":\"chat.completion.chunk\",\"created\":1677652288,\"model\":\"openai/gpt-4o\",\"choices\":[{\"index\":0,\"delta\":{},\"finish_reason\":\"stop\"}],\"usage\":{\"prompt_tokens\":10,\"completion_tokens\":10,\"total_tokens\":20,\"input_tokens_details\":{\"cached_tokens\":0},\"output_tokens_details\":{\"reasoning_tokens\":0}}}\n\n"
+ }
+ }
}
}
},
@@ -64,26 +99,158 @@
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
+ },
+ "examples": {
+ "badModelId": {
+ "value": {
+ "error": {
+ "code": "bad_model_id",
+ "message": "Invalid model ID: 'invalid-model'"
+ }
+ }
+ },
+ "modelNotFound": {
+ "value": {
+ "error": {
+ "code": "model_not_found",
+ "message": "Model 'openai/gpt-1' not found"
+ }
+ }
+ },
+ "providerNotSupported": {
+ "value": {
+ "error": {
+ "code": "provider_not_supported",
+ "message": "Provider 'anthropic' is not supported for model 'openai/gpt-4o'"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized - missing or invalid API key",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ },
+ "example": {
+ "error": {
+ "code": "unauthorized",
+ "message": "Missing Authorization header"
+ }
}
}
}
},
"403": {
- "description": "Forbidden - insufficient permissions",
+ "description": "Forbidden - API key is inactive, expired, or model not allowed",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
+ },
+ "examples": {
+ "inactiveKey": {
+ "value": {
+ "error": {
+ "code": "forbidden",
+ "message": "API key is inactive"
+ }
+ }
+ },
+ "expiredKey": {
+ "value": {
+ "error": {
+ "code": "forbidden",
+ "message": "API key has expired"
+ }
+ }
+ },
+ "modelNotAllowed": {
+ "value": {
+ "error": {
+ "code": "forbidden",
+ "message": "Model 'openai/gpt-4o' is not allowed for this API key"
+ }
+ }
+ }
}
}
}
},
- "404": {
- "description": "Project not found",
+ "429": {
+ "description": "Too many requests - usage limit exceeded",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ErrorResponse"
+ },
+ "example": {
+ "error": {
+ "code": "usage_limit_exceeded",
+ "message": "Usage limit exceeded: 1000.00 / 1000 tokens used"
+ }
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal server error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorResponse"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/v1/models": {
+ "get": {
+ "operationId": "listModels",
+ "summary": "List models",
+ "description": "Lists the currently available models, and provides basic information about each one such as the owner and availability. Returns only active models.",
+ "tags": ["Models"],
+ "parameters": [
+ {
+ "name": "provider",
+ "in": "query",
+ "description": "Filter models by provider (optional, currently not implemented)",
+ "required": false,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "List of available models",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ModelsResponse"
+ },
+ "example": {
+ "object": "list",
+ "data": [
+ {
+ "id": "openai/gpt-4o",
+ "object": "model",
+ "created": 1677610602,
+ "owned_by": "openai"
+ },
+ {
+ "id": "anthropic/claude-3-opus",
+ "object": "model",
+ "created": 1677610602,
+ "owned_by": "anthropic"
+ }
+ ]
}
}
}
@@ -103,16 +270,453 @@
}
},
"components": {
- "parameters": {
- },
"schemas": {
+ "ChatCompletionRequest": {
+ "type": "object",
+ "required": ["model", "messages"],
+ "properties": {
+ "model": {
+ "type": "string",
+ "description": "ID of the model to use. Format: `{author_id}/{model_id}` (e.g. `openai/gpt-4o`)",
+ "example": "openai/gpt-4o"
+ },
+ "messages": {
+ "type": "array",
+ "description": "A list of messages comprising the conversation so far.",
+ "items": {
+ "$ref": "#/components/schemas/Message"
+ },
+ "minItems": 1
+ },
+ "max_tokens": {
+ "type": "integer",
+ "description": "The maximum number of tokens that can be generated in the chat completion.",
+ "minimum": 1
+ },
+ "stream": {
+ "type": "boolean",
+ "description": "If set, partial message deltas will be sent, as in OpenAI. Streamed chunks are sent as Server-Sent Events (SSE).",
+ "default": false
+ },
+ "stream_options": {
+ "type": "object",
+ "description": "Options for streaming response.",
+ "properties": {
+ "include_usage": {
+ "type": "boolean",
+ "description": "If set, an additional `[DONE]` message will be sent with usage statistics when the stream is finished."
+ }
+ }
+ },
+ "tools": {
+ "type": "array",
+ "description": "A list of tools the model may call. Currently, only `function` type is supported.",
+ "items": {
+ "$ref": "#/components/schemas/Tool"
+ }
+ },
+ "tool_choice": {
+ "oneOf": [
+ {
+ "type": "string",
+ "enum": ["none", "auto"],
+ "description": "Controls which (if any) tool is called by the model. `none` means the model will not call any tool. `auto` means the model can pick between generating a message or calling a tool."
+ },
+ {
+ "$ref": "#/components/schemas/ToolChoiceSpecific"
+ }
+ ],
+ "description": "Controls which tool is called by the model."
+ }
+ }
+ },
+ "Message": {
+ "type": "object",
+ "required": ["role"],
+ "properties": {
+ "role": {
+ "type": "string",
+ "enum": ["system", "user", "assistant", "tool", "developer"],
+ "description": "The role of the message author. Required properties vary by role:\n- `system`, `user`, `developer`: requires `content`\n- `assistant`: `content` is optional (can be empty if `tool_calls` is present)\n- `tool`: requires `content` and `tool_call_id`"
+ },
+ "content": {
+ "type": "string",
+ "description": "The contents of the message. Required for all roles except `assistant` (where it can be empty if `tool_calls` is present). For `assistant` role, defaults to empty string if not provided."
+ },
+ "name": {
+ "type": "string",
+ "description": "An optional name for the participant. Provides the model information to differentiate between participants of the same role. Used for `system`, `user`, `assistant`, and `developer` roles."
+ },
+ "tool_call_id": {
+ "type": "string",
+ "description": "The ID of the tool call that this message is responding to. Required for `tool` role only."
+ },
+ "refusal": {
+ "type": "string",
+ "description": "The refusal message from the model, if any. Used for `assistant` role only."
+ },
+ "tool_calls": {
+ "type": "array",
+ "description": "The tool calls made by the assistant. Used for `assistant` role only.",
+ "items": {
+ "$ref": "#/components/schemas/ToolCall"
+ }
+ }
+ }
+ },
+ "Tool": {
+ "type": "object",
+ "required": ["type", "function"],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": ["function"],
+ "description": "The type of the tool. Currently, only `function` is supported."
+ },
+ "function": {
+ "$ref": "#/components/schemas/FunctionDefinition"
+ }
+ }
+ },
+ "FunctionDefinition": {
+ "type": "object",
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64."
+ },
+ "description": {
+ "type": "string",
+ "description": "A description of what the function does, used by the model to choose when and how to call the function."
+ },
+ "parameters": {
+ "type": "object",
+ "description": "The parameters the functions accepts, described as a JSON Schema object. See the guide for examples, and the JSON Schema reference for documentation about the format.",
+ "additionalProperties": true
+ }
+ }
+ },
+ "ToolChoiceSpecific": {
+ "type": "object",
+ "required": ["type", "function"],
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": ["function"],
+ "description": "The type of the tool."
+ },
+ "function": {
+ "$ref": "#/components/schemas/ToolChoiceFunction"
+ }
+ }
+ },
+ "ToolChoiceFunction": {
+ "type": "object",
+ "required": ["name"],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the function to call."
+ }
+ }
+ },
+ "ToolCall": {
+ "type": "object",
+ "required": ["id", "type", "function"],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "The ID of the tool call."
+ },
+ "type": {
+ "type": "string",
+ "enum": ["function"],
+ "description": "The type of the tool call."
+ },
+ "function": {
+ "$ref": "#/components/schemas/FunctionCall"
+ }
+ }
+ },
+ "FunctionCall": {
+ "type": "object",
+ "required": ["name", "arguments"],
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The name of the function to call."
+ },
+ "arguments": {
+ "type": "string",
+ "description": "The arguments to call the function with, as JSON."
+ }
+ }
+ },
+ "ChatCompletionResponse": {
+ "type": "object",
+ "required": ["id", "object", "created", "model", "choices", "usage"],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "A unique identifier for the chat completion.",
+ "example": "chatcmpl-123"
+ },
+ "object": {
+ "type": "string",
+ "enum": ["chat.completion"],
+ "description": "The object type, which is always `chat.completion`."
+ },
+ "created": {
+ "type": "integer",
+ "description": "The Unix timestamp (in seconds) of when the chat completion was created.",
+ "example": 1677652288
+ },
+ "model": {
+ "type": "string",
+ "description": "The model used for the chat completion.",
+ "example": "openai/gpt-4o"
+ },
+ "choices": {
+ "type": "array",
+ "description": "A list of chat completion choices. Can be more than one if n is greater than 1.",
+ "items": {
+ "$ref": "#/components/schemas/ChatCompletionChoice"
+ }
+ },
+ "usage": {
+ "$ref": "#/components/schemas/Usage"
+ }
+ }
+ },
+ "ChatCompletionChoice": {
+ "type": "object",
+ "required": ["index", "message"],
+ "properties": {
+ "index": {
+ "type": "integer",
+ "description": "The index of the choice in the list of choices.",
+ "minimum": 0
+ },
+ "message": {
+ "$ref": "#/components/schemas/AssistantMessage"
+ },
+ "finish_reason": {
+ "type": "string",
+ "enum": ["stop", "length", "content_filter", "tool_calls"],
+ "description": "The reason the model stopped generating tokens. This will be `stop` if the model hit a natural stop point or a provided stop sequence, `length` if the maximum number of tokens specified in the request was reached, `content_filter` if content was omitted due to a flag from our content filters, or `tool_calls` if the model called a tool."
+ }
+ }
+ },
+ "Usage": {
+ "type": "object",
+ "description": "Usage statistics for the completion. In streaming responses, this is only present in the final chunk when `stream_options.include_usage` is true.",
+ "required": ["prompt_tokens", "completion_tokens", "total_tokens", "input_tokens_details", "output_tokens_details"],
+ "properties": {
+ "prompt_tokens": {
+ "type": "integer",
+ "description": "Number of tokens in the prompt.",
+ "minimum": 0
+ },
+ "completion_tokens": {
+ "type": "integer",
+ "description": "Number of tokens in the generated completion.",
+ "minimum": 0
+ },
+ "total_tokens": {
+ "type": "integer",
+ "description": "Total number of tokens used in the request (prompt + completion).",
+ "minimum": 0
+ },
+ "input_tokens_details": {
+ "$ref": "#/components/schemas/InputTokenDetails"
+ },
+ "output_tokens_details": {
+ "$ref": "#/components/schemas/OutputTokenDetails"
+ }
+ }
+ },
+ "InputTokenDetails": {
+ "type": "object",
+ "description": "Additional details about input tokens.",
+ "properties": {
+ "cached_tokens": {
+ "type": "integer",
+ "description": "Number of cached tokens in the input.",
+ "minimum": 0
+ }
+ }
+ },
+ "OutputTokenDetails": {
+ "type": "object",
+ "description": "Additional details about output tokens.",
+ "properties": {
+ "reasoning_tokens": {
+ "type": "integer",
+ "description": "Number of reasoning tokens in the output.",
+ "minimum": 0
+ }
+ }
+ },
+ "ModelsResponse": {
+ "type": "object",
+ "required": ["object", "data"],
+ "properties": {
+ "object": {
+ "type": "string",
+ "enum": ["list"],
+ "description": "The object type, which is always `list`."
+ },
+ "data": {
+ "type": "array",
+ "description": "The list of models.",
+ "items": {
+ "$ref": "#/components/schemas/Model"
+ }
+ }
+ }
+ },
+ "Model": {
+ "type": "object",
+ "required": ["id", "object", "created", "owned_by"],
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "The model identifier, which can be referenced in the API. Format: `{author_id}/{model_id}`.",
+ "example": "openai/gpt-4o"
+ },
+ "object": {
+ "type": "string",
+ "enum": ["model"],
+ "description": "The object type, which is always `model`."
+ },
+ "created": {
+ "type": "integer",
+ "description": "The Unix timestamp (in seconds) when the model was created.",
+ "example": 1677610602
+ },
+ "owned_by": {
+ "type": "string",
+ "description": "The organization that owns the model.",
+ "example": "openai"
+ }
+ }
+ },
+ "ChatCompletionChunk": {
+ "type": "object",
+ "required": ["id", "object", "created", "model", "choices"],
+ "description": "A streaming chunk in the chat completion response. Used when `stream: true` in the request.",
+ "properties": {
+ "id": {
+ "type": "string",
+ "description": "A unique identifier for the chat completion chunk.",
+ "example": "chatcmpl-123"
+ },
+ "object": {
+ "type": "string",
+ "enum": ["chat.completion.chunk"],
+ "description": "The object type, which is always `chat.completion.chunk` for streaming responses."
+ },
+ "created": {
+ "type": "integer",
+ "description": "The Unix timestamp (in seconds) of when the chat completion was created.",
+ "example": 1677652288
+ },
+ "model": {
+ "type": "string",
+ "description": "The model used for the chat completion.",
+ "example": "openai/gpt-4o"
+ },
+ "choices": {
+ "type": "array",
+ "description": "A list of chat completion choices for this chunk.",
+ "items": {
+ "$ref": "#/components/schemas/ChatCompletionChunkChoice"
+ }
+ },
+ "usage": {
+ "$ref": "#/components/schemas/Usage"
+ }
+ }
+ },
+ "ChatCompletionChunkChoice": {
+ "type": "object",
+ "required": ["index", "delta"],
+ "description": "A choice in a streaming chat completion chunk.",
+ "properties": {
+ "index": {
+ "type": "integer",
+ "description": "The index of the choice in the list of choices.",
+ "minimum": 0
+ },
+ "delta": {
+ "$ref": "#/components/schemas/Delta",
+ "description": "A delta representing the change in the message content. The first chunk typically contains `role`, subsequent chunks contain `content`."
+ },
+ "finish_reason": {
+ "type": "string",
+ "enum": ["stop", "length", "content_filter", "tool_calls"],
+ "description": "The reason the model stopped generating tokens. This will be `null` for all chunks except the final one. This will be `stop` if the model hit a natural stop point or a provided stop sequence, `length` if the maximum number of tokens specified in the request was reached, `content_filter` if content was omitted due to a flag from our content filters, or `tool_calls` if the model called a tool."
+ }
+ }
+ },
+ "Delta": {
+ "type": "object",
+ "description": "Represents a change in message content. The first chunk typically contains `role`, subsequent chunks contain `content`.",
+ "properties": {
+ "role": {
+ "type": "string",
+ "description": "The role of the message author. Typically present only in the first chunk.",
+ "example": "assistant"
+ },
+ "content": {
+ "type": "string",
+ "description": "The content of the message delta. Present in content chunks.",
+ "example": "Hello"
+ }
+ }
+ },
+ "ErrorResponse": {
+ "type": "object",
+ "required": ["error"],
+ "description": "Error response.",
+ "$ref": "#/components/schemas/ErrorResponse",
+ "properties": {
+ "error": {
+ "type": "object",
+ "required": ["code", "message"],
+ "properties": {
+ "code": {
+ "type": "string",
+ "description": "A machine-readable error code.",
+ "examples": ["bad_model_id", "model_not_found", "provider_not_supported", "unauthorized", "forbidden", "usage_limit_exceeded"]
+ },
+ "message": {
+ "type": "string",
+ "description": "A human-readable error message."
+ }
+ }
+ }
+ }
+ }
},
"securitySchemes": {
"bearerAuth": {
"type": "http",
"scheme": "bearer",
- "description": "Bearer authentication header of the form `Bearer `, where `` is your auth token. More info [here]('/docs/api-reference/authentication')"
+ "bearerFormat": "JWT",
+ "description": "Bearer authentication header of the form `Bearer `, where `` is your API key. More info [here](/docs/api-reference/authentication)"
}
}
- }
+ },
+ "tags": [
+ {
+ "name": "Chat",
+ "description": "Chat completion endpoints"
+ },
+ {
+ "name": "Models",
+ "description": "Model management endpoints"
+ }
+ ]
}
diff --git a/docs.json b/docs.json
index 3d5bc52..479bd0f 100644
--- a/docs.json
+++ b/docs.json
@@ -83,10 +83,50 @@
"group": "SDK Documentation",
"pages": [
"sdk/index",
- "sdk/typescript/index",
- "sdk/python/index",
- "sdk/rust/index",
- "sdk/go/index",
+ {
+ "group": "TypeScript",
+ "icon": "https://d3gk2c5xim1je2.cloudfront.net/devicon/typescript.svg",
+ "pages": [
+ "sdk/typescript/index",
+ "sdk/typescript/configuration",
+ "sdk/typescript/send",
+ "sdk/typescript/stream",
+ "sdk/typescript/tools"
+ ]
+ },
+ {
+ "group": "Python",
+ "icon": "python",
+ "pages": [
+ "sdk/python/index",
+ "sdk/python/configuration",
+ "sdk/python/send",
+ "sdk/python/stream",
+ "sdk/python/tools"
+ ]
+ },
+ {
+ "group": "Rust",
+ "icon": "rust",
+ "pages": [
+ "sdk/rust/index",
+ "sdk/rust/configuration",
+ "sdk/rust/send",
+ "sdk/rust/stream",
+ "sdk/rust/tools"
+ ]
+ },
+ {
+ "group": "Go",
+ "icon": "golang",
+ "pages": [
+ "sdk/go/index",
+ "sdk/go/configuration",
+ "sdk/go/send",
+ "sdk/go/stream",
+ "sdk/go/tools"
+ ]
+ },
"sdk/openai/index"
]
}
@@ -95,20 +135,21 @@
{
"tab": "API Reference",
"icon": "terminal",
- "hidden": true,
+
"groups": [
{
- "group": "API Documentation",
+ "group": "Introduction",
"pages": [
- "api-reference/index",
- "api-reference/authentication",
- "api-reference/errors",
- {
- "group": "Caching",
- "pages": [
- "api-reference/caching/purge-cache"
- ]
- }
+ "api-reference/index",
+ "api-reference/authentication",
+ "api-reference/errors"
+ ]
+ },
+ {
+ "group": "Endpoints",
+ "pages": [
+ "api-reference/chat-completion",
+ "api-reference/models"
]
}
]
diff --git a/images/byok-dark.png b/images/byok-dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..6ffc6abf36356d1099eed7d831064bad8f758b31
GIT binary patch
literal 310286
zcmeGDWpo_BlPC<^jyZ{$nVFfH#>^ZuGses~<}tGqGbCna7*k9!GdpHx_T%5~-rYU-
zp8da@?{A;(kw#KUB~__N-9TkU>CcFGh!7AEp8+xwst^$H=@1Ywf$*^JCB*FxoDdM7
zy@7B+4$17S?v=5D+rJ6fHPywPCDWJylX@cnJ~NeFYQ{nushsW8gJeq^t~7
zD4MC5a!o-rV&xZ!>ii0lC_INt&>trS%p#pRRA?+TZT9VN*F_FG~&VF+^a}Y7K
z(jrXOeLH@uDyGC3hJheaK`BA_6RaPJ3>CveNZn1Y)_W<=k+*dmz=X_loxjybvGCCwsWXE}{^!%dr>5Z)en
zG*LbbP%|5JRewzXS{ylF70-)hHb5yRAI3vsn2iEi0}DpIJYJ~w&r1%LcK`>*%cB;I
z_CuLu$eF-O)%+4gCL4RBmxQ;D63Uh=7;JNs~
zNA}Qs9;6?dA1I=6%A-R8jMunm&gGa8mU3rwpdJGr-VMG;^7hECecIyj@;~lwc<^#^
zDZjoTvo=uArc-Peh$hA>ih^7J*b9jb4S}WHoeE18!a(A1QhpZvrY>0
znB7Uz#4sM3$W#>a9-Ry|0oh=0eV!ibA>oZLRKsOURMFiH;^4(kHpT87dP^S#)@36=
zGB44LB^de~hixlB0vw?L;W`wgu=sZN0C~&b7bNc~T!4cEk|aK-fJOTdNeU*(XLJaB
z+A#3s5qRv`jj3~v4-)8nLeE86f=5P}M>q*xP6CJ3lB&ePoG1&Ib_rPv&%reXXI3@~
zpMIYG&NdGI9QffBYH)L-)5%P0$mMBUQ!|WH;>i*B*(u`jg+>u0nJs2Zx(3&~C_E?p
z=v!3noba49rtOkZM@xvH_~72FvLC5H#OE6@mN8tl>jK~yYA$s41J+jp+iun&LH_tuB!#@i%
z+CXFrGbj&TY7kTkploD?Ams`98GRZJ`aC*_+YHIP0S6^Y6AA51f*>C{Y1!+=^g*ph
zo&^~r2(6mn2jm|k^aaH7Zii~(nGh-`v}_pc9&;zcm7uzk5A6`E8-({UB=88|Nk2&t
zvx+jH`hanb$%SM{(Bi-(02#W(AQ==GHuQ}6WD9QZ>XIw
z-lMe>RP`R6Pv2`iL$1XJkpG4chxQ4k4wA-^9wL#a#6XorSVo9|x7?_k5%rX&K+BM@
z&FA;UN{ZA0
z42|!QxUlJnF;S!?dL+h!suJ=Nh1ED{Q!$ieDI{ew6m_H)rK}6}^WBt%)EY|X)E#XI
zIHUREb)|k5<$hl)>QqrvV^_OUj@Cr47}KCvTdw$Oa1yj6?QZYR?_TL0)hgy!_K0+Y
ze%Lg-{@aR!K9iU+BUM^YwxT#Ef3?K#w~-Z(%{fOXo+}3($00|hRePb@eySUiA6ZAB
zfvm7dm&Dmrp_Q(+3+F>-9Va~pvhCW;@uZ1W>{QguuUXyv2DPK$Id=QR#+0w$8kK#5
zZZ%KTmf~@6`m%e>;c>2TmvJm{2>B!kZ3%M~Qx$>Z4mp}R4qxoQV6Q^2TDM}hO1m#-
z;7msio9?otvEH#evIu`>#~Z+IJMfO&K>*;aW6$SWc)&HLFU
z)@AUP3+Z5FiDJ((YgEvK8&bK+*VhsLF&rCtUHI8UeCGE!%Yak(re+^j9}&4}ff0Gx
zBwvA=)RzHyQ{iof?b(6B7=8sDDj_P9q*
zRy*R0;%u^tvE{pf72w?A;>0_}WBWcx7n?SlemCvd9syyICrMZ0cscBFQ)`tFl-MhJ
zNLj}t5^C_2JI~l!@>>SEhFvvG)=!ES?8P|Xy!`54liaDD{F6%G=l%lWU{rGp#0m>ZnQ
zbbC`GuPm>tjwa8hr)pnSKdz_xr_9GoKYBmn$BZY0m&PZ-KMO9kJZ(J8FFDWVuMyAd
zu7WLf&D2oUfg6Eafpa1!-S^#>-A|$xqPU`*qN_cXJ?z0sp(tX#Vw#~VJGd9n?KTD;
zr9S&Veoq@88rK;AF-Gn?={4VsHJz;aZmJdAfp3gU3M`F>2DJ}qfbQ~t6ckGk0;!~=
zCAB1kfw-9L?7R95s1UcgdPD(50}?+u}7JOLovn
zw`(H+DJ5|49CU~INB2ryByEXyD)~#kMwB6_AVC1`e}ol4kA?N7yQQwGdua|d8mepjqa?x46~rXi}~#C+5I
z^AW=wqv2hVK;5%^IJ+%<(U@ZA@oK3#-aU
z%5CPzu1doO)mk-o51li9+_w=YjzZl+%09m@Hy*`f#QWW4Ruk?^opt0Gp}VSk#MEMF(|qjQQe!W_
zTtnZfrD*WE+4~mnY^nbUb$;0ayx#22{>S2par38TldD75qu|@!gvah0C-v?YtinI)QB47GXXRK?+fkMd%3}2>U!!TC52o~VORgT8QdAKhll$;
zLgqqdArH)#vYWlfG%jZ3*FSe!a(B(Aaay%n9aU-VlL2+xKS!2#b4zod&Ro|0{0*N)
z-^6F7ZwFoT(1ZnF1a3Ya$SrCuSH-UPcCMa`ot&gxnm>0ILBJ;KWw}8ZoIwPpLPLBw
z#V^~|c}7fJ-uR)
z0_?4e-;-hy>gJk}>&|@r3dgyld;|3h>FIaNZ|d%l;uCLBc{3rpZ@K`|H;DyzSlvBs)+*t@2Q%pi@CXjtCgeMVuZcQdjW!z
zjE*Y=1Qz8#4vCDJD%pA*8eqwSXE|I{$E
zGO;lKXW#Fj0{@iqDO-D*+v!MH+rO{b`xrv394tHn{|4~?RQ=bG{|!|8zd+g8SXll$
z=zpvFzdQ(-xvDdO5ayn2vLCfKdB~!
zSXaMU{7y&$YY8Rw_w=33{<)yK-+yTSJ$=tZIax2#X3If9h(G`&MAbbZk8|LR)Ml3l
z@~Es^;RrE)t-+T@@}OX-W2mqAKppNuU{d#eX42n)cBZF`w1dn4_Kie*QSa8~wc%T3YD4T(d&6*ZmB-&~=+`s3<9eVxeUM|L&$E+mP-lBxA^y
zhN2Mpo7)KWn~@1zAp==$)@~Y;t3fI0fQb5?fAD$O-CWpQz*ue4fsnu|Noos
z|K;~LzM!vTid;|H9bWxioy?~jL+=vGWk=gZ?*DE3FG}D@M0$200&VvDFyw8l2G6Vi
zLZWVHzteMP|5yW&O4_pPqVzA=VWadP(9&ZrWfoq(r&wu)zu*XI%AjpYmJ9C=np-jd
zXXQ`Ao`MeD6Trw)&-*91U%uRk9}$(+)8T}5<|eANAE(Kuz3E511v$$DXwzp(Pd9r0
zLV|bKC~RnB$qQ_Sd#cmWHulgro!0?%$%HMYVB6RsjK4Q*IPnxE^$Sg!$Leos)y6Pb
zz1A&mUSRZoN&c)Qilr~v@^+OJ96bEi{?QZSUr^!yu5x-t;kkuI$2UR_p2s2)0}9*G
zrIgZ;)%DYZo{$!f^D`C*&OH`T2~Z*vHbkIdcoPgaME$>ilw^vRp)J}A{86#2EG(Ht
zM@OUtiFh@YkXEOa`m|1wrOZNmfc#4JH?sO38J>VY7+6Xir+mNICqXnBi56C30#qnO
zNs*`cE>ZGw?DV+&yXMPBH{K4;C60>tT?Kqn0RiX?-j;=WbMCnx>v2UD+$P(Nf-)0K
zEJg0^wF>0rLz*WRKABOfG1}W`x`E-{>E7kY2`eH@<7#AjXRe++V^|AUon$(N_=5-w||b
zS(OQ6(r++1Fi1F5Mes^?R>lGH}Y(raFM3l0sh#Ag4Hu$}Ajm+RRvlpZDg3)X=^
z(1wn)>5=%g+D$}jBJ(XgB~m#b#!liz`L2M$8I1guHex%Wmgmd35T-a$=ZDxn2uGD%
zROMsQo@(hqz#|}Vh|-H@d`!$)v)FDlj;!i)OBm5}hdK5d@spsY-2zNialX}Xj%uJT
zpLCxJ2W?R`33^7E-o{ruMw7fDozA`BWzvQ}VU%t;TYHuNRtPpUH`ek)AFIO>$-pUlBKknlGzw3G5ztR#aI*X9aUX3v^T^q&N-+xTM9Ad}GbqsORDL#+4^wBfC8TuLxwVi7i1$c*_vttvQgW_wE4Y=c
zNf#w$g^!O+@p8b}+3PuS1~5m%QMkt_GfekO)*1jh3dq+PSIGXtG9$=>j^pY9Z(}pL
z0Gt3Bcu5rblFl3r68`v`66VMm)QLb{Vny26t6$SE&JX5$P(%RoVMTG3ujMpwWU0-F
za&wrV_nojB$j$-PNCMI_^Z6POu#nx8m~4V=O!2V{0PuWSWoEU!fUOHSiaF1OPD;!f
z0d+gXjnJ#gCMJ(A+Aw~VaEv$Y0V5OD__v>@5!VFN*TFO^nAjXosk}mp!Y9b!MYw&_
z`+@H2J;Y|gt0Se4ad0ny0T3(*UQs8{Cz#CL9QYfBfqaw4VW(&AbHT;Uz9lLK76Vf7htpsI&r3E)kemP$LLJHhc-N_y
zN-=o#AT&Uk=Y2N?_N~KH`Nu&te<9j2-y;(i#%8x18?+^sXMake_(Wb*YGfi0o1$Bo
zVZzHt8^5<#oSw+L8$^D8bdN4yUw86-O6NP&mzD}`vMYH(3Vx_(LaXI=($*X=sBxhy
z4Df6mIDD+_Vwsq}#_R^`cqu84tjSINpw$M_x?RCx++fFovUj`D#5&H1*;(!Xmh%6?
z0da~!;n9Ugmt(52J;Ar`&vz>|{8kyH&`WnMyiGXdE2A9tNa)YSoO=+!$t2h$m<>r5
zJEX6JkxN#VP38hDDOD~nAF@-RM+Hg1pi3LkWE+!Z$N&jIxM0)^aTU-=@-i(0U3Xj#
z!an>oak$IB>JEvpdg=_kj{p9d|1Z^A$!eOY6SDS+>If*lAIf
zz~%|H47@rB1IE88<0SZnpwWeCLrmk7k&sw&3{`if_}h0R&aqnxb+$cyS$4f7eCmvt
ze{t8a-ww%iuOlcaatSQ586Fb+!CVHVW`s<1z9O*u>&5kw9pD@wC~#cJ&cqaFG)KAg
zLod-CaJ5M1$2Wie3u(w>0YBr`Q;4IQKcG~eUs}0YA_m+Ik&%t8;Z;9Gfs`mdx!k^S
z%~D6lRGHx`BgPKmCT_!0z~>edkx56DkD^ooE6FWmV1B3JhI2qwaLXzO@?=9&;YvDw
zpcsZ8SM33xCfhF;Mny?a$*@tvo5BvfRG01~mT^RJAVLR?KY!Z}4QX;7{0&MOH;I&CKZe3W*=LJwH_Gu`+d0M&vU961O
z66fv!)olXYZGw#HC$E?vTiv;ZW&$_8I6u}H%$*B`5^vLUk!zdfZ59cI)uv@kEf@Ym
zvIIiQ!q1rXfawi_MwEJK-qdz@gaUjC;UkBqEe9-=Hmek3?=NfD2@v
z1(x3aN$n`w(M-c5F1C4|b`xFH95)h{A1r{evpaGt!IY4UW~p3_FhJvi`D=F-KH>Mr
z004VXmnRZez+%a<;cZe{3h?vt-9`^0i9i04V_bAAM+UK+7GmR)8t
zDI=wIN+eyF#iNry;dC&d#*ih-eiKTa|BI<5MU6xun(1lsS~v`xiERv-y3{2imBcqQ{f#1GhqkFT+7b(;h>-D)M3o1BK+TW{`@EfAT5p^km{`kA
z$rOA@P3AV_!iB1MI12>xPpkn;Q37a-)ff^Z;D|1e5m%Vh7%9og;T9J&*t)doDtJ_?
zRK#bh3=M;s_0KVO`)Cz|1Dq%Xz5>`ljQkR!G~=?;&IXmx#>YM6rk&zq;Un1}DWBj3
zq||;Jvgw&&<@|O_NyJ6VR!xtM+36bNi?}*U$CQsMB1)XcGF~W6F2DkPy%t8Gq6Be%
z-YPg>Jbx`kC#K$wry&hPlTOOB<B4AtAR~V1zD89z^AY-I9==9w}-9
zZ@-jj_BdRD|C=^N>-w3Ea98r{64H)^8XIpmddkuN-ajY6hqftyms_y1*4Zq$NAtBj
zWUw-kVHW_ialqtI9cla0Xzd_j|&bk;#o;lO-#v%GYa5e
z@kvUk^&%G&x7nN}PBWPtXNaAr;l<(Q!ZeD>C7CXgwv3aMd(dX2cBQ^_xz+VRKDbTC
zkdJyPoJM8pmNll;I+4c|-VyGYU6TIVMyzPBMobR37Fs<-)51I==S5IOk=_h`y}*zw
zj4e#Pm-|u}SPj1*!E%wrC#}j4$5bQlQdh@%e4}(eI2B8yX*$fY+W4@3EUthq%o<-`
zsp5YMDzjB@C13jsle$|)`kMtJl|RjO1!dn0B$=(17apd(tN_G_;CU4An?f>#2GWjZ
zFr!;|Gi*6&>Gk9{MIPNj&uaG(3m$u}Y_BbZ=F`WK1d`w(v60^|v-=yS-(I^Ze
zgOWExhq2kRu|pFlzsq@jZN6;3#qr!ThewKMX^3rCr5dEKVTa-6C5x4z<{=&XSw9k3FL<;;_bZ8(>wm2^
zf=n~ILy!f{a@X+5rHMwAt`c(f6y90jWHQoj3Z?~D$7!!<_zDfKo9UNK;60=yO!0M0
zlQv9}3GUncF~`(5q;keZdMra(cZcADN46S
zyU4;oWD{{CD;hgAm&s;>FQL$jC}>1cB&agI`KIQ4Q_zNH7G}SM!1hkqMo;;YrGMN=
zXarylnU{i<_Nv$ofTznt@IoERi5B^TMZv%nBUQ3rJLYGi4x0HBQ*hi~qX<+?5}9mV
zlo*()Lxgw=Uuy0>i
z`KZDqnsz@SM$FTKcx)aqut==6p!}cxaH&RhgICA|L4_Hi7%eIMOJ3eK2mW8eT4dJS
z4AP9q|JOb=PdGwM7E6yn8-7*WDUN??#O;htwh0Xc@PQOs?P
zOaC_&G%qbJJQiw^-=G?(l^e1pQL5H?+XDKY-^`2KMpF8l@f8+)bX3@waCa$ee?Jp|
zX;|FB0kYS2Hc^#tb4X56YIk?6x+Sp5UoU>q)*}r_c}RxCEJ_H=3(x)&lHd@K9PZ-D
zi6fqtbe&i)Sb@yjzmtw8zp_SxvD_;=VU)s`Y&~p$KnST#=3{kI&<#Odd9Vms!W9pB
zdG(uyX$m~bpxq9o_mvW;j~1x=J&319fxg~mR*a8ZH{Xh*p90#;%gYJt54p!67sc^X
zbeg|z^eV0k*@2?M-t$#N;h<5zW#Pmn81~ngkQ@1a-cOgP|Fzxttr+$9P9i&>dvAti
zt~HYVW^b5wy%8i*vRSSBAX43PRuPaIPPemI@GOKkH?Ehta-9Ze{_!0bsXF>AFwpY6H(<|8L~=($*bkWq5{65BROMl
zIQ5cWtyYSenOPM4{t`puj1k<=4*v;0RJy$Ucr_;qk~n~QkOD|Ipg`kHrcP3$4>R1&
zqL2fhrEa^}3Ev(&m;Vg%B6^1fXSf%%H)v3Sh*or4XzwA=M)@}
zBeE&~_?DC<{UL)N1q~+>-`ibUT^oYR|AleN)w7L6^So{Xur*P#dhy#fv4G^iGxQfHTV#XD_|b
z`zK?tC4NF~N_@m)qhtsRH5N6N@gF4aU|ndVv0!!IrztbfORn#4(;d#!l=jM6I|=gf
za9OqbR=5t>u07!$K59nG?a&X_wAD{=WDGo?!pP#xN+^1&n&EZr`wu>0)IlcNB!=YY
zlPwT_CC_YLNn}d|k>b+&M@B^kcCZlFusXy4oX6OvdJRTh9}O>Q28&mZCtWsCn!6PC
z##8*jaTP5}QVr`lp%an148N>UKYD$q2efpP$Q}OKz!`g5cTQgDbX)F^IHc5Z!=U49
z466tH*fQrRnJr=rQXrXPnFmG)iXQ5C>5-VH6G?0C6qYfm;&Y1=D0vWME?y|0Xoqpg
z5h-mXLlfNBDabgBtoKfk27i+`RbS-rj_;h&Ceg<8yRd`ArOIKo8qT9wy+r2|S$*2}QmtG*v!_1kf#ixq!f4Eod)Y!^<*QXs5kKv
zBeEEmlN1?Y;jqOH{~UdFeuIwgY%!0s;&aE#Ln{O&TqPr-34%+@(?!mBNK{PBi;a;K
zCSN$fFcc|7kC(83hUuX^+iaVwk_eopDsng3g#RRFpc0e}9%lPeA&UD@EB{py>DhdB
zVIRlS#TDfk9(*gm5yosm!YU}8`a+!nrbvrSS2m%3b`7_piTLsy9;K^!Xz}jW(R-Kv
z@)`^^GO2^x`t@Yc--m1v9zmSPNJ~-X>3u#sl#rgOlJ^XJQ0tO3SaJvr<@z5=EGMEbtyPWX>hH`>5)&^C8DsP8J6JM2s8>0L*6Vk$CEho+;!kE>=zH
zaD_*3YtLAMhV8=IVx5(WSSE;Kun
zTfE*EfDnE$4?YbdLq_x&cU}pf)K5EY0jR(GzrZFYoO10AmZwylpIjf@zcj7K5tH~9
zbLNU%?T%fH{{B8IG=A3ggtR>vTXB2IY2IT_uO$*zMfDl~#8qYj2|sGh?{N#VrBwG#
zD86{^DnFXVdlbj_ovA%dh7t-6e%oHx*pLAmLjWWyw32d1+UD-Q=n4+)uaBluY-NC8
zz{nL`KFO2%HSuqV`CF@CQRbIGFIOz1F=n-2I4HA>mkh7X_U|=4GlIZ9p!_X2@af7V91UN|%L`A=Q9`|L)
zj3uRic1Dp9VcF9(?~+B6f8Ib*`p$u1nkV_ug%X3D-Z;-|w#D^5PHxY99IGWQz?gH?
zoy0uWZ;G59L^WmH_4*~ULs9sLVQS#I@GF+(SBDtsr@Z+6Y9qU0ItkzEE4P2^9m(c6Xv!)k7Cbb>Xkl_+)}WI2R8}
z=^ei0`l=rQ^V|yj4Q{>kg2yzRA+m==fKdets7u$RpJ8!B_URNq+Hb~}_rIQcX*f8R
z%$&9!y}cqI&Ht=$X?c6>F?|n7r^x-7;z|4B-_j#DywfE#(k%Qxnz;At=nK`>NfP-Z
zcO!6CEiMg*JHVv#%k#~lF~NI!dE{y@A^kptnR1PfXK_T7*6=xFAPciX(~e{#WMpLN
zt6fIf2~y@YzbC>N&lh+0IF-IU)mY*7R7SlmKHT;%)Z5faREj??2KCU9&y$e|SsqBH
zm=;DFFfE3SrBTjgA%G~V5GV}qzmxjeC%H;dh@tR!?Q*KUgP$otC
z%FBZt58Kg3VqG>*jWf?$ZZ$?-fNoTiK^tyAlkl_Q8_>#sZkXq#6-%4lgW4i4Gx~Wa
zWy^EN=)B@(@@Wg{-e`)A!wxGtTB)4cnu>oiUzCFFEi>dfb_A4>8DqcP7)`7Uk#!G!
zbJ$Pb`jz2Wk>93&R;oEv?|8Ki?m-84=+`KVC=L?scXTwoxQz{x`(f75nJCFFEg@+W
zDbPI`S5lNJh$r6!n5uJOLlu5JLfR=VIkwG&aq#CXim2RWjg>T={1F;`Q7Pmc<&)ipBhSrVVj~83#Y07eycDZ!hACNzL
zRv$Yn65s`$V(SMY3q8UMkKc>R60Nve;q#8q*FvKUIzFvJyZD-;t(ztN<7`0qls+KOW4wp%KJ|xrbi_&%cRJmf#2670tlD6xv2aE%%y
zhdy3>7wMJSdF3Reym_*RLs_+|h
zhFc9ZTrt*uT#eS-Xs|JN)Od@U`vE{cx6EwOzx?AU$
zBt>5V81lU2$}~_rQ9lvwo-4{pDYiV>;avY8asL5ag%zF_FC19ptjIy4P6^rWX4b9M
zE~lQC64Uu`yHUIw!uGJ`i)VTdGCn#e+s2Zppcw+;=T0Ka&=OM1Kg0`EbDsI&5$H(X
zwI5z;p|gn6>b_q*C1e0{iJ1TsI5}$yU^!4kBD654*$(IC#e_k>4Zq)@CbSTJgirb>
z$qAwTl=JJghk|vibS>=f7;LHlI&d
z$6Ve`o1PHlPc%(MZ>y`O3M^&vOf~Qo?+gdd{}(Tc@c6@P2LtK`Vk_ixO0~L(27J#U
zmm2Ni6pA}brID#J2&hYj6R3#>zmV~aKD~HcpRD3L;3k)s&Vtfk7G3=%jf_b6a{OU$
zPgnIOO|rEV-rt`oM<|c#XXx3P=#O?@<(yZq*_nJnfk`T8dwWfjt^!b4%7_6|yC*GD
zdT0&BO4u^MnQyy8AUKV$djSvG^vfO!sPcA=DD`pn;jq-Xz~^qG9UsJvJ>uXmdUxs0
z{+2R7DEy8klN!fRb=sITpF80tdCSmfK#X{Sa7Y1gy4h1$&Z=y-%f(;z=Q`LM9T#F_
zuH87|pjsszMb~l(X>MI*tR#i9{pn&OjgH-;&CsI0C7|5Hg?FQ(MA`vZ5R#t^fW$S?
zb;{}_n>c8t@8JY==y1tiRNOFPte-ulRTd=ljMB%@?
zo(%bA`Ui}ef#LwtqV%qCyoTxFJ5L3ZWg2xyJ8oTGWy~}$Lu0uFyTZbhuRN~(I)7M>l8bv
zV@lJ
z4O*We-_lM*T!8Kj|G$j22oZM}bjtj#?s~^A$q~(;=YOybH--m^h5bbc2Pdxi0l$@N
z_Jf{I`7M6TN}P+Bc!}41rK_
ze&r3ub{?)ruVHO4Z`B^yn4TnAid$}z>`SS^&f=ybWfw=2r|73(;(`?wMdA^+i;RIs
z$)JD`Rn?(nbZ3SN>7Do34aD_lkiBxkdEd2*~nHQSk^v+|sc5qq6TWE6UREmeD+;
zigKesQWRt0eM+k~Ul-^lqH;Uwq3B-*&=h1#KDs1QYET}08!sp@U@0TU3lbv4
zH+qbtDU96Tb`B*e_h;YPd6J7QSlahm)VVhqy^~p~mFmWjmF7W3Az(l`DRy;bb458F
z9Tc?WS4js&^$Hx=Wnj~cU_P~=prO&+#F&6tWP<`kSe}bqqxBtTD)fjOOt(=9@FO^f
zy>K2bFpifxwZK?uWxzr~%|s*BDLEv;8n-Do2LLhVP7xV1|K>NoAGKjxKfi=1^B&Z@
z^FP_yt#@|RN;)gfS1Mn9Sw7CQJh9}k{j^Q!u?BRV5JvvFL(B*QHN?c^bHdI4(2eC@
z!vW4D&&W0rQ`88)J9BkqY70NS*g^6HL*wJUhZ+^tz7L4)+%_1s5?i$Ezdlm6d7KOc
zMi7N|DmOZ;>NbKHRRZNGGaXNPciVZB
z$zDmEo71+Gr8RSW-WZ_fPrc2Wppa3ldWtv=tdd%VM_DS5HGd!TXlJ4S`GBLFRcylu
z8r|;~b*?8_vESX#76>I~ywRbBw_Zs?9-g~)SLeQ1?u;{cQ?m^+N?sWJqW1B7=k4=o
z{X%U9tp?3mMXPC8zsFnA2&57+MW#;qg`B_?dabQ0;WseYv9rw0??v%pZmnsvep)ff
zRB$-?MyJbPP;=O$*HkLL^89I|JT4?2vTH0W0+!8bLG9Ou9ZIT3gAwjkBoHX-U~nq5
zzMA*0=H~zi`^^;rP#l5c~mwm2{pwF-Qq0exgh5HAJW<_w&VWXX?yj5c`C4P
zYb^cJ#`X1N$$WrT=wSyPSG~e_MU=aIWZn0Ok>{-aY78eL_o~hOg|};*^-{ycWJ~C&
z@${ZZ+*=o~vg-mi+jX3mr^U}_G?#NZ65>wy9AZ3yBdBzrCfi92zfd+K_~z(!bM0wP
z?~c~e+&-)637tnZ7+`1jqn+qRa^AJ=yXXsSam;w5{W6Q!6h+IB_a)@W;r>xZl-7xo
zb$qMpXHr2%!pGL@{)L)!e#`M!xKnoNi5vQ=)?YEMoYqUw4!GF*P5y*be(b30!1I!y
ztq4?nL?wG^xsEqS^U|s&Xs`FCLP9uKoxE>;U)$DqC_B8rKf$bytt)hR-_&?rQT;Gz
zL9DYFE5CLeUyA$%)H3kHtZd$r<*=EN8Q^{~&vxL{9JYO|FH;-y32FG@u1DBY*wikq
z@6;1k9Mvnw+&R?s@#7ll3Q?&dY`)x&zBg4q3hqjpM+fvt7xt79#F^b%&8;9&LN84y)ecRH0SJmy~p1HEXh>i
zGlLFE39FqZVSV|(B6{ol;No#whf;n_Gd^(aB45gl9Z~v9VmpsD1GEc=hmH^!NZr4+
z?DgWhc-yK_vPo_y=CBAQy5u6~NC?v_Y!6Fgj9
zak#ZKu9D6#OiUi&n%_^!y#X9_?5VYXkO6T=e^jc7_Yis^?DBtObo#RGYAhmb}uE
z`B{jZJ~tHjdd}a@pev@GWQ7bYoHy4`$f`l*1=%EYDk46Wbwo>s7B&
zLUM;2*ZeL$d)RpaaV5FFQ+psk>YLz6Yy)qEvtJ8=Q52ff&QJ;y8COTlo;#b;=YN{3
zc1(VwQ`ie&>oqxGqHaSk*io7i_ZfPtnC0L7&=_$LemGWhuqkZuA0Cf9kH)yi+#U@1;!3K*1icN+i0Bw-Se_gi_u34UUq+5~nxEcI
zd-LSd(p{T@$>4MQ38W|L9*H6$!n&!KL*9z*up7zL$zp5^L+8amn7MV{q&MeUhNAIA
zf@8Hhs^%iNGpX~-i8mcMTy8W%5BsK9o)3nPt#7mU&ihU_(pL!vp+5uaere$D?(J>X
zNE7wnt@|}il*6IPKg#7#6?}mE)xR_Hdv9)8{wBnatD7HAQUnIg{*Ty6H#&i
zJ`ky%T&X;B)G#A5Z9~zA$Ch~ZItTIv
zDG_+qJ~BUsz)bef=c)o6$;-!NhN2TTw&~5}34KUWG&fQrvA|?7@DnnqYgX)mU~Z)_
z4O%WGMH}=d_}X1Xs6^6ZAIeg>v>p4GkI`48#3VJ!Qezm47dGVRH~p~VY~Kd?9gg#)
zJDX*pxL^cu!aRA0d)pN#rS&a6Kx1!0g*konWrKpl0fV824axVyAJ1l;6Ro2)Cz7y*
zY3Ji_i_O;|4=)yn0T;Kk87ODgO&P$1bX+z(^~~qNQ^5nz-7*y(N;7;s37GEnBazG@
zihizmobm&i2^nr;nkdQ(3I+z8AV|fTig_G&if}3^gHZDA!(PL}r2VfYaytqnF5rdL
z7FTYI(PtR7k})w^o8kpAG$1*lI#rsLp=`XD08`n#x*+8Da>bcJSR|qtpQju4=mWTd
zy$Hbw1j7JE>fCGrxJe*oE-PeslRQFt(Vb{f|@Sk+;B+(phir_O?Zn$A{SH^~1=Wz1qdUi`l6GYN%@
zF)J#iP~)jfG>vw|j2r+!E0)%)NLl^L(-5LBz-!P29+)O0+n>GA%nU`O;4@l!58W#0
z_Dixk>1h%fG_q*Q(z=1vPn3iow9O*1HxiQ_?Y(cFe>Sa#51RWt`d#wov^fQ?C6ujI
zRaAE3RmBs~3PiKWsEQQJ=c;yK`la%j1i!D8La?}RhiChBZ}jf-l>eNlQwm#dz$VPq
zOS^&g;}LV$JprWAFyTZL#LdpM(&kU@HI4)HO#OUQ#LV&Ov(8rw7Q;a(ht|#Tm%?|;
z$4WlcEk(*D=(yBlt%p0YxK06fq~Rd&L1SK@5x|Hniw9QJcYnZS8%ovRWGzj8*T(1q
zOhv*RDJA(A=&3`CaI2)Ny!t&9WMsWV5(-&deYREYCaUhY$BU-p*b3da&-WvCB2ME&xLEIgLo
zq9lAEa#?yOmDN>d7?2U$wC;`neuBU)mijt&puK!VE={7%1U_RPyz9FYPX1|_Vw9iq
z;rh&OvlpgW?RC!8)pcZUTcRHti6TM0eNNc5>2$&Pv{a(jswdb_0z-~v5+-h!jh9oB
zMd$ef5E=WGtXhL{=O-hWyWq~Kch^dv)e6Gf&>d+Fw+a5^t8O%^xFcFbcU<9)UA;91
zFbrSS**J^mn8xXQWhC{mqyhBs`r>K5K0*PF#PkyCeOH@-l=>uBJ-mV%KZG@aUlM*8
z`@6)i?a1y5F@V2HjSPwEFR4>o&Xn{>5d<*&duWdkkX#XMltGMz5v+?=je>zkH`4a|
zJe$Z#<_5Fd0vfw&Zs_9b*O3MYq_E3;kA4>ON`L??s~%y~r7MwVV71g7t}+4Xvn9?y
zjPjoEyi2TS-geAV9jPuWhou2cjh
z@~ljw!q%dCXSH|AF%#`%a_ut>sy0E|vgb#oFn3E#Oq8^O50o}bV&EkucqPl_$&Lhm
zl4x%?;!ft1HcoUwBhSGp{$pCGhv$BZR6>z`pModC#p}f}Y<5tq;b}RFt=(Xf<4cp6
z&s*#&$0x;jel4imx_7R(dhaQpfUI$YpPU}wD#?j*)0dqZrbAU^u32T!F#-2>=`+i{
zOC0bxJgPbJ{AgRby7#&Fz|CaRFd!9xw+F1QaUV&o9a~xMB8El6vpcO&@B+@*Od|s|
zr@1SY`jZ={6vBm`J_)_tqaPXHBU0HUzvf9?KKSFzx+PC^;Y2H1x^o@1lR5@E#`zZ5
zy{uh^KmVY}vchMkx=ENat-<<@j5*!)wzi^yf9%G3xcINmEjPNToM?i9oayyDRb5W8
z$qv<-{_Bq!`aJ36A4=0kM2b>LY1i>ax}P~v)q4B-oc2yUWONdA%%iOqLBvI&QB*Jj
zWLj#r55P+WHA0Ial47Lu^~t7q{T@RyRIB_zgZ`?Jt}lE!8k=_$RWf8!C3WMy8=@ar
z1J<4|vvyzT;02hh|GatJty&;-&|EDaOkX7VMpPYez|naW(i775NHE*XqTQw$xB!z2
z7dzHb4H>RD`=!uvy=4w!z@eeF<_tX&O&1r^#JHkG$30UBnBS=sb7Q_<5_VFh*#@^b
zW^tI;0!&KfX?~mkgnUS$*G#X+SikvcDkCckp4Bp-EXunLK$^S!=X1jdf1l>yVQfP`
zb5)BquOr6x*CpF0!pPKA<)A`^tj5INiyyBKT2Wm{=da(9`MQH1UFuOGspRQhpQGWc`{U#h>rmN|hDu&@I=vgqE
z8QWqa`+@uvB!N*;W^`2-Nvcb`iN|ZmXolO_#SXt-!o=Jm^GX#uJ=tT
zzTJ1FU3X|ckZR|6Hcx)@DU)Zx*I4_o
z!QP$)li2;_6nL@DC=@
z!V|lCl^S0=fv;<+rsma1kD`|ElIc(tcN*yICl3Agh&R^Wg@?cbt3(W81P-5QdZQ{?kxf&NmYNi4pLs-p
z48&I|Gjgt#AVR<*Plp%7)QbN?dU`~0jbgK_%OnF6RGH5-DhZJC|6}Ye!`h6ttx*as
zEyW5HXmNLGae@^mXp6f`aSarQ(n2Zj?(S|u0>#}mXwl&A2{-#bXP@srXYaG`_apg}
zA8($u)|_k1F~=M)W&8Q_KlyCRmHCO^;Ak=Nh5_NrK3jyP&PO40*avb3U5Ukn_`iRB
zDv5ZjMXFp=U1z|@bFze%a~`~%u+2lGAT-WV8+w^tW1qyK7w93)qf`Gi!RM4%~i@bGW3te(Oi`%HwCeQ!#B(Q91XU;2z
z(NzApg$tt^waTxevK@>KOAlOB{#`$bQ{yp}8Y;^TJg+p~Q4=4I#_+sm4|He{+G^Ej
zui`csirOQDC-9Q<9Iq7dCq6bjH`|twu-C*OY#%a=qg{v;4is&=={=%(Vg0vh*2Sf^
zW-m}W~V=x^3k-bHd)26*`z96A+
zVeht282EdE{XAqyUek8E5xXPnjMm+5E%JCbLn|@bOvGVj|3xXc6&y>cz4>qLu%c*du&IGQ_C
z+t-c;RUNELUulW?JZ0oN#pgd9NN7$?2g-l9t{qsXj!NrcIJi=r_eb;+J72Ijtz!UN
zzT}kD7BaJVkUHnPbkRwd(tous7>X6;!L#W22U42SqqDCf{e5uSrRJNFC-&53`Af=g>)DZY
zhn=vpLVWN-ii7-e3PqLO!sv*>QB`LqVGrqYU+_G
zY`ET=tHIpd=$fuB1QZXCZ?=9z9vptj2BeL76Cx<~H>pZY>gW@mysFwd=ffcLDV20-
z?bZ%)%KGaCvI(geqN~k`TphI^p>c0$@GXDE_lHJLgjEl`VwU_$+(n1YXy{I07pM&6
z!H9GA#Xa=<%P5yZ0eV}0=2wstNNi1$`Y7uEag_r8GyY)7j0|O1W5NPwPD^0_MclLz
z?7M~;UuUb9^NT+R#6LKa48t{#bj_~7&+{3rsQEeUO{L9hnp2*#k~1X
zF93}*1+$k8jp;IfGT3W=Xu`YC%M{Z9FQVi}dxAW>r|h*G-hsTfe&OL;X~j}aH9MO<
zvYfdr)l(RddUBUXirZ^4!M9nHg?Wro3gx#9?lg;($=RZlh3)SHYs-ZDgRC8aKC1=i
z8>-N&dBd>YFe37ief|G9U5=CXkI42qTV3|NKx)1N>c*Jf*VjUiv}uXYtx=`;?<(C|
zeXMkK!m6}zFX&B;;^>y@Z4CH6I~Kgade0*lo71n+==Jjg^ucv@iP!Q;GRu=F%l}&E
zCozX+GnW;`+rVjMA#5!AL>9utF}rH!q)n9NKEq863dcN8&F
z!6mT*XVLMy#ics2!)cD;J*2cUiR?DyL5}yzi$U8AOv&+RF0VY;yYc~L9NMQZ9l(g-
zTImy*2PZl<#rLZIsP6T^prM_ltcf0Y1L>RsiP9g@KPyGCJ2MTo{DN966lS%J(=7^C
zK4-H6KD4T`+y1+y~SwAujw1+0J&wYt~fW+`*i^O`l?7)hWMyrm0
zR2k}^KA^XQS+Iq)wuNV@ARWl>1jQ>23J9oo@BY?P#U5%b4
zO!~XA&VG2jk3E8?0F$Iz9$)m;sB6ZCo>FY!LYjVnl5JCtVcys0vVEpUSr?}Z)oBxj
zer>nUX$tbelU!4jlQe#}cVx;naum$o_#gbXK73Pcq7|Z@ZbrT9)m3IBeMTKK5Jv}|
zh&G-fe9HEWlZj;`e%37fD*jv`RTrOvf+H44_nIz&X`JZS&I$*g1W@kV4?KDOSg-ud
zfR#0BlXs>=au-)`FA<3q(6c|MU$h^0u6=G7_UcyYZ3JVJJ+!gI%BVT)FA`?^v5xGgXq2%uv3QTFX&@^yNmpo+5
z;W7+~GG0S&y2eh%DdgtwKY5i&^w$#FesDTpYe;9A
z<;?dc#j|UzU>J36og21SyA()G#oOM$tk)dTuy6G^S?V`$B$@?y*>81Mik{3d)(7{6
z{v4)ETFSPW(Tn*1bEJ5p50u1H1PpjA#1$&86y=NC*|8CE>X;4{G}-(9@k7Jd&YFG=
zY@B=cd(6e6L4#o{sl^ppZ>yZI+_?2p#hB&$Xk^_Iz)IKs3zqT|t
zCp+9}_ThacHJB`eY*K8*DtM*flY)OUOfP%SuRP?ZkTG}V*Pi_K#cfE?ce~HaPfg<7
zFdrn}R!F(6v{i!KAl_Z>dEz;=!x%;gQskkSobBcuKI9yO_-3o#w@LJz+Vz~STOgYW$zD#B_839
zX4qB^5ameutJ=2o3;=PxJ5^9?xcz+)>evyAR|PSgJRaT=5wa_$le|j6{6oo?tG$R;
zK#(di(dOx@Cd#7A;WB^5!M#J@^bZ*pvjQ>|@3ryM<5@;J?Lk{r?ncQ^JLr>(*UjQw
zNaqdx+siklr)45=ZxJq?5tJdAWHzDcLsJT?WX$L3kJ_X7iarGd2Q_)yjfL?8EzYxM
z+Glr;+BX|Sw+h+Pn|v9cnRM_%_2xr+HUhYr-bw4C$s!muKGi^bMWU^vD&80v9sf4m
z)sL+Ez4=8&6?o{Ui^PI-XeF09^sVZ*Oe4d+wSwF=-*(>8ovcQZF^g!?l`u*F<^E=o
zCXQ65=pn{zWoISQpBo8CQ(SxfHX(*lYs&}0cAJnwsC=L&nV!BG&+)>096TKwTj?}>
zL5d{kb7KK|_Fk39irm6V31tV0K9yvSf}@U44$2*m_6mOn&opU@CPx{mtw1PVhF;|8
zt04AFA5Z*qm+6=+tzYa1{4`WdSe}b1Q=S{|zOBtRZ?$pL>-Gh`z$7+VzOAYeqQ<*x
zX<@M38Pju=X-CJ-54!jgoe~bZ@ax;R7{=3T;%JLi$ETZ9$&MfU;?1OP{u8Aoi;;Zw
zG~5*rAI};|V!yKr=$V%beSf8U=Jp^|ik((kB_umTFkuZM)=T8R9`Jl}O)z9S~gSW6{lqGZ(GTK^-K=
z!@P#pWsy#jw0I{F1)Zxw0>+J2N67ZNx%7HuXB&6^^X}xEHGbb)=!G0$eKE^KtcT)C9y)EnmA4O(o!cg++@8Lfrs&%*uB$F;&NP*DGZq2#JCCGK*Vm#01u5f+b7|Zuq@FKO8xb1;Y
z#FEg))YSBbK+)^wD9DO_bT1EAwDY1C(Z#3mff+M7JoW72clyY^
zT9&9iX#|VIJ>MGU6La!ytYAHiTUP%EM20g^XfgPf!TzJo;n(-wDt~NMAi*Ouba^ADyy<>5OGNgM_S2TN@g94NU9tHfnxg`|kV!{2lJOX#}1-bXs=incq7
z+f~SI$+-Z_2WVUA0tc!VB0!kCR3;BZYR4=BRIjc``D6m@_}OT%5Qt}|H+9|A7LGhA
zbTn*a_}^&G9f(NWT2KNvCSN7lqyLnaV=y21JE6Rm&f!nN&{mp
zS;7IhQDSGQKrDqdZzl|SS>NwK_1(gEcYhhbP8U;~zF5llBy~Dwj(9`0GjaJ7Itd2y
z@Y$=xcw)a{ETQ43p(bY2XDYmT3w#5N2FqGAMZYTP>_ow8zH!i>fJ>O?Gnk!>9SuM`
za7wr`*uU8Enb;F6j5B}ap+0{mNJodo7rOrYWZ}h_9PqYS1G6ho+a=K-)5;)NBV{^Qi+(NxWYTKz7=~5r5*dnU8hX
zqPl7VZM3(%Tccyn4a73OYCDy%i*^wTnZ867SJD+!lIKqMKK6`d@{P3{8;|GrJdBaO
zVcl>Mc=!u`dQ-iXcMhXQmbQ0#s=eN~`px&_nNKM;RKzC;K7WL0=$rdudXLN2U57Y_
zi*b?%m39uT9V5`yZ1Zkq>xYYe%2CuRdDI?W)nh~nV`e9@S($Qu^F|-(+0-!Sa5mzt
z@NH*6ExC3-(q;&25CU)(_V$E3QsSdO&RaQ`x`($DQED7;cbty7zzi&p0
zK=aeJO+lKRtUvQq`}aY%qs9j%v8P5Fm@z!h3^esDz7L)z(SfYoW=n*kfY!B0-GqWp
zNl`)DOcBz=Br>;PSe+`JvuZq!QHd*Pd~k5kGM!ar$n0xbvD8?CmeEf<+O=p%*86i0
zw>Gk!o9tmyFv3NDL{L{WOkRuAo|Z=ynxcEp$+Ty9U
zYfoNxsj
zbST0wYT;IZr&J4*6Ssr#%BDX#J5)GEp#!hReQbFxCN(iwAILnZs`=$F-ZFbEFpP-(
zi|miMkr^JT{$A7Ba>p7gsHNRfH4Xwh$+#Ql8w@7n}b6?hP!i&A)-MmVXnTe)oz;M;Xd|oMd
zg<4JpL8r@1cQ*S_E$GvK<5%@a(_82KQV>?&-B$|FP*A?{=#M~PORCRF60l
z&D;KdQZl<}c#Of}Ye#0RoIB)3N
zV28&pD5f-Jb@_df&qchz0aEL35=HTjmbgwiRbVpyp*pc{D{?;`^Uh=^Ng9^!|CgDHtYPyrMHSh1cK)`2bW(X)u09;
zNiSE!-r$KyNFU#NZo5C1M&I1>`inAf`(&gyUBgI=TS40Y_X6mjd(u#p8~N>dLpo0L
z>y;gm^XZx_lTdY8pb}8Fu`OhGdpo|(Lq1v>nuwfsnO33ZsKmKuIF`vk$Np&bX!Yun
zh=!Y%TnGR6#%=<6Xj3)@Gl|#6NwvZUsp7jDp>$Q{{xAZt(d#BMvzqwvP{)N&J6}V|
zLGQK*f!{gRIlkb@NOGR%+k`_XUs9k!3S_7jyZx<#
zu)j5R7bvJxJ2&`+<4PmGPva|QCQ>O<^h~!mB##O5O3355bD(LpH*qvg$p%>YPV$&0
z$wkIa@og~VR5+E-mIZ^snrUdTFZ@O(`=?u@!qf+SQ!y|m=4ZC6uzJ^{XD$*3&a{u+
zG(A}7vh1PDQ$6@q^R!|}^OB;L6$(7{?;EG{a%2%XXG66(zL1z5=_kJ%v%mZVWl*gI
z4lC(K7^>}jWf#3_UUlgX>Bk+`Q0+o61=N~cx#Ejx=1_7q#|~uzL-N1X`CB7N*Sw|XCK#AV(7GbX8~~f9Fxx1#evxGkz7eTu`S^D27v3P#%PXuY0s1OVI^KLtl@J
z68lqa6{1^r(>i9S9|BM=B4-|3%2I($k8_w#>Hw&OUM2X8mdzL!{k+EwA%&Y
zFe~KGA|UF&`fzcz20Cbat~-yvJDRRI(v18hHlMWQON!c-h3mzDagOp!i?NLtEd%tk
zCT9_JB5uM*Jj;tsRX~BJMicVxu2&2psVF8#7vDM>#?~a6W6Tl+b?G*h`1QS4#LdY5
ztA7Lh{|2(N`FWKGP6
zAe;1Y^0{1TNZ5S0Kg@a76HRSV)^>UBwCuF0v~zNb>{hZXgfr^}5QHchr^izP)Z{aD
zl=^k95EAbn*u+-%S##Ctvb3QBBo4On-+|v+!QcFDANE$y-i{b0{R&eqjT(I~{R{Uh
zL~jIp6wc)CUBlY?s=`LF<|8kzy-mm;>Zq^0aq;cUG>6Iw&U^GU!N1vJOI&~yzw_Oc
zYJPm#6Y%oMSbE1X`046^U&=-G`v7&sM_9)EXEDGCTN0~-L?wcK==yQ{N_-glT(0?N
zVT!=Etb74guC*3!vl!QIcekR>8S7~Kj>>#!9kF=;0+e00DARy%tH=p{F3
ziuz)s^-C4?fTmqJMb$5QiaTco0MNvcdP(0&&{QuI#XmIfERI0oCq@V)z9+^)-xO={
z5a;=GIiCngfchN9o3zinDXZ6sZlmvuvI2jsw3bb)XmI51w8)U654`+fubcH*tWzhk
z_GIYZM3Ej(gwKB75JZSTiZ;0I;gV7(%bd)Ny2R5>Abi_fg3!I%>rEta;W9_sq|8W9
zPclib^w-}fjnJy-LPoy+ANRA)_36ed1`^zQpIP~hBTi7^@17B1*?T~a9TZ>!m+VWu
zL*CfnC^R5Lyh3^Ae{h2(GkRW%eALabWIoR?1_fJ}OKIZkPWKkBm8KO2)4|WoKP!n>
z4UpQefdtm2VSaMAbYV~_b4zv!N-Bd<|iI5|t
z-3|{twHZd@^kE`SG;~EBgMIOET)Re08j&;$nKw#OS$-%o)+GK5s;lQnc
z+6Y%uG1L&`-5!TfhHE<~
z{Gve?A!Sa!Y8+$G%NOd_+1jo1Gil)DUK*%Iw-c^S{Vu+tzsqo=fJmz>AzM@;Z
zmej~Q_;K-h+J_s;Sm(i)QeeG0FG4Sa$EeGjvEnZi=bBBcZUj5X+1THy8uG<$#<|0~
zu_G#69HrZZEF`SzEmG5lQ`1wE(%RZEsRRs$dtEMN{9>LXd4+4?^9e~pa-v;w)Ijd-
z2G4-g`Yn7yd58F$(bA0sNHB&KNf{-g<#Ork?
zjaTOHp&Mp=scmjns@F{7G2!O!CbV{`DH+0R7wRC8*3EZj-
zN-?32{jk0pzoww*@Bvy^Ha|d<(X|yq?5nwB{YD{(!*ROAU(4g#4Y=E<CzgEqVO{dMG{Tb4j+q@b>35Pc`XP8B7tPD
zX-PVT`ifN>6F(3%POJEraj@S^I|0h!@wgvqTJ?o(8%MsTlr3o7N3CP7OoYG=
z4rayf-(2O)EObw$D1kvk0uQnY?IH=OmYgvNBU;p_9mL1N5IuA6n-?cB9_>O8!G0l#
zpo=FsfMD
z*$Z=6TOXU^#Xst;HztApe#UT3JmLX)5)pj-MY{rez+6D&{Y^}Boa8NVpXDtxq~TM_
zv?qG*a!VbuV+nk(5D+@+*{h*7M6Fw7@85obV}RIwP3+ln;Ly77f7>Qu==&FV%sDvm
zbcXYx#t-YQxr9?FteQFi1@#rx|M)t6eEW{2Ghf^vcux5AC@%=V
zdVD0NH|CQw=1yM-$j4^tkhP-4fM7VLR8(>r_{6lSzWm@{p%9&3@$A*LUd@^NP)X5{
z70BHp4YcIvK=QI?!Lhvq_|o+0;*ZK+_7UL5b!8MF)NF5(@{07WXTzA&*+dX--|TPf
z9>eREla?$MTq`Frty@pO^TcW8>1UTJdnh*ycl9`Oa5?`~12U$@ERg@D8D*Tm_eI)@
zkSXLd$xDxSCfcYl7IHE~^qAa49t23<_yUt?&-hXclyTQ3zkO2K8j!v?pQ
zg>Fky-ezNJV}P^+hH$GMV-A})mG3bNjOL8k+L`oS9^NdQn7!Z>I<`0uR#P5*@p171
zlsYDGJ{je&kFNW@+wyCR1hjf>MATqSn$-1IQxNE|+fuORD55AcmV+1n{D&ykF8Q)a
z2)WzbW19Y?R@59bY4Mx_cKqt4=0xR{uM@(4)^uWe$7ZBi?JI*!=iSNyh5pSY9teP=ZQ+!H_&ZBXOmy%uEX
zYLe3kR8j^-H9?$3`RC6|e$I@z$S4%|ah}M&Iw81+uTOO2BxJZRm6(T;mGxMrfp?Z{
zkuOlvOC9o?6hbUReT_UvXOFob?#6vJJDg$j(~U1*f2hIIJO*E?1a;#!^>gT{qT7
zr7rH_3hBfbqEL1MCbydlcvg%Jb|@vH#O+)2x@=giC8Rs5Jj6`T``=)Qu~oZ#iZcGs~(qJhE7~wPRZ~_3ekAc}Rx)%p*y7uJcRe9FkW5
zq_>?8*pR&nbO}?WgHk@?FCwH#K9wl!&CJfqDJX;u8x;)i-Rh`Hp{d{Ne*!)rr9_k4
z7p0{vpcb-&vWhmd`BEN3aWm3--L*PD!P6Hn3x=n#Z+sUSP!&@NO&ec`?D5aByl8Cr
zVRK1I(tr(e*(+0ye*xu8fb#sEoMTBh`651EnE+YwEaI`2I#$g9?3j@}a~QaqCNU32
z&{~fU@v0VaC(Dgn-c8>;$r5oSSM4F+fs$NE-#YZi*D${>n+F_#?=7g`9P9^c3MoHY
z;=h&mHNHRbf+HOq9%Qq^UQM|@RZEFJEshU)@TOWTI5_%3p<8H__t_m}ypo!>woSf=
zw3MULXG>zwIp?jb*jT{JmS5tSxp)y&C<>e
zgxk&g$=E=atrs5tjT9XYHO!5^T!7Mt;0&&5OIHWJB446
zb0dUK>ZMhm(fqR!&b=v^9W6n%g@EW|Ow?YoYy~MBpqmxV0)r&B`XwMMGgc~l5PNv9C@
z8rR4UBV=L{@Km)*Xcj-H@A7)+RZqkCWBIu{YY~?xXzXJ@8SUERb(4Pd;Is;7QX1m)
zrM*J^V;HCE`OluJ>h^>N38gUfp0OJGo>QOEu*!B!LGDPzp8L9j_m
zx%lhk-`;Zq?ETsle>S;MQOFPb#-Q0W>fapKcL*1SpPxiCK(RWnIoC3V?f4}U1X-S|$7+Hp+j
zcWWYO6J5}jTi()bPtz$C^vk?N`Ac5e%NDux*S)n6rfZQ)xkcEEhhg&j0DE{|O5INL
z*N#@+rR&gsiWnFGG%_41qFfX%q%hA}npn6)lu{VTK+3x`kl0=_{}OSDb~Dh&h@g&8
zikK4cFHuZ`Xa}i~6f{;ELSPQ=YBLK+Ma0y5U+G6LxohGd6~x+k(_?Nomo^g$^@U%4
z?#w=N3ZC}{Rr)4+%hL+fK$baXig!e=m%HJ4+#ELkCZdSjO_#+c2<_AE`S7L!tOnj|
z5wp*StzW0RFb9QhTB5bc6@9FS=!;f#eQZp?{7`eb=xRCKy5<@fHj-Z0XHwTm@qo*q
z*METle`)SaYKuf%R%&OyGEb7dx%Wrp)%HP^A3aKBPW@$*(7}7dMwzE51P792=BB%i
zc=~_IZ-4(AtQF9Cp+xmO`RxhRFSylxRF}M18|Jt7WCmwTe_-e#vwR?S`pJw@F
zPM(h|25oR7)oJ6jO=2C_fC!1*}-
zMCLT;fk{%mP2s+1k#xB`b$xO1(#^jJTN}rU$sH2)hECDX#e*rXE(Go(Up;Y)*Tu
zh;k$Ey?$^{Z;=IZZ1B9P^-0t`U=SqskdkJwA4G|WW;1LvC|+f^wyc9=)tkphI4HBahp`Boa!?i6{F58#
z;zh2msyw>VH+)!57}WxRn~#>($61^j4FJ(fvj;dy{TCf0#s|nPQ-*P_=J9Mmw^CWs
zaQP9@pwQZxmyU1|Fj1^s!tXkca+m=wJOc}N_CBnuVlz4mU-s?KIQEu}s0?s9{3tsJ
z1CYkO@Zs5S_8i8_I5eGoO-yFhMeTpT;bA^qY60jF)w?wIuUEPDoI9}~N-?g%;seTLjp>^zY-_LUM)ZA{SulS~a$vkhOTuH>
zWhq=UsLu9vyhCj1M)~2Q;t6iVudpPymV-<)Jq}>yFC;wog}SsJ_FhS7ID&FGqSs&V
zdO7{+u>stJJ_b9MYPM;Qn}IJadZ&lo8e=GQ>YZxZjPh!aD7Da`#a}|NtHD<}I-h@v
zQ0bADJn04d76wJURt5cM{>>Keh*(P5ul&MW>_f)sr@eyV>7!~1;qXKPg4`Lxc
zkMTi??mv}}u8gvt{>Wv`{yK+x$+zzL9+d<#G`jzV->jV!GKLq)kd;e#w;WQ2HC{%&
z2>Nj~kIt&rX6gToW6uAVPCZ=hJ}Cn(J1J#P^s@na+&ai$P-N4>5v87f?wos%*F^9#
z<&8f6uv7TI%MmE3dh(rqe0B<13yzglv)k)OO-Hg^9~{I;8?#^>+RdLeZ5F#wiGTYx
zHhL_Wyd+=UOX{ce_ECM*Z(Qgv@p3SGBXroDH>O{kWar@MQO6a2X?3g_f(?L1FGdu&`(|Dm{;)Hn-M?1r}VL6
zuGrDU7u6^zP&>`wt9ymQ%?2GkcmHm3z4ujq!dVB{@JXS
zyA!Bf2PNM=XFBJkPJkT)>ca~MQe3hlJ_Rl9>h*#cKcfbZ70YA)$D00SRc%`PH9zXr
z{p#_f?x%0xCdLos4j7&Wp8u|kUf|;QpL}n__K9J_)S0*^gK>4<5P6h43R?zwH
z*BR6fU}3j|i1VH-$M_TyW7C?~8AlZ)#<_KoU!hYIG(wb~;XJnKLBYYd&CfH`yCr~Z
z%3Y|c0G?m@m42yiU*BUg)O5zm!_C$X>{6t{^qjiB5%J`0U{@Biu2ykFGiaI)$~|aT
z8dFdR(5#_$U-%PL^`@(EujM@NQ>^kEJHA{`l>B9Lxu(PwrAtHB6i{}<;x2m3%d}e-
z&lB%8#)~UTF3?p2g+Z2FmCW5jTn(gr#^{N;y#F5el{d8=3&59!j!mP`NZPwek{5#si~bpsM%So_luA7#KW*u
z{o^gK#OS{e2>;C|gnuzc;@TK>AtZ{E+o$40at+n&7;mlUFm5cL(KY@Ih>do5*cfrc
z-_2s_k7Mra86i6O@wNegSgY!4)JV`cR%xhASFPwzxJHiZ8hRjFK`vp|E>UAcpnf9+
z4Uur8TM@Yd$^snRvu*(J9xP8xnG$XXM$TC*ua*x3t<8U_+hofQvl+aW4HDH9ZXX(@
zo8qz!zI1SiTl0Tl)hz^Cj-<1v2`%v^OEK1bO`(NS`jxBC^V+lp_I>&a0RsRAj}i&!
z-P#ZUk8!<(6-P*c!$wcK
zhTl4$o$nJoX{1`!HwU~4`^&v98u7elfFkYckL79cR0wj-u0Mf!KbcSWY5L;b8-SI>
z@}iWU_SA#yD>#1FXa*^;;g_fm2g^}~;n(hE4?~`O@2;CVxJyH%ssFXu`aiXoG0pQ=
zA5vafEPX-=+${@uk-A_x3{8MG_P$s6eIvMts;JAuV617M5c!~WfJM{z4cO3!b=w@c
zbk87o3AS1zp{&(>zHiC)lGzuA7%#ZwzXcld8(*36*!oG8j()
zC&Ge?R=JY}8q0J<+`R7!rxZ@!W6*js}>yg`9_T;CTthD`%M}7zK6QHL#jztg-(2*ykv>+84x;p2ILz-_m3O59c|*ip@peU6gXX`Dv7CnndB5P5Lse9Njnf!tL0_F)we6h$$-+HrS$#p6<0={+#t6pczpqH0rTH9U(z9^DV{HP$7EN!8b8IB}xzPIgf5p2_Qiplu7
zZEKv*Ll7F*LdO0&_1|hPzovJZMTt@mXL{++9gNV=k`PSfDr~yhq6`c&LS&Q$HlAaD
zNGYsAopsQR@k%?CFvBR1kdH9?>bS-RBI%#Vv*v61)l1`Mdm1Voq^|cKTeQT{CLSka
zRB)zYf*FBGMfn?H9&8$|b!DsoRova;8*%FZN%%b434Li}v
z#NtW;Yo$JiQR^1I*6!C1JJ)9n!4uPE+9ZrzR*C4rUoXcI566sF>1TW`7mgl-PwjtS
zdv3EDQnRzO*SZbjFZ$kyTt2&$R~yFi6}JPwi@2U-Hs^`%f057}Qm#@WN$J$|ecq-%
zS|nZ9*Vw+o-r+v=wSj2A$Q$2pn$;x*Iv00IIhyl;+V_ea9eXr)D~|sBsa8_&|5F0{
z=WaE=4+Oq9&UJp4wgj5PRhtV4@4NR~bbh#V-%A`xsi;dlY(44VVA|RUp@`X55uwjW
z1O3H}p#C;tT06-VjK!J~
z=%|AQ&?Y+xuu*H?y;$*p+0oC=f@dQ7INaRa?osfM0xFWH7H2C!vvOILL#h?xEcVFs
zT;2O!Ej6vEb&$($?k#dpaH%cB|^w*#4
zf4|p5^c99rE;_z#8EqHfBae_K27%md-hK&@fx9g}(jU|B&3F~6WN|2sDjkdKi19fd
zN1yoKc)MI_XhmJW|AO;xc)5SB??1yN&|b!v3qARrgH}^TvT9k)vlWsTr{(B@%|8{E
zv1m9&?k#HFiVU_lLMUS_hBIRwuosd=Tnp3hm*&B{=iRJT(HR~KU&e$F$hp*#hDs)>
z@bupIj+*8MQWH_(H_Bt9z@`IYZ7|U%jqxb$OrKHvawzB2)#;(h@yLkh8Qi-OCfcx9
zZD4}$GRXJgYgAFS0N9?Z{SEL`a%*#n}KCz>w=Y
z@ha#Dz1U+HVGd^Al4IR7hQc#W@Y}Hzt2XJxHNQGL-FE$BpG#oN@tlzT*!z?U+{<=i
zeJWSW@yX)cQ4-@Rwkv?NlD&O9GCO{XmAPbU{K*KiiIz(eMF~SKolokd_|u1-rZ1@X
zy-4qAA)cQklE!s+d^Rb+Pnu`(9I)1^7^G0yVX2NABJrP+{y$3qJ6qH^B&nJX6(Y^o
z(h@I;oh32PeTH`Lp8=BCd{t^bh$D2sYfxEOB+Jk{oY4HF<8L<=u2H5bZ??%(G6%NP$soxv&yzQ!w(Cu_!A8EX*4Cpg
zZ)SdeNaSXjcDL;!J^$zANh1t}z|0dC6EZ01=pAOK+bUDpaZG%Ekmjhd3`pU14Nkwl
zpC6hc_m~Tav9X>3{jxdOFQ}}UeDMnzZTZo;P|Fy}MxFZTcEJ@Afm&<0i~)^R9D0)5
zLqjBwezD;}a+6aa>wFn5JhsYD$?v9ht+n>w^U447+&+sLBr~3xH)5_JF;`uI=w7ec
zYGJ=y)VT){#X#V23LV6Ve9A}fOb#Hot(UJ^
z6jd^}mthSaiKqbPkIM)7v*8SUS3IOXFcr9Wg6is7bi0lNTaWF@^D`+jhGeQ{ZQLf@
zk!=WB3P0_RJFzF$DB<&gWXd;$|FbRl->Clo^8*siEAF5WxE{kQ5|lHX^K1Px&_nhN
z^U&{k+wyXA<=vt7oPtN;)7zQeCvmKmw}E8Nw;L`ydgJk82$-ekS(s6IAfqeqM4k*|
zWAWS|vklKgp5`V-eSIIL_DEou#DrNGaBptgUZ3oHn95!pj)8AMSy}&!Fm+fsb7N1W
z!O4V%R(ac~zNs@7FW7vn&UUWZa5RNmHb`gx5W4hz|JNpAby(@fME6#b|wsk|(E_oNQ-w%YiN(RH%_
za`yi90;6L5u!yEuUbi9=F;&4GqJCZF%pI+5Jg}_ex_x1E8#|H)`CJL!vAGLGPbTxe
ztU)#)RT4;_oPyenpU})@4WtWX&?Er>Kt9k4P-0u$lg5H_uge?mrBZKQk0+V8G?2_F^ZWi?*
zl;$Gc?6j_Vm%Bo~a*h39dMb$l?jViAB~1HL#mp>2FKe%*!PX)J0h>zd%JugGS;kTL
z?lrAl@wZ%!Hx0T1>M%(EwH5tu&Rjfk@@r%_>0&ICVbS|UWUE@zV_rjfZg}G*IaBLl
zb^GPs2$h!6jcd!k)%;+a=LN_TFGEl&NMzL&aaX&W>8${2;6N_MjN<&ZOQAK^_ZO7f
zRH2A9dtW~CPzT@kcJSNCF&;y(qwD_0C{GN>aIobFH;dCSyo#s1z*qA7s<~B(j0bv
zwsIu2d+3+r2{%kZ>pv4YLh|bO*ytM7l{J(q(t3L+KKn{Wuv&6Q&~W9vA9g}Rqf&PYiQgTscIQc7Jy1^c|YeH0G0r5!Ep}!DKbX*
z=B9UijSlfIE{NrP&DzmR_O{-Uq)#m_GB1g=-0g@BS&3Z;+FFJ=j6+f4w4K4<$CE2#
zWFHP06+D*3i8%Dj6?R4v`>dx|4(Tf@NX>iCi!6G7TbbY07Fpb#Z`U5eiY%rJ=bA|(
z@&0EY@!zb+C*xOvC2x&Qn_O1!c86+^jWLxK=P)~;9biU=dHeEXXP(QnFD|ehJ^9jR
zz5j5rZo4k)_J>U5FZ8sTft^M^Ya8ptzCwnQ36yAE18M1b=p?T?iGF9MEk|Ao~
zDa|MpLxJtqa@Hqicb1}1p4EtF{J(Vy{s{~IJN*(+eV9d64Bv{V64O!kyE+5^9Yoh@
z_es(B8*OmuM6|M|4#t)Nhh%6ov|su
z%L3+2TvO(^^m4t6^2fi|ty}y}kJ9^Yma%>r_U2>di|1W+%1NN33@*nrRajN=goaun
z(7-H6eRf9PS2AN}4(7rK_K93`<0BX~d#W2v9D%`(LBlZZshvjmjIMl*AVof~aolgj
zYuFJi0g1O&HS}2Pc1PnG3k?6S0*whTx%3%>
zJ1uwN?68UV@m^xTPOC$l-f>|eScYgcjrPQIl-0t_s%d6Shb@A=F5j~ct7JMm_H{;0
z50bUiL2klY73-4r8z6+DSqxws`ZGoQG!zayK8{f$<&!%IzM7is(7ETi%{RKZyt&%v
zHDHiUT1bI7#f-&s=^eN3ir(GNb0!e7Y9hfKh_=&Q-?N15{{q54du|$7LS~GAoL5kz
znd#?VF=njF$_X&`U$mV!*pd#j1p2Eal`k!GjzW*vMn|U$ti9?mKa|W+#k0WkrW55F
z(0}dypraw;$rTc+DyfJG4%UUiU~zmI4dyF#oWF~>rUM~ICJo{Qnu^&$je
zC#Y&QP-bzm%QEvdxga#u%ibq*6;K&z{}OG+HMz68ArA7X28T>gT;<&1wxccjTUG4*%pjU$6Pd|#w5YV&Gk`TwO)sSxj!C3fKg?-LAU*yS%7oC>i|0`XJg&bL+nQwaR`
zzZDmg{P+9+WbXbuK7Vei{~e$Ij?cf2!2g^6X9Z$xYyv;%e*R&6i2Klw#?aDQ$k^EU
zNg>vk{!bSF|9P=uFwsq>p01BgNcV1K$Vt=%jdSk`%&GmmL;XLW`R7kB-HaniQZ-NQ
z8T)OxeV+I0gfv6_KG%D=r|!(Nt#9tquj`3<{gq6a7?a+ABtFOTBl(lJn=YFUzuJmM
z@&JpIjnC&SoHk#82;q0M9#v~;{-scHtCILtpVOI3yzdnw)1vDb0mjDZ^$kt%>3F0j
zFn7?TlPEd;U$Y3}C9XUdhyj%DRApeN4nx=(sbe08cQ?k9I&iW6rLn!1DNg(X-uJ<4
zG5%Kdb=od3=%N5Ijdv*j(%rSQiLXKLsQ3bac`lL^bPwI?;AK(`lz(9(`j_Ab$whhr
zl}Na{Gwq0p*=;mD9Z^_KOg6Hu{$c>-H6c!J+@a`<1+kuaprv7?1ybqCM)#KxDap%9
z9^$>nQxd0X>Ocy$O9Jb=yNOkvZ~o%Ihy5P-{d{KouTy{F~BMGkxv(L4RrXRq~98
z&uy4`S?BTvUSx$i=chSq`f2I-|F|FE-;MLzb&d{uS*_(v$DW7si24}bAa9feajyh(
zPe$qOzc%Z)KK-^opBcL%)kyfVP|l6@1-miB>wjs|IcmCyY0i{g+UN2Yxu38Bim2i8DqZ3F_ksNPn|F|1B3^x=_m$LxNVx5NtH0)B;2eK@rz`(`r~l5=--6PA
zZSNnb?Z4~kALQuE|N4l(o5cV7zFfTO0_D
z43BZTu~vd>{fLB6z*Y0-^-Pz~p3~1=gSR5M0Mn0K{fYfz@vp@&rtfc7g2I{q0|wEAar3#;I2E
zqoEK&XL>#Y?`>JAxa}V?Yug;3v@w0;Dtk8nQEUU4ca#OgmCQMr9B$x06l
zq7Gf9c&ujK(sYVy6jrRN^(B#m-kwM;a+I1nJT*7D13+rsPGkRxMAzky3d3L-pEOWJ
z9UK!K1@Rs5KqALv!AGHGrR@@D`|Uyp6ATC2#YnL-UIiQZ_@;{Vt==j|OtgfkVynnN
zsX%b9Q;24Fs9U~oBbH$P5Q0wT0j(yC_IwN62>mqj4=CL%vvdY=j1rr*5UkP9U?
znpsT~cihF&;L|irzQENpfdO{I&~_a9gEe9UIdY1@qEsm97?!ib-gwsfWlW}&O_qk)i0yC!n|E+_)d8?MoJQOyVwLeUiNFJrvh=qnpM`A3
zim{7YR(V@OLsPh%WWuyffMAEiWB0>ac>{b0RHG3D&=%h6>7DEDFf|8
zyrmou9gUm05a|o2VK*IbTnW;`Y%*+mEMn3xrNLYVU{!}8FmyXuV{>llEfDRV*mb3yly}#`s70o#`LWrUJ
z=8U9y5kuF4{4zjM{4LTEtVgN6oDdUSuy3P{NB23nr5z!Fh!G3}V;C_65@d^he3o3`
z*q(|ESo44~f6#a#I>m^WDL8t&Yq{b$_a;~4#ds5=1O@6TH22jU@I_vYSR#Ysk0HqEkkewuch*1wUNiYg;fNtcW-HY&$<($9ST&l!5vB
zRk``3CQ7qr58QvAI=J+M5;kcWqU|(8#;ZO)?Hyb`b%LILwZ*CZ3cVbW5s_f7yJ-S1
z28|;9f`=C(1GMPR9!#AQ3}=Bdsqp8Y;NPoC||kqCzMl%w6N_fuX}h#IJ1!0)#b12O00WS
zr0H-az{G1`j=)R~GkvHy}W<63FrW!JQMjg6IPCUw!rlcz3^XRA?nLeFjx{#r=!!Qf8jI=-i($L^Nx9xd
z?pug6?H$1no{*W#Q>kGY2v7hjCSBR65Y@evdMLB;@I^<+hIs};)Im`XsY)@!H?!{u
z9?WFd6wDrJ0EcvXffstG77n<{iy2^=btR2
z$zpQfQq!KbgmPJ+e=66~(}k6)GyPneOR-+9nOw?kAZs`cha)_Cv14g3&tW!r`{A56
zZI5rnl~sy&23sB~)+X0M<@Q|5sGc6GwI&2T28^ipKszRHsrgN%?Kw`uO2(LF%g;CQ!O>Pt4
z9@L99eiX}X*vyKX(V3wNQq>5J-*Ndd*nwR~pmy#FnowV4BCMwpJ}2{F||jkhkmfnpfgf;mojs!#?#Ts*)^ra
zM2VAmMp}DhW)?i>oHKq0z_`Uxxm~&c{jElik=zB|XG@>O|AYs0eRc6>v-lI=BVr9j
z`*)hQhon(iDar_vS&|%P+&k~r7rrM|_CuJTYExXDdjY(ZS>vo4&dmRQFzjB|wQ0b9
z^l1HzLtn`@N|2iM$MY0_RV~?u_Jvaer{GYjm4^oK=_DPx%VT$G`)b1Vl_J(F3U+%jlJd<h?w+XAL>g1a?ECz)^UCMIdW>+&PDaKarl>gf)h-NU#@t)eyp7>-{TwvU{s
z5r*_8XwFg)>i~^0RCSC*quvQK^t=ajI;Q$I$0EX-Q2NsQjE2XW@cPMUPWTbbH#&1{
z2d~mAF@+_%#HnZac4CR@Nl>kVZeZrq57{|6Y(aZ)yy|}G5s~tI8?XBB#OD7dwQB~h
ztnC#fU|7w(Qdk5_R(3`xD9&!uUeCB1_#CH7s4()sK|yxrX|Lp%A(Xo_BXTuU_eBVt
z#9_MHlbLhwlS|^rg{RCUW3vWOae_tG4gz;!v_85bG-D+Jj31QIKe*flK2_@4FCv}i
zOx<~h>nsvhbVgFN&5?K*inkzB@Bl%QD*~P;A0+g?H;8(Zarhb{@v>7u%ZQJ)dz^&o1zgv6|N}d2SVtoln_bo<`JWX
zp0?X~1SiiN`s8C_l?y)I^+oG^MCd-h69n!rzDkmMjl*mAb40EyR=VnJ$`H%C5p?>2
zucrZKl<>c2=Ra`N+T<5xj!Q^=`AkBM8dJmeNh{zT*7qYBDfYESq&V4B>MuSeyURpE
z4Z^HPUzoFNzaU;%g4PUycLdzt`v*45VD_xPlL4E}DC&`ldAVDm9x4SmJPeMh;BC!O
zMrhfud&P6PASZ67>zzKsz7}E5^g{}T*zSDlZD9a|4&+^UX-e!1o6@
zp0U?EEBh|daECcZ4Pt8%;ES0e$EG4CDIRw*cxJUo+TaoH=n9hS3#^_Ux?12^3Xvo>
zyFY2uFsV(abs)`CD9|#Lpkl)!^2bBtA$5iL^>Do&9q89*J^L}DpSsfdW$inQ>R0_!2EMzW93LwA28b*nidXdA!24Vb|w
z!a;h$pn7JIUez()mk(+!#Ga)|E6h3dcKhVCNVKZ4c`jui+P+6-)tZT3S{0+J
zN!UoZh8z)d;b@pBHyuwEDEry1Jr7+%j#M9wWN>XfG~t+FM{wXjmsbVP;Kc8tSvsDeeR%*t=1{_!O1O!
z)%TSc_nXsRw23lL0t9QRIU{;aS7(hgf1@>u0bqscOx^HUxnXj?(
zgEv^wCyOH@JV8h`(qX71th!=t!`bW1b1Zu1QWH}<%pe5%Wy{4%3E-!JJ5r?#yI1ST
zZ!*0ru^r=FF{dv+Wf`(QBI-m6?~*t>Xy`e#-;O`PBwKp(l{HVohUO})6|c}tp+B!A
zgvJTOa?m@<0X#;#&X=bs26I(-CN7me45uf@OJejd}I{M;OwV;`3?Oen916ac<%%
zE5l$)pB3TtJiB{F@eLAxQ%F^rL#JS8^Fl2ZakFz;{tzM
z@RhY82Z@aU_pU^(`{w>C`jjhgNpmu)ea%K_hfWSc6Gno=MvK;=vyZ0{&Q}x#w>_GN
zpEiJ~^jojxKNWwRp~?mD&>P_9Q81CPT-_0CbvxgAgwEH^Rkpg+SHw1D?V!Oq
z#Ji*;)O*5cv5&V4S^R=vZ@Io*7aZCO!Ba*1<)YrvHRODynEaf*{?sIqt!Q_hJ@Z&RkUPvy9OeV=&F|!XgR_A!Z}w4Fo=ucI2liF3hfGv#cDJm}=}ph-#@;
z^Yt5bMV^C76JoLVqU;>%=yV0WIhHw!VQ+UjU=jflY-$L_V-noCcH*gedH{p}}+q%sr89Vs_Z
zMfnS#VXrL~8^yEkm0*~w-|yYE`+?a>Y}7_HLN@Mbo@+C3kPpDN0=3pFxPA6iRH~{c
zEF4VcB9@(QRB*W~c>e;wd7KqgSWd87ZUpI-KM%&K6^vyo#10wE@LASc=gw>(6SgS+
ziOrCI!)9)>XXE}FzPVn?4b~IG744q(5H0D6_QLkZ)B7~pK(YI<(z&OoCJQ$V${R|E
zDsNh27Iip_o7M>oi%`{tA@^f_b(q%C<==bUXD3(=?@0c{S38=Ewx;dI$x|`8=DKp4
zW`6xHSWEH|4kgw|_VKAl!uc0t%w21KrVx8eeG>`u!Min~o$DkTX>O$1p>!ignIIC`
z+7%s3UGEA@noLb9t)yycMsNQS1n5Y+=1H0aFSS&76~`0(OD=*-$szCMj<~03+d7yu
zJF6@c7RW}Mw2DtYES}8xZ>|VdEqbnj1EPl^v`mFhyN9mw(wOrpEFon-lDGf2^A_oq?i9rwc
zv=Zq=RRvWAwryqFuTrhaR_9>*-J6FpkFRDa3+9F-yyV*fihA_Ag}87E{T!?tm0a#P
z8X66}a75`02(!)W&E&NztdlGAuu8#Ws%+!=zn7OO{#qerBFnX1a{kro1A`
z1Q+He9ea=jKUQq|>O3EoIESKQ4AUj{>2d^Z=d|u7V{P`r&7rP1+pgw6)M)k;=sih2
z-F>TogXPUyv8c{Vp8(oY`;JavWNtzm-}=*zyY@mpJEYv5+9aA3bJ44#3pIKz%e>T{
zQ<9wZjBj~DWNevGiOA8TC5no6d%z48x}^y*6^8#@c)~x&*t^fez`ad9QCDx1Ylp&|
zO;p{eesDK!>KV?DeO}L3$(Add
zu4@F8Q+;{sxXnQdq85;T8CCtXAJCb#+5ICn8U+?
zgXqNjnFlrXgd|v-Uh_R6kOUu=*|`ZYm2n^wgsk(8SlJNZwFrwwn$Egw%8N#He)w_t
z{mc0fSNl(b2M;f{o0^zhC=vZ5o%#4l=&{xV;a6)61
z70+_0cL&wgq{N7&&rU+EJB{V?HjS=+JF|R3R|#K+gu6w+k)BUd1hh(rVARTlxI{RCa*MI(
zAstE1o+s2tHlR5^FM^8J+PbJ8ibE3le*H857YMQoJ{1U@KjZ-yCw+u598YQcuXlR3brk&51|
zZS6^3dw2{)HP%mg@{ByQbAAB`Z9foZS({f}wcl0Jg}*a6xIAWAttD+bkF5)IbilZf
zo41I8DCigjn?mzje-+K1l_kQGo9AT%AifKvSSd+cygkPB+lTEiz5VTC`0&}Wgi^q)
zds>R`L}EpSvxT8}{dN>U+0>~(xdxs5cPWn(`0IyaPm~_NO}`8JZ@4f+BC@<;SF8l`?Lifc
z(*T3#@jmD{1H!cT%L
z!}(P+)eJPjwpqO~>>f;eC-yC#$H}n>8Q57o*!upjA^XNihh
z;G78J9-fnh1^pBy{Z4sgP%QBblPL!=;K>*OMHI!bFxLxzTqgHOPFoh%WiV`2H9nLn0p^M}?3pWd7>yFbJPq~USRC2E9!<57u+
z#ql6$D!NV8rb62du7+Lx79OsdI2Y+@j(=LedcX8H
z28Kyk2mS&8g+T-)k3*~Peq41r@$A;pt%gNz_c)SNQ2VJFNNZbc2Epy=5+jZx4^z@=|^G
zLmHQtl2p>X>%5&xSvA8EaQ@;`MR-S)j;rn6A88((5v!CO-;O_5Pk@-+gMiN?kLvAY
zRM;evWzMY%-ou|dDQ2ZWWwPKhyYo%nX8=)`#;snqBzfA%;d$@$nSE3$
zi$&FnqK@c4BuHMxn%60(N?*~m7w9-my<5Fnc~Hyv16=H=O=SO^<62Dv$d5B1t%yjG
z*leUASSRQY?}g`(uKp$;8rl^1RFMTX_T=8g>`p}B(+xO^cI?<&F4wc{9|Gj+rlYQrU4~Ugb>3QM}e}@a`8^IyT*Pl2j_uz(lV0wSsqi*~C`9B6>F2
zPWAwbmuXZsA1dlHS$wvJ_ZNWp{k)Ft?d|=gZ$LrTk7vsIlml()V!9qVqOjuuKM9}J
z3M;*w;0=MGF(JLQoSYo1lgGNM_chCI6X
zhbiLmrSBJb(Z*}kyzU(mtV@{qm`J-ffd0