Merge remote-tracking branch 'origin/main' into kaput-peach

This commit is contained in:
kirillk
2026-05-08 16:04:05 -04:00
48 changed files with 1561 additions and 354 deletions
+1 -3
View File
@@ -54,9 +54,7 @@ export const Flag = {
// Experimental
KILO_EXPERIMENTAL,
KILO_EXPERIMENTAL_FILEWATCHER: Config.boolean("KILO_EXPERIMENTAL_FILEWATCHER").pipe(
Config.withDefault(false),
),
KILO_EXPERIMENTAL_FILEWATCHER: Config.boolean("KILO_EXPERIMENTAL_FILEWATCHER").pipe(Config.withDefault(false)),
KILO_EXPERIMENTAL_DISABLE_FILEWATCHER: Config.boolean("KILO_EXPERIMENTAL_DISABLE_FILEWATCHER").pipe(
Config.withDefault(false),
),
+7 -6
View File
@@ -5,6 +5,7 @@ import os from "os"
import { Context, Effect, Layer } from "effect"
import { Flock } from "./util/flock"
import { markNoIndex } from "./kilocode/spotlight" // kilocode_change
import { ensureRealDir } from "./kilocode/global" // kilocode_change
import { Flag } from "./flag/flag"
const app = "kilo" // kilocode_change
@@ -42,12 +43,12 @@ export const Path = paths
Flock.setGlobal({ state })
await Promise.all([
fs.mkdir(Path.data, { recursive: true }),
fs.mkdir(Path.config, { recursive: true }),
fs.mkdir(Path.state, { recursive: true }),
fs.mkdir(Path.tmp, { recursive: true }),
fs.mkdir(Path.log, { recursive: true }),
fs.mkdir(Path.bin, { recursive: true }),
ensureRealDir(Path.data), // kilocode_change
ensureRealDir(Path.config), // kilocode_change
ensureRealDir(Path.state), // kilocode_change
ensureRealDir(Path.tmp), // kilocode_change
ensureRealDir(Path.log), // kilocode_change
ensureRealDir(Path.bin), // kilocode_change
])
// kilocode_change start - keep generated Kilo data out of macOS Spotlight
+20
View File
@@ -0,0 +1,20 @@
import fs from "fs/promises"
/**
* Like `fs.mkdir({ recursive: true })` but also repairs broken symlinks and
* junctions whose target no longer exists (a Windows edge-case where the user
* had a junction at e.g. `~/.kilocode` pointing to a deleted directory).
*
* `fs.mkdir({ recursive: true })` silently no-ops when a junction exists even
* if its target is gone, so subsequent writes inside that path fail with ENOENT.
* We detect this by calling `fs.stat` (which follows the symlink/junction) after
* mkdir: if stat fails the entry is broken and we remove + recreate it.
*/
export async function ensureRealDir(p: string) {
await fs.mkdir(p, { recursive: true })
const ok = await fs.stat(p).then(() => true).catch(() => false)
if (!ok) {
await fs.rm(p, { force: true })
await fs.mkdir(p, { recursive: true })
}
}
@@ -16,12 +16,11 @@ export function FlowDiagram({ name, height = "400px" }: { name: string; height?:
const [cssLoaded, setCssLoaded] = useState(false)
useEffect(() => {
Promise.all([
import("@xyflow/react"),
import("@xyflow/react/dist/style.css").then(() => setCssLoaded(true)),
]).then(([xyflow]) => {
setMod(xyflow)
})
Promise.all([import("@xyflow/react"), import("@xyflow/react/dist/style.css").then(() => setCssLoaded(true))]).then(
([xyflow]) => {
setMod(xyflow)
},
)
}, [])
const diagram = diagrams[name]
+59 -48
View File
@@ -3,6 +3,11 @@ import { getKiloUrlFromToken } from "../auth/token.js"
import { getDefaultHeaders, buildKiloHeaders } from "../headers.js"
import { KILO_API_BASE, KILO_OPENROUTER_BASE, MODELS_FETCH_TIMEOUT_MS, PROMPTS, AI_SDK_PROVIDERS } from "./constants.js"
export type KiloModelsResult = {
models: Record<string, any>
error?: { kind: "unauthorized" | "network" | "schema" | "http"; status?: number }
}
/**
* OpenRouter model schema
*/
@@ -63,13 +68,13 @@ function parseApiPrice(price: string | null | undefined): number | undefined {
* Fetch models from Kilo API (OpenRouter-compatible endpoint)
*
* @param options - Configuration options
* @returns Record of models in ModelsDev.Model format
* @returns Typed result with models and optional error info
*/
export async function fetchKiloModels(options?: {
kilocodeToken?: string
kilocodeOrganizationId?: string
baseURL?: string
}): Promise<Record<string, any>> {
}): Promise<KiloModelsResult> {
const token = options?.kilocodeToken
const organizationId = options?.kilocodeOrganizationId
@@ -84,54 +89,60 @@ export async function fetchKiloModels(options?: {
// Construct models endpoint
const modelsURL = `${finalBaseURL}/models`
try {
// Fetch models with timeout
const response = await fetch(modelsURL, {
headers: {
...getDefaultHeaders(),
...buildKiloHeaders(undefined, { kilocodeOrganizationId: organizationId }),
...(token ? { Authorization: `Bearer ${token}` } : {}),
},
signal: AbortSignal.timeout(MODELS_FETCH_TIMEOUT_MS),
})
const response = await fetch(modelsURL, {
headers: {
...getDefaultHeaders(),
...buildKiloHeaders(undefined, { kilocodeOrganizationId: organizationId }),
...(token ? { Authorization: `Bearer ${token}` } : {}),
},
signal: AbortSignal.timeout(MODELS_FETCH_TIMEOUT_MS),
}).catch((err: unknown) => err as Error)
if (!response.ok) {
throw new Error(`Failed to fetch models: ${response.status} ${response.statusText}`)
}
const json = await response.json()
// Validate response schema
const result = openRouterModelsResponseSchema.safeParse(json)
if (!result.success) {
console.error("Kilo models response validation failed:", result.error.format())
return {}
}
// Transform models to ModelsDev.Model format
const models: Record<string, any> = {}
for (const model of result.data.data) {
// Skip image generation models
if (model.architecture?.output_modalities?.includes("image")) {
continue
}
// Skip models that don't support tools — Kilo requires tool calling
if (!model.supported_parameters?.includes("tools")) {
continue
}
const transformedModel = transformToModelDevFormat(model)
models[model.id] = transformedModel
}
return models
} catch (error) {
console.error("Error fetching Kilo models:", error)
return {}
if (response instanceof Error) {
return { models: {}, error: { kind: "network" } }
}
if (!response.ok) {
// 401 with auth credentials: fall back to unauthenticated public endpoint
if (response.status === 401 && (token || organizationId)) {
return fetchKiloModels({})
}
const kind = response.status === 401 || response.status === 403 ? "unauthorized" : "http"
return { models: {}, error: { kind, status: response.status } }
}
const json = await response.json().catch(() => null)
if (json === null) {
return { models: {}, error: { kind: "schema" } }
}
// Validate response schema
const result = openRouterModelsResponseSchema.safeParse(json)
if (!result.success) {
return { models: {}, error: { kind: "schema" } }
}
// Transform models to ModelsDev.Model format
const models: Record<string, any> = {}
for (const model of result.data.data) {
// Skip image generation models
if (model.architecture?.output_modalities?.includes("image")) {
continue
}
// Skip models that don't support tools — Kilo requires tool calling
if (!model.supported_parameters?.includes("tools")) {
continue
}
const transformedModel = transformToModelDevFormat(model)
models[model.id] = transformedModel
}
return { models }
}
/**
-2
View File
@@ -77,7 +77,6 @@ export async function fetchOrganizationModes(token: string, organizationId: stri
})
if (!response.ok) {
console.warn(`[Kilo Gateway] Failed to fetch organization modes: ${response.status}`)
return []
}
@@ -85,7 +84,6 @@ export async function fetchOrganizationModes(token: string, organizationId: stri
const parsed = ResponseSchema.safeParse(json)
if (!parsed.success) {
console.warn("[Kilo Gateway] Organization modes response validation failed:", parsed.error.format())
return []
}
+1 -1
View File
@@ -33,7 +33,7 @@ export {
getKiloDefaultModel,
promptOrganizationSelection,
} from "./api/profile.js"
export { fetchKiloModels } from "./api/models.js"
export { fetchKiloModels, type KiloModelsResult } from "./api/models.js"
export {
EMPTY_KILO_EMBEDDING_MODEL_CATALOG,
fetchKiloEmbeddingModelCatalog,
@@ -0,0 +1,124 @@
// Verifies fetchKiloModels typed result and 401 fallback behaviour.
import { test, expect } from "bun:test"
import { fetchKiloModels } from "../../src/api/models.js"
const VALID_RESPONSE = JSON.stringify({
data: [
{
id: "test/model-a",
name: "Test Model A",
context_length: 128000,
max_completion_tokens: 16384,
architecture: {
input_modalities: ["text"],
output_modalities: ["text"],
},
supported_parameters: ["tools", "temperature"],
},
],
})
function stubFetch(fn: (input: string | URL | Request, init?: RequestInit) => Promise<Response>) {
;(globalThis as any).fetch = fn
}
test("returns empty models and error when both auth and public requests return 401", async () => {
const orig = globalThis.fetch
stubFetch(async () => new Response("Unauthorized", { status: 401, statusText: "Unauthorized" }))
const result = await fetchKiloModels({ kilocodeToken: "bad-token" })
;(globalThis as any).fetch = orig
expect(result.models).toEqual({})
expect(result.error).toBeDefined()
})
test("falls back to public endpoint on 401 and returns models", async () => {
const orig = globalThis.fetch
let callCount = 0
stubFetch(async () => {
callCount++
if (callCount === 1) {
return new Response("Unauthorized", { status: 401, statusText: "Unauthorized" })
}
return new Response(VALID_RESPONSE, {
status: 200,
headers: { "content-type": "application/json" },
})
})
const result = await fetchKiloModels({
kilocodeToken: "expired-token",
kilocodeOrganizationId: "org-123",
})
;(globalThis as any).fetch = orig
expect(callCount).toBe(2)
expect(result.error).toBeUndefined()
expect(Object.keys(result.models).length).toBeGreaterThan(0)
})
test("returns error with kind=network on fetch exception", async () => {
const orig = globalThis.fetch
stubFetch(async () => {
throw new Error("network error")
})
const result = await fetchKiloModels({})
;(globalThis as any).fetch = orig
expect(result.models).toEqual({})
expect(result.error?.kind).toBe("network")
})
test("returns error with kind=http on non-auth HTTP error (e.g. 500)", async () => {
const orig = globalThis.fetch
stubFetch(async () => new Response("Server Error", { status: 500, statusText: "Internal Server Error" }))
const result = await fetchKiloModels({})
;(globalThis as any).fetch = orig
expect(result.models).toEqual({})
expect(result.error?.kind).toBe("http")
expect(result.error?.status).toBe(500)
})
test("returns models without error on success", async () => {
const orig = globalThis.fetch
stubFetch(async () =>
new Response(VALID_RESPONSE, {
status: 200,
headers: { "content-type": "application/json" },
}),
)
const result = await fetchKiloModels({})
;(globalThis as any).fetch = orig
expect(result.error).toBeUndefined()
expect(Object.keys(result.models).length).toBeGreaterThan(0)
})
test("returns error with kind=schema when response body is invalid JSON", async () => {
const orig = globalThis.fetch
stubFetch(async () =>
new Response("not valid json{{{{", {
status: 200,
headers: { "content-type": "application/json" },
}),
)
const result = await fetchKiloModels({})
;(globalThis as any).fetch = orig
expect(result.models).toEqual({})
expect(result.error?.kind).toBe("schema")
})
@@ -164,7 +164,8 @@ export class CodeIndexConfigManager {
// LanceDB doesn't need a qdrant URL; qdrant does
const hasStore = isLancedb || !!qdrant
if (provider === "kilo") return !!(this.kiloOptions?.apiKey && this.modelId && this.currentModelDimension && hasStore)
if (provider === "kilo")
return !!(this.kiloOptions?.apiKey && this.modelId && this.currentModelDimension && hasStore)
if (provider === "openai") return !!(this.openAiOptions?.apiKey && hasStore)
if (provider === "ollama") return !!(this.ollamaOptions?.baseUrl && hasStore)
if (provider === "openai-compatible")
@@ -118,7 +118,7 @@ const WithSessions: ParentComponent<{ sessions?: typeof mockSessions }> = (props
session_diff: {},
message: {},
part: {},
provider: { all: [], connected: [] as string[], default: {} as any },
provider: { all: [], connected: [] as string[], default: {} as any, failed: [] as string[] },
}}
directory="/project/"
>
+4
View File
@@ -70,3 +70,7 @@ Hono-based HTTP server with OpenAPI spec generation. SSE for real-time events. W
## Providers and Models
Uses the **Vercel AI SDK** as the abstraction layer. Providers are loaded from a bundled map or dynamically installed at runtime. Models come from models.dev (external API), cached locally.
## Fork Isolation Rule
`opencode/` is a fork of upstream opencode. When a change must touch a shared upstream file, extract the Kilo-specific logic into a mirror file under `src/kilocode/<same/path>.ts` (tests under `test/kilocode/<same/path>.test.ts`) and call into it from the upstream file behind a single `kilocode_change` marker. Example: a Kilo override for `src/cli/cmd/tui/component/dialog-provider.tsx` lives at `src/kilocode/cli/cmd/tui/component/dialog-provider.tsx`. Avoid inlining Kilo-specific logic directly into shared upstream files. Files and directories whose path contains `kilocode` never need `kilocode_change` markers.
-1
View File
@@ -1,4 +1,3 @@
import { EOL } from "os"
import { Effect } from "effect"
import { Provider } from "@/provider/provider"
@@ -33,14 +33,20 @@ export function createDialogProviderOptions() {
map((provider) => {
const consoleManaged = isConsoleManagedProvider(sync.data.console_state.consoleManagedProviders, provider.id)
const connected = sync.data.provider_next.connected.includes(provider.id)
// kilocode_change start
const failed = sync.data.provider_next.failed ?? []
const failedGutter = KiloProvider.renderGutter(provider.id, failed, theme)
const failedDesc = KiloProvider.failedDescription(provider.id, failed)
const baseDesc = KiloProvider.PROVIDER_DESCRIPTIONS[provider.id]
// kilocode_change end
return {
title: KiloProvider.PROVIDER_TITLES[provider.id] ?? provider.name, // kilocode_change
value: provider.id,
description: KiloProvider.PROVIDER_DESCRIPTIONS[provider.id], // kilocode_change
description: failedDesc ?? baseDesc, // kilocode_change
footer: consoleManaged ? sync.data.console_state.activeOrgName : undefined,
category: provider.id in PROVIDER_PRIORITY ? "Popular" : "Other",
gutter: connected && onboarded() ? () => <text fg={theme.success}></text> : undefined,
gutter: failedGutter ?? (connected && onboarded() ? () => <text fg={theme.success}></text> : undefined), // kilocode_change
async onSelect() {
if (consoleManaged) return
@@ -98,6 +98,7 @@ export const { use: useSync, provider: SyncProvider } = createSimpleContext({
all: [],
default: {},
connected: [],
failed: [], // kilocode_change
},
console_state: emptyConsoleState,
provider_auth: {},
+1 -1
View File
@@ -544,7 +544,7 @@ export const layer = Layer.effect(
)
.pipe(
Effect.catchIf(
(e) => e.reason._tag === "PermissionDenied",
(e) => e.reason._tag === "PermissionDenied" || e.reason._tag === "NotFound", // kilocode_change - also ignore NotFound (broken symlink/junction on Windows)
() => Effect.void,
),
)
@@ -432,13 +432,7 @@ export function patchAgents(
description: "Get answers and explanations without making changes to the codebase.",
prompt: PROMPT_ASK,
options: {},
permission: Permission.merge(
defaults,
askGuard(kilo.mcpRules),
user,
askEditGuard(),
denies(user),
),
permission: Permission.merge(defaults, askGuard(kilo.mcpRules), user, askEditGuard(), denies(user)),
mode: "primary",
native: true,
}
@@ -11,6 +11,36 @@ import type { RGBA } from "@opentui/core"
import type { ProviderAuthAuthorization } from "@kilocode/sdk/v2"
import { KiloAutoMethod } from "@/kilocode/components/dialog-kilo-auto-method"
// ---------------------------------------------------------------------------
// Failed-state gutter/description helpers
// ---------------------------------------------------------------------------
/**
* Returns a red `!` gutter element when the provider is in a failed auth state,
* or `undefined` if not failed and not connected (falls through to default check).
*/
export function renderGutter(
providerID: string,
failed: string[],
theme: { error: RGBA },
): (() => JSX.Element) | undefined {
if (!failed.includes(providerID)) return undefined
return () => <text fg={theme.error}>!</text>
}
/**
* Returns a description suffix when the provider has encountered an error,
* or `undefined` to leave the default description unchanged.
*
* NOTE: The sync state only carries failed provider IDs, not the error kind.
* A generic message is used so it remains accurate for auth, network, and
* schema failure types alike.
*/
export function failedDescription(providerID: string, failed: string[]): string | undefined {
if (!failed.includes(providerID)) return undefined
return "(connection error — click to reconnect)"
}
// ---------------------------------------------------------------------------
// Provider priority (replaces upstream map entirely)
// ---------------------------------------------------------------------------
@@ -28,9 +28,9 @@ export function submitFeedback(rating: "up" | "down", dialog: DialogContext, ctx
return
}
const revertID = ctx.session()?.revert?.messageID
const lastAssistant = ctx.messages().findLast(
(msg): msg is AssistantMessage => msg.role === "assistant" && (!revertID || msg.id < revertID),
)
const lastAssistant = ctx
.messages()
.findLast((msg): msg is AssistantMessage => msg.role === "assistant" && (!revertID || msg.id < revertID))
if (!lastAssistant) {
ctx.toast.show({ message: "No assistant messages found", variant: "error" })
dialog.clear()
@@ -9,10 +9,7 @@
import { useDialog } from "@tui/ui/dialog"
import { DialogSelect, type DialogSelectOption } from "@tui/ui/dialog-select"
import { DialogPrompt } from "@tui/ui/dialog-prompt"
import {
getKiloEmbeddingModel,
normalizeKiloEmbeddingModelId,
} from "@kilocode/kilo-indexing/embedding-models"
import { getKiloEmbeddingModel, normalizeKiloEmbeddingModelId } from "@kilocode/kilo-indexing/embedding-models"
import { useSync } from "@tui/context/sync"
import { useToast } from "@tui/ui/toast"
import { createResource } from "solid-js"
@@ -522,13 +519,17 @@ export function DialogIndexing(props: DialogIndexingProps) {
}
case "projectToggle": {
if (globalCfg().enabled) {
toast.show({ message: "Global indexing is enabled, so this project is already covered.", variant: "info" })
toast.show({
message: "Global indexing is enabled, so this project is already covered.",
variant: "info",
})
dialog.replace(() => <DialogIndexing useSDK={props.useSDK} />)
break
}
const current = getIndexing(sync)
const enabled = !indexing.enabled
const updated = enabled && !current.provider && hasKiloAuth(sync) ? { ...defaultIndexing(sync), enabled } : { enabled }
const updated =
enabled && !current.provider && hasKiloAuth(sync) ? { ...defaultIndexing(sync), enabled } : { enabled }
await saveProjectIndexing(sdk, sync, updated, toast)
dialog.replace(() => <DialogIndexing useSDK={props.useSDK} />)
break
@@ -26,10 +26,7 @@ export namespace KiloCompactionPayloadRecovery {
].join("\n\n")
}
export function strip(input: {
messages: MessageV2.WithParts[]
update: Update
}) {
export function strip(input: { messages: MessageV2.WithParts[]; update: Update }) {
return Effect.forEach(
input.messages,
(msg) =>
@@ -79,26 +79,28 @@ export namespace KiloSessionPrompt {
yield* input.sessions.removeMessage({ sessionID: input.sessionID, messageID: tail.info.id })
})
export const recoverProviderFinishError = Effect.fn("KiloSessionPrompt.recoverProviderFinishError")(function* (input: {
sessionID: SessionID
status: Pick<SessionStatus.Interface, "get">
sessions: Pick<Session.Interface, "messages" | "removeMessage">
}) {
const state = yield* input.status.get(input.sessionID)
if (state.type !== "idle") return
export const recoverProviderFinishError = Effect.fn("KiloSessionPrompt.recoverProviderFinishError")(
function* (input: {
sessionID: SessionID
status: Pick<SessionStatus.Interface, "get">
sessions: Pick<Session.Interface, "messages" | "removeMessage">
}) {
const state = yield* input.status.get(input.sessionID)
if (state.type !== "idle") return
const msgs = yield* input.sessions.messages({ sessionID: input.sessionID, limit: 2 })
const tail = msgs.at(-1)
if (!tail || tail.info.role !== "assistant") return
if (tail.info.finish !== "error" || tail.info.error) return
if (!tail.parts.some((part) => part.type === "step-finish" && part.reason === "error")) return
const msgs = yield* input.sessions.messages({ sessionID: input.sessionID, limit: 2 })
const tail = msgs.at(-1)
if (!tail || tail.info.role !== "assistant") return
if (tail.info.finish !== "error" || tail.info.error) return
if (!tail.parts.some((part) => part.type === "step-finish" && part.reason === "error")) return
const prev = msgs.at(-2)
if (!prev || prev.info.role !== "user") return
if (tail.info.parentID !== prev.info.id) return
const prev = msgs.at(-2)
if (!prev || prev.info.role !== "user") return
if (tail.info.parentID !== prev.info.id) return
yield* input.sessions.removeMessage({ sessionID: input.sessionID, messageID: tail.info.id })
})
yield* input.sessions.removeMessage({ sessionID: input.sessionID, messageID: tail.info.id })
},
)
export function guardPermissions(input: {
agent: { name: string; permission: Permission.Ruleset }
+11 -4
View File
@@ -39,17 +39,24 @@ export const layer = Layer.effect(
const run = Effect.gen(function* () {
const ctx = yield* InstanceState.context
yield* Effect.logInfo("bootstrapping", { directory: ctx.directory })
yield* Effect.logDebug("bootstrapping", { directory: ctx.directory }) // kilocode_change - was logInfo; downgraded to avoid printing to TUI on every startup
// everything depends on config so eager load it for nice traces
yield* config.get()
// Plugin can mutate config so it has to be initialized before anything else.
yield* plugin.init()
yield* Effect.promise(() => KilocodeBootstrap.init()).pipe(Effect.forkDetach) // kilocode_change
// kilocode_change start - shareNext removed from list, handled by KilocodeBootstrap
yield* Effect.all(
[lsp, /* shareNext, kilocode_change - handled by KilocodeBootstrap */ format, file, fileWatcher, vcs, snapshot].map(
(s) => Effect.forkDetach(s.init()),
),
[
lsp,
format,
file,
fileWatcher,
vcs,
snapshot,
].map((s) => Effect.forkDetach(s.init())),
).pipe(Effect.withSpan("InstanceBootstrap.init"))
// kilocode_change end
const projectID = ctx.project.id
yield* bus.subscribeCallback(Command.Event.Executed, async (payload) => {
+67 -45
View File
@@ -1,5 +1,5 @@
// kilocode_change new file
import { fetchKiloModels } from "@kilocode/kilo-gateway"
// kilocode_change - new file
import { fetchKiloModels, type KiloModelsResult } from "@kilocode/kilo-gateway"
import { Config } from "../config/config"
import { Auth } from "../auth"
import * as Log from "@opencode-ai/core/util/log"
@@ -19,6 +19,23 @@ export namespace ModelCache {
const TTL = 5 * 60 * 1000 // 5 minutes
const inFlightRefresh = new Map<string, Promise<Record<string, any>>>()
// Per-provider failure tracking
const failures = new Map<string, KiloModelsResult["error"]>()
/**
* Get the failure state for a provider (undefined = no failure)
*/
export function getFailure(providerID: string): KiloModelsResult["error"] | undefined {
return failures.get(providerID)
}
/**
* Get all provider IDs that have a failure state
*/
export function failedProviders(): string[] {
return [...failures.keys()]
}
/**
* Get cached models if available and not expired
* @param providerID - Provider identifier (e.g., "kilo")
@@ -61,24 +78,30 @@ export namespace ModelCache {
// Cache miss - fetch models
log.info("fetching models", { providerID })
try {
const authOptions = await getAuthOptions(providerID)
const mergedOptions = { ...authOptions, ...options }
const models = await fetchModels(providerID, mergedOptions)
// Store in cache
cache.set(providerID, {
models,
timestamp: Date.now(),
})
log.info("models fetched and cached", { providerID, count: Object.keys(models).length })
return models
} catch (error) {
log.error("failed to fetch models", { providerID, error })
const authOptions = await getAuthOptions(providerID).catch((err) => {
log.warn("getAuthOptions failed", { providerID, err })
return {}
})
const mergedOptions = { ...authOptions, ...options }
const result = await fetchModels(providerID, mergedOptions)
const { models } = result
if (result.error) {
failures.set(providerID, result.error)
log.warn("model fetch error", { providerID, error: result.error })
} else {
failures.delete(providerID)
}
// Store in cache (even on error, to avoid hammering the API)
cache.set(providerID, {
models,
timestamp: Date.now(),
})
log.info("models fetched and cached", { providerID, count: Object.keys(models).length })
return models
}
/**
@@ -100,32 +123,29 @@ export namespace ModelCache {
const refreshPromise = (async () => {
log.info("refreshing models", { providerID })
try {
const authOptions = await getAuthOptions(providerID)
const mergedOptions = { ...authOptions, ...options }
const models = await fetchModels(providerID, mergedOptions)
// Update cache with new models
cache.set(providerID, {
models,
timestamp: Date.now(),
})
log.info("models refreshed", { providerID, count: Object.keys(models).length })
return models
} catch (error) {
log.error("failed to refresh models", { providerID, error })
// Return existing cache or empty object
const cached = cache.get(providerID)
if (cached) {
log.debug("returning stale cache after refresh failure", { providerID })
return cached.models
}
const authOptions = await getAuthOptions(providerID).catch((err) => {
log.warn("getAuthOptions failed during refresh", { providerID, err })
return {}
})
const mergedOptions = { ...authOptions, ...options }
const result = await fetchModels(providerID, mergedOptions)
const { models } = result
if (result.error) {
failures.set(providerID, result.error)
log.warn("model refresh error", { providerID, error: result.error })
} else {
failures.delete(providerID)
}
cache.set(providerID, {
models,
timestamp: Date.now(),
})
log.info("models refreshed", { providerID, count: Object.keys(models).length })
return models
})()
// Track in-flight refresh
@@ -145,6 +165,7 @@ export namespace ModelCache {
*/
export function clear(providerID: string): void {
const deleted = cache.delete(providerID)
failures.delete(providerID)
if (deleted) {
log.info("cache cleared", { providerID })
} else {
@@ -158,20 +179,21 @@ export namespace ModelCache {
* @param options - Provider options
* @returns Fetched models
*/
async function fetchModels(providerID: string, options: any): Promise<Record<string, any>> {
async function fetchModels(providerID: string, options: any): Promise<KiloModelsResult> {
if (providerID === "kilo") {
return fetchKiloModels(options)
}
// kilocode_change start
if (providerID === "apertis") {
return fetchApertisModels(options)
const models = await fetchApertisModels(options)
return { models }
}
// kilocode_change end
// Other providers not implemented yet
log.debug("provider not implemented", { providerID })
return {}
return { models: {} }
}
// kilocode_change start
@@ -956,6 +956,7 @@ export const ListResult = Schema.Struct({
all: Schema.Array(Info),
default: DefaultModelIDs,
connected: Schema.Array(Schema.String),
failed: Schema.Array(Schema.String), // kilocode_change
}).pipe(withStatics((s) => ({ zod: zod(s) })))
export type ListResult = Types.DeepMutable<Schema.Schema.Type<typeof ListResult>>
@@ -3,7 +3,8 @@ import { Config } from "@/config/config"
import { ModelsDev } from "@/provider/models"
import { Provider } from "@/provider/provider"
import { ProviderID } from "@/provider/schema"
import { mapValues } from "remeda"
import { mapValues, pickBy } from "remeda" // kilocode_change
import { ModelCache } from "@/provider/model-cache" // kilocode_change
import { Effect, Schema } from "effect"
import { HttpServerRequest, HttpServerResponse } from "effect/unstable/http"
import { HttpApiBuilder, HttpApiError } from "effect/unstable/httpapi"
@@ -29,11 +30,22 @@ export const providerHandlers = HttpApiBuilder.group(InstanceHttpApi, "provider"
mapValues(filtered, (item) => Provider.fromModelsDevProvider(item)),
connected,
)
// kilocode_change start
const failed = ModelCache.failedProviders()
// Note: connected only contains providers with non-empty models after Provider.Service.list(),
// so failed must be checked explicitly for providers whose fetch returned an error.
const failedSet = new Set(failed)
const validProviders = pickBy(
providers,
(item, id) => Object.keys(item.models).length > 0 || id in connected || failedSet.has(id),
)
return {
all: Object.values(providers),
default: Provider.defaultModelIDs(providers),
all: Object.values(validProviders),
default: Provider.defaultModelIDs(pickBy(validProviders, (item) => Object.keys(item.models).length > 0)),
connected: Object.keys(connected),
failed,
}
// kilocode_change end
})
const auth = Effect.fn("ProviderHttpApi.auth")(function* () {
@@ -274,19 +274,22 @@ export const sessionHandlers = HttpApiBuilder.group(InstanceHttpApi, "session",
params: { sessionID: SessionID }
payload: typeof PromptPayload.Type
}) {
// kilocode_change - cast to bridge schema-readonly→PromptInput-mutable; matches legacy Hono session.ts
yield* promptSvc.prompt({ ...ctx.payload, sessionID: ctx.params.sessionID } as unknown as SessionPrompt.PromptInput).pipe(
Effect.catchCause((cause) =>
Effect.gen(function* () {
yield* Effect.logError("prompt_async failed", { sessionID: ctx.params.sessionID, cause })
yield* bus.publish(Session.Event.Error, {
sessionID: ctx.params.sessionID,
error: new NamedError.Unknown({ message: Cause.pretty(cause) }).toObject(),
})
}),
),
Effect.forkIn(scope, { startImmediately: true }),
)
// kilocode_change start - cast to bridge schema-readonly→PromptInput-mutable; matches legacy Hono session.ts
yield* promptSvc
.prompt({ ...ctx.payload, sessionID: ctx.params.sessionID } as unknown as SessionPrompt.PromptInput)
.pipe(
Effect.catchCause((cause) =>
Effect.gen(function* () {
yield* Effect.logError("prompt_async failed", { sessionID: ctx.params.sessionID, cause })
yield* bus.publish(Session.Event.Error, {
sessionID: ctx.params.sessionID,
error: new NamedError.Unknown({ message: Cause.pretty(cause) }).toObject(),
})
}),
),
Effect.forkIn(scope, { startImmediately: true }),
)
// kilocode_change end
return HttpApiSchema.NoContent.make()
})
@@ -82,7 +82,14 @@ export const ProjectRoutes = lazy(() =>
Project.Service.use((svc) => svc.initGit({ directory: dir, project: prev })),
)
if (next.id === prev.id && next.vcs === prev.vcs && next.worktree === prev.worktree) return c.json(next)
await InstanceStore.reloadInstance({ directory: dir, worktree: dir, project: next, init: await getBootstrapRunEffect() })
// kilocode_change start
await InstanceStore.reloadInstance({
directory: dir,
worktree: dir,
project: next,
init: await getBootstrapRunEffect(),
})
// kilocode_change end
return c.json(next)
},
)
@@ -7,6 +7,7 @@ import { ModelsDev } from "@/provider/models"
import { ProviderAuth } from "@/provider/auth"
import { ProviderID } from "@/provider/schema"
import { mapValues, pickBy } from "remeda" // kilocode_change
import { ModelCache } from "@/provider/model-cache" // kilocode_change
import { errors } from "../../error"
import { lazy } from "@/util/lazy"
import { Effect } from "effect"
@@ -50,12 +51,21 @@ export const ProviderRoutes = lazy(() =>
mapValues(filtered, (x) => Provider.fromModelsDevProvider(x)),
connected,
)
// kilocode_change start: Filter out providers with no models to prevent crashes
const validProviders = pickBy(providers, (item) => Object.keys(item.models).length > 0)
// kilocode_change start
const failed = ModelCache.failedProviders()
// Keep connected or failed providers even when they have 0 models so /connect can re-auth them.
// Note: connected only contains providers whose model list is non-empty after Provider.Service.list(),
// so failed must be checked explicitly for providers whose fetch returned an error.
const failedSet = new Set(failed)
const validProviders = pickBy(
providers,
(item, id) => Object.keys(item.models).length > 0 || id in connected || failedSet.has(id),
)
return {
all: Object.values(validProviders),
default: Provider.defaultModelIDs(validProviders),
default: Provider.defaultModelIDs(pickBy(validProviders, (item) => Object.keys(item.models).length > 0)),
connected: Object.keys(connected),
failed,
}
// kilocode_change end
}),
+1 -3
View File
@@ -84,9 +84,7 @@ export const layer: Layer.Layer<
}
// kilocode_change - prefer KILO_CONFIG_DIR profile when set, else fall back to global.config
const root = Flag.KILO_CONFIG_DIR ?? global.config
return yield* fs
.globUp(instruction, root, root)
.pipe(Effect.catch(() => Effect.succeed([] as string[])))
return yield* fs.globUp(instruction, root, root).pipe(Effect.catch(() => Effect.succeed([] as string[]))) // kilocode_change
})
const read = Effect.fnUntraced(function* (filepath: string) {
+1 -1
View File
@@ -307,7 +307,7 @@ export const layer: Layer.Layer<
// kilocode_change start
!!process.env["KILO_E2E_LLM_URL"] ||
(input.modelID.includes("gpt-") && !input.modelID.includes("oss") && !input.modelID.includes("gpt-4"))
// kilocode_change end
// kilocode_change end
if (tool.id === ApplyPatchTool.id) return usePatch
if (tool.id === EditTool.id) return !usePatch // kilocode_change
@@ -22,23 +22,26 @@ const writeConfig = (dir: string, agent: Config.Info["agent"]) =>
),
)
it.live("agent color parsed from project config", () =>
// kilocode_change start
it.live("agent color parsed from project config", () =>
Effect.gen(function* () {
const dir = yield* tmpdirScoped()
yield* writeConfig(dir, {
code: { color: "#FFA500" }, // kilocode_change
code: { color: "#FFA500" },
plan: { color: "primary" },
})
yield* Effect.gen(function* () {
yield* Effect.gen(function* () {
const cfg = yield* Effect.promise(() => AppRuntime.runPromise(Config.Service.use((svc) => svc.get())))
expect(cfg.agent?.["code"]?.color).toBe("#FFA500") // kilocode_change
expect(cfg.agent?.["code"]?.color).toBe("#FFA500")
expect(cfg.agent?.["plan"]?.color).toBe("primary")
}).pipe(provideInstance(dir))
}),
)
// kilocode_change end
it.live("Agent.get includes color from config", () =>
// kilocode_change start
it.live("Agent.get includes color from config", () =>
Effect.gen(function* () {
const dir = yield* tmpdirScoped()
yield* writeConfig(dir, {
@@ -54,6 +57,7 @@ it.live("Agent.get includes color from config", () =>
}).pipe(provideInstance(dir))
}),
)
// kilocode_change end
test("Color.hexToAnsiBold converts valid hex to ANSI", () => {
const result = Color.hexToAnsiBold("#FFA500")
@@ -22,10 +22,12 @@ describe("Kilo indexing auth resolution", () => {
expect(resolveKiloIndexingAuth({ provider: { options: { kilocodeToken: "provider-token" } } }).apiKey).toBe(
"provider-token",
)
expect(resolveKiloIndexingAuth({ auth: { type: "oauth", access: "oauth-token", accountId: "org_oauth" } })).toEqual({
apiKey: "oauth-token",
organizationId: "org_oauth",
})
expect(resolveKiloIndexingAuth({ auth: { type: "oauth", access: "oauth-token", accountId: "org_oauth" } })).toEqual(
{
apiKey: "oauth-token",
organizationId: "org_oauth",
},
)
expect(resolveKiloIndexingAuth({ env: { KILO_API_KEY: "env-token", KILO_ORG_ID: "org_env" } })).toEqual({
apiKey: "env-token",
organizationId: "org_env",
@@ -17,17 +17,19 @@ const real = await import("@kilocode/kilo-gateway")
mock.module("@kilocode/kilo-gateway", () => ({
...real,
fetchKiloModels: async () => ({
"free-model": {
id: "free-model",
name: "Free Model",
cost: { input: 0, output: 0 },
limit: { context: 128000, output: 4096 },
},
"paid-model": {
id: "paid-model",
name: "Paid Model",
cost: { input: 1.0, output: 2.0 },
limit: { context: 128000, output: 4096 },
models: {
"free-model": {
id: "free-model",
name: "Free Model",
cost: { input: 0, output: 0 },
limit: { context: 128000, output: 4096 },
},
"paid-model": {
id: "paid-model",
name: "Paid Model",
cost: { input: 1.0, output: 2.0 },
limit: { context: 128000, output: 4096 },
},
},
}),
}))
@@ -0,0 +1,53 @@
// kilocode_change - new file
// Integration: when fetchKiloModels returns a 401 error result, ModelCache
// surfaces the failure and caches empty models (allowing re-auth via /connect).
// The real 401-fallback unit test lives in packages/kilo-gateway/test/api/models.test.ts.
import { test, expect, mock } from "bun:test"
import path from "path"
import * as Log from "@opencode-ai/core/util/log"
Log.init({ print: false })
// Simulate a 401 typed error result from the gateway
mock.module("@kilocode/kilo-gateway", () => ({
fetchKiloModels: async () => ({
models: {},
error: { kind: "unauthorized", status: 401 },
}),
KILO_OPENROUTER_BASE: "https://api.kilo.ai/api/openrouter",
}))
mock.module("opencode-copilot-auth", () => ({ default: () => ({}) }))
mock.module("opencode-anthropic-auth", () => ({ default: () => ({}) }))
mock.module("@gitlab/opencode-gitlab-auth", () => ({ default: () => ({}) }))
import { tmpdir } from "../fixture/fixture"
import { Instance } from "../../src/project/instance"
import { ModelCache } from "../../src/provider/model-cache"
const CONFIG = JSON.stringify({ $schema: "https://app.kilo.ai/config.json" })
async function withInstance<T>(fn: () => Promise<T>): Promise<T> {
await using tmp = await tmpdir({
init: async (dir) => {
await Bun.write(path.join(dir, "kilo.json"), CONFIG)
},
})
return Instance.provide({ directory: tmp.path, fn })
}
test("401 from gateway sets provider as failed in ModelCache", async () => {
ModelCache.clear("kilo")
await withInstance(() => ModelCache.fetch("kilo"))
expect(ModelCache.failedProviders()).toContain("kilo")
expect(ModelCache.getFailure("kilo")).toMatchObject({ kind: "unauthorized", status: 401 })
})
test("401 from gateway caches empty models (not undefined)", async () => {
ModelCache.clear("kilo")
await withInstance(() => ModelCache.fetch("kilo"))
const cached = ModelCache.get("kilo")
expect(cached).toBeDefined()
expect(Object.keys(cached!)).toHaveLength(0)
})
@@ -16,11 +16,13 @@ mock.module("@kilocode/kilo-gateway", () => ({
fetchKiloModels: async (options: any) => {
captured = options
return {
"test-model": {
id: "test-model",
name: "Test Model",
cost: { input: 0.001, output: 0.002 },
limit: { context: 128000, output: 4096 },
models: {
"test-model": {
id: "test-model",
name: "Test Model",
cost: { input: 0.001, output: 0.002 },
limit: { context: 128000, output: 4096 },
},
},
}
},
@@ -0,0 +1,91 @@
// kilocode_change - new file
// Verifies that:
// 1. ModelCache.failedProviders() surfaces providers that encountered errors.
// 2. ModelCache.getFailure() returns the typed error for a failed provider.
// 3. Clear removes failure state.
import { test, expect, mock } from "bun:test"
import path from "path"
import * as Log from "@opencode-ai/core/util/log"
Log.init({ print: false })
// Stub fetchKiloModels to return controlled typed results.
let stubbedResult: { models: Record<string, any>; error?: { kind: string; status?: number } } = { models: {} }
mock.module("@kilocode/kilo-gateway", () => ({
fetchKiloModels: async () => stubbedResult,
KILO_OPENROUTER_BASE: "https://api.kilo.ai/api/openrouter",
}))
mock.module("opencode-copilot-auth", () => ({ default: () => ({}) }))
mock.module("opencode-anthropic-auth", () => ({ default: () => ({}) }))
mock.module("@gitlab/opencode-gitlab-auth", () => ({ default: () => ({}) }))
import { tmpdir } from "../fixture/fixture"
import { Instance } from "../../src/project/instance"
import { ModelCache } from "../../src/provider/model-cache"
const CONFIG = JSON.stringify({ $schema: "https://app.kilo.ai/config.json" })
async function withInstance<T>(fn: () => Promise<T>): Promise<T> {
await using tmp = await tmpdir({
init: async (dir) => {
await Bun.write(path.join(dir, "kilo.json"), CONFIG)
},
})
return Instance.provide({ directory: tmp.path, fn })
}
test("failedProviders returns empty array when no fetch has occurred", () => {
ModelCache.clear("kilo")
expect(ModelCache.failedProviders()).not.toContain("kilo")
})
test("getFailure returns undefined when fetch succeeds", async () => {
stubbedResult = {
models: {
"test/model": { id: "test/model", name: "Test", cost: { input: 1, output: 2 }, limit: { context: 128000, output: 4096 } },
},
}
ModelCache.clear("kilo")
await withInstance(() => ModelCache.fetch("kilo"))
expect(ModelCache.getFailure("kilo")).toBeUndefined()
expect(ModelCache.failedProviders()).not.toContain("kilo")
})
test("failedProviders includes provider after auth error", async () => {
stubbedResult = { models: {}, error: { kind: "unauthorized", status: 401 } }
ModelCache.clear("kilo")
await withInstance(() => ModelCache.fetch("kilo"))
expect(ModelCache.failedProviders()).toContain("kilo")
expect(ModelCache.getFailure("kilo")).toMatchObject({ kind: "unauthorized", status: 401 })
})
test("clear removes failure state", async () => {
stubbedResult = { models: {}, error: { kind: "network" } }
ModelCache.clear("kilo")
await withInstance(() => ModelCache.fetch("kilo"))
expect(ModelCache.failedProviders()).toContain("kilo")
ModelCache.clear("kilo")
expect(ModelCache.failedProviders()).not.toContain("kilo")
expect(ModelCache.getFailure("kilo")).toBeUndefined()
})
test("failure state is cleared when subsequent fetch succeeds", async () => {
stubbedResult = { models: {}, error: { kind: "unauthorized", status: 401 } }
ModelCache.clear("kilo")
await withInstance(() => ModelCache.fetch("kilo"))
expect(ModelCache.failedProviders()).toContain("kilo")
stubbedResult = {
models: {
"test/model": { id: "test/model", name: "Test", cost: { input: 1, output: 2 }, limit: { context: 128000, output: 4096 } },
},
}
ModelCache.clear("kilo")
await withInstance(() => ModelCache.fetch("kilo"))
expect(ModelCache.failedProviders()).not.toContain("kilo")
expect(ModelCache.getFailure("kilo")).toBeUndefined()
})
@@ -37,9 +37,7 @@ describe("Kilo Session.list", () => {
db.update(SessionTable).set({ project_id: project }).where(eq(SessionTable.id, session.id)).run()
})
const sessions = await AppRuntime.runPromise(
Session.Service.use((svc) => svc.list({ directory: tmp.path })),
)
const sessions = await AppRuntime.runPromise(Session.Service.use((svc) => svc.list({ directory: tmp.path })))
const ids = sessions.map((item) => item.id)
expect(ids).toContain(session.id)
@@ -203,7 +203,8 @@ test("BrowserOpenFailed event is NOT published when open() succeeds", async () =
await Instance.provide({
directory: tmp.path,
fn: async () => { // kilocode_change
fn: async () => {
// kilocode_change
openShouldFail = false // kilocode_change
const events: Array<{ mcpName: string; url: string }> = []
@@ -259,7 +260,8 @@ test("open() is called with the authorization URL", async () => {
await Instance.provide({
directory: tmp.path,
fn: async () => { // kilocode_change
fn: async () => {
// kilocode_change
openShouldFail = false // kilocode_change
openCalledWith = undefined
+1
View File
@@ -3029,6 +3029,7 @@ export type ProviderListResponses = {
[key: string]: string
}
connected: Array<string>
failed: Array<string>
}
}
+1
View File
@@ -5128,6 +5128,7 @@ export type ProviderListResponses = {
[key: string]: string
}
connected: Array<string>
failed: Array<string>
}
}
+252 -139
View File
@@ -415,9 +415,9 @@
]
}
},
"/experimental/workspace/adaptor": {
"/experimental/workspace/adapter": {
"get": {
"operationId": "experimental.workspace.adaptor.list",
"operationId": "experimental.workspace.adapter.list",
"parameters": [
{
"in": "query",
@@ -434,11 +434,11 @@
}
}
],
"summary": "List workspace adaptors",
"description": "List all available workspace adaptors for the current project.",
"summary": "List workspace adapters",
"description": "List all available workspace adapters for the current project.",
"responses": {
"200": {
"description": "Workspace adaptors",
"description": "Workspace adapters",
"content": {
"application/json": {
"schema": {
@@ -466,7 +466,7 @@
"x-codeSamples": [
{
"lang": "js",
"source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.experimental.workspace.adaptor.list({\n ...\n})"
"source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.experimental.workspace.adapter.list({\n ...\n})"
}
]
}
@@ -5549,9 +5549,15 @@
"items": {
"type": "string"
}
},
"failed": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": ["all", "default", "connected"]
"required": ["all", "default", "connected", "failed"]
}
}
}
@@ -8332,6 +8338,47 @@
]
}
},
"/indexing/status": {
"get": {
"operationId": "indexing.status",
"parameters": [
{
"in": "query",
"name": "directory",
"schema": {
"type": "string"
}
},
{
"in": "query",
"name": "workspace",
"schema": {
"type": "string"
}
}
],
"summary": "Get indexing status",
"description": "Retrieve the current code indexing status for the active project.",
"responses": {
"200": {
"description": "Indexing status",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/IndexingStatus"
}
}
}
}
},
"x-codeSamples": [
{
"lang": "js",
"source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.indexing.status({\n ...\n})"
}
]
}
},
"/suggestion": {
"get": {
"operationId": "suggestion.list",
@@ -8607,6 +8654,72 @@
]
}
},
"/telemetry/setEnabled": {
"post": {
"operationId": "telemetry.setEnabled",
"parameters": [
{
"in": "query",
"name": "directory",
"schema": {
"type": "string"
}
},
{
"in": "query",
"name": "workspace",
"schema": {
"type": "string"
}
}
],
"summary": "Set PostHog telemetry enabled state",
"description": "Update the PostHog client's opt-in/out state at runtime. The CLI reads KILO_TELEMETRY_LEVEL once at spawn — this route lets clients (e.g. the VS Code extension) propagate runtime telemetry consent changes.",
"responses": {
"200": {
"description": "State updated",
"content": {
"application/json": {
"schema": {
"type": "boolean"
}
}
}
},
"400": {
"description": "Bad request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/BadRequestError"
}
}
}
}
},
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
}
},
"required": ["enabled"]
}
}
}
},
"x-codeSamples": [
{
"lang": "js",
"source": "import { createKiloClient } from \"@kilocode/sdk\n\nconst client = createKiloClient()\nawait client.telemetry.setEnabled({\n ...\n})"
}
]
}
},
"/remote/enable": {
"post": {
"operationId": "remote.enable",
@@ -12469,6 +12582,102 @@
},
"required": ["type", "properties"]
},
"Event.workspace.ready": {
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "workspace.ready"
},
"properties": {
"type": "object",
"properties": {
"name": {
"type": "string"
}
},
"required": ["name"]
}
},
"required": ["type", "properties"]
},
"Event.workspace.failed": {
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "workspace.failed"
},
"properties": {
"type": "object",
"properties": {
"message": {
"type": "string"
}
},
"required": ["message"]
}
},
"required": ["type", "properties"]
},
"Event.workspace.restore": {
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "workspace.restore"
},
"properties": {
"type": "object",
"properties": {
"workspaceID": {
"type": "string",
"pattern": "^wrk.*"
},
"sessionID": {
"type": "string",
"pattern": "^ses.*"
},
"total": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"step": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
}
},
"required": ["workspaceID", "sessionID", "total", "step"]
}
},
"required": ["type", "properties"]
},
"Event.workspace.status": {
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "workspace.status"
},
"properties": {
"type": "object",
"properties": {
"workspaceID": {
"type": "string",
"pattern": "^wrk.*"
},
"status": {
"type": "string",
"enum": ["connected", "connecting", "disconnected", "error"]
}
},
"required": ["workspaceID", "status"]
}
},
"required": ["type", "properties"]
},
"Event.worktree.ready": {
"type": "object",
"properties": {
@@ -12627,102 +12836,6 @@
},
"required": ["type", "properties"]
},
"Event.workspace.ready": {
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "workspace.ready"
},
"properties": {
"type": "object",
"properties": {
"name": {
"type": "string"
}
},
"required": ["name"]
}
},
"required": ["type", "properties"]
},
"Event.workspace.failed": {
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "workspace.failed"
},
"properties": {
"type": "object",
"properties": {
"message": {
"type": "string"
}
},
"required": ["message"]
}
},
"required": ["type", "properties"]
},
"Event.workspace.restore": {
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "workspace.restore"
},
"properties": {
"type": "object",
"properties": {
"workspaceID": {
"type": "string",
"pattern": "^wrk.*"
},
"sessionID": {
"type": "string",
"pattern": "^ses.*"
},
"total": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"step": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
}
},
"required": ["workspaceID", "sessionID", "total", "step"]
}
},
"required": ["type", "properties"]
},
"Event.workspace.status": {
"type": "object",
"properties": {
"type": {
"type": "string",
"const": "workspace.status"
},
"properties": {
"type": "object",
"properties": {
"workspaceID": {
"type": "string",
"pattern": "^wrk.*"
},
"status": {
"type": "string",
"enum": ["connected", "connecting", "disconnected", "error"]
}
},
"required": ["workspaceID", "status"]
}
},
"required": ["type", "properties"]
},
"OutputFormatText": {
"type": "object",
"properties": {
@@ -14113,9 +14226,7 @@
"maximum": 9007199254740991
},
"archived": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
"type": "number"
}
},
"required": ["created", "updated"]
@@ -14229,13 +14340,19 @@
"type": "string"
},
"processedFiles": {
"type": "number"
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"totalFiles": {
"type": "number"
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"percent": {
"type": "number"
"type": "integer",
"minimum": 0,
"maximum": 100
}
},
"required": ["state", "message", "processedFiles", "totalFiles", "percent"]
@@ -14670,9 +14787,7 @@
"archived": {
"anyOf": [
{
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
"type": "number"
},
{
"type": "null"
@@ -14903,6 +15018,18 @@
{
"$ref": "#/components/schemas/Event.kilo-sessions.remote-status-changed"
},
{
"$ref": "#/components/schemas/Event.workspace.ready"
},
{
"$ref": "#/components/schemas/Event.workspace.failed"
},
{
"$ref": "#/components/schemas/Event.workspace.restore"
},
{
"$ref": "#/components/schemas/Event.workspace.status"
},
{
"$ref": "#/components/schemas/Event.worktree.ready"
},
@@ -14921,18 +15048,6 @@
{
"$ref": "#/components/schemas/Event.pty.deleted"
},
{
"$ref": "#/components/schemas/Event.workspace.ready"
},
{
"$ref": "#/components/schemas/Event.workspace.failed"
},
{
"$ref": "#/components/schemas/Event.workspace.restore"
},
{
"$ref": "#/components/schemas/Event.workspace.status"
},
{
"$ref": "#/components/schemas/Event.message.updated"
},
@@ -17056,9 +17171,7 @@
"maximum": 9007199254740991
},
"archived": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
"type": "number"
}
},
"required": ["created", "updated"]
@@ -17668,6 +17781,18 @@
{
"$ref": "#/components/schemas/Event.kilo-sessions.remote-status-changed"
},
{
"$ref": "#/components/schemas/Event.workspace.ready"
},
{
"$ref": "#/components/schemas/Event.workspace.failed"
},
{
"$ref": "#/components/schemas/Event.workspace.restore"
},
{
"$ref": "#/components/schemas/Event.workspace.status"
},
{
"$ref": "#/components/schemas/Event.worktree.ready"
},
@@ -17686,18 +17811,6 @@
{
"$ref": "#/components/schemas/Event.pty.deleted"
},
{
"$ref": "#/components/schemas/Event.workspace.ready"
},
{
"$ref": "#/components/schemas/Event.workspace.failed"
},
{
"$ref": "#/components/schemas/Event.workspace.restore"
},
{
"$ref": "#/components/schemas/Event.workspace.status"
},
{
"$ref": "#/components/schemas/Event.message.updated"
},
@@ -0,0 +1,36 @@
<svg
viewBox="0 0 40 40"
width="24"
height="24"
xmlns="http://www.w3.org/2000/svg">
<style
type="text/css"
id="style1">
.st0{fill:currentColor;}
.st1{fill:#FFFFFF;}
</style>
<g
id="g5"
transform="matrix(0.44296788,0,0,0.44296788,-2.1262454,-2.1428569)">
<path
class="st0"
d="M 93.9,67.1 C 92.9,79.9 73.6,90 50,90 26.4,90 7.1,79.9 6.1,67.1 Z"
id="path1" />
<path
class="st0"
d="m 92.2,59.4 c 0.5,0.9 0.8,1.8 1.1,2.7 H 6.7 C 7,61.2 7.3,60.3 7.8,59.5 8.3,58.5 8.3,57.3 7.6,56.3 5.8,53.6 4.8,50.4 4.8,46.9 c 0,-9.4 7.6,-17 17,-17 7.2,0 13.4,4.5 15.9,10.9 0.5,1.3 1.8,2.1 3.1,1.9 3,-0.3 6.1,-0.5 9.2,-0.5 3.2,0 6.3,0.2 9.2,0.5 1.3,0.2 2.6,-0.6 3.1,-1.8 C 65,33.8 72.1,29 80.2,30 c 7.8,0.9 14.1,7.3 14.9,15.1 0.4,4.1 -0.7,8 -2.8,11.1 -0.6,1 -0.6,2.2 -0.1,3.2 z"
id="path2" />
<path
class="st1"
d="m 21.8,41.8 c 2.8,0 5.1,2.3 5.1,5.1 0,2.8 -2.3,5.1 -5.1,5.1 -2.8,0 -5.1,-2.3 -5.1,-5.1 0,-2.9 2.3,-5.1 5.1,-5.1 m 0,-7.7 c -7,0 -12.7,5.7 -12.7,12.7 0,7 5.7,12.7 12.7,12.7 7,0 12.7,-5.7 12.7,-12.7 0,-7 -5.7,-12.7 -12.7,-12.7 z"
id="path3" />
<path
class="st1"
d="m 78.2,41.8 c 2.8,0 5.1,2.3 5.1,5.1 0,2.8 -2.3,5.1 -5.1,5.1 -2.8,0 -5.1,-2.3 -5.1,-5.1 0.1,-2.9 2.3,-5.1 5.1,-5.1 m 0,-7.7 c -7,0 -12.7,5.7 -12.7,12.7 0,7 5.7,12.7 12.7,12.7 7,0 12.7,-5.7 12.7,-12.7 0,-7 -5.7,-12.7 -12.7,-12.7 z"
id="path4" />
<path
class="st0"
d="m 65.5,14.8 -7.8,3.9 c -0.3,0.1 -0.6,0.1 -0.8,-0.2 l -6.5,-8.3 c -0.3,-0.3 -0.7,-0.3 -1,0 l -6.2,8.5 C 43,18.9 42.7,19 42.4,18.9 l -8,-4.1 c -0.5,-0.2 -1,0.2 -0.9,0.7 L 36.7,29 c 0.1,0.5 0.6,0.9 1.1,0.9 h 24.5 c 0.5,0 1,-0.4 1.1,-0.9 l 3.1,-13.5 c 0,-0.5 -0.5,-0.9 -1,-0.7 z"
id="path5" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

@@ -0,0 +1,24 @@
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
shape-rendering="geometricPrecision"
d="M9.8132 15.9038L9 18.75L8.1868 15.9038C7.75968 14.4089 6.59112 13.2403 5.09619 12.8132L2.25 12L5.09619 11.1868C6.59113 10.7597 7.75968 9.59112 8.1868 8.09619L9 5.25L9.8132 8.09619C10.2403 9.59113 11.4089 10.7597 12.9038 11.1868L15.75 12L12.9038 12.8132C11.4089 13.2403 10.2403 14.4089 9.8132 15.9038Z"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M18.2589 8.71454L18 9.75L17.7411 8.71454C17.4388 7.50533 16.4947 6.56117 15.2855 6.25887L14.25 6L15.2855 5.74113C16.4947 5.43883 17.4388 4.49467 17.7411 3.28546L18 2.25L18.2589 3.28546C18.5612 4.49467 19.5053 5.43883 20.7145 5.74113L21.75 6L20.7145 6.25887C19.5053 6.56117 18.5612 7.50533 18.2589 8.71454Z"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M16.8942 20.5673L16.5 21.75L16.1058 20.5673C15.8818 19.8954 15.3546 19.3682 14.6827 19.1442L13.5 18.75L14.6827 18.3558C15.3546 18.1318 15.8818 17.6046 16.1058 16.9327L16.5 15.75L16.8942 16.9327C17.1182 17.6046 17.6454 18.1318 18.3173 18.3558L19.5 18.75L18.3173 19.1442C17.6454 19.3682 17.1182 19.8954 16.8942 20.5673Z"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

@@ -0,0 +1,27 @@
<svg viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M29.0063 32C30.6426 32 31.9691 30.6735 31.9691 29.0372C31.9691 27.4008 30.6426 26.0743 29.0063 26.0743C27.37 26.0743 26.0435 27.4008 26.0435 29.0372C26.0435 30.6735 27.37 32 29.0063 32Z" fill="currentColor"/>
<path d="M2.96281 5.92563C4.59913 5.92563 5.92563 4.59913 5.92563 2.96281C5.92563 1.3265 4.59913 0 2.96281 0C1.3265 0 0 1.3265 0 2.96281C0 4.59913 1.3265 5.92563 2.96281 5.92563Z" fill="currentColor"/>
<path d="M16.0179 18.9523C17.6534 18.9523 18.9792 17.6264 18.9792 15.991C18.9792 14.3555 17.6534 13.0297 16.0179 13.0297C14.3825 13.0297 13.0566 14.3555 13.0566 15.991C13.0566 17.6264 14.3825 18.9523 16.0179 18.9523Z" fill="currentColor"/>
<path d="M2.96243 12.1157C4.43511 12.1157 5.62896 10.9218 5.62896 9.44912C5.62896 7.97644 4.43511 6.78259 2.96243 6.78259C1.48975 6.78259 0.295898 7.97644 0.295898 9.44912C0.295898 10.9218 1.48975 12.1157 2.96243 12.1157Z" fill="currentColor"/>
<path d="M9.49905 12.1157C10.9717 12.1157 12.1656 10.9218 12.1656 9.44912C12.1656 7.97644 10.9717 6.78259 9.49905 6.78259C8.02637 6.78259 6.83252 7.97644 6.83252 9.44912C6.83252 10.9218 8.02637 12.1157 9.49905 12.1157Z" fill="currentColor"/>
<path d="M29.0064 25.199C30.4791 25.199 31.6729 24.0052 31.6729 22.5325C31.6729 21.0598 30.4791 19.866 29.0064 19.866C27.5337 19.866 26.3398 21.0598 26.3398 22.5325C26.3398 24.0052 27.5337 25.199 29.0064 25.199Z" fill="currentColor"/>
<path d="M22.5347 25.199C24.0074 25.199 25.2012 24.0052 25.2012 22.5325C25.2012 21.0598 24.0074 19.866 22.5347 19.866C21.062 19.866 19.8682 21.0598 19.8682 22.5325C19.8682 24.0052 21.062 25.199 22.5347 25.199Z" fill="currentColor"/>
<path d="M29.0064 18.3567C30.3146 18.3567 31.3752 17.2962 31.3752 15.988C31.3752 14.6798 30.3146 13.6193 29.0064 13.6193C27.6982 13.6193 26.6377 14.6798 26.6377 15.988C26.6377 17.2962 27.6982 18.3567 29.0064 18.3567Z" fill="currentColor"/>
<path d="M29.0064 12.11C30.3146 12.11 31.3752 11.0495 31.3752 9.74129C31.3752 8.43307 30.3146 7.37256 29.0064 7.37256C27.6982 7.37256 26.6377 8.43307 26.6377 9.74129C26.6377 11.0495 27.6982 12.11 29.0064 12.11Z" fill="currentColor"/>
<path d="M29.0064 5.33146C30.3146 5.33146 31.3752 4.27094 31.3752 2.96272C31.3752 1.65451 30.3146 0.593994 29.0064 0.593994C27.6982 0.593994 26.6377 1.65451 26.6377 2.96272C26.6377 4.27094 27.6982 5.33146 29.0064 5.33146Z" fill="currentColor"/>
<path d="M2.96297 18.298C4.27118 18.298 5.3317 17.2375 5.3317 15.9293C5.3317 14.6211 4.27118 13.5605 2.96297 13.5605C1.65476 13.5605 0.594238 14.6211 0.594238 15.9293C0.594238 17.2375 1.65476 18.298 2.96297 18.298Z" fill="currentColor"/>
<path d="M2.96297 24.9012C4.27118 24.9012 5.3317 23.8406 5.3317 22.5324C5.3317 21.2242 4.27118 20.1637 2.96297 20.1637C1.65476 20.1637 0.594238 21.2242 0.594238 22.5324C0.594238 23.8406 1.65476 24.9012 2.96297 24.9012Z" fill="currentColor"/>
<path d="M2.96297 31.3483C4.27118 31.3483 5.3317 30.2878 5.3317 28.9796C5.3317 27.6714 4.27118 26.6108 2.96297 26.6108C1.65476 26.6108 0.594238 27.6714 0.594238 28.9796C0.594238 30.2878 1.65476 31.3483 2.96297 31.3483Z" fill="currentColor"/>
<path opacity="0.5" d="M9.4988 17.8826C10.5771 17.8826 11.4512 17.0085 11.4512 15.9302C11.4512 14.8519 10.5771 13.9778 9.4988 13.9778C8.42051 13.9778 7.54639 14.8519 7.54639 15.9302C7.54639 17.0085 8.42051 17.8826 9.4988 17.8826Z" fill="currentColor"/>
<path opacity="0.5" d="M22.5349 17.9418C23.6123 17.9418 24.4858 17.0684 24.4858 15.9909C24.4858 14.9135 23.6123 14.04 22.5349 14.04C21.4574 14.04 20.584 14.9135 20.584 15.9909C20.584 17.0684 21.4574 17.9418 22.5349 17.9418Z" fill="currentColor"/>
<path opacity="0.5" d="M16.0182 11.4025C17.0646 11.4025 17.9129 10.5542 17.9129 9.50784C17.9129 8.46144 17.0646 7.61316 16.0182 7.61316C14.9718 7.61316 14.1235 8.46144 14.1235 9.50784C14.1235 10.5542 14.9718 11.4025 16.0182 11.4025Z" fill="currentColor"/>
<path opacity="0.5" d="M16.0177 24.4256C17.0632 24.4256 17.9108 23.578 17.9108 22.5324C17.9108 21.4869 17.0632 20.6393 16.0177 20.6393C14.9721 20.6393 14.1245 21.4869 14.1245 22.5324C14.1245 23.578 14.9721 24.4256 16.0177 24.4256Z" fill="currentColor"/>
<path opacity="0.5" d="M9.49903 4.67762C10.4456 4.67762 11.2129 3.9103 11.2129 2.96375C11.2129 2.0172 10.4456 1.24988 9.49903 1.24988C8.55248 1.24988 7.78516 2.0172 7.78516 2.96375C7.78516 3.9103 8.55248 4.67762 9.49903 4.67762Z" fill="currentColor"/>
<path opacity="0.5" d="M22.5351 30.7495C23.4808 30.7495 24.2475 29.9829 24.2475 29.0372C24.2475 28.0915 23.4808 27.3248 22.5351 27.3248C21.5894 27.3248 20.8228 28.0915 20.8228 29.0372C20.8228 29.9829 21.5894 30.7495 22.5351 30.7495Z" fill="currentColor"/>
<path opacity="0.3" d="M22.535 10.9847C23.3506 10.9847 24.0118 10.3235 24.0118 9.50785C24.0118 8.69221 23.3506 8.03101 22.535 8.03101C21.7193 8.03101 21.0581 8.69221 21.0581 9.50785C21.0581 10.3235 21.7193 10.9847 22.535 10.9847Z" fill="currentColor"/>
<path opacity="0.3" d="M9.49877 23.9502C10.3136 23.9502 10.9741 23.2896 10.9741 22.4748C10.9741 21.66 10.3136 20.9995 9.49877 20.9995C8.68396 20.9995 8.02344 21.66 8.02344 22.4748C8.02344 23.2896 8.68396 23.9502 9.49877 23.9502Z" fill="currentColor"/>
<path opacity="0.3" d="M16.0179 30.0384C16.5709 30.0384 17.0192 29.5902 17.0192 29.0372C17.0192 28.4842 16.5709 28.0359 16.0179 28.0359C15.4649 28.0359 15.0166 28.4842 15.0166 29.0372C15.0166 29.5902 15.4649 30.0384 16.0179 30.0384Z" fill="currentColor"/>
<path opacity="0.3" d="M16.0178 4.02273C16.5691 4.02273 17.016 3.5758 17.016 3.02449C17.016 2.47317 16.5691 2.02625 16.0178 2.02625C15.4665 2.02625 15.0195 2.47317 15.0195 3.02449C15.0195 3.5758 15.4665 4.02273 16.0178 4.02273Z" fill="currentColor"/>
<path opacity="0.1" d="M9.49903 29.5646C9.8221 29.5646 10.084 29.3027 10.084 28.9796C10.084 28.6565 9.8221 28.3947 9.49903 28.3947C9.17596 28.3947 8.91406 28.6565 8.91406 28.9796C8.91406 29.3027 9.17596 29.5646 9.49903 29.5646Z" fill="currentColor"/>
<path opacity="0.1" d="M22.5345 3.59856C22.8551 3.59856 23.1149 3.3387 23.1149 3.01815C23.1149 2.6976 22.8551 2.43774 22.5345 2.43774C22.214 2.43774 21.9541 2.6976 21.9541 3.01815C21.9541 3.3387 22.214 3.59856 22.5345 3.59856Z" fill="currentColor"/>
</svg>

After

Width:  |  Height:  |  Size: 6.0 KiB

@@ -45,6 +45,24 @@
fill="currentColor"
></path>
</symbol>
<symbol viewBox="0 0 40 40" id="xiaomi-token-plan-sgp">
<path
d="M17.3598 5.03522C13.6378 5.20577 11.3905 5.78765 9.47432 7.07179C8.10992 7.97471 7.10668 9.14849 6.38435 10.6935C5.59179 12.389 5.24066 14.255 5.09017 17.7262C4.90959 21.6087 5.17043 25.4812 5.75231 27.5378C6.27399 29.4039 7.10668 30.8285 8.38079 32.0223C9.95588 33.487 11.7216 34.2595 14.4604 34.6709C16.9685 35.0421 22.7773 35.0621 25.3154 34.711C28.4054 34.2896 30.3718 33.4168 31.987 31.7414C32.7896 30.9187 33.1608 30.377 33.6824 29.2835C34.4951 27.5679 34.8261 25.7922 34.9867 22.2407C35.107 19.7026 34.9867 16.0909 34.7358 14.4055C34.1439 10.4527 32.4585 7.88441 29.519 6.39962C27.964 5.62713 25.6766 5.17567 22.4963 5.02519C20.0986 4.91483 19.7776 4.91483 17.3598 5.03522ZM21.0617 14.3854C22.386 14.6964 23.0281 15.1378 23.4494 16.0407C23.8808 16.9637 23.951 17.7262 23.951 21.8896V25.8022L22.5264 25.7721L21.0918 25.742L21.0417 21.9297C20.9915 17.7663 20.9714 17.6359 20.3895 17.1844C19.8679 16.7731 19.4264 16.7229 16.5772 16.7129H13.8685L13.8183 21.2275L13.7682 25.742H10.9591L10.929 20.0336C10.909 15.5291 10.939 14.2951 11.0293 14.2349C11.0996 14.1847 13.2365 14.1647 15.7747 14.1847C19.4967 14.2249 20.52 14.265 21.0617 14.3854ZM28.9472 14.3252C29.0174 14.4657 29.0475 25.3708 28.9773 25.722C28.9773 25.7621 28.3252 25.7822 27.5426 25.7721L26.108 25.742L26.0779 20.0838C26.0679 15.9906 26.0879 14.3854 26.1682 14.2951C26.2585 14.1847 26.6096 14.1546 27.5727 14.1546C28.6964 14.1546 28.8669 14.1747 28.9472 14.3252ZM18.9349 22.2307V25.8022L17.4601 25.7721L15.9753 25.742L15.9452 22.331C15.9352 20.455 15.9452 18.8598 15.9753 18.7996C16.0054 18.6993 16.3967 18.6692 17.4802 18.6692H18.9349V22.2307Z"
fill="currentColor"
></path>
</symbol>
<symbol viewBox="0 0 40 40" id="xiaomi-token-plan-cn">
<path
d="M17.3598 5.03522C13.6378 5.20577 11.3905 5.78765 9.47432 7.07179C8.10992 7.97471 7.10668 9.14849 6.38435 10.6935C5.59179 12.389 5.24066 14.255 5.09017 17.7262C4.90959 21.6087 5.17043 25.4812 5.75231 27.5378C6.27399 29.4039 7.10668 30.8285 8.38079 32.0223C9.95588 33.487 11.7216 34.2595 14.4604 34.6709C16.9685 35.0421 22.7773 35.0621 25.3154 34.711C28.4054 34.2896 30.3718 33.4168 31.987 31.7414C32.7896 30.9187 33.1608 30.377 33.6824 29.2835C34.4951 27.5679 34.8261 25.7922 34.9867 22.2407C35.107 19.7026 34.9867 16.0909 34.7358 14.4055C34.1439 10.4527 32.4585 7.88441 29.519 6.39962C27.964 5.62713 25.6766 5.17567 22.4963 5.02519C20.0986 4.91483 19.7776 4.91483 17.3598 5.03522ZM21.0617 14.3854C22.386 14.6964 23.0281 15.1378 23.4494 16.0407C23.8808 16.9637 23.951 17.7262 23.951 21.8896V25.8022L22.5264 25.7721L21.0918 25.742L21.0417 21.9297C20.9915 17.7663 20.9714 17.6359 20.3895 17.1844C19.8679 16.7731 19.4264 16.7229 16.5772 16.7129H13.8685L13.8183 21.2275L13.7682 25.742H10.9591L10.929 20.0336C10.909 15.5291 10.939 14.2951 11.0293 14.2349C11.0996 14.1847 13.2365 14.1647 15.7747 14.1847C19.4967 14.2249 20.52 14.265 21.0617 14.3854ZM28.9472 14.3252C29.0174 14.4657 29.0475 25.3708 28.9773 25.722C28.9773 25.7621 28.3252 25.7822 27.5426 25.7721L26.108 25.742L26.0779 20.0838C26.0679 15.9906 26.0879 14.3854 26.1682 14.2951C26.2585 14.1847 26.6096 14.1546 27.5727 14.1546C28.6964 14.1546 28.8669 14.1747 28.9472 14.3252ZM18.9349 22.2307V25.8022L17.4601 25.7721L15.9753 25.742L15.9452 22.331C15.9352 20.455 15.9452 18.8598 15.9753 18.7996C16.0054 18.6993 16.3967 18.6692 17.4802 18.6692H18.9349V22.2307Z"
fill="currentColor"
></path>
</symbol>
<symbol viewBox="0 0 40 40" id="xiaomi-token-plan-ams">
<path
d="M17.3598 5.03522C13.6378 5.20577 11.3905 5.78765 9.47432 7.07179C8.10992 7.97471 7.10668 9.14849 6.38435 10.6935C5.59179 12.389 5.24066 14.255 5.09017 17.7262C4.90959 21.6087 5.17043 25.4812 5.75231 27.5378C6.27399 29.4039 7.10668 30.8285 8.38079 32.0223C9.95588 33.487 11.7216 34.2595 14.4604 34.6709C16.9685 35.0421 22.7773 35.0621 25.3154 34.711C28.4054 34.2896 30.3718 33.4168 31.987 31.7414C32.7896 30.9187 33.1608 30.377 33.6824 29.2835C34.4951 27.5679 34.8261 25.7922 34.9867 22.2407C35.107 19.7026 34.9867 16.0909 34.7358 14.4055C34.1439 10.4527 32.4585 7.88441 29.519 6.39962C27.964 5.62713 25.6766 5.17567 22.4963 5.02519C20.0986 4.91483 19.7776 4.91483 17.3598 5.03522ZM21.0617 14.3854C22.386 14.6964 23.0281 15.1378 23.4494 16.0407C23.8808 16.9637 23.951 17.7262 23.951 21.8896V25.8022L22.5264 25.7721L21.0918 25.742L21.0417 21.9297C20.9915 17.7663 20.9714 17.6359 20.3895 17.1844C19.8679 16.7731 19.4264 16.7229 16.5772 16.7129H13.8685L13.8183 21.2275L13.7682 25.742H10.9591L10.929 20.0336C10.909 15.5291 10.939 14.2951 11.0293 14.2349C11.0996 14.1847 13.2365 14.1647 15.7747 14.1847C19.4967 14.2249 20.52 14.265 21.0617 14.3854ZM28.9472 14.3252C29.0174 14.4657 29.0475 25.3708 28.9773 25.722C28.9773 25.7621 28.3252 25.7822 27.5426 25.7721L26.108 25.742L26.0779 20.0838C26.0679 15.9906 26.0879 14.3854 26.1682 14.2951C26.2585 14.1847 26.6096 14.1546 27.5727 14.1546C28.6964 14.1546 28.8669 14.1747 28.9472 14.3252ZM18.9349 22.2307V25.8022L17.4601 25.7721L15.9753 25.742L15.9452 22.331C15.9352 20.455 15.9452 18.8598 15.9753 18.7996C16.0054 18.6993 16.3967 18.6692 17.4802 18.6692H18.9349V22.2307Z"
fill="currentColor"
></path>
</symbol>
<symbol viewBox="0 0 40 40" id="xai">
<path
d="M12.4579 15.6036L26.1529 35H20.0656L6.37059 15.6036H12.4579ZM12.4524 26.3764L15.4974 30.6909L12.4551 35H6.36377L12.4524 26.3764ZM33.6365 7.15727V35H28.647V14.2236L33.6365 7.15727ZM33.6365 5L20.0656 24.2205L17.0206 19.9073L27.5451 5H33.6365Z"
@@ -75,6 +93,13 @@
stroke-linejoin="round"
></path>
</symbol>
<symbol viewBox="0 0 24 24" id="wafer.ai">
<image
width="24"
height="24"
xlink:href="data:image/png;base64,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"
></image>
</symbol>
<symbol viewBox="0 0 40 40" id="vultr">
<path
d="M15.2983 4.60669C15.1614 4.38264 14.9695 4.19726 14.7409 4.06809C14.5123 3.93893 14.2545 3.87026 13.9919 3.86859H6.05C5.63892 3.86859 5.24467 4.03189 4.95399 4.32258C4.6633 4.61326 4.5 5.00751 4.5 5.41859C4.5 5.7108 4.58182 5.99716 4.73619 6.24526L6.78072 9.24931L17.0034 7.03502L15.2983 4.60669Z"
@@ -163,6 +188,28 @@
fill="currentColor"
></path>
</symbol>
<symbol viewBox="0 0 24 24" fill="none" id="the-grid-ai">
<path d="M4 3L7.76471 6.40541V8.35135H4V3Z" fill="currentColor"></path>
<path d="M4 21L7.76471 17.5946V15.6486H4V21Z" fill="currentColor"></path>
<path d="M20 3L16.2353 6.40541V8.35135H20V3Z" fill="currentColor"></path>
<path d="M20 21L16.2353 17.5946V15.6486H20V21Z" fill="currentColor"></path>
<path d="M9.17642 3L11.0588 6.40542V8.35135H9.17642V3Z" fill="currentColor"></path>
<path d="M9.17642 21L11.0588 17.5946V15.6486H9.17642V21Z" fill="currentColor"></path>
<path d="M14.8236 3L12.9412 6.40542V8.35135H14.8236V3Z" fill="currentColor"></path>
<path d="M14.8236 21L12.9412 17.5946V15.6486H14.8236V21Z" fill="currentColor"></path>
<path d="M4 8.59458L7.7647 10.5405V13.4594L4 15.4054V8.59458Z" fill="currentColor"></path>
<path d="M9.17642 8.59457L11.0588 10.5405V13.4594L9.17642 15.4054V8.59457Z" fill="currentColor"></path>
<path d="M14.8236 8.59457L12.9412 10.5405V13.4594L14.8236 15.4054V8.59457Z" fill="currentColor"></path>
<path d="M20 8.59458L16.2353 10.5405V13.4594L20 15.4054V8.59458Z" fill="currentColor"></path>
</symbol>
<symbol viewBox="0 0 32 32" fill="none" id="tencent-tokenhub">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M18.0835 25.1541C19.5821 26.7684 21.1466 28.1292 22.6694 29.2117L21.5103 30.8416C19.8992 29.6963 18.2543 28.2675 16.6802 26.5808C17.1455 26.1486 17.6143 25.6722 18.0835 25.1541ZM9.99365 2.74979C11.7639 1.73255 13.8054 2.24897 15.6479 3.32304C17.52 4.41448 19.4573 6.22477 21.2603 8.33866L19.7378 9.63651C18.0045 7.60434 16.238 5.98161 14.6411 5.05058C13.0147 4.10247 11.8203 4.00682 10.9897 4.48417C10.0366 5.03255 9.41678 6.47496 9.78271 9.17167C9.86549 9.78127 9.99965 10.4345 10.1812 11.1277C11.6144 10.9497 13.0985 10.8513 14.6167 10.8543C17.7104 10.8604 20.4741 11.1506 22.7944 11.6805L22.7964 11.6814C23.2 11.7609 23.5914 11.858 23.9702 11.9656C23.9685 11.9703 23.9661 11.9746 23.9644 11.9793C24.661 12.1766 25.3101 12.3961 25.9067 12.6404C28.6066 13.7462 30.6077 15.4947 30.603 17.8855C30.599 19.9274 29.1314 21.4372 27.2798 22.4959C25.3986 23.5714 22.8625 24.344 20.1304 24.8484L19.7671 22.8807C22.3935 22.3957 24.6819 21.677 26.2866 20.7596C27.9209 19.8251 28.6011 18.8396 28.603 17.8816C28.6051 16.7818 27.6669 15.5237 25.1479 14.492C24.5672 14.2542 23.9208 14.0387 23.2134 13.8465C22.6517 15.1437 22.0035 16.4444 21.2612 17.7244C18.9392 21.7281 16.437 24.776 14.0688 26.6082C11.7614 28.3932 9.24631 29.2529 7.17822 28.0535C5.41209 27.0291 4.83828 25.0026 4.84717 22.8699C4.85632 20.7032 5.45524 18.1208 6.38428 15.5027L8.27002 16.1717C7.37685 18.6887 6.85497 21.0304 6.84717 22.8787C6.83939 24.7607 7.35367 25.8424 8.18213 26.323C9.13349 26.8747 10.6925 26.6915 12.8452 25.0262C13.3191 24.6595 13.8045 24.2295 14.3003 23.742C13.4493 22.6129 12.6395 21.4021 11.897 20.1101C9.59084 16.0976 8.20303 12.4071 7.80029 9.44022C7.40803 6.54936 7.92116 3.94134 9.99365 2.74979ZM14.6128 12.8543C13.3044 12.8518 12.0235 12.9291 10.7827 13.0701C11.4353 14.9013 12.3808 16.9381 13.6313 19.1141C14.2698 20.2249 14.9606 21.2715 15.6841 22.2537C16.9553 20.7654 18.2592 18.9138 19.5308 16.7215C20.1679 15.623 20.7315 14.5102 21.2271 13.4012C19.3246 13.0558 17.1033 12.8592 14.6128 12.8543ZM6.23193 11.8416C6.39799 12.459 6.59817 13.0982 6.83154 13.7566C4.8717 14.2207 3.07218 14.836 1.49854 15.5398L0.682129 13.7137C2.33167 12.9759 4.20224 12.3309 6.23193 11.8416ZM24.8901 3.62675L25.8853 3.70976C25.7206 5.68459 25.2981 7.84221 24.6128 10.0701C24.1572 9.9381 23.6801 9.8164 23.1831 9.71854C23.0101 9.6845 22.8337 9.6559 22.6567 9.62577C23.3278 7.47916 23.7373 5.41176 23.8931 3.54276L24.8901 3.62675Z"
fill="currentColor"
></path>
</symbol>
<symbol viewBox="0 0 24 24" id="tencent-coding-plan">
<path
d="M20.0483 17.1416C19.6945 17.4914 18.987 18.0161 17.7488 18.0161C17.2182 18.0161 16.5991 18.0161 16.3338 18.0161C15.98 18.0161 13.3268 18.0161 10.143 18.0161C12.4424 15.8298 14.3881 13.9932 14.565 13.8183C14.7419 13.6434 15.1841 13.2061 15.6263 12.8563C16.5107 12.0692 17.2182 11.9817 17.8373 11.9817C18.7217 11.9817 19.4292 12.3316 20.0483 12.8563C21.2864 13.9932 21.2864 16.0047 20.0483 17.1416ZM21.5518 11.457C20.6674 10.495 19.3408 9.88281 17.9257 9.88281C16.6875 9.88281 15.6263 10.3201 14.6534 11.0197C14.2997 11.3695 13.769 11.7194 13.3268 12.2441C12.9731 12.5939 5.36719 19.9401 5.36719 19.9401C5.80939 20.0276 6.34003 20.0276 6.78223 20.0276C7.22443 20.0276 16.0685 20.0276 16.4222 20.0276C17.1298 20.0276 17.6604 20.0276 18.191 19.9401C19.3408 19.8527 20.4905 19.4154 21.4633 18.5409C23.4975 16.6168 23.4975 13.381 21.5518 11.457Z"
@@ -313,6 +360,46 @@
stroke-linejoin="round"
></path>
</symbol>
<symbol
viewBox="0 0 32 32"
id="regolo-ai"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:svg="http://www.w3.org/2000/svg"
>
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="px"
></sodipodi:namedview>
<defs id="defs1"></defs>
<g inkscape:label="Livello 1" inkscape:groupmode="layer" id="layer1">
<path
class="cls-1"
d="m 30.997126,19.704021 v 10.396552 c 0,0.09195 -0.01436,0.178162 -0.04023,0.261494 -0.112068,0.364944 -0.454022,0.632184 -0.859194,0.632184 H 19.70115 c -0.497128,0 -0.899426,-0.405172 -0.899426,-0.899424 v -8.252874 c 0,-0.0431 0,-0.08333 0,-0.126436 v -2.011496 c 0,-0.497126 0.402298,-0.899424 0.899426,-0.899424 h 10.399424 c 0.431036,0 0.795978,0.30747 0.879312,0.71839 0.01436,0.06035 0.02011,0.117816 0.02011,0.181034 z"
id="path1"
style="fill: #303030; stroke-width: 0.287356"
></path>
<path
class="cls-1"
d="m 30.997126,19.704021 v 10.396552 c 0,0.09195 -0.01436,0.178162 -0.04023,0.261494 -0.112068,0.364944 -0.454022,0.632184 -0.859194,0.632184 H 19.70115 c -0.497128,0 -0.899426,-0.405172 -0.899426,-0.899424 v -8.252874 c 0,-0.0431 0,-0.08333 0,-0.126436 v -2.011496 c 0,-0.497126 0.402298,-0.899424 0.899426,-0.899424 h 10.399424 c 0.431036,0 0.795978,0.30747 0.879312,0.71839 0.01436,0.06035 0.02011,0.117816 0.02011,0.181034 z"
id="path2"
style="fill: #4d4d4d; stroke-width: 0.287356"
></path>
<path
class="cls-2"
d="M 30.100574,1.002874 H 19.704022 c -0.497126,0 -0.899424,0.402298 -0.899424,0.899425 v 8.25 c 0,1.353448 -0.54023,2.652298 -1.494254,3.609194 l -3.545976,3.543104 c -0.954024,0.956896 -2.255748,1.494252 -3.606322,1.494252 H 6.454023 c -0.635058,0 -1.146552,-0.514366 -1.146552,-1.14655 v -3.31322 c 0,-0.635056 0.514368,-1.146551 1.146552,-1.146551 h 5.844827 c 0.405172,0 0.744254,-0.267241 0.859196,-0.632184 0.02586,-0.08333 0.04023,-0.16954 0.04023,-0.261494 V 1.899425 c 0,-0.06322 -0.0057,-0.120689 -0.02012,-0.181034 C 13.094826,1.307471 12.729886,1 12.29885,1 H 1.899425 C 1.402299,1 1,1.402299 1,1.899425 V 3.91092 c 0,0.0431 0,0.08333 0,0.126436 v 8.252873 c 0,0.494253 0.405172,0.899426 0.899425,0.899426 h 0.908046 c 0.635058,0 1.146552,0.514368 1.146552,1.146552 v 3.313218 c 0,0.635058 -0.514368,1.146552 -1.146552,1.146552 H 1.905172 c -0.497126,0 -0.899425,0.402298 -0.899425,0.899424 v 10.399426 c 0,0.494252 0.405173,0.899424 0.899425,0.899424 h 10.399426 c 0.497126,0 0.899424,-0.405172 0.899424,-0.899424 v -8.252874 c 0,-1.350574 0.537358,-2.6523 1.494254,-3.606322 l 3.543104,-3.545976 c 0.956896,-0.954024 2.255746,-1.494253 3.609194,-1.494253 h 8.25 C 30.597702,13.195402 31,12.793103 31,12.295977 V 1.899425 C 31,1.402299 30.597702,1 30.100574,1 Z"
id="path3"
style="fill: #000000; stroke-width: 0.287356"
></path>
</g>
</symbol>
<symbol viewBox="0 0 24 24" id="qiniu-ai">
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g fill="currentColor" fill-rule="nonzero">
@@ -563,6 +650,20 @@
fill="currentColor"
></path>
</symbol>
<symbol viewBox="0 0 24 24" fill="currentColor" id="mixlayer">
<path
id="path0"
d="M 5.68608 17.017227 L 1.920257 17.017227 C 1.106327 17.017227 0.446512 17.677059 0.446512 18.49094 L 0.446512 22.256819 C 0.446512 23.070698 1.106327 23.73053 1.920257 23.73053 L 5.68608 23.73053 C 6.500003 23.73053 7.159825 23.070698 7.159825 22.256819 L 7.159825 18.49094 C 7.159825 17.677059 6.500003 17.017227 5.68608 17.017227 Z"
></path>
<path
id="path1"
d="M 18.08707 23.728745 L 21.852949 23.728745 C 22.666828 23.728745 23.32666 23.068911 23.32666 22.255032 L 23.32666 18.489155 C 23.32666 17.675274 22.666828 17.015442 21.852949 17.015442 L 18.08707 17.015442 C 17.273191 17.015442 16.613358 17.675274 16.613358 18.489155 L 16.613358 22.255032 C 16.613358 23.068911 17.273191 23.728745 18.08707 23.728745 Z"
></path>
<path
id="path2"
d="M 21.852949 0.334885 L 18.085396 0.334885 C 17.272299 0.334885 16.611572 0.993814 16.611572 1.808628 L 16.611572 4.653366 C 16.569042 5.666567 16.151106 7.000376 15.426642 7.684097 C 14.7216 8.348349 13.469247 8.67781 12.572987 8.67781 L 11.198444 8.67781 C 10.302151 8.67781 9.048056 8.348349 8.344845 7.684097 C 7.620368 7.000376 7.202333 5.666567 7.159825 4.653366 L 7.159825 1.808628 C 7.159825 0.995586 6.500897 0.334885 5.68608 0.334885 L 1.920257 0.334885 C 1.105443 0.334885 0.446512 0.993814 0.446512 1.808628 L 0.446512 5.576227 C 0.446512 6.389269 1.105443 7.048199 1.920257 7.048199 L 3.340856 7.048199 C 5.16 7.048199 6.895903 7.905521 7.923271 9.405823 C 8.295248 9.951394 8.530828 10.514679 8.530828 11.003565 L 8.530828 13.917433 C 8.530828 14.730419 9.189767 15.391144 10.004573 15.391144 L 13.772204 15.391144 C 14.585191 15.391144 15.245916 14.732204 15.245916 13.917433 L 15.245916 11.003565 C 15.245916 10.514679 15.481452 9.951394 15.853506 9.405823 C 16.879032 7.905521 18.616743 7.048199 20.435946 7.048199 L 21.856522 7.048199 C 22.669506 7.048199 23.330233 6.389269 23.330233 5.574453 L 23.330233 1.808628 C 23.330233 0.995586 22.671293 0.334885 21.856522 0.334885 L 21.852949 0.334885 Z"
></path>
</symbol>
<symbol viewBox="0 0 40 40" id="mistral">
<path
d="M8.92783 8.88101H13.357V13.3088H17.7861V17.738H17.7835H22.2152V13.3088H26.6418V8.88101H31.0722V26.5949H35.5V31.0241H22.2139V26.5962H17.7861V22.1671H13.3557V26.5949L17.7861 26.5962V31.0241H4.5V26.5949H8.92783V8.88101ZM22.2139 26.5962H26.6418V22.1671H22.2152V26.5962H22.2139Z"
@@ -665,6 +766,18 @@
stroke-linejoin="round"
></path>
</symbol>
<symbol viewBox="0 0 40 40" id="llmgateway">
<g transform="translate(1.21, 0) scale(0.17241)">
<path
d="M218 59.4686c0-4.1697-2.351-7.9813-6.071-9.8441L119.973 3.58361s2.926 3.32316 2.926 7.01529V218.833c0 4.081-2.926 7.016-2.926 7.016l15.24-7.468c2.964-2.232 7.187-7.443 7.438-16.006.293-9.976.61-84.847.732-121.0353.487-3.6678 4.096-11.0032 14.63-11.0032 10.535 0 29.262 5.1348 37.309 7.7022 2.439.7336 7.608 4.1812 8.779 12.1036 1.17 7.9223.975 59.0507.731 83.6247 0 2.445.137 7.069 6.653 7.069 6.515 0 6.515-7.069 6.515-7.069V59.4686Z"
fill="currentColor"
></path>
<path
d="M149.235 86.323c0-5.5921 5.132-9.7668 10.589-8.6132l31.457 6.6495c4.061.8585 6.967 4.4207 6.967 8.5824v81.9253c0 5.868 5.121 9.169 5.121 9.169l-51.9-12.658c-1.311-.32-2.234-1.498-2.234-2.852V86.323ZM99.7535 1.15076c7.2925-3.60996 15.8305 1.71119 15.8305 9.86634V220.983c0 8.155-8.538 13.476-15.8305 9.866L6.11596 184.496C2.37105 182.642 0 178.818 0 174.63v-17.868l49.7128 19.865c4.0474 1.617 8.4447-1.372 8.4449-5.741 0-2.66-1.6975-5.022-4.2142-5.863L0 146.992v-14.305l40.2756 7.708c3.9656.759 7.6405-2.289 7.6405-6.337 0-3.286-2.4628-6.048-5.7195-6.413L0 122.917V108.48l78.5181-3.014c4.1532-.16 7.4381-3.582 7.4383-7.7498 0-4.6256-4.0122-8.2229-8.5964-7.7073L0 98.7098V82.4399l53.447-17.8738c2.3764-.7948 3.9791-3.0254 3.9792-5.5374 0-4.0961-4.0978-6.9185-7.9106-5.4486L0 72.6695V57.3696c.0000304-4.1878 2.37107-8.0125 6.11596-9.8664L99.7535 1.15076Z"
fill="currentColor"
></path>
</g>
</symbol>
<symbol viewBox="0 0 40 40" id="llama">
<path
d="M27.1942 9.03509C24.4881 9.03509 22.3726 11.0731 20.4574 13.6623C17.8258 10.3114 15.6255 9.03509 12.9925 9.03509C7.62404 9.03509 3.51001 16.0234 3.51001 23.4181C3.51001 28.0453 5.74831 30.9649 9.49831 30.9649C12.1971 30.9649 14.1387 29.693 17.5904 23.6594C17.5904 23.6594 19.029 21.1199 20.0173 19.3699C20.3643 19.9293 20.7298 20.5327 21.1138 21.1798L22.7322 23.902C25.8843 29.1769 27.6416 30.9649 30.8229 30.9649C34.4778 30.9649 36.51 28.0058 36.51 23.2822C36.51 15.538 32.3039 9.03509 27.1942 9.03509ZM14.9574 22.0263C12.1606 26.4123 11.1928 27.3962 9.63574 27.3962C8.03194 27.3962 7.07872 25.9883 7.07872 23.4781C7.07872 18.1096 9.75562 12.6199 12.9471 12.6199C14.6752 12.6199 16.1197 13.617 18.3316 16.7836C16.2308 20.0058 14.9574 22.0263 14.9574 22.0263ZM25.5202 21.4751L23.5831 18.2456C23.0969 17.4514 22.5938 16.6676 22.0743 15.8947C23.8185 13.2032 25.2556 11.8611 26.9676 11.8611C30.5202 11.8611 33.3638 17.095 33.3638 23.5219C33.3638 25.9722 32.5612 27.3947 30.8989 27.3947C29.3053 27.3947 28.5451 26.3421 25.5188 21.4737"
@@ -741,6 +854,457 @@
fill="currentColor"
></path>
</symbol>
<symbol id="hpc-ai" x="0px" y="0px" viewBox="0 0 384 86" enable-background="new 0 0 384 86" xml:space="preserve">
<image
id="image0"
width="384"
height="86"
x="0"
y="0"
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAYAAAABWCAYAAADG10E5AAAAIGNIUk0AAHomAACAhAAA+gAAAIDo
AAB1MAAA6mAAADqYAAAXcJy6UTwAAAAGYktHRAD/AP8A/6C9p5MAAAAJcEhZcwAADsMAAA7DAcdv
qGQAAGEdSURBVHja7Z13nBxHmfe/T1X3hM0Kq2Q5m+AVWT4DJmhl8AHGGDDMHuHgvYMDgU1OBwd3
M3NHBgdwOhMPH3HnDmNjm3Sc1mSDhTmw1kkYB9kKq7hhUnfV8/7RM7O70kqWbckB5udPe0Y73dXV
VdX15OcRVRUeAEREH8j1bbTxUKK9/tv4S4Z5qDvQRhtttNHGQ4M2AWijjTba+AtFmwC00UYbbfyF
ok0A2mijjTb+QtEmAG200UYbf6FoE4A22mijjb9QtAlAG2200cZfKNoEoI022mjjLxRtAtBGG220
8ReKNgFoo4022vgLRZsAtNFGG238hSJ4qDtwb+i/cG1XOTXeGXvfpS7TifOqOmHEpupoYAx2Mm16
xp/85mdOjIjED3V/22ijjTYeKZCHXTKsK67oSP1uw9Fu6ZInuMgeHfjwWQJHoWHNu+4jrcer2e1E
4joaOvX1HaqVO015/noW1tardNwwf0I2bHnv86Ye0pFt4xGBh936b6ONBxEPOgFQEIG9rsle/N3D
nLhnxlbOIIqfJD4+Fm+dkAJiI4JRH4pVUOpJ34OsJ42qn1J0YaBh3aPuTuPqv6Cc+b6V+jX/+I51
G4sU/UM90G08PNEmAG38JeMhJwDpj/3ncVFv72kSx2coOgAsAOpGNIUaNSQvqYigXkg629rP1dXm
eevudhpkLB3GYI0ImbKveytUfx+lt3+T+X3/ydDQWJ68AWgThDaaaBOANv6S8YAW/32BQrLvKxSk
IKX8imBDv5wh5fgfyHQ8S30ckhAkRITmayma2KlFBFVtfQdQdai3zmvVqw2MFTFGAlEJNIidiMiU
x3VKVP+Bzc5/9cRbnrv9oR7whwp6P+damlergPBnt9k9UAIAgvwZjksbfxl40AhAE6oqnR/96ZKo
c8eHSE+9VrSnCzWginjXPAdAkYRRb274e8ID3quqoiKISCAWEVH1xmOAWNUFAlutMc9Od3NPxfR0
Tv7d4BYRUfIYLaJzqaT+/HB/NzpJdn+V5Otevz2y8cAJALSJQBuPVDzoBCC4+LuDbNfPcnj5aLtr
fqdSFuxsZyTx7kBeJvECHlW8gAgCYhEVJTbeWxCv6gTYmCI82YTSWRb5iI0ql5R3vex7FFoyxZ/v
C6zIA5xlneMvMr33P7KJwAMmAM2r9dCsoabk9nBgUhp81kPejzYOHg65G2geTBF8Lpezlz399afY
eNeFLOw7RndnY9J1VEKMWtQ5QD2KqLGIV1TBYxCxMAexcj5GREE0kRoaaqJkkbYWqgWcTcdRXY0X
L0/VIPOUju7/+nBZ5N9BRVR5CGjhIUVL5dZ4rAKF+/WABQqAJNqfphSQDPpD/YgPAzS25cZS0xax
banM2GvfntZtNv69/+Zbl+1jwB/MDbmASJ78jH4UZ/w/DxT04KsKVcg3VACFhg55xuBMk299UMfi
zwWHlADkwRRVzfLDD09fNviGZ3mxX7C15YtEJzC6w6qmxEjQUPm0Js8l/XJewBhqow57Cya8S3y8
OQ6sCauVCee12yr9XlhGECwTMU8wEnQZEcGrbSwNwQigVIz11inW16c07DhaM9lPdpz3HZV3yCXJ
qv3z4m5k7z3jfj1bUQsyswHRJkPKn6VN4L5h5iaue+z3uvfeTzJkiswgBPsaxsa4a2H2jpd8Nv+W
aD8fDEN0Pm+uYdCMLOsWHj3RuN8gjCQfjIxAEc0X8lpMmIYH3idFckOYscG8MDLIqsKgn/kjzbsU
CmgRVdVEDXBf7r23BDjr3/nGZxFabKL+GWkMDjkblwN72dnfeaqZn72ICiuM210V7e6UeEpV0uIt
okYQ71BjQamLcJf4+KeCvcqxe7TX7r5z7KyzJudqf/k5w9ktlegxvrfnPZrOvCLtvCWOFZ9w9qoO
0Nsw6VXWxL2+Hl1FuuMwVY/E0WS5rv+g73vJt0Uf3hOrjX2iUEg4sNHiqAAMUFKAAqoPGgHTFnub
bGePYE+Y+60CkplftCFhFWluGaOMts6YnqMmVZA9VDp790Fn34QCSPP65jyrqgwNDZnS8LDnEM/B
SggBjsnhh4fxiWloRh8bpqLm69PkEx646qppf7r3dvL5vCkWCmhCZefGDHuizCLXKgUKMsqojDEm
E0wIQDfdyiD09/frwEBJKSbzW9CiIo98qeOQE4DUuT863hv9D0mFJ9opashuNb4jhY8Q49VZVW8J
RLRujNkai5RStfjL85Yv2nDc0D9Fq1jlR3OjUiqVmhZiafRbcjLEMMO+QEE+Ujzqn1m85P0mjlNG
AY9JXEhnEwCtR5dpOnuseo3Fx6lydmKUuO9NnHnaT3njdeHg596jI4w8gIhiFQZXW17zmiwiGaIw
IAiEcvP3jtmnHxtu59RTa/trcRCCG754U7ZavyM76SvprNntpWo8wWIpd3TA9ns8cRDNM0fEO96/
cnwoN2R+VvpZetMn3mFJHz/vAU2gT03y1+OTlIbiRATnAXH+HV/84rK4tmyhY/theL9Q476FWGo2
7KyIRDW/Y+c9YV/XrZU3v+juB9TvA8QDsQEUCgUpkQu2dvwxXUkf0+Gqf0pjq1aMi6U6L9bA20rP
vIBdN4EzEVKPl17wLxPzNs2L1zMa7UkEGgaplp+0KGTPvXLZrJuWK7P+WcncGbBy5RZWr64ODg4G
I/39SvNdOQgYhOC6D1w9r7Zo/HBv6kuMW3SMy27B+sW4YBzRTIVabZtx43fb3cu2VYsvuP1gzk/3
JZcs9OVHLzfBrqOc71gEZRq0CAfEojtcdmpjNu686+jz/3Fs0aJFftXIKl+k6HUmYdWGJ2GLBgvy
la/MZzI1+4UM7PQ13pnMriXI5GZngp5oqj8dHXfWcyafLBKXktvPjS9d3c/4ZJY4LpOWVDJvc5zX
0QEShPTJTm69tkyx+KBnMjgkBKCp9wcIzhu+TLLdLzaV2OtCK2Y8pcZtM1pLIUZx1qIQCfpLY8wH
B1KH/XrdmhOigeEbUhs3jnaNP7l/nNWr43w+b64sXmlP4zTXmlyFQgEpFpDgwsv/VQg+YHyD92i+
TOoAcxsmaEgA8Q9IZxd774xDfUw9UF/9NVPZ1+SuP+OPpQHVxDPoflJ2VUFE+fznFxP7b0Ew35Ai
cFnEh4gPsRokQ6+GqZ4/vXPlxRf/ZN26ddFczeWGh+3A+iH9t+WXvxvT9w/eV7yZrNVUs6rpLs/8
uwM2O2umDrekdv/oiIvOfN+CD3zArVuzJuLs77w2TMu79z/h+14CHiVWb/DRZiKzniXBz1hXv4qN
Q3WGdZ9c58z5B8h8+mtHus7oVHULT1GpPQkznka7svhsSlSMEKoEDucDgngqFjK7vMR/wJrf1jGX
ctbzNxyKdZpM170RgJaVN/m+h+4+/NSPn0lQ/ZRI3KGu08apTUo8vyZGRNU5jpifYstEhqhWJj1x
F/PTL9XckJ+Le2x6QAPkyNnSRav/mvrhH5nZEVHfVL8lGqfU3ffg3Dtzb33rraV8XvNAoVi8n55t
KgyKZSuG9/8gpFI+JcQ+W3XeCT5dOU5rE/ODcgD1ANKCBqgYUbVqrTHb49jfman5n7pM9nu9k/G1
y9/7vPp1EEuiPpED7tM5Pz6MjnA16a3PTpXnPS4w247C9fUR7AiIFxpAkRrqndadxD7tq7a+a3Ps
whtsuufy1E73k8qHXnLXSgjXqZpBEcfgIP0jI1pSlUERRq7+rOUOe6lMHb5ixp19Q3aYlgwOX6iy
ZQeiY1kNurH18B0ffNdvfwhFZq7xFi7+xlFEcik+vRCfqicz5W3rVJlBNwwQSJ1UvC7/DzesKWhB
C4WCFAoFfbCk6oNOAFRVVo+M2K2rzzIbzvvou8QEH8MqOPVkuox4VWplcDUQEU9QMU6/Enb3/vOj
17xn9zrWRV0fHR6oL1n6Stm1M6wtr36QoSEHao/jUcGt3FoXRGd4Rwig3Rdc/eEY/SfiCG8aS64Z
QwC3SZMARFzhbXAUoibWOBKP8VpxErt/jydveTeFgmttbM3N/D4+v4ho5zlXPT4W932sLAP1IM3E
e47EMA0wXjOccdx57/zZhg0b5pQCBvP5YKRQdOkLfny2hP4dBCo6PqmYwEsqMIGdEq0576I+Qt/9
7Yme7f8vv+ZF1QJoeP6l/5ii/2N79G/WP02y3nWWbDxjbXgEvIN6HQAzf8l/6Nhdny1/4JXXq2py
0YwxUlU5AYJ1IlHXxd9e5KLMkODfpMjAjPsI0xyUwYiICE4Vq4r3ftr1N4q3UZ36mizMfKK85mWb
DsV63ddvM3+YqZKZqSbMfOa7F6vqm1TVGWNMs1WA2EC2t6LRWAhqwQii259ZedffXzuXFDWTACiI
fHrtqzLhxKX767/LjN1mHM87/czX31EC11x/93Uc8qqmeILYlW+8jps2Xz/oe/s/gAlWqwgaTCHx
MjAV1aisPo5UTBcmVQYTIBJqA5HxrkNVJ1G+ZQK5pHzW6b9BVfIiMkpOhin5PQnB4k9d2rnlva+d
Wn7OcHbb2NjbzbIjX4uEx0MQG4mNyLjBdYGmVG0dNKWYCbwL8d6BeJxzJMMvXuDXin7TGvPf5be+
+J58Xg0Io8WclHSYvIhedOHajjGp/bhD/Yne7zsuVPBNdVvyb2O+vmDRgjdsXH9SjULLX31aE/a5
772E8uS3rZiKUUkbMUawOpcru4oQKSI2vuqZAz0vWTs46Pa8u9z7Dv2ACMVBzwYqIjqyenV8W+F9
TyPsehNBCJU6ZLqMRDV8VMV7j2JQFTVOP5VeuuCf3rVmZMctl3y6N3XeFe+vd2ZKTOz8J6w8Pj+0
PnnAHPTS65tcU8OM1jKGiXo3c5CVmZrVGVKdgipGVdV6URF11mSsCdIvC3of89xZm1nylt5vIikH
MHsAqVTqXifR+BjUgUsWq6ritUoce/AdmHASI1UAislLgHG9eO9nHao64/A41SSeYh9HcnOLpNNg
DG5i+9/R3fu1ro8NnywnSDAXgTxmaMinPvulgWrkv+6MP1+RFUA0g8jMEHW1xXE1F+OseUyZeb5r
3ht8nf9OX/CDU+7vXNzPGZz1sScyF1x1pMCpIlI3xtjGc7Ve4lAgmkoj6RCCCngBO//lrWWbzxvV
fXn3oNid995Fn5p93X3d/BUhhy2ukKD39T/tunHT9QXf2/9tgnC12hAVIWH1y8nakxgTBslmqwEG
jKoGJA4lWZKH60R4vYvcj1IXful9x53/vVQRfEmH7QmsnHY8yWEHVYMt733tVPe5//GMXb76Y5Yu
+5gG9ng1EiM16yib2IXE3hCbXXgveKZQ1436EEg8/xqbf1NzdiLIOd7rF8Ozv/vEYlF8sYhfP7De
AlIEr5lxsX4n+9v89xjX5FD/2N1byx2MIqwWmy/MfslNVH+cMQYRAhHT3MFlPwfqlK1j/WbW/D1I
TnYHnQCoIisvuS50C7vXUPdHUq+jNkiCvOLI470XdQKqIvLByrtfXNj96mft/OTnB0+MJnZ9HZEP
gwyATKJaLTS9IEpI92D3/aZ26mMDKRKvIGgQdpNsSibCpJYZSb2N8361uHGFEfQ+z0OhcGimzqtH
nU+IQOuhUlA/CiROpJ1w24zfZFrOuNc5a/pB7X1MN2cglU48bsvlR8eBvbDzDd8f2LOtIRky33nG
C04g0z9sws6TkQAnLanHNQ6Zqw9JBHji+4UxqHgQbxCfUjWPc958Pfj81x9kIkBL+wPTnzmw9fHa
yxRdDhokUp7altgJECvUOkCOTlyZ7STqMs/PXHj1EeTzhmLR79fpwNYPoG8BkLn/zzaEYT22660/
6KttuelT2rfw/QRhl9jAGSMeDOICRBPmQkQbBNoDtnH/1sjM3tigV2rdH7y9a/w9A8M3pAZWrKBC
RXK5XLIyS7gRkbjrU58/OQ4zX/Ad3U+XsNWeUx94NFaRnYhLIVFPkgdMQ5QqSB0SJ4TG0eILDWBj
554nsRsOzi8N5vOY9evXRzQJ9M0LwN0f85g8Clt/LCUc/bNt9aKKeP8sg8UShCIioge2xdY33/mQ
+FUfXAIwrFYE/b/6TSf6wDzdhVl8IEg6g3qPOGfw3hpjVEQ+39VjLhiSIZO54IfP8eO7vhSHqZMT
Cqge6EaMbVHEwcQSf1+7JJIEic007lhrm6klhGRjSgOCCU7uCrasJo9hUAwyZB4G8TcNOET9nioc
sLvA9YBmk8+lDZuhKN6E99qqCqLiUXV4YdbR+H02ggBSoYhwrE5MfWjP9q7+cq5fg+7P4IIV3hmn
qjMNWzJrg5wxR81jRs+mr5GaRdPdaGqhVDL51Of+N9Hbqhoa+Z0ODZo7f7KvFCQvhXzyuv8yN5zS
3onn3msLZifKLjQVgE+j6o4JnD6drxRT92p/cJ0H0MWQZPned+RyDRZhlLpX/1Yzb/5r1QZgLIBR
RY2qR0MwNRpKa8AjFgSLU2ZKlrP058aaSGVe2o7VPrxh+60vGR0drQNcX7o+aD5710cuflyc6b0Y
SR2palRVSJa5psAbdX3qNavexPhwDHV9eDOOmhqKYd+ssqoGobqO1KNNNb7oI0svf6aIaL55wQJw
2Yj7CoUe5/RJAIwh1xQxBZATWBlkz/nmcsE8buY63ntdz9XkQ4eD+vIcN/So4Kgv/ymjuuzVRqvL
rWxWq40BiKPEwqJKjPyWju6Pbnv9iyeuvODvTlBfu5AwPN42/CBag7ZHDOvAwMB9Gyxr8CYADOm6
2qyM34HXW6JMFsUgzZskQCQIIg3+lsG1ZpBBcnB/ZIDko37fF9fcGEw+PIkEMAOGWkIAginUODyz
1QEm2r8zSOI1jSYbvsaqzim4ZhSdl5ZBbOaRbBBBYL0xZ3De8CyOvD6R+gCkTlTnYzTCqhNRJ6pe
VJubf4vwWlWM916aKqppSMI1a4BKWjTcjQQ1ok7zjLgavXXxey7tTPw5DnViv5kxhVBcMSwAW57I
4zHZkxLuYu7DEwg+K8IWQaxgjIiZzDobn0a8/AAWVvYAumehev+erFTCMTYo2U9+62U4924N0lbE
iEETu4+vSyMdizZFZnynSQiys+pjK86J8c4Z79Sqx6s2dLSiiBoJdqfo6PZEwUeyF3/3sBWscK/O
3xqJiHLOVw7zHQu+Ekh4uPGaFjUYJ2q8YrwTVQVT8c7gXLBbne9VZ8re+T7v/DxV69TbOFEnNw7B
to5AYqyZ0ihtHquRf+/SS67omI6H3E5YTx3IMO0l2YiLn0ZuWr4uqppu1qnPdj9ZYKnRGScf0B1U
4+7sI18C6F25wd9TX3cUdueLtL4kVJxoM4lbXEfFYvCYWvlz1f855e6B/HBKPWeCHAs6yf4C0yaQ
QrFw3whA5CCOwHgIjIx96RM1490lNo7HAQgziE21NjZVtVG9dkqwbtPTRkZG4mGGH/qsoYONTx+j
uNZ7CIBmwHeBRIkobmeESqgckH7TQ4SRPyKyCeEucLcAdzKtrtmjEW0RAQlDsMErWz+df9mgwqvx
6hKNiEebXis09QYSg4j1bBXvrpQ4+iT1yoeoVy6Wem1dUxXU5JrERImoH/ejUsbsGsd3j5+x5bDM
Ex7s+IOCFpRczququGz3S9Sb3v2dL6aOkRoah6Bp1DjEVlHT86TOf7vkuHvvf4V7xQNUAa185StF
sp1rVEhjAjHGiPdeVb02LEEiRlFvE+N8revH4sfPUVf5kPjqZ4BrwJYRG5Nk4mrOnYgPrGggIlUR
UznGufpZJUrufL7XBWAIXopJP8H5MOM1LeqNqCYZipPIfo+3U2AcqtmqmvrVEk59VLS/iK3/M9r5
IwgnEwcLMczOAIB6wTuLMR2i6dopW+g7a3Q019po4/vpAayqT+gcvKqftbgRiBGJ16o69fq05uZv
NDkOpLX7PXkHAQc1EnjdOqLQV1aJn7cEiZF4CWIduGrD10QxIj9MLZj3X7USbvulvRl2R49JRHnp
Yra2dS/szzVzrq3OWUMmlSXeuQ1dstSwbl101GnR1bdloquJan/jcMYmaQ0cEKh6sMZ67DOAnzVy
Vz88dEAzHrCl1mraG6OlYCLwM1Q+ovDpq8Huu/uJTSG+HmfelM7oPa4ShyLWWydRxVTepJh/RFKd
1to5p0UFJEgt1i9d3Z9/3bXbi3F9FTbdCyBekxegYdpqNGAbxy8w8oZO233n2NsHp5qG5M7P/89i
mSq/33v/DlCfJIUSK4RGgy0gKSe62Eta+qW2/TkefnnoB37aKT8xMYrKp69YGKQnnyn1w2O1u+w+
V6UGiOtONunMVpQ+IepSqD7GT9lVwB/ufdIPLWN4Y3TEKYhfKYEVVLx6z4wwZfEmUtTXRdLbjJq3
D/SF3+WNb2DdCcLKN15CZd4z5E9b73qh4M9XOGz20HmFGsT9Inanw3e+sOOS75+/Y83zN2Uv/vFh
FVt5hdRDm9wT2fMt9iDqewIluJIgvKDfLP7pY9a8JzGM6FoY4VPX3nTlU1D+WZHnAQEtxxwVIQDt
UfVbJzXo7rZTU6/55dNzF1AqVdgOZMsg93kLVIVjzfjuAYTNzT/2XHjZfO/lqaEkaWyaMLSear97
W7wz/ciWAFZCyPBwF27BE0WxIlXE1lEc3jvUKI3QrEvH/+H5O8jlrJ/YLWgyz/d6g8o+Bq8Rq+2b
tEzixpH8JY7r2O4eU5vankTQXnORl3plmDCNtaEKLduAYgKMMUZif8bCT3yxe4Es6D7UExDcW8jO
SOPTeBLFq8U3TF1eGgx1uDmRAmb6GCNg9t+4tQFRKpxa2HH4LZNvPmNr5V1Dd5ff+bJNE+85fduC
e+48Vzuy3zAAcbSH91ByeO+wdXdU1ySc/dmnLhAbnt78LemCR4hn5I2zELtrdWr81ZPbr71p7MKz
6qwWSy5nyWGnvvbc7Z21sX9xIpdoyhgfBhob0VhiXNyDiwKr6Z1Wd3Y7n6k9Y37+sz2NqZtex4oc
XLuAoq2oVzjqKDJBiqdoHByP2epaYz19OJCbgJ8gXny4E4Ix1GURO6WEu1S8WNXKU1muiY5HdW5z
vbt3G84BW/pp5CraC/50tWYe4L26WWlZRFAVVH21ImHvOyrbf/adY+at9OtWi9KNrvvMGgGovOUF
l/nJXf/k0CkwsZDMu1EjxnUIUlN8lxX8Yb7KY/PkTd2Xn2JS7lE6JwOcjLlBMdH2a5bUdw9Fb1r9
w2f+z8paf25E+xnR/qEh7R8raeVNp/0m1ZF5O/X6T5wiKk5VkwDQ5CliMZS7xYKvRMdt6iVRWT6G
pHTIXDefWy+vqurEx7EaCcrl8ccySLD0kis6AKqSPjxAnqT7ZOgfWk5/XzhoL8q6HH7hlnSPcbra
gGCmGvn6TfIpDoXfa2rJtQCDpTEZox/mVDPPVjkDzHI3yTdecEW04YvrDXhCUJPUEFADPllIcTxh
wqjxpqxd6/o6l/8Ay/dEjLb8exWsKBZDaNLHVMIlR+3IPecglZWcudBmyZ1iIZ0dHZ1zcSgq/SvG
EpYmkB2kghncv2+ddf97JZAK3O5gR5+CDObXBk23V/O1c1SduSXxzDH7nBurfh5hVWIfHR86OdZi
xWIbL1+TVCX/dyj1UM592g8u2Uix6HMrVrjBkcTWkiMHq9SP/ePrJvH+i3Xrt8YiRiWUxAjZUHRr
txi3AzGLVuxYvGAhwIBOS7K50rAZyOcOmmSrMlODBQs+oE5M+gVip7oD321lDzWCUcR6+WGg/JdR
E4t2iJIGl5xnpAM1KoQ8q+t93ztxAFKUSnPu4tbeT+X+Pid8eq0oKr0X/XSeajyAS/zoE841cQjQ
JjGIlhgv/LRy4+ar84UCpfUo/TmlHx1cNOhHL1rhAaqVW77pa8HVyUB5rKLiLSJhMvsaCBosUI2P
L2pBsxqfmCaYr+JQiVXFqYqi0yWqVODuWrrnnze+a6giBYSSMDCQ12HwA6WSDgwNKSK6+/Wn3BZr
tqCxbPbqYk8i1CsOQxnxGYLIYMURVjqe2porG9rZC1p9Y6P2ArsE7pxhXxClGVdkg85Fi09mhHgZ
yyIUSZnMkyxBR8MBGzCoWBR2CmwjMaa03NaZg9CIiB6c9OQHjoOnAhrGl8+PFptwU6/G/Yn4H3fg
TR01FkPswNw0///+cM8mmNZtHyhGk4/5n/1qj3HauQ026UypylQgXtzQkftE7DbjiDGI7HJ1f2TL
zTz9sZd7/ad//gN+3vMlTjW4RlV84zW3qawaPZrh4RsOJBJjThyIfckriK668dxvL8ka2y1o7MQK
ImKAjvg7+Ds96fNKSDZ7stdpQ6kXWstxmqbcN2KQ6HQdGjlZPThob5y6Kz00PFxlaMht2rSpbHxc
S4RzmcHAzLiHgFH1WrNiRY9F6VVt+cELGIyi4MVhUFveLDs77161asSPrFUpSUHzebRQLGgz4GJo
VEykl91K2PF/urN6SmeqD2890AVhueH1AthtCwO34LAJuG10RSOYM4ctlYbg+vtgf9vzzHwzp0/z
cRt8syr5QkE+cdTTDpNq9SSJl6cltR18z+wxFTCWH1gT3qpR/EEVFktz/DRIlDriwYZL1OhJ65Wf
iAzNOXGWcWD+fV15s9HKUdfK0SMCOsSQKevfHWmRftSJJMl3Zzn/qipKVbwNfrLyJy+Li9+7OqT4
zx5OcwCr8iM6Umw0XCzW+dSX/+BlXs5qAD7tUGsRJ6KdqFQBhzW9CxBR/eLVJzFhgqS8ayuuc9ZQ
IvwWu/xXKyFcd+UJyd+KydwUQAsgzajzdDDv1iga+00kfnWATTWNZUnIaBapg4RWtFZ73GB+bbC+
OqY2SAezA39lemNWYhVuAY6YXitivIQCSEx4XPcnhh+z7o0n3MJQzvBcfXLil73XCtugaD/Qu4+A
y4cUB9UGYESP8/HC+WrHwfUnm7IAavGSromRX2363JryA7lHZTz9OJsJlw3Cd1YMrTcrSjkHJecB
E2xNglWMJhuFOIgXgJuMoeFTvW6dPer2o+JNcd9PiY98B7I1Pcu3PulxRsLsow91gq0E+j5PEtvc
yq3VqHBDEOKNx4/dje1PNj41ScLDxI3VC7O48z3h2Z+QJyLgiCWa1FWrVvmtZKLS0JADSJ/zX8f4
KH6mNgx7c16dWOrGgpSt1+rx0sbzCIgmHtBWUCvYXYLrR2z9T8Hh8Z8Kr00od5GiLxYbQfWNWwyA
MhjFTG270WCO1zo7rQmSd8vWkkfSEGwqMpKuQN6QK8QUha5nXT2/Fu18gfmrYJGhXPO61E6PQ/NI
5toYwFsw36X5B2u9d+ZETPVbqaCna2T3h1+4XgpUm7SvVCwF/rwTT5Koe4CwkrjezgjsbszfnzRI
//6dbzp508fPv/J6g7xg78lRD5L2Xp+z4PxfXQhPG6fVwoyxdj0H1U2jUCg0EsrBGGPi1SwL1C3c
F8/pnMNEW2rqO36zbh0R29Z3kl9XgXVQzDNaLMrKlSfYdf92q+HUR9W0+6h7kLs3aH1eXYNddXFd
KU9gxI6rEOBlN+prO/vzF3aVy+mlSY63CJ3FybU2SUW5mTUnROsA1q2jlIxQq7eFGcGgU+942pbg
Uz/6rTF+NX4fg2YEdSy7rmvn/L4aE5PBXvl8TOP+XkUzgtykMNPVVxo2oQjh8CibeirCzT3n5Hqj
qP4UUd37XRG9HtWTG8aGfb2oDxkOHgEQRc/5/rEEE2mipYnEYyZJgkUyoKaiJv59Po8pFvGJcjt/
n2/jdXwl9b5HjSzlakqPK+dIwryTmK4y+AUJ4TEVkAmgH3y3Nnyb4bsrdYSROJN67w2YO3ZSzy5u
blrTz2KtL08c/UCGI+KA3905FoS2FCgGg6ay0HRBS3IdNa4xOoen/r033xxL7wnUdbow/YSP9j5+
mTVhR3j+VWVjtc85nofXl8gcaY1nz4e/uz825btV+xPXPyOzbq6BB2Oxk6hPbV+wvbJDCogW0Caf
PTN9QQHV4lkySf7Led/vzvHVHrzPAFVwDtiRXFPvynQuvWvjX+eKUioWHUDstnSa7Pw8rvMIcYfH
mtqebgXjaGJ/NtrymVf1sffeqcF7iCRWxGok2tsntR1bP8Jduq61M4lo3zvO7UCnnk8w2YVYmknJ
khQyDa1kHN2UvXXDREFO1n+7MH1d2tWfm3io7D1PAieMh5ueoso1MmfQ+YHr9+8rJpgQvM5T6Nn3
IhE1gd9VS/dPKCq8hrLIpJAvks8XKRTUA74gBSmgIkf/8Jvp2xde7YN02gVOglg7Q1+tJs9VBg7j
UenuO27KTjwWO24Rn+hudc56HwLcMzhjj1oFvkAzq+reiLNdO2xcySSTK6AOMXa6NIM1gqR6ZGKq
b3HPcTu3Rpsjs9c9hUR/LGlF7hbVbSos3PNeCh0iwVPJ5b6m1frxErglc4+gbFD05IerDeDgEQAF
zjGLkdjjOw3h1gYXnujjBcpiZctXvnJUCm6vjuxbB7SXtbyxQdQB5LDFzzTjdPJGqnnyplhonK0d
dVxvjHrwWYGUxRgIyklSoGCb5smbYlFigC7p3THhqpuFqJ855E+C4P6ECd43JDmLVE1TRJfWht4q
cAOQ2o8/uBqmsw/cD69Vsc/2oo8DGzs0EO+MeqwV6UKQvZucZcIwxsU/3PDOU+uZz1zRpwbVWQRA
RaQmaJeq9gnBbs0EXX6wOGikMQ/Tk57UY2h6eq0sXjB1DOsmIAe5EpQAciRfckCSZrmRnRdVJPNx
F5C1FaFuRVORmNirxyRWXINRk/gcqEFQQZyx4lBiS0OqioM0RhXT1Zt4/DTyQSlIunfxklhSJwUq
iCQbl1GTGONpWDzC4OdLzv/3KvpWzPnVnwlmSmFOZwKFUEz2tBPQnzd8eWePr51kH5feh/ltFiCA
QqGgUixqkuPqBDCabVGuOWCtpe7npYPq7owgSmnYki8qwOhoUiVIkJYdbXD182qMDI7BCKvI+2so
GgYHG34MIwzm1zLynhOk843D+ChCTF/i2kx9OplOSw2jIjDVP2OzH01SBGihcXKhKSvnkcHiavNz
rcQek3gTaZiwR+owSCO2FIzSVbXMP+2NKzes/8x3VRvLtcG5NyYgUVsIUsPIL1H/QqZzeYE0lPwi
h1MqOffUv1nhlaVmhnpHRVSE/xHRu/Ac1niulhp69jJ46HAQVUCCBt/KEC322AmT+CebhtJRAF8R
Yyp/+tPtNREYHBlhJJffuxFwgowr7BDkd4Nr1wadH/1Bf8fHvrJEst0L3SRP8z026rT/9apPx/YG
LhrZvPhTl07sshNToHeJtSnVnnlAB1IFOsFUDfXD/CiXtwZeqn0qwfqduB6/h3gmqEMndi++v4m1
7uO47bP9pvrZhPfm533/9QQGUVUaimwJZiiAYT/SSeOV2e7T3VchqHxGepPXsanPbRjiVQELUgGp
hruXuHD5Hql0Janc0JSgtTHuiehPc/NvfJ/1ybS6XhTO+WqizXPdKBU0bkbSzgxnUATXoLXNv01v
Ao3qc3thKIfRTN+zjexeLJJOJMw9InVV2C3Zrh80/x1L9dZQO0aBk5ibOgdo/Nx1l5Y+SxJ7sQcO
kQRQGLHJTDa4s5ZmZQ4pxTSCwpoYnU6GUaAwnbhGYEQ1MXSK6EgyMZ6RkdalIyOrgZUhdEJkkJTD
41Vmbq4z7oyKDuxngxwCQ24IiiU3At7qe6rgo2SDbgQSqBjEJNpKRVA1VmxYFPGp8y4zRoO5ZGhJ
qD8Z4NeoPA9pWfWmo9mdHt570ZXHRBFPFKFzDybfodw8Y6t/WEoAB9VdDozDlgM0BDcfpJHgUjwi
WpNI42m/+sGZ105vzOhGRC808OoAc8G1P5860R9eOdNL/0X0LvmOC+QIPzV1LLLgPytivmGibe/Z
VgtOFj/vskDkdGzlUsTdgUTg+sD3CD5EgjEdpuRRNXnyRjO7BM1GamRuX8lUOlxRKh2IH96hmxxN
NiUXmAYRbZh9W4yGORhTKAaCxsEex55RkDMiXXHA52tvO/WPuWG1Wq9UvDEkibAEERUxDkxZ0bDB
VcUw1s8qVvmZlZiadQSbtLBJEA74CTQp5pFkRAgS11hsEiVtx8GUMVIjSafRvMY2DMoN+4KmEseB
WQmQWjltZO0JN3XEmalTjY26Ep7AJ0F4zAr4uTaKqtN1DBZzt8zy9Z8ZKUzDKiyPpexWtX6ehYPl
hIaKyHSK4QWVGZRF9r+AzASzI5JzUGpIYvkihTxSEKRAXjTJhjNrXhqbrqAN/56VwNThaFzFa5k9
6KJrXtjo971SwLGxsdYcITVBXGIWUKsgSbI9r4hPeqfqIhNIZXDt2sB4nSv/fktPb1Q7MfJTkT2z
+YuAOMUdXq/WXwa6VPbW8FQE/dUe7SZP9TDCQSMAiQIjFSW+6TWSUl9h4wYe0Fi8uBw5u58mUOQI
VRlS+JiL6q/M9uy6wY/3ftN27yqys3ymrYe32lrXTk1V8qJ9HwzDhf/ulj5lxJvNJ8VkPiFx9nRU
l4kpg+vzmAkQKwRBYjAqEFy58kprwylPIynd9KRoiy3UuD619bo/3b8kK/dp4OYejlZ+HNPMdGga
/yXn7x1p6O/V739PmOkr52JPq4BaLxg1HmNUraWV8Rh+1NU9/6Ooyvr1Javpzs2pBYd5JGGPmjkf
wICZgmBMjaZdupZ2RYo+t9faS7Rfiko+jxEFhodtTtUyrLb1vXkMq80nyrNk7vJFoB9sGcx4I3p4
UeIZ5uZN50vSkISzbvRS7exj7/wygsK2/o2HGzFP93FHwv1rmkS704iYFY9R/ysW7N4+OlxIWli/
Pkb4DVCb2/tDjPgwjXfPao3BTLhF9zqHB5pxdha2Z+UYjvHWN0Ugs58jsDA+nTa7NKDkSzowgBYL
aKGgWgAdzY2KNPPnqhpUDaWSyZWGTa5UMrkSZqhUSuY8vAv1BuezqJ91P515bzUEBdBRckJ+b3vh
MPi1a0dai17xHUDKC6Ii6jHSzMM8HdkQ1oWgdvMtEynwse5HNa9CRtTepnAPTSlJYlqZssT3KPJ3
As9sXqJikiTpqjUVc3NC0uQgMtoHFwfRCAzV83w6wCSl0oLt0rTPGjwYlnk/mW6Wx5thBN7TNcoA
xyo8RkM7ueOnl19ILndTvXTZTQB29d89RwzLX9o39ZGBN1yrRQqKiHLJtx5rXPoFjWhjcVJVE9yj
ni4PzhJ0JfddAacVT3NfcSk3rnGv7vViSqyqKbtgWXXbuR8+tGKbWkTkj6omxlRS0x4lQcI9mUgQ
YiFVNV4OV0wfuAZbmigZZV+MsgLn7ufWklTqMOpx00XNE6IDGMUn/QtR1MeiVq13omrnV6rfrtjo
XYte//7atjtzsuiaa/wtr3jzzniybtIGT5wWNVXFTCE+BHHe+i5xVo/Ynt04H7ibZPYNNAvPN8pa
KgyuHjT205e/gN4la6644MekTQx0cvlnfkSHB49HzPjk2efX/zXH5TcPMKAU89SGn/cnc+dVlwTU
l5R9Okt6axkzCfUl4LMN54B64pygYeMlzoixHmOcxNE8guqums92dZpK6kf5Ql6Ko0Mit620mddM
vtxDnxImK1YDENeojShilF0iXFfPDXltMBFSKGpw0feviVx8D3A0c6kBZJJQ9TnmM//1qBPeLreT
+A8kcEzbmed65UQwPkYzMm0emTXJMwoPJ6+ZosjKz3W7kg77jgu+v1W936KG/sZ5s5wKvKiopgOI
+woFkcHBvIzkUYqqxcZpgpBXldLq1ZI+/1vHWJv9eOKlNYmS5iqfglqIm/8juDtF6lXvHU7rzh/U
U91jKjzaAviZTBitPojK/KEcZqw0NsPxYc9BSC4tgBgvRzct6Z7pxL9JougQJzFeO6amUjqeYnsI
tsl9zd2+yvLKW553V8dnrvyl+nkD2F20POsUQQxi9Xg3k2MQ9Xi14qPR+S5evyPo+KvGS73fSOCH
CgfXBsB/jXkJxCixabTtm6mGkVRQZ34R/rj0kis6WHN6vZ8xJlri5b58ZEvkGIZcDnJw+TlX3Ywf
11LpMvK54enTGnnRBZ8oo3yKJA9CgLdVJ5u2JAajnWiRos/GgwvFZxaKxE39P03RXLz3Pq5u5ohs
jbFDOwHOyqeM2JGEi6zblA+1XvdegVSqYvCh0diLN71nifLmmWvIayOb9f0Q5KTBa82szuEbI2AU
fKOcayQOjwaqDhvF16mJvjvZ5y+ZWPPqbU9auzYYLRbN2rVrXXDJVzYFTBhEvLFjeFNG68dJktM+
MYCJlyNJh4cBdw+DH8phKMFAw7C4evU1lrVrdWRkJA5Of//TqPJCjG/5V6qJaYR5oj6oOpHPlnJA
oQAUyJWGgOGLKAmlXPK+5QdUKQqQh3wBioXZnwBFYTSnQnI9MMQYJRklJ2jJZ//9u0t0qv4cY00K
Y8C3BENJSi80DCbKUPaC75zSweUAZPkOscbdIqTmZDSljhWvnp7DvNFnroNbZ/0e7YJM7z7nUFUx
MbgFfZRKc7U/077UogV6na6MRUTlwp/fqW67gJ0zRXdjyzJK6vhike8xOGgSxk0asREIhbxcA4b+
fg37Uke6Xb0vJbwb4n7E1EnMAh6cRwOPD9Lr57/tQ1fsvuBTu1HAz/TAU5O4DzYNNPL00qlfDin9
fXVVccS0vAabwkCx0BwHGZIhUQ0fPdOW7Fu0zCMuC3YM57u2cnN5sz++owOcna5uPXOQ9hjGILpR
/Vgi9TVd/eMFEOzCzyhtoapi6jUQW1bvRjd+qeA6z/xUVr02U6E/7HAQvYAUOfe/b2toNPb2HRHJ
egkeA/xmGcsiBgcZo5XGat8UvsHalEo5GBoi85k3/MoS3lNvLfjGnPls47ZNJ4IsEIMGHrVe09kA
BA6/1SgqmfiqFYHv6MfupWc0qCqT4xvZR5nGgwZxROjmwbM+dfuIrnXNOICmJ0wVlYIiRRHf8Zmr
tzS812c/9wOdNuFOUa5DpW5Ud4jIPIvuFIXI6LxYJsqou524fl3g3Y3V93xg+4t1a6W05lWsWj3i
R4bPlIIURM57yq2SYZwwzlDtsNg02IlEr97KKEm33zX11By5dSLiUCUnjc2ZAiNrcYho37lf7psM
ogFjJuJEtdjcvFziLIMgmtoamHBHDiiNIuSKlBoeQ7nStOdQkcL0fgHk88XW34qFZhATqsMIlCgU
CjJaLAkMMsaYIKj90vzHOLf7RHWuVbdgz5lU6EP42zlNFzMcjGctNE3ho4xIenta4+6XMjx86VFD
7wtv5/YkBNju3wQlIrhsCnZXyeVylAaGzcorT7BbtmwJnv70p9dLe9YG1mS7a9oCUkH5T7WIuxUW
0dqgZksBok6Q+ikLF+rnt62WidkdQKGoI42MrO5pax5HqmrxXSSZAFIN/aIm2lYbI2Tv2MCGmgnd
76nZU2dsFdpwGaSxYAQ4EY7+q0EGf1nUtS4vCHmhWZi9edUKWRHecsEnnoXzz9prVlRQOhJbUNyD
2Oq1ev6pNS76WgcSciCJ9CTu/q3Y3bvUm75EPJ4EU01SXKhpMa4igmY6LTu2jtuFS37G+tFIz6eD
hyHn38RBVAEJ8vH/vJUwXWOuOFiRtAbB04CvXvfGlfHqb9xHF4eG959Ue24O/PifYEALoEVpSlYB
02s4TvS5pgYSKUostjNxH5u8XlcPvsGibz9exXQDSpLusHEjtapaM0H6lgdlBmwlWsUqP1IqhcJ6
GF7hWK9KIXmqwcKIYYBAVOfNQSEf2MLySuBqN6SRN4y/a2jHs/Jrg5HRi/ZZVLyZmKDU2ACLFD3r
8+YarjEBK28XU/6DatfT0IrH7hR8T4NjD0j0gsbUO7tz3734jO/m/pe7hhvimkhRoQjFZBfISP+r
jAtfpEHFJ6mJU42QH69IhIg1xNk7Qu29J5EQp7UfuaESUCI3BCXySWyBolCkIAUAGhp6ClKkJQA1
N/V8kYF8XkdHR5NWxwii7Xe/UPr6M5QnOXhoOpM4iPshqj6du3l8zO03N89wi+ZhJmv7bEFVsbUa
Lm0olUqA+HX/+vkn254Fx3w7le6yz3iFMb5O6FKAgXO/A/b7oXw8/tPUpaet3fnGU8bT513+G43j
J5nAyoyNt9lHJdxicUuetfPMS07mXxuiTasDSL6gUiyIdp33zceqj/6fk4qKWwB2Z2OuAtQo4iyE
ggTZTQBiw98K0iCoM9XATQO5qMJ8G21f88tz3r9JhT+KQl5IHEELQoGCFEV815eu7jUVfaf3blZM
Q8PFU5G6x6WNCSuIk18dx3HpDemuOFM9MA2vBrUb0fh2TO1JaJLZFYkFTdPQ2E3fM4rEdPeUtbxj
FEH5rD6kjiT3hoNnnFAlXLD8TuPiu5l7YxKFp3V96tuLhoaGDCM0FY8HhIYGiMr7nnb37g+8/DYo
NLWQjcGfmS6zxnTm4VoSWxumA/J58uvXx7evygdKsDrhJpuaQm16uRjxbsJ2dq5/IMNxALWcEqQD
ChSUAVj5iaLm1w9pvijkRcgNNV6KFbgmG733uN/LFCZVteY8jAUvYQ9NL9D7hQIAS97+oq2SGV8r
VD2qSHWBiPNY9WI1EqsqEnvSsTwrjoKLL1/10scmtrrE7VNVZf5Xr+7JfvTK1xLwj0jd2Mphxqpt
WQXFIGqtOBGjNvjpkiVd1dIAWioVND+A5ksz60WUyFOEfDGJT4NWlEHTWLl3olel0JAKSiTqxewL
vrrE9C18rvEHW4JP8tVgaqpU6hr4heBfuHFGDmi7895zATn1sGXL9B+6+p4gmey3TJD6kuno+kLQ
Mf8LdPV9ga6uL9CR/QJh+gK6+3NkVyonrAzCqPb1IK5Xmc7Y2hoUA5joMCw2SPUf/tnsBd97xey1
hZ6/4NquzvPWPtGbef/qUlNPAVXMZMOoFCRNJnTF+yD4P1G5MU/edNueH8XW/9QYo3OsbQNoJKqi
3a92Xj+W/viFA0f9x0iqqKoFQQtF1UIBzZ57+TNqU/5reJ5vEudSbxBMYpeZdkaQSGOCX2RN9doq
VbN8dy32Hr33gi0qU2e9cLO6nu8jtWRvUQvBNpCaiphWG4lNxjnTM/+PHX2Hb2hIXA9bAzAcZAmg
74rrdmz7467fYOQYXFOt3nQ0CFEjj6qbeHWpVPrWIARw5gE03GD9SyRi/XSVptm5DU09Ce1HEjWB
SFOlGCAuNqFOjhZHpUTJBZ986krx5iQvcRLIQ0uMaOK2hWl72/3h94r39QJt1GVfd4yedhquUJwO
dBkexsNgwiE9gzjRi86ZR2ofaJTt2w+MyAOLNSqgIyvOVESqXWdf/r++w7wOZZninHpJyjqSuHq2
qj1hTvEalMzFX/8JmfSd9sv/Uzc7tF+C3SdKt3+S0d4e6xAf3GPVB62pMSa0XgMkKqvpDH41Whgi
v14pMlMtUEq8FIF8KZ9MSFPN3NSxNWd7hgJYmKH5KBYULVCSPB1P636KinmsryeegPfL62Z/qB0l
pLemxGQhnngB+c+eT/Ft4wAuFWLm9FRMoKqIOrS3lxw5SpQSF4LII1onUXEYEi61KR1PgozDaae5
lcteZO/Ydfdvyyn5MfDCuZYHJLEAihyBr38m9dn/egmYO8FtR2xQ1S2PVutPQVgshB5NJZK3KSeS
DfVkHWqEqbhfVN598p1Di042u4Zkl7ng299RTZ3IdEkznXHf2JKJfU1VpXKGzjvsCXft3Hxt5pNf
3hieH0yZWtShn1m+2IT2FIM5HBDCcKbRW0Dx3gs+CDCTBPWOKxe+e2gCVW6/qBSkapHca6zFSgLW
aWzsZTf52rFK5kZJ6nB0gFQTIu5T2pqPIIy1Hv1y25pnT/IoSfHW77oZdYEfdjioNoA3ilQ/fnZp
rRI+H2hZryTJiuewYTcZeeW84R99n4s+MgVJrVvZH5Es5ZqBn8n3fQ6jo8E4NFy1Ug23Py/gru54
y3N2loaV3NCQ/e9O/xqrspC5QwCcoj+5/YL3PDhGm1oteabrZvwtP1Nr3ULQ4CbuQ7jvATAfB1iz
dJ9ophEDwq6O39Zj+T5qXy0RgYZTENSanGXrAggsymPEdRxvyhnU1qF3PurL2KgbCQJwUxgJ8WJJ
oruaJXetw0eXGa1d28oQSD5xA20OV2mGUii/B0luqrjnCnFr5vxXgUIe8uBd/cXi4pQ6r3KQd38v
MWRuRTREbAw+9QQWL3kWcBWAdVUw+35FE483g2a6Ws9rbKblyeUbmUKS7FGmYY+JGu9Hgm3/+OKJ
7Nnf+apY+wxFe2kVVVFJuBMRhFAFj80swHYNYZyITyEa4byHOO2MvV3wWcH3gcaK70yIgLdJI+I2
u85lXxQRzQ0n0lW3qXy55sMXovIsZvs7CWBEYxHvEY29mq5HhymOq3d0Y30Znb9QTKWKxAZSSZnK
2TYykow+UldMNcZlf9jTby++HapHHX10pu/tXw7KfmLOcZ1lBelerQyOWPz3f0fq9jtBj8RnQJyg
M6t4CcYI6nWnnxz/ESLKAIqY+F6ZNX/oUn7cGw6aeCIiWgTvfPR78X4cFdQaEItPKLIzxuCR50zc
OXYigClX9d6q5uT2+Y89xhAhNpAIxUGSEtpnEOw11gbn71CdHBwSKZ3zhueIr75cUCcaqWqsYhQQ
kxRC16oq19J9/wvQJyMbi4oTL76RKmBub/vA1T3ASmDP3EgFQYZKJcNKwoRF9VESxmo9GjQS1Tc2
EvHYPZqfjsFolqSwTG+kSRCo32tLm8udZP/IFwqqqvLENR+ZstZ/XIKp2wi3CqaGqhf1gdcEoAaj
gqoxuBrqKxgfwtQd2Ik0blsW9ROoTqGU8Ti8M8578M5gnWyRmjt/8s3P27ry0uu0KKsNhaIWi6pF
VAfIa54BJU/iItxIF97S8AFzB183FEQFEc49J0Ox6AmWHS0pe6qPas00wbOgAs77SWBU4GeC/lLg
V9OH/hL4mTesFfg/RHYmDo91krKHaXBdIN6hacSYbugYBMjnMaQyKG6fB+IT4piuTb8cVYdEdbG1
GhJNoW43Lq7hohjvqvgYXD3r8xTpfvSEMkjw1PHr/1tS2a8HTlrJmEWME2xj5ThEnaqLoR47jbZE
Wp+KtBbVJTJlQ8Xj+gTfhZhdKlJX8SlFwxZzJ0Tnv+TN5/4eYGB9kv1095mv3hmofFhgi/ceJ0ii
kVXQwOBRIfZCKFI36vwCScc1MUGI2bYlCThwBuMdxgnGqSbfLXgnStyoTJnaYlPV4pv++ItKTtXe
/slPRrtsxWsQOZGZ/ImfsRqSbrB1xDCB9HenbzbKzTTinBLDRl2SxAWaRA6rqDg/FtR3JXac9USe
Vr3kvet5J25QiNmDAMxQxB3q8OGDrp/KRotu0WjX2ri3V7VBv5OxTcR/0SAwJvvJa1/w1iWhzXh/
LwztQH52HeD9DYhaS318CtUssaPujdwo1egDlX9/2VZE/MQl10mHTJ0ZePrEe0l8HT14l9gJVBV1
v6ov7flBfmTVfUus0wyDLBQaXZzCmdh7IpQIh2ssApe8tD6JIbLetdjKYqHQUv/Mwu4kKFcDvBqP
R0hS3ICKR8XjjGOyUmHpXt2acV4zt7mAYlFC1MwON90Pjd0nisWiFxFGGInH3/TXG6Ve/XsTBzcL
RtQtUO/TTmUyRlyyv7i+pDQogEvhXUQgDiQm7NmEuhrqe5KYLx+paKTi1cGuslf7ker/veznAOvW
rAFGpjd4FYoUtEBRaXr4JG5VM5T+DQ53biMAWlBd7FYYALNgwfM9weIkvNWIimhyNGJcEfUmdX21
k6dV0h2nVSYmXlZx8RmtoyIvr8TZVwTS+Sqb7nxu7M2VoBiNkWA3OIuq4OJe8BZLJyn1L0hd+O3j
ryliNMKqqNnfEXhhZlFgT4hHVXzDXVZdgwWI8VLFGTfroQfXKiPFYixx5cNGK8PN3B3qVZNEOQFe
rHhRwVREvIipLxGhLmhWEn2IMxIvURGUYKwxF6EKLjZeJZ3tKp22IDq7xLBXVUmSQSaYfPtpaysT
1TNjn93kTeydIK6RUyoJ4lIjdIroLhW7VdWLEiuS7VSYVMWqyu4Ge+FQjbx6k0R+R4ud8ea2ism+
Z/ysl/2mWCz6AVByQ35eeVLU2HpzNKQRQGAVjApGLZYAVuTcykuu4/b3v8JS7/qx8daZaJEa1+NN
tAh8t7QIh0R41V9M/vB1OxtLT5vrPAlzExpezI1DsWLACxuXN5pobv4zoyL2czxQHNR00KoqCDuy
n/rmlxkbz6l1abEi3thk3aPg1aIcG6NLMkHXmIkr+9VCFApFldKw5EiKwu+3LGSljCzoFR/XvaSz
t5po8h8q7zrj18lKHwzWx1vfJ6ovMhqIJnm+GpGcVkBjNXin8Rd57fOm7rMuf6+RDZ1XX216tgmN
7J5qkgwDIhhlwghhYgNILivmm3LAjB6kBtTHKbx1YqWeJI6TKCkDSYDXNGqrmJ7ZSQs9BiHlkKmE
4zcuiYi1u4A0+DRKrQOSbMQj3D8C0Jx+gHw+X/vaJe//3Y5/+HjOSfrfCcb+SuN06OMFdUzZomnB
bqcZ9CaU8c7ifR8Ek8QaQmzQYHtSUtRsF8QF4rO3ShD9a/XMwa8CsFJDrmuyeDO7IUxrXKX1zwNF
w0VyaiA/nLq56ld74xVrwPu9mvKiSLrnN7nXD5ZLqn6lSLl7cFBXjazy5JO1m7SZjE34yct+qWl9
ldoOJFiA6DaUOkgaxTojgg+CY6yGq0bgxrSPOozJ7tsVWSAiIoOhKbm5EIzNxj5WG6BoUMNJBKKo
xECMShACTHR3CyecAJdoeOQa2ZG95LrX3Fi9Z0J9/AqQLo/DBJOq8WJRWxdcLyoxkt4EmsaYnYoG
ig9VpRxjxkWqhxkvzqhWIitjdaKFX+qo3/Oh0htf5fZZ7ORDL/+uP+eqTYGPL4pNZoXVVIc3VYwm
uizN7ALfiUhSAJ4ojUpNNOrFE2KieY2w+FgJdipxgMbzJgi2/9R49yHeetHvj0PTt0JdRHxe1Xxm
8e9Edt7jMXXE2iRYzCWR4EqA8SGiIZRK7pjcMOu6t8SCbCBaukPDzX3JAtYwyX6rmtQfmTQiPTcn
aW5GkjXiTasWw54xryoBSf6SCDbOmtbp1PCtN+vQ4KBLAILovJ5H/dpn51/uU1mjYYjYZmFYURKi
023VZ5Y/PnuvevbZNXnn3pZVVTwOujpgfDPEk79IVbe9svKul/66ueg6c+/7G4nd2zGCzigFJ96I
qBMVHyLRtc76tff/4Wd0NerxIun5YdBJKuwiTHWSCjsJUo0j7MKmurolTO3lMLT3U45CsBsCN8MI
acGn8aRRUdR34XGwqTUqjbHJJnWWCEQ1LUooqh2imhHVTvHGHUDl8QOEqhQKBd2wYUNtx/tfflOH
Df7Gwb+o9bdgd2WwOzzBFoeZ0kR9YRpclzaeJ5OoRHxXI2/LdsRVt0k9vjyo1V5WPfNVX23da51E
B1iv4YBfH0WlWW3u5v6lf61B5wukVcu+jjd1vMSJBKZp8B3YjP9hqWFhXacaj6xa64u5ghSvKRgp
JEwxazXI5/Mm0KnvqstMxUuOjrxgNT3fuo5lVjNLIX2EdeFya1wn3ungSgg9UxUfJG4M+zqqnUoV
WoZviAiNSDVtiFIB3nTipR8v8/CmB08PzvTWW0bzdbDyc0J2Jcrn1nDiju43m7o7i1TmF9SibTrV
EWstglqE+m0Q17xW5kUaSc27sOacxN6JUdkcaqUr8FoXlYmqMfEN3na+6fmHV8/a9J5XbcujZlY+
ohkYZDBY+K4X3pytp061uv2TYuIN6jvr3neD7xB8h+DmCfFCQSLBTEqiXlKRIELDapzIQ8bgFo+L
1XUmvasYpHtfV37bi6+HktuQJApSgGJBYNftaJhGbS8xHdRNSD1Q6tYQSUgtiInCxEYwkEN5NVFg
u36L+G3ECwPQDL7HEi0WfNbgu4xoemdga9fOfDZPB0oalSSQ0ZvmOvJgPGoq4KYluLnqLh1KHFQJ
oFnSTETKmXP+86J65+JTgpgFNMK7k8IPjZJrFrd1bMx4tftl0ZI0wU29dJ49t8dm0jAzPo6GZaSv
97PpbNdHXvC6U3eM5dcGIhJ3fPbyF3oXnYfYXpXZhiIvmqjucJPGmot589DmHDlbonTfjMAty5Em
6as/PWJdatvv1evS5LENVmfkmUmSMN4aarxzX00WQAvr18N6InO+3+rFbBSVamLEqyEClhTEXUCA
+o1J1SyS26QvDKFeu5F4MYS7wDfSIPgUmN1gd1KxU1uSOKAGSnPlFDjgBTCdeyCf121v/evNg2vX
nvPL309eFrueU0TMi9TPX06wfTk+2y0IBnVJTH3FoJk6puwFmcQtulGCTb8NUv0/WHqkjmw49dTa
/evUgaNAQRgsGIpFb6R6lJc77ond4ZPGZ1O4Lo+aGupS2EoGO7FLTfWe2ib7BwUpSEGKSUCUtpLb
rU3mYQi0oOi5536hHPuJq+S23z/edfY46tqJ1KpJWvAQEYeXSCA+fPTz/73YVO1mjSs3it+3NrIz
dmOL6gum/jTcMLVld1ak6tZlXNDhrM06q6gZB3GIT+GNx/pKsuY+B+tWNltKvgwwZqbeN3Rp/4Vr
vz0pvNBp+gUa3PMoUXsUPu5TLQfQGaBV6zEGm0EytXEx8ybrYsYy9fI6n1p8jZm8538r//jquxPp
V6W4LzdmYISRGJjgPadPAMXs2T/4Uq1LX238+Ale4+PQqFcJezHlHrAWn4VgEtFObGx2yW5bkS67
RSO/QeNdV2qY/kn1qy+9m9PmiL4d1IACTj6xTt3CP6LlzG3E82IjtZo1E7G4FEZNKEpKTO02gKIk
fd/F02/v+sz//C8a10XTGcxkLHbC47oFiVDX9Tts5WZWrWplQdVw0xZ86i58ZgLf4/AhSd6uhmdW
OA6V+S1WXGYZAJQZ4uwhwUFvuZnSd3BwMPjF37z1I9RT7562qYviFVWNcbpqYY/5w/aK/kiMOakR
+t1Mbt+UFK54//YXvbS4YlhypRzDw+JnSgSqSKGQF4CPZI44WRYvmYhe98Jr86qmQJIBMfOOT75O
jlvxQXX+CKTpJ5pcPu1I5xzGXx4f0/EaTj21llc1zUm/L2OpKJIoh5HPXRekd99wRCbTjDRMPN32
9OzOdrN919+9ZDcnnBBw3XUxhYIAiQ87UCxow3Nd6bn01/PN+K6eJHhx5n6YBnbDrgy7zzl9C5so
o0jvBT84SrNVSy3dOD8947qkP+PpcXreldsxPi47crmcTaKuH3DYujRTWQPkCwX5yleKqc3vHl5a
7QqVmKOsukXiOg433lghcFDFU62l3OR2H/XdYVzvbVPvW72ZfN4MUAjWF4gS7lFl2q2zod8/SMiT
N6O5URkYKOl5i6/srbJzkaTmV6s040Wnv1FNPitvOXlWGucmlzn9+EpBCkK+yGhB5covf3MZO7OQ
mQfshGql0WQFmA/VbHKPcErVTxosVq2RfUWsmrhWH0gfuWXdmhMSV6kLvr2g29iFdcXhQm3Ocy1d
I02NGjCPrm1vW3PKxDVgJlYi3d3oSH9OB8fGZGJkQtbpdQaIlsvh6aezsf79C/6nrza+ebHrmXeM
Gllmw3rGaYfgJgLx0RhTwTYTTG0zUXb3009c/8e1qwuuofY0gFdkD0l+/1gKHZug3J8f7iovoqvm
eIxx6eUq6Q5nKmlEMjZeUMHUyzbcWpM4dZtMdN4xPzu6a+MVV0SMrHX5fEGKhaIqymypYyAF6yOG
N2Yy229YvPfdm29oH1QzVN/x9Dtaa0yRBecOL4PlwPZWktQyHTT/UfnWSVtYi2tek/3s1cun295T
2G40kM2yoPia7Rs3bqw0o7VnFUnbD+7LuM55/QO5eJ9QTSFSz174jcPjSvqrwLMbL696Y1VEIvX+
r/s7zbqdU9GPNEjtkwCc/rYXnVEaHiY3lGNY8XOJkPlGXdDW7UG6Pn/5Iu94t2p6jURxZ+LkN7tW
nNoAj1Pq5eulL/N39b9/yR8YHrY0yiLet2dGtLEpSSPAcbVgV4Ev3pvrZqPoSOtzz98KIi0PoSKN
r3soilr/zANFP+3kniRTOCTzfO8weaA47f5gBmW1rGKVL1L02no39+hfHkNxpYWTzODaM9zI6tVx
a+NvonXJwX02VZXVstr206+3rSyZY47J+eHhYb93xpiZt91bWVugMH1BHkZHR2WgVNLCPp1QH3wk
DBTJ2ipCgYIWKMg1XGNGdK2hVHKay+3znbuon47OsaPiowZvj9euVVcoFKTYdII4CHU0BgcHg4mR
ETkG/AD5xLgPrGbQbh3Yasrlsrn99gWO/DrHaE5yuRwDuVwyxvu6f3ODnRkX0vqYPaetpTmDf30I
36VDgkNCAAYgNaoaIaKZc799sndcjMijRFBnU15EYluvnrI8lfnNnVHlfyWcSQC0kQwKC1xx+tsu
PaM0nEsIQJKjrDUBefLmGopmhCQj08DAQOquMz/cHZmul2p56k2kwpXGmBreB4prFG41GDxeGkXR
42hTnJE3x2e9/Aq54oouTn/x5P3kKqVp7GlUSZq2M+znmhxIaQ4CoY0iG83NYp8GtBn3SHiGxrdC
QfKFAsVS4/br9+jGYONjBLhGGBkhzoMpHOQNSlEp5EUo5ilqYbrdz60L6NrctTwsV4OpKe3o7PSL
+vv9qsFBv5f0pY23sZU3TGbQtYNMAFBZgYSjzWDu/Yz7LEPdHmgRgEZ8wijIQB4tFlQPZHPUJKnw
zAb3/64WC0DR51VNMTl/DoVp8veVYE8riCs0XGRnbpaa2HHkmmuuMVu3bjWMrid7yecUVsK6lXRf
go6MFMiNrdCkSFuupbVWWllxDjpRBigUkGIBKJWE/n6BQXIXkaSmLh6gxN5oa1/89Z4d38uH4CBK
nA8HHBICoI0XVhDluOPSqdf+y0tZsOjrtjKlcRB6F4Zxqjz5gi6fWjce+O+TDk8S772IMV7UGxVV
VYuPrqgte+kZUCI/tF4bOta98cWfdYeVHY9yJniGiTlD013Ptrt3R5IOU0ZiVZxBLWK8ijOgXrxN
5jH27v3xO874xMpLLgm713xDR3TEHQwCkAczCjLWGuPBWSePANCv5AeUYkHJDRmGhz0iks/nodhQ
AU03euDGzIYa7j7P1SFEUyVSkERlV6Cg+7/njI13j5LNjeHmUEg3CQFYEebyubhQLCbRUHu9JzNu
OSudpM5xWtLPQkGkUGikRHoEcJH5hjG8UCjsm5t+BGKasDYFyv0vwT0czKZPn50zb/qHR9hYHcrw
5MS3HpVHHfeo1J/e+uGXes18HXWS6Zq/XSe3vbw7pddNRukfqLUniXNexRiMqDqXBGUa9eLNzwjk
RlHZoKI7RMyUqKt7tX2C70d0kcJTxHc9Wu34ctEuJNiNq2UaAYyBGBxIHTTllUh9VDPGBmLTUx+Y
OOsVHwfIgS3dj5StLV3vzHlXEr0vUJjJ9e5jlEQTPXlhWnxuNTTDrHqAHWqde2BKxKaE0UieQZPU
HKSV0cie2XQOmLun9969fQ/eIVCnNFSKB5pvY/+da2m/Zkt0bTw8cK+V57QhBbQsOvfeYmIHnA5D
mXXhXgLFQ0swHrT8FMdxXPpPn/rYS1mQ+bjdIUf6VPzsJ6aX/2p0/JYRr6mTRIxvusaoKmIDkXQq
0Y3snYirNboikuTk8F2CmUoqQNldYCYR1wOuO4k0Td0NOHzcpVqfdDYI3jt18XsvZsOGB+RdciAL
6IHMwH10Y/8zxL0OYHtDbeN+44BKjyoHLlLTFBTmkgZ52BGABy1T3QY21I6+JHcZk/4s7XW/s74r
U7nnNsEGiDVIaCGVRtIZkWxWSIUNHx0/Z/715HCJXzA2cTjw2SRMm0bAkylDuCnZ/H0a4sWIqd5l
0+W/n3r3S8/jyRvi/IM4Bm200cYjDC2PzAPfpx9JHMmDuvltuFXrH3rbb78nd0f/z+ys31h/apfQ
vQTJJsW1ieuqUQ3iGHEOvKfhNjp3gxInEbFqmM7T3ciRYmpJUlgC1KUUTSEd9f+xQfzKqe/8v2/m
82oo4e7VQ6eNNtr488esLUZmHDPP0ftwMPt4mOJB1y+0vFlEGBpW893b//tSwnBIwrBRSywJpPLe
tXJs709IE9GEEPhsw1c3C1ITwrvR+EiMBljdfIvPZv5TdtW+MDW1fivFok88Sx741LRVQIcabRVQ
G4cOe3nXHYhr0IHi3l5dhYfawP6QEIBmtm4Usp/5n8ONqb/WR7W/AR4nNqCRnhPiOt4KkqTEnbOv
QgAYxe6Ocd0OUw7wPQEaem827UpXM5eI7fvS8i8M3jm6ngNNH3Dgz9MmAIcYbQLQxqGD7mnePZir
6QBe3YfaBvAQEIDZA96kgD0Xfv+4qFx+mXR2raJePdGH6QV+bIvKgm6SykJ79bXhw2wEnwZT1aRS
z9a6+O7fokEpcEuvnvjPv7qNdRyy2r5tAnCo0SYAbRw6JGH2uvfm0kzBMMdv+2lr1rkqkhS23M85
D7Xb6IO/u6hOx3BKkj2BQl4oFj0rV4aDn/60rltf/as4jp+J4SSUhV6YJ+h8RXpJ6g3HQCMZdypS
O7lb6of9ITJ3/jYz1fUz7dh109Q7bh6Dg6fq2efjtAnAIUabADwikM8bisVHnD3tPkkAModNYH9o
SwAHhoaP+JwDMe+SH/WWmVwoUeow73UhRgLU1QVTcdhanDXb+mvxtrEzT53MDUnlIOSxaaONRwya
7878z361pxLZXjJZOjOya9vrTp9ERI/68trMWLnc550EgUlVZGyH9nzx3Er09oKZ7LNdzmsawAQa
98bzd1XZGZZr0cJUOrs7rFXqO9526njnhVct8QSh+Korv/XF93ReeNWSQLR22Jby1O1H9C1cZMId
t3+lGA+ceYG57Z7blnR1z99ZrU9lY3wHgIltvfzWv76n/8K1XeMytUic1+pbT/9T8xnyeTWfOuJH
S7zZnnraUa/YOLJa4sWqneMfKvWlj+4MamVxfdvjHZsuvNHq2Psme87+xgK3YyIsf3TNpsFBDdb9
/a97mZjgXW957s49nTqWD/8iu/P2nb0ST7l3fyC3vQB69H+MpLfWa/PmT/Xs2rj7pBpFfPbs7xxO
R7cPNm+pRV1B94qenRvXfexjlttvr3Z99if9Pj0WUA9Egy7JGD9Zicb7Ap8tBy4b1allCWrS0bFg
YrI+sUAqcbRg+YIdG4dOqvRfuLZrIojnm7rGJz4u3Hr77QRbJ6P5NlWtE8UKEEzG8c73D+1+KNbP
w4IAtNFGG/cPK1kZrmNdFP77ZW+n4t+icWpchDpWf2WFc1FO9vAOIyS1IK25zcC5ihzr1X+QRJLu
U3RKxHxbRKqKvgllg7Xm3RLrJodeIMKj8awzgX7Ne96Dmt+JMTdF6D9KderdtW987H873/CJwbha
fjvGXCXqj/DwPIEdVoL3qrXbXFz/JOjxIvyqZ0n3ewZLF1W+N/jKR8eV3veK3fVEL5V51ObfGEjt
g97u3K5+0SdNUHs0Ig6RLcbyn5N+6hcp2/2xlITbJs889Z3zLrmud9JH5/n6WMe8Lv2Hs17/26ki
RU9ejRbQrk9f9ncefYPCzkDsex/znn+79Xdn/8sLJAz+DeHWtIvPmnrHi7ekzvnvLwViTJTK/NRU
y6/GBFfW3vnic4LzS4PqOv4FKhbjQlw2ROJJJAqMS2eNmF+L6NEG/a2KvU5j91ZBuzD2PyvvPP38
9Hnf/aQKpxiRbWL0Iu/lGaCnCJTxQadEROIm/qX8/qGrHor1c1DTQbfRRhsPLtaxLlr4iS9270oF
p7lK7ciUrV3g1axE7Vs9ZhPCk1F9omAu8vh+VF/lFQ9aQ3icgQsxZqOBHoR7BP5WMUeJSL+R4Ig4
pcfh5WUKFsvNHjlWrZ4icK0if4VGx2KMsG5d5N8gT1ThOaj/JXAS8GQFvPo+4ngl8AoAlG1n5gbL
Hx8bP4a6fEOCybRI6gKr4bIo6/8pluxtlo6rlehUCG4F/SFe3+68XwTZeTq//+V+08YrASr1qfnY
ykli3B3bXv/SiStXrgz59NpUfkTq8uWfLMz2ZM5UeBIQeLEXr2PdqK1WnucXH/sEM7X78XElvmT5
Ob/42TY2P7ceRTemypPXuzD1QVLpN6fzX/xO7PUDSrwU7IVG/RJFn62YQYGfiMgPgT6UZ2Ps7YHI
8bVsx1NFTIcxcm3HJT9Z6qKpFxv1j0Z1E5hQ8M9Q5AgV+Yqz8T2dHfP63e6xOx6q9dMOgmqjjUc4
pnq6e6QaLbKp1A97dvt/UWOvsj0dVvGPCdQca8T8PJXiQ4hco6oVhc1e6FDVHYiMqMjPvZXPq+rv
49gdHsdxFMVRFNUq87VaeZHUy9upT3mpV8akPrWAetn72uQ9xJWnqPe3ishNAM65J6r6MugfVfUw
Vd2F6mYvbp5XfZaq36GqZe/1hqKI9zFvVps6Xiz/Un77iy5MZ7OfNEbegvE/FIIVQKeiX5u/eNFH
EH+DF+kJw9TxuntnVcPMTwDCicrygPFHiyy5UUHWrVsXMTYWFYt46mOv0HK9n3Ltq5RrZT+56wn5
vBrp7T1K7rnD+erUlIHTdzC2QtElQRBuKf/uiv8DvmPieD4LF39abfcJQSB5/46XXvDSn5XyYvQH
EvtdZDNn19/54n8S0V8AHap6S+T9cbZaMaYyNWEqU5HUdp8scdzhvZtEuBN8BNIv6E1G/DVWzPXU
a9+YnPzj6EO1dtoEoI02HuFQZ4+VmMdY5OSdCzI/9oZ/q1XKP/HCr2KJF3t1T63V3Trx/oIAzgut
/4/A+8db1QUaxx+Ren1YqvVPEbvlxvsu6/2vrffjRvXR6v3TnffXeq+Rer8hVrfIe1clpuxj/2Sb
stt644mxvKqx9ckjrMoOA2mj9AfKBvD3iPerwT9e0JsEH1ujNwyuXRtYFz/bEO0Os+kfd5x/5enl
ytR/i/IS67GeymLw1hK8YefdtV8b5XEicqmJsXaq3GFM6laAOLV5eWz6MON3jAroYF4DhoZc5vwr
jg7r3W/zKl6936XOpzXm6LO7LlsYa3S8t+47qv6HkQmeFVt5njdhiA3vpFRy1gTfcEqFKDrNVKsX
1d9y+vBAfjhVKpWcuuoTqdRNUPXrc0nG4qMAELldVI9V0R0ef6tTfWLs3d8Dd4pSVnTMq60qHK7I
49XLOeL9V1009Zr8Q7h22gSgjTYe4QicLDPYtHgdAb0G+OdMYF4lAbcrHA7yDaPydQBUI1Gcqvaj
+m0T8LdGeL41tqgu7nXe9cXe3eCcq7g4frm6eNLE8Z3EsRBHW4nc4RK7OOjIbNK47vyObZNbvvna
+rmfvfJYjz1O1V+P1+WqXj38DNW0Vx1S1d2gd6qq4nXDhuvHQq/eqmrdTKS9eraJ0SPV2+c6/CJw
hxmf3uUx1/hw+/dEsq+aF574GVOPDpNKdcI7fwOKmMySJwbxVF16lt64+NL/67z9qJFggIFUHPB6
DSaP08AZrHmZBsZoKlxQTYWPJ6otUpO6y3q5WHy8ROA1IrLDWPkV+bzBsjFJPyO3pgNzAUCO9fFR
X16bERMvlFT6hr7axOYSOFSOFLjL4CsKSxBuNJg/GpEnCeaxiv4akUhUthrc4wFvkKIleEkQynOC
0J73UK6dNgFoo41HOLxyPGgUmvCjz3zbi//Jv/3Fn3zqt87eQi1+ls10TBnli+Et68+WqfImVX1B
7PSFCouBRXhzhhj7MiyPC1LpJ2TSmXJHtuPOjo6OONXZeVSqq/eX0j1vmemet8n09FnbPe+x0j1v
PVrfarKdY5LpOiH9qv/6h3pcfycungf83Hs9RpCKUTYCIdArwvdRsoD60I69fvf6GsaOohxWlcrH
ROTxgtkp+O1GZJeKPMWL31p+66lvrrzl5e/r+I39301rDitrtms78xYtMCZ4R9fFP3qLqlkD9ueG
iefs2LHro7X6LebWCz84INH4W6WeXQvhi601ZwhsUBMMePyJ4kmDv+OoIPVTa/0UYo4yIlVR7qBY
9N6bAYVOQW449edf3aaqcmXxSnt3pb5Ce3ofA2bi2e99bbXv3C/3ieqTgXvALBVYIGquV2Gbwnxg
kyDbFbIgf8LLkYB49ERH/MK4ri83kV/2UK6dNgFoo41HMgYGUgIVgetdIH9kcJDjrr41ffPIzSlv
g91SKf8ulda7O560okZXx48RuVWEKYGfA92qflUUxy+LatEzonq9VqnWflOvVEemylO/qU5O/s6V
d33Dj+/YphM7vu93797gx7ffw+TOyyfPe9cGrU7lieu3qOf/qfI0gbN70n1fFGQHyFUqfh3we+C3
gbU/FmGrwLc7w+zGYrHoseajIN9R4ld4/ItRezMmvlLF3CNqfyfiroK8GRgeTm2+9K/LcFzal8fP
1vLOL/rq7me6cvltGusPNPD/4Uz0WqSe2bRmTVlYuILKvBs07P1Q9LYX/d8Lf/LV6z3+CrVmgxHJ
IPwvKtdveNupNQi/BtwAfF+CYAv5vDHG7xThV4j+qFQquSEw3XQrGjuM3CLpzA9K4Ixd7BHuRmXE
q59EuBWR64zyO+A2jLkY9DZBf63or1S4G+FG4HjQFyHmVEEXF4qFhywWoO0G2kYbjwi0Ks8I5ARK
yfeBAcOnLxe2bBSA5f/8GtkILN24UTZdckVy6VJg3SZYuRQ2Tf9pLmwClhZexKbCOuAeWLMGLrkE
2MRSljYvZ2nhdDYVFPhuq8GlL3oRLBM2Fa4AlrF0zXfZdMkyWLoUli2De+5JTl2zBjaBx8uWz37Z
ks6mYAKyuypkMhFj/SncWBYTeN7yrin4Uw1WW9hoj2MDG84ZNmR7u9m2s5t/fsUfufjy14nntRkX
/u3Rbzt16+jnL5/HFLDs2J0DuRVQKgEDwGxb62ihAIXhWX8bvOgtfuTMM01yPgwMDbGIUc/gICNn
fN7SvVHYmZbl5wyx8e1Xmf6OHeJ6KwZAU6HsnJpM9tTNocBuepsN33knPP7xe4337jNP27m/OKhD
jTYBaKONNh65OOecLDLQB1OgZ+zSd1JNShvpPpLHzIyu12Y+mblPhOlqdHOWgL5vxe7baKONNtpo
42GDtgTQRhuPOMzMPyV7fZmJPHmKJAXip1Fs/tj4lp9x/vTZRZKa9gDFPOSLxdkNFfdotXnyrLuT
1LfOzzi32Pq58X1Gu8X8rHsUZ54/q2cJCo3kYq3yy7MK90KBguxxMcWZHSjuOTatJ5/dx3zj7zOf
OQ/F0dGk/RKQa3wC5EpQyjW+zzExAwOadKOQiCFtFVAbbbTRxn3D3skYZxOAhzrZWhtttNFGG208
LNGWANpoo41HLO4tHXtbAmijjTbaaKONNtpoo4022mijjTbaaKONNtpoo4022mijjTbaaKONNtpo
o4022mijjTbaaOPPEP8f9ZcNAArQ/3IAAAAldEVYdGRhdGU6Y3JlYXRlADIwMjYtMDMtMjVUMDg6
MDE6MTcrMDA6MDDPknFJAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDI2LTAzLTI1VDA4OjAxOjE3KzAw
OjAwvs/J9QAAACh0RVh0ZGF0ZTp0aW1lc3RhbXAAMjAyNi0wMy0yNVQwODowMToxNyswMDowMOna
6CoAAAAASUVORK5CYII="
></image>
</symbol>
<symbol viewBox="0 0 24 24" fill="none" id="helicone">
<path
d="M18.3697 8.08776L12 10.8745V11.7289V17.8656L18.3697 8.08776Z"
@@ -920,6 +1484,20 @@
>
<path d="m4 17 6-6-6-6M12 19h8"></path>
</symbol>
<symbol viewBox="-14 -14 100.8 100.8" fill="currentColor" id="digitalocean">
<polygon
fill-rule="evenodd"
points="36.4 58.7 22.4 58.7 22.4 44.6 22.4 44.6 36.4 44.6 36.4 44.6 36.4 58.7"
></polygon>
<polygon fill-rule="evenodd" points="22.4 69.5 11.6 69.5 11.6 69.5 11.6 58.7 22.4 58.7 22.4 69.5"></polygon>
<polygon
fill-rule="evenodd"
points="11.6 58.7 2.5 58.7 2.5 58.7 2.5 49.6 2.5 49.6 11.5 49.6 11.6 49.6 11.6 58.7"
></polygon>
<path
d="M36.4,0C16.3,0,0,16.3,0,36.4h14.1c0-12.3,10-22.3,22.3-22.3s22.3,10,22.3,22.3-10,22.3-22.3,22.3h0v14.1h0c20.1,0,36.4-16.3,36.4-36.4S56.5,0,36.4,0Z"
></path>
</symbol>
<symbol viewBox="0 0 40 40" id="deepseek">
<path
d="M35.6638 9.91965C35.3251 9.75432 35.1785 10.0703 34.9811 10.2316C34.9131 10.2836 34.8558 10.3516 34.7985 10.413C34.3025 10.9423 33.7238 11.289 32.9678 11.2476C31.8625 11.1863 30.9186 11.533 30.0839 12.3783C29.9066 11.3356 29.3173 10.7143 28.4213 10.3143C27.9519 10.1063 27.4773 9.89965 27.148 9.44766C26.9186 9.12633 26.856 8.76767 26.7413 8.41568C26.668 8.20235 26.5946 7.98502 26.3506 7.94902C26.084 7.90769 25.98 8.13035 25.876 8.31702C25.4587 9.07967 25.2973 9.91965 25.3133 10.7703C25.3493 12.6849 26.1573 14.2102 27.764 15.2942C27.9466 15.4182 27.9933 15.5435 27.9359 15.7249C27.8266 16.0982 27.696 16.4609 27.5813 16.8355C27.508 17.0742 27.3986 17.1248 27.1426 17.0222C26.2777 16.6504 25.4919 16.1164 24.828 15.4489C23.6854 14.3449 22.6534 13.1263 21.3654 12.1716C21.067 11.9511 20.7606 11.7416 20.4468 11.5436C19.1335 10.2676 20.6201 9.21967 20.9641 9.09567C21.3241 8.965 21.0881 8.51968 19.9254 8.52501C18.7628 8.53035 17.6988 8.91834 16.3428 9.43699C16.1413 9.51421 15.934 9.57529 15.7229 9.61966C14.4557 9.38091 13.1598 9.33506 11.8789 9.48366C9.36565 9.76365 7.35902 10.953 5.88305 12.9809C4.10975 15.4182 3.69243 18.1888 4.20308 21.0768C4.74041 24.122 6.29504 26.6433 8.683 28.6139C11.1603 30.6579 14.0122 31.6592 17.2668 31.4672C19.2428 31.3539 21.4441 31.0886 23.9254 28.9873C24.552 29.2993 25.208 29.4233 26.2986 29.5166C27.1386 29.5953 27.9466 29.4766 28.5719 29.3459C29.5519 29.1379 29.4839 28.23 29.1306 28.0646C26.2573 26.726 26.888 27.2713 26.3133 26.83C27.7746 25.102 29.9746 23.3074 30.8359 17.4928C30.9026 17.0302 30.8452 16.7395 30.8359 16.3662C30.8306 16.1395 30.8826 16.0502 31.1426 16.0249C31.8639 15.95 32.5637 15.7349 33.2025 15.3915C35.0638 14.3742 35.8158 12.7049 35.9931 10.7023C36.0198 10.3956 35.9878 10.081 35.6638 9.91965ZM19.4414 27.9433C16.6562 25.754 15.3055 25.0327 14.7482 25.0634C14.2256 25.0954 14.3202 25.6913 14.4349 26.0807C14.5549 26.4647 14.7109 26.7286 14.9295 27.066C15.0815 27.2886 15.1855 27.6206 14.7789 27.87C13.8816 28.4246 12.3229 27.6833 12.2496 27.6473C10.435 26.578 8.91632 25.1673 7.84834 23.2381C6.81637 21.3808 6.21638 19.3888 6.11771 17.2622C6.09105 16.7475 6.24171 16.5662 6.7537 16.4729C7.42583 16.3442 8.11451 16.3267 8.79233 16.4209C11.6349 16.8368 14.0536 18.1075 16.0828 20.1194C17.2402 21.2661 18.1161 22.6354 19.0188 23.974C19.9788 25.3953 21.0108 26.75 22.3254 27.8593C22.7894 28.2486 23.1587 28.5446 23.5134 28.7619C22.4441 28.8819 20.6601 28.9086 19.4414 27.9433ZM20.7748 19.3568C20.7745 19.2906 20.7904 19.2253 20.8211 19.1666C20.8517 19.1078 20.8962 19.0575 20.9507 19.0198C21.0052 18.9821 21.068 18.9583 21.1337 18.9503C21.1995 18.9424 21.2662 18.9505 21.3281 18.9741C21.407 19.0024 21.475 19.0546 21.5228 19.1235C21.5706 19.1923 21.5958 19.2743 21.5947 19.3581C21.5949 19.4123 21.5843 19.4659 21.5636 19.5159C21.5428 19.5659 21.5123 19.6113 21.4738 19.6494C21.4354 19.6875 21.3897 19.7176 21.3395 19.7378C21.2893 19.7581 21.2356 19.7682 21.1814 19.7675C21.1277 19.7676 21.0745 19.7571 21.0248 19.7365C20.9752 19.7158 20.9302 19.6855 20.8925 19.6473C20.8548 19.609 20.825 19.5636 20.805 19.5138C20.785 19.4639 20.7739 19.4105 20.7748 19.3568ZM24.9213 21.4848C24.6547 21.5928 24.3893 21.6861 24.1347 21.6981C23.7516 21.7114 23.3756 21.5918 23.0707 21.3594C22.7054 21.0528 22.4441 20.8821 22.3347 20.3488C22.297 20.0881 22.3042 19.823 22.3561 19.5648C22.4494 19.1288 22.3454 18.8488 22.0374 18.5955C21.7881 18.3875 21.4694 18.3302 21.1201 18.3302C21.0005 18.3232 20.8843 18.2875 20.7814 18.2262C20.6348 18.1542 20.5148 17.9728 20.6294 17.7488C20.6668 17.6768 20.8428 17.5008 20.8854 17.4688C21.3601 17.1995 21.9081 17.2875 22.4134 17.4902C22.8827 17.6822 23.2374 18.0342 23.748 18.5328C24.2694 19.1341 24.364 19.3008 24.6613 19.7515C24.896 20.1048 25.1093 20.4674 25.2547 20.8821C25.344 21.1421 25.2293 21.3541 24.9213 21.4848Z"
@@ -1154,6 +1732,12 @@
fill="currentColor"
></path>
</symbol>
<symbol viewBox="0 0 220 32" id="abliteration-ai">
<text x="0" y="24" fill="currentColor">
<tspan font-size="24">Abliteration</tspan>
<tspan dx="8" dy="2" font-size="12" fill-opacity="0.6">.ai</tspan>
</text>
</symbol>
<symbol viewBox="0 0 40 40" fill="currentColor" id="abacus">
<path
d="M6.93433 9.57807C6.93433 8.92952 7.46008 8.40376 8.10864 8.40376C8.75719 8.40376 9.28295 8.92952 9.28295 9.57807V16.6239C9.28295 17.2725 8.75719 17.7983 8.10864 17.7983C7.46008 17.7983 6.93433 17.2725 6.93433 16.6239V9.57807Z"

Before

Width:  |  Height:  |  Size: 286 KiB

After

Width:  |  Height:  |  Size: 339 KiB

@@ -7,8 +7,12 @@ export const iconNames = [
"zai",
"zai-coding-plan",
"xiaomi",
"xiaomi-token-plan-sgp", // kilocode_change
"xiaomi-token-plan-cn", // kilocode_change
"xiaomi-token-plan-ams", // kilocode_change
"xai",
"wandb",
"wafer.ai", // kilocode_change
"vultr",
"vivgrid",
"vercel",
@@ -16,6 +20,8 @@ export const iconNames = [
"v0",
"upstage",
"togetherai",
"the-grid-ai", // kilocode_change
"tencent-tokenhub", // kilocode_change
"tencent-coding-plan",
"synthetic",
"submodel",
@@ -26,6 +32,7 @@ export const iconNames = [
"scaleway",
"sap-ai-core",
"requesty",
"regolo-ai", // kilocode_change
"qiniu-ai",
"qihang-ai",
"privatemode-ai",
@@ -34,7 +41,6 @@ export const iconNames = [
"perplexity-agent",
"ovhcloud",
"openrouter",
"llmgateway",
"opencode",
"opencode-go",
"openai",
@@ -49,6 +55,7 @@ export const iconNames = [
"moonshotai-cn",
"modelscope",
"moark",
"mixlayer", // kilocode_change
"mistral",
"minimax",
"minimax-coding-plan",
@@ -57,6 +64,7 @@ export const iconNames = [
"meganova",
"lucidquery",
"lmstudio",
"llmgateway", // kilocode_change
"llama",
"kuae-cloud-coding-plan",
"kimi-for-coding",
@@ -67,6 +75,7 @@ export const iconNames = [
"inception",
"iflowcn",
"huggingface",
"hpc-ai", // kilocode_change
"helicone",
"groq",
"google",
@@ -82,6 +91,7 @@ export const iconNames = [
"evroc",
"drun",
"dinference",
"digitalocean", // kilocode_change
"deepseek",
"deepinfra",
"cortecs",
@@ -104,6 +114,7 @@ export const iconNames = [
"alibaba-coding-plan-cn",
"alibaba-cn",
"aihubmix",
"abliteration-ai", // kilocode_change
"abacus",
"302ai",
] as const
@@ -17,7 +17,13 @@ function Chevron() {
return (
<span data-slot="markdown-mermaid-chevron" aria-hidden="true">
<svg viewBox="0 0 16 16" fill="none">
<path d="M4 6L8 10L12 6" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.6" />
<path
d="M4 6L8 10L12 6"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="1.6"
/>
</svg>
</span>
)
+5 -1
View File
@@ -357,7 +357,11 @@ async function svg(renderer: Mermaid, source: string, cfg: ReturnType<typeof con
})
}
export async function renderMermaid(root: HTMLDivElement, signal: { aborted: boolean }, input?: Partial<MermaidLabels>) {
export async function renderMermaid(
root: HTMLDivElement,
signal: { aborted: boolean },
input?: Partial<MermaidLabels>,
) {
const label = mergeLabels(input)
const blocks = Array.from(root.querySelectorAll('pre > code[data-lang="mermaid"]'))
if (blocks.length === 0) return