From f87698c0d4afec1e4b621002acda0a13cfe2fc81 Mon Sep 17 00:00:00 2001 From: olddonkey Date: Tue, 18 Aug 2026 14:54:50 -0700 Subject: [PATCH 001/114] feat(xai): enable Priority Processing on the API-key transport MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase B2 of the FastWire umbrella (lidge-jun/opencodex#1886), closing the request in #1875. Fast now works end to end for xAI, and only where xAI documents it. Capability follows the transport. The registry gains a key-auth service-tier overlay applied only when a preset allows the key override and the captured effective auth transport is key-based; xAI declares Fast there and stays unclassified on OAuth, because Priority Processing is documented for the public api.x.ai endpoints and not for the Grok CLI subscription gateway. The overlay resolves inside the shared FastPolicyAuthority capture, so the catalog and the runtime cannot disagree — and the runtime only rewrites the base URL to that gateway when authMode is "oauth", exactly when the overlay withholds the capability, so Fast can never be injected into the unverified endpoint. The catalog stops telling every provider OpenAI's story. Fast tier copy is now per-provider, and xAI's says what xAI actually charges: priority processing at 2x token price, not "1.5x speed". Providers that declare nothing keep their current bytes. Pricing is declared rather than hardcoded to one vendor. The OpenAI-only provider gate becomes exact (provider, model) priority rules, so xAI gets its documented flat 2x while routed resellers sharing the grok slug inherit nothing. The long-context relationship is likewise a declaration: OpenAI publishes that Fast and long context are exclusive regimes, while xAI publishes neither a combined rate nor an exclusion — so a confirmed-priority request above 200k prices at the published long-context rate and is marked a known lower bound, surfaced in the dashboard as "≥$" rather than an invented stacked multiplier. Billing still follows the response echo, which matches xAI's rule that the priority rate applies only when the response confirms it. NOTE — beyond the Fast path: xAI's bundled cached-input price for grok-4.6 was $0.30 against an official $0.50, so every xai cost estimate (not just Fast) was low. A verified-override layer corrects it ahead of the bundled row, which the existing expected-price overlays sit behind and could not reach. The Fast multiplier applies on top of the base price, so shipping the premium without this correction would have compounded the error. Full suite at this commit: 13330 pass / 10 skip / 1 fail — the one failure is the pre-existing dev-side key-login-live-update regression, confirmed to reproduce on this branch's own base commit (bcc77c039) with none of these changes applied. Co-Authored-By: Claude Fable 5 --- .../docs/reference/configuration/providers.md | 20 ++- gui/src/i18n/de.ts | 1 + gui/src/i18n/en.ts | 1 + gui/src/i18n/fr.ts | 1 + gui/src/i18n/ja.ts | 1 + gui/src/i18n/ko.ts | 1 + gui/src/i18n/ru.ts | 1 + gui/src/i18n/tr.ts | 1 + gui/src/i18n/zh-TW.ts | 1 + gui/src/i18n/zh.ts | 1 + gui/src/pages/Logs.tsx | 35 +++-- gui/src/pages/logs-cost-format.ts | 11 ++ gui/tests/logs-cost-lower-bound.test.ts | 10 ++ src/codex/catalog/effort.ts | 2 +- src/codex/catalog/parsing.ts | 2 + src/codex/catalog/provider-fetch.ts | 25 +++- src/providers/fastwire.ts | 13 +- src/providers/registry.ts | 20 +++ src/providers/service-tier.ts | 35 +++-- src/server/management/shared.ts | 4 +- src/usage/cost.ts | 74 ++++++---- src/usage/expected-prices.ts | 85 ++++++++++-- tests/management-api-logs-metrics.test.ts | 25 ++++ tests/service-tier-capability.test.ts | 126 +++++++++++++++++- tests/usage-cost.test.ts | 125 +++++++++++++++++ 25 files changed, 545 insertions(+), 76 deletions(-) create mode 100644 gui/src/pages/logs-cost-format.ts create mode 100644 gui/tests/logs-cost-lower-bound.test.ts diff --git a/docs-site/src/content/docs/reference/configuration/providers.md b/docs-site/src/content/docs/reference/configuration/providers.md index 2c1d2e3eef..d7c2294cd9 100644 --- a/docs-site/src/content/docs/reference/configuration/providers.md +++ b/docs-site/src/content/docs/reference/configuration/providers.md @@ -87,7 +87,7 @@ differing backup and rewrites known legacy namespaced selected ids to bare ids. | `modelMaxInputTokens?` | `Record` | Positive per-model max input limits used for catalog auto-compaction hints. | | `defaultMaxOutputTokens?` | `number` | Provider-wide `openai-chat` fallback when the client omits `max_output_tokens`. | | `modelMaxOutputTokens?` | `Record` | Positive per-model `openai-chat` fallback budgets; exact/pattern matches beat the provider default. | -| `modelCosts?` | `Record` | Per-model display prices (USD per 1M tokens), keyed by that provider's exact upstream model id — not a provider identifier or a routed `provider/model` label, e.g. `{ "deepseek-v4-flash": { "input": 0.14, "output": 0.28, "cacheRead": 0.0028, "cacheWrite": 0 } }`. Any model id is a valid key — custom providers may target any OpenAI-compatible endpoint through the `openai-chat` adapter, and local or internal provider ids work even when they are absent from the built-in catalogs. User-configured prices win over the built-in catalogs in the Logs `~$` and Usage estimates; historical entries are repriced from the current overlay, so editing a price can move past totals. The fallback order is user `modelCosts` → jawcode catalog → expected-price overlay → model-level vendor fallback, and an all-zero entry falls through to the next source in that sequence. Each rate must be a non-negative finite number at most 1,000,000 (USD per 1M tokens); out-of-range rows are rejected by the management boundary and dropped on load. Display-time estimation only: overlays never affect routing, account selection, quotas, or billing. | +| `modelCosts?` | `Record` | Per-model display prices (USD per 1M tokens), keyed by that provider's exact upstream model id — not a provider identifier or a routed `provider/model` label, e.g. `{ "deepseek-v4-flash": { "input": 0.14, "output": 0.28, "cacheRead": 0.0028, "cacheWrite": 0 } }`. Any model id is a valid key — custom providers may target any OpenAI-compatible endpoint through the `openai-chat` adapter, and local or internal provider ids work even when they are absent from the built-in catalogs. User-configured prices win over the built-in catalogs in the Logs `~$` and Usage estimates; historical entries are repriced from the current overlay, so editing a price can move past totals. The fallback order is user `modelCosts` → exact official correction → jawcode catalog → expected-price overlay → model-level vendor fallback, and an all-zero entry falls through to the next source in that sequence. Each rate must be a non-negative finite number at most 1,000,000 (USD per 1M tokens); out-of-range rows are rejected by the management boundary and dropped on load. Display-time estimation only: overlays never affect routing, account selection, quotas, or billing. | | `headers?` | `Record` | Extra upstream headers. Authorization, cookies, API-key headers, embedded newlines, and invalid names are rejected. | | `openRouterRouting?` | `OpenRouterProviderRouting` | Default OpenRouter `order`, `only`, and `allowFallbacks` preferences; valid only for canonical OpenRouter with `openai-chat`. | | `modelOpenRouterRouting?` | `Record` | Exact model-id overrides that replace the provider-wide OpenRouter preference. | @@ -151,6 +151,24 @@ contract; existing configurations see these migration deltas: Explicit capability `false` and Responses caller-tier forwarding retain their existing contracts. +### xAI Priority Processing + +The built-in `xai` preset advertises and injects Fast only when its effective transport uses +`authMode: "key"`. It sends `service_tier: "priority"` to xAI's public Chat Completions or +Responses API. `ocx login xai` uses the separate Grok CLI subscription gateway, so OAuth remains +unclassified: its catalog rows do not advertise Fast and the proxy does not inject a tier. + +xAI charges Priority Processing at 2× the standard token price for input, output, cached, and +reasoning tokens; cache discounts are applied before the multiplier. Cost estimates use that premium +only when xAI echoes `service_tier: "priority"` (or when an adapter explicitly records an assumed +priority outcome). An echoed `default` is a downgrade and stays at the standard price. + +For `grok-4.6`, the standard rate per 1M tokens is $2.00 input, $0.50 cached input, and $6.00 +output. A prompt of at least 200,000 tokens reprices the whole request at $4.00 / $1.00 / $12.00. +xAI has not published how that long-context band combines with Priority Processing. When a +long-context response confirms `priority`, the dashboard therefore shows the published long-context +cost with a `≥` marker and a lower-bound explanation; it never invents a stacked multiplier. + API-key providers may hold a literal key or an environment reference. OAuth providers use the credential store populated by `ocx login`; subscription-backed Claude Code launch behavior is configured under [`claudeCode.authMode`](/reference/configuration/server/#claude-code). diff --git a/gui/src/i18n/de.ts b/gui/src/i18n/de.ts index 976d81c702..c6851ca73f 100644 --- a/gui/src/i18n/de.ts +++ b/gui/src/i18n/de.ts @@ -711,6 +711,7 @@ export const de: Record = { "logs.detail.estimate.cache_detail_missing": "Cache-Details fehlen; Eingabe ist als Obergrenze geschätzt.", "logs.detail.estimate.expected_price_overlay": "Ein verifizierter Expected-Listenpreis wurde verwendet.", "logs.detail.estimate.provider_cost_overlay": "Ein vom Anbieter konfiguriertes Preis-Overlay wurde verwendet.", + "logs.detail.estimate.priority_lower_bound": "xAI hat keinen kombinierten Preis für Priority und langen Kontext veröffentlicht; die angezeigten Kosten sind eine Untergrenze.", "logs.col.error": "Fehler", "logs.col.upstreamReason": "Upstream-Grund", "logs.col.duration": "Dauer", diff --git a/gui/src/i18n/en.ts b/gui/src/i18n/en.ts index 9ed230f6dc..3ce843e9ff 100644 --- a/gui/src/i18n/en.ts +++ b/gui/src/i18n/en.ts @@ -744,6 +744,7 @@ export const en = { "logs.detail.estimate.cache_detail_missing": "Cache details were unavailable; input is an upper-bound estimate.", "logs.detail.estimate.expected_price_overlay": "A verified expected list price was used.", "logs.detail.estimate.provider_cost_overlay": "A provider-configured price overlay was used.", + "logs.detail.estimate.priority_lower_bound": "xAI has not published a combined Priority and long-context price; the displayed cost is a lower bound.", "logs.col.error": "Error", "logs.col.upstreamReason": "Upstream reason", "logs.col.duration": "Duration", diff --git a/gui/src/i18n/fr.ts b/gui/src/i18n/fr.ts index 20e9311cb9..10e2b9b281 100644 --- a/gui/src/i18n/fr.ts +++ b/gui/src/i18n/fr.ts @@ -725,6 +725,7 @@ export const fr: Record = { "logs.detail.estimate.cache_detail_missing": "Les détails du cache n’étaient pas disponibles ; l’entrée est une estimation de la limite supérieure.", "logs.detail.estimate.expected_price_overlay": "Un tarif catalogue attendu et vérifié a été utilisé.", "logs.detail.estimate.provider_cost_overlay": "Un remplacement de tarif configuré pour le fournisseur a été utilisé.", + "logs.detail.estimate.priority_lower_bound": "xAI n’a pas publié de tarif combinant Priority et contexte long ; le coût affiché est une borne inférieure.", "logs.col.error": "Erreur", "logs.col.upstreamReason": "Motif en amont", "logs.col.duration": "Durée", diff --git a/gui/src/i18n/ja.ts b/gui/src/i18n/ja.ts index ce7f4d1642..a7c2d31212 100644 --- a/gui/src/i18n/ja.ts +++ b/gui/src/i18n/ja.ts @@ -687,6 +687,7 @@ export const ja: Record = { "logs.detail.estimate.cache_detail_missing": "キャッシュの詳細が利用できませんでした; 入力は上限の推定です。", "logs.detail.estimate.expected_price_overlay": "検証済みの予想定価が使用されました。", "logs.detail.estimate.provider_cost_overlay": "プロバイダー設定の価格オーバーレイが使用されました。", + "logs.detail.estimate.priority_lower_bound": "xAI は Priority と長いコンテキストの組み合わせ価格を公開していないため、表示額は下限です。", "logs.col.error": "エラー", "logs.col.upstreamReason": "上流の理由", "logs.col.duration": "所要時間", diff --git a/gui/src/i18n/ko.ts b/gui/src/i18n/ko.ts index 2909a498c1..95dc62227f 100644 --- a/gui/src/i18n/ko.ts +++ b/gui/src/i18n/ko.ts @@ -730,6 +730,7 @@ export const ko: Record = { "logs.detail.estimate.cache_detail_missing": "캐시 상세가 없어 입력 전액을 상한으로 추정했습니다.", "logs.detail.estimate.expected_price_overlay": "검증된 expected 정가를 사용했습니다.", "logs.detail.estimate.provider_cost_overlay": "프로바이더 구성 가격 오버레이를 사용했습니다.", + "logs.detail.estimate.priority_lower_bound": "xAI가 Priority와 긴 컨텍스트의 결합 가격을 공개하지 않아 표시 비용은 하한입니다.", "logs.col.error": "오류", "logs.col.upstreamReason": "업스트림 원인", "logs.col.duration": "소요 시간", diff --git a/gui/src/i18n/ru.ts b/gui/src/i18n/ru.ts index 6bf8dca072..bd4d59991c 100644 --- a/gui/src/i18n/ru.ts +++ b/gui/src/i18n/ru.ts @@ -728,6 +728,7 @@ export const ru: Record = { "logs.detail.estimate.cache_detail_missing": "Детализация кэша недоступна; входные токены оценены по верхней границе.", "logs.detail.estimate.expected_price_overlay": "Использована подтверждённая ожидаемая цена из прайс-листа.", "logs.detail.estimate.provider_cost_overlay": "Использован ценовой оверлей провайдера.", + "logs.detail.estimate.priority_lower_bound": "xAI не опубликовала совмещённую цену Priority и длинного контекста; показанная стоимость является нижней границей.", "logs.col.error": "Ошибка", "logs.col.upstreamReason": "Причина от провайдера", "logs.col.duration": "Длительность", diff --git a/gui/src/i18n/tr.ts b/gui/src/i18n/tr.ts index 3abaaaef6c..d7ab493cb1 100644 --- a/gui/src/i18n/tr.ts +++ b/gui/src/i18n/tr.ts @@ -735,6 +735,7 @@ export const tr: Record = { "logs.detail.estimate.cache_detail_missing": "Önbellek detayları eksik.", "logs.detail.estimate.expected_price_overlay": "Doğrulanmış liste fiyatı kullanıldı.", "logs.detail.estimate.provider_cost_overlay": "Kullanıcı tarafından yapılandırılan bir sağlayıcı fiyat katmanı kullanıldı.", + "logs.detail.estimate.priority_lower_bound": "xAI, Priority ile uzun bağlamın birleşik fiyatını yayımlamadı; gösterilen maliyet alt sınırdır.", "logs.col.error": "Hata", "logs.col.upstreamReason": "Yukarı akış nedeni", "logs.col.duration": "Süre", diff --git a/gui/src/i18n/zh-TW.ts b/gui/src/i18n/zh-TW.ts index 869b863370..994a155ff9 100644 --- a/gui/src/i18n/zh-TW.ts +++ b/gui/src/i18n/zh-TW.ts @@ -1805,6 +1805,7 @@ export const zhTW: Record = { "logs.detail.attempt.recovery.emptyCompletion": "空白完成重試", "logs.detail.attempt.recovery.unknown": "未知的復原原因", "logs.detail.estimate.provider_cost_overlay": "已使用供應商設定的價格覆蓋。", + "logs.detail.estimate.priority_lower_bound": "xAI 尚未公布 Priority 與長上下文的組合價格;目前顯示的是費用下界。", "pws.cockpitImportDescription": "從此裝置匯入 Cockpit Tools Antigravity JSON 匯出檔。不會顯示檔案內容。", "pws.cockpitImportFileLabel": "Cockpit Tools Antigravity JSON 匯出檔", "pws.cockpitImportChooseFile": "選擇 JSON 檔案", diff --git a/gui/src/i18n/zh.ts b/gui/src/i18n/zh.ts index de6897e351..666d9ca31b 100644 --- a/gui/src/i18n/zh.ts +++ b/gui/src/i18n/zh.ts @@ -723,6 +723,7 @@ export const zh: Record = { "logs.detail.estimate.cache_detail_missing": "缺少缓存明细;输入费用按上限估算。", "logs.detail.estimate.expected_price_overlay": "使用了已验证的 Expected 标价。", "logs.detail.estimate.provider_cost_overlay": "使用了用户配置的提供方价格覆盖。", + "logs.detail.estimate.priority_lower_bound": "xAI 尚未公布 Priority 与长上下文的组合价格;当前显示的是费用下界。", "logs.col.error": "错误", "logs.col.upstreamReason": "上游原因", "logs.col.duration": "耗时", diff --git a/gui/src/pages/Logs.tsx b/gui/src/pages/Logs.tsx index b7acbb4d02..afd722de2b 100644 --- a/gui/src/pages/Logs.tsx +++ b/gui/src/pages/Logs.tsx @@ -15,6 +15,7 @@ import Debug from "./Debug"; import type { LogsTab } from "./logs-tab-keydown"; import { logsTabKeyDown, readTabFromHash, selectLogsTab } from "./logs-tab-keydown"; +import { formatEstimatedUsdTotal } from "./logs-cost-format"; import { modelTitle } from "./logs-model-title"; import { speedLabel } from "./logs-speed-label"; import { cacheSplit, isCursorUsageProvider, tokensTitle } from "./logs-token-title"; @@ -53,7 +54,8 @@ type CostEstimateReason = | "usage_estimated" | "cache_detail_missing" | "expected_price_overlay" - | "provider_cost_overlay"; + | "provider_cost_overlay" + | "priority_lower_bound"; type TokPerSecondResult = | { kind: "value"; value: number; estimated: boolean } @@ -238,20 +240,16 @@ function formatTokPerSecond(result: TokPerSecondResult | undefined, localeTag?: } function formatEstimatedUsd(result: CostResult | undefined, localeTag?: string): string { - if (!result || result.kind === "unavailable" || !Number.isFinite(result.estimate.cost.total) || result.estimate.cost.total < 0) return "\u2014"; - const totalUsd = result.estimate.cost.total; - return `~$${new Intl.NumberFormat(localeTag, { - minimumFractionDigits: 4, - maximumFractionDigits: 4, - }).format(totalUsd)}`; + if (!result || result.kind === "unavailable") return "\u2014"; + return formatEstimatedUsdTotal( + result.estimate.cost.total, + result.estimateReasons.includes("priority_lower_bound"), + localeTag, + ); } -function formatEstimatedUsdValue(value: number, localeTag?: string): string { - if (!Number.isFinite(value) || value < 0) return "\u2014"; - return `~$${new Intl.NumberFormat(localeTag, { - minimumFractionDigits: 4, - maximumFractionDigits: 4, - }).format(value)}`; +function formatEstimatedUsdValue(value: number, localeTag?: string, lowerBound = false): string { + return formatEstimatedUsdTotal(value, lowerBound, localeTag); } /** Consecutive failed polls before a stale table is called out. Two seconds each, so ~6s. */ @@ -273,6 +271,7 @@ const ESTIMATE_REASON_KEYS = { cache_detail_missing: "logs.detail.estimate.cache_detail_missing", expected_price_overlay: "logs.detail.estimate.expected_price_overlay", provider_cost_overlay: "logs.detail.estimate.provider_cost_overlay", + priority_lower_bound: "logs.detail.estimate.priority_lower_bound", } as const satisfies Record; /** @@ -956,11 +955,11 @@ function LogDetailDialog({ {cost?.kind === "value" ? ( <>
- {t("logs.detail.costTotal")}{formatEstimatedUsdValue(cost.estimate.cost.total, localeTag)} - {t("logs.tokens.input")}{formatEstimatedUsdValue(cost.estimate.cost.input, localeTag)} - {t("logs.tokens.cacheRead")}{formatEstimatedUsdValue(cost.estimate.cost.cacheRead, localeTag)} - {t("logs.tokens.cacheWrite")}{formatEstimatedUsdValue(cost.estimate.cost.cacheWrite, localeTag)} - {t("logs.tokens.output")}{formatEstimatedUsdValue(cost.estimate.cost.output, localeTag)} + {t("logs.detail.costTotal")}{formatEstimatedUsdValue(cost.estimate.cost.total, localeTag, cost.estimateReasons.includes("priority_lower_bound"))} + {t("logs.tokens.input")}{formatEstimatedUsdValue(cost.estimate.cost.input, localeTag, cost.estimateReasons.includes("priority_lower_bound"))} + {t("logs.tokens.cacheRead")}{formatEstimatedUsdValue(cost.estimate.cost.cacheRead, localeTag, cost.estimateReasons.includes("priority_lower_bound"))} + {t("logs.tokens.cacheWrite")}{formatEstimatedUsdValue(cost.estimate.cost.cacheWrite, localeTag, cost.estimateReasons.includes("priority_lower_bound"))} + {t("logs.tokens.output")}{formatEstimatedUsdValue(cost.estimate.cost.output, localeTag, cost.estimateReasons.includes("priority_lower_bound"))} {cost.estimate.price && ( <> {t("logs.detail.matchedKey")} diff --git a/gui/src/pages/logs-cost-format.ts b/gui/src/pages/logs-cost-format.ts new file mode 100644 index 0000000000..65ce2e1d47 --- /dev/null +++ b/gui/src/pages/logs-cost-format.ts @@ -0,0 +1,11 @@ +export function formatEstimatedUsdTotal( + totalUsd: number | undefined, + lowerBound: boolean, + localeTag?: string, +): string { + if (totalUsd === undefined || !Number.isFinite(totalUsd) || totalUsd < 0) return "\u2014"; + return `${lowerBound ? "≥$" : "~$"}${new Intl.NumberFormat(localeTag, { + minimumFractionDigits: 4, + maximumFractionDigits: 4, + }).format(totalUsd)}`; +} diff --git a/gui/tests/logs-cost-lower-bound.test.ts b/gui/tests/logs-cost-lower-bound.test.ts new file mode 100644 index 0000000000..eddb95039e --- /dev/null +++ b/gui/tests/logs-cost-lower-bound.test.ts @@ -0,0 +1,10 @@ +import { expect, test } from "bun:test"; +import { formatEstimatedUsdTotal } from "../src/pages/logs-cost-format"; + +test("ordinary dashboard costs retain the estimate marker", () => { + expect(formatEstimatedUsdTotal(0.77, false, "en-US")).toBe("~$0.7700"); +}); + +test("priority long-context lower bounds render with a greater-than-or-equal marker", () => { + expect(formatEstimatedUsdTotal(0.77, true, "en-US")).toBe("≥$0.7700"); +}); diff --git a/src/codex/catalog/effort.ts b/src/codex/catalog/effort.ts index 3bf5daa086..0648b64d17 100644 --- a/src/codex/catalog/effort.ts +++ b/src/codex/catalog/effort.ts @@ -147,7 +147,7 @@ export function applyCatalogModelMetadata(entry: RawEntry, model?: CatalogModel) entry.service_tiers = [{ id: "priority", name: "Fast", - description: "1.5x speed, increased usage", + description: model.fastTierDescription ?? "1.5x speed, increased usage", }]; entry.additional_speed_tiers = ["fast"]; } diff --git a/src/codex/catalog/parsing.ts b/src/codex/catalog/parsing.ts index f42049150e..7ef17e6c14 100644 --- a/src/codex/catalog/parsing.ts +++ b/src/codex/catalog/parsing.ts @@ -125,6 +125,8 @@ export interface CatalogModel { supportsVerbosity?: boolean; /** Whether this exact routed model has a verified OpenAI-compatible service tier. */ supportsServiceTier?: boolean; + /** Optional provider-specific copy for the advertised Fast tier. */ + fastTierDescription?: string; supportsReasoningSummaries?: boolean; /** Normalized upstream capability names retained for management/API consumers (#485 follow-up). */ capabilities?: string[]; diff --git a/src/codex/catalog/provider-fetch.ts b/src/codex/catalog/provider-fetch.ts index 69203c8940..b5e01a8e49 100644 --- a/src/codex/catalog/provider-fetch.ts +++ b/src/codex/catalog/provider-fetch.ts @@ -34,7 +34,8 @@ import { getModelMetadata, getModelMetadataCaseInsensitive, listModelMetadata, r import { enrichProviderFromRegistry, shouldCaseFoldMetadataModelId } from "../../providers/derive"; import { captureFastPolicyAuthority, - serviceTierSupportForModel, + fastPolicyForModel, + serviceTierSupportFromPolicy, } from "../../providers/service-tier"; import type { FastPolicyAuthority } from "../../providers/fastwire"; import { effectiveGoogleMode, getProviderRegistryEntry, providerMatchesRegistryTransport } from "../../providers/registry"; @@ -646,8 +647,13 @@ export function applyProviderConfigHints(name: string, prov: OcxProviderConfig, const reasoningEfforts = configuredReasoningEfforts(prov, model.id); const defaultReasoningEffort = modelRecordValue(prov.modelDefaultReasoningEfforts, model.id) ?? model.defaultReasoningEffort; const supportsReasoningSummaries = configuredReasoningSummarySupport(prov, model.id); - const supportsServiceTier = serviceTierSupportForModel(prov, model.id, name); - const { supportsServiceTier: _staleServiceTier, ...modelWithoutServiceTier } = model; + const fastPolicy = fastPolicyForModel(prov, model.id, name); + const supportsServiceTier = serviceTierSupportFromPolicy(fastPolicy); + const { + supportsServiceTier: _staleServiceTier, + fastTierDescription: _staleFastTierDescription, + ...modelWithoutServiceTier + } = model; // 已发现窗口只允许被配置值压低;缺窗口时,已开的 Context cap 就是实际窗口。 const discoveredWindow = typeof model.contextWindow === "number" && model.contextWindow > 0 ? model.contextWindow @@ -670,6 +676,9 @@ export function applyProviderConfigHints(name: string, prov: OcxProviderConfig, ...(defaultReasoningEffort ? { defaultReasoningEffort } : {}), ...(typeof supportsReasoningSummaries === "boolean" ? { supportsReasoningSummaries } : {}), ...(typeof supportsServiceTier === "boolean" ? { supportsServiceTier } : {}), + ...(supportsServiceTier === true && fastPolicy.fastTierDescription !== undefined + ? { fastTierDescription: fastPolicy.fastTierDescription } + : {}), ...(prov.adapter === "kiro" ? { supportsVerbosity: false } : {}), // Default-on for openai-chat providers (explicit false opts out); other adapters // advertise only on explicit opt-in. @@ -1837,8 +1846,11 @@ async function gatherRoutedModelsUncached( ? nativeDefaultReasoningEffort(cm.modelId) : undefined; const supportsReasoningSummaries = configuredReasoningSummarySupport(rawProvider, cm.modelId); - const supportsServiceTier = effectiveProvider - ? serviceTierSupportForModel(effectiveProvider, cm.modelId, cm.provider) + const fastPolicy = effectiveProvider + ? fastPolicyForModel(effectiveProvider, cm.modelId, cm.provider) + : undefined; + const supportsServiceTier = fastPolicy + ? serviceTierSupportFromPolicy(fastPolicy) : undefined; const base: CatalogModel = { id: cm.modelId, @@ -1875,6 +1887,9 @@ async function gatherRoutedModelsUncached( ...(Array.isArray(cm.reasoningEfforts) ? { reasoningEfforts: [...cm.reasoningEfforts] } : {}), ...(cm.defaultReasoningEffort ? { defaultReasoningEffort: cm.defaultReasoningEffort } : {}), ...(typeof supportsServiceTier === "boolean" ? { supportsServiceTier } : {}), + ...(supportsServiceTier === true && fastPolicy?.fastTierDescription !== undefined + ? { fastTierDescription: fastPolicy.fastTierDescription } + : {}), }; // #962: the dedupe below drops the provider-derived row this custom row replaces. Inherit that // row's provider capability metadata (reasoning ladder, default effort, parallel tool calls, diff --git a/src/providers/fastwire.ts b/src/providers/fastwire.ts index d36a9cf19f..00e4bb198e 100644 --- a/src/providers/fastwire.ts +++ b/src/providers/fastwire.ts @@ -32,6 +32,7 @@ export type FastPolicyAuthTransport = export interface FastPolicyAuthority { readonly providerAdapter: string; readonly fastWireDeclaration: FastWire | null | undefined; + readonly fastTierDescription?: string; readonly modelWireOverrideAllowed: boolean; readonly authTransport: FastPolicyAuthTransport; readonly capability: { @@ -54,6 +55,7 @@ export interface ResolvedFastPolicy { | "pin-unavailable"; readonly adapter: string; readonly fastWire: FastWire | null; + readonly fastTierDescription?: string; readonly forwardCallerTier: boolean; } @@ -185,7 +187,16 @@ export function resolveFastPolicy( else if (capability === undefined) eligibility = "unclassified"; else eligibility = "eligible"; - return { capability, eligibility, adapter, fastWire, forwardCallerTier }; + return { + capability, + eligibility, + adapter, + fastWire, + ...(authority.fastTierDescription !== undefined + ? { fastTierDescription: authority.fastTierDescription } + : {}), + forwardCallerTier, + }; } export function canonicalFastTierMarker(callerTier: string | undefined): "priority" | undefined { diff --git a/src/providers/registry.ts b/src/providers/registry.ts index c81735ba15..a81a038add 100644 --- a/src/providers/registry.ts +++ b/src/providers/registry.ts @@ -217,6 +217,18 @@ export interface ProviderRegistryEntry { supportsServiceTier?: boolean; /** Registry default for exact model service-tier capability; explicit config keys win. */ modelSupportsServiceTier?: Record; + /** + * Registry-only service-tier defaults for an OAuth preset's explicit API-key transport. + * Applied only when `allowKeyAuthOverride` is true and the captured effective auth transport + * is key-based. Explicit provider config still wins field-by-field, including `false`. + */ + keyAuthServiceTier?: { + supportsServiceTier?: boolean; + modelSupportsServiceTier?: Record; + chatServiceTier?: boolean; + }; + /** Provider-specific copy for the Codex catalog's Fast tier. */ + fastTierDescription?: string; /** Registry default for plaintext reasoning replay; see `OcxProviderConfig.preserveResponsesReasoningContent`. Registry-only like `supportsServiceTier`. */ preserveResponsesReasoningContent?: boolean; /** Registry defaults for per-model Codex reasoning propagation; explicit user keys win during enrichment. */ @@ -991,6 +1003,14 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [ baseUrl: "https://api.x.ai/v1", authKind: "oauth", allowKeyAuthOverride: true, + // Priority Processing is documented for xAI's public API-key Chat Completions and + // Responses endpoints. OAuth is a separate Grok CLI subscription gateway and remains + // unclassified; do not turn this into a provider-wide supportsServiceTier declaration. + keyAuthServiceTier: { + supportsServiceTier: true, + chatServiceTier: true, + }, + fastTierDescription: "Priority processing, 2x token price", featured: true, oauthId: "xai", jawcodeBundle: "xai", diff --git a/src/providers/service-tier.ts b/src/providers/service-tier.ts index a06c42c7b4..bfd613d4c2 100644 --- a/src/providers/service-tier.ts +++ b/src/providers/service-tier.ts @@ -59,22 +59,41 @@ function buildFastPolicyAuthority( registryTransportMatch: boolean, ): FastPolicyAuthority { const registry = registryTransportMatch ? getProviderRegistryEntry(providerName) : undefined; + const authTransport = resolveProviderAuthTransport( + provider.adapter, + provider.authMode ?? registry?.authKind ?? "key", + provider.apiKeyTransport, + ); + const keyAuthDefaults = registry?.allowKeyAuthOverride === true + && (authTransport === "authorization_bearer" || authTransport === "x_api_key") + ? registry.keyAuthServiceTier + : undefined; const authority: FastPolicyAuthority = Object.freeze({ providerAdapter: provider.adapter, fastWireDeclaration: cloneFastWire( provider.fastWire !== undefined ? provider.fastWire : registry?.fastWire, { freeze: true }, ), + ...(registry?.fastTierDescription !== undefined + ? { fastTierDescription: registry.fastTierDescription } + : {}), modelWireOverrideAllowed: !isCanonicalOpenAiForwardProvider(provider as OcxProviderConfig), - authTransport: resolveProviderAuthTransport( - provider.adapter, - provider.authMode ?? registry?.authKind ?? "key", - provider.apiKeyTransport, - ), + authTransport, capability: Object.freeze({ - ...(provider.supportsServiceTier !== undefined ? { provider: provider.supportsServiceTier } : {}), - models: Object.freeze({ ...(provider.modelSupportsServiceTier ?? {}) }), - ...(provider.chatServiceTier !== undefined ? { chatServiceTier: provider.chatServiceTier } : {}), + ...(provider.supportsServiceTier !== undefined + ? { provider: provider.supportsServiceTier } + : keyAuthDefaults?.supportsServiceTier !== undefined + ? { provider: keyAuthDefaults.supportsServiceTier } + : {}), + models: Object.freeze({ + ...(keyAuthDefaults?.modelSupportsServiceTier ?? {}), + ...(provider.modelSupportsServiceTier ?? {}), + }), + ...(provider.chatServiceTier !== undefined + ? { chatServiceTier: provider.chatServiceTier } + : keyAuthDefaults?.chatServiceTier !== undefined + ? { chatServiceTier: keyAuthDefaults.chatServiceTier } + : {}), }), modelAdapters: Object.freeze({ ...(provider.modelAdapters ?? {}) }), hardPins: captureWireAdapterHardPins(providerName), diff --git a/src/server/management/shared.ts b/src/server/management/shared.ts index 77d1f74264..3ebea685e8 100644 --- a/src/server/management/shared.ts +++ b/src/server/management/shared.ts @@ -86,7 +86,8 @@ export type CostEstimateReason = | "usage_estimated" | "cache_detail_missing" | "expected_price_overlay" - | "provider_cost_overlay"; + | "provider_cost_overlay" + | "priority_lower_bound"; export type CostResult = | { kind: "value"; estimate: NonNullable>; estimateReasons: CostEstimateReason[] } @@ -143,6 +144,7 @@ export function costResult(entry: MetricSource): CostResult { ? "expected_price_overlay" as const : undefined, estimate.price?.source === "user" || estimate.attempts?.some(a => a.price.source === "user") ? "provider_cost_overlay" as const : undefined, + estimate.priorityLowerBound ? "priority_lower_bound" as const : undefined, ].filter((reason): reason is CostEstimateReason => reason !== undefined); return { kind: "value", estimate, estimateReasons }; } diff --git a/src/usage/cost.ts b/src/usage/cost.ts index 5cf798e144..b574723902 100644 --- a/src/usage/cost.ts +++ b/src/usage/cost.ts @@ -22,7 +22,8 @@ import { activeConfiguredProviders, activeUserCostOverlays, userCostOverlayVersi import { EXPECTED_PRICE_OVERLAYS, findExpectedPriceOverlay, - resolvePriorityMultiplier, + findVerifiedPriceOverride, + findPriorityPricingRule, findContextTier, isLongContext, type Cost4, @@ -81,10 +82,12 @@ export interface AttemptCostEstimate { price: MatchedPrice; cost: CostBreakdown; estimated: boolean; - /** Applied OpenAI priority-tier multiplier (undefined or 1 = standard). */ + /** Applied provider priority-tier multiplier (undefined or 1 = standard). */ priorityMultiplier?: number; /** Set when the published long-context rate was applied (#908). */ contextTier?: ContextTierName; + /** Confirmed priority + long context has no published combined rate; this cost is a floor. */ + priorityLowerBound?: true; } export interface CostEstimate { @@ -93,10 +96,12 @@ export interface CostEstimate { estimated: boolean; attempts?: AttemptCostEstimate[]; price?: MatchedPrice; - /** Applied OpenAI priority-tier multiplier (undefined or 1 = standard). */ + /** Applied provider priority-tier multiplier (undefined or 1 = standard). */ priorityMultiplier?: number; /** Set when any priced attempt used the published long-context rate (#908). */ contextTier?: ContextTierName; + /** Set when any priced attempt is only a known lower bound. */ + priorityLowerBound?: true; } function finiteNonNegative(value: number): boolean { @@ -232,7 +237,7 @@ function resolveMatchedPriceInner( /** * Exact provider/model price lookup: user-configured `modelCosts` first, then - * the jawcode provider bundle, then the expected-price overlay, then the + * an exact official correction, the jawcode provider bundle, the expected-price overlay, then the * model-level vendor fallback. All-zero rows fall through ("not billable"). */ function resolveMatchedPriceExact( @@ -245,6 +250,20 @@ function resolveMatchedPriceExact( // operator's explicit price is authoritative for the ~$ estimate. const userOverlay = userOverlayMatch(provider, modelId, userOverlays); if (userOverlay) return userOverlay; + const verifiedOverride = overlays === EXPECTED_PRICE_OVERLAYS + ? findVerifiedPriceOverride(provider, modelId) + : undefined; + if (verifiedOverride && validCost4(verifiedOverride.cost4) && hasNonZeroCost(verifiedOverride.cost4)) { + return { + provider, + modelId, + cost4: verifiedOverride.cost4, + source: "expected", + sourceRef: verifiedOverride.source, + verifiedAt: verifiedOverride.verifiedAt, + status: "verified", + }; + } const metadataProvider = resolveMetadataProvider(provider); const bundled = metadataProvider ? getModelMetadata(metadataProvider, modelId) @@ -316,13 +335,6 @@ function isEstimated(usage: OcxUsage, usageStatus: UsageStatus, priceStatus: Exp return usage.estimated === true || usageStatus === "estimated" || priceStatus === "verified-derived"; } -/** - * OpenAI provider ids eligible for service_tier "priority" price multipliers. - * Only canonical OpenAI forward providers use the priority tier; routed providers - * (OpenRouter, Cursor, etc.) may share model slugs but have independent pricing. - */ -const OPENAI_TIER_PROVIDER_IDS = new Set(["openai", "openai-apikey"]); - /** * Resolve the effective service tier from persisted log fields. * Priority: responseServiceTier (server-confirmed) > requestedServiceTier @@ -399,9 +411,9 @@ function isConfirmedFast(tier?: ServiceTierInput): boolean { * normalized billable input — normalization subtracts cache read/write, so a * cache-heavy long prompt would fall below the boundary and under-bill. * - * Skipped entirely for a response-confirmed Fast request: OpenAI does not serve - * long context in Fast mode, so the two are mutually exclusive regimes rather - * than composable multipliers. + * A provider's declaration decides how a response-confirmed priority tier relates to this band. + * OpenAI declares the bands exclusive. xAI publishes neither a combined rate nor an exclusion, + * so its long-context rate remains the known lower bound instead of inventing a stacked multiplier. */ function applyContextTier( cost4: Cost4, @@ -409,25 +421,27 @@ function applyContextTier( modelId: string, rawInputTokens: number | undefined, tier?: ServiceTierInput, -): [Cost4, ContextTierName | undefined] { - if (rawInputTokens === undefined) return [cost4, undefined]; - if (isConfirmedFast(tier)) return [cost4, undefined]; +): [Cost4, ContextTierName | undefined, boolean] { + if (rawInputTokens === undefined) return [cost4, undefined, false]; const rule = findContextTier(baseProviderLabel(provider), modelId); - if (!rule || !isLongContext(rule, rawInputTokens)) return [cost4, undefined]; + if (!rule || !isLongContext(rule, rawInputTokens)) return [cost4, undefined, false]; + const confirmedFast = isConfirmedFast(tier); + if (confirmedFast && rule.confirmedPriorityRelation === "exclusive") { + return [cost4, undefined, false]; + } return [{ input: cost4.input * rule.multiplier.input, output: cost4.output * rule.multiplier.output, cacheRead: cost4.cacheRead * rule.multiplier.cacheRead, cacheWrite: cost4.cacheWrite * rule.multiplier.cacheWrite, - }, "long"]; + }, "long", confirmedFast && rule.confirmedPriorityRelation === "lower-bound"]; } /** - * Apply the OpenAI priority-tier multiplier to a Cost4 when applicable. + * Apply a declared provider/model priority-tier multiplier to a Cost4 when applicable. * Returns [effectiveCost4, multiplier]. Multiplier is 1 (no-op) when: * - serviceTier is not "priority" - * - provider is not a canonical OpenAI forward provider - * - model is not in PRIORITY_MULTIPLIERS + * - no exact provider/model rule exists */ function applyPriorityMultiplier( cost4: Cost4, @@ -437,8 +451,7 @@ function applyPriorityMultiplier( ): [Cost4, number] { if (tierScalar(serviceTier) !== "priority") return [cost4, 1]; const base = baseProviderLabel(provider); - if (!OPENAI_TIER_PROVIDER_IDS.has(base)) return [cost4, 1]; - const multiplier = resolvePriorityMultiplier(modelId); + const multiplier = findPriorityPricingRule(base, modelId)?.multiplier ?? 1; if (multiplier === 1) return [cost4, 1]; return [{ input: cost4.input * multiplier, @@ -467,12 +480,12 @@ export function estimateAttemptCost( const attemptServiceTier = attempt.tierOutcome ? serviceTierContextFromOutcome(attempt.tierOutcome) : serviceTier; - const [tieredCost4, contextTier] = applyContextTier( + const [tieredCost4, contextTier, priorityLowerBound] = applyContextTier( price.cost4, attempt.provider, attempt.model, attempt.usage.inputTokens, attemptServiceTier, ); - // Exclusive both ways: if the long rate applied, the request was NOT served as - // Fast (Fast does not support long context), so the Fast multiplier must not - // also apply — otherwise a downgraded request bills at both rates. + // A published long-context row owns the numeric estimate. OpenAI declares that band + // exclusive with Fast; xAI's confirmed combination is deliberately left unmultiplied + // and marked as a lower bound because no combined price has been published. const [effectiveCost4, multiplier] = contextTier ? [tieredCost4, 1] as const : applyPriorityMultiplier(tieredCost4, attempt.provider, attempt.model, attemptServiceTier); @@ -486,6 +499,7 @@ export function estimateAttemptCost( estimated: isEstimated(attempt.usage, attempt.usageStatus, price.status), ...(multiplier !== 1 ? { priorityMultiplier: multiplier } : {}), ...(contextTier ? { contextTier } : {}), + ...(priorityLowerBound ? { priorityLowerBound: true as const } : {}), }; } @@ -528,6 +542,7 @@ export function estimateComboCost( ? { priorityMultiplier: estimates.find(est => est.priorityMultiplier)?.priorityMultiplier } : {}), ...(estimates.some(est => est.contextTier) ? { contextTier: "long" as const } : {}), + ...(estimates.some(est => est.priorityLowerBound) ? { priorityLowerBound: true as const } : {}), }; } @@ -548,7 +563,7 @@ export function estimateRequestCost( if (!tokens) return null; const price = resolveMatchedPrice(input.provider, input.model, overlays, userOverlays); if (!price) return null; - const [tieredCost4, contextTier] = applyContextTier( + const [tieredCost4, contextTier, priorityLowerBound] = applyContextTier( price.cost4, input.provider, input.model, input.usage.inputTokens, input.serviceTier, ); const [effectiveCost4, multiplier] = contextTier @@ -561,6 +576,7 @@ export function estimateRequestCost( estimated: isEstimated(input.usage, input.usageStatus, price.status), ...(multiplier !== 1 ? { priorityMultiplier: multiplier } : {}), ...(contextTier ? { contextTier } : {}), + ...(priorityLowerBound ? { priorityLowerBound: true as const } : {}), }; } diff --git a/src/usage/expected-prices.ts b/src/usage/expected-prices.ts index 64a42e87e7..d0cb90d139 100644 --- a/src/usage/expected-prices.ts +++ b/src/usage/expected-prices.ts @@ -181,6 +181,30 @@ export const EXPECTED_PRICE_OVERLAYS: readonly ExpectedPriceOverlay[] = [ { provider: "cursor", modelId: "auto", cost4: { input: 1.25, output: 6, cacheRead: 0.25, cacheWrite: 1.25 }, source: "https://docs.cursor.com/account/pricing + https://cursor.com/blog/aug-2025-pricing", verifiedAt: "2026-07-20", status: "verified" }, ]; +/** + * Exact official corrections for stale nonzero catalog rows. These are intentionally separate + * from fallback overlays: they win over the bundled row only for the declared provider/model and + * therefore cannot reprice routed resellers that reuse the same model slug. + */ +export const VERIFIED_PRICE_OVERRIDES: readonly ExpectedPriceOverlay[] = [ + { + provider: "xai", + modelId: "grok-4.6", + cost4: { input: 2, output: 6, cacheRead: 0.5, cacheWrite: 0 }, + source: "https://docs.x.ai/developers/pricing", + verifiedAt: "2026-08-18", + status: "verified", + }, +]; + +export function findVerifiedPriceOverride( + provider: string, + modelId: string, + overrides: readonly ExpectedPriceOverlay[] = VERIFIED_PRICE_OVERRIDES, +): ExpectedPriceOverlay | undefined { + return overrides.find(row => row.provider === provider && row.modelId === modelId); +} + /** * Exact-key overlay lookup. Returns verified first, then verified-derived. * NEVER returns "unverified" rows — fail-closed is enforced in code, not just docs. @@ -196,12 +220,7 @@ export function findExpectedPriceOverlay( ?? exact.find(row => row.status === "verified-derived"); } -/** - * OpenAI Fast mode (`service_tier=priority`) price multipliers by model slug. - * Source: https://openai.com/api-fast-mode/ (2026-07-31). - * Fast pricing applies uniformly to all token types (input, output, cache). - * Models not listed here fall back to 1× (no multiplier). - */ +/** OpenAI Fast price multipliers retained as a compatibility export. */ export const PRIORITY_MULTIPLIERS: Readonly> = { "gpt-5.6-sol": 2, // Post-price-cut Fast tables (https://openai.com/api-fast-mode/, 2026-08-05): @@ -219,6 +238,49 @@ export function resolvePriorityMultiplier(modelId: string): number { return PRIORITY_MULTIPLIERS[modelId] ?? 1; } +export interface PriorityPricingRule { + provider: string; + modelId: string; + multiplier: number; + source: string; + verifiedAt: string; +} + +const OPENAI_FAST_PRICING = "https://openai.com/api-fast-mode/"; +const XAI_PRIORITY_PRICING = "https://docs.x.ai/developers/advanced-api-usage/priority-processing"; + +/** + * Exact provider/model priority premiums. Routed resellers never inherit a vendor rule merely + * because they reuse its model slug. Multipliers apply uniformly after cache discounts. + */ +export const PRIORITY_PRICING_RULES: readonly PriorityPricingRule[] = [ + ...["openai", "openai-apikey"].flatMap(provider => + Object.entries(PRIORITY_MULTIPLIERS).map(([modelId, multiplier]): PriorityPricingRule => ({ + provider, + modelId, + multiplier, + source: OPENAI_FAST_PRICING, + verifiedAt: "2026-08-05", + })), + ), + ...["grok-4.5", "grok-4.6"].map((modelId): PriorityPricingRule => ({ + provider: "xai", + modelId, + multiplier: 2, + source: XAI_PRIORITY_PRICING, + verifiedAt: "2026-08-18", + })), +]; + +/** Exact provider/model priority-pricing lookup. */ +export function findPriorityPricingRule( + provider: string, + modelId: string, + rules: readonly PriorityPricingRule[] = PRIORITY_PRICING_RULES, +): PriorityPricingRule | undefined { + return rules.find(rule => rule.provider === provider && rule.modelId === modelId); +} + /** * Long-context pricing tiers (#908). Several vendors reprice the ENTIRE request * once the prompt crosses a published input-token threshold, so a flat Cost4 @@ -244,6 +306,8 @@ export interface ContextTier { inclusive: boolean; /** Per-field factor from the short rate to the published long rate. */ multiplier: Cost4; + /** Published relationship between confirmed priority and long-context bands. */ + confirmedPriorityRelation?: "exclusive" | "lower-bound"; source: string; verifiedAt: string; } @@ -277,6 +341,7 @@ export const CONTEXT_TIERS: readonly ContextTier[] = [ thresholdInputTokens: 272_000, inclusive: false, multiplier: OPENAI_LONG_CONTEXT, + confirmedPriorityRelation: "exclusive", source: OPENAI_PRICING_DOC, verifiedAt: "2026-08-03", })), @@ -287,19 +352,21 @@ export const CONTEXT_TIERS: readonly ContextTier[] = [ thresholdInputTokens: 200_000, inclusive: true, multiplier: UNIFORM_DOUBLE, + confirmedPriorityRelation: "lower-bound", source: "https://docs.x.ai/developers/pricing", verifiedAt: "2026-08-03", }, { - // 260813: grok-4.6 long-context tier mirrored from grok-4.5; the official pricing row - // was not yet published when the model page went up, so treat as provisional. + // xAI publishes the whole-request >=200k band for grok-4.6. Its combination with + // Priority Processing is not published, so confirmed priority uses this row as a lower bound. provider: "xai", modelId: "grok-4.6", thresholdInputTokens: 200_000, inclusive: true, multiplier: UNIFORM_DOUBLE, + confirmedPriorityRelation: "lower-bound", source: "https://docs.x.ai/developers/pricing", - verifiedAt: "2026-08-13", + verifiedAt: "2026-08-18", }, { // daybreak-blue-latest aliases gpt-5.6-sol, which publishes the full long-context row diff --git a/tests/management-api-logs-metrics.test.ts b/tests/management-api-logs-metrics.test.ts index f7077a8951..0255005e2f 100644 --- a/tests/management-api-logs-metrics.test.ts +++ b/tests/management-api-logs-metrics.test.ts @@ -95,6 +95,31 @@ describe("GET /api/logs display metrics", () => { expect(dto!.displayMetrics.cost.estimateReasons).toContain("cache_detail_missing"); }); + test("confirmed xAI priority plus long context is exposed as a cost lower bound", async () => { + addRequestLog(baseEntry({ + provider: "xai", + model: "grok-4.6", + usage: { + inputTokens: 200_000, + outputTokens: 10_000, + cacheReadInputTokens: 50_000, + }, + tierOutcome: { + canonical: "priority", + wireKind: "service-tier", + wireValue: "priority", + fastOutcome: "applied", + confirmation: "confirmed", + responseServiceTier: "priority", + }, + })); + const [dto] = await readLogs(); + expect(dto!.displayMetrics.cost.kind).toBe("value"); + expect(dto!.displayMetrics.cost.estimate.priorityLowerBound).toBe(true); + expect(dto!.displayMetrics.cost.estimate.cost.total).toBeCloseTo(0.77, 9); + expect(dto!.displayMetrics.cost.estimateReasons).toContain("priority_lower_bound"); + }); + test("unmatched price is unavailable instead of zero", async () => { addRequestLog(baseEntry({ provider: "no-such-provider", diff --git a/tests/service-tier-capability.test.ts b/tests/service-tier-capability.test.ts index 2e397be86b..2cbf756548 100644 --- a/tests/service-tier-capability.test.ts +++ b/tests/service-tier-capability.test.ts @@ -7,12 +7,20 @@ * ever receiving an injection (PR #860 family). */ import { afterEach, describe, expect, test } from "bun:test"; +import { buildCatalogEntries, gatherRoutedModels } from "../src/codex/catalog"; import { providerConfigSeed, enrichProviderFromRegistry } from "../src/providers/derive"; import { getProviderRegistryEntry } from "../src/providers/registry"; +import { decideTier } from "../src/providers/fastwire"; import type { RequestLogContext } from "../src/server/request-log"; import { applyServiceTierGate, handleResponses } from "../src/server/responses/core"; -import { canForwardServiceTierForModel, serviceTierSupportForModel, supportsServiceTierForModel } from "../src/providers/service-tier"; -import { serviceTierAdapterForModel } from "../src/providers/service-tier"; +import { + canForwardServiceTierForModel, + fastPolicyForModel, + serviceTierAdapterForModel, + serviceTierSupportForModel, + serviceTierSupportFromPolicy, + supportsServiceTierForModel, +} from "../src/providers/service-tier"; import { candidateCapabilityEvidence } from "../src/routing/capability"; import { resolveProductionBehaviorValues } from "../src/routing/compatibility/behavior"; import type { OcxConfig, OcxProviderConfig } from "../src/types"; @@ -47,6 +55,92 @@ describe("registry capability reaches saved configs without overriding them", () }); }); +describe("xAI Fast capability follows the captured authentication transport", () => { + function xaiProvider( + authMode: "key" | "oauth", + overrides: Partial = {}, + ): OcxProviderConfig { + return { + ...providerConfigSeed(getProviderRegistryEntry("xai")!), + authMode, + apiKey: authMode === "key" ? "xai-test-key" : "oauth-test-token", + liveModels: false, + models: ["grok-4.6"], + ...overrides, + }; + } + + async function catalogEntry(provider: OcxProviderConfig) { + const models = await gatherRoutedModels({ + providers: { xai: provider }, + } as unknown as OcxConfig); + return buildCatalogEntries(null, [], models) + .find(entry => entry.slug === "xai/grok-4.6"); + } + + test("registry declares a key-auth overlay without classifying OAuth", () => { + const entry = getProviderRegistryEntry("xai")!; + expect(entry.keyAuthServiceTier).toEqual({ + supportsServiceTier: true, + chatServiceTier: true, + }); + expect(entry.supportsServiceTier).toBeUndefined(); + expect(entry.chatServiceTier).toBeUndefined(); + + const keyPolicy = fastPolicyForModel(xaiProvider("key"), "grok-4.6", "xai"); + expect(keyPolicy).toMatchObject({ + capability: true, + eligibility: "eligible", + forwardCallerTier: true, + fastTierDescription: "Priority processing, 2x token price", + }); + + const oauthPolicy = fastPolicyForModel(xaiProvider("oauth"), "grok-4.6", "xai"); + expect(oauthPolicy.capability).toBeUndefined(); + expect(oauthPolicy.eligibility).toBe("unclassified"); + expect(oauthPolicy.forwardCallerTier).toBe(false); + }); + + test("catalog and runtime publish the same key/OAuth conclusion", async () => { + const keyProvider = xaiProvider("key"); + const keyPolicy = fastPolicyForModel(keyProvider, "grok-4.6", "xai"); + const keyCatalog = await catalogEntry(keyProvider); + expect(serviceTierSupportFromPolicy(keyPolicy)).toBe(true); + expect(keyCatalog?.service_tiers).toEqual([{ + id: "priority", + name: "Fast", + description: "Priority processing, 2x token price", + }]); + expect(keyCatalog?.additional_speed_tiers).toEqual(["fast"]); + expect(decideTier(keyPolicy, true, undefined)).toEqual({ kind: "set", value: "priority" }); + + const oauthProvider = xaiProvider("oauth"); + const oauthPolicy = fastPolicyForModel(oauthProvider, "grok-4.6", "xai"); + const oauthCatalog = await catalogEntry(oauthProvider); + expect(serviceTierSupportFromPolicy(oauthPolicy)).toBe(false); + expect(oauthCatalog).not.toHaveProperty("service_tiers"); + expect(oauthCatalog).not.toHaveProperty("additional_speed_tiers"); + expect(decideTier(oauthPolicy, true, undefined)).toEqual({ kind: "drop" }); + }); + + test("explicit supportsServiceTier=false wins in policy and catalog for both transports", async () => { + for (const authMode of ["key", "oauth"] as const) { + const provider = xaiProvider(authMode, { supportsServiceTier: false }); + const policy = fastPolicyForModel( + provider, + "grok-4.6", + "xai", + ); + expect(policy.capability).toBe(false); + expect(policy.eligibility).toBe("capability-unsupported"); + expect(decideTier(policy, true, undefined)).toEqual({ kind: "drop" }); + const catalog = await catalogEntry(provider); + expect(catalog).not.toHaveProperty("service_tiers"); + expect(catalog).not.toHaveProperty("additional_speed_tiers"); + } + }); +}); + describe("service-tier capability is exact-model and provider-scoped", () => { test("an exact model entry overrides the provider fallback in both directions", () => { const provider: OcxProviderConfig = { @@ -237,6 +331,16 @@ describe("the gate fires on the live handleResponses path", () => { ({ ...providerConfigSeed(getProviderRegistryEntry("deepseek")!), apiKey: "sk-test" }); const openAiKeyProvider = (): OcxProviderConfig => ({ ...providerConfigSeed(getProviderRegistryEntry("openai-apikey")!), apiKey: "sk-test" }); + const xaiKeyProvider = (): OcxProviderConfig => ({ + ...providerConfigSeed(getProviderRegistryEntry("xai")!), + authMode: "key", + apiKey: "xai-test-key", + }); + const xaiOAuthProvider = (): OcxProviderConfig => ({ + ...providerConfigSeed(getProviderRegistryEntry("xai")!), + authMode: "oauth", + apiKey: "xai-oauth-test-token", + }); test("DeepSeek never receives service_tier, even with fastMode on", async () => { const body = await drive("deepseek", deepseekProvider(), "deepseek-v4-flash", {}, true); @@ -286,6 +390,23 @@ describe("the gate fires on the live handleResponses path", () => { expect(body.service_tier).toBe("flex"); }); + test("xAI API-key runtime injects priority while OAuth does not", async () => { + const keyBody = await drive("xai", xaiKeyProvider(), "grok-4.6", {}, true); + expect(keyBody.service_tier).toBe("priority"); + const oauthBody = await drive("xai", xaiOAuthProvider(), "grok-4.6", {}, true); + expect(oauthBody).not.toHaveProperty("service_tier"); + for (const provider of [xaiKeyProvider(), xaiOAuthProvider()]) { + const optedOut = await drive( + "xai", + { ...provider, supportsServiceTier: false }, + "grok-4.6", + {}, + true, + ); + expect(optedOut).not.toHaveProperty("service_tier"); + } + }); + test("an unclassified custom Responses provider keeps caller values; only explicit false strips", async () => { const custom = (): OcxProviderConfig => ({ adapter: "openai-responses", baseUrl: "https://gateway.example.com/v1", apiKey: "sk-test" }); const preserved = await drive("custom-gw", custom(), "some-model", { service_tier: "priority" }); @@ -328,4 +449,3 @@ describe("unclassified chat-wire tier projection (release-audit fix)", () => { expect(serviceTierSupportForModel(provider, "some-model")).toBeUndefined(); }); }); - diff --git a/tests/usage-cost.test.ts b/tests/usage-cost.test.ts index 11fa3d77fc..a7f58d4d88 100644 --- a/tests/usage-cost.test.ts +++ b/tests/usage-cost.test.ts @@ -1,4 +1,5 @@ import { afterEach, describe, expect, test } from "bun:test"; +import { createAdapterTierMetadata } from "../src/providers/fastwire"; import { calculateCost, estimateAttemptCost, @@ -12,8 +13,10 @@ import { import { EXPECTED_PRICE_OVERLAYS, PRIORITY_MULTIPLIERS, + PRIORITY_PRICING_RULES, CONTEXT_TIERS, findExpectedPriceOverlay, + findPriorityPricingRule, resolvePriorityMultiplier, type ExpectedPriceOverlay, } from "../src/usage/expected-prices"; @@ -564,6 +567,128 @@ describe("priority (Fast) service tier multiplier", () => { }); }); +describe("xAI Priority Processing pricing", () => { + const usage = { + inputTokens: 100_000, + outputTokens: 10_000, + cacheReadInputTokens: 20_000, + }; + + function outcome(responseServiceTier?: string) { + const tracker = createAdapterTierMetadata( + { + capability: true, + eligibility: "eligible", + fastWire: { + kind: "service-tier", + canonicalToWire: { priority: "priority" }, + foreignCallerTiers: "verbatim", + }, + demandDecision: "force-fast", + }, + { kind: "set", value: "priority" }, + "service-tier", + "priority", + )!; + if (responseServiceTier !== undefined) tracker.observeResponseServiceTier(responseServiceTier); + return tracker.outcome; + } + + function estimate(tierOutcome: ReturnType, requestUsage = usage) { + return estimateAttemptCost({ + ordinal: 1, + provider: "xai", + model: "grok-4.6", + usageStatus: "reported", + usage: requestUsage, + tierOutcome, + })!; + } + + test("xAI rules declare exact 2x premiums with official provenance", () => { + const xaiRules = PRIORITY_PRICING_RULES.filter(rule => rule.provider === "xai"); + expect(xaiRules.map(rule => rule.modelId)).toEqual(["grok-4.5", "grok-4.6"]); + expect(xaiRules.every(rule => rule.multiplier === 2)).toBe(true); + expect(xaiRules.every(rule => rule.source === "https://docs.x.ai/developers/advanced-api-usage/priority-processing")).toBe(true); + expect(findPriorityPricingRule("xai", "grok-4.6")?.multiplier).toBe(2); + expect(findPriorityPricingRule("openrouter", "grok-4.6")).toBeUndefined(); + expect(resolveMatchedPrice("openrouter", "grok-4.6")?.cost4).toEqual({ + input: 2, + output: 6, + cacheRead: 0.3, + cacheWrite: 0, + }); + expect(resolveMatchedPrice("cursor", "grok-4.6")?.cost4).toEqual({ + input: 2, + output: 6, + cacheRead: 0.3, + cacheWrite: 0, + }); + }); + + test("grok-4.6 standard and confirmed priority prices include the official cache rate", () => { + expect(resolveMatchedPrice("xai", "grok-4.6")?.cost4).toEqual({ + input: 2, + output: 6, + cacheRead: 0.5, + cacheWrite: 0, + }); + const confirmedOutcome = outcome("priority"); + const confirmed = estimate(confirmedOutcome); + expect(confirmedOutcome).toMatchObject({ + canonical: "priority", + fastOutcome: "applied", + confirmation: "confirmed", + }); + expect(confirmed.cost.total).toBeCloseTo(0.46, 9); + expect(confirmed.cost.cacheRead).toBeCloseTo(0.02, 9); + expect(confirmed.priorityMultiplier).toBe(2); + }); + + test("an assumed priority outcome uses the same 2x premium", () => { + const assumedOutcome = outcome(); + const assumed = estimate(assumedOutcome); + expect(assumedOutcome).toMatchObject({ + canonical: "priority", + fastOutcome: "applied", + confirmation: "assumed", + }); + expect(assumed.cost.total).toBeCloseTo(0.46, 9); + expect(assumed.priorityMultiplier).toBe(2); + }); + + test("an echoed default records a downgrade and bills the standard price", () => { + const downgradedOutcome = outcome("default"); + const downgraded = estimate(downgradedOutcome); + expect(downgradedOutcome).toMatchObject({ + fastOutcome: "downgraded", + fastDowngradeReason: "response-declined", + confirmation: "downgraded", + responseServiceTier: "default", + }); + expect(downgradedOutcome).not.toHaveProperty("canonical"); + expect(downgraded.cost.total).toBeCloseTo(0.23, 9); + expect(downgraded.priorityMultiplier).toBeUndefined(); + }); + + test("confirmed priority at 200k uses the long-context price as a marked lower bound", () => { + const long = estimate(outcome("priority"), { + inputTokens: 200_000, + outputTokens: 10_000, + cacheReadInputTokens: 50_000, + }); + expect(long.contextTier).toBe("long"); + expect(long.priorityMultiplier).toBeUndefined(); + expect(long.priorityLowerBound).toBe(true); + expect(long.cost).toMatchObject({ + input: 0.6, + cacheRead: 0.05, + output: 0.12, + }); + expect(long.cost.total).toBeCloseTo(0.77, 9); + }); +}); + describe("long-context pricing tiers (#908)", () => { const SOL: ExpectedPriceOverlay[] = [ { provider: "openai", modelId: "gpt-5.6-sol", cost4: { input: 5, output: 30, cacheRead: 0.5, cacheWrite: 6.25 }, source: "test", verifiedAt: "2026-08-03", status: "verified" }, From 057f93ea50aa82b402b1bfab1180feb8c1bbee22 Mon Sep 17 00:00:00 2001 From: olddonkey Date: Tue, 18 Aug 2026 15:18:35 -0700 Subject: [PATCH 002/114] docs(devlog): capture the xAI Fast pricing UI evidence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The readiness checklist requires a screenshot for GUI changes. Three seeded grok-4.6 rows exercise every branch of the new pricing path in one view: standard, a response-confirmed priority request at exactly the documented 2x premium, and a confirmed-priority request above the long-context threshold rendering as "≥$" because xAI publishes no combined rate. Captured against a local proxy with a seeded usage log; no live xAI request was billed to produce it. Co-Authored-By: Claude Fable 5 --- .../evidence/010_logs_priority_lower_bound.png | Bin 0 -> 155108 bytes .../260818_fastwire_b2_xai/evidence/README.md | 17 +++++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 devlog/_plan/260818_fastwire_b2_xai/evidence/010_logs_priority_lower_bound.png create mode 100644 devlog/_plan/260818_fastwire_b2_xai/evidence/README.md diff --git a/devlog/_plan/260818_fastwire_b2_xai/evidence/010_logs_priority_lower_bound.png b/devlog/_plan/260818_fastwire_b2_xai/evidence/010_logs_priority_lower_bound.png new file mode 100644 index 0000000000000000000000000000000000000000..e7ac2ea00753d4be8f7bcbc49396317eae39bdfa GIT binary patch literal 155108 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

o8>2 z7mmpdGI*tOg7$$WN%0C*F%dWIH&&qn(Pw$CE~6$rf@#{>FjJFC&C?F86liwI9M`z5 zkDn`ho`3Sye)EKnKM~`Xa5y`*BmBNpa zvHi-Sw5F3$QBjv7P%I}71b$R?AU^lvBS|OPE^Ju3I!PbRIE-OY;8@PtF5cb+HExLc z2l<7Uj#zj1_)jnATyJ|*06{{&I1m&?`D*TN78JAkG}=KC&9b}F-!`GN^h6Bsl9793g&hdRq{o$c}_kLUK|OTkFg-wcN(?b;$v$DK#5$|%%l!W*HO_|cbM*(F&hP}5(Tk&tK2;BmZ7 zDQD}0{H}BdYGG*wv(5vyA#Te=G!pe2qpt^BlDo%Sao+H5QKCTZF@o<|aX<{B#9puA zy89WJ(f8Ya?J3gOo4SKp-pOuATBnWc$jNM_3~zTp6Jn(2q@`r8gPBfB&y1T|w;{$oxion84z^||tuY`WNw52{yWse3Lkz1SZWOA8LSpqgSv%XxcI`

hx4@5;i6-rd@8l%URM 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�a&$Ph!rr~ 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 Q@D2<_>Z4@k2cxh54}?k+ssI20 literal 0 HcmV?d00001 diff --git a/devlog/_plan/260818_fastwire_b2_xai/evidence/README.md b/devlog/_plan/260818_fastwire_b2_xai/evidence/README.md new file mode 100644 index 0000000000..034ab80d71 --- /dev/null +++ b/devlog/_plan/260818_fastwire_b2_xai/evidence/README.md @@ -0,0 +1,17 @@ +# FastWire B2 (xAI) — UI evidence + +`010_logs_priority_lower_bound.png` — Logs & Debug, three seeded `xai/grok-4.6` rows +that exercise every branch of the new pricing path: + +| Row | Situation | Cost cell | +| --- | --- | --- | +| `req-standard` | no Fast requested | `~$0.0300` | +| `req-priority` | response-confirmed priority, prompt under the long-context threshold | `~$0.0600` — exactly the documented 2x premium over the row above | +| `req-longctx-priority` | response-confirmed priority, prompt above 200k | `≥$0.8760` — the published long-context rate, marked a lower bound because xAI publishes no combined price | + +The `≥` prefix is the visible change: a cost that is a known floor rather than an +estimate now says so instead of rendering as `~$`. The detail drawer explains why +via the `priority_lower_bound` estimate reason. + +Captured against a local proxy with a seeded `usage.jsonl`; no live xAI request was +billed to produce it. From 1d7d8177a383db5066e8040cfb6ae5e4ab6d52a9 Mon Sep 17 00:00:00 2001 From: olddonkey Date: Tue, 18 Aug 2026 22:59:13 -0700 Subject: [PATCH 003/114] fix(xai): address B2 pricing review --- .../260818_fastwire_b2_xai/evidence/README.md | 2 +- .../docs/reference/configuration/providers.md | 11 +-- gui/src/i18n/de.ts | 3 + gui/src/i18n/en.ts | 3 + gui/src/i18n/fr.ts | 3 + gui/src/i18n/ja.ts | 3 + gui/src/i18n/ko.ts | 3 + gui/src/i18n/ru.ts | 3 + gui/src/i18n/tr.ts | 3 + gui/src/i18n/zh-TW.ts | 3 + gui/src/i18n/zh.ts | 3 + gui/src/pages/Logs.tsx | 54 +++++++-------- gui/src/pages/logs-cost-format.ts | 69 +++++++++++++++++-- gui/tests/logs-cost-lower-bound.test.ts | 57 +++++++++++++-- src/usage/cost.ts | 8 ++- src/usage/expected-prices.ts | 3 + tests/usage-cost.test.ts | 47 ++++++++++++- 17 files changed, 228 insertions(+), 50 deletions(-) diff --git a/devlog/_plan/260818_fastwire_b2_xai/evidence/README.md b/devlog/_plan/260818_fastwire_b2_xai/evidence/README.md index 034ab80d71..0ae66d31f3 100644 --- a/devlog/_plan/260818_fastwire_b2_xai/evidence/README.md +++ b/devlog/_plan/260818_fastwire_b2_xai/evidence/README.md @@ -7,7 +7,7 @@ that exercise every branch of the new pricing path: | --- | --- | --- | | `req-standard` | no Fast requested | `~$0.0300` | | `req-priority` | response-confirmed priority, prompt under the long-context threshold | `~$0.0600` — exactly the documented 2x premium over the row above | -| `req-longctx-priority` | response-confirmed priority, prompt above 200k | `≥$0.8760` — the published long-context rate, marked a lower bound because xAI publishes no combined price | +| `req-longctx-priority` | response-confirmed priority, prompt at or above 200k | `≥$0.8760` — the published long-context rate, marked a lower bound because xAI publishes no combined price | The `≥` prefix is the visible change: a cost that is a known floor rather than an estimate now says so instead of rendering as `~$`. The detail drawer explains why diff --git a/docs-site/src/content/docs/reference/configuration/providers.md b/docs-site/src/content/docs/reference/configuration/providers.md index aa095c4eff..29eb441e3b 100644 --- a/docs-site/src/content/docs/reference/configuration/providers.md +++ b/docs-site/src/content/docs/reference/configuration/providers.md @@ -154,14 +154,15 @@ Explicit capability `false` and Responses caller-tier forwarding retain their ex ### xAI Priority Processing The built-in `xai` preset advertises and injects Fast only when its effective transport uses -`authMode: "key"`. It sends `service_tier: "priority"` to xAI's public Chat Completions or -Responses API. `ocx login xai` uses the separate Grok CLI subscription gateway, so OAuth remains -unclassified: its catalog rows do not advertise Fast and the proxy does not inject a tier. +`authMode: "key"`. API-key mode uses the key transport at `https://api.x.ai/v1` and sends +`service_tier: "priority"` to xAI's public Chat Completions or Responses API. `ocx login xai` +instead stores OAuth credentials for the separate Grok CLI subscription-gateway flow, so OAuth +remains unclassified: its catalog rows do not advertise Fast and the proxy does not inject a tier. xAI charges Priority Processing at 2× the standard token price for input, output, cached, and reasoning tokens; cache discounts are applied before the multiplier. Cost estimates use that premium -only when xAI echoes `service_tier: "priority"` (or when an adapter explicitly records an assumed -priority outcome). An echoed `default` is a downgrade and stays at the standard price. +only when xAI's response confirms `service_tier: "priority"`. A missing or unparsed response tier is +not confirmation, and an echoed `default` is a downgrade; all three stay at the standard price. For `grok-4.6`, the standard rate per 1M tokens is $2.00 input, $0.50 cached input, and $6.00 output. A prompt of at least 200,000 tokens reprices the whole request at $4.00 / $1.00 / $12.00. diff --git a/gui/src/i18n/de.ts b/gui/src/i18n/de.ts index cdc510443c..c7e4bafc85 100644 --- a/gui/src/i18n/de.ts +++ b/gui/src/i18n/de.ts @@ -657,6 +657,9 @@ export const de: Record = { "logs.col.tokens": "Tokens", "logs.col.tokPerSec": "tok/s", "logs.col.estimatedCost": "~$", + "logs.cost.approximate": "~{amount}", + "logs.cost.lowerBound": "≥{amount}", + "logs.cost.unavailable": "—", "logs.metric.tokPerSecTitle": "Ausgabe-Tokens pro Sekunde über die gesamte Anfragedauer", "logs.metric.estimatedCostTitle": "API-Listenpreis-Äquivalent, keine tatsächliche Belastung; bei fehlendem Preisabgleich nicht verfügbar", "usage.cost.total": "API-Listenpreis-Äquivalent (dieser Zeitraum)", diff --git a/gui/src/i18n/en.ts b/gui/src/i18n/en.ts index 2a80b4feb7..22b18ab4df 100644 --- a/gui/src/i18n/en.ts +++ b/gui/src/i18n/en.ts @@ -690,6 +690,9 @@ export const en = { "logs.col.tokens": "Tokens", "logs.col.tokPerSec": "tok/s", "logs.col.estimatedCost": "~$", + "logs.cost.approximate": "~{amount}", + "logs.cost.lowerBound": "≥{amount}", + "logs.cost.unavailable": "—", "logs.metric.tokPerSecTitle": "Output tokens per second over the full request duration", "logs.metric.estimatedCostTitle": "API list-price equivalent, not an actual charge; unmatched pricing is unavailable", "usage.cost.total": "API list-price equivalent (this range)", diff --git a/gui/src/i18n/fr.ts b/gui/src/i18n/fr.ts index ba7798d64f..1388137610 100644 --- a/gui/src/i18n/fr.ts +++ b/gui/src/i18n/fr.ts @@ -671,6 +671,9 @@ export const fr: Record = { "logs.col.tokens": "Jetons", "logs.col.tokPerSec": "jetons/s", "logs.col.estimatedCost": "~$", + "logs.cost.approximate": "~{amount}", + "logs.cost.lowerBound": "≥{amount}", + "logs.cost.unavailable": "—", "logs.metric.tokPerSecTitle": "Jetons de sortie par seconde sur toute la durée de la requête", "logs.metric.estimatedCostTitle": "Équivalent au tarif catalogue de l’API, et non montant réellement facturé ; aucun tarif n’est disponible en l’absence de correspondance", "usage.cost.total": "Équivalent au tarif catalogue de l’API (cette période)", diff --git a/gui/src/i18n/ja.ts b/gui/src/i18n/ja.ts index 88a4e47f6c..9ade561da5 100644 --- a/gui/src/i18n/ja.ts +++ b/gui/src/i18n/ja.ts @@ -633,6 +633,9 @@ export const ja: Record = { "logs.col.tokens": "トークン", "logs.col.tokPerSec": "tok/s", "logs.col.estimatedCost": "~$", + "logs.cost.approximate": "~{amount}", + "logs.cost.lowerBound": "≥{amount}", + "logs.cost.unavailable": "—", "logs.metric.tokPerSecTitle": "リクエスト全体の所要時間あたりの出力トークン数", "logs.metric.estimatedCostTitle": "API 定価相当額(実際の請求ではありません); 未対応の価格は利用できません", "usage.cost.total": "API 定価相当額(この期間)", diff --git a/gui/src/i18n/ko.ts b/gui/src/i18n/ko.ts index 14a3512c9d..38fea1b47e 100644 --- a/gui/src/i18n/ko.ts +++ b/gui/src/i18n/ko.ts @@ -676,6 +676,9 @@ export const ko: Record = { "logs.col.tokens": "토큰", "logs.col.tokPerSec": "tok/s", "logs.col.estimatedCost": "~$", + "logs.cost.approximate": "~{amount}", + "logs.cost.lowerBound": "≥{amount}", + "logs.cost.unavailable": "—", "logs.metric.tokPerSecTitle": "전체 요청 시간 기준 초당 출력 토큰", "logs.metric.estimatedCostTitle": "API 정가 환산치이며 실제 청구액이 아닙니다. 가격 미매칭은 표시하지 않습니다.", "usage.cost.total": "API 정가 환산치 (이 기간)", diff --git a/gui/src/i18n/ru.ts b/gui/src/i18n/ru.ts index 10243dbe2f..12bbe081f7 100644 --- a/gui/src/i18n/ru.ts +++ b/gui/src/i18n/ru.ts @@ -674,6 +674,9 @@ export const ru: Record = { "logs.col.tokens": "Токены", "logs.col.tokPerSec": "tok/s", "logs.col.estimatedCost": "~$", + "logs.cost.approximate": "~{amount}", + "logs.cost.lowerBound": "≥{amount}", + "logs.cost.unavailable": "—", "logs.metric.tokPerSecTitle": "Выходные токены в секунду за полную длительность запроса", "logs.metric.estimatedCostTitle": "Эквивалент стоимости по прайс-листу API, а не фактическое списание; если цену не удалось сопоставить, значение недоступно", "usage.cost.total": "Эквивалент стоимости по прайс-листу API (за этот период)", diff --git a/gui/src/i18n/tr.ts b/gui/src/i18n/tr.ts index b9c7705c14..a37107e91f 100644 --- a/gui/src/i18n/tr.ts +++ b/gui/src/i18n/tr.ts @@ -681,6 +681,9 @@ export const tr: Record = { "logs.col.tokens": "Jetonlar", "logs.col.tokPerSec": "jeton/sn", "logs.col.estimatedCost": "~$", + "logs.cost.approximate": "~{amount}", + "logs.cost.lowerBound": "≥{amount}", + "logs.cost.unavailable": "—", "logs.metric.tokPerSecTitle": "Çıktı jetonu / saniye", "logs.metric.estimatedCostTitle": "Tahmini API liste fiyatı", "usage.cost.total": "API liste fiyatı eşdeğeri", diff --git a/gui/src/i18n/zh-TW.ts b/gui/src/i18n/zh-TW.ts index 664d74f256..256d9828ee 100644 --- a/gui/src/i18n/zh-TW.ts +++ b/gui/src/i18n/zh-TW.ts @@ -527,6 +527,9 @@ export const zhTW: Record = { "logs.col.tokens": "Token 數", "logs.col.tokPerSec": "tok/s", "logs.col.estimatedCost": "~$", + "logs.cost.approximate": "~{amount}", + "logs.cost.lowerBound": "≥{amount}", + "logs.cost.unavailable": "—", "logs.metric.tokPerSecTitle": "按完整請求耗時計算的每秒輸出 token", "logs.metric.estimatedCostTitle": "按 API 標價估算,並非實際扣費;價格無法符合時不顯示", "usage.cost.total": "API 標價折算(當前範圍)", diff --git a/gui/src/i18n/zh.ts b/gui/src/i18n/zh.ts index 91eb89045f..7f58c0d103 100644 --- a/gui/src/i18n/zh.ts +++ b/gui/src/i18n/zh.ts @@ -669,6 +669,9 @@ export const zh: Record = { "logs.col.tokens": "Token 数", "logs.col.tokPerSec": "tok/s", "logs.col.estimatedCost": "~$", + "logs.cost.approximate": "~{amount}", + "logs.cost.lowerBound": "≥{amount}", + "logs.cost.unavailable": "—", "logs.metric.tokPerSecTitle": "按完整请求耗时计算的每秒输出 token", "logs.metric.estimatedCostTitle": "按 API 标价估算,并非实际扣费;价格无法匹配时不显示", "usage.cost.total": "API 标价折算(当前范围)", diff --git a/gui/src/pages/Logs.tsx b/gui/src/pages/Logs.tsx index afd722de2b..468805b301 100644 --- a/gui/src/pages/Logs.tsx +++ b/gui/src/pages/Logs.tsx @@ -15,7 +15,7 @@ import Debug from "./Debug"; import type { LogsTab } from "./logs-tab-keydown"; import { logsTabKeyDown, readTabFromHash, selectLogsTab } from "./logs-tab-keydown"; -import { formatEstimatedUsdTotal } from "./logs-cost-format"; +import { formatEstimatedUsdTotal, summarizeEstimatedCosts } from "./logs-cost-format"; import { modelTitle } from "./logs-model-title"; import { speedLabel } from "./logs-speed-label"; import { cacheSplit, isCursorUsageProvider, tokensTitle } from "./logs-token-title"; @@ -239,17 +239,17 @@ function formatTokPerSecond(result: TokPerSecondResult | undefined, localeTag?: return `${result.estimated ? "~" : ""}${value}`; } -function formatEstimatedUsd(result: CostResult | undefined, localeTag?: string): string { - if (!result || result.kind === "unavailable") return "\u2014"; +function formatEstimatedUsd(result: CostResult | undefined, localeTag: string | undefined, t: TFn): string { return formatEstimatedUsdTotal( - result.estimate.cost.total, - result.estimateReasons.includes("priority_lower_bound"), + result?.kind === "value" ? result.estimate.cost.total : undefined, + result?.kind === "value" && result.estimateReasons.includes("priority_lower_bound"), localeTag, + t, ); } -function formatEstimatedUsdValue(value: number, localeTag?: string, lowerBound = false): string { - return formatEstimatedUsdTotal(value, lowerBound, localeTag); +function formatEstimatedUsdValue(value: number, localeTag: string | undefined, t: TFn, lowerBound = false): string { + return formatEstimatedUsdTotal(value, lowerBound, localeTag, t); } /** Consecutive failed polls before a stale table is called out. Two seconds each, so ~6s. */ @@ -344,29 +344,16 @@ function summarizeFilteredLogs(entries: LogEntry[]): { requests: number; totalTokens: number; estimatedCostUsd: number; + priorityLowerBound: boolean; unpricedRequests: number; unmeteredRequests: number; } { let totalTokens = 0; - let estimatedCostUsd = 0; - let unpricedRequests = 0; - let unmeteredRequests = 0; for (const entry of entries) { const tokens = displayTokenTotal(entry); if (tokens !== undefined) totalTokens += tokens; - if (entry.usageStatus === "unsupported") { - unmeteredRequests += 1; - continue; - } - const cost = entry.displayMetrics?.cost; - const total = cost?.kind === "value" ? cost.estimate.cost.total : undefined; - if (total !== undefined && Number.isFinite(total) && total >= 0) { - estimatedCostUsd += total; - continue; - } - unpricedRequests += 1; } - return { requests: entries.length, totalTokens, estimatedCostUsd, unpricedRequests, unmeteredRequests }; + return { requests: entries.length, totalTokens, ...summarizeEstimatedCosts(entries) }; } export default function Logs({ apiBase }: { apiBase: string }) { @@ -611,7 +598,12 @@ export default function Logs({ apiBase }: { apiBase: string }) { {t("logs.conversation.totals", { requests: conversationTotals.requests, tokens: formatTokens(conversationTotals.totalTokens, localeTag ?? locale), - cost: formatEstimatedUsdValue(conversationTotals.estimatedCostUsd, localeTag), + cost: formatEstimatedUsdValue( + conversationTotals.estimatedCostUsd, + localeTag, + t, + conversationTotals.priorityLowerBound, + ), })} {" "} @@ -730,7 +722,7 @@ export default function Logs({ apiBase }: { apiBase: string }) { {formatTokPerSecond(log.displayMetrics?.tokPerSecond, localeTag)} - {formatEstimatedUsd(log.displayMetrics?.cost, localeTag)} + {formatEstimatedUsd(log.displayMetrics?.cost, localeTag, t)} @@ -955,11 +947,11 @@ function LogDetailDialog({ {cost?.kind === "value" ? ( <>

- {t("logs.detail.costTotal")}{formatEstimatedUsdValue(cost.estimate.cost.total, localeTag, cost.estimateReasons.includes("priority_lower_bound"))} - {t("logs.tokens.input")}{formatEstimatedUsdValue(cost.estimate.cost.input, localeTag, cost.estimateReasons.includes("priority_lower_bound"))} - {t("logs.tokens.cacheRead")}{formatEstimatedUsdValue(cost.estimate.cost.cacheRead, localeTag, cost.estimateReasons.includes("priority_lower_bound"))} - {t("logs.tokens.cacheWrite")}{formatEstimatedUsdValue(cost.estimate.cost.cacheWrite, localeTag, cost.estimateReasons.includes("priority_lower_bound"))} - {t("logs.tokens.output")}{formatEstimatedUsdValue(cost.estimate.cost.output, localeTag, cost.estimateReasons.includes("priority_lower_bound"))} + {t("logs.detail.costTotal")}{formatEstimatedUsdValue(cost.estimate.cost.total, localeTag, t, cost.estimateReasons.includes("priority_lower_bound"))} + {t("logs.tokens.input")}{formatEstimatedUsdValue(cost.estimate.cost.input, localeTag, t, cost.estimateReasons.includes("priority_lower_bound"))} + {t("logs.tokens.cacheRead")}{formatEstimatedUsdValue(cost.estimate.cost.cacheRead, localeTag, t, cost.estimateReasons.includes("priority_lower_bound"))} + {t("logs.tokens.cacheWrite")}{formatEstimatedUsdValue(cost.estimate.cost.cacheWrite, localeTag, t, cost.estimateReasons.includes("priority_lower_bound"))} + {t("logs.tokens.output")}{formatEstimatedUsdValue(cost.estimate.cost.output, localeTag, t, cost.estimateReasons.includes("priority_lower_bound"))} {cost.estimate.price && ( <> {t("logs.detail.matchedKey")} @@ -977,7 +969,7 @@ function LogDetailDialog({ ) : (
- {t("logs.detail.costTotal")}{"\u2014"} + {t("logs.detail.costTotal")}{formatEstimatedUsd(undefined, localeTag, t)} {t("logs.detail.unavailableReason")} {cost?.kind === "unavailable" ? t(metricReasonKey(cost.reason)) : t("logs.detail.reason.usage_missing")}
@@ -1032,7 +1024,7 @@ function LogDetailDialog({ {attempt.durationMs}ms {formatTokPerSecond(attempt.displayMetrics?.tokPerSecond, localeTag)} - {formatEstimatedUsd(attemptCost, localeTag)} + {formatEstimatedUsd(attemptCost, localeTag, t)} {reason} ); diff --git a/gui/src/pages/logs-cost-format.ts b/gui/src/pages/logs-cost-format.ts index 65ce2e1d47..656cc4fe60 100644 --- a/gui/src/pages/logs-cost-format.ts +++ b/gui/src/pages/logs-cost-format.ts @@ -1,11 +1,72 @@ +import type { TFn } from "../i18n/shared"; +import { cachedNumberFormat } from "../intl-formatters"; + export function formatEstimatedUsdTotal( totalUsd: number | undefined, lowerBound: boolean, - localeTag?: string, + localeTag: string | undefined, + t: TFn, ): string { - if (totalUsd === undefined || !Number.isFinite(totalUsd) || totalUsd < 0) return "\u2014"; - return `${lowerBound ? "≥$" : "~$"}${new Intl.NumberFormat(localeTag, { + if (totalUsd === undefined || !Number.isFinite(totalUsd) || totalUsd < 0) { + return t("logs.cost.unavailable"); + } + const amount = cachedNumberFormat(localeTag, { + style: "currency", + currency: "USD", minimumFractionDigits: 4, maximumFractionDigits: 4, - }).format(totalUsd)}`; + }).format(totalUsd); + return t(lowerBound ? "logs.cost.lowerBound" : "logs.cost.approximate", { amount }); +} + +export interface LogCostSummaryEntry { + usageStatus?: string; + displayMetrics?: { + cost?: + | { + kind: "value"; + estimate: { cost: { total: number } }; + estimateReasons: readonly string[]; + } + | { kind: "unavailable" }; + }; +} + +export interface EstimatedCostSummary { + estimatedCostUsd: number; + priorityLowerBound: boolean; + unpricedRequests: number; + unmeteredRequests: number; +} + +/** Sum valid displayed costs without upgrading a mixed estimate into a known lower bound. */ +export function summarizeEstimatedCosts(entries: readonly LogCostSummaryEntry[]): EstimatedCostSummary { + let estimatedCostUsd = 0; + let pricedEstimates = 0; + let everyPricedEstimateIsLowerBound = true; + let unpricedRequests = 0; + let unmeteredRequests = 0; + for (const entry of entries) { + if (entry.usageStatus === "unsupported") { + unmeteredRequests += 1; + continue; + } + const cost = entry.displayMetrics?.cost; + if (cost?.kind === "value") { + const total = cost.estimate.cost.total; + if (Number.isFinite(total) && total >= 0) { + estimatedCostUsd += total; + pricedEstimates += 1; + everyPricedEstimateIsLowerBound &&= cost.estimateReasons.includes("priority_lower_bound"); + continue; + } + } + unpricedRequests += 1; + } + return { + estimatedCostUsd, + priorityLowerBound: pricedEstimates > 0 && everyPricedEstimateIsLowerBound, + unpricedRequests, + unmeteredRequests, + }; } diff --git a/gui/tests/logs-cost-lower-bound.test.ts b/gui/tests/logs-cost-lower-bound.test.ts index eddb95039e..c0bf527f4c 100644 --- a/gui/tests/logs-cost-lower-bound.test.ts +++ b/gui/tests/logs-cost-lower-bound.test.ts @@ -1,10 +1,59 @@ -import { expect, test } from "bun:test"; -import { formatEstimatedUsdTotal } from "../src/pages/logs-cost-format"; +import { describe, expect, test } from "bun:test"; +import { DICTS, interpolate, type Locale, type TFn } from "../src/i18n/shared"; +import { + formatEstimatedUsdTotal, + summarizeEstimatedCosts, +} from "../src/pages/logs-cost-format"; + +function translator(locale: Locale): TFn { + return (key, vars) => interpolate(DICTS[locale][key], vars); +} test("ordinary dashboard costs retain the estimate marker", () => { - expect(formatEstimatedUsdTotal(0.77, false, "en-US")).toBe("~$0.7700"); + expect(formatEstimatedUsdTotal(0.77, false, "en-US", translator("en"))).toBe("~$0.7700"); }); test("priority long-context lower bounds render with a greater-than-or-equal marker", () => { - expect(formatEstimatedUsdTotal(0.77, true, "en-US")).toBe("≥$0.7700"); + expect(formatEstimatedUsdTotal(0.77, true, "en-US", translator("en"))).toBe("≥$0.7700"); +}); + +test("USD placement and separators follow a non-English locale", () => { + expect(formatEstimatedUsdTotal(0.77, false, "de-DE", translator("de"))).toBe("~0,7700\u00a0$"); + expect(formatEstimatedUsdTotal(undefined, false, "de-DE", translator("de"))).toBe("—"); +}); + +describe("conversation cost lower-bound aggregation", () => { + const priced = (total: number, lowerBound: boolean) => ({ + usageStatus: "reported", + displayMetrics: { + cost: { + kind: "value" as const, + estimate: { cost: { total } }, + estimateReasons: lowerBound ? ["priority_lower_bound"] : [], + }, + }, + }); + + test("marks a total only when every included priced estimate is a lower bound", () => { + expect(summarizeEstimatedCosts([priced(0.77, true), priced(1.23, true)])).toMatchObject({ + estimatedCostUsd: 2, + priorityLowerBound: true, + }); + expect(summarizeEstimatedCosts([priced(0.77, true), priced(1.23, false)])).toMatchObject({ + estimatedCostUsd: 2, + priorityLowerBound: false, + }); + }); + + test("preserves unpriced and unsupported exclusions without minting a lower bound", () => { + expect(summarizeEstimatedCosts([ + { usageStatus: "reported", displayMetrics: { cost: { kind: "unavailable" } } }, + { usageStatus: "unsupported" }, + ])).toEqual({ + estimatedCostUsd: 0, + priorityLowerBound: false, + unpricedRequests: 1, + unmeteredRequests: 1, + }); + }); }); diff --git a/src/usage/cost.ts b/src/usage/cost.ts index b574723902..3af42a3c8e 100644 --- a/src/usage/cost.ts +++ b/src/usage/cost.ts @@ -451,7 +451,9 @@ function applyPriorityMultiplier( ): [Cost4, number] { if (tierScalar(serviceTier) !== "priority") return [cost4, 1]; const base = baseProviderLabel(provider); - const multiplier = findPriorityPricingRule(base, modelId)?.multiplier ?? 1; + const rule = findPriorityPricingRule(base, modelId); + if (rule?.requiresResponseConfirmation && !isConfirmedFast(serviceTier)) return [cost4, 1]; + const multiplier = rule?.multiplier ?? 1; if (multiplier === 1) return [cost4, 1]; return [{ input: cost4.input * multiplier, @@ -542,7 +544,9 @@ export function estimateComboCost( ? { priorityMultiplier: estimates.find(est => est.priorityMultiplier)?.priorityMultiplier } : {}), ...(estimates.some(est => est.contextTier) ? { contextTier: "long" as const } : {}), - ...(estimates.some(est => est.priorityLowerBound) ? { priorityLowerBound: true as const } : {}), + ...(estimates.every(est => est.priorityLowerBound === true) + ? { priorityLowerBound: true as const } + : {}), }; } diff --git a/src/usage/expected-prices.ts b/src/usage/expected-prices.ts index d0cb90d139..af94b8b262 100644 --- a/src/usage/expected-prices.ts +++ b/src/usage/expected-prices.ts @@ -242,6 +242,8 @@ export interface PriorityPricingRule { provider: string; modelId: string; multiplier: number; + /** Apply the premium only after the upstream response confirms this tier. */ + requiresResponseConfirmation?: true; source: string; verifiedAt: string; } @@ -267,6 +269,7 @@ export const PRIORITY_PRICING_RULES: readonly PriorityPricingRule[] = [ provider: "xai", modelId, multiplier: 2, + requiresResponseConfirmation: true, source: XAI_PRIORITY_PRICING, verifiedAt: "2026-08-18", })), diff --git a/tests/usage-cost.test.ts b/tests/usage-cost.test.ts index a7f58d4d88..362868f4f2 100644 --- a/tests/usage-cost.test.ts +++ b/tests/usage-cost.test.ts @@ -609,6 +609,7 @@ describe("xAI Priority Processing pricing", () => { const xaiRules = PRIORITY_PRICING_RULES.filter(rule => rule.provider === "xai"); expect(xaiRules.map(rule => rule.modelId)).toEqual(["grok-4.5", "grok-4.6"]); expect(xaiRules.every(rule => rule.multiplier === 2)).toBe(true); + expect(xaiRules.every(rule => rule.requiresResponseConfirmation === true)).toBe(true); expect(xaiRules.every(rule => rule.source === "https://docs.x.ai/developers/advanced-api-usage/priority-processing")).toBe(true); expect(findPriorityPricingRule("xai", "grok-4.6")?.multiplier).toBe(2); expect(findPriorityPricingRule("openrouter", "grok-4.6")).toBeUndefined(); @@ -645,7 +646,7 @@ describe("xAI Priority Processing pricing", () => { expect(confirmed.priorityMultiplier).toBe(2); }); - test("an assumed priority outcome uses the same 2x premium", () => { + test("an assumed priority outcome stays at the standard price", () => { const assumedOutcome = outcome(); const assumed = estimate(assumedOutcome); expect(assumedOutcome).toMatchObject({ @@ -653,8 +654,26 @@ describe("xAI Priority Processing pricing", () => { fastOutcome: "applied", confirmation: "assumed", }); - expect(assumed.cost.total).toBeCloseTo(0.46, 9); - expect(assumed.priorityMultiplier).toBe(2); + expect(assumed.cost.total).toBeCloseTo(0.23, 9); + expect(assumed.priorityMultiplier).toBeUndefined(); + }); + + test("missing provenance and a requested tier do not prove the xAI premium", () => { + for (const serviceTier of [ + "priority", + { requestedServiceTier: "priority" }, + { configuredServiceTier: "priority" }, + ] as const) { + const unconfirmed = estimateRequestCost({ + provider: "xai", + model: "grok-4.6", + usageStatus: "reported", + usage, + serviceTier, + })!; + expect(unconfirmed.cost.total).toBeCloseTo(0.23, 9); + expect(unconfirmed.priorityMultiplier).toBeUndefined(); + } }); test("an echoed default records a downgrade and bills the standard price", () => { @@ -687,6 +706,28 @@ describe("xAI Priority Processing pricing", () => { }); expect(long.cost.total).toBeCloseTo(0.77, 9); }); + + test("a combo is a lower bound only when every priced attempt is a lower bound", () => { + const confirmed = outcome("priority"); + const lowerBoundAttempt = { + ordinal: 1, + provider: "xai", + model: "grok-4.6", + usageStatus: "reported" as const, + usage: { inputTokens: 200_000, outputTokens: 10_000 }, + tierOutcome: confirmed, + }; + const ordinaryAttempt = { + ordinal: 2, + provider: "xai", + model: "grok-4.6", + usageStatus: "reported" as const, + usage, + }; + + expect(estimateComboCost([lowerBoundAttempt, { ...lowerBoundAttempt, ordinal: 2 }])?.priorityLowerBound).toBe(true); + expect(estimateComboCost([lowerBoundAttempt, ordinaryAttempt])?.priorityLowerBound).toBeUndefined(); + }); }); describe("long-context pricing tiers (#908)", () => { From d887a4f2d5b299b2846d09d12aa7435d1065238f Mon Sep 17 00:00:00 2001 From: olddonkey Date: Tue, 18 Aug 2026 23:43:41 -0700 Subject: [PATCH 004/114] fix(gui): translate estimated cost labels --- gui/src/i18n/de.ts | 6 +++--- gui/src/i18n/fr.ts | 6 +++--- gui/src/i18n/ja.ts | 6 +++--- gui/src/i18n/ko.ts | 6 +++--- gui/src/i18n/ru.ts | 6 +++--- gui/src/i18n/tr.ts | 6 +++--- gui/src/i18n/zh-TW.ts | 6 +++--- gui/src/i18n/zh.ts | 6 +++--- gui/tests/logs-cost-lower-bound.test.ts | 4 ++-- 9 files changed, 26 insertions(+), 26 deletions(-) diff --git a/gui/src/i18n/de.ts b/gui/src/i18n/de.ts index c7e4bafc85..8dd5ff7b58 100644 --- a/gui/src/i18n/de.ts +++ b/gui/src/i18n/de.ts @@ -657,9 +657,9 @@ export const de: Record = { "logs.col.tokens": "Tokens", "logs.col.tokPerSec": "tok/s", "logs.col.estimatedCost": "~$", - "logs.cost.approximate": "~{amount}", - "logs.cost.lowerBound": "≥{amount}", - "logs.cost.unavailable": "—", + "logs.cost.approximate": "ca. {amount}", + "logs.cost.lowerBound": "mind. {amount}", + "logs.cost.unavailable": "nicht verfügbar", "logs.metric.tokPerSecTitle": "Ausgabe-Tokens pro Sekunde über die gesamte Anfragedauer", "logs.metric.estimatedCostTitle": "API-Listenpreis-Äquivalent, keine tatsächliche Belastung; bei fehlendem Preisabgleich nicht verfügbar", "usage.cost.total": "API-Listenpreis-Äquivalent (dieser Zeitraum)", diff --git a/gui/src/i18n/fr.ts b/gui/src/i18n/fr.ts index 1388137610..e99e1d2abd 100644 --- a/gui/src/i18n/fr.ts +++ b/gui/src/i18n/fr.ts @@ -671,9 +671,9 @@ export const fr: Record = { "logs.col.tokens": "Jetons", "logs.col.tokPerSec": "jetons/s", "logs.col.estimatedCost": "~$", - "logs.cost.approximate": "~{amount}", - "logs.cost.lowerBound": "≥{amount}", - "logs.cost.unavailable": "—", + "logs.cost.approximate": "env. {amount}", + "logs.cost.lowerBound": "au moins {amount}", + "logs.cost.unavailable": "indisponible", "logs.metric.tokPerSecTitle": "Jetons de sortie par seconde sur toute la durée de la requête", "logs.metric.estimatedCostTitle": "Équivalent au tarif catalogue de l’API, et non montant réellement facturé ; aucun tarif n’est disponible en l’absence de correspondance", "usage.cost.total": "Équivalent au tarif catalogue de l’API (cette période)", diff --git a/gui/src/i18n/ja.ts b/gui/src/i18n/ja.ts index 9ade561da5..8b07c757a9 100644 --- a/gui/src/i18n/ja.ts +++ b/gui/src/i18n/ja.ts @@ -633,9 +633,9 @@ export const ja: Record = { "logs.col.tokens": "トークン", "logs.col.tokPerSec": "tok/s", "logs.col.estimatedCost": "~$", - "logs.cost.approximate": "~{amount}", - "logs.cost.lowerBound": "≥{amount}", - "logs.cost.unavailable": "—", + "logs.cost.approximate": "約{amount}", + "logs.cost.lowerBound": "最低{amount}", + "logs.cost.unavailable": "利用不可", "logs.metric.tokPerSecTitle": "リクエスト全体の所要時間あたりの出力トークン数", "logs.metric.estimatedCostTitle": "API 定価相当額(実際の請求ではありません); 未対応の価格は利用できません", "usage.cost.total": "API 定価相当額(この期間)", diff --git a/gui/src/i18n/ko.ts b/gui/src/i18n/ko.ts index 38fea1b47e..9f84f7c9e0 100644 --- a/gui/src/i18n/ko.ts +++ b/gui/src/i18n/ko.ts @@ -676,9 +676,9 @@ export const ko: Record = { "logs.col.tokens": "토큰", "logs.col.tokPerSec": "tok/s", "logs.col.estimatedCost": "~$", - "logs.cost.approximate": "~{amount}", - "logs.cost.lowerBound": "≥{amount}", - "logs.cost.unavailable": "—", + "logs.cost.approximate": "약 {amount}", + "logs.cost.lowerBound": "최소 {amount}", + "logs.cost.unavailable": "사용 불가", "logs.metric.tokPerSecTitle": "전체 요청 시간 기준 초당 출력 토큰", "logs.metric.estimatedCostTitle": "API 정가 환산치이며 실제 청구액이 아닙니다. 가격 미매칭은 표시하지 않습니다.", "usage.cost.total": "API 정가 환산치 (이 기간)", diff --git a/gui/src/i18n/ru.ts b/gui/src/i18n/ru.ts index 12bbe081f7..1ef1a7b10c 100644 --- a/gui/src/i18n/ru.ts +++ b/gui/src/i18n/ru.ts @@ -674,9 +674,9 @@ export const ru: Record = { "logs.col.tokens": "Токены", "logs.col.tokPerSec": "tok/s", "logs.col.estimatedCost": "~$", - "logs.cost.approximate": "~{amount}", - "logs.cost.lowerBound": "≥{amount}", - "logs.cost.unavailable": "—", + "logs.cost.approximate": "около {amount}", + "logs.cost.lowerBound": "не менее {amount}", + "logs.cost.unavailable": "недоступно", "logs.metric.tokPerSecTitle": "Выходные токены в секунду за полную длительность запроса", "logs.metric.estimatedCostTitle": "Эквивалент стоимости по прайс-листу API, а не фактическое списание; если цену не удалось сопоставить, значение недоступно", "usage.cost.total": "Эквивалент стоимости по прайс-листу API (за этот период)", diff --git a/gui/src/i18n/tr.ts b/gui/src/i18n/tr.ts index a37107e91f..ce94f89e61 100644 --- a/gui/src/i18n/tr.ts +++ b/gui/src/i18n/tr.ts @@ -681,9 +681,9 @@ export const tr: Record = { "logs.col.tokens": "Jetonlar", "logs.col.tokPerSec": "jeton/sn", "logs.col.estimatedCost": "~$", - "logs.cost.approximate": "~{amount}", - "logs.cost.lowerBound": "≥{amount}", - "logs.cost.unavailable": "—", + "logs.cost.approximate": "yaklaşık {amount}", + "logs.cost.lowerBound": "en az {amount}", + "logs.cost.unavailable": "kullanılamıyor", "logs.metric.tokPerSecTitle": "Çıktı jetonu / saniye", "logs.metric.estimatedCostTitle": "Tahmini API liste fiyatı", "usage.cost.total": "API liste fiyatı eşdeğeri", diff --git a/gui/src/i18n/zh-TW.ts b/gui/src/i18n/zh-TW.ts index 256d9828ee..864818bbda 100644 --- a/gui/src/i18n/zh-TW.ts +++ b/gui/src/i18n/zh-TW.ts @@ -527,9 +527,9 @@ export const zhTW: Record = { "logs.col.tokens": "Token 數", "logs.col.tokPerSec": "tok/s", "logs.col.estimatedCost": "~$", - "logs.cost.approximate": "~{amount}", - "logs.cost.lowerBound": "≥{amount}", - "logs.cost.unavailable": "—", + "logs.cost.approximate": "約 {amount}", + "logs.cost.lowerBound": "至少 {amount}", + "logs.cost.unavailable": "無法估算", "logs.metric.tokPerSecTitle": "按完整請求耗時計算的每秒輸出 token", "logs.metric.estimatedCostTitle": "按 API 標價估算,並非實際扣費;價格無法符合時不顯示", "usage.cost.total": "API 標價折算(當前範圍)", diff --git a/gui/src/i18n/zh.ts b/gui/src/i18n/zh.ts index 7f58c0d103..15e09582b1 100644 --- a/gui/src/i18n/zh.ts +++ b/gui/src/i18n/zh.ts @@ -669,9 +669,9 @@ export const zh: Record = { "logs.col.tokens": "Token 数", "logs.col.tokPerSec": "tok/s", "logs.col.estimatedCost": "~$", - "logs.cost.approximate": "~{amount}", - "logs.cost.lowerBound": "≥{amount}", - "logs.cost.unavailable": "—", + "logs.cost.approximate": "约 {amount}", + "logs.cost.lowerBound": "至少 {amount}", + "logs.cost.unavailable": "无法估算", "logs.metric.tokPerSecTitle": "按完整请求耗时计算的每秒输出 token", "logs.metric.estimatedCostTitle": "按 API 标价估算,并非实际扣费;价格无法匹配时不显示", "usage.cost.total": "API 标价折算(当前范围)", diff --git a/gui/tests/logs-cost-lower-bound.test.ts b/gui/tests/logs-cost-lower-bound.test.ts index c0bf527f4c..44cc160e74 100644 --- a/gui/tests/logs-cost-lower-bound.test.ts +++ b/gui/tests/logs-cost-lower-bound.test.ts @@ -18,8 +18,8 @@ test("priority long-context lower bounds render with a greater-than-or-equal mar }); test("USD placement and separators follow a non-English locale", () => { - expect(formatEstimatedUsdTotal(0.77, false, "de-DE", translator("de"))).toBe("~0,7700\u00a0$"); - expect(formatEstimatedUsdTotal(undefined, false, "de-DE", translator("de"))).toBe("—"); + expect(formatEstimatedUsdTotal(0.77, false, "de-DE", translator("de"))).toBe("ca. 0,7700\u00a0$"); + expect(formatEstimatedUsdTotal(undefined, false, "de-DE", translator("de"))).toBe("nicht verfügbar"); }); describe("conversation cost lower-bound aggregation", () => { From c13981b5a029d8ee66d662829ee85d2b92e74976 Mon Sep 17 00:00:00 2001 From: olddonkey Date: Tue, 18 Aug 2026 23:52:14 -0700 Subject: [PATCH 005/114] docs(xai): clarify API key transport --- .../src/content/docs/reference/configuration/providers.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs-site/src/content/docs/reference/configuration/providers.md b/docs-site/src/content/docs/reference/configuration/providers.md index 29eb441e3b..181820d24b 100644 --- a/docs-site/src/content/docs/reference/configuration/providers.md +++ b/docs-site/src/content/docs/reference/configuration/providers.md @@ -154,8 +154,8 @@ Explicit capability `false` and Responses caller-tier forwarding retain their ex ### xAI Priority Processing The built-in `xai` preset advertises and injects Fast only when its effective transport uses -`authMode: "key"`. API-key mode uses the key transport at `https://api.x.ai/v1` and sends -`service_tier: "priority"` to xAI's public Chat Completions or Responses API. `ocx login xai` +`authMode: "key"`. API-key mode targets `https://api.x.ai/v1` through the `openai-chat` adapter and +sends `service_tier: "priority"` through Chat Completions. `ocx login xai` instead stores OAuth credentials for the separate Grok CLI subscription-gateway flow, so OAuth remains unclassified: its catalog rows do not advertise Fast and the proxy does not inject a tier. From 33e1c3e08d2f3145e5b92164ad23f3cd0743f8c3 Mon Sep 17 00:00:00 2001 From: olddonkey Date: Wed, 19 Aug 2026 00:01:31 -0700 Subject: [PATCH 006/114] docs(xai): separate OAuth gateway rows --- docs-site/src/content/docs/guides/providers.md | 2 +- docs-site/src/content/docs/ja/guides/providers.md | 2 +- docs-site/src/content/docs/ko/guides/providers.md | 2 +- docs-site/src/content/docs/ru/guides/providers.md | 2 +- docs-site/src/content/docs/zh-cn/guides/providers.md | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs-site/src/content/docs/guides/providers.md b/docs-site/src/content/docs/guides/providers.md index e1451dcfbd..fd56b2ad47 100644 --- a/docs-site/src/content/docs/guides/providers.md +++ b/docs-site/src/content/docs/guides/providers.md @@ -110,7 +110,7 @@ ocx logout | Provider | Adapter | Base URL | Notes | | --- | --- | --- | --- | -| `xai` | `openai-chat` | `https://api.x.ai/v1` | Live-first Grok catalog; `grok-4.5` is the fallback default. | +| `xai` | `openai-chat` | `https://cli-chat-proxy.grok.com/v1` | OAuth uses the separate Grok CLI subscription gateway. The API-key override uses `https://api.x.ai/v1` and may inject Priority Processing. Live-first Grok catalog; `grok-4.5` is the fallback default. | | `anthropic` | `anthropic` | `https://api.anthropic.com` | Claude models; live model list fetched from `/v1/models`. | | `kimi` | `openai-chat` | `https://api.kimi.com/coding/v1` | Kimi K2.7/K2.6/K2.5 coding models. | | `nous` | `openai-chat` | `https://inference-api.nousresearch.com/v1` | Nous Research subscription gateway (same backend Hermes Agent uses). Device-grant login against `portal.nousresearch.com`; the access token is the per-request inference JWT. Mixed paid + `:free` model catalog (`tencent/hy3:free`, `stepfun/step-3.7-flash:free`, ...) discovered live from the signed-in account. Refresh tokens are single-use and rotated on every refresh. | diff --git a/docs-site/src/content/docs/ja/guides/providers.md b/docs-site/src/content/docs/ja/guides/providers.md index 81a19e5e5b..f99bf35aec 100644 --- a/docs-site/src/content/docs/ja/guides/providers.md +++ b/docs-site/src/content/docs/ja/guides/providers.md @@ -105,7 +105,7 @@ ocx logout | プロバイダー | アダプター | ベース URL | 備考 | | --- | --- | --- | --- | -| `xai` | `openai-chat` | `https://api.x.ai/v1` | ライブ一覧を優先し、フォールバックのデフォルトモデルは `grok-4.5`。 | +| `xai` | `openai-chat` | `https://cli-chat-proxy.grok.com/v1` | OAuth は独立した Grok CLI サブスクリプションゲートウェイを使用します。API キーのオーバーライドは `https://api.x.ai/v1` を使用し、Priority Processing を注入する場合があります。ライブ一覧を優先し、フォールバックのデフォルトモデルは `grok-4.5`。 | | `anthropic` | `anthropic` | `https://api.anthropic.com` | Claude モデル; ライブモデル一覧は `/v1/models` から取得。 | | `kimi` | `openai-chat` | `https://api.kimi.com/coding/v1` | Kimi K2.7/K2.6/K2.5 コーディングモデル。 | | `nous` | `openai-chat` | `https://inference-api.nousresearch.com/v1` | Nous Research サブスクリプションゲートウェイ(Hermes Agent と同じバックエンド)。`portal.nousresearch.com` へのデバイスグラントログイン; access トークンはリクエストごとの inference JWT。有料 + `:free` モデルの混在カタログ(`tencent/hy3:free`、`stepfun/step-3.7-flash:free` など)はサインイン中のアカウントからライブ探索されます。Refresh トークンは単回使用で、更新のたびにローテーションされます。 | diff --git a/docs-site/src/content/docs/ko/guides/providers.md b/docs-site/src/content/docs/ko/guides/providers.md index 4f57dab7cc..b24e17f3fc 100644 --- a/docs-site/src/content/docs/ko/guides/providers.md +++ b/docs-site/src/content/docs/ko/guides/providers.md @@ -104,7 +104,7 @@ ocx logout | 프로바이더 | 어댑터 | 베이스 URL | 비고 | | --- | --- | --- | --- | -| `xai` | `openai-chat` | `https://api.x.ai/v1` | 실시간 목록을 우선 사용하며, 폴백 기본 모델은 `grok-4.5`입니다. | +| `xai` | `openai-chat` | `https://cli-chat-proxy.grok.com/v1` | OAuth는 별도의 Grok CLI 구독 게이트웨이를 사용합니다. API 키 오버라이드는 `https://api.x.ai/v1`을 사용하며 Priority Processing을 주입할 수 있습니다. 실시간 목록을 우선 사용하며, 폴백 기본 모델은 `grok-4.5`입니다. | | `anthropic` | `anthropic` | `https://api.anthropic.com` | Claude 모델; 실시간 모델 목록은 `/v1/models`에서 가져옵니다. | | `kimi` | `openai-chat` | `https://api.kimi.com/coding/v1` | Kimi K2.7/K2.6/K2.5 코딩 모델. | | `nous` | `openai-chat` | `https://inference-api.nousresearch.com/v1` | Nous Research 구독 게이트웨이(Hermes Agent와 동일한 백엔드). `portal.nousresearch.com`에 대한 디바이스 그랜트 로그인; access 토큰은 요청별 inference JWT. 유료 + `:free` 모델 혼합 카탈로그(`tencent/hy3:free`, `stepfun/step-3.7-flash:free` 등)는 로그인한 계정에서 실시간으로 발견됩니다. Refresh 토큰은 단회 사용이며, 갱신할 때마다 회전됩니다. | diff --git a/docs-site/src/content/docs/ru/guides/providers.md b/docs-site/src/content/docs/ru/guides/providers.md index 1966d9db63..1dfe171a58 100644 --- a/docs-site/src/content/docs/ru/guides/providers.md +++ b/docs-site/src/content/docs/ru/guides/providers.md @@ -114,7 +114,7 @@ ocx logout | Провайдер | Адаптер | Базовый URL | Примечания | | --- | --- | --- | --- | -| `xai` | `openai-chat` | `https://api.x.ai/v1` | Каталог Grok загружается в реальном времени; фолбэк по умолчанию — `grok-4.5`. | +| `xai` | `openai-chat` | `https://cli-chat-proxy.grok.com/v1` | OAuth использует отдельный шлюз подписки Grok CLI. Переопределение с API-ключом использует `https://api.x.ai/v1` и может добавлять Priority Processing. Каталог Grok загружается в реальном времени; фолбэк по умолчанию — `grok-4.5`. | | `anthropic` | `anthropic` | `https://api.anthropic.com` | Модели Claude; актуальный список моделей загружается из `/v1/models`. | | `kimi` | `openai-chat` | `https://api.kimi.com/coding/v1` | Модели Kimi K2.7/K2.6/K2.5 для кодинга. | | `nous` | `openai-chat` | `https://inference-api.nousresearch.com/v1` | Шлюз подписки Nous Research (тот же бэкенд, что использует Hermes Agent). Вход по device grant против `portal.nousresearch.com`; access-токен — это JWT для каждого запроса к inference. Смешанный каталог платных + `:free` моделей (`tencent/hy3:free`, `stepfun/step-3.7-flash:free`, …) обнаруживается вживую по авторизованному аккаунту. Refresh-токены одноразовые и ротируются при каждом обновлении. | diff --git a/docs-site/src/content/docs/zh-cn/guides/providers.md b/docs-site/src/content/docs/zh-cn/guides/providers.md index 4e924458ee..a73676e496 100644 --- a/docs-site/src/content/docs/zh-cn/guides/providers.md +++ b/docs-site/src/content/docs/zh-cn/guides/providers.md @@ -95,7 +95,7 @@ ocx logout | 提供商 | Adapter | 基础 URL | 备注 | | --- | --- | --- | --- | -| `xai` | `openai-chat` | `https://api.x.ai/v1` | 优先使用实时 Grok 目录;回退默认模型为 `grok-4.5`。 | +| `xai` | `openai-chat` | `https://cli-chat-proxy.grok.com/v1` | OAuth 使用独立的 Grok CLI 订阅网关。API 密钥覆盖模式使用 `https://api.x.ai/v1`,并可能注入 Priority Processing。优先使用实时 Grok 目录;回退默认模型为 `grok-4.5`。 | | `anthropic` | `anthropic` | `https://api.anthropic.com` | Claude 模型;实时模型列表从 `/v1/models` 获取。 | | `kimi` | `openai-chat` | `https://api.kimi.com/coding/v1` | Kimi K2.7/K2.6/K2.5 编程模型。 | | `nous` | `openai-chat` | `https://inference-api.nousresearch.com/v1` | Nous Research 订阅网关(与 Hermes Agent 使用同一后端)。通过设备授权登录 `portal.nousresearch.com`;access 令牌是每个请求的 inference JWT。付费 + `:free` 模型混合目录(`tencent/hy3:free`、`stepfun/step-3.7-flash:free` 等)会从已登录账户实时发现。Refresh 令牌是单次使用,每次刷新都会轮换。 | From d4023aedda625b81ab234bfecfa396dbd6a092e8 Mon Sep 17 00:00:00 2001 From: olddonkey Date: Fri, 21 Aug 2026 06:28:10 +0000 Subject: [PATCH 007/114] docs(xai): separate the OAuth gateway row in the remaining locales 33e1c3e08 split the OAuth subscription gateway from the API-key endpoint in the provider table for en, ja, ko, ru, and zh-cn, but zh-tw, fr, and tr kept https://api.x.ai/v1 as the base URL. OAuth routes through the Grok CLI gateway at https://cli-chat-proxy.grok.com/v1; only the API-key override targets api.x.ai, and only that transport injects Priority Processing. Co-Authored-By: Claude Claude-Session: https://claude.ai/code/session_017zpLCh4eEms6un3VjapRgL --- docs-site/src/content/docs/fr/guides/providers.md | 2 +- docs-site/src/content/docs/tr/guides/providers.md | 2 +- docs-site/src/content/docs/zh-tw/guides/providers.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs-site/src/content/docs/fr/guides/providers.md b/docs-site/src/content/docs/fr/guides/providers.md index 59381edd60..40ee8021f1 100644 --- a/docs-site/src/content/docs/fr/guides/providers.md +++ b/docs-site/src/content/docs/fr/guides/providers.md @@ -115,7 +115,7 @@ ocx logout | Fournisseur | Adaptateur | URL de base | Remarques | | --- | --- | --- | --- | -| `xai` | `openai-chat` | `https://api.x.ai/v1` | Catalogue Grok découvert en direct en priorité ; `grok-4.5` est le modèle de repli par défaut. | +| `xai` | `openai-chat` | `https://cli-chat-proxy.grok.com/v1` | OAuth utilise la passerelle d'abonnement Grok CLI distincte. Le remplacement par clé API utilise `https://api.x.ai/v1` et peut injecter Priority Processing. Catalogue Grok découvert en direct en priorité ; `grok-4.5` est le modèle de repli par défaut. | | `anthropic` | `anthropic` | `https://api.anthropic.com` | Modèles Claude ; liste des modèles récupérée en direct depuis `/v1/models`. | | `kimi` | `openai-chat` | `https://api.kimi.com/coding/v1` | Modèles de programmation Kimi K2.7/K2.6/K2.5. | | `nous` | `openai-chat` | `https://inference-api.nousresearch.com/v1` | Passerelle d'abonnement Nous Research (le même service en amont que celui utilisé par Hermes Agent). Connexion par autorisation d'appareil auprès de `portal.nousresearch.com` ; le jeton d'accès est le JWT d'inférence envoyé avec chaque requête. Le catalogue mixte de modèles payants et `:free` (`tencent/hy3:free`, `stepfun/step-3.7-flash:free`, ...) est découvert en direct pour le compte connecté. Les jetons d'actualisation sont à usage unique et renouvelés à chaque actualisation. | diff --git a/docs-site/src/content/docs/tr/guides/providers.md b/docs-site/src/content/docs/tr/guides/providers.md index ee153a0780..15e2ab3cf4 100644 --- a/docs-site/src/content/docs/tr/guides/providers.md +++ b/docs-site/src/content/docs/tr/guides/providers.md @@ -129,7 +129,7 @@ ocx logout | Sağlayıcı | Adaptör | Temel URL | Notlar | | --- | --- | --- | --- | -| `xai` | `openai-chat` | `https://api.x.ai/v1` | Canlı öncelikli Grok kataloğu; `grok-4.5` geri dönüş varsayılanıdır. | +| `xai` | `openai-chat` | `https://cli-chat-proxy.grok.com/v1` | OAuth ayrı Grok CLI abonelik ağ geçidini kullanır. API anahtarı geçersiz kılması `https://api.x.ai/v1` kullanır ve Priority Processing ekleyebilir. Canlı öncelikli Grok kataloğu; `grok-4.5` geri dönüş varsayılanıdır. | | `anthropic` | `anthropic` | `https://api.anthropic.com` | Claude modelleri; canlı model listesi `/v1/models` üzerinden getirilir. | | `kimi` | `openai-chat` | `https://api.kimi.com/coding/v1` | Kimi K2.7/K2.6/K2.5 kodlama modelleri. | | `nous` | `openai-chat` | `https://inference-api.nousresearch.com/v1` | Nous Research abonelik ağ geçidi (Hermes Agent'ın kullandığı aynı arka uç). `portal.nousresearch.com`'a karşı cihaz yetkilendirmesi girişi; erişim belirteci istek başına çıkarım JWT'sidir. Oturum açmış hesaptan canlı olarak keşfedilen karışık ücretli + `:free` model kataloğu (`tencent/hy3:free`, `stepfun/step-3.7-flash:free`, ...). Yenileme belirteçleri tek kullanımlıktır ve her yenilemede döndürülür. | diff --git a/docs-site/src/content/docs/zh-tw/guides/providers.md b/docs-site/src/content/docs/zh-tw/guides/providers.md index ee7d709880..28298c768a 100644 --- a/docs-site/src/content/docs/zh-tw/guides/providers.md +++ b/docs-site/src/content/docs/zh-tw/guides/providers.md @@ -103,7 +103,7 @@ ocx logout | 供應商 | Adapter | Base URL | 備註 | | --- | --- | --- | --- | -| `xai` | `openai-chat` | `https://api.x.ai/v1` | 優先使用即時 Grok catalog;fallback 預設為 `grok-4.5`。 | +| `xai` | `openai-chat` | `https://cli-chat-proxy.grok.com/v1` | OAuth 使用獨立的 Grok CLI 訂閱 gateway。API key 覆寫使用 `https://api.x.ai/v1`,並可能注入 Priority Processing。優先使用即時 Grok catalog;fallback 預設為 `grok-4.5`。 | | `anthropic` | `anthropic` | `https://api.anthropic.com` | Claude 模型;即時模型列表從 `/v1/models` 取得。 | | `kimi` | `openai-chat` | `https://api.kimi.com/coding/v1` | Kimi K2.7/K2.6/K2.5 coding 模型。 | | `nous` | `openai-chat` | `https://inference-api.nousresearch.com/v1` | Nous Research 訂閱 gateway(Hermes Agent 使用相同 backend)。透過 `portal.nousresearch.com` 做 device-grant 登入;access token 是每次請求使用的 inference JWT。混合付費與 `:free` 模型 catalog(`tencent/hy3:free`、`stepfun/step-3.7-flash:free` 等)會從已登入帳號即時探索。Refresh token 為單次使用,每次 refresh 都會輪換。 | From 6c748663e5e15a89ae32c45fa48ee12241e57f7d Mon Sep 17 00:00:00 2001 From: Hsia97 Date: Fri, 21 Aug 2026 14:52:12 +0800 Subject: [PATCH 008/114] fix: enable call_id thought-signature replay for Claude Code Claude Code's Anthropic Messages path never received a reasoning-replay scope because it does not send the Codex parent-thread header. Derive one from the stable per-session prompt_cache_key (metadata.user_id) so Gemini/Antigravity thought signatures are remembered by call_id and survive history replay. Also read nested extra_content.google.thought_signature when parsing Google responses. --- src/adapters/google.ts | 19 ++++++++++++++++--- src/server/responses/core.ts | 12 ++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/adapters/google.ts b/src/adapters/google.ts index 07dd38e476..746f9490a4 100644 --- a/src/adapters/google.ts +++ b/src/adapters/google.ts @@ -413,6 +413,7 @@ interface GoogleResponsePart { thought?: boolean; thoughtSignature?: string; thought_signature?: string; + extra_content?: { google?: { thought_signature?: unknown } }; functionCall?: unknown; } @@ -421,6 +422,18 @@ interface GoogleFunctionCall { args?: unknown; } +/** + * Read a Gemini/Antigravity thought signature from a response part. Antigravity can place it + * either directly on the part (`thoughtSignature` / `thought_signature`) or inside the same + * nested `extra_content.google.thought_signature` shape used on the Responses wire. + */ +function googlePartThoughtSignature(part: GoogleResponsePart): string | undefined { + const direct = part.thoughtSignature ?? part.thought_signature; + if (typeof direct === "string" && direct.length > 0) return direct; + const nested = part.extra_content?.google?.thought_signature; + return typeof nested === "string" && nested.length > 0 ? nested : undefined; +} + /** * Carry a Gemini thought signature with the exact function-call part that produced it. Google * validates the signature against that specific part, so it must ride the individual tool call @@ -430,7 +443,7 @@ function googleToolCallMetadataFromPart( part: GoogleResponsePart, fallbackSignature?: string, ): { providerMetadata: OcxProviderOpaqueToolCallMetadata } | undefined { - const signature = part.thoughtSignature ?? part.thought_signature ?? fallbackSignature; + const signature = googlePartThoughtSignature(part) ?? fallbackSignature; if (!isLikelyRealThoughtSignature(signature)) return undefined; return { providerMetadata: { google: { thoughtSignature: signature } } }; } @@ -960,7 +973,7 @@ export function createGoogleAdapter(provider: OcxProviderConfig): ProviderAdapte } if (parts) { for (const part of parts) { - const sig = part.thoughtSignature ?? part.thought_signature; + const sig = googlePartThoughtSignature(part); if (part.thought === true && sig && isLikelyRealThoughtSignature(sig)) { pendingStreamThoughtSig = sig; } @@ -1224,7 +1237,7 @@ export function createGoogleAdapter(provider: OcxProviderConfig): ProviderAdapte } let pendingThoughtSig: string | undefined; for (const part of parts) { - const sig = part.thoughtSignature ?? part.thought_signature; + const sig = googlePartThoughtSignature(part); if (part.thought === true && sig && isLikelyRealThoughtSignature(sig)) { pendingThoughtSig = sig; } diff --git a/src/server/responses/core.ts b/src/server/responses/core.ts index 22bf3c18c3..dbe3a7dad8 100644 --- a/src/server/responses/core.ts +++ b/src/server/responses/core.ts @@ -2177,6 +2177,18 @@ async function handleResponsesInner( if (inboundClientThreadId) { parsed._clientThreadId = inboundClientThreadId; parsed._reasoningReplayScope = { clientThreadId: inboundClientThreadId }; + } else if ( + options.inboundWire === "anthropic" + && options.promptCacheKeyIsSharedCohort !== true + && typeof parsed.options.promptCacheKey === "string" + && parsed.options.promptCacheKey.trim().length > 0 + ) { + // Claude Code has no Codex parent-thread header, but its metadata.user_id is + // translated into a stable per-session prompt_cache_key. Use it as the replay + // thread identity so Gemini thought signatures are remembered by call_id for + // Anthropic Messages clients too (#1735/#1926). Keep `_clientThreadId` unset so + // existing provider session-id derivation (first-user-text fallback) is unchanged. + parsed._reasoningReplayScope = { clientThreadId: parsed.options.promptCacheKey }; } } catch (err) { if (isTranslatorBudgetExceededError(err)) { From b31f3dbed424db6967a958cc326b05b71944170d Mon Sep 17 00:00:00 2001 From: Hsia97 Date: Fri, 21 Aug 2026 15:27:58 +0800 Subject: [PATCH 009/114] test: cover Claude Code thought-signature replay scope Adds regression coverage for the Anthropic Messages reasoning-replay scope and for reading nested extra_content.google.thought_signature from Google response parts. --- ...laude-code-thought-signature-scope.test.ts | 111 ++++++++++++++++++ ...google-signature-history-roundtrip.test.ts | 14 +++ 2 files changed, 125 insertions(+) create mode 100644 tests/claude-code-thought-signature-scope.test.ts diff --git a/tests/claude-code-thought-signature-scope.test.ts b/tests/claude-code-thought-signature-scope.test.ts new file mode 100644 index 0000000000..1d214eda41 --- /dev/null +++ b/tests/claude-code-thought-signature-scope.test.ts @@ -0,0 +1,111 @@ +/** + * Regression coverage for the Claude Code thought-signature replay scope: + * + * Claude Code speaks Anthropic Messages and does not send Codex's + * `x-codex-parent-thread-id`. The server must still create a reasoning-replay + * scope for a real per-session `prompt_cache_key` (derived from + * `metadata.user_id`) so Gemini/Antigravity thought signatures can be remembered + * by call_id. The shared Desktop `prompt_cache_key` cohort must NOT get a scope. + */ +import { afterEach, describe, expect, mock, test } from "bun:test"; + +import type { ProviderAdapter } from "../src/adapters/base"; +import type { AdapterEvent, OcxConfig, OcxParsedRequest, OcxProviderConfig } from "../src/types"; + +const actualResolver = await import("../src/server/adapter-resolve"); + +let adapterFactory: ((provider: OcxProviderConfig) => ProviderAdapter) | undefined; + +mock.module("../src/server/adapter-resolve", () => ({ + ...actualResolver, + resolveAdapter(provider: OcxProviderConfig, cacheRetention?: "none" | "short" | "long") { + return adapterFactory?.(provider) ?? actualResolver.resolveAdapter(provider, cacheRetention); + }, +})); + +const { handleResponses } = await import("../src/server/responses"); + +afterEach(() => { + adapterFactory = undefined; +}); + +function captureAdapter(captured: OcxParsedRequest[]): ProviderAdapter { + return { + name: "capture-replay-scope", + buildRequest: () => ({ url: "https://capture.test", method: "POST", headers: {}, body: "{}" }), + async *parseStream(): AsyncGenerator { + yield { type: "done" }; + }, + async runTurn(parsed: OcxParsedRequest, _incoming, emit) { + captured.push(parsed); + emit({ type: "done" }); + }, + }; +} + +function testConfig(): OcxConfig { + return { + port: 0, + defaultProvider: "a", + providers: { + a: { + adapter: "openai-chat", + baseUrl: "https://capture.test", + authMode: "key", + apiKey: "capture-key", + models: ["m1"], + }, + }, + } as OcxConfig; +} + +async function drive(options: { + promptCacheKey?: string; + promptCacheKeyIsSharedCohort?: boolean; +}): Promise { + const captured: OcxParsedRequest[] = []; + adapterFactory = () => captureAdapter(captured); + const body: Record = { + model: "m1", + stream: true, + input: [{ type: "message", role: "user", content: [{ type: "input_text", text: "hello" }] }], + }; + if (options.promptCacheKey !== undefined) body.prompt_cache_key = options.promptCacheKey; + + const response = await handleResponses( + new Request("http://localhost/v1/responses", { + method: "POST", + headers: { "content-type": "application/json" }, + body: JSON.stringify(body), + }), + testConfig(), + { model: "", provider: "" }, + { + inboundWire: "anthropic", + ...(options.promptCacheKeyIsSharedCohort === undefined + ? {} + : { promptCacheKeyIsSharedCohort: options.promptCacheKeyIsSharedCohort }), + }, + ); + await response.text(); + expect(captured.length).toBe(1); + return captured[0]!; +} + +describe("Claude Code Anthropic inbound reasoning-replay scope", () => { + test("a real per-session prompt_cache_key creates a call_id replay scope", async () => { + const parsed = await drive({ promptCacheKey: "session-key-123", promptCacheKeyIsSharedCohort: false }); + expect(parsed._clientThreadId).toBeUndefined(); + expect(parsed._reasoningReplayScope?.clientThreadId).toBe("session-key-123"); + }); + + test("the shared Desktop prompt_cache_key cohort does not create a scope", async () => { + const parsed = await drive({ promptCacheKey: "shared-cohort-key", promptCacheKeyIsSharedCohort: true }); + expect(parsed._reasoningReplayScope).toBeUndefined(); + }); + + test("an Anthropic replay without prompt_cache_key does not create a scope", async () => { + const parsed = await drive({}); + expect(parsed._reasoningReplayScope).toBeUndefined(); + }); +}); diff --git a/tests/google-signature-history-roundtrip.test.ts b/tests/google-signature-history-roundtrip.test.ts index c914825bee..571ce27c1a 100644 --- a/tests/google-signature-history-roundtrip.test.ts +++ b/tests/google-signature-history-roundtrip.test.ts @@ -118,6 +118,20 @@ describe("#1735 thought signature survives history replay", () => { .toBe(SIGNATURE); }); + test("a functionCall part with nested extra_content.google.thought_signature is read", async () => { + const adapter = createGoogleAdapter(provider); + await adapter.buildRequest(firstTurn()); + const events = await adapter.parseResponse!(new Response(JSON.stringify(googleBody([ + { + functionCall: { name: "shell_command", args: { command: "pwd" } }, + extra_content: { google: { thought_signature: SIGNATURE } }, + }, + ])))); + const start = events.find((e: AdapterEvent) => e.type === "tool_call_start"); + expect(start && "providerMetadata" in start ? start.providerMetadata?.google?.thoughtSignature : undefined) + .toBe(SIGNATURE); + }); + test("parallel calls each keep their own signature", async () => { const adapter = createGoogleAdapter(provider); await adapter.buildRequest(firstTurn()); From 82d2f32ff5712a641ccd307f2e5fb646e95ab374 Mon Sep 17 00:00:00 2001 From: User Date: Sat, 15 Aug 2026 00:09:10 -0600 Subject: [PATCH 010/114] feat(cursor): native SelectedImage vision for verified models (data: only) --- .../docs/reference/configuration/providers.md | 7 + src/adapters/cursor/discovery.ts | 20 + src/adapters/cursor/images.ts | 685 ++++++++++++++++++ src/adapters/cursor/live-transport.ts | 26 +- src/adapters/cursor/protobuf-request.ts | 16 +- src/adapters/cursor/request-builder.ts | 43 +- src/adapters/cursor/types.ts | 9 +- src/providers/registry.ts | 10 +- .../catalog-vision-sidecar-modalities.test.ts | 21 + tests/cursor-blob.test.ts | 184 +++++ tests/cursor-discovery.test.ts | 17 + tests/cursor-images.test.ts | 574 +++++++++++++++ tests/cursor-request-builder.test.ts | 61 +- tests/cursor-static-catalog.test.ts | 7 + tests/cursor-vision-wire-harness.test.ts | 103 +++ tests/helpers/cursor-grumpy-fixture.png | Bin 0 -> 440734 bytes tests/oauth-provider-reconcile.test.ts | 29 + tests/provider-registry-parity.test.ts | 5 + 18 files changed, 1782 insertions(+), 35 deletions(-) create mode 100644 src/adapters/cursor/images.ts create mode 100644 tests/cursor-images.test.ts create mode 100644 tests/cursor-vision-wire-harness.test.ts create mode 100644 tests/helpers/cursor-grumpy-fixture.png diff --git a/docs-site/src/content/docs/reference/configuration/providers.md b/docs-site/src/content/docs/reference/configuration/providers.md index 135f8f9632..207ec76f21 100644 --- a/docs-site/src/content/docs/reference/configuration/providers.md +++ b/docs-site/src/content/docs/reference/configuration/providers.md @@ -345,6 +345,13 @@ Cursor-specific model parameters: Explicit variants send Cursor's `default` model with its `optimization` parameter, preserving the selection on every request. They remain available when live discovery omits `default`. +### Vision + +Native Cursor vision uses `SelectedImage` (JPEG soft-cap + `blobIdWithData`) for models that can +see images natively — Claude, Gemini, GPT, Kimi, and Grok among them — using active-turn `data:` +images only. Auto, the Composer family, and GLM (`glm-5.2`) stay on the curated `noVisionModels` +list and use the vision describe sidecar instead. + Cursor server-driven local tools are disabled by default. Codex continues using its own tools such as `apply_patch` and `exec_command` with its own approval and sandbox policy: diff --git a/src/adapters/cursor/discovery.ts b/src/adapters/cursor/discovery.ts index a530df2d94..020c22ffc5 100644 --- a/src/adapters/cursor/discovery.ts +++ b/src/adapters/cursor/discovery.ts @@ -103,6 +103,26 @@ export const CURSOR_ROUTER_MODEL_IDS = [ ...CURSOR_ROUTING_LEVELS.map(level => `${CURSOR_AUTO_MODEL_ID}-${level}`), ] as const; +/** + * Cursor models that cannot see images natively. OpenCodex routes them through the vision + * sidecar (the catalog still advertises image so Codex can attach). Evidence: + * - Composer family: Cursor staff — text-only; "Model does not support images" + * - Auto / router modes: Cursor docs omit Images for Auto Cost; staff — pick Claude/GPT for images + * - glm-5.2: Cursor docs omit Images; Z.ai GLM-5.2 is text-only (vision is GLM-5V) + * + * Composer ids are enumerated explicitly — prefix wildcard matching is deliberately out of + * scope here; a live-discovered new Composer slug stays native-path until curated. Everyone + * else in the static seed (Claude, Gemini, GPT, Kimi, Grok) takes SelectedImage. Other + * live-discovered ids stay unclassified (native path) until curated. + */ +export const CURSOR_NO_VISION_MODELS = [ + ...CURSOR_ROUTER_MODEL_IDS, + "composer-1", + "composer-2.5", + "composer-2.5-fast", + "glm-5.2", +] as const; + /** Wire id Cursor Connect expects for the auto-router (GetUsableModels returns `default`, not `auto`). */ export const CURSOR_AUTO_WIRE_MODEL_ID = "default"; diff --git a/src/adapters/cursor/images.ts b/src/adapters/cursor/images.ts new file mode 100644 index 0000000000..9997d0c67c --- /dev/null +++ b/src/adapters/cursor/images.ts @@ -0,0 +1,685 @@ +import { randomUUID } from "node:crypto"; +import { create } from "@bufbuild/protobuf"; +import type { OcxContentPart, OcxImageContent, OcxMessage } from "../../types"; +import { + SelectedContextSchema, + SelectedImageSchema, + SelectedImage_BlobIdWithDataSchema, + SelectedImage_DimensionSchema, + type SelectedContext, + type SelectedImage, +} from "./gen/agent_pb"; +import { + storeCursorBlob, + type CursorBlobRequestScopeToken, +} from "./native-exec"; + +/** Final per-image byte cap after prep (OmniRoute / composer-api style). */ +export const MAX_CURSOR_IMAGE_BYTES = 1024 * 1024; + +/** + * Inbound decode/fetch bomb ceiling before JPEG prep. Large clipboard PNGs may exceed + * {@link MAX_CURSOR_IMAGE_BYTES} raw but shrink under the wire cap after re-encode. + */ +export const MAX_CURSOR_IMAGE_DECODE_BYTES = 16 * 1024 * 1024; + +/** + * Soft target for Cursor vision hydration. Live A/B: ~430 KiB PNG failed ("gray"/wrong UI) + * while the same visual as ~75 KiB JPEG succeeded. Prefer JPEG at or under this size. + */ +export const CURSOR_VISION_SOFT_MAX_BYTES = 100 * 1024; + +/** Soft target when the client requests `detail: original` or `high`. */ +export const CURSOR_VISION_SOFT_MAX_BYTES_HIGH = 256 * 1024; + +/** Longest edge after Cursor vision prep (Cursor staff guidance: ≤ 2000 px). */ +export const CURSOR_VISION_MAX_EDGE = 2000; + +/** + * Decode bomb: reject images whose sniffed longest edge exceeds this before Bun.Image. + * Separate from {@link CURSOR_VISION_MAX_EDGE} (output resize target). + */ +export const MAX_CURSOR_IMAGE_DECODE_EDGE = 8192; + +/** Decode bomb: reject images whose sniffed pixel count exceeds this before Bun.Image. */ +export const MAX_CURSOR_IMAGE_PIXELS = 25_000_000; + +const CURSOR_VISION_JPEG_QUALITIES_DEFAULT = [85, 70, 55, 40] as const; +const CURSOR_VISION_JPEG_QUALITIES_HIGH = [90, 80, 65, 50] as const; +/** Stop shrinking below this longest edge when chasing the soft byte cap. */ +const CURSOR_VISION_SOFT_MIN_EDGE = 256; +const CURSOR_VISION_SOFT_SHRINK = 0.85; + +const CURSOR_VISION_PASSTHROUGH_MIME = new Set([ + "image/jpeg", + "image/jpg", + "image/png", + "image/gif", + "image/webp", +]); + +/** Upper bound on images attached to one Cursor turn. */ +export const MAX_CURSOR_IMAGES = 12; + +/** Marker when an image cannot be prepared for the Cursor vision wire. */ +export const CURSOR_VISION_IMAGE_OMITTED = + "[image omitted: undecodable or unsupported type]"; + +export class CursorImageError extends Error { + readonly status: number; + + constructor(message: string, status = 400) { + super(message); + this.name = "CursorImageError"; + this.status = status; + } +} + +export interface ResolvedCursorImage { + data: Uint8Array; + mimeType: string; + uuid: string; + /** Codex/OpenAI image detail hint; affects JPEG soft-cap tier. */ + detail?: string; +} + +export type PrepareCursorImageOutcome = + | { status: "ready"; image: ResolvedCursorImage } + | { status: "omitted"; reason: string }; + +function isImagePart(part: OcxContentPart): part is OcxImageContent { + return part.type === "image"; +} + +function estimatedBase64DecodedBytes(payload: string): number { + return Math.floor((payload.length * 3) / 4); +} + +function isHighDetail(detail: string | undefined): boolean { + const normalized = (detail ?? "").trim().toLowerCase(); + return normalized === "original" || normalized === "high"; +} + +function softMaxBytesForDetail(detail: string | undefined): number { + return isHighDetail(detail) ? CURSOR_VISION_SOFT_MAX_BYTES_HIGH : CURSOR_VISION_SOFT_MAX_BYTES; +} + +function jpegQualitiesForDetail(detail: string | undefined): readonly number[] { + return isHighDetail(detail) ? CURSOR_VISION_JPEG_QUALITIES_HIGH : CURSOR_VISION_JPEG_QUALITIES_DEFAULT; +} + +export function decodeCursorImageDataUrl(url: string): { data: Uint8Array; mimeType: string } { + const comma = url.indexOf(","); + if (comma < 0) throw new CursorImageError("Image data URL is malformed."); + const header = url.slice(5, comma); + const payload = url.slice(comma + 1); + const isBase64 = /;base64/i.test(header); + const mimeType = (header.split(";")[0] || "").trim().toLowerCase() || "application/octet-stream"; + + if (!mimeType.startsWith("image/")) { + throw new CursorImageError("Image data URL must have an image/* media type."); + } + if (!isBase64) { + throw new CursorImageError("Image data URL must be base64-encoded."); + } + if (payload.length > MAX_CURSOR_IMAGE_DECODE_BYTES * 2) { + throw new CursorImageError("Image input is too large to process safely."); + } + + const normalized = payload.replace(/\s/g, ""); + if (normalized.length === 0) { + throw new CursorImageError("Image data URL contains invalid base64 data."); + } + // Reject lenient Buffer.from acceptances (wrong alphabet, bad padding, truncated groups). + if (normalized.length % 4 !== 0 || !/^[A-Za-z0-9+/]+={0,2}$/.test(normalized)) { + throw new CursorImageError("Image data URL contains invalid base64 data."); + } + if (estimatedBase64DecodedBytes(normalized) > MAX_CURSOR_IMAGE_DECODE_BYTES) { + throw new CursorImageError("Image input is too large to process safely."); + } + + let data: Uint8Array; + try { + data = Buffer.from(normalized, "base64"); + } catch { + throw new CursorImageError("Image data URL contains invalid base64 data."); + } + if (data.byteLength === 0) { + throw new CursorImageError("Image data URL contains invalid base64 data."); + } + // Round-trip guard: Node/Bun can silently drop trailing garbage. + if (Buffer.from(data).toString("base64").replace(/=+$/, "") !== normalized.replace(/=+$/, "")) { + throw new CursorImageError("Image data URL contains invalid base64 data."); + } + if (data.byteLength > MAX_CURSOR_IMAGE_DECODE_BYTES) { + throw new CursorImageError("Image input is too large to process safely."); + } + return { data, mimeType }; +} + +function throwIfImagePhaseAborted(signal?: AbortSignal): void { + if (!signal?.aborted) return; + if (signal.reason instanceof Error) throw signal.reason; + const err = new Error("Cursor image phase aborted"); + err.name = "AbortError"; + throw err; +} + +/** Magic-byte format sniff (independent of declared MIME). */ +export function sniffCursorImageFormat( + data: Uint8Array, +): "png" | "jpeg" | "gif" | "webp" | undefined { + if ( + data.byteLength >= 8 + && data[0] === 0x89 && data[1] === 0x50 && data[2] === 0x4e && data[3] === 0x47 + && data[4] === 0x0d && data[5] === 0x0a && data[6] === 0x1a && data[7] === 0x0a + ) { + return "png"; + } + if ( + data.byteLength >= 6 + && data[0] === 0x47 && data[1] === 0x49 && data[2] === 0x46 && data[3] === 0x38 + ) { + return "gif"; + } + if (data.byteLength >= 4 && data[0] === 0xff && data[1] === 0xd8) return "jpeg"; + if ( + data.byteLength >= 12 + && data[0] === 0x52 && data[1] === 0x49 && data[2] === 0x46 && data[3] === 0x46 + && data[8] === 0x57 && data[9] === 0x45 && data[10] === 0x42 && data[11] === 0x50 + ) { + return "webp"; + } + return undefined; +} + +/** Collect image URLs from one message's content parts, preserving order. */ +export function extractCursorImageUrls(content: string | readonly OcxContentPart[]): string[] { + return extractCursorImageParts(content).map(part => part.imageUrl); +} + +export interface CursorImagePartRef { + imageUrl: string; + detail?: string; +} + +/** Collect image parts (URL + optional detail) from one message's content. */ +export function extractCursorImageParts( + content: string | readonly OcxContentPart[], +): CursorImagePartRef[] { + if (typeof content === "string" || !Array.isArray(content)) return []; + const parts: CursorImagePartRef[] = []; + for (const part of content) { + if (isImagePart(part) && typeof part.imageUrl === "string" && part.imageUrl.length > 0) { + parts.push({ + imageUrl: part.imageUrl, + ...(typeof part.detail === "string" && part.detail.length > 0 ? { detail: part.detail } : {}), + }); + } + } + return parts; +} + +/** + * Resolve OpenCodex image parts (data: URLs only) into bytes for SelectedImage. + * Prep (JPEG soft-cap) runs before the 1 MiB wire cap so large clipboard PNGs can shrink. + * Unsupported / undecodable images are omitted (fail-closed). + */ +export async function resolveCursorImages( + imageUrls: readonly string[], + signal?: AbortSignal, + options?: { details?: readonly (string | undefined)[] }, +): Promise { + if (imageUrls.length > MAX_CURSOR_IMAGES) { + throw new CursorImageError(`Too many images in one request (max ${MAX_CURSOR_IMAGES}).`); + } + + const out: ResolvedCursorImage[] = []; + for (let i = 0; i < imageUrls.length; i++) { + throwIfImagePhaseAborted(signal); + const url = imageUrls[i]; + if (typeof url !== "string" || url.length === 0) { + // Soft-omit missing URLs rather than aborting a mixed turn. + continue; + } + // Remote URL fetching is deliberately out of scope here; https:// images are omitted. + if (!url.toLowerCase().startsWith("data:")) continue; + try { + const resolved = decodeCursorImageDataUrl(url); + if (resolved.data.byteLength === 0) continue; + const outcome = await prepareCursorImageForWire({ + data: resolved.data, + mimeType: resolved.mimeType, + uuid: randomUUID(), + ...(options?.details?.[i] ? { detail: options.details[i] } : {}), + }, signal); + if (outcome.status === "omitted") continue; + if (outcome.image.data.byteLength > MAX_CURSOR_IMAGE_BYTES) continue; + out.push(outcome.image); + } catch (err) { + if (signal?.aborted || (err instanceof Error && err.name === "AbortError")) throw err; + if (err instanceof CursorImageError) continue; + continue; + } + } + return out; +} + +export async function resolveCursorImageParts( + parts: readonly CursorImagePartRef[], + signal?: AbortSignal, +): Promise { + return resolveCursorImages( + parts.map(part => part.imageUrl), + signal, + { details: parts.map(part => part.detail) }, + ); +} + +/** Filename Cursor clients typically put on SelectedImage.path (shunt / agent parity). */ +export function cursorImageAttachmentPath(uuid: string, mimeType: string): string { + const normalized = mimeType.toLowerCase(); + const ext = normalized === "image/jpeg" || normalized === "image/jpg" ? "jpg" + : normalized === "image/gif" ? "gif" + : normalized === "image/webp" ? "webp" + : "png"; + return `attachment-${uuid}.${ext}`; +} + +/** + * Re-encode toward a JPEG under the soft vision cap when Bun can decode the payload. + * Unsupported MIME, oversize dimensions/pixels, or undecodable bytes are omitted (fail-closed). + * After the quality ladder, edges shrink iteratively until the soft byte cap is met + * (or the min edge floor is hit) so large clipboard PNGs do not leave >softMax JPEGs + * that Cursor vision hallucinates on. + */ +export async function prepareCursorImageForWire( + image: ResolvedCursorImage, + signal?: AbortSignal, +): Promise { + throwIfImagePhaseAborted(signal); + const mime = image.mimeType.toLowerCase(); + const softMax = softMaxBytesForDetail(image.detail); + const qualities = jpegQualitiesForDetail(image.detail); + const lowestQuality = qualities[qualities.length - 1]!; + + if (!CURSOR_VISION_PASSTHROUGH_MIME.has(mime)) { + return { status: "omitted", reason: CURSOR_VISION_IMAGE_OMITTED }; + } + + const format = sniffCursorImageFormat(image.data); + // Peek headers before Bun.Image so huge compressed bombs fail closed cheaply. + const sniffed = sniffCursorImageDimensions(image.data); + if (sniffed) { + const edge = Math.max(sniffed.width, sniffed.height); + const pixels = sniffed.width * sniffed.height; + if (edge > MAX_CURSOR_IMAGE_DECODE_EDGE || pixels > MAX_CURSOR_IMAGE_PIXELS) { + return { status: "omitted", reason: CURSOR_VISION_IMAGE_OMITTED }; + } + } + + // Second-pass skip: already soft-capped JPEG that has a real SOF (not SOI-only junk). + const declaredJpeg = mime === "image/jpeg" || mime === "image/jpg"; + const alreadySmallJpeg = declaredJpeg + && format === "jpeg" + && sniffed !== undefined + && image.data.byteLength <= softMax; + if (alreadySmallJpeg) { + return { status: "ready", image }; + } + + try { + throwIfImagePhaseAborted(signal); + // Force a full decode before accepting passthrough / encode (Anthropic-style validate). + await new Bun.Image(image.data).resize(1, 1).jpeg({ quality: 1 }).toBuffer(); + + // Passthrough only when declared MIME matches actual JPEG magic (never PNG-as-JPEG). + if (declaredJpeg && format === "jpeg" && image.data.byteLength <= softMax) { + return { status: "ready", image }; + } + + throwIfImagePhaseAborted(signal); + const meta = await new Bun.Image(image.data).metadata(); + const width = typeof meta.width === "number" ? meta.width : 0; + const height = typeof meta.height === "number" ? meta.height : 0; + if (width > 0 && height > 0) { + const edge = Math.max(width, height); + if (edge > MAX_CURSOR_IMAGE_DECODE_EDGE || width * height > MAX_CURSOR_IMAGE_PIXELS) { + return { status: "omitted", reason: CURSOR_VISION_IMAGE_OMITTED }; + } + } + let targetW = width; + let targetH = height; + if (width > 0 && height > 0 && Math.max(width, height) > CURSOR_VISION_MAX_EDGE) { + const scale = CURSOR_VISION_MAX_EDGE / Math.max(width, height); + targetW = Math.max(1, Math.round(width * scale)); + targetH = Math.max(1, Math.round(height * scale)); + } + + const encodeAt = async (w: number, h: number, quality: number): Promise => { + throwIfImagePhaseAborted(signal); + let pipeline = new Bun.Image(image.data); + if (w > 0 && h > 0 && (w !== width || h !== height)) { + pipeline = pipeline.resize(w, h); + } + return new Uint8Array(await pipeline.jpeg({ quality }).bytes()); + }; + + let best: Uint8Array | undefined; + for (const quality of qualities) { + const encoded = await encodeAt(targetW, targetH, quality); + if (!best || encoded.byteLength < best.byteLength) best = encoded; + if (encoded.byteLength <= softMax) { + return { + status: "ready", + image: { ...image, data: encoded, mimeType: "image/jpeg" }, + }; + } + } + + // Quality ladder missed the soft cap — shrink edges until it fits or we hit the floor. + while ( + best + && best.byteLength > softMax + && targetW > 0 + && targetH > 0 + && Math.max(targetW, targetH) > CURSOR_VISION_SOFT_MIN_EDGE + ) { + throwIfImagePhaseAborted(signal); + const nextW = Math.max(1, Math.round(targetW * CURSOR_VISION_SOFT_SHRINK)); + const nextH = Math.max(1, Math.round(targetH * CURSOR_VISION_SOFT_SHRINK)); + if (Math.max(nextW, nextH) < CURSOR_VISION_SOFT_MIN_EDGE) { + const scale = CURSOR_VISION_SOFT_MIN_EDGE / Math.max(targetW, targetH); + targetW = Math.max(1, Math.round(targetW * scale)); + targetH = Math.max(1, Math.round(targetH * scale)); + } else { + targetW = nextW; + targetH = nextH; + } + const encoded = await encodeAt(targetW, targetH, lowestQuality); + if (!best || encoded.byteLength < best.byteLength) best = encoded; + if (encoded.byteLength <= softMax) { + return { + status: "ready", + image: { ...image, data: encoded, mimeType: "image/jpeg" }, + }; + } + if (Math.max(targetW, targetH) <= CURSOR_VISION_SOFT_MIN_EDGE) break; + } + + if (best) { + return { + status: "ready", + image: { ...image, data: best, mimeType: "image/jpeg" }, + }; + } + // Undeclared/mismatched magic with no encode result — omit rather than lie about MIME. + if (declaredJpeg && format !== "jpeg") { + return { status: "omitted", reason: CURSOR_VISION_IMAGE_OMITTED }; + } + return { status: "ready", image }; + } catch (err) { + if (signal?.aborted || (err instanceof Error && err.name === "AbortError")) throw err; + return { status: "omitted", reason: CURSOR_VISION_IMAGE_OMITTED }; + } +} + +/** + * Sniff PNG/JPEG/GIF/WebP dimensions from raw bytes when the header is present. + * Best-effort only — unknown formats return undefined (dimension is optional). + */ +export function sniffCursorImageDimensions( + data: Uint8Array, +): { width: number; height: number } | undefined { + // PNG: signature + IHDR chunk (width/height at bytes 16..23) + if ( + data.byteLength >= 24 + && data[0] === 0x89 && data[1] === 0x50 && data[2] === 0x4e && data[3] === 0x47 + && data[4] === 0x0d && data[5] === 0x0a && data[6] === 0x1a && data[7] === 0x0a + ) { + const width = ((data[16]! << 24) | (data[17]! << 16) | (data[18]! << 8) | data[19]!) >>> 0; + const height = ((data[20]! << 24) | (data[21]! << 16) | (data[22]! << 8) | data[23]!) >>> 0; + if (width > 0 && height > 0) return { width, height }; + } + // GIF: "GIF8" + width/height as little-endian u16 at bytes 6..9 + if ( + data.byteLength >= 10 + && data[0] === 0x47 && data[1] === 0x49 && data[2] === 0x46 && data[3] === 0x38 + ) { + const width = data[6]! | (data[7]! << 8); + const height = data[8]! | (data[9]! << 8); + if (width > 0 && height > 0) return { width, height }; + } + // WebP: RIFF....WEBP + VP8X / VP8 / VP8L (same layout as anthropic-image-guard). + if ( + data.byteLength >= 30 + && data[0] === 0x52 && data[1] === 0x49 && data[2] === 0x46 && data[3] === 0x46 + && data[8] === 0x57 && data[9] === 0x45 && data[10] === 0x42 && data[11] === 0x50 + ) { + const fourcc = String.fromCharCode(data[12]!, data[13]!, data[14]!, data[15]!); + if (fourcc === "VP8X") { + const width = 1 + (data[24]! | (data[25]! << 8) | (data[26]! << 16)); + const height = 1 + (data[27]! | (data[28]! << 8) | (data[29]! << 16)); + if (width > 0 && height > 0) return { width, height }; + } else if (fourcc === "VP8 ") { + if (data[23] === 0x9d && data[24] === 0x01 && data[25] === 0x2a) { + const width = (data[26]! | (data[27]! << 8)) & 0x3fff; + const height = (data[28]! | (data[29]! << 8)) & 0x3fff; + if (width > 0 && height > 0) return { width, height }; + } + } else if (fourcc === "VP8L" && data[20] === 0x2f) { + const raw = data[21]! | (data[22]! << 8) | (data[23]! << 16) | (data[24]! << 24); + const width = (raw & 0x3fff) + 1; + const height = ((raw >> 14) & 0x3fff) + 1; + if (width > 0 && height > 0) return { width, height }; + } + } + // JPEG: scan for SOF0/SOF2 marker with dimensions + if (data.byteLength >= 4 && data[0] === 0xff && data[1] === 0xd8) { + let offset = 2; + while (offset + 8 < data.byteLength) { + if (data[offset] !== 0xff) break; + const marker = data[offset + 1]!; + // Standalone markers (TEM, RSTn, SOI, EOI) carry no length payload. + if (marker === 0x01 || (marker >= 0xd0 && marker <= 0xd9)) { + offset += 2; + continue; + } + const length = (data[offset + 2]! << 8) | data[offset + 3]!; + if (marker === 0xc0 || marker === 0xc2) { + const height = (data[offset + 5]! << 8) | data[offset + 6]!; + const width = (data[offset + 7]! << 8) | data[offset + 8]!; + if (width > 0 && height > 0) return { width, height }; + break; + } + if (length < 2) break; + offset += 2 + length; + } + } + return undefined; +} + +/** + * Build SelectedImage messages for the AgentService vision path: + * store bytes in the local KV map under sha256(blobId), and encode + * `blobIdWithData` so the server can populate its cache without relying solely + * on getBlobArgs timing. Also set `path` like native/shunt clients. + */ +export function buildSelectedImages( + images: readonly ResolvedCursorImage[], + requestScope?: CursorBlobRequestScopeToken, +): SelectedImage[] { + return images.map(image => { + const blobId = storeCursorBlob(image.data, requestScope); + const dims = sniffCursorImageDimensions(image.data); + return create(SelectedImageSchema, { + uuid: image.uuid, + path: cursorImageAttachmentPath(image.uuid, image.mimeType), + mimeType: image.mimeType, + ...(dims + ? { dimension: create(SelectedImage_DimensionSchema, dims) } + : {}), + dataOrBlobId: { + case: "blobIdWithData", + value: create(SelectedImage_BlobIdWithDataSchema, { + blobId, + data: image.data, + }), + }, + }); + }); +} + +/** + * Always send `UserMessage.selected_context`, even when empty — matches cursor-agent. + * When images are present, they are blobIdWithData refs backed by the request-scoped KV store. + */ +export function buildSelectedContext( + images: readonly ResolvedCursorImage[] = [], + requestScope?: CursorBlobRequestScopeToken, +): SelectedContext { + return create(SelectedContextSchema, { + selectedImages: buildSelectedImages(images, requestScope), + }); +} + +/** + * Resolve data: images for the active user/developer turn onto SelectedImage. + * Tool-result image promotion is intentionally out of scope in this slice. + */ +export async function resolveActiveCursorImages( + messages: readonly OcxMessage[] | undefined, + signal?: AbortSignal, +): Promise { + if (!messages?.length) return []; + // Tool-result continuations are out of scope in this slice: no trailing toolResult promotion. + if (messages.at(-1)?.role === "toolResult") return []; + + for (let i = messages.length - 1; i >= 0; i--) { + const message = messages[i]; + if (!message) continue; + if (message.role === "user" || message.role === "developer") { + return resolveCursorImageParts(extractCursorImageParts(message.content), signal); + } + } + return []; +} + +function imageDataUrlFromPrepared(image: ResolvedCursorImage): string { + return `data:${image.mimeType};base64,${Buffer.from(image.data).toString("base64")}`; +} + +/** + * Re-encode a single image URL through {@link prepareCursorImageForWire}. + * data: URLs only. Omitted images become text (caller replaces the part). + */ +export async function prepareCursorImageDataUrl( + imageUrl: string, + detail?: string, + signal?: AbortSignal, +): Promise<{ status: "ready"; imageUrl: string } | { status: "omitted"; reason: string }> { + try { + const resolved = imageUrl.toLowerCase().startsWith("data:") + ? decodeCursorImageDataUrl(imageUrl) + : null; + if (!resolved) { + return { status: "omitted", reason: CURSOR_VISION_IMAGE_OMITTED }; + } + if (resolved.data.byteLength === 0) { + return { status: "omitted", reason: CURSOR_VISION_IMAGE_OMITTED }; + } + const outcome = await prepareCursorImageForWire({ + data: resolved.data, + mimeType: resolved.mimeType, + uuid: randomUUID(), + ...(detail ? { detail } : {}), + }, signal); + if (outcome.status === "omitted") return outcome; + if (outcome.image.data.byteLength > MAX_CURSOR_IMAGE_BYTES) { + return { status: "omitted", reason: CURSOR_VISION_IMAGE_OMITTED }; + } + if ( + imageUrl.toLowerCase().startsWith("data:") + && outcome.image.data === resolved.data + && outcome.image.mimeType === resolved.mimeType + ) { + return { status: "ready", imageUrl }; + } + return { status: "ready", imageUrl: imageDataUrlFromPrepared(outcome.image) }; + } catch (err) { + if (signal?.aborted || (err instanceof Error && err.name === "AbortError")) throw err; + return { status: "omitted", reason: CURSOR_VISION_IMAGE_OMITTED }; + } +} + +async function prepareCursorContentParts( + content: string | readonly OcxContentPart[], + signal?: AbortSignal, +): Promise { + if (typeof content === "string" || !Array.isArray(content)) return content; + let changed = false; + const next: OcxContentPart[] = []; + for (const part of content) { + if (part.type === "image" && typeof part.imageUrl === "string" && part.imageUrl.length > 0) { + throwIfImagePhaseAborted(signal); + const prepared = await prepareCursorImageDataUrl(part.imageUrl, part.detail, signal); + if (prepared.status === "omitted") { + changed = true; + next.push({ type: "text", text: prepared.reason }); + continue; + } + if (prepared.imageUrl !== part.imageUrl) changed = true; + next.push({ ...part, imageUrl: prepared.imageUrl }); + } else { + next.push(part); + } + } + return changed ? next : content; +} + +/** + * First original-message index that still needs image prep for the active vision window. + * Historical messages before this index are left untouched (no decode). + */ +export function cursorVisionPrepareStartIndex(messages: readonly OcxMessage[]): number { + // Tool-result image preparation is out of scope in this slice. + if (messages.at(-1)?.role === "toolResult") return messages.length; + for (let i = messages.length - 1; i >= 0; i--) { + const role = messages[i]?.role; + if (role === "user" || role === "developer") return i; + } + return messages.length; +} + +/** + * Rewrite image data URLs in the active vision window (last user/developer turn) through + * the JPEG soft-cap path before protobuf encode. Historical messages are left by + * reference. Undecodable images become {@link CURSOR_VISION_IMAGE_OMITTED} text so + * image-only turns stay userMessageAction. + */ +export async function prepareCursorRawMessages( + messages: readonly OcxMessage[] | undefined, + signal?: AbortSignal, +): Promise { + if (!messages?.length) return messages; + const prepareFrom = cursorVisionPrepareStartIndex(messages); + let changed = false; + const out: OcxMessage[] = []; + for (let i = 0; i < messages.length; i++) { + throwIfImagePhaseAborted(signal); + const message = messages[i]!; + if ( + i >= prepareFrom + && (message.role === "user" || message.role === "developer") + ) { + const content = await prepareCursorContentParts(message.content, signal); + if (content !== message.content) { + changed = true; + out.push({ ...message, content } as OcxMessage); + continue; + } + } + out.push(message); + } + return changed ? out : messages; +} diff --git a/src/adapters/cursor/live-transport.ts b/src/adapters/cursor/live-transport.ts index 07bfa54dca..970a2dd120 100644 --- a/src/adapters/cursor/live-transport.ts +++ b/src/adapters/cursor/live-transport.ts @@ -13,6 +13,8 @@ import { type TranslatorBudget, } from "../../lib/translator-budget"; import { activePromptText, prepareCursorRunRequest } from "./protobuf-request"; +import { prepareCursorRawMessages, resolveActiveCursorImages } from "./images"; +import { cursorRequestMessagesFromRaw } from "./request-builder"; import { createCursorContextUsageTracker, createCursorProtobufEventState, @@ -569,10 +571,24 @@ class LiveCursorTransport implements CursorTransport { // Advertise MCP tools before the stream opens — the server only calls tools it was told about. await this.prepareMcp(); - const activeText = activePromptText(request); - this.activeClientToolFinalizeGraceMs = clientToolFinalizeGraceMsForRequest(request, this.clientToolFinalizeGraceMs); - const cursorVisibleTools = cursorToolsForActivePrompt(request.tools, activeText, request.toolChoice); - const clientToolDefs = buildCursorToolDefinitions(cursorVisibleTools, request.toolChoice); + // JPEG soft-cap rewrite for active-turn data: images before encode. Rebuild text + // messages from the prepared raw channel so omission markers replace stale + // pre-rewrite content that activePromptText and the tool filter would otherwise see. + const preparedRawMessages = await prepareCursorRawMessages(request.rawMessages, signal); + const selectedImages = await resolveActiveCursorImages(preparedRawMessages, signal); + const preparedMessages = preparedRawMessages === request.rawMessages + ? request.messages + : cursorRequestMessagesFromRaw(preparedRawMessages); + const activeRequest: CursorRunRequest = { + ...request, + messages: preparedMessages, + rawMessages: preparedRawMessages, + selectedImages, + }; + const activeText = activePromptText(activeRequest); + this.activeClientToolFinalizeGraceMs = clientToolFinalizeGraceMsForRequest(activeRequest, this.clientToolFinalizeGraceMs); + const cursorVisibleTools = cursorToolsForActivePrompt(activeRequest.tools, activeText, activeRequest.toolChoice); + const clientToolDefs = buildCursorToolDefinitions(cursorVisibleTools, activeRequest.toolChoice); // `request.tools` is the catalog already filtered and budgeted by request-builder. Derive // conversion provenance only from tagged synthetic tools that also survive this final prompt // filter; a client tool with the same wire name can never opt into conversion by collision. @@ -608,7 +624,7 @@ class LiveCursorTransport implements CursorTransport { }); // Build the payload once. The estimate is only worth deriving when there is no // carry-forward to fall back on — with a carry present it would never be used (#373). - const prepared = prepareCursorRunRequest(request, { + const prepared = prepareCursorRunRequest(activeRequest, { estimateInputTokens: contextUsage.carryForwardTokens === undefined, }); this.blobRequestScope = prepared.blobRequestScope; diff --git a/src/adapters/cursor/protobuf-request.ts b/src/adapters/cursor/protobuf-request.ts index 37a45c1c3f..863d8a8fe4 100644 --- a/src/adapters/cursor/protobuf-request.ts +++ b/src/adapters/cursor/protobuf-request.ts @@ -15,6 +15,7 @@ import { storeCursorBlob, type CursorBlobRequestScopeToken, } from "./native-exec"; +import { buildSelectedContext } from "./images"; import { estimateTokens } from "../../lib/token-estimate"; import { parseDataUrl } from "../image"; import { @@ -336,7 +337,7 @@ function contentText(message: OcxMessage): string { .map(part => { if (part.type === "text") return part.text; if (part.type === "thinking") return part.thinking; - if (part.type === "image") return `[image produced by this tool, omitted from Cursor text replay: ${part.detail ?? "auto"}]`; + if (part.type === "image") return undefined; return undefined; }) .filter((value): value is string => typeof value === "string" && value.length > 0) @@ -723,6 +724,8 @@ function conversationTurns( userMessage: storeCursorBlob(toBinary(UserMessageSchema, create(UserMessageSchema, { text: contentText(message), messageId: crypto.randomUUID(), + selectedContext: buildSelectedContext([], requestScope), + mode: 1, })), requestScope), steps: [], }; @@ -792,6 +795,7 @@ function buildPreparedCursorRunRequest( ? appendCursorGenericToolUseHint(request.tools, rawText) : rawText; const lastRawIsToolResult = request.rawMessages?.at(-1)?.role === "toolResult"; + const selectedImages = request.selectedImages ?? []; // Native models resume the remembered Cursor conversation. External wire // models continue as userMessageAction so history-blob tool results stay // visible without a ResumeAction. Some native composer ids are also routed @@ -799,12 +803,17 @@ function buildPreparedCursorRunRequest( // because a bare resumeAction makes them continue exploring with native tools // instead of answering (observed on composer-2.5; see discovery.ts). const externalToolContinuation = lastRawIsToolResult && cursorNeedsExternalToolContinuation(request.modelId); - const actionCase = (externalToolContinuation || (!lastRawIsToolResult && text.trim().length > 0)) + // Image-only active turns (including soft-omitted images) stay userMessageAction. + const actionCase = ( + externalToolContinuation + || (!lastRawIsToolResult && (text.trim().length > 0 || selectedImages.length > 0)) + ) ? "userMessageAction" : "resumeAction"; const actionText = externalToolContinuation ? CURSOR_EXTERNAL_TOOL_CONTINUATION_TEXT : text; + const selectedContext = buildSelectedContext(selectedImages, requestScope); const action = create(ConversationActionSchema, { action: actionCase === "userMessageAction" ? { @@ -813,6 +822,9 @@ function buildPreparedCursorRunRequest( userMessage: create(UserMessageSchema, { text: actionText, messageId: crypto.randomUUID(), + selectedContext, + // OmniRoute / cursor-agent always send mode=1 on UserMessage. + mode: 1, }), requestContext: buildRequestContext(), }), diff --git a/src/adapters/cursor/request-builder.ts b/src/adapters/cursor/request-builder.ts index 131fbf5152..9d0e83cbbf 100644 --- a/src/adapters/cursor/request-builder.ts +++ b/src/adapters/cursor/request-builder.ts @@ -31,6 +31,7 @@ import { type CursorCheckpointInvalidationReason, type CursorCheckpointSnapshot, } from "./checkpoint-store"; +import { extractCursorImageUrls } from "./images"; /** Probe-verified Cursor Connect boundaries, with byte headroom for the enclosing field. */ export const CURSOR_TOOL_COUNT_LIMIT = 330; @@ -211,15 +212,8 @@ function contentPartToText(part: OcxContentPart | OcxAssistantContentPart): stri case "thinking": return part.thinking; case "image": - // User-message images are still flattened here: this path builds the plain-text prompt, and - // the schema slot that could carry them (UserMessage.selectedContext.selectedImages) is not - // populated by this adapter. The tool-result ENCODER does build real McpImageContent - // (see protobuf-request.ts), so the old "unsupported by Cursor adapter" wording is no - // longer true of the encoder — but note that nothing reaches Cursor today either way: - // every Cursor model is in noVisionModels (providers/registry.ts), so the vision sidecar - // describes or strips images before this adapter runs. Kept the same length to avoid - // shifting any byte-budgeted prompt path. - return `[image omitted from this Cursor text prompt: ${part.detail ?? "auto"}]`; + // Images ride UserMessage.selected_context (SelectedImage) instead of text. + return undefined; case "toolCall": // Cursor does not accept OpenAI Responses assistant tool-call parts as native history here. // Rendering them as visible "[tool_call]" text leaks synthetic protocol markers back into @@ -252,9 +246,19 @@ function requestMessage(message: OcxMessage): CursorRequestMessage | undefined { switch (message.role) { case "user": case "developer": - return { role: message.role, content: contentToText(message.content) }; + { + const content = contentToText(message.content); + // Image-only turns survive as empty content; the encoder keeps them userMessageAction. + if (content.length === 0 && extractCursorImageUrls(message.content).length === 0) { + return undefined; + } + return { role: message.role, content }; + } case "assistant": - return { role: "assistant", content: contentToText(message.content) }; + { + const content = contentToText(message.content); + return content.length > 0 ? { role: "assistant", content } : undefined; + } case "toolResult": return { role: "tool", @@ -263,6 +267,19 @@ function requestMessage(message: OcxMessage): CursorRequestMessage | undefined { } } +/** + * Rebuild the text `messages` channel from prepared `rawMessages` so omission markers + * and JPEG-rewritten parts stay visible to activePromptText after image preparation. + */ +export function cursorRequestMessagesFromRaw( + messages: readonly OcxMessage[] | undefined, +): CursorRequestMessage[] { + if (!messages?.length) return []; + return messages + .map(requestMessage) + .filter((message): message is CursorRequestMessage => !!message); +} + export function generatedCursorConversationId(): string { return `cursor_${crypto.randomUUID().replace(/-/g, "")}`; } @@ -409,9 +426,7 @@ export function createCursorRequest( parsed: OcxParsedRequest, options: CreateCursorRequestOptions = {}, ): CursorRunRequest { - const messages = parsed.context.messages - .map(requestMessage) - .filter((message): message is CursorRequestMessage => !!message && message.content.length > 0); + const messages = cursorRequestMessagesFromRaw(parsed.context.messages); const activeText = [...messages].reverse().find(message => message.role === "user" || message.role === "developer")?.content ?? ""; const visibleTools = cursorToolsForActivePrompt(parsed.context.tools, activeText, parsed.options.toolChoice); const budget = applyCursorToolBudget(visibleTools, parsed.options.toolChoice); diff --git a/src/adapters/cursor/types.ts b/src/adapters/cursor/types.ts index c7b8d65a2d..cbc9a9f3f6 100644 --- a/src/adapters/cursor/types.ts +++ b/src/adapters/cursor/types.ts @@ -2,6 +2,7 @@ import type { OcxUsage } from "../../types"; import type { OcxMessage, OcxRequestOptions, OcxTool } from "../../types"; import type { CursorRoutingLevel } from "./discovery"; import type { CursorCheckpointInvalidationReason } from "./checkpoint-store"; +import type { ResolvedCursorImage } from "./images"; export interface CursorRequestedModelParameter { id: string; @@ -17,7 +18,13 @@ export interface CursorRunRequest { conversationId: string; system: string[]; messages: CursorRequestMessage[]; - rawMessages?: OcxMessage[]; + rawMessages?: readonly OcxMessage[]; + /** + * Images for the active user/developer turn. Encoded as SelectedImage blobIdWithData refs under + * UserMessage.selected_context (bytes live in the request-scoped KV store for getBlobArgs + * hydration). History stays text-only. data: URLs only in this slice. + */ + selectedImages?: readonly ResolvedCursorImage[]; tools?: OcxTool[]; toolChoice?: OcxRequestOptions["toolChoice"]; parallelToolCalls?: boolean; diff --git a/src/providers/registry.ts b/src/providers/registry.ts index 24e46c476f..f77004df96 100644 --- a/src/providers/registry.ts +++ b/src/providers/registry.ts @@ -10,6 +10,7 @@ import { MOONSHOT_BASE_URL_CHOICES, MOONSHOT_INTL_BASE_URL, } from "./base-url-choices"; import { + CURSOR_NO_VISION_MODELS, CURSOR_STATIC_MODELS, cursorModelContextWindows, cursorModelIds, @@ -994,11 +995,10 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [ // no-effort fallback to `kimi-k3-max` would never be reached. Mirrors the other K3 // routes (kimi, kimi-code, opencode-go). modelDefaultReasoningEfforts: { "kimi-k3": "max" }, - // Cursor's wire protocol never forwards image parts (request-builder emits an unsupported- - // content marker), so the vision sidecar covers ALL cursor models regardless of what the - // upstream model could natively do. Live-discovered models outside the static list fall back - // to the same marker until they appear here. - noVisionModels: cursorModelIds(CURSOR_STATIC_MODELS), + // Blind Cursor models (Auto routers, Composer, GLM-5.2) go through the vision sidecar; + // multimodal hosts (Claude/Gemini/GPT/Kimi/Grok) take native SelectedImage. The catalog + // still advertises image for noVision members so Codex can attach (sidecar option B). + noVisionModels: [...CURSOR_NO_VISION_MODELS], }, { id: "xai", diff --git a/tests/catalog-vision-sidecar-modalities.test.ts b/tests/catalog-vision-sidecar-modalities.test.ts index a9e4f1cd85..dd6d975283 100644 --- a/tests/catalog-vision-sidecar-modalities.test.ts +++ b/tests/catalog-vision-sidecar-modalities.test.ts @@ -5,6 +5,8 @@ import type { OcxProviderConfig } from "../src/types"; import { deriveComboCatalogModel } from "../src/codex/catalog"; import { PROVIDER_REGISTRY } from "../src/providers/registry"; import { enrichProviderFromRegistry } from "../src/providers/derive"; +import { CURSOR_NO_VISION_MODELS, CURSOR_STATIC_MODELS } from "../src/adapters/cursor/discovery"; +import { modelInList } from "../src/types"; import type { CatalogModel } from "../src/types"; const base: OcxProviderConfig = { @@ -257,3 +259,22 @@ describe("vision-capable provider models feed combo modalities", () => { expect(hinted.inputModalities).toEqual(["text", "image"]); }); }); + +describe("Cursor native vs sidecar vision registry", () => { + test("curates noVisionModels for Auto/Composer/GLM while advertising image for all static ids", () => { + const cursor = PROVIDER_REGISTRY.find(entry => entry.id === "cursor"); + expect(cursor?.noVisionModels).toEqual([...CURSOR_NO_VISION_MODELS]); + for (const model of ["auto", "composer-1", "composer-2.5", "composer-2.5-fast", "glm-5.2"]) { + expect(modelInList(cursor?.noVisionModels, model), `${model} should match noVision`).toBe(true); + } + for (const model of ["auto", "composer-2.5", "glm-5.2", "gpt-5.5", "gemini-3-pro", "grok-4.5", "kimi-k3"]) { + expect(cursor?.modelInputModalities?.[model]).toEqual(["text", "image"]); + } + for (const model of ["gpt-5.5", "gemini-3-pro", "grok-4.5", "kimi-k3"]) { + expect(modelInList(cursor?.noVisionModels, model)).toBe(false); + } + for (const model of CURSOR_STATIC_MODELS) { + expect(cursor?.modelInputModalities?.[model.id]).toEqual(["text", "image"]); + } + }); +}); diff --git a/tests/cursor-blob.test.ts b/tests/cursor-blob.test.ts index c4bdbd2e7b..f382348adc 100644 --- a/tests/cursor-blob.test.ts +++ b/tests/cursor-blob.test.ts @@ -47,6 +47,7 @@ import { GetBlobArgsSchema, KvServerMessageSchema, SetBlobArgsSchema, + UserMessageSchema, } from "../src/adapters/cursor/gen/agent_pb"; beforeEach(() => { @@ -125,6 +126,35 @@ function actionText(bytes: Uint8Array): string | undefined { return action?.case === "userMessageAction" ? action.value.userMessage?.text : undefined; } +/** Minimal valid 1×1 PNG for SelectedImage fixtures (not signature-only). */ +const PNG_1X1 = Uint8Array.from( + Buffer.from( + "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==", + "base64", + ), +); + +function activeUserMessage(bytes: Uint8Array) { + const msg = fromBinary(AgentClientMessageSchema, bytes); + const run = msg.message.case === "runRequest" ? msg.message.value : undefined; + const action = run?.action?.action; + return action?.case === "userMessageAction" ? action.value.userMessage : undefined; +} + +function activeSelectedImages(bytes: Uint8Array) { + return activeUserMessage(bytes)?.selectedContext?.selectedImages; +} + +function nativeTurnUserMessages(bytes: Uint8Array) { + const msg = fromBinary(AgentClientMessageSchema, bytes); + const run = msg.message.case === "runRequest" ? msg.message.value : undefined; + return (run?.conversationState?.turns ?? []).map(turnId => { + const turn = fromBinary(ConversationTurnStructureSchema, blobData(turnId)); + if (turn.turn.case !== "agentConversationTurn") return undefined; + return fromBinary(UserMessageSchema, blobData(turn.turn.value.userMessage)); + }).filter((message): message is NonNullable => message !== undefined); +} + /** The `toolName`s advertised in the top-level AgentRunRequest.mcp_tools channel (undefined when unset). */ function mcpToolNames(bytes: Uint8Array): string[] | undefined { const msg = fromBinary(AgentClientMessageSchema, bytes); @@ -140,6 +170,160 @@ describe("Cursor blob handshake", () => { expect(Array.from(id)).toEqual(Array.from(sha256(data))); }); + test("encodeCursorRunRequest attaches selectedContext with blobIdWithData image refs on the active user turn", () => { + const imageBytes = PNG_1X1; + const expectedBlobId = sha256(imageBytes); + const bytes = encodeCursorRunRequest({ + modelId: "claude-4.6-opus-high", + conversationId: "c1", + system: [], + messages: [{ role: "user", content: "see this" }], + selectedImages: [{ + data: imageBytes, + mimeType: "image/png", + uuid: "img-uuid-1", + }], + }); + + expect(actionText(bytes)).toBe("see this"); + const userMessage = activeUserMessage(bytes); + expect(userMessage?.mode).toBe(1); + expect(userMessage?.selectedContext).toBeDefined(); + const images = activeSelectedImages(bytes); + expect(images?.length).toBe(1); + expect(images?.[0]?.uuid).toBe("img-uuid-1"); + expect(images?.[0]?.mimeType).toBe("image/png"); + expect(images?.[0]?.path).toBe("attachment-img-uuid-1.png"); + expect(images?.[0]?.dataOrBlobId.case).toBe("blobIdWithData"); + const withData = images?.[0]?.dataOrBlobId.value as { blobId: Uint8Array; data: Uint8Array }; + expect(Array.from(withData.blobId)).toEqual(Array.from(expectedBlobId)); + expect(Array.from(withData.data)).toEqual(Array.from(imageBytes)); + expect(Array.from(blobData(expectedBlobId))).toEqual(Array.from(imageBytes)); + }); + + test("encodeCursorRunRequest always sends empty selectedContext and mode=1 on text-only turns", () => { + const bytes = encodeCursorRunRequest({ + modelId: "claude-4.6-opus-high", + conversationId: "c1", + system: [], + messages: [{ role: "user", content: "hi" }], + }); + + const userMessage = activeUserMessage(bytes); + expect(userMessage?.text).toBe("hi"); + expect(userMessage?.mode).toBe(1); + expect(userMessage?.selectedContext).toBeDefined(); + expect(userMessage?.selectedContext?.selectedImages.length).toBe(0); + }); + + test("encodeCursorRunRequest keeps selectedContext only on the active user turn", () => { + const activeImageBytes = PNG_1X1; + const bytes = encodeCursorRunRequest({ + modelId: "composer-2.5", + conversationId: "c1", + system: ["You are helpful."], + messages: [{ role: "user", content: "active turn" }], + rawMessages: [ + { + role: "user", + content: [ + { type: "text", text: "old turn" }, + { type: "image", imageUrl: "data:image/png;base64,old", detail: "auto" }, + ], + timestamp: 1, + }, + { + role: "assistant", + model: "cursor/composer-2.5", + content: [{ type: "text", text: "ack" }], + timestamp: 2, + }, + { role: "user", content: "active turn", timestamp: 3 }, + ], + selectedImages: [{ + data: activeImageBytes, + mimeType: "image/png", + uuid: "active-img", + }], + }); + + const roots = decodeRootMessages(bytes) as Array<{ role?: string; selectedContext?: unknown }>; + expect(roots.some(root => root.selectedContext !== undefined)).toBe(false); + + const historicalUser = nativeTurnUserMessages(bytes)[0]; + expect(historicalUser?.text).toBe("old turn"); + expect(historicalUser?.mode).toBe(1); + expect(historicalUser?.selectedContext).toBeDefined(); + expect(historicalUser?.selectedContext?.selectedImages.length).toBe(0); + + const activeMessage = activeUserMessage(bytes); + expect(activeMessage?.mode).toBe(1); + const images = activeSelectedImages(bytes); + expect(images?.length).toBe(1); + expect(images?.[0]?.uuid).toBe("active-img"); + }); + + test("encodeCursorRunRequest uses userMessageAction for image-only turns with selectedImages", () => { + const imageBytes = PNG_1X1; + const bytes = encodeCursorRunRequest({ + modelId: "claude-4.6-opus-high", + conversationId: "c1", + system: [], + messages: [{ role: "user", content: "" }], + rawMessages: [{ + role: "user", + content: [{ type: "image", imageUrl: "data:image/png;base64,abc", detail: "auto" }], + timestamp: 1, + }], + selectedImages: [{ + data: imageBytes, + mimeType: "image/png", + uuid: "image-only", + }], + }); + + expect(activeUserMessage(bytes)).toBeDefined(); + expect(actionText(bytes)).toBe(""); + expect(activeSelectedImages(bytes)?.length).toBe(1); + }); + + test("encodeCursorRunRequest uses userMessageAction for image-only turns after assistant reply", () => { + const imageBytes = PNG_1X1; + const bytes = encodeCursorRunRequest({ + modelId: "composer-2.5", + conversationId: "c1", + system: [], + messages: [ + { role: "user", content: "first" }, + { role: "assistant", content: "ack" }, + { role: "user", content: "" }, + ], + rawMessages: [ + { role: "user", content: "first", timestamp: 1 }, + { + role: "assistant", + model: "cursor/composer-2.5", + content: [{ type: "text", text: "ack" }], + timestamp: 2, + }, + { + role: "user", + content: [{ type: "image", imageUrl: "data:image/png;base64,abc", detail: "auto" }], + timestamp: 3, + }, + ], + selectedImages: [{ + data: imageBytes, + mimeType: "image/png", + uuid: "follow-up-image", + }], + }); + + expect(activeUserMessage(bytes)).toBeDefined(); + expect(actionText(bytes)).toBe(""); + expect(activeSelectedImages(bytes)?.length).toBe(1); + }); + test("encodeCursorRunRequest sends rootPromptMessagesJson as blob IDs, not inline JSON", () => { const bytes = encodeCursorRunRequest({ modelId: "claude-4.6-opus-high", diff --git a/tests/cursor-discovery.test.ts b/tests/cursor-discovery.test.ts index 9c0891beda..01953df36f 100644 --- a/tests/cursor-discovery.test.ts +++ b/tests/cursor-discovery.test.ts @@ -4,6 +4,7 @@ import { CURSOR_DEFAULT_CONTEXT_WINDOW, CURSOR_ROUTER_MODEL_IDS, CURSOR_ROUTING_LEVELS, + CURSOR_NO_VISION_MODELS, CURSOR_STATIC_MODELS, cursorCodexToWireModelId, cursorCheckpointModelAffinityId, @@ -22,6 +23,22 @@ import { } from "../src/adapters/cursor/discovery"; describe("Cursor discovery metadata", () => { + test("no-vision list is a curated explicit subset of the static seed", () => { + const ids = new Set(cursorModelIds(CURSOR_STATIC_MODELS)); + expect([...CURSOR_NO_VISION_MODELS]).toEqual([ + ...CURSOR_ROUTER_MODEL_IDS, + "composer-1", + "composer-2.5", + "composer-2.5-fast", + "glm-5.2", + ]); + for (const id of CURSOR_NO_VISION_MODELS) { + expect(ids.has(id), `${id} must be in the static Cursor seed`).toBe(true); + } + for (const id of ["grok-4.5", "grok-4.5-fast", "gpt-5.5", "claude-sonnet-5", "kimi-k3", "gemini-3-pro"]) { + expect(CURSOR_NO_VISION_MODELS as readonly string[]).not.toContain(id); + } + }); test("static seed includes Cursor's public model families plus the safe auto model", () => { const ids = cursorModelIds(CURSOR_STATIC_MODELS); diff --git a/tests/cursor-images.test.ts b/tests/cursor-images.test.ts new file mode 100644 index 0000000000..5f734157f3 --- /dev/null +++ b/tests/cursor-images.test.ts @@ -0,0 +1,574 @@ +import { describe, expect, test } from "bun:test"; +import { createHash } from "node:crypto"; +import { create, fromBinary } from "@bufbuild/protobuf"; +import { + CursorImageError, + CURSOR_VISION_IMAGE_OMITTED, + CURSOR_VISION_SOFT_MAX_BYTES, + CURSOR_VISION_SOFT_MAX_BYTES_HIGH, + MAX_CURSOR_IMAGE_BYTES, + MAX_CURSOR_IMAGE_DECODE_BYTES, + MAX_CURSOR_IMAGE_DECODE_EDGE, + MAX_CURSOR_IMAGE_PIXELS, + MAX_CURSOR_IMAGES, + buildSelectedImages, + cursorVisionPrepareStartIndex, + decodeCursorImageDataUrl, + prepareCursorImageForWire, + prepareCursorRawMessages, + resolveActiveCursorImages, + resolveCursorImages, + sniffCursorImageDimensions, + sniffCursorImageFormat, +} from "../src/adapters/cursor/images"; +import { + handleCursorNativeKv, + resetCursorBlobStateForTests, +} from "../src/adapters/cursor/native-exec"; +import { cursorRequestMessagesFromRaw } from "../src/adapters/cursor/request-builder"; +import { activePromptText, encodeCursorRunRequest } from "../src/adapters/cursor/protobuf-request"; +import { + AgentClientMessageSchema, + GetBlobArgsSchema, + KvServerMessageSchema, +} from "../src/adapters/cursor/gen/agent_pb"; + +/** Minimal valid 1×1 PNG (real IHDR; not a signature-only stub). */ +const PNG_BYTES = Uint8Array.from( + Buffer.from( + "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==", + "base64", + ), +); +const PNG_DATA_URL = `data:image/png;base64,${Buffer.from(PNG_BYTES).toString("base64")}`; + +async function oversizedDecodablePng(): Promise { + const pngPath = new URL("./helpers/cursor-grumpy-fixture.png", import.meta.url); + const src = new Uint8Array(await Bun.file(pngPath).arrayBuffer()); + return new Uint8Array(await new Bun.Image(src).resize(2400, 2400).png().bytes()); +} + +describe("Cursor image resolver", () => { + test("rejects more than MAX_CURSOR_IMAGES in one request", async () => { + const urls = Array.from({ length: MAX_CURSOR_IMAGES + 1 }, () => PNG_DATA_URL); + await expect(resolveCursorImages(urls)).rejects.toMatchObject({ + name: "CursorImageError", + message: `Too many images in one request (max ${MAX_CURSOR_IMAGES}).`, + }); + }); + + test("omits data URLs above the inbound decode bomb ceiling", async () => { + const oversized = "A".repeat(Math.ceil((MAX_CURSOR_IMAGE_DECODE_BYTES + 1) * 4 / 3)); + // Soft-omit: one bad URL must not abort a mixed turn. + const resolved = await resolveCursorImages([`data:image/png;base64,${oversized}`]); + expect(resolved).toEqual([]); + }); + + test("prep-before-cap accepts PNG over 1 MiB that JPEG-encodes under the soft and wire caps", async () => { + const png = await oversizedDecodablePng(); + expect(png.byteLength).toBeGreaterThan(MAX_CURSOR_IMAGE_BYTES); + const url = `data:image/png;base64,${Buffer.from(png).toString("base64")}`; + const resolved = await resolveCursorImages([url]); + expect(resolved).toHaveLength(1); + expect(resolved[0]?.mimeType).toBe("image/jpeg"); + expect(resolved[0]!.data.byteLength).toBeLessThan(png.byteLength); + expect(resolved[0]!.data.byteLength).toBeLessThanOrEqual(CURSOR_VISION_SOFT_MAX_BYTES); + expect(resolved[0]!.data.byteLength).toBeLessThanOrEqual(MAX_CURSOR_IMAGE_BYTES); + }); + + test("omits undecodable payloads under the decode ceiling instead of sending them", async () => { + const junk = "A".repeat(Math.ceil((MAX_CURSOR_IMAGE_BYTES + 1) * 4 / 3)); + // Pad to valid base64 length so alphabet/padding checks pass and Bun decode fails. + const padded = junk + "=".repeat((4 - (junk.length % 4)) % 4); + const resolved = await resolveCursorImages([`data:image/png;base64,${padded}`]); + expect(resolved).toEqual([]); + }); + + test("decodes valid base64 data URLs through JPEG prep", async () => { + const resolved = await resolveCursorImages([PNG_DATA_URL]); + expect(resolved).toHaveLength(1); + expect(resolved[0]?.mimeType).toBe("image/jpeg"); + expect(resolved[0]!.data.byteLength).toBeGreaterThan(0); + expect(resolved[0]!.data[0]).toBe(0xff); + expect(resolved[0]!.data[1]).toBe(0xd8); + expect(resolved[0]?.uuid.length).toBeGreaterThan(0); + }); + + test("soft-omits malformed and non-image data URLs", async () => { + expect(await resolveCursorImages(["data:image/png,not-base64"])).toEqual([]); + expect(await resolveCursorImages(["data:text/plain;base64,YQ=="])).toEqual([]); + expect(await resolveCursorImages(["data:image/png;base64"])).toEqual([]); + expect(await resolveCursorImages(["data:image/png;base64,"])).toEqual([]); + }); + + test("omits remote URLs — this slice is data: only", async () => { + expect(await resolveCursorImages(["http://example.com/image.png"])).toEqual([]); + expect(await resolveCursorImages(["https://example.com/image.png"])).toEqual([]); + }); + + test("resolveActiveCursorImages selects the last user turn and ignores earlier images", async () => { + const resolved = await resolveActiveCursorImages([ + { + role: "user", + content: [{ type: "image", imageUrl: PNG_DATA_URL }], + timestamp: 1, + }, + { + role: "assistant", + model: "cursor/auto", + content: [{ type: "text", text: "seen" }], + timestamp: 2, + }, + { + role: "user", + content: [ + { type: "text", text: "active" }, + { type: "image", imageUrl: PNG_DATA_URL }, + ], + timestamp: 3, + }, + ]); + expect(resolved).toHaveLength(1); + expect(resolved[0]?.mimeType).toBe("image/jpeg"); + }); + + test("resolveActiveCursorImages supports developer turns", async () => { + const resolved = await resolveActiveCursorImages([ + { + role: "developer", + content: [{ type: "image", imageUrl: PNG_DATA_URL }], + timestamp: 1, + }, + ]); + expect(resolved).toHaveLength(1); + }); + + test("resolveActiveCursorImages returns empty for text-only trailing toolResult", async () => { + const resolved = await resolveActiveCursorImages([ + { + role: "user", + content: [{ type: "image", imageUrl: PNG_DATA_URL }], + timestamp: 1, + }, + { + role: "toolResult", + toolCallId: "call-1", + toolName: "read_file", + content: "done", + isError: false, + timestamp: 2, + }, + ]); + expect(resolved).toEqual([]); + }); + + test("user message after toolResult does not promote stale tool images", async () => { + const resolved = await resolveActiveCursorImages([ + { role: "user", content: "first", timestamp: 1 }, + { + role: "toolResult", + toolCallId: "call_view", + toolName: "view_image", + content: [{ type: "image", imageUrl: PNG_DATA_URL }], + isError: false, + timestamp: 2, + }, + { role: "user", content: "new question without an image", timestamp: 3 }, + ]); + expect(resolved).toEqual([]); + }); + + test("CursorImageError carries HTTP status for callers", () => { + const error = new CursorImageError("blocked", 403); + expect(error.status).toBe(403); + expect(error.name).toBe("CursorImageError"); + }); + + test("buildSelectedImages uses blobIdWithData + attachment path and keeps KV hydrated", () => { + resetCursorBlobStateForTests(); + // Minimal PNG signature + IHDR claiming 2x3 (not Bun-decodable — stays PNG) + const png = Uint8Array.from([ + 137, 80, 78, 71, 13, 10, 26, 10, + 0, 0, 0, 13, 73, 72, 68, 82, + 0, 0, 0, 2, 0, 0, 0, 3, + 8, 2, 0, 0, 0, 0, 0, 0, 0, + ]); + expect(sniffCursorImageDimensions(png)).toEqual({ width: 2, height: 3 }); + + // Standalone RST0 before SOF0 must not be parsed as a length-bearing segment. + const jpegWithRst = Uint8Array.from([ + 0xff, 0xd8, // SOI + 0xff, 0xd0, // RST0 (no length) + 0xff, 0xc0, 0x00, 0x0b, 0x08, 0x00, 0x03, 0x00, 0x02, 0x03, 0x01, 0x11, 0x00, // SOF0 2x3 + ]); + expect(sniffCursorImageDimensions(jpegWithRst)).toEqual({ width: 2, height: 3 }); + + const [selected] = buildSelectedImages([{ + data: png, + mimeType: "image/png", + uuid: "u-dim", + }]); + expect(selected?.dataOrBlobId.case).toBe("blobIdWithData"); + expect(selected?.path).toBe("attachment-u-dim.png"); + expect(selected?.dimension?.width).toBe(2); + expect(selected?.dimension?.height).toBe(3); + const withData = selected!.dataOrBlobId.value as { blobId: Uint8Array; data: Uint8Array }; + expect(Array.from(withData.blobId)).toEqual(Array.from(createHash("sha256").update(png).digest())); + expect(Array.from(withData.data)).toEqual(Array.from(png)); + + const reply = fromBinary(AgentClientMessageSchema, handleCursorNativeKv(create(KvServerMessageSchema, { + id: 1, + message: { case: "getBlobArgs", value: create(GetBlobArgsSchema, { blobId: withData.blobId }) }, + }))); + const kv = reply.message.case === "kvClientMessage" ? reply.message.value : undefined; + const data = kv?.message.case === "getBlobResult" ? kv.message.value.blobData : undefined; + expect(Array.from(data ?? [])).toEqual(Array.from(png)); + }); + + test("prepareCursorImageForWire re-encodes large PNG as JPEG under the soft cap", async () => { + const pngPath = new URL("./helpers/cursor-grumpy-fixture.png", import.meta.url); + const png = new Uint8Array(await Bun.file(pngPath).arrayBuffer()); + expect(png.byteLength).toBeGreaterThan(CURSOR_VISION_SOFT_MAX_BYTES); + + const prepared = await prepareCursorImageForWire({ + data: png, + mimeType: "image/png", + uuid: "big-png", + }); + expect(prepared.status).toBe("ready"); + if (prepared.status !== "ready") throw new Error("expected ready"); + expect(prepared.image.mimeType).toBe("image/jpeg"); + expect(prepared.image.data.byteLength).toBeLessThan(png.byteLength); + expect(prepared.image.data.byteLength).toBeLessThanOrEqual(CURSOR_VISION_SOFT_MAX_BYTES); + expect(prepared.image.data[0]).toBe(0xff); + expect(prepared.image.data[1]).toBe(0xd8); + }); + + test("detail original/high uses a higher soft tier than auto", async () => { + const pngPath = new URL("./helpers/cursor-grumpy-fixture.png", import.meta.url); + const png = new Uint8Array(await Bun.file(pngPath).arrayBuffer()); + const auto = await prepareCursorImageForWire({ + data: png, + mimeType: "image/png", + uuid: "auto", + detail: "auto", + }); + const original = await prepareCursorImageForWire({ + data: png, + mimeType: "image/png", + uuid: "original", + detail: "original", + }); + expect(auto.status).toBe("ready"); + expect(original.status).toBe("ready"); + if (auto.status !== "ready" || original.status !== "ready") throw new Error("expected ready"); + expect(original.image.data.byteLength).toBeGreaterThan(auto.image.data.byteLength); + expect(auto.image.data.byteLength).toBeLessThanOrEqual(CURSOR_VISION_SOFT_MAX_BYTES); + expect(original.image.data.byteLength).toBeLessThanOrEqual(CURSOR_VISION_SOFT_MAX_BYTES_HIGH); + expect(original.image.data.byteLength).toBeLessThanOrEqual(MAX_CURSOR_IMAGE_BYTES); + }); + + test("exotic MIME and corrupt PNG fail closed", async () => { + const bmp = await prepareCursorImageForWire({ + data: new Uint8Array([0x42, 0x4d, 0, 0, 0, 0]), + mimeType: "image/bmp", + uuid: "bmp", + }); + expect(bmp).toEqual({ status: "omitted", reason: CURSOR_VISION_IMAGE_OMITTED }); + + const corrupt = await prepareCursorImageForWire({ + data: new Uint8Array(128).fill(0x41), + mimeType: "image/png", + uuid: "corrupt", + }); + expect(corrupt).toEqual({ status: "omitted", reason: CURSOR_VISION_IMAGE_OMITTED }); + + // Soft-cap-sized labeled JPEG must still decode; junk under the soft max is omitted. + const fakeJpeg = await prepareCursorImageForWire({ + data: new Uint8Array(128).fill(0xff), + mimeType: "image/jpeg", + uuid: "fake-jpeg", + }); + expect(fakeJpeg).toEqual({ status: "omitted", reason: CURSOR_VISION_IMAGE_OMITTED }); + }); + + test("prepareCursorRawMessages JPEG-preps active-turn user data URLs", async () => { + const pngPath = new URL("./helpers/cursor-grumpy-fixture.png", import.meta.url); + const png = new Uint8Array(await Bun.file(pngPath).arrayBuffer()); + const imageUrl = `data:image/png;base64,${Buffer.from(png).toString("base64")}`; + const prepared = await prepareCursorRawMessages([ + { + role: "user", + content: [ + { type: "text", text: "describe" }, + { type: "image", imageUrl, detail: "auto" }, + ], + timestamp: 1, + }, + ]); + const user = prepared?.[0]; + expect(user?.role).toBe("user"); + if (user?.role !== "user" || typeof user.content === "string") throw new Error("expected image parts"); + const part = user.content.find(item => item.type === "image"); + expect(part?.type).toBe("image"); + if (part?.type !== "image") throw new Error("expected image"); + expect(part.imageUrl.startsWith("data:image/jpeg;base64,")).toBe(true); + const payload = part.imageUrl.slice(part.imageUrl.indexOf(",") + 1); + const bytes = Buffer.from(payload, "base64"); + expect(bytes.byteLength).toBeLessThanOrEqual(CURSOR_VISION_SOFT_MAX_BYTES); + expect(bytes[0]).toBe(0xff); + expect(bytes[1]).toBe(0xd8); + }); + + test("prepareCursorRawMessages replaces exotic images with omission text", async () => { + const bmpUrl = `data:image/bmp;base64,${Buffer.from([0x42, 0x4d, 0, 0]).toString("base64")}`; + const prepared = await prepareCursorRawMessages([ + { + role: "user", + content: [{ type: "image", imageUrl: bmpUrl }], + timestamp: 1, + }, + ]); + const user = prepared?.[0]; + expect(user?.role).toBe("user"); + if (user?.role !== "user" || typeof user.content === "string") throw new Error("expected parts"); + expect(user.content).toEqual([{ type: "text", text: CURSOR_VISION_IMAGE_OMITTED }]); + }); + + test("cursorRequestMessagesFromRaw surfaces omission text after prepare", async () => { + const bmpUrl = `data:image/bmp;base64,${Buffer.from([0x42, 0x4d, 0, 0]).toString("base64")}`; + const raw = await prepareCursorRawMessages([ + { + role: "user", + content: [{ type: "image", imageUrl: bmpUrl }], + timestamp: 1, + }, + ]); + const messages = cursorRequestMessagesFromRaw(raw); + expect(messages).toEqual([{ role: "user", content: CURSOR_VISION_IMAGE_OMITTED }]); + expect(activePromptText({ + modelId: "grok-4.5", + conversationId: "cursor_test", + system: [], + messages, + rawMessages: raw, + })).toBe(CURSOR_VISION_IMAGE_OMITTED); + }); + + test("live-transport image phase: prepare rawMessages then resolve SelectedImage", async () => { + // Mirrors live-transport.ts: prepareCursorRawMessages → resolveActiveCursorImages. + const rawIn = [ + { + role: "user" as const, + content: [ + { type: "text" as const, text: "What is in this image?" }, + { type: "image" as const, imageUrl: PNG_DATA_URL, detail: "high" }, + ], + timestamp: 1, + }, + ]; + const rawMessages = await prepareCursorRawMessages(rawIn); + const messages = cursorRequestMessagesFromRaw(rawMessages); + const selectedImages = await resolveActiveCursorImages(rawMessages); + expect(selectedImages).toHaveLength(1); + + resetCursorBlobStateForTests(); + const bytes = encodeCursorRunRequest({ + modelId: "grok-4.5", + conversationId: "c-wire", + system: ["You are helpful."], + messages, + rawMessages, + selectedImages, + }); + const msg = fromBinary(AgentClientMessageSchema, bytes); + const run = msg.message.case === "runRequest" ? msg.message.value : undefined; + expect(run?.action?.action.case).toBe("userMessageAction"); + if (run?.action?.action.case !== "userMessageAction") throw new Error("expected userMessageAction"); + expect(run.action.action.value.userMessage?.text).toContain("What is in this image?"); + expect(run.action.action.value.userMessage?.selectedContext?.selectedImages.length).toBe(1); + }); + + test("image-only remote soft-omit yields userMessageAction with omission text", async () => { + const raw = await prepareCursorRawMessages([ + { + role: "user", + content: [{ type: "image", imageUrl: "https://example.com/missing.png" }], + timestamp: 1, + }, + ]); + const messages = cursorRequestMessagesFromRaw(raw); + expect(messages).toEqual([{ role: "user", content: CURSOR_VISION_IMAGE_OMITTED }]); + const selectedImages = await resolveActiveCursorImages(raw); + expect(selectedImages).toEqual([]); + resetCursorBlobStateForTests(); + const bytes = encodeCursorRunRequest({ + modelId: "grok-4.5", + conversationId: "c-https-omit", + system: [], + messages, + rawMessages: raw, + selectedImages, + }); + const msg = fromBinary(AgentClientMessageSchema, bytes); + const run = msg.message.case === "runRequest" ? msg.message.value : undefined; + expect(run?.action?.action.case).toBe("userMessageAction"); + expect(actionTextFrom(bytes)).toBe(CURSOR_VISION_IMAGE_OMITTED); + }); + + test("remote image with valid text continues text-only", async () => { + const raw = await prepareCursorRawMessages([ + { + role: "user", + content: [ + { type: "text", text: "what color is the sky?" }, + { type: "image", imageUrl: "https://example.com/missing.png" }, + ], + timestamp: 1, + }, + ]); + const messages = cursorRequestMessagesFromRaw(raw); + expect(typeof messages[0]?.content).toBe("string"); + expect(messages[0]?.content).toContain("what color is the sky?"); + expect(messages[0]?.content).toContain(CURSOR_VISION_IMAGE_OMITTED); + expect(await resolveActiveCursorImages(raw)).toEqual([]); + }); + + test("strict base64 rejects truncated and wrong-alphabet payloads", () => { + expect(() => decodeCursorImageDataUrl("data:image/png;base64,iVBOR")).toThrow(CursorImageError); + expect(() => decodeCursorImageDataUrl("data:image/png;base64,!!!!")).toThrow(CursorImageError); + // Signature-only 8-byte stub is valid base64 but must not bypass prepare (no ≤64 passthrough). + const stubUrl = `data:image/png;base64,${Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]).toString("base64")}`; + const decoded = decodeCursorImageDataUrl(stubUrl); + expect(decoded.data.byteLength).toBe(8); + }); + + test("signature-only PNG stub is omitted by prepare (no ≤64 bypass)", async () => { + const outcome = await prepareCursorImageForWire({ + data: new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10]), + mimeType: "image/png", + uuid: "stub", + }); + expect(outcome).toEqual({ status: "omitted", reason: CURSOR_VISION_IMAGE_OMITTED }); + }); + + test("oversize sniffed dimensions omit without Bun decode bomb", async () => { + // PNG IHDR with absurd width/height; sniff rejects before Bun.Image. + const ihdr = new Uint8Array([ + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, + 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, + 0x00, 0x01, 0x00, 0x00, // width 65536 + 0x00, 0x01, 0x00, 0x00, // height 65536 + ]); + expect(sniffCursorImageDimensions(ihdr)).toEqual({ width: 65536, height: 65536 }); + expect(65536).toBeGreaterThan(MAX_CURSOR_IMAGE_DECODE_EDGE); + expect(65536 * 65536).toBeGreaterThan(MAX_CURSOR_IMAGE_PIXELS); + const outcome = await prepareCursorImageForWire({ + data: ihdr, + mimeType: "image/png", + uuid: "huge", + }); + expect(outcome).toEqual({ status: "omitted", reason: CURSOR_VISION_IMAGE_OMITTED }); + }); + + test("truncated FF D8 JPEG under soft cap is omitted (no SOI-only fast path)", async () => { + const truncated = new Uint8Array([0xff, 0xd8, 0x00, 0x00]); + expect(sniffCursorImageFormat(truncated)).toBe("jpeg"); + expect(sniffCursorImageDimensions(truncated)).toBeUndefined(); + const outcome = await prepareCursorImageForWire({ + data: truncated, + mimeType: "image/jpeg", + uuid: "soi-only", + }); + expect(outcome).toEqual({ status: "omitted", reason: CURSOR_VISION_IMAGE_OMITTED }); + }); + + test("PNG bytes labeled image/jpeg are re-encoded as JPEG, not passthrough", async () => { + const outcome = await prepareCursorImageForWire({ + data: PNG_BYTES, + mimeType: "image/jpeg", + uuid: "mislabeled", + }); + expect(outcome.status).toBe("ready"); + if (outcome.status !== "ready") throw new Error("expected ready"); + expect(outcome.image.mimeType).toBe("image/jpeg"); + expect(outcome.image.data[0]).toBe(0xff); + expect(outcome.image.data[1]).toBe(0xd8); + expect(sniffCursorImageFormat(outcome.image.data)).toBe("jpeg"); + }); + + test("oversized WebP VP8X header omits before Bun decode", async () => { + // RIFF....WEBP + VP8X with canvas size 65536x65536 (stored as size-1). + const webp = new Uint8Array(30); + webp.set([0x52, 0x49, 0x46, 0x46], 0); // RIFF + webp.set([0x57, 0x45, 0x42, 0x50], 8); // WEBP + webp.set([0x56, 0x50, 0x38, 0x58], 12); // VP8X + // width-1 / height-1 as 24-bit LE at 24..29 → 65535 → displayed 65536 + webp[24] = 0xff; + webp[25] = 0xff; + webp[26] = 0x00; + webp[27] = 0xff; + webp[28] = 0xff; + webp[29] = 0x00; + expect(sniffCursorImageFormat(webp)).toBe("webp"); + expect(sniffCursorImageDimensions(webp)).toEqual({ width: 65536, height: 65536 }); + const outcome = await prepareCursorImageForWire({ + data: webp, + mimeType: "image/webp", + uuid: "huge-webp", + }); + expect(outcome).toEqual({ status: "omitted", reason: CURSOR_VISION_IMAGE_OMITTED }); + }); + + test("prepareCursorRawMessages leaves historical images untouched on a later user turn", async () => { + const oldUrl = `data:image/png;base64,${Buffer.from([...PNG_BYTES, 1]).toString("base64")}`; + const prepared = await prepareCursorRawMessages([ + { + role: "user", + content: [{ type: "image", imageUrl: oldUrl }], + timestamp: 1, + }, + { + role: "assistant", + model: "cursor/grok-4.5", + content: [{ type: "text", text: "seen" }], + timestamp: 2, + }, + { role: "user", content: "thanks, no image", timestamp: 3 }, + ]); + expect(prepared?.[0]).toEqual({ + role: "user", + content: [{ type: "image", imageUrl: oldUrl }], + timestamp: 1, + }); + expect(cursorVisionPrepareStartIndex(prepared ?? [])).toBe(2); + }); + + test("aborted image-phase signal stops further local prepare work", async () => { + const controller = new AbortController(); + controller.abort(); + await expect(prepareCursorImageForWire({ + data: PNG_BYTES, + mimeType: "image/png", + uuid: "aborted", + }, controller.signal)).rejects.toMatchObject({ name: "AbortError" }); + + await expect(prepareCursorRawMessages([ + { + role: "user", + content: [ + { type: "image", imageUrl: PNG_DATA_URL }, + { type: "image", imageUrl: PNG_DATA_URL }, + ], + timestamp: 1, + }, + ], controller.signal)).rejects.toMatchObject({ name: "AbortError" }); + }); +}); + +function actionTextFrom(bytes: Uint8Array): string | undefined { + const msg = fromBinary(AgentClientMessageSchema, bytes); + const run = msg.message.case === "runRequest" ? msg.message.value : undefined; + const action = run?.action?.action; + return action?.case === "userMessageAction" ? action.value.userMessage?.text : undefined; +} diff --git a/tests/cursor-request-builder.test.ts b/tests/cursor-request-builder.test.ts index 6820ebc048..21548e26f4 100644 --- a/tests/cursor-request-builder.test.ts +++ b/tests/cursor-request-builder.test.ts @@ -302,7 +302,7 @@ describe("Cursor request builder", () => { ]); }); - test("uses an explicit image placeholder for unsupported image parts", () => { + test("omits image parts from text — they ride SelectedImage, not markers", () => { const request = createCursorRequest({ ...base, context: { @@ -320,13 +320,58 @@ describe("Cursor request builder", () => { }); expect(request.messages[0]?.content).toContain("see"); - // A USER-message image is still flattened here (this path builds the plain-text prompt). - // The tool-result ENCODER does build real McpImageContent, so the placeholder no longer - // claims the encoder as a whole is unable to send images. (Neither kind reaches Cursor in - // production today: every Cursor model is in noVisionModels, so the vision sidecar runs - // first — see devlog/_plan/260817_cursor_toolcall_decode/020_*.md.) - expect(request.messages[0]?.content).toContain("image omitted from this Cursor text prompt"); - expect(request.messages[0]?.content).toContain("high"); + expect(request.messages[0]?.content).not.toContain("image input unsupported"); + expect(request.messages[0]?.content).not.toContain("data:image/png"); + }); + + test("preserves image-only user turns as empty-string active messages", () => { + const request = createCursorRequest({ + ...base, + context: { + messages: [ + { + role: "user", + content: [{ type: "image", imageUrl: "data:image/png;base64,abc", detail: "high" }], + timestamp: 1, + }, + ], + }, + }); + + expect(request.messages).toEqual([{ role: "user", content: "" }]); + expect(request.rawMessages?.length).toBe(1); + }); + + test("preserves image-only active user turn after assistant reply", () => { + const request = createCursorRequest({ + ...base, + context: { + messages: [ + { + role: "user", + content: [{ type: "image", imageUrl: "data:image/png;base64,abc", detail: "high" }], + timestamp: 1, + }, + { + role: "assistant", + model: "cursor/composer-2.5", + content: [{ type: "text", text: "ack" }], + timestamp: 2, + }, + { + role: "user", + content: [{ type: "image", imageUrl: "data:image/png;base64,def", detail: "high" }], + timestamp: 3, + }, + ], + }, + }); + + expect(request.messages).toEqual([ + { role: "user", content: "" }, + { role: "assistant", content: "ack" }, + { role: "user", content: "" }, + ]); }); test("preserves Responses tools and tool choice for Cursor request context", () => { diff --git a/tests/cursor-static-catalog.test.ts b/tests/cursor-static-catalog.test.ts index 4dbd772e86..fa8be304f3 100644 --- a/tests/cursor-static-catalog.test.ts +++ b/tests/cursor-static-catalog.test.ts @@ -111,5 +111,12 @@ describe("Cursor static Codex catalog", () => { ]); expect(entries.find(item => item.slug === "cursor/glm-5.2")?.supported_reasoning_levels) .toMatchObject([{ effort: "high" }, { effort: "max" }, { effort: "ultra" }]); + + for (const modelId of ["auto", "composer-2.5", "gpt-5.5", "gemini-3-pro"]) { + expect( + entries.find(item => item.slug === `cursor/${modelId}`)?.input_modalities, + `cursor/${modelId} should advertise image input`, + ).toEqual(["text", "image"]); + } }); }); diff --git a/tests/cursor-vision-wire-harness.test.ts b/tests/cursor-vision-wire-harness.test.ts new file mode 100644 index 0000000000..a01ae1cdde --- /dev/null +++ b/tests/cursor-vision-wire-harness.test.ts @@ -0,0 +1,103 @@ +import { describe, expect, test } from "bun:test"; +import { fromBinary } from "@bufbuild/protobuf"; +import { encodeCursorRunRequest } from "../src/adapters/cursor/protobuf-request"; +import { + AgentClientMessageSchema, + ConversationStepSchema, + ConversationTurnStructureSchema, +} from "../src/adapters/cursor/gen/agent_pb"; +import { handleCursorNativeKv, resetCursorBlobStateForTests } from "../src/adapters/cursor/native-exec"; +import { GetBlobArgsSchema, KvServerMessageSchema } from "../src/adapters/cursor/gen/agent_pb"; +import { create } from "@bufbuild/protobuf"; + +function blobData(blobId: Uint8Array): Uint8Array { + const reply = fromBinary(AgentClientMessageSchema, handleCursorNativeKv(create(KvServerMessageSchema, { + id: 1, + message: { case: "getBlobArgs", value: create(GetBlobArgsSchema, { blobId }) }, + }))); + const kv = reply.message.case === "kvClientMessage" ? reply.message.value : undefined; + const result = kv?.message.case === "getBlobResult" ? kv.message.value.blobData : undefined; + if (!result) throw new Error("missing blob data"); + return result; +} + +function activeSelectedImageBytes(bytes: Uint8Array): Uint8Array | undefined { + const msg = fromBinary(AgentClientMessageSchema, bytes); + const run = msg.message.case === "runRequest" ? msg.message.value : undefined; + const action = run?.action?.action; + const image = action?.case === "userMessageAction" + ? action.value.userMessage?.selectedContext?.selectedImages[0] + : undefined; + if (!image) return undefined; + if (image.dataOrBlobId.case === "data") return image.dataOrBlobId.value; + if (image.dataOrBlobId.case === "blobId") return blobData(image.dataOrBlobId.value); + if (image.dataOrBlobId.case === "blobIdWithData") return image.dataOrBlobId.value.data; + return undefined; +} + +function anyMcpImageContent(bytes: Uint8Array): boolean { + const msg = fromBinary(AgentClientMessageSchema, bytes); + const run = msg.message.case === "runRequest" ? msg.message.value : undefined; + for (const turnId of run?.conversationState?.turns ?? []) { + const turn = fromBinary(ConversationTurnStructureSchema, blobData(turnId)); + if (turn.turn.case !== "agentConversationTurn") continue; + for (const stepId of turn.turn.value.steps) { + const step = fromBinary(ConversationStepSchema, blobData(stepId)); + if (step.message.case !== "toolCall") continue; + const tool = step.message.value.tool; + if (tool.case !== "mcpToolCall") continue; + const result = tool.value.result?.result; + if (result?.case !== "success") continue; + for (const item of result.value.content) { + if (item.content.case === "image") return true; + } + } + } + return false; +} + +describe("Cursor vision wire harness", () => { + test("grok attach keeps non-empty PNG bytes on the wire; tool-result images stay text-only", () => { + resetCursorBlobStateForTests(); + const imageBytes = new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13]); + const imageUrl = `data:image/png;base64,${Buffer.from(imageBytes).toString("base64")}`; + + const attachBytes = encodeCursorRunRequest({ + modelId: "grok-4.5", + conversationId: "c1", + system: [], + messages: [{ role: "user", content: "see this" }], + selectedImages: [{ uuid: "img-uuid-1", mimeType: "image/png", data: imageBytes }], + }); + const attachWireBytes = activeSelectedImageBytes(attachBytes); + expect(attachWireBytes).toBeDefined(); + expect(attachWireBytes!.byteLength).toBeGreaterThan(0); + expect(Array.from(attachWireBytes!.slice(0, 4))).toEqual([137, 80, 78, 71]); + + const viewBytes = encodeCursorRunRequest({ + modelId: "grok-4.5", + conversationId: "c1", + system: ["You are helpful."], + messages: [{ role: "tool", content: "[tool_result]\ncall_id: call_view\nname: view_image\nis_error: false\noutput:" }], + rawMessages: [ + { role: "user", content: "describe the image", timestamp: 1 }, + { + role: "assistant", + model: "cursor/grok-4.5", + timestamp: 2, + content: [{ type: "toolCall", id: "call_view", name: "view_image", arguments: { path: "/tmp/x.png" } }], + }, + { + role: "toolResult", + toolCallId: "call_view", + toolName: "view_image", + content: [{ type: "image", imageUrl, detail: "auto" }], + isError: false, + timestamp: 3, + }, + ], + }); + // Tool-result image promotion is out of scope in this slice: no McpImageContent on the wire. + expect(anyMcpImageContent(viewBytes)).toBe(false); + }); +}); diff --git a/tests/helpers/cursor-grumpy-fixture.png b/tests/helpers/cursor-grumpy-fixture.png new file mode 100644 index 0000000000000000000000000000000000000000..a06cdc84a2491b7289866dd884f5f6fa1034f8c7 GIT binary patch literal 440734 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

hvddan4-@|<@; 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%0DWZrohfWhFLCA2Z6rPx0H~v(h6!B} zKC-T#qbhyv-gqp$`aKe|h}q_ z;-0~(_e^AOH2ROZTxaDLeK0fA&m%MGtcL*|)q3UGlbs8#j&^flB@15;cDHSxxgf^s z*~Fb~AhFu1r(goJ(~11!nx4LRUfzHIR)!#Z#>KcjpJfcJv+iexqi_om*NHWDUDB`si;#r@+=VOk%d1WaDGsQ2inJs(Zyd-(BsyM) z6UXrIcdJCXMF$Q9jw`%@8S2%9kR&#;-f+4+A2M|Ag@$UV#jB^9CeP0bTCAxIz#*fB zT44myv!e-S1RUuowa&()a@aVCfsQ3IR%%aTBI%4@UVdc{&Kq&1S(&_Ge5-+Cm>Xoin*#fYEEiPS9?hb`;*Yzb4Z{CX}wl z)Y-D^W{%3;+nM7`SCkKMlF^EmCASlzHy{#HBxBuPlJZJ3Ce^QhxVvu%SlGTq_lyWQ z@fz$r>PM|?PoAiS?e6^t^`FnDF0t{R-1`~8Cn8b%o7&d4wzcgVY7kZtZP~|`WtMF` zgQ&&y%y>VY7b2}`AXNGj5>t{zNQ^Gq<_vprVHDIj$Y7QPb@^0o`#5o}T6rJ&;$F1K z%VpAOyJJ*0eM^1Kbz;=k;X8fj+F!Bk>pt|ZLsy-r`VyZbh0UXJU!;;;(si3!w3qN- zh%YsjAMMG!D5*q8gl5B-t9x9 zfH!AxMb_YnNKYQ0-%1-*RtOc%lKz4NLux#J_5;;@WOfsNKVXX#`x zHdHyi&nQH)+|6`HcGInCv+1(zmVmBwE-dAMaf;(0Rbfcwh{;-quB8E`svZfXI-iHJ zWOLfV%;xh(8(kYVOG^!`>-#;54Gs8!;Z_zxpn~3ie^BPYspaUb949cdx|;}aGjkUZ zx;fC>E;1l(T$3_p7>tON&IXu_XIWP}`qrqqPo1@zed97M zHOYOL9Q+(`gmf<00DJ#%UO4yLhm{!bdlVRf!$X!(`$iJK$;M8j9Qy%OPOy6Xt|M?I zGG8n z2<6GLF^ZC1FWIZUM@lz43lv-$1-ZSu(|vt%bE7e--wcLw=2lRcSd!ujbDLVA>C{mus;e&WZ9{5*&Tbmu02PwbHIDf1Yht(*cmA zxW>6wjy4@yBQsa^Z(e>t-MjuV<2ql{h4#CVR~?o4zb*9OMcyi)ndNQ)d-oyRY37$A z@DLz)?3|lSKV}Z+XFZmscbWT_)7OwHl?Y^fPR#FZ;J4_H$0!Oi+Lv-**nv0Cbn3d) z=Co05wT8Y>n3EFR(AjZI9E(WLN}()w6uI3V%YNcDfdk$4c4a+p?@;Oh;?lU`##P0hY6%adRFrh#|FE_v0(W9`w~-Ms1s6R0#o!DL>5r0dqQT({V>16j0#W{siYkbB3N!Hk13FFTN|Fb&ZZL5O~b3- z;W!?xe};`Ybu!f;h-5IXw%44#?LvGbV#Qummc4Ihg%j`yp`lA)Jk}&MjosDo6ap_J zd1=>JKim%jNh=MS{Z3*fh`xHB^*YO+2ZOQ7irgo%_p9YnqA?bP3N(#-sG&su%&d>s zQnqbZPgmIM5#Lmod1KtL$Dp1T{68&U{1|iSS&(xYXmZs zN^h4)M%vK~P}&T-^?UXG%F<6>pZ*@)6%<43b)NUBL4rF7cOIj@7ma_a7uw}lI}jjQ znq7zB|2h(^i30WOK0a>ychzQgW(?L2$0vO$c%NB!MsO+G;8Auh6yLtTI`>C<>|HaA zHh@0?xo6az$F6G|{+%9;dk4edxJUjHMj~?s5_Wrr1$j7@Snl-9ZZ8@183lT=pUe6X zFjv&D2OB%_uT5$yJ~?RlI$78!bdoo?l5KU-zXIA;Y5hd>0vV5h#b7V~k}NF#C& zwJBq$NiCgOzh4Vn3Rr&KhY#;$kYR3LT`fv4;N+$?C9Vk+1j9P+PgEm@DUIRDO`04J z-!C?)2~5DJr(2{;f$_OtOqnxO4=-RgYE=de)p}wWSK#dQtjx}l`%-W?*)W1UBAQXd zmTF$iuUAHBQBbm7L)Z|NXx%eJ?)qP7{)f^Tb!)PQtSO5076h^s6(Qqnw6B>Ab^Ms@ zS+7f-kDi(9*s77js_pl5-Z-f?aJ9o$%N=4dDafQ50%(4Ru_Du;#f)HQZ{m{ztB@B> zAu2<_hnOVgtVK1?%qAoSY;lkjMoGu!XCFokzbQtN_Z-=}g2BCsR*?UIqjS#y?dJVZ zPd-fYSevg0RtFmU0iMl*a%Fs19YT&WBYHws+ zwe+Rt|G5_@aZRFzE<`ucMhB^RpB2u5K&mgkHP&Rsa@;YedkTY{{V-sZDRp%ag>xC6 zeBYQm58FJ;^ew2WT&=TGs@9VD5p*}_m3+OznXfo?+ zs_{s}bXbNWZQ*nyx(bN#`f4Ev@8P^@RGc^uAoY3G>-wxe1SUt0Kt3-8R7B_<_dIw!+;NM0Y z_;(yr83h4Az)oBnhT!>=r~1aQegFOUQcgq6LVdc!OD=^nkc8g?dd#|IIw1O?ad@NQ zw3NZRocDY_jta)PRrP3>q3Pab5;h}n`b1ebQ|K_@oaIzj=Jw z4Jof?8<7X_WLd|-em}e zvNc*KLSs0WFu}f#s)Z^0%CpbeYG{lOE@goZ{sogc2x$zoIqu5lWVD6#Iqgqn2X$W< zxI)>jKP<~e@yxB7b>ai0Pq)o>vnvm)dm|b2Uu&``_TMdS^v-ihlvc9bbwZMww!lHr z_-Bs)aC;}hr5xj6SRS_bWr^m0wA7Ntb1sV+q)(4m&EZqF`2?AC7UZNe0-{TMp8u^8 z;B@3A&`}TJA#k)rD&;SgdQ|0g!hsbw+Q&7r_smrQah10HA?9A_d7DT_Nu^F+DTADj zZ9rLe{S5e^)zmzlL>#;FzzG+l1|i&Co(zITu)qU~K)} zWbdWYkQ9%ot3YrFdPsUk)tFN~N8_mc%gprMPJr$)8QwUQ-ogN=Ey-Plg1rJ}*2RSL z^}Jbe!L7)|M^J9Xm@#2VLLY5*;nQ!8jW!2SlZ;%eh1>)K(YJ16b8x$vNGqQHMTCyi z5<0MV_Mo_m-f*?t#cVPm1j%^piBxnLoMr4-ywsJ3ecHH~hSe+csi81A*-1}rQS0qp z+3Z(kyWf`K*@P(07ZMWA^yd1xXX;k$NEyeWS;+})XC%q-A-pu~Qtl684=cB~m^qBV z%1OVgkpkV};h-$gzn5n8NF+HVSXHOrt)-=P9PI5_`cXsebQ$CtW7aa<07!AiEn^jb zs2be;-CbGVTh&h6E1Xd>(BI$PDhv3*VqSjtt6%GSGOJ>}-~?gV-rlb?*=eyqmQ}&w zF3SD=uKe_8|Ec``_rEWkdasb70I`{6Jsi%|< zjL}CN*ptsZzTJu#5@aFp9lH}k!IBggos}-;R|;m7K@L2Fo;p5#yukP{xzXyzm~A(Z zzhV{uS@*e=F$6%62HJW+Iv6XibwGQMvmO!2M#HjRuVmEZ#KjFT`~(L@1T;R_4OvoNsp@wAc0!wT^bi)O_E=QqMZ{ zw%re^i!;E8`R)^>NVnzT+c)LKtCzZ05AW`zXTC-ePHl^$^8LHFNKm)%&_E=h4sTQ;HWOQw1zF?v^EoTx-vRWF)weC8>6XaQlwnNqHS!3(f zTH{l(lWINNuC$-sa!3|zo5j7}J$Uer<_T=9yhgA2X}MHT&fnNa+-v5ob03%|Pk9p5 zaJ#8hk20gzSx*U$_P$7NJ?{%<)Wb{JTekx-r^A`SM!{}ZCxKB# zP`pHN&@_Mq$EfSWeod2bh}L+zp12Nr_MXWe!)mqe({7SrdZ0@1Uz9W?#mJpb4#-13 z7|ugHW6dj2cR>nYd7atz#gHtC-Ehw=k4)K4_C~rS9HZ&^ZX+K#zR1vN>eqoJ$7(WI zlL=>?8;8qWULu#2feij~ZCCIp|y zJ?TCET@B6G5m^0IXZr2Weo&W8N3$h$jF8pTeTd8?U+alj<8rlt)lO!6vWUjSVkH#QFsKRc_74NK?&WI-eX@CO-iAnWJ+WFc5CY1tx;|{B<>9drONm1j}vQs)!P5)3tj+iD%lmh?T@vKA5yK_icU=WN9DwtkIu6;*&t@5DR+q=8eulNY2zc@v3o; z`ei;_l~2RM2cQet0*FHucjqjH!9$htq7LV|ajaiYd`o*Q4z%eJwtYC( zsJlxK-o;!es|2XX*Rm|4dm?RR{k*$KXWCKTFC?lN9qu0bHp6$x#b0?3+OD$G$>oe( zBLq3nTf@P$15V_CqHiyatzlw2_7?KKteNWqIvde5%i9Zc-MYOvuBKbRe$08+j-{^I zYh+^=(yw%ZlkJ(Wuj}fn|4C)69r)6P`Rf+2#}-pI>tC=e5XDDDv@46ue#$yel#fV5*(X1KZ2{$$dd*JMqWAWXUd$kcbHdD%kB*2o6 zp%v)_P(st@3aD6+b4b1JM>~%ejoI7zd2+-Ogc+A zZB^Ndj_F#z{w`bLtcNm=${W}S)t*}tn2*_#hE$jc0hzpyax$TIm)Y^=`Yo56rBTo8oD0e{W+kJWa_PxbdR$IaB_xBHy;?-K^(n2XP`}Oll zlU-|{M+rfQq@0GZLvbN=jajm5N_R2*vtcWHum~t$UD5<)@z9zehc={Dx4MZlpxNbi zw7KunVL~`f-V3FzZ@>Naf~dwZH7tm=2@!RL_zZ)iTJjp`mHIpewx3BVq@6Cwc3f|+ z&4$=ok>6xB!k+LRJ{wL-9o*@>2)s0(z14Vs%s;gC^2;*nx#NG@`<<`-SS>WyckZJM ztQ1&>!?VwZHECY&K zn?9ZPW5Gc8c=_Fx?&~h3?)i8BmIR6@3sy#{?$3A253LNORuiC6Y9Z%c+0$39mOR%{ zGaJhq6boIBGU`8h%vMs@*X*_nMzvZ~Ij=1@UHz=;T2K8PvPN3hW|P2VBZY%ps2-Vh zdmD;iPlu6p4`$mEmq7)i5vlzR4?`K@RFuL9VGwZAcXuBYToCwRaQAn2V$pK#-~92r z@}tjQmshV|>2Fyp=6p3?bUtsMJrF!Sq3IMv5M$s(f1uVKx98B4I??YD7CG)VWjvXx z?Tb3PRN01(h?D4(+1JMoFCuPAOE7$8G(2EOa-L!2>fpG$=DiQw?uA<8KaUSTflMTy zWo~@3iFS<#XQMV)$-vF*TB=(i*_?(+BsOb2Fo1*?BcjBkB(tqbu`i~l`S{7W29ES(t#-_C-aqwfuQ%o0yAPTl&+Bt$ zI#bhlU~md7UIYikEwVW#IE{LpoDjUUNl`_%>=12RL)<1uts`k)pMjQydQuuYAY7v= z$g=v{a|lw3!^~&qx^VAU_jzBCV}+x_>(~?4ry#or;Uh3PNtg+{vE7|jGe@!v73U;{<(mn%$`+b)+=RbwIW&(Ci$-}^J|F_D4sx-~t&_p7p) zO;o@8aDP{}+kF{>B&lEA6P$kd;~$m#+q?4J_ixIdefe``W*{Bw2OBT0pMXFa;`vlw zynNw|8~IZPc%ZdDTk2dPx+SB(hX{-^ZZxtDL1(rPX$n;-qHFGj_f9){*7qh*60WoK z1nK4m=PQFM2Wp@cp}D{YZyGSF&VvSxIkqDo#fol)dPIEt#J;^i*Fwr7CmV82D{9rO zxBjt=dPZfMHKGbxI2%ZLK;vYS8X(9sw^juI6>B8w;QZ_|gLx`Rn9V@4&a%?$HR##k z5*4di^!*DyM^*Y#4<{li{7ku^UpBi#xxKyDUbqW!j}%_wJLOO}n?t$13l+5qB@3Rt z?aQGKJ_KUs-e+x`N>5p2lpl!TAuwW7A}I0od7w#qu1T7$ZA#m&lqe0bbIO`t+8En1 z%`Twzbv|jk2+pNEy?G+LAU*Vlhq761<;1zSAX`j1BS6zWC9B?T%W*O&Jw%Nr1P;qG zoq5V#wuR!{c@Njh=eteTYpf{&#q>5S%z-W<_3CnM+F*{A36{~3JMAewn<+CA7=M-l zZ3KfCcC!t5E^XdrndY3FtXg@r$)+pSPyGkY@x1FFcWQksCjNM9j@u?li;4w($V$*jN>FNiZwf`C+s9&cMieUumprHBgER0V%>+bpJ zca;p^Me(fqO6Q^l9km&vFrsc|N%ziH|I+Y>!@2CXOl?Y-w(Vr*hri0 zUe?yzq`}=DMhi!!FNSpX7h5$AgU8;;>^$qt{O$JsLEH)$;TE1UG>SBFfn>HrjLD?{ zYOuOLA9eS7l7LBb?a(PXJCRkpcC9Y6bXDUn@4a*kqFf*Hsv? zTeixLqQgUch1kRSyru0vZ4@K)ss!xY|tV@-eDfC$iZVm!U--BZC?~rJ2ZCArVa=A8SADVpn=L@4>0F ze#AJdH;v}`GA=QgcX>nG&0X~ehPXs-+Q+_|dPBZ1&Z~J}Rny1|sUKE%!RNW;@e={4 zja?0u*94^cbMv~zM9!NpJUPTqlo7hEKq^qW7mgSczLa1@NM<(m&lCY^ep|!;kO8el zuWSM1Lb@}UmaUF#26HHQI33k%EY|&SP;Q<*HSD_D zXxyiQAoT?!$^kTv*P^aCDZ^+f)3XES`8NpqgjSXGZIMpCMV;T&=e za{tvATxS;2G50<9hV^lA-d4(UV3q%^i8wL>3Bjc!1uo}YQn(}964OwKCB6$i_d08K zgS%Sg^4b)D)cX+lRplWd`*RE(G8O=t%8XpIxZOt`vt0ODq%WlO4<0t-))Hq z`nW5F82;%Hr+&w{5R=!!bIR18nKTHYB92 zEpZ+W%Ked!C;I=9ybYE=`$VkjgY1x4=|PGn@z1fzt!6x}jouHMFczgk=?D}iBs#eD z-$VEO(Vld#NugHZyjw0xbVH?6tOTwueM=^$;Xu!HG37v*AmfQ(8X6cOymjg02A;tl z!aiyr4c9`Gjr!2@Lww?w zH!v~$7H+DtWBnb)uy&!=5tFhK%>uu4*y*f&;_W20e1C1AGIOjyJCAQDrFBI0x#edy z_5LaXYEXzyMwG|xo@;ke)ejexB3>Qm-9~100ONY7C&ZCexb*{B&wd$9M#_G$c-{cC z3U10f7`eR?gs;r@hbFpA<}t_jUYjhVZpIg829}eO>U)>J&&9lX0G4b!4$^q5^^OT( z0kfytRMw{%KmyzMkbRy317`4G5?9}_cPNF`+=Q$_C#km~enobN@k!+-3=l0>Mq36l zV32#LXTN;;y1aSwtc7AL-ERfiCmE1qlI^GZ96#f*cZ^?Tyd)B! zv=Y+et{(GI>FtJ%I^6cO^-u=_q<|Z>j&hhxhcM=;OgYot%-J2!3j-O-U)o#fsgunT zI92O2u|-<5{QEXwZF;{7ltn#x(Dy5M_5dC6W-Ln zqTzL|s$d<2Hv%{rbW~y+^}eguXZ_yPWT>yXCI#m2ac~4Hq28)q;jF6}I#+?H^!&w3;!hu25T&?fR`?v3!`=4^lx(_1Fx}}P}lspV42b9d(35q_Zdzo`K z#?|$rK?eOE+ZN89_C*-*DxEd@0)8&sOKG^%#nK^#<$np7EU47N%Uups?bN$pICTP5 z?}ZK@D*XrnX0+*DCZu+vF7r6Jl2dQUnif9lkD{az(#ws`0?(!HTAbP7A(fO+QlWzQ|sxW9ISF=w*ac zGcxNypmvD)Ubly(k;tsQ`BxZZ&Wjr5NztBK{DNSn4Z@hmHLOo>MEayBQ%i~J{Yfer z^#uhk7dL{U%dxK-AdW-O`*>V-_hj8MzE!ovvz5VebA&75SwUp$^&I7k0UoVBo)2yv zZ2Gxb2ZkJxxwYKrn&A{Qdg0)3NP9>$G#0l36m@EZVK}c8`{0YLm`rKD97z{`JV9aV zq+V6dDWPOmE?GS1{o@~hQRa(x<*Tp0(!YVzk%=XE`SPb<=$ZU~|MOSnFMj!p@?ZYf z|3${<*^8Ib<%ZA(WKZpz@8uPu7jqdCvj4k>2N`NlGTUgX7Cqzqdx#!G)YDO%BY+a? zcswn4t2@myKGJ6m5f8$U)@F1}km&*O61ZrDt`*9TyPga%?^91OMuR=0$xgi2q&=5x zTcx~l+&?l)0ZGyRrL`QxQXDi!CLR11Byi;fcivM9ph9n2YdH3|j;+iJ_VHAc(e^wy zCSFyBwsF>Er(~sa5Ibl2RR9fA0mJ*$$M8Gzqdz)pfhmLga5{NSBbjn<8_#6AJ5n#dP z1nWBqbWYsVF&LDDYDh`|N_9YR#O6jRCQDIu>DT9ZtO7ujTtOxrK#|0TK0akL-LE96 zdTL}kUHQ3~t&m*<>1X5*Qsx?dg}5jLAv;g~7`ZLaolk+l=0wd-u$zQXkN}q~?O!MJ zwpCHDYogYG&mYTHYZ$wU2tr7PO`Fhn1C@P(k*M!#LYWtA+v8kk_qllM%%`p~)aTia z{PTBdVDjI!!~ZDL@33?qJOBDRy1!4-L+Uo?E9&FRa8_kF%NMdJwsO!wb!*5!C0kP%Y1weSW;QTbn$`83WX6d3hg@nS?pNpygeovK3^71|5cRj&a}kmv## z(|Fk=+ntcUa7~X%C{>$gt`ASysx&IXFxMq9>`(^NvH_tlUW=*Z{?%*5J!xS_Wz7Ni zvR*;6cr5{$4u3i|XqFI);iTL=d!~Ei+45sxOF_!CauKLZ#wHvkM~M5bXS6@4eod(% zgLFzH+$S7xYEbxI)GbU^U?hp^mIa>eUIYm^LB`6m4rdd0txyN#KClPGn3kep+x;Mi zUQhKpd%q=@M$W21d6?FCEHFEgG{|caUBcPmjJbatYrnVi%?zJ&dj5P;{`lQ@mZ9$0 zm~0(<{`5ujJd!)3z_G`8VQJ|}l`(A+h*_@BWk0zAmLo8i~UPKz% zMP^I}vfcK|W@l%LI0VEB+NM7xb%{O9GXum7NW=ZhDw${+slRe4yi%MX6=17-DZ-o7s{ zKYLxCUoGX7FnY_Y>+)>3FJEteUmiB=@|<&;&&nvoHfCgVa@1(ATbxH-2MnZ{rPM3g zWO4xZ6ij5WfgBr%Jmvyug+~N$qwTgJt4FkGQU;qiyd;R$s8Krf%syONGC2yQCrOJ& zw#?*rZ8^Ci^1dG#1p3o;+-UD30`T9hUz+DP5ER(XYtA*zarGKdC-$<~`8aYrev5BZ zd;Z)y7}rV3UNM?h`)X_Roxu~yY7d!SSl5g#&48OM(tECy;~rG6?PeKKmYGd;uW*n_ z7Ug|7tL1#wARjpQ9Cu6EMf0nLw$MUHMtc$pg`;8#`@G56j>?`T z$`#H=oPoyv5N!KCf)uGH9_^HgP+FK}T3)<(ZrgJ_T{uK3U7k&fblup<;*rFPED!!D z`zW;RQy*T>h1YQV7y}&Whsshz3bZFFIPNxx_Ux496V&p$>&2Ba*mTew?@D8W?a)~3 z@Ip|GBoN|yo;`7kDIcALSlthTG)lP#q<;L?S08SkTJKB#+Dzcw?E-}X-L~9y>d%pljq#r-MPf9>a`#!piB#YP}`SBZQg&lZQ(WrSM8t! zj?wga2I(x%DfN>P(on0A#(_GJ$`P*0qH_pNXoF|=FBl1>yZO@XFUOX--ez3=a(#VM zR;vf02YDS1T*%yUEN*4XUiR746TvWOK+j56^0 zPk;K;GMSky#CZbA-rar>3!cn@*Qv&LbyeQqtuBUkBov&%OH=D_`s#tMU1Hj9oke`S z=5sv@-)_WsG{r#d_Ev7ViyY-M%2l7_H?m=m3APb-#{$7eTZ=Z-*!1-@lk@7mP=Br+ zbYw&#!+HXt0)vWYl4y*S^axfcrK_#ab;wHG%r$yBk9O!wer52VL6C%bs&T!k=vD{z zxks{nt#R6uVHu5wWq0scV4Qlkf~5|F*Rsc9@>%?iXP+Z$`Mg&zUdpk+4?u(5DA%U+ z&z7MD!Q$SqJ{ibEIZIB7XEvHDqtdt~NCD?4c3!|^T3WK;x4|K`ox zGM(OQkL7(NP)US=b5zjSlxBhAHxl&8G6?U;`h;5DZ45g=0GA392H_C@Z};NDCoo=&K;ik_VZwzRfCd%w+RuoH$`*4q8YklQZG z-CU1|lx;Uq<6oNh`@gj?PkrBVoi_nR-n*<(G~}^t7q3QA>c)qYN=9xCebry>wDWQi zDb*)ZFZ5*5*G{^DqdxH&T_acAi=CQgNIuE73o`%(4oo{0> zqamV+BE#tE8K@=}5Pd)^nSsH+C3|qa%@cWY(cY~d#Eb+9X!_%>0fm&j}Oo9ooAtaFA*yxpLgCA-j55ry=#e^~a`)DDKeh`;bYeJgyurE7w zp;2YSzy`ccH}||p=1mR#y*8x-jj>wLK7aMOf(_N1&!_U)>(2zO|IOe0joR^WXiSn) zFK0Qcg^i4yzrB0=p?vX^AIaFf`R3bj-q+<;s$ko)M!Y7TttZpD-3&G^lCE|vcAQAj zdL3Mjjr6m&5?b7t4muR=iu^YTVAZ;617@;rJ4P{G>1$`$L-y^a=653q^OOKGHgXH;h3l2d_#i*}WfU_q#a?Xdf17}16M2oqu@9xge4<|Gwj2O6RfH|OfxEulA~2-yV+I)g$ROhI2*yl z${O_?J@`t;=JRC_Olqc9-oWf<2)SNgZ@+&ZgH*-^tsoG`c9J z$6)oKzfaL?n0f4|1Zp&^eXVDmfm*`oTGyJTt`xPg%Ravxi`te->#u~t6DzilX`SaF z(V%R93xO7uH#E^oUFi8b8@>s z{;f+~xL|8O!alDv`|jUrXt|q>*8xlo&DQ}%H@mN|rT#ofZvNa$*e4yg`vkLw)@49i zcmkn)*wSiA88~7-S>RX02d2wK4DDzarAJ7*MTM`ry&=a#+F7Oc^JULt6To$Xt;|d_ zi^mbyDrI$FHPKy71W6K7LTf2*q0Bon{;aRLd!p@mr@X-5vxVjL>(}LP|MqXo|NZ~` z4`tTC>Nxbj`m4Vx|MqYHrt`%3ZTARRtjkY+{6#~+qqhFyA^wAc(u`f=Gh-u+e6gy#^sv8U_2@h59?Ob zT<0ZNOP`s}%+vo`2De@}^uC~We{*%M03nHBh~cnz){r)XBq~Q3D1@IIfeZ5r+T*si zGs`#e?DvU)I?x|fs7E^8lug$2Ir?`bWMr_;u&INi;l62V{b?J})K6%h>j2T)J=v8l z(z{_Z)2=9>3FpYb7f{|r9-1<%hH$l#+>LFmkXAHt%CCwoGk}01-2PfmtZ9CHVs!Mpm!)OhM zjEQQ}j=XK;^87BHwc$kfqSwx|88_c?tToi&zvsoaw;~;A?PMRz#?vv>kW4pQuQRE- zj#vi=d2Y4yt^ulRc(&);N?8tW5=zeA#$8|s)`b2%;WaZ3xb|7;UxefU9FaPo{%lB`;D{tSvmD9$E zJnz3KU;gapQojpwY8iLACmOzloxqcuscipJ_p7x#x#o?EoJH28 zw4rA!BDzJ4n0>%^DI-r3i~6UA8IdUu7)&w^@~QWQ0z8I{Q13kU$`#IjJS+3%ylmD( zAq-^aY{p?AWiYp0&o_yc{gi=iLx395N;WH3H`ir3U+6iB5K1q(I$t1=UO9M$4hs1|`2Bb<_^Mx~e!|OC=E5G6GICdRu;;VPsVMey?22({g*CfKQ6 zrU7}(@wX4~W2B&Lf{+ zZsy6j?PFG3PB;x^gG1|A^K3Y07MWU_G=?#t+=>Y1AS#`Z$x9+jg*2)Mmqcet5BN3P zhFEI^Qmns|N*E~(oG^6Lx+H`vSiV(YD+v8ea5a?EZL@P5{S$4MF*aI%OUN#@tAjZ% zy&Tou*gLMbCMkz&KvJa{ZCSJFS-*`I1Ais+9c#oc2nXjjMuqGE=VD*3mrIpldJh%Z zw)%qnguS4wWCBqPA8)3cwR7H6FePWSyInGbU=#>AfK$-cJC~cQg`5#Ab+OuqjPD$l z>*d^acCKk}QXBy&j+W0`PW*SqA;WZ6!6f?iiSJ;hYv51Mq`yPlGo2&+hxyDLh~co@ zJiXREWhhFvccr5RPEQ1`$^I2ASo}+~2e9ATzb!XL$(Ek`KIV$ERy>{SAPHg5Qy306 z3b53}f3lJs-#B&s4s_|_D%ep^S$f zvSUG@42aV&H+pVSPNk?pSq7Cz?m--@qb`^Bg?Bd!bkz4Ffy%$Le=R1{zK=brak^Ub z)c6^b9NBob+Trh5Q*rHSZwLR|-~RBwyB3jx^o9>wNZU8hY+H%PTI*UHIeM|jW|r!` zl3}zgEQA%*u^iC{6ELD5#g`%%4OOSjx!fAolExr@)&*fW^$=Oq{JWYcCFf`+A(1u? zLsMz8b%!h@=Ku10^@6ilF9MftpJLm?o)0PiUANe&GR`%t_EO8sTKIul5f74ciaQ&@ zkB7KpK8d#Ndj{--mLlay%m?xfnK85^GK=xB%omIXor+a? zcYmk8@bP4%Ug;4%mO-d%`WfR|fM6W}CYO`!3W#p6NmgQkYAPH$&*)`G9gKUx_nyCd zsKaKvE+@?-_cMV7zL?L-nmU{MqD@MoR{7+~Q)N!CU%V{u-@a8p?GHZxLAkoRE)NeY zJ)^hp-S=VNf8`aBH;_i7mz3F@^LuKuJCcq7}-bZ5ua1P~<-+WVc`>omy`S)(Om6pMnpn!d)7C{0TpA(bB z#OxPjeb9a49=>|{LhJeA{z3PMK$1Y~9$DcL+zPToJLu(droFme-D%wM4}b8PG|_pU z^!NYnH@_{b`@6El*|8s)#+T!a*(*5u@vtneAi6EJCze;#%dh2d)_1G&{@q)_>oCkw z*%J~1im_P>HIV)28TMyQdNi;DQt$17vRc-!;BbPd3U!$<5;)h5GIbm~?PoLne3A;J z``&qu`yFd(C)>&K`1gnRx4MrCW`+)cxxehiTsP?bqmaksL}uAD0BFohc&>@1UIZ1 z&`l(67mHDO`t+(?UoV8*U{hU2I+Zm6sAdy*(1Kk#36z5gNrc7xbJ>?bRavhIsf#xg zLCbbeP;bA+H>A?Ng20iUmryu*@&lPbl305=}rKB*H_J*+ZbX)B{cjUPoMANWVU}WOvqCefB*zodU`%9IZ8MVg)+X*DPK^ zPyb+m1SNtQ!*bY#dJ$HoH;~wij7an*t6qIDESQTYv&_s?+8`w6lLwTU5I>7J)zlgh zhbRT)JaVySgJqxD>+O1NR_xi3l_Wj`8d5tOecjWkoVt|W4ve+jHZ?_FFD19tx;%UK zLXi5`Uw^INefi~=<*VQQu6+OfyYkQf{LiYJ|I5GpOH)!H1Lw0j&B5H0001BWNklGgZJ7A{R{;#lhn?ML=s18n!kt>Lrnk z&F?wkvE0{l_`t4T| zSX$1Ux$+sn=<|?7J*z(3QxJ9a}z%!unsg1A*Ow)o(-ulN;!xD5vcj|++L)EGFImD?yd;X-{eL(!Fl*N3m;DzOqS{R1ZZC9{ux!(Y5K$O2E&UG}=uD1P&w2WlO zj4%vU26V7Xuw*t`JJHOF=x*gYXNzY?Dbd4&j5tZqMW`mFmvdRn#$`6KTA=2VXx|+* zcVloe%By)0=Rl%|ZTHqO2(0xrbj!F+NjA`Fg7tjH{QrK7Epc$1+FdT*jTm0)&`7BUa?f&`c*L!yAHEHZXT~~b$Gll zy!~C%=<`wSJK?JKy{+V|{{Be{;KxL`i#kb7l!!U+NiM=DH;}D9yA!x**aeDSc0xqU zgR`T09Mxp9D(l_qf&rSaZ2hdx)ok*F#cF5X=ml3qDAnILmP4i8%-KvkZ@Y$s@|shm z!%R?5_>mxn^Tsj`0Sr(EZ~l}W^|(Z z|M-vcZ~yl1<)=UWQmtqTG|2jHuFK8VP~2$kNm>|S7W;zQOMWlNgxW6J=~d)0C;Qhn-Uje{J-f+O}crIvRfb99Q)wM6MrXVx)l272E2PRk3s z9S7oai33qGr@9kFC_w}~hRp*~3}mKe*V}N88ooycr7iMgsaY~|QSX`>dp}56?HVxz zf2q<{D@4LT*XNB85i%jlZC}p5vd{U+^_A8|?bIYJ!nMbGR=2`@Q67|$P;1xBIgL1- zsO1O=WzeNvgR)rm_n<(9z;Ckf90W35&Xrar57U9$k&rTKZ!UeQD@sAxNwxK>>nkbg zY5Lu9C$S^e-TcbJN!(YF!XT8c*K+>s=c|~4M#&6BTyU_XVCp6A*{}BbeYhuS0lB8j30p@ZWJcQMt-Q&lD3u{P1`PJOZx` zoso8Kfpzb*e(Y(G4Y+--(bd@3;ea3W2PucEZXg9jK8{MGfxPOR33xlYCYF-r94dYG zs?1oIacjSr_qqN#CoKvY3nUx=>DjJzf!Tr&34q2{04K!xe@ig7-H2t5Az-Ar9@ zepPd6YW!7TksHNtYK8RuH+R+AefRF}To4K=46@4o* z&W!jn^9Cx!AVFlw^T|w|pR?YT|4upHjH0P!V_ZLcxNYhL7`>a#6MAYDknmE4n)tGhciA%r6~dW79%` zE(1iK4UT>O>Sfc-Lam*Is_u5ldz}6IIPK*1)Hb^9mI|IvWUKYP>3+#B#R%fGho>rG zbiz|hy&5@k$&(<^dK+F}we3%T@Uc>AyIGnOE6t`L~0CP&xk)yNS_sCgmxInB~vdiq+V2?3LF~e8s*2V zLuSUUV`zZ$DcEx+DR>N?q4{n$+C?VnZ0)hHyk@CN#YkCaYL~N&Mb6`IRojLB79B1l z5ueBiseyV^rixt~bn$vKLG#%_9Kl%mcmb{9_|aG2Z52UdXb(GQ;0fL3b4F59!W9n> zjbqdTkGiQ)gkaS2Z%Ais$g9P&%wLi{Sb&18180;>R%dxF>;F2`xyayOy#CBRzxOua z&tAUp`HY6;cfbBk`R2PfM-Z?-s17y5IQM$x`r7*5ToYN6;L5FQvt&wqrLn2kQ{I;ghPy~U79`K;~GmzYb!@OqA@*P$stq@JE_Y8)z2kZRTd7-94v z^KanE3;=6_qcf4k;hu}zHd2Z^bkm&TjOXOBg)aNZUT=Xe1n~!Q^tL6ccb>1sXk1Xgo%wi zXm}xBB;l3Sx||`Y1q2V0m}$!ia6I0B1pF%-j!Qqn(y!R+3ZtsS;QqUf5W_$UYTh=yGgw1 zpfo=LM2*p|J9r(;Y#_L5hfX=$^!gNxu4h~EeyX+oaJ#y=Uun~%n0JKJV_&e}*lrNe z+}u1d(y~RN5F{nKHKKQ0RT}wEP(u{?f~#xMjv_825{vdb zyS!{y%NfzNv#dWO&*-Df{=$K^8B#O+JN zOulA~w|#~g5Vhx=nR**2xxd+vI1p&`_4ge)&gYDlTwG)na=62>42{;QSiJuH%*@>` zw!eUk*<}fLrk1)4JR>JV`Y|CWHhAhqcTpQLR3mEUykL*BXkqB4QFnxHr-5!dnROZi zpv;7~&x?8a!`EMzU;g43dM!0>J_GeT6yNAQ2ZHCEsG3 z{mr?bIPP}qwVf(?%Df3CB6F-uYPr4=k;!K%5u|F=WE-^SpcM0P)@$z(v#xDxrqhWW zKfhzGvuF4lf<`_bDAUwr&sYyPH~#q^mABiw^6=rkq>fKG%F^p!YsA*_ONTgS>Zv{_AKoxc0#ibVt^75brR`}Dj1#MH8}y1 zz2zZQ$7Vnjh+VSOc`f%R?EzoIf%jQXKEx4%ngOw&Vc%zIpri6x2OnwM>Wul&*!G%O z+VNddb+Z#RVU=zm1~n~IF3{i9d1Qn%Ted~qquf#*tI>$>bUbx^SN^`6mDlfSeb%Ra zNv)pvn15>4a+bO;h-y^}!Nm>vXa;#JH)o?_$7NkyU_?V5W_srZdeOIVMP}0I5x1lF z+|`#EgY}#hfv80)0*jDOWfL~irk&Qdya6oGdU5!seJrHYJx0Coy8%c2-pks&YaiLf zlE% z*f8!2)F9ds1n;Q-Zelv#PFeBw)j|X_2#Bi{gHaA;zL<&_2GNPVxm?c6>ld$eERX30 zGF_ML`k`z$E0r7g-q8&L;cL)S7fP15_~Lz<8xLt~*w6a2!cbB3z+@mI#!{WDr%E9;yEMAf#z8)*2+2j;`4! znXy%W%b-tUT>)FOZ#A1hL1j8$s||X6`!g)*8%O}W(PrkvCCZ&hTq^CQugH7cCV1F^ z?51ytfwCX$=^zqj$+mI$Nd>37g@bVHbm-lTxa-LCKxrHr=H4R^Lf+RdlwU_(wSmmz z*RQF+8#p8~iF~auJk@h*hg(gS3ULAx2RdZ3u2y{~-M_4Je;gUr=h0Pw@{4kov;>FS z`_yTVGsy}AO@?mWZ$oCZ7vbE!*@2TK_ZX0(1Rg3lHH~(X+mcXd1JTxQapr>31hY*V zkr4#~q34{DAyIc;UwxlUa8sbT^*)Y|yep$p86ErW_s-gLa+~^Kudj4}CFMzrAcGdBt`h^T>vdw( zdJcLjEhTX<$uxNn>hZZoOZ+^uWRx8PjUrn-*WAFF8s+oN4KJ9q+L*1#5cLyTXZM>A zX)SV_W+RI6QLyQuK!WyTou#HU#HC)3(u&a-CWe{J7y1J+Rx<07b?}nstKX?+?$%BP zjv6Iuh^t2Iq+q7(#=$5AA_aSrV5QBG0En(*MtRyG!rzrH1W<8i=sXK*@h8sR#=C`G z`5k-L15A=Dp?-T<%N1uN_d`B|WV(0JMFkFpwymigIju%UAo7Nvw2pGGNL7w`;WGMYz7+W?eRR+K5Nq~jk_`kqU+~VYhI+??q;p}jXJT+5H6go<(_%YB7h$0cd~i57i)=r&EBqp?kq{v31$8*zv^W9vC_7mS;#1N znEv_RCNYTDT$KFMpH=Q@@W21ppZ)iI<6|eD2k$DgiHqq-8DZq{ax+{&ni*Y0 zMwCN2E=K;<8E;PaI@;l+qwr15`bixG1Vk8_RjLiCPgrG`R&~k*p7w@!A4u1b=D%yP z6**Y-0Z0F4KH$jOq`4d94BbBlJ)k0$FqtAyHWQg7Y+yF|v@kAdJY8tKAWntj0ArIu z%Wh0h z%9cSDeKO*;`hN)mfZFcvV5)D+`wzEed3~imV0vrwIlwTdZytf1m#<&R7$O)$fb!XA zpLS>C>TugDZb2MV!@;}E4YZ3}|Y)924+1W~af&>6;L zD*8aVmsdAe$}ae#FO=WG!Ur`l3mwDKlAtnh6ytR^mvLW*P=@;QHI~p?3w){HoBA$< z%g{aG7#i=HTHAY%tdtl^=pZN>Cm5*uQE}o3vFIEp)23AoNOCq`DB~d$<@da9yMa0E zk+$^pa^4Ud>0eGJxQv8?Ix=JjUYrNd4yQxS7w4RN5=Ai1S9Nz*!-4GC!HR~m2n8|} zsn#I@4meqK%*o7c==nEmO?(4sR(Kt%T}VuKcM(*RixhZ3%~lZW#;v zfMHhf68l`WXAQcHlAI9~odYP4oQ#>@^h-~eBM@uZ>)I`5WY3WIC}%L)ko%b`e0-yg zaDDSc_v-z-_v%%jj;H16^JkvsHlLQyUcD+Woy`SA zEED5ovmNkJs&aOmt%dP@WQ^;&><=a@vd^@aV%i|~W3$<+tiWEJOlPuzcefAa9mKya zdKgnpw8MsRJPoD^;V*t>AJlbo!{os*Z-y1QpIZoFpk2BDJUFbKb)fkgp<$xdQSOI= zMcV%MA{*X3xh_}Nhyxi#P7^J$wqut&@Se?B?;X4jP-l zzoT_h`{XX1pIN?yX!6TH4s zlnlxmW$;aC6@%)}u8*gGKhgu=eeI{dL?(*G`6#lXNV1Kl^k5Vbwh^hK!D{kV*1Gh7 z3QlHPhNGGK5hZK5wH>N^U zq6o=a&6X9u-{0Mq+0^xIvhctAyT4OL{i|R7N}>p<3dP7ueoyP!cW=HIJNU;x{;@RI zIiVka@kROikAGCe|FfU{to-`dzito%24Z07Gwa7#FkFS~3CT>6W-v>zd#9Gw1me>* z5qx}T*KiUQ+co03&gsy*&%fRa-ei}hlDZz2k#r8vaDCHbN@X~++*D;GQezvK_~Hy2 z1t_5+|p*bSz4Ohlk0Wg4yW*j56uXb89tu7Y(ygVqQs-D ziRDfVXELt)2l1}-%0{h@9@}ep)Aw~Rp?dQ@bRVR;wu`-DZbA=P*dWF=Sv}$&=eA}_ z+o3Q5-PSf3x6QETw{#y9dFxE>$|L|HT-vxca6gGKnY#OG9|h`9S>*G%eD>LAo@o%e z3v_jG?8Ra(QWZfL%5O|YG?D6mQl6B`-$4j;kqs(bZEUclCUR{LX(P!CE6spF&Xi zJ$o>@1#YeN^f}kst)#bH8m&vcihN$lVsDbWPARgsxn75DR-RoUHPV>p*dRI0wmnz- z7+V<%je-7fIRsIVE8F=6E?;!to7Y|20Lxsr=bAnK-DEfKU2P}2zOjpnH+G{^yGul> z{>;YyxHfPh&)mGSo0;ZUruy}X);AW&)-%4%)Uya{OkqM@Ck;&00F~2*poKs4vd=v? zT=%QK33=gUDs{mu64XNTy-ke2ee7yJE|HmzDcw6o_i-{(K9g4WV?FBn2*uH# z3|878r0qMG^AFASe2pUUtgm3mf*>=bjcYI!qnO`&E-!UH&N+M1`y$Fvqs%NrYFyOZ zG>~Cy3EZ9qQ!WV^{yE1p=BUH0kF^n`jYtZ2V0f~92&YXJ!L&5~_M6}Qru_Ur|EKc9 zFMcdXOh!&ETLhwWDL?qZ52g49WQRlNvoUC7jr5%V@tbeUU;M>ilvl4mE8l*LA{arz zOm}*IbPz%<{`TR%Jexc#%f(VgM7^rqHx#nOnzd1zGBT5_Is`Ye#_Ww``Bwsg)J@OP zq4o2r15d3t)p(srDho)MldK!(eSl|8hHS!JLXK8Yvx7HMLl)-#d@_m*n45K>7CH~a z@Ln^)O%t_(1f;&?VT`p6$UUR|G^SFctFp9aA4@55;PZ)ZO7Xoxh{ix*+Ygjg^Kq5bQ*t-hFXp2lUp1WSb_UfZgl|asEF*ln$yI3^+Z*?!$ zI~h2CcV~m^)&vohlw`ZaUARm%-~|j~=DO`0zoqu=#|+YwqBB~LS~|8n!*NgOLE10^ z!tu}?n%2&SE&%8d!TupM=0nWs|EKItdnC)UBeCoI5?d~{b@!0N0hb{l5g@-v9|Zx@ z|Kfk-CqjfU;54VZSyh=C8H?}kf|(t=_q-dPni;POM27qGx7_8dcI@n7xUW{kV9<$p zdgZ!>Q8I=Hdw>p5-8Ky~vI*mSi1M7vVz#W;qfC#;i|H7|7%k3@#*<)WiByTh)pqDw zWr>U+wTD)Zg;EyFQdYN!s;mi^P$VxJBGsPp`td!52GTXcK!)wA9smGn%&%jtTzN%I ztkPms&{2&9aw=6%N4-61mZNA(zF$;jL*KW?gw@<=uO)8E|GR z!3eu+;pyJu^Ld)U{Py*89y@txrJjWHJVV;;imp*t7K{M)o_k3g>W_vr3fG5!%?| z6IJ4Lh>Q=GwOq=9_u)}vGm{z=j8I`Aqa;V(GQ5*Z`KN#SCn{X@E&rRp`5V>29*;z~ zV~$`nAb*bY!8`x>{dYB=4NnLp9cZe8V|KeC-#RuNA`ZD`6)%V7{9I&63nL0BVKs)) zIMn7N$s_le)G-K->AqZ1`8;7ch$;`D6~gcRddqpQ8YQwqcV{Gcqvm#Ct{N&vLIZ-_ z_iD1Aih&4H96mlfxhaII6hdrzaO)q`iWQ+}2-M07C$wgLCL{f|cNBufZ{%~a z4YV268-7+QK7{0>CR~8NFp%+l2*_tlDljMFUQ}~l%3?LI9=rDe_9;8v-P|z8?mdwm9Yi1c`O2Pl zjW~p%cP)A#etHAhhGb}YPs*4PUjpVG^9B#SMRJ4#A^RegnLPAsky|;dHD@$Gz2Flc^^?MFg+G7W!P*_yGP_6fb@-YD@8_Hfx|2pnUTh@Gz{^d>626#wc z%h2IvSQf`euOZzCmAJ$NUKTI`q$q45VL$J3wTwQ`s%720zH&2(flP~qWkCTlv$8`7 z5Q^58xjjqDq6C==4OQgar!^@8Mbi$HB|Sdk{Ey563)wcwZjgy(8d_%`pD3 zrBa5#`}=?Rhw@i{{nsp6!wbCK2-p9||MVASv04)7W@PWnW>bFn=_mgF*WdqF=H%af z_&{m)_3LAqqn|avjiIQ4md2nWKMy)k=B`i5jk^*8k(+bWt22ztlC%`%K?Mewi6b{$ zLw&Gv6B68t%=4i&q#Q5L!#?g&rpWT?;U>;&3Q@h*uRQ8?kw5P?Ecwmj9(K&*LZBNp z9{?E`GJ(rrsD9cMbR`c0&LRL@!_qE+5B<#C(?qkY(-}VF`WlPIlYlow2LkZMdkrvL z1~Cl`VLk_{-Nfw=3`7Ws_%6IfrFgP1WCtw*NkbM<=ZXX2QiPE}GA z6CBqN`S<~)Cqm$448t6u3Cj#~E6^d=b)fozJ7Dd9u;GHJA^-p&07*naRPqTBChy%5 zEabl5-M=dz-hC|V+f{kpJTVf6hz#gt*&Pk|f<4O3M7F~)J3Vild%-X~a?ISvyKR6< zZ>tfGJT%4-4VYHTd3k1g)*T}mb*#w6-r7so^@A!8L?Fh&6baxNn>$5hC`A<&o=1yR zjn(B!1Xh(wSUYI5qx2Mwi?g~WqH=_t5SKTsyGJF96*?Vej9wa{(6NUz z=&i?cnGUt>+j!ppft2VdTJM5ei=6QnF#)>GD-24tmu76PhS|l|7F;DZ^6Ye9F&caQ z;rq>LjGTV3L!|K?hU0x6zjDOTuWS%Bkl?7CAvZj5y#?S47{!+@pKQqq#y>>K*BoI7 za>x(d6r(~w`P%&;#ZbO66u1zu2r9Er8}z(L{C97;`Plxx{(G-}tn#_)SakQ|-nuyl zgULi_j~4Z8Ue2Rg8BM$q8|oM@hrY3Sz+X;4&uYzygitg(J(nhBL7V5qg4_$jW96Dh zd7eiK9K4VGw{m~f8#UqxYr|V{82;yjZ1>kXL$vZkgCb7eo*PYD}1;M&#eHZ#Q?|UH-3+rTZE~7)xp7Q2k5F&iqQU)Q5 z7>DmD`)U+QAPs+}IDBO#mmSYrgk&hp@CT zA6Q%LwLKHwhYIoaz&_yk!Cv_I@gtSGguS9iC_Tl!efjcCKplW-+N%K)PHQJSUA^o> zM?0>CXk^uR{q-}O^+@dDIdYyEzd_i3PN zsKX{Dtji$!)5-J+kMr0BrY7ick&?l>R$g8PtaIp!-m4p8@4V$#zUN-9^a{C`4f*q2 zm2vI-`Sa|>*AxqTB(!r+bLm3w`sWkcGR%rWLT<=QOKUF`x)WAoV)|@>5VaXZ0aw!Z z*RItVePRFukeB<6=gIf|+uIt1@T1=Ff5tn%I_Un%UV5@5p|q{g^H>tyPHz&Swk31B zROl?HLi@#eDbpo6&e2A7yAuHfTc%b4b|_EJk3@n)5VMYaE-PBM52iPH@UKR{|BOC zaUD}c!b1MtZ~u(n1#k^Q42>Fo_~D20+yC$%Xb^n*@`Zmx;5j+~PaW1j#smU{Ay0S^ zFoMS7TZZ76VAFzWENbnuQ74Ny3>{r+z3-@HhJgp~#@_c~uYCG+s`O!z5F`ODDt&V1>{era4YNliAM80HuAL9LRx<|KMgIK7cm!agU6n6l0=K-#(m z5xENDWMnHD;fPdWjbh)j9CRdw?m^97oiALiVQv~MO6AxT-c&gm04j=+`9?8-C{Ix< zJ%%Ky(rv9opJjsP8u?0Z_2j{DXd+ufM-r+aEHjJ<V7 z&1?DhKmMr-ockMfeA)tpMgU%HZg945Mec!|D8}8w{d}B9ThBAYUl=chsmyt9+RFKA zS#IthYUefld;H}KLwQiJS>_`CNX>AgcK1EGx2`pxYg-3b=R`slVRm@R{K*YUBIL<$F}aM$Hgb8& z6+$o|kFHQR?k~J^y>d|fpSM1RVYz-^ZcHer;UE^FJjUB33hnz6G)+OJ3aXbR3|_L`GslBVl5cb~6`-D?sSY1usKC#v=P_Js?N~ zlN)$}vY1n(vbx*5H5It4Z5%X0*k5Io!U~bNDb>6WJn^o%56(|s2^xAKJA+b~&X5&g zR&eJbuZTQ)tUVc)rspM)aDsNO0EHeRXD%Wci}q2}$?Lh1vcnuIf}v|VOyAh!2D+is zp*cF56+7f~)=#~Gk|U_~J07<&D91IHK4$WN{cnH%k3BfbRtpA!wWjVdj*^O?(qm|M zCR91kNf5_@f`vd3hS5w(sr)VSbTvN_!hpQgkw9l3ZOS^;cJ5PoFcDk2HU86pIz`bORZOKD*B(@c{fa&ryTuZv4au||Z; zkz0!1>Y~RqN1RygFn$o2sNW{Yi|lP^z@R#G7(ufsNq2n5rx0~6VC@_&8fM*DR6~-0@;VKx))Wih}8eW}xYxB4Rn;WXv zGlh+!E@YsCXLl4?5B|+w+pOEZG>{q@4rMT49FNTHqh;@i_>a~4R^&ls%3GAlbf)8i zE1f*=(OXqL>S3&%$R&Wj+RTw(jHTEUwG4JZypP;G*2Nt_KpDu5aw7XY&*+ZYmAAAe6ah0V82=4urIpC1yQgA_u>v=^jAc?F#cE*>I=VGqJvoB z^-wqd(~m!}(;%4OcE?kBc!!kLjP>zfpTCyRU%r$VbYBa0JJd{r=N+;Il+WyxhIX## zX8;e4)TNT20u-wI9zbB=tw7znt}y}!G!US;J9z>|=i3D-d9J;-}=Eu70fdb7jOVHZla zG=|I!L;9rk2n>Y#SO^qYYK4R%7y_+=0vXC15fK<4C|kq#STzJ(g;r;*A32$<{2&9P zjBwV@hYX+sB~`E?Xf5)L`^B-+PbRw23hj*dXJv{&pFcv1PxMA`CHSauIOgYcia{EKeDqCC*oe%Fz;V;yMb3p{? z&p3B76H)j#ats+&8e3xmh%{w6mC8#L)}S9a zh(~0UIweNNgb2NoyZvw}N7kdMM%|xf5Ftx#f>u*eJKzX{M8vh@#>UXtmkcobp7xpc zO5XeJT8;bLvZCcw!xMFxV24H~WhzOgAee{xrx4-n zd0EW&MCfCEBGSOi1ft$O6&OWe*+6U1W%;bRbfrU-WktnMtUItj#?Q&to5^2^h9 zDh%V8D;=N&>A+sl7T5B)i^xXRfH6$IMm~?z7#Z7QkJ`soro8mZk-tG2IO!-?wDghZ zte^7tE#IbIOb$OeENLK43&Xcf(Ev26N6i~1E8#p4`Tb!CqLIT4mH80x;m~LcTVyVI zHKF&bAAl^#qfbfO{1q%W{B9OX*9P_4-#Mfrwz`&vsppBdstVb(dVHh(5n5$UA$i(^ zM8Os#dp+-1ieywfa;Xl{qx_A>fKPpovM+ccTQLctD-$0w^1SiDV6DPyMdl+R?J30A zct-*ad9X#aS)@k;WI7PKu)+gLkK!U#4A=FE}fBVS?mEP~&C zH|!vn<$?_+f$UoDUgI-NdwG1a(bey>w+ek|`1=^v!m~47oEJt(v{<%BrO>oEEaZ90 z>&aSW-H7twG@b?wG?;5{gNG3`aq^VB5C zl(TRaU0p&f4H}!E%iMBZHZw5?y0lF~2hI|nRrd!TcCAOZ2bPjY!yd0q8Au8@>lx7< zPwQgF^T}Hrm*^m7MOdA<)?#(Ux^t%|gmckz2VhrGXSucW>IUdd?C9jBGgJk4I4OzXnBbS zBN>H0tc~{gPk@*og%SwE1oh0*L(6ANu{M7BehjbePmfKOH!cbFs|wSQ4;GYl57s@| zc(iLiI)r8O?8N9N)U-%yUUxE(t&scmV+E7h+S>i2dPVinzJK@UhEea9rerfjiZ4Ku zG#VmNjqmXDv#MQe=%X&aU+)>LdCefIj#Bgr0HDF?R|2x^U=anbybSIUa;f2o!eFfA zKtsk*d$3;fY^cQ2$kx^w28E69tW=%Cl~HBI*CNZa7-K|?P6y42*aubPuU6A`&}8@+ zGk{mdS^4FtY5!Ty_xro%#AwEBYt)pLZgvuF*!lf_jpVgdLAXh$_}uj#@GcT1e!X zbndPmFb!fa;PbzYhGrNp3l@55$e$-FP=bYG@FSPS@n()rKo{hC%4nv%+~LHWGx@=z zSGMy|&Y2*mhp_MVCAPuJy0E4{PjC|Knx=^sQs5{4fSc%M*b1CJZ zZMC<$d3jPv+8+5@87y4v@EDL+L#;hYZooS(Mb4huCWJY|`p1HIbBg9&QaHm?9U&)t zAWAu}+df3w8>mKhLvWzHxlh;R^^r@dhI>G3FNYdY2aO2IYz``0DL|9UFq|8WKJ3kN zO(Cxrc!?&=H73q4!<(luhkF444oWx-oGO$6*5odVElwg1@oW>&2?Hqv``O6$qf#ZT z8^`Br7Omsis0CL0m{jEyU<1{&QhM#Ey3?r)ZI!6%`d+a2rtBE*D&c8=?#7ZM}yZ1>6Z8I2QE+-OYx#q6O|s|cTf-TF#0P~;E-755?v>A=sjZuV&x9j zsMe*xiP&eOz#$2Uh}`e7tZo*O-v!H?QkTFW0pZV-O{JRFey0}+Cb>}1ylP#4&Dr7F zqwy?&t5dERDAc}_DUCwCg~CU4pjz1`epYL6_^Y{$jVl{2jSa3DH8$#SPkowh7&+)t z(pT!}9U;qq=e3-Tt$dxz9nv*7%WJxKOl*iwvxVRbyVR=>H*-Q#nVJO4Fh`ZW?EC;( zpj`_+_?*oG=}XOq9&mfmA=8)pz4aDoKPlBvsQqn+-jwq;`Fr{KD4Yy-zfv|~3sT;V z2}zVgt%`w**4^ZSIV(Ve%6|e#b1HjS+W;CR4uC>r>!@s=TOV@LzLF#Z7O8{~6fWv7 z5lTm!Jrdh+@dHT>B{^5le75BM0AY^qQBcmHc7-u;GZBf&%j=d(`u6@^S*~x(%jUJ* z+zQDLL4j+(zQX%cNDL>fWpU@LTQB7(^h*Mk3Mxm4#F+B2x$8#-Bmt9(%ZJ6J|< za%cmi7VC-Dl^EZMR8Jr!uDOT^SV%D{5Jo8fhH(_MxB$!%G{@XJnAKoZA&-Yt1fEN| z*)jOz@eV@m1g0KS=#<)Ay8!|UWs)a=_=4mm)~M^%^Ip#$x*A*HIfK}S*K~%(9To&b& z+jK6ZH_m4scKn-OI37O06mG0DnFVix*&e4dmaz}5Fz`3_wa96ZSC^+JgKn6|-E6ks zTz@ulb2^jFcVZXi?{Qz8aQ}SjSc6DiJkjfIo~6fM=V{8-A%8r_uIz&n7Qi;#bB!iM zHI%(*10prXzzYv)l3ks^y?lY8sFWk_O$>c%%7fkyln;!gn&DGUf?50WK6aV)wL0;k zVcGUT&x4SU%U*b1qq%!pUaKCve9ipttQ+%ZQws+Rqa1Fq1u|F+4E02AomNuzN;|9g zf1sYb-<(<04>fou0dJLe%O(ZRktd2yF=giLxd4W7b$d6f40r6iIdk3%s$sY^Xc*olxxRa zN@!BJ#=rC0$>G|T5{l2FY*C7$85R;|3ROYK+2V#5mTTJ~aLJ<%CBNT^F^yf$0H_k5 z02Dg8;zeXvj_imSAUa+{!qXvQc;CTP{YKzuY*gOH6&=iM_WpZi?jIXjr6}bwLGO7s zc4=&79FwTUr=t*_KEt*c>!^nbJhqfcFv*#Dl2rxCW4b1@=y=;BO4VJ7aU{#&4 zQ{8tE(AX0c0(!*i45hI&$D%&9Ly&9BA$yVmY2$<@g=NU)Farg!oO0Ng(T;x5FbzAR|`){w=jMup4K=u*h zd@g=2l0+H)XUK+hlQrCs`#Yx-Scp+QratNUqS+wucY750-o+#a(|AafrU#a!A z7@^7qOP&sUm)$8`XD^fYd{#3Dl$Rh}tJ>oO*~on#ydJ_{Kt&^;JS$~Ana~RcqJ1`B zmoqoZtlX~^en(9b2n+6S#a@N9!Sn03%t4|NMg-|%A0EWqw&z!r^P9}b49D-qy;@1w zi_V@fgc9=XzyACSpYQwcKT3IB&Q#Dlw1e%!no4D~c7yihX@N(#EC^&wJ-N(@M7Jl{ zz-kO_rLebO29M=+>bYZ!QLp{*jG&~wKX59ccq3|3&+YZq_8NdvYzqt}A04R1K#qH7 zSV3N*M>`2v>@7w#jXE$G+VF$5fEJM~6O&I&!Z~mrz}UeW-30<2^~DhQ^tv4;HgFAs z4|4=MRDg_BJ73Y|TII3Uji+gO()K$_2*-E^T*uys$IKDFq4(Gew>%d*t~n9I>kR>O zcrSzDXcX3NYH5!!pNT!z5c%vxIOxJ9Lt5vLHo1smb-gJJbfl8Lh)f2@zyQr4Cvrx7 zc?=~REn;grMfU}RPS4PC@XiUt>pVU;0HpSY4BqWVtde*}DXWMm1lZE=0aKI5s~U8X zGIWZdkBsOg?gW(mdEa=v5t+y!HO+ksL3_@7ok645ohL7arHz)aj;iEi-3UyE^g&Um zF^n+*5Xq^)GHM%J3h84H8AsLjZc6tg`F+iK%xlfYcdtXP$&Y-koPN&d&+@XDO<9-N z;K}pGkh>R&t%V%2u|o9cwVcC>KNd<}5T^UHFwfS9FWlc8HmGSmm0xNGgF`FBT!gMK z&&915dtPaU%zO`0gdSXc|5OfVZAgz>H4ef;&8_RM89DGIcs=H@f;G;bho~gDIE^HA zJ5@HHjB_v~1;YRvb^?nP-j{^+q|Av_XRa4vHMU@cViAKFg;eBHuL;HFQl2g-An`X4 zo6goC5)XZc1V=D{LA=e)n621@XF@ zFL>Wj)UVrJS!}jdkW~)=*SWc+CkllMFrC*Eki5(}24IPu-xvZ%=P&h~2a(4NsCyz< zN2;+t?#t^lC}tP@fyYXQGL*NWXFJjgi)q=u9tar3CWmPYVM_uXa+QjUfa?e>aS=ff zkw+;L_M(q<7^OG#E(7H&5!Z}McSn;Zlmb!iR|FrY^QMe3E*SgKiQ}O)p+4zY54)!) z(fYC;R{%-eC-lq?d<5lOHYoMm?JEyIxV&f6nW7rwQF(nf(m2u`Bh~E78?AW?eak!l?WM>+P-B zD>$=q1GGqp_q}t^FhW@6LFN$6hZ~r@b^rh%07*naR4Fj)-VBA}u&?D4@dJ_WQfEO? z{0hAvN}DG-vwB37wkiYUd27FHlojsFiPaUzd5h#F3u((U%TvoOfC~4=Q<*PjRJ;an zT2{@0r3qju<{w=O@jlwULaJcw{Y<#-@u*IS+pUagc)>8RfOSzb95ZcdT_X|*V4VVn zF58m>wB5q%Y*B+V)=>g}9gX|Id+1&m9XNpLvHSt^qm3BU!NbtN-|jbIg9q(%S+*Nd z6z;Vh_D&e<$GtkmaHLwvZX?OX(dIEPG%6(sW(dL2 zn6=}_Prot@{?ohnw63AFr!y9ctCR;6g7Xze`n*yWxQFebk~BCkjE#yMI>uv$W0E0-P#HIW5U=2KFOR(59EJdXK!Lw( zgCXy^t?ywD>Plc@;JcUCtneM?ya&U%UfOiUYW{#Slc2#QuY~y4 zZ8TdD@YxAaQ@D^qXJXG#Xmdn%z*#`-JQNa0JCMF9>TwP#R7XvySCQs{XASl@0G{~V zfQ4a6jLP^lqTq&MguTF~BN2(9;0bamD@*6$8(UwVkMPjP4=oK(4%}b z3>DU$$FsGP;Rdv{!$of$?Sq4jP1OTREqaaQH4np_&5tfpD9BUmx4>e!4oGe`yJ)i; z>$NG3cFnwhEfaN3B*9OSpKka8=kpDQQw31V8Mmr|dAS^eYB?D_xu*o!BgO2dal>p> zFelOtHBD^8I#MH1^+RMkc?84_!u|r$^vBQB8;w~HW!;pc6WK7x$7Y>5+yjz_mMPgW z?2pfX_t(z%$FXKasmZ&kbIlMmr!K#hll3jEZZCL9THh_A%M>C(_r% zCRF?m2OsI>1Ev6rn>k;2=m!wD?D;-WwsU&uh5e;LtibE}T1lYE6F?2M1S5$q4yUqt z-IkY^P1)^_Wp$5Mt>N{AWi4pTi22-?#C z;z+_aViXL!^Pntqvq2SBFhiuL*1$vHZV4(N;}L!FdaZ`87X(RrT0MBb-VDG}KXL&B z5fdLD&Sj3gUtj@noRPXr0ffM}QidUSLAelmssr2>0@Tk7;|e+U%K@cO3wqrLq+Ryg zvYUu;tO~QJ*DXOmO5-ZPYvu!|{T3cOjS*0uj>hF_Cmw)du31c4wN>I^FJ<7U+o%eN zmj$fn0-@8au&R)abJy}&uldNs=iQ!Vk(CB=)%f@3MZ5_#-~;fN?l_FFw*D;lat^f2 zkqeIU!^nYK=@5|0F%4m!43+^I35?nqnCc>u70(3a?dk=mu#9vUz;j-k9s&GiIfgYv zjLGRjg$r*S*V=3p#UW0C9oZ0RQrAZT8O7e|sEL-f*feX84u_0EQUs*@9x`T2XCcdH z_NO5JEU3QO>UTa=Qp6R>=<}Wgs22@;=rv=F*Lj9K(S5Nj59t8N6XKBco89_w&cI$E z5QnvowF;wD>GxRED8mGEWN&De4P$x7O(i*LO=k3Nr$mOMsz&G&kzzn|XWHC`l# z?%8cE=Xwb+=tAQe958$^wUNwLc|A|fOC>L<+uTEourVND0k%W#Q+ZG_dXYyPg5X^9 zuN0)Y(FZKxL{tJpWOj2T zuh+~KlNbUaVbj(ke+-I7=K8cyO^iWq>KQ_Nn?e4&A3HDd%8-Y#jIK~oCOSB_kF>x@ z+wCI%TkBu7W+YJC+RG)29xr=MHm*FEGAu%1!+41`tSX9Da@W>ktBOEMz>3({xVG*Y zU4cU1Y*cN41{cVYvpLU9bij#$3ZOm+EQBB-kVYp&N|1kVrE18b(~zO3BD6ob$b&8v zrG%_S-<5J$9$0cmhBJ&4)*aGMVAy9IR(Jz>S89aBoI5F=buTt9Jonktu4FkR1raK~ z)o?c&%yBu2x8C!f0A_gENb%maCt@ymeD9hdtgV(iY>mAnto3SCQ*qlHZ`|B?AOAi-OoPNk@k-M}6;JDE}C zwellCz6inVoFOlwJuDa=E8AjFN1sj&u;pqXuY2nRrQ$G8*gr@;U{6av!Lz1951a*= zLZinAQ>gG~u#ONti{mtIOi1$g{oNf&tTv>tJ~G|cFaRepU(z9J>Gg^Q;gGBB4(nev z=sH$=_*iDk**6Kq@O&7n?2Y$TD_#pj$MS8|$j9d2y^g*1o$SH)kxt$B5CGZ|#D0_E zCN-7FCsb&9cybH~>Sc2TzE|q`#;$qZEo3na{pauW|JHY#!t5tO$9Cao1QUbWawu3^ z8QS1FQ6|z1hGDR<0vr;CK>4{SoU1~?8^X`j@Cn@HQAf#!AK|?t1>i6sP_zI!N%;x6 zjh)~&mAe4SA%{o>ga)_=EoW}j?9V&gpa=0fQTnq37Va<0mOM~9*SPTJdo$3aCJ=wPGZ zi7cNW6yKsNl?bB)yr?;bYjPc>vH|Pz#Zc(%4u>j$rUW6NT0QZQzL-V@YU?A+zuUeF z)gDH*zK8N2gwNrXtB(T4VK#9jWXCiP^7otrf+m&IW_^8p$LM#G=R}!a1Q)8{g#od@ zh?S7uF<9kBV={6vWV-{Wyh7uZN1Qzs0t7b3H8meLpwyTpnzs<|Fx9MHq!b-g1#1D-$oG>orAe@2P~irG)yB`ph^J`!0@cJOR?S%;9b zA=R1teeW@^DOYp+|3#PmU8hfa1EP08vmVTAIOouPJ*9!9ui5im7S@o%TH#+QT2H=O zeZGzNJN%q2lYt_=g7WJhG=Dx&wq3|O50>B0-IKCn$T_*I7QDSi_N!3SjXc4bBf5W< zEHG*d*Y4HsKf;<84DOB-223k=5qS%ULlAyN(A?>&pG-%uLF*Y+O3s>N`t6D zCgayw_hi;DyZ{=)eWRQ};}O?n8`m~&?1mO~r;BJFdtf|81Zn8YY2PO!ehq)FZk<>Set$2sr0Iy#_tc^}4C__nPzKHRJI^m_4U9 z2WyWWp}b)1XK}qZfEB=_$Wgl-j*%VKVYgB^gYbMmF88xxp@@U38rT2@fJy=dHP1-V zX|Du9N*!aZX&U)-THKOZy&^1E)x$&kcQUae)1HUP31-Av>c_}Z$Pje+1E&U>5Z&A` zoX<6qQYe%YY?ei4_tKtG>jhvz7&^+q+ff`c)oo4fn~>_9rw-+wm9OW@^2zJO=gCfK zmJ$6N_v^Qh2=~|Zx)`A9+5NQ9wsV(Uvn<@;-HRhHjBGjByUl;+8}6;<9*C4V-1CNf z6Uskqh9na_EvhzIxaCa3b&&=?vR_PmDS_srOoU-h|IPSI*u z+r0>pU&DR~Z_V(2R3e-d?oH7Z@?xTk8#Ia{E^m^?x-zKs__sxcZz zSZh=6?jFj+&0SfcTN(gryF-~mFraJ(-Rsz-Mcu{-f(g##^BHuk3J=nXjL-4f@0FhE z*9DD4GH|7ZA81^Hzzo8P)}I#C9&pw~d#uM1T8oZ&$GQocWou6Y|8^;n!_^Ipq>y{9 z(N5(ln)4PW>jgADy!4DYw_Nk4$nR1Hz&Hwqz6Ba~+_EA8^9Jza0NEYhEIOiz^u}wb z^-4y0Sl*u*Smvf5$f*Jd^@_agVOLfcA=-U^d~U2MD*D722edv)Cu!h?vZw?ft#k`7 zMvmeb-aCY8>VNHf>y7_xj9W;$20jZ;uN})K_LCN1rG7@CcNUPd)?UvPWy-`X#3HaU zOZM3?Rj!#vM9PK-ZLbuSa@$f~BRoYb5=Zh{%F@);Mxw*( zl;N4f!Ey+&UiU%fbWYsqP0?sgv~dRUic0VlqMn4OXJRkdkv5VE1`I|`jREdc?SB!G z+9PEHieQwDu@Tecjr?{evTFR3#6{O`4qprJ!@vXv7>rJ=Kt>viJw?f0{%JzPs~ zYta39u8ntka1d=^8mpy*rYuZ%5r3u63xa~^2i%7RatW5T-2)SEX zX}o%#V1>Hcy^Hrzf@t_$Dyx{3mlx!UH)XOzibL&3i8%^u6ex4#tUxToOtFA6fG@L_e|7sIYgLP-nnX0o2B2ZRVfpafWY9Kihx7o zA}bcECIPftdN=PY}MRvz2kD+Rv1U>PF^T;qiGqB18b26_7S+{o??Bhqs-#r2hg z<-JDg17S?Ap)+D1t>lE|I1y5{@F1`%dk*_U8P8i8CdR{vf21SC-;TWpi`bT9^z@r2h4P~6b4MhIDcRaE; z?{(aJQ*TOmlYm!45n(E1G)$PPa8v>*6IPUv+@(c@YS}AU9Oao~+|Z&J-vc2Oeq&By zfctYhUUzrumIySvnd1nCyKD$}W$FYy9_CY$u8aaK$utY2MvY`8_h9#aBdn7~j*Mk? z&13(9ahY720;dEIAe=bZg}c$xk91iO1J#HUQ;w?g8KEul=m75N^6tY2a$=yo73HwN z$xY~Wqr%9*y_RZKS4TK9^N2#oxyeR56>IQ2uuT^0-?4`q#jNoNz0&p?lRj1JU6W;r z{#Lyej4{X&fEGc{K-r)@OPvOrfjlfL*II0juz4JO{B$~+l`;C7`vMRW_z$6vGa9I? z6IHXya%gnMvX^Y}wGgAG6`NThP7xGK+di326)!$ID z6h;BWLGCZ*OKez)qgbKy30qY{0O=`&G9J|h2P=Ai+?CyaQ^p8IyCc)8b#B7&QCO5S zOR0zkk6hSnxhl)qx-26MPXslD0DGX{m*vfa@_Ls`d3xTI`TDlpp>Hs9?UP-3MZa|N zQfpI)auhjLc@J1CXrqWcA`t7${gY-?&qeNMf=l;he`=cpgfz40&5emcE|bPUc*mG* zdZy?lA9dL5q?I|+p~Ntj6R@a3J&uC=9;I4Sc28sLR`zOE%UAUuUzg9HKi3}eP#!QO zrX#FZcyG=@3ONh~^}5@XvfFSzz(N1~{Kz?B-Sl`~w!2;V`UGxmL<}b7^OvtRRI2ht zRUN$UwyN7*D1vc&gF1br0uTnD(=gj20<+nw<~-)uBp)#HA5v#9ENDzz&gEuxqlf{3tI_GMrdg&7?maB1+qJkJ zK7W3!&5y9A*sX0oDYJ;MxR&1X1}%|apP%Re+~3_0)sL0#Fg?!&^gNU^3=bL$LXkt> zGMcqLux1{2r)N`JTt)*SKN)F@-WW*_z^If$bA%?UQO@B_j>qL@3F_Bv<)0VQeN5aC z`oo(*=xUKzu%es2Br-g%~R6uL;VxtSk;dxo=J4U66 z0JM|QjE;d{h%S-eAo^%P>BG3Lkpwr!a@r{P=PBDD+hLeHnujQ$!{t%)zS-?`E+F;E z#E8nF&`s7iGZ}(*BDC+VFIC>G*2DPs5h(Xz$yxKNO>?Mlk1Vbs3lz(LB0SYwxqeX) z@WESGA>Ekru*%gBukX;Ntzj$ceEw_shW;7)W2)k>mbhwhdk^0C{H^oX-|Tqh5b!Yc z?^llz&}UfiMrICMGJ-kmJQC=QwWEQuMVJl8A_oqo?dS;0%pxpJs@Fk2@m%g7Mg+eB zNOJf7LwUG=U^w~!;+oNzJ;hOGc5`>9ai56W7~-3T#if)R7Hz5&rdg}3x|U$aLLg-$ z%AcH4@fd0myYGCC!q70`rfUpi@XDDhk5q+w2f(o6ypZ`x%7n&Hu=WA0*4E}QYNEc^ ziDTiMI+@i);eQQ7?0YCSDs_#k!tudTjZJ3oUVzx_U3*S3_6)NJ$O?oewC=HQLV@N8 zf(4?x)~P=HOf)d(Ja7jbTYAM|@jJC-0w%I}$-_UNl@nEZMpX##T6rG{sE7P3uF1K* zG|qh1Iv-kOhLHhAYG6pHQHOHpzJJ^g2!Pal$4VXEx^v+U*F&hIEHcX$g<QW1KXh0)E|lprR_IXf*<(+U zP|HIaQ^7VznF`V&pzI06ybu_Gif zJxQ&)VX%3PnK6`~vUs%5mLtuG(UvAcSWdSZU>vWe0dSo)gH zVWS=}S>Y!e9m+!+G%2M`*$U6N_C^l&zRKwwi<6e7dyF5;f%VvlvNM``)Wu%~0K$q2 z^P6=JLTt|b4Zw}cS6c}<^xM{V^K^3<>|n}Lr#os_F8v^%4M3Vot}r!fc44G3l`qa2 z)dnJNfv`g)3gu@_K~T_>Q(N8gDv3sLWoykfZf?%~NO^wLs^{>Z*OQG2hps#>7l-IB z^5jvkOXYPIr7pZw=8#EY+e*-0UlFb(eGzN@5te1@Dm`=aU{$VG!^j6U_3^YPyc{Buf4$=rwN-3pio{LDaxOTld8-6~d z)ZkS|!;^%KArmj&M}7Ldb^GKx3NCu=4K|pX3-iK=T|~QBxrC@5#}EWnh3gefo5*r^ z-qHJI1E8p-r#3TVr3rr$-+t92{x>TgAgcmho|HTt8Lo@QeQ!dsnnnr7BpZn;*VJHR z-t$^%dSPfp)>SdkQ4xCgF&LjL9CU(V9eNXpL#xWx7`#F)f}x_yic2Bvo}eZKQ+T$$ zWlF^5pzrz+%AXgFy#py3j?14UFo8a;R#}wwSeZMV#tjF>22cF?x%~e3zo!@W!|#4q-oN{< zOcu+sg!c)sTU-mFDuk4AFEADmqIK6@W_2n zd0n{AHT%`)y4on4^K&9XfKa^3$PS!m8XeJ#y>4(SYejv4ghpN)T;u=;89YVBe+a}j z!sjn9Y+PYr9MT7y&9p2r|L|1M$`zgyyf~C1(fiYH;vv~OPDmJw49nj58A8_r=q*S^9zFNahP7~Z!Em=RkHGAI($T$BHA zBQusO1371+s4Ed1%B*l0dpRkcSgOO5m3gm6^ZTwYuuNkqvr8(`fW`vMps%dVeF6?v z%3U{){d!0{zl?MS`Vp_(y3!sp>lza!XMUhMaHL~Ho9m$^MPWWpCOQ?g}&;B_(s@1-yg>(DQTbA@8=0=lj~$Ueh^}UK*ycC{9|Y}sywa< z4VT`i2?(e_RSTY(gFMd5)tYQ=$eRN6G{3nicen4#WP$uVLT?R43q*TsUSWXLbfBp1 zf#!Q8H9D=TczzObE;Kw!^Gf5T@~LQEvEN0% zW;cO}b(-3EhM1Q!pP_+4Q#MpUI{}W4*c4H+!?{arP-f#g0`-pw2=mOr0T9P$!Wj{M z3n-+#ri7tCHxSPAWz;?L;7!;XAgA@4^U3@VLYJ4eL7?%al0BWv4N&akMV&hs29r}W zib2)^CNnAt>}&v$c8W46uYN51sm6or?Remv!kC0mW((f9e)GBlR5c#vqO)SR=MC?K z?LIR;2gVs%2cKjd*pQ^$p&W?vNuM(Sy%g?AiCSqrJ%4Tc6h`L2c#sjK$@BT*bLKTw zzUm#E4XqkgOMo`sSJ)sqy2tg-Tqi>BO?K$~ibgaKIgH<0)iaOQxMm;JS|x3&BN)-6 zVT`?83L|snRiMGm_LZKwdp)?7tFcGeKQdUNpEkX4U|`(x87UZnOc|v})hfiQ0toB< zmW(jQZ@3w|R4BlVk#al*aB?}BGxdfj68@V&>GK3p-4WEai*>Y^MO#?(EgB6R6%Na4q%^km1&MM)reHAj@svZ!4D^rZckv=jf5Y$H-c8fW0p9f`e1n zMeq<9$m{V*0rC1iM>U+iW&kT)MRO77KvS)1xql-MogW}u+M2Xepz^MLuPMa5k+avs zL_ay8vnBtw-jC<3p^#4lz@h*EAOJ~3K~!O_uLQV4Be8Spy=k)}ubZqVUke=9>0J5w z`_1cD4yES_^c`et&cE}9&*PJ4jhlgFF_;`x7O2t2jsjMN*g&fTQ8{cfU_%6a=Xl|J zuBTosmRwv*gLMukZthQ?J`rSc4}cl0`o)T+AzEBR?rC71@|?Fm@2S+L<_Cvs1j6SS z$9thu@zyR!Vh~d(>}~kf03R9^(Yx53>hch$WqWz4-hmB{>`h6bw*F$!;ommc(BsRm_YAz(|CHkfZ1Tko_*St(sAjZL+gxAfcLz>BU*MG`7NT+ z^MF_5*J}qz{6KHFdvK_^DF=Ci*Hc%S27*|fAZoFZg!|73Vc(yPZ>6+`(HNd9>YDRh z^@g6_Z`gtStU|UAWuN5E@YRIc1kbeh& zWRIgVJE62z5li3#02C(cBXBIF&fJ&rK@}77+Gz%|S&JH}wARbmD||jiHBg}gf-Cqf zK`|S3^K8&#rOT*9N_~Z6Qs*;~MrCErw!+CstLq>lD!mTP4xakrU{j}vbLh?dy}VZP z0>U1}9-?tHK9>pPPhLcWFLupN#K0qKrh1uyGBx>rR#-XwsdEn5c9eUUA`E-30`an9 zWS&I+NZdx;4>e6Af$>1)d&mMpK$`>!@UC(9vp%QhArgPzNb~%D6JQ#H z!MQ78!+{~t*Vi49#2{)xTU8U2u$$#b>~ZweqrTHGa7P3EiEF@OU#@P5xJFksP`;uL zeTptdGa=>A4E@eo&t9V^ih5PD5UsxeH4(=$E!!;{0>tM+gYsFTD;SAcf}M-(dGNYf z$KI48!f@Q)Y2&-R2Ej3~ngRTx&8kv0dn!4SAbdv4MM-ExlqC$k(Y{4pEbKD1rfEMJ zoI@Y>2%(cfF8VF|+(LGH6Kjnl>@^OSG~O2)wIECxmSh6Wuc@UO0ErZOoHbP!a%e5A#q1PuERdw;nUb*tD3Pi42+5ZR8LGHceS%kpq{ zTW)Xfd0#LNY!oQ{bU%<^kRy!POq8z&gCrac&_N##;=SisMi2!^YFXc#Kg z%@s?yM^qC5@P<4-dsFPotf(ZB(MqfxP*ihostF13LwF_|&FTyY_1wmN6o!=M;Cgp7 z0pC=L#fpsJv0(baI_A`rcw37N)4`Om(;vCyIo2BF6%8VTWOWio5_0sEXD5rIHcn#{ z9b!!+djqt`Fn^>z3F_1jq$sR)vxlBH8tb1^F4EU< zC^-|%L4Xe=wti5-nH-c-uksyK3_i1;G7_0061)h z`pZ!{u*;-Em+&yA%Sl-PP0G$m2(=$ct(fzXP@EDn5-=bsfdWSeonHHFQEuPemeFWe zzC1s%XZdd^pjtx`GM3F3VtGSuY=7dW83?&(R)LNbrcQOf+zn9La|Oug4dYQ@83M>t zjeywr7LM{H0(cdyQN6L1^V9MoTPdMA2wc+S^<2qb$YyL7Wi)AoMV2$|3%SfQLs#K5dUh zG~;M!YlW&&rUmpdjTzKplVQ&LU-zn>(r{@+!>Ukg%k6r-s1Z+#RCwMqP9(Q~%zNmX zfjrp%p)mcK6=(CBY)lQW>AA-|0XLHK?z&cD|6(r+D9Rzwb|6bSK8$>={GB|v`Pt+_ zy(QAI*y{7Em`C3)#;&%K4gPVbA;1y`#pbrJHt4Wk@qIH7V%^-`-BF=CZG`X1TNis` zmX%1Wh$P7Xw8Cai+x@Oq-q7r3uuLIi^9zuEIaO@YuCiSnp1Rf9v6pQ>%QI z&^r#fS0^DHN&;G0UOasDI-^FJu5|j#(eZDszy3AYLr51;ueQ%8|K~sa_8+zJm8-LN zZs7%BO(sjqp-sGym(zl6%G(BjCzb_b}E4hiY{`9b9m zm<=uiqVTu#_j$7Vu$e(fUV!=79AU6^=E?MD&RdhSI2LsV(ezAsemTa3zE6@YIuva3TSOwi9pwSJ{;<12xuIf z1AEr)lOs8LVUus2Xm=6F;OofgIn++!<&Zr|OAhoh0rbK#2rFXlLEZvzn*9KHDpc$t zP*?{KFPjvqU}8Iz{Z6?<)VTAS6l4v2R{?HNXakTUA|eN-LOgD;#wmzHz!7s0ck}!L zYF({YhC>M`!n&W)n}El>zP)86NfirYMpV8&KJj|sZBR;Hh7;M^Q1c(-&A#l29Bc!{ z9Z?A=>(|%kvY5@wci(;Fm_0o|Rm=h^44~v8q`!RmR5q_Km64A41xGhxU#Z{vmIDl- zw%aP#jwOo<2@6GxpGbKElVK`fE385?b3Br44Q6JZ<;C%XykjsI^V)#{E2*oa^2qla%vDjfv!>|hOcHkez zqjGn1S8i78h#Z^)FsWz5oMPPZ+~7dJzq>6z{`dpyvf)va3U$4rR}V6()e5wzkP&Ns z#?(p>{vdA+qjI%gmtTJUwS0N}s;>4EtZ(pBs2q@lIV|558l1s*M(-w!_9281Sv3V{ z7h!!y_(E=B4HK(@c~ID%$xxKxF+z!SBfL_j3=!>dH%ROsj2p%U&j0~3n@!8Z!vpy; zs7uChY!=ipTrccKBpevN>uMcGP^1GR-N^8~h>>!7jf`_aS4|m*H4VoAy%HjFklEyr z((}H`X&*PABF{F09y@ScksyvAiSF7L46kz-9c&{w4hQ%FS=3ZRzpI1d{radV4HZEO7J;3a<%739F1qjGI+IZvnN zz2!B95}q81vQp?nr#YkwAynDWoE``-F0Y}?5ubDHo*!PHp;QS*mWri(yzc?R9m1CB zi{qBN3{e+s2pBRF00HDAW96i5wx}BxS3Bkz;J3xY9ofNN*tA1NvOH*k@qEu>{R6Sd zxQtJ8RuOm|VxC@JpX#&h4*Rmcg50hto1oUsQ51VU^;x5dP8Mpzh>Pp&Pj5cccurNG zIhoL~fL9Jf&vRX)2T5+ZJ0IwBoleN!qtNg{A)AczYjUDTuh-~H5P?(yoyI8tCh=5C zKRK%6bGqgnBsdh~GN1P^?xBJeNYY1DTWoinQ5H++~@MYMDsiUf`IBr9&W6qCTSwWmg^L z^Ho}4)SxdxQ7zIN>&NGoT9}gVp87~ix0YF|vFvQyMMHm_&w61M!HBCQDxn9fA#j zw}%h!c|BOY5O}}+@KOEMkH_-m)912S-IV)>_v+9Ekc~OS>1iq~k9({ZB!!hjQ@JwW ztP&`IjmUb0JeWK}UO)A7)?6qr32y|JFZ&+{s0X#a6mplTEcCd}E^4W9PB#|HrDsGk zhk|n?X;`1$a$!*DXiLf}gH&V9wG!=EvDspJBi!ADZAGVM0f~qN``PO`yhh-e!wa_o zApws3GCF2KsYVIi32b&-dLuIkS2iaJbntOYH1o~PlGlVMI;{wHh4<$%f4DZv4_{wj z%Jb7>dAMJfCE4w8FQQb15dn`M(GPjDO%RQNI}U+?b1egG1_2C`D5P+m8hz5m2HNKSfVpSfWp97a7>fRc0jr~y1mz9rhN}glwVkRYNrLHOv;4B(*CqTQT zjAj|CFek$BknP(){TPSxJYev@xF;bMNdF*Mp#hx)vCYSYQy;QGhU0oeV87KCcNi35s zYIiYmsPpYf+uyyS8d@{M_ubaA{cWWxg;5n`YG$JQdfSO8hbCkg;_ueAOy|Sj%DLzn z&F$<+Kr6}XH&>2YX?NNp)ZEn$o?btv2Oxd9(Ms7J>jdQrI&?-e))G)9SLmhjjY>q%M8 zrsWx-Y*5u+Fy{bPy)VlZ48l=4?V$V-ZcjuWVE|i^c$|TbrUFTy!_X9+?UAKJ*`sX2 zs5Q3m=hq@=j*7IdgTuX2Qy(!NeJR{*9?W17>c_n@TIaktLh78Wd~d3Uh7cVXF{uev zb`-eZyT%)J-^VL^ST%p#<g>Gl!p>^--gno@HRtw#vB~aqu|M1(go{Y=O%a(ut<~M&(nLkX>+1a5rSXL)eIspMlC$G7ByjyylHflh`cEPF43}(UODFqZC(Ll z!GlW>DLQt!5@K~uRXw0dpBad3c$6ded&jldphTftZxCEt(F%<-dtM_C5B_*~BH;Fp z<|PVohoS)783H3wcuF7*BQF-v2-(8Z1hW;e3iSwN8qj{^*F+3+C!YJ_`fz_5#5 zt7Qjz+`R2CFVE$&KbF;6Ub4~b_&1_1$oH`~cI*-4o?l;<D99*wv+(=M(W4wi4ejN91d}3LnyENY#iIT%;jT3%5NgiETdM&{ZJm& z=u0#!(Rye-pmF~D`+Gjam&eD7^#Dga6=$5skr5-J*}H+ucxVtaM@o`}W`y$j<6K6e zSEV1yhWA}V>n&%l=0P?t#mUePY!RjA#F!3R@^_Csb2Q)q0B-a0LL@ux+I!q%pWFX} zK#J>XZbB&YhYZX2)N5hFD2VY&w|DEZ-2sCk>R6<2s01U5L+R?~CAGngE0F>`77>hP zQdHIhvWY#%oDqfZk&BMTHR?pCy%;D2{vcAQ_ab5j8G|$c^5k=LgA9-uL1WsRq!^Au z?yw`OB19-&^KU0K96mDNkp zD2qA?fWaJ*4GibygEZp}lbI(GaPnsHUsK!}sF%-UAyutnT9+#D&v*b&%-eJ52ZjsS zmAF{h_n|2Zm1wBJ#17o+P%h|{v|g6^WKl+COZ2sKjJhWY5NvdEHY0357XWE>cU%7a z&;Pvq>DOP%H8$&#KT;6IvPU;Ut{D-;m?FhPcI*%jO0SkIRA|9_y~ddU#IqJY?nIwPx?wNb?+F z@jTn3o&1^}vf)wZYf52b10pOKY->U60l=d@JSp_n2i)Eklob@w zavn^M(-FhzyR8hM^?F&}KRlG@ub(4?dZ1A-Wgbxsd6hZM=w|i@-;s#Mc{^8gz`jo^E@4t>!eeC`RB;qS^(9f!8Wt z#x<}xOpJ>STp7M?z2vcUim|>Qju$;%oO>j%ALKz;XKqqNRQC+mjV_e{DW8zW+to;+ zIMQo~Wgx$u${nte2&IRCg@0l{fs9E3mSM$<_k50U@%#X@BD6o%_?a1zU`;xxuEfH; z;oOQS_R(fLTAK6bpzeSsCVahc^B_6zlm*K0xvm2e{Hh_u z0I4BB(0|@foEHea5`SJhMJbfZTH%@Um9wYJ1_@3 zsNwxIb`!{Z!XVssa>YU zBseX=d9JsYP!UsEUPo>%Nq%hPGs7@N96Jl1M&QxT3k8evAao8}tRkcx^9@fwuUWj* zF;I7-4rNsA2|y5^h*fI4U6)oROb_n` zWoI+wlZOsTlbHb;4EDl|P0;#KXkTTkST~n)Tw+}SeUA)~y4U$x*r|^Y1ObD6B^XQK zF0n!%%KI3D=z=*)|F)OweQw#EL)4T%a4G=cglArKAMkozOE1!ys49RlThnmu{6jh2 zbeCV!4>H`)=iN>p_e6NilxHcORL7a5gBiV^oTDpX%lyjoQH|Ly3dZiAfuq1rWs0ko zaL4-AF7!6+s*B~EaJv!z)CVE>u7zZBxmmt>zj|-04M0W&iWnm2o4X49tB9Q^`?iX2oLwb_NmB$!pp=W{EI*P^YZk%DZl*kOZn@+`CBSh zwmuAW=*#nSS*})P9r;s=7p5tOMj0-*+ioOK!c+AI&^@#qss)cWCa7+;Iqk7}djn8i3~|gP&i9k)9tRDR{LO`Q$(Yo@(-+3m8ayj6d}q` zP#I*2d4s@2pL6$qmY~Ekkn(0XF@|!((1OkfP!Az`tbb+#f=2+tP%Zcd1}Fu{T;s-) zIUE~pPRX`)IF&_sC%``Jc9XJNF3M`XD7)=5y&VYX*A0k{Zo&|gFs1^G=XcFL*#(zN zmb$%!(WAYnXc5|4q6-)Eicw(#`dsAG!7_tRZtdPhv+2@U0iay9(wqp_Lu+8wQ7W$u zuP;+oTjt>RmoHx;lA}f*d^UJ`35?V?fZ`tRqIT`KNQ2lOm8p;x)nngyR5cULi}<+M zE7f8sD=Wv<^*by6EbD|>YVu8d35|x@;4JT{MHsODaW^&B?dOhv^s3258|9-B0i?oY zPJ2w^An#kWVa2#3jY9z3sL3n5x|`&Rl$UyNj)lS5qyo=xD_-OmuhSpb}l)7EuL;7??u(!N?l|wagZnwW^eL z+Q@a&N_Pcz%5RV`CF+OCQH*thd>d<5k%Q9W0tk@dv)NpmA-WH79HNye%JN<}stY}z zKt6%b=H>SGj#ej03*uS94hPCt)S2URfQGP1=V%17T$h{MTYC2o@86a6>ZVN4hH-tX znteDflUZ2=rUAl?89prN;1tJVCy)g~BI>vgJLKQMIyGUA2eqMiR^)79FyT1laCgjE z!+1CoEC;Ux$6`Dn=uut;1%Y}_C^iTyq$KctQ(&U5lr`v2&y`5$_WqXnMS%I(4<1Ze zM{(ODYzS`>p4sN*iPys%eE0D~`O_c&$ebj`?yv({&mqPfg7L_)gn~fm4#EY1Aj}1c zNWx1$p=;FgJgrAu%i zO4Z)Kd!XkDA&xP@vphdN5!H(^ftb>sozYl9qZK^&B+W-y;#ImkyETc+~dt_*^}BMV9xfZ|k_ zN|dvNwS`fcP2rI*%A6&okUOxQuvd`ML6AXAaq^ObaT2U=1apbAfHbJoS6Yv1W{%Rx zO*x)HG9%s&u)=`}a5S1RDmR`knN!Cc;+DTYKb22kJ`-+2x@trxS!SkZB*(&7WyX9KJ zGoj=T(J0_WFrM19$v*M)_;r0hc4IMKJV$h;HyVWGeQD`yphk z2xKSrQB5HR8=P7RtMB|UkRK6G7?a`XvSe{JubcyPiZO@S`}nz_U%P+J`$CBd-qW8-aT-WR_nY*LeN%G zVQp+KwK#~f4z9}pI)NC17>1VjrblM5hx>fPV~bELJ&2=n; zU!xHf>0yhoY+Iu_-wg#vp*^26p9@coB}cpLVE|DYGu>f7+IWT7! z11J%EJ{!pc*13hOc67&KY~^nS2=qSlzk83=T>j=r5TFiPE_GL=;~-!xmKEmgeBRYw z^YW(fe7X)IFi>@@xFLhF9G%VUj=T=`sC`}NN$eB)rBMRN{^ET^515|;ZmC6os;uhD zf$cf^XF6{fp=)7Xj+ZO73NU*159T>GXn}mWVQ=-9*G>8Ib`ixBu!hIT@K|mu4Vv^ACxx{v+N~Tm=7Wjr3r7&_MEDxE@UIO}=jnH5U z09i$NXv~bcEjy#E2U>x8;&3Z%BYsKP+(C7CPSgKd( z{f5d)y^c$l)Aun!9!w8|pCKO!Mug~S_>7{)59*U>YKH5kVPz)aTo-z<9ciJHkQ0$b{ zKwwsO@P@cHsDR>m&(orA+d+D_?6BQUOQcV)K_y1K5lk^5=G(oJ>8B%3&v z*H`6e@g4*V!FAJd`R#9iE2Z@Gm0@9ld5)~hKESgcD|8Ic821jPh2w>^KBoC>DFU*H z!P5u<$LLhlSfgYI-tYPb;|vd5iW1*3cY(s+0y4Qo%cWHZ9DBLY2)Vt#W5^uF&io9p zlbX9I-#=B}JQ*m{z(5=-&F_+BZKzCu5v0h(wk%ho_{86!`bAwjC_~Y84`WB8{376? zDMoQV9E)R&;h+J062H7jfhw0kC@KTA%r!8dDP4m+t`z`Y;6H%(2MSRVAI-rshm6R$ zOc%4V951=X5b?ox80kVt6nqy9x57)&T;N(T4hT-gK4r;g?0e=qXX+&YgLvG)wUgux zW2vHNJ%y_|{FwummrEmyvS36)ADk0}MosZ&kgYuJR!Xbxf06?McC!OQA&ml1;_4X< zG(S4`R2Y#t^`i5{_e1{W%8(qky{6c&{q22h!_iLMa*3#e_6&?ctWzj-Fu!5$*vG(W z+5q@wxtl?S`JP<9>@rZ->1Ua$zb&hyGJ;N!-eZak>jP1=SktcPSpw`B7((aHQ+F<5a!vG5Q|zpWqN2ZTVLW3M5Ng;3UPW!V{wz7J6G;(9{4%b4=9UWcIP z%)mV%8GOyCw4fr;c_G~H);HzL=UjY!PNXSW4y*MvGc=$e!#b>yV>%*C1i-sVc19|K+QZd}7kj2=!o*a=u zf#x)JR;2d!ZRC`o1NOKL9S2bCs?-u#5OgQwd@}qxWm<dupL4a6KsiI5 zP<4ay-fDspkrG6S*p)K&Y@AX?r`9O`y;`XPK%ma2GM=b=n!v`9m#$J#m0*ULDH&$OZKi6jY@{*WlX|PDe9%!H(W8q^FG?44 zcvu&e#pR~&c@tTPTw5?L3`E@;5 z9I&vWs{!*Sx-dkeCjNnx!ymSX&EL-gyjSQ$MUO?R+#Bx;ixq@8Xi*qlqp%>sh&2N+ z>T)Qr$iJfPV5AL@FNZJ%E1bY{M~2%khdpzIckkYlm;#|gQb(Rjd3oNH4?kSW9B%j- z%6rG&#%!&L4sM{oh8MV3s5FP0McEpGBAMF!L8!iN_6a!N53GZ>U?=+;uoTBV%eijX z%kuR28LfyFDFKiv@=xdSp}c@l1reG+;8O|h0MZj@IuXD}c@RJU@ek!Uzxho$efM4Y z=YRfZ^&x-ia}0gVgAn?wHxw9FI+Kx*EZq(JYrFPjp@pCVh=`3L(SY20@M|QG8~cd;EgVi~{ka4=Qa{Gx;Il@aG*q%$ zU#czw-vGSxnnEB@5K0QyjOv>RH%p#{+_Ag~kImm78Zs?P=sC)Asu}_`QWS+lgb6k5 zFhmi>LYfXg_?sRf4fY8=!9##vqt?sC+vqS)N1Tai;H5 z6t=P{GK~Ub2kSxSgflP-kX&}KxIO~w#dDg+B>4L^9z*i5EW_FDlkdMZwpm>gcnHV< ze6#0Iu|bBMeU1cHhqOj!qgM&>pHTwHG|@19p=(D9G@{1fZgC+x&oVeTH9GMtmvJ!U zm2$2Qm-aW>LgqtqdoQ{{`N6rBXw=+yhcx&1@{1OUS=(&Eq|Y4M%IEN8T&^5HSmbXg zZ{OzEuiaBKO5T3|+N+IqEI=qWqGzG7X+x7-1o_YR4|nDDWzWVK1i?gj6pPM6+l+WG zFR$fgv!f^f@yDOaa(%;^VIYwopd?3y8+Nre>RAfLp7Z5`y!fe{_Lp)XgA_bsU!Sd^Ja{?3iyW};2iNl^!Hc9K(I;A6rQ}&V-_OQ8 zXlhYgDrzmdv`o*Ulz~$OxGux|sZToQ0fzR&9L;f>mq-4Ah?Yn}sG7j*hQK(M^1G&A z^JpcEYl(Db%yGuwxR&=F=bK0-^*zVf)v)lhT#E2D9e=`1;nc|3I=ml_H3-sDL;bXh5J@5!V3F^A)F2c zfqL}n~n@T^71XDW8!Gk;yPUfvbzus26m)(5?H_svUQ|Lc){#UTJ znF3wz+Ld!>$Cl@+kx`|p8>3;XJfiHD;z>WLJT1R`A(J_<)C#q;VMXdap;Q&HZy+L} zA7vkNFp{H$tL%LBFk! z^!s(ueP zk>f!jO7ZI>#1%c*gL_#>V0}kDn#JOVhyuV`XDs9y>OeJCLr%1 zcghKe;AaOmHdcWonerZZEppQD=$S)F0l0VC@5h48l_vRk1*HK-?>TtG`hO3MC+P_mLhNRd-ZoP!>5#C3><>ep+^fpq>u- z6DnpT3`r@Lahb8k9r%GE2-ht}uPO5!HO=3tsUcvPCWYWmC~}WK#1b7ai!8Arn}g;vylBNHkh_K0?vN?~v!*Q5c2Uk&eRtHPCjoT9nm7G6hDx z(_YX4A|68ydq_|N%uGYE4;wSlAU_P7tf(9|^Gf7%sR9DB#>PoaOGm`QeW|i;AuzJ* z_G$gZv8rQ;@v+m6^$J5kWL{j)N*{G$;Hv7T}azJ_H4`{{Ds~X`m8?_lVrr&!2uRfA$~$k|F8O zk6&cDhp;4l>uMNEG7TrITBNmA?n5I*Wg-w>9A7X-kt#UY+(5E&+Lz;LQf6lv3Q#8E zffkCIp5E(*3~x{vgWNs6K5dRh0u$CVb83^a-v-Y(xXBah^WXm4e=YAG?#d58{80YO zfBAo@z;2kAjk^Evx-Gb%^ns2?9v{b2F;Y+nSjKB5W;!Twmr~LjU5JWQbEqy=jv)B{ z-6hP5mjE&Jp=LWr_ZN6egoIb-S4XO3GMkIy7G4E8xF==%`XoBn8B;8CC)L#cbNe0qP*#uDpO}*l3FTV zb?#~lJk&wzZ~=sW}7KmSKxkZ&YF$2H~bT(GUl8G2`TISX%6D^rJYubtDOgDN0W4#e+$OVMhfgom3- z)l|L}*R2Wx?@Q6rs%I@E(6}?%?eq#o+8?kZG4GIoq@@qIKvT%m3di^3iIY;)f|f97 zEirRgg?+V=J7&E)#wbeiqvoA=5>09#JdtZ<4JT2i$n$EUqdt;~2D#~5)u1DUdVl{w z%aA2D_jlzl{^BpV@S!+AeEdiyiO>~WbOK!rff9=n06f>uV=NE`rzgAHu>baU^QwII zbi$f*_UC4AX5`b4B%OgJj#_m(MNsDSI8`V7{H$7Jd>@pZsAy1s??c%E0nh87Sl5g> z;=LiPjQ-^iGNW-Vk;1u{_YQ;L%KDAOqj zL}XMtc`1*N0Nx!0HjMVYI2WD)f8*akzhmvbzHZ8XcPR7KoFQ%eAn!h%P03M!h>hx* zN33OrLRQ`PnDx-O4(?_1tRC|4{3V+LV20Ea#(BA{jhIyVF)ve4*#e9<8MEK_bT+2} zvs$fd1OX8x@=qY-OrCz!u1f(50Y9qs-Bm#)GAu`WGSG1t#S4Xp`{+op_+5tZk>8JT zc6nZ;1KE`jdnt0TxmBu-D$I*zwT;Z|z3bnF=h=cU0Y>+3SH6CIV*m5!mrZ$jei3ob z#D=cGj=K%!XCkZ)yG2H%6zAr%bq*IIq*jzvY^LQdWr9c^IXzT&PZn5wE+B!pLs*}! zp7W^uScCX#4P*U4@+Rzsb-agEoT`Q}zH07LpP%{u;0}pqG4POiZ=5JaYRo+XBVKJ+ zMI6NAf{TS7cL1{4F%!>2bh~&C6hT466|&teWJPyw!wlca>ju}uUV+2rHOu`ITnFYW zP>L221nn!VS;!)K=$>Q&Oy2gL&DLeEo$kHnoC6pjAg_4*e&w<+TXQ|1dNu(1SG8=q zkhg&>o$*wFazdF}a_VGbrNt!j`Y=CWkvzYWEyUoVsaelyZQRwULK ziZEooEc=^1>ttWHC|5d>sS5(sUKPk=)}a18p2~8wX8ow~4hU0`Bmuy&$+8Lz--FT= zss(oFcoYhes9NyFv*hMnwy!T@ISVg~N?|r3o#tt;+$=pEgmD3sW2wlvoMXOlzc?rE z2?7Jk;}vzv(d*ka)9^TPU+@~T2L%P{oHm~C)2CnPxj)?9m7jk4vHaoR{+sg3v+$B% z6wSc#|MD;YQvUAm{*EBBKmF-XHJXBZ1_6)q#fla{z|cwuRcTR43<6?M)W|tHG;R;G zTJ~V$+9DsRoIS3^b$>XNuaVC-&H&E_KoZBwIs5<};Xa@Y(L4vtfH?Nkr%&Yu;lzbX z+m@pVpZn8ZkpK|BFiL<{vtT$)6wi&vo!PnJ-bqn4rwg33#`>(~KoJ3ReSAwjAVTy1 z5%wNPl4VD-r8y_Tk`zIs`+t!?GOL&^%%*0iEiGsORh2ZDb24&N&EC828HIL8AS;MJ zf8<`HYO2QzF7a|~Ej6n_ml=pAQykSNdh4Awf~{xgln7q?z9NDg5HcCXju9UV3^x*? z(P%Q$-?Of`Z@Sl+F;C`3L8DC9R#fU-%ehv$^Q}rGZh`hlz1n-`GWFY>6n=lbr=ME5 zwky}RrEEuQLkKw9O#J$@ir2g=2{$+c|96i^P?hS{lLLCbr?ZoS=}h28#$PvUx0STt z6L;cPoTWbn=u&(0vS-ZmyvS5*roYhuxvq& zD%158LI2D=LU`fRP9ATpQ8ia1FL6)Z`8Vo|mzCnHX{D=I1$Ol}*A=<;dfQ;DJ?8c2 zUb3zB?-Aa}pqgan5%J}ZW%l+0FN96VRjwR+{o9rh+Rc7l{_(7DRR!vS_tJ1Z2|)4h zwm0pPg70mIo?5&Lstf?~XX_-J67#h~_g9N*{#VZZ`eF6gSBvFG(1?tNpta34sWf%D z`PHvRF=#Rr=}4T%=7Si`;&__GXuOW+XN<^BSrSp|d`YzWAwK;4PM?Da3q4*-r9P-! zh2hh^X9H$w(aVHrxz~dxxGYSPe7AM4md_!}^h`SJ zab$xq%^~x-i8Y$p!+|nafG&>*J4>A5%fLYh#zRhS2(ZpdRwps&ZFN0tZpN*YVJB_n z*Uw+<^tbf>EI-LwTFhqg`#=8~|LfoXJ(dZ+vy;QH_k=FPiO0G`3E{d+{H+oo7X;p#Nq}Z zpD9o2fm5CN`sI&!T|KK^!$bs`3My(Y>6St7OYe*+WsKB0>BE@Pcn@Oa=hfOF%QY~G zb4&HN4Cab{m3veBTi3P6&~tC?JSm4_s3|Q=4NJWAklMJC!I&n_-Yv15gGVaXg3w7T zYUVgqu;^uLf0N}*Vn8o^GL0pQf&`RkW@pJ?^Yvr!4;~q0;-P|F(W5jKwB?-po;x)6 zaN9O)ok0ce&JMYERf_GajD2u$*?KHJF=zd5v#Dh&dSIjc%YoQ-WLf=SGDCIcqnQ1!x&SL>^h_0;D# z6sTRoB#{(Rg=R3|?AL8`{@ecLkQpyD-+fO!gQp`C6((YuWJOqZHNlW%^}d(c_DL|F z9iZ26q;OArE9*YG!jvt@E3leAzpx=qMMCdSTn9WD_Fh*)JT31@PA!WePE%i&#v=?uFd@XEOtAg_J(0Yx3>@;z@=6WWSJ8|3KRuGEaW`_h2<{IehLk3O^GGQO-L zIKr(!z%qFRJo6bF(9a@s#GGa_5?-L= zfByMr_1a%BX4{?UH93w-$D-e4j-Cs0fLEnVquH$*Mzuo}uK6m1TI_2$T92_M>Oa+> z%CYL+D*Ghsf&mQ2IqUw8`vjnm(mwYRidg`J*ctU*#Sbx7)kN#~9I@FMO)j7%L0|(s z^ZMZczpmEGUR-k)4D zh<3KSvFFt?ZSf%$xVO^=Z&hd8XLbEM+4!`m?dO(XYOB=k^A(Ojh=2Ry`ds#gz_V@7 zTBXb^S+voW-HnOzYh84UJ{gwkq{=~6alRrVW6s||&o^bN>jirmI9z(>I%j&6icgyU zz0OY+gtuN*vT4!%KdRo;_vNHYC)w!y>YFt3vi0DMSn$1SBmO%7Vw}q?qsk|)5+rpb zf0lpl1?_0l5DYJDsbNi7_=6Zt=90`@ZPxMq=|$rm^mVx(I6Xf9FMs)K{N>l5WpFXV za>Q&EmCF0iwQ5=cbhhU6P9(I-g92JH)`UUk`{G?b#Fnu#^vY+>8ZnOa;H51rFv(f1 z0cvS%!n!})$E{f4RtAyb@Q1^AxW8Agd$-%h>&uf$_C;udaLq|geSEJ#;E&(_sblebobT(Na{4*GeSz3!s=s-Db*6UraIYYNfB*!&#`CnPjfFT5 z?6_5q-fyfWExFDTcB$FXzMPD~X-Rt&)dRW%-M@3stPHRnot<3uLWL?8W`eRB6A$lV zzlF0N02AOJoF$GFAmK>C+#jD_lG|VxgPaf`7$E4Y`Q9p-CzU|wypJ<__}mXr@tM^o z16`Haap*RB1l2D4a~(EzJQI&O_WRE3-TDLu_we6S=DHQ6re3_rKa8X{cRqO(JjJ&F z03ZNKL_t(XRqVNQZV&!f7_AVfN7wrM8L|La@B^l z!)K-@c?QzDcb$RFYshrTy<(NwmONR(=6VXrcat$wz_XJ?`ND~ao|3BHE?{uJ{W?GbMo83a@8yl?-h8M0f>q^?9OG3ErM-wY^VCAt^Z9c=^S5rog=21H z7Oykii^{vnuOL z%iDx2QE%(cC=qrJ8r{S?x5^|Hqx5{cFL{S3O2%Ys=eJT1v@h8%gR7as+7$% zsg?pU+7t+lG?cKlUUUy3S<iagqthLcTb3K=wvZ#BkX2~1l&*!&h&Rb@^PVno}mv)#p-M8|0gG;8k zJX+`Yx=kc_{^bL+Q*s7g2W(HcjbPgEFP)y9n7{gQjgc7`|&gKU&{h@i>V$`7X{~xH2De2grzl@7A z_nZ<47H?+ugIUZDlX%_i;tUFSW+yj)dhV!e`QCuFeSH7^HU9dmInTw)hC$<)X(;sB z)jNiOA!<%~tJ6CkY@FH127OJ8#I5Q9WF0xX$~RU5Geexq>{L{6{2o!#{YdsT^e zI-g}gST^XuQzn;#O%8T?(p<}S>oFCMfwKl6R!&@`E^&(0VHf}S$3cWM{0&sHFw+(K zxEwky3Q1`s2Ee!pm&@mfpUkGtqUpKi{n;H}71R{DN@-&kt!b^_(gG;QU$nF?X_Fb6 zxe9c-!CUhVNP{!4buFc@EQ7=3H(Ta?*=}QY=W~YVemZn30G2>9)90_>9l<9>XjeXD z@34+@zj1D&pj8={dEV4RPmpDe^qD8$S*uEXITqB93lRYJ<55QIo~55%*=ITaPEBz% z6zP$Oi=;|AuoP>GrR-9(+sE`)p*J}lPh*#y=c)|we1ymz$9!R;rRicG>zCJfdi-WG zA!gLc^gz19h`0sCothHjQpk3M2-FyJOE$@5*HAy(*4Y&sc-3`^t(Np&8q=w2kGb(gq8`o}@Xld0nOsi{LRv5+AWB*zq`u zBdKaua2$lVf9?v(xl`+Ou;YMS$L=oPcE2j69@{LnOf%Ej?7O#Z=Dy+>OdFXq<(kKD z#Io9epd5MylkTeJ^ zqN^7%Ae*^B*jLtB>P?sBd?Gnj&l+4nzuEGJ%ibm-02eF{VoJ;%{rbfQs&jtpbzO$? z-?y1O3#mYH7QTRdFGx4ZbuzyEJ< z;4Qsdocvsx=VXUu?5f5bi7I6!#C#@&H~L|jb<@{8(4$SXw9h}M2vnlP5Dj8*!1<5` zCLk~+1Pe(m$wVmyxg02cfOLWgaA+kB&0+^p3|TtBFY(w5-F=AH^{d(o5KGXnr(7;M z&UI15lC`>j&v9@{|Nd`(Q5pLC*Uw!aTbXY<*8TCM-z#HfBx>yPvVQkQ5C7V=W@nvwT=Kwz42tOGi%(dmAf)X8VumD-&?(o))7P?0M9U< zd!w>T<%%yxl#0m3_tfB@m=HwF;_3TyZzsY58K5nm8>5ha``h0{YYa95;HTCrc0)GZ z!G+auFZX|mYE-SQf^3S)m7UwryS#4aY(4JUr=63_@i4bwT+Xe^1y!FmA-Dj_$x)Xh zwu36Yc0I?$5S3ng;ci;=^IP-tEm2U36Y)&=jOBbPK%q!w)+^x)*w@$=oC|>&356UL z_6qI=_isESu7Ik9Z)&C*VW+g)0;{D&H=s2}SThN;@9Be%){Z)}hduP;B44K49UwlG=Vf#t44_$=VvrX?LSac`zE6B1@omm(gBkbEOqabR*feQ=Tvjj6M{^AOcDl{8QA1APyZZnGMaE zV-oNylX3Q@vq*i{7Bp~8{O<@0^rKmfSa4b>`gvrJg;6Ms5am&4Q(BCYOgv~5ONj1H zi?}vMZi>_lR<$iF2}MX;*K1)W?uUsw`0py32uzj7*Jor;ytIN1PBUd>7vafpAr9fM zlsqwiH&L?6NR$Q7F`Ul2d1e*>8R5GcO~FlP z7Ws6lB zWJ+>)!-&`C=lJ~PlQ_da{PaFf`%QfM=ifDwMil{0c-AP!?c3wGj#-PK1F2m4;mR|V z=y?{H%zp*fK5KJ4(QG)^u)MiVVF;Ml3<_jcnCS#wMS#LOVrJe3hL*}UUI5dl-qjr~m28dRF>q!F#RMi^oNo=&=a$-d-xZJxOkL*_^YuRjCZj5-br;xzq znV#Zxy^1-N!NuIzmdRMawJAMq0sugntTp^fCzWkobnXdz--%2nG}s3ve~I*0Ylxr+ zTf-%qS{jnA5ASc|{rj6(F5z(?$uYOPsyI9yEhY**BUh3{{aYL!uDVDfI_Jc(orQU_ z7W-K&k$qK`jGwiDjW8d4+3BJS=Cej*?(!kWn5fdmc^`$dLD^535Y6n_m0(ve?U{^P32gyYVdU?%&5^dFPV5v*$t?UiOKv`#W+t_21e5 z<|XIgrKiZDSiMw4X_4^7%BDqJ5vgev|17ipmoIpgDI2D&0@+Pf9Ng=wNbyG=c!57u z-n{CcHIZ5Ik7sCBzQIf7_G84H`N%Asb(tIB|kh(lioTgO8jGH8O3WPE$8(Xj%B)xB}a zts+eaZT-yWWsm8)#SIL!<)$+MG(e>G-Z&z=4md@4%%mW}L1b0@CFp>nIX_PsZ zGW>IBtjP{;D^xkBU0G&1z1PiJ#5MJO-5Zq*Z*EjofinOS6a{$0i3}Zo4|xq)=PN3E zIc9TAZSuwKO?R#D-#=(n(F8jNyS<2Bb(i8XDfuWR9E*~0{N>#;W(WHDo0u}HbhC`j z?hv2;_@W5`M!&c=X}f2Cx`0u}pg2=6Oabdwfi_tMnLJK_(M5uZ(@HI#nut)FqC}Ev zeqH#Ag-ZSe;#5z_&dm_UUM&I>>yE#Bcn}#1$9VtYy{aV;>pXt_s=yALs{ndnrJju|J#Gc5vXp?=Dhs=BYm7m=-`nHxRcqb%$35LXL-akW`RHpjdfVPB z8|GhEaDa_1fM$L+0O8h#r3g%G(^^|zB1iqTKg8YrLwx=66#xC(A0nO6 z^CS4%ZR76dMpYI`)nX&WUTvHKj#HvH`p_zU*SJ|Gh4=~qv2&{62iCd1GAY%`2_U$k zs*D8E&M&z>x3qd7A(ez2f6EGq%h-ic;F*@ay2MJE7$*s28d=x^xpqLq5eje(Djpkh zFt%!NhT?ppVA`XMe56Hvs6>!)OKv(pi<1@g_W7g{KqaS)j7wN{_dZAylN9N=3C8H0Rf`*JRlw%Y@3ZIZ4;F6VTC*C}a%P zINJL6lKa^|??GnQj?oXa2c2Qe+>iS65xG8Carvi$iLNi+mRcH6MO{}pM3-{<0H*`2 zbRSj~k2geG^mp{59r)BSD-y);>F46A&XQI~Tj-yO4GU0kQQV%BW>Md>_!lvrS(=m? z_HyX;GVrb^rf5eq$nvVEtR84OqaKOd^vz_rT5v}`U!kbSLSYw@*r?<_$hqt@wsW<8 zU$;tV5?&Fy-ykg`wzn#gccW8D=;B`gK~Xn-FwGlpw;E3)^WblB^x7RhQx#&?J zdWu?%82{q5IR>9knVA3n`0hrC{D1uIbKKtFsAT`?)9<)z&7Jce*!3|VL;#8Trk6_lCJo}ihETvn8jC%vLp#=j^y&2<2w%OOQ293T&4Tq8pn z0M_S$n;;MvO~$eM{^(~R$K%=a+N<10K9^|-GJQ_v>HA~+_WN(~^7yEX{N3GcY$XwD zM7KJvgJJB4u&lYHezE?p#_I}$Qhn+c6s3KUBZwDts#gHo_I)iaE+9TLy*1-pA~07Y zxWg&5c%=3-+T*qaCvAYN?l9NXWxxF-kO`Wu%kwQU3;EGFZm4kXBj(?qVmP!KAL@e> z1r#}9P{6xtA$CF{xtmqF?7>}SuU%^Q-%y$_$KFbslHpRJyS;@CZXS!-C?4*q#N5Vs zdzSs+4{oYfI%$0&P>a zO2Zs(g<)bm1lk;EU%S@oyTq~7uA?81EeEqiwUesXXcnW{A`TmZC*wUd`GSB{D*Y{Q zZ{xJuiNz0x&ez4*+FP%;GR)QxD`8EiT0ejD@BRcZRuOmqx0fn!Z=F~BvkoDj^N*Gy z?fHe@>Rb0;?#ook>xW8214gN1U87asx;NL?SR1B2|BL?6Rpcyb*PQX!-}1m&O!_02 zu1y$Vz=Q}a5(HO9qqxQ=khmoCn==8Irj@O!jBbXwHqbHKna`y(s(a_%voBp6uZvms zKbgsNG~FA=p6k9qTZMqG%8#!Ra1I8)Kx4e*q;h;lePgL_`I!`8=Jol-{oW(OB`cM^ z%6aOm^r&;ryo_@>vSQGisMOZZZHL&%Ae4cx8IacPVi~U|Gs3CY|N5%W#rX)x$wt7{w6#GS&O-?DS5j> z!21*^Or|lN%wm(mF;uX|v#Er8DEHG^`0cmf)T3uEe!OY`)Bp@y4J#K)MvDT zqn^XWKf7)x;t8+8QypTuapoP9V@fGs+sSq;%J1#3!{^<|jQV5!dmPpItQOIBcZ|*U zs6gxEyHouB8GeYh%GLX9r}ha!IZRWl?!osYp2_FYleno!&8eIqy6Nr#-=2V&q4amfi z?qzynGK(8&yK@X{4X}^PFU*&Bar1E@^+4y8l)=+1Zedyu>=L99}Jw zmZ9ja=<-J+P^fe}hYktbysnK$`+Z*uykvZr1 ztv5>TAgWA%o&qinNzjsf6>2(%3f>eU-KS6Rql+vCwQE{9$?fYvaP z;nH)j-`lOb;o|EIarB|fJr#V>Sd);JC_bn3#L4eq&YZX4Hn&PTOAk- z=v70Y0~W>Aha%pYOLH4=lKa~4KK>LRfB89HS1%&LxqtUQHowEc?REn%v40I6$gt^o z?_tLz!&y#~z(eOTTg21TceMa+Z*SuJ^OK!6Ed(-Tc&7IT_POlZ>#;*kOu1d-W{D)$ zS_#%D^Ud_)apnhs@Qmb65}M;7ULgB{H-847JH2aPFKgCgVMznLTIt^5T=*goL1FH< ze?G?R)3er#S|iyNGx(BmHrCBJ24EC&{nNVO4wVp3TTU$p+!BaXC9G(UHBHbc(6y!O z*6Fuk-%Jz;!a5#C!_RQw237Zzd~jHJbZJ*tsa`CFzw7#p75#Lb6aVwYMVL+t%U)Y81##rbDt zYiQ~;+R=`;{fU-&>&WWgwwHAM`zqD7+4S`}T$FtaaeXmX*CXiL^X||0@?7h0+6~i3 z&X=SO?FMWEnRXHM*LkTp*PhRXgXDJrE(VleOvI};ccSqv0hz)LpwN#YQV13pUo0R8 zEj?()j@0t3grmj6grl&buu)}Zz3p??wQAP%f}O8%_$M2a%Y}dGkhdF)rnIw`P{`Ki zYK>(Zd{tmYpHBCA(9bZ}2pGEzByMYT+mXTw2ys|2tkqiSvhF0QX$|i*=~-*ey3K?N zKTw||@sSiXDyhkuhxc>y-xZ4$uR@3y$%#IT@?cliJH=$$s|42AAe9R;_37B7Z3-@q zM{&;o^*{bs{Oxc5>o#|cEZ-@>;5%8LzBXgdB^S)(~)P>OSMhU5b9O#3jxy}+{d5?LRt|!dyo_L z>sd!gu}Y?PY8u{BzXPLC_rG-1`w=-mOGXyIef}b2j5AZ9df<4T+7ME_#!IUuml%yo zIe)_bH)<2D)*DH$npmc#qV+V3?g$(*A4&$&z7|UQsfkdIF-tXddu#PP@12EoH zniWk6wVE0Es-Cd!okrGrt@C1i^LyPxuQFSufyGnZ9hc63Hc@P3Z#r z0X1{#X$adsjtooAuwDlg?E)4kFICONp?p=1Xg5kH7E#d4s~-Kevu;1HyZS3BNZ)gZ zr}WDGgPM^9acRm!slb^WSS4t);EiNlnJATD^H3 z1n*bRlz*i?z7lwlvNO*C_A#Csb+g0iAYJAok98qcd|@nw%ksNY$Y%rpC*8sRf2zt5+OxVw9Z`QoH9 zH=l!Jr+UG0&5~!4A2NEJyGxQe(<{X3AhUcb203O{vZ>=qOjJ?fuKIa-A213wj>&is zM+8kY0(FSNo?r<2&~wbjQ%w;)QQ1h!Trw4YRwO*^3sq1~CzHfz{1To70tbwqTLL1y z8M)Ph;WZqosZ>?=n+*A=hE?@P03}IZ_M}H*q(s$eW8+L(`s3Eo zcXopH+TfTf2gj*siX-QdFEA&qMZHQ8y1sh;-eYaK=bDk={+RvuEqJa-hFEh5B{6YA zral}^^@=d0(b@w6tG996(WAi%vpT!8C*|8oi{0k25AmLD8o7i%;v{T%oU+YX++ z+3+lzN+3uJbQ}Y86qfH}`S5E@7x!@(Ocm&CkB7LuTgKhpjj#YOkKg0V=g(>ds&qb_ z#?37l5J0WBvO9p`SYH51AD>_1csRw&%Qm(f+cbcp+8?7$Ouj?zGgircwwQz1zhoO~ z4Nm*-HSj|}Phpq07FD-luBi3?EMtGmF}7dVull>{m$n(A{##jVUuy5Ti?6B;rkd=L zjz9L=-$t-spU0n_>vhyzf8RyN7l8yNRy%K%eOLjEw_rR~dNdGD2uLVk0cdSaqe`Zw z5km!6m6`OfPr=K8q}N528> zAmNVgd+2rCx{Wv$i+%JgWNp@5ViFh#W!)JVIkVllM@`>-=(%z$sP)qam95t~)xD_9 zs!+_u*WF$drS;=>r@mGNP*sv`*S31Whn@qz)+j9joYZNsjoJK0)tS;<=f5lK$1zhW z0YyLCdo5QvIED+2x7|Oy*XZF9sakq)lX1Mf>{a$JXTxW`yg-F|uX{qU#7G&}r+d6# z3R%uI!`wzmn^GX_Q3`0?p0)P)db^9ojuQ1oMjB273;v8n21AgeF+~N<6G6#Yg>DLA1=UYt+{OKukXWz|aQ2?T)>LeFeF>gxS?+u`*8b*SNnqQld!!J&;2@@>ffW>sdRuQkHB(KO z?cX1LN=_}ou9lL!R6UDGtj4MhaHX1Ld!gV~HaqEx&t&2t?%&7zU;ZP0`pf@``Q67@ z9YT{SuT;U7vsm6NV=@B0eiysrG*0nd?Y|uWy7@zlmLDQ!)7X-zL1G1Nfy(I)5u9T@ zuNVRKb9i0vV)X)l!Z8Lf=I^+_xewrSD!I22+x4R9deT>Yb^VUA2{WGKK5J@A)h+W@ zl`LC_Sqq=6lsQ2iH+v}c5G?Q58~k!K!=ZbxJCR{%_8|?m0aFD!!NGZ4DHPGS1{nw0 zI+!}Ps{y?lRiVDUP%nGw=A2IUp`2mw&(ZhR^X)Cd-uFS;%R9~|s}FL(o@EtjkElR~ zX(&T8z0cd17)=(U%cO66fc{Xu;4(b^w<-!moCr|7o?7EHjMI+UM=O^VuQD5Cb~a@z z4g^D6eRHo9Uw;o8>nTvXQKYM2u*RHt6%$!&q)V_w=+G>gstm@xMqc&xReyhXbF1Ge zE0a!mt_4Xb?$qzrbMMA*96=YiIFY(ad}%aX7;(^4BV`gxVK$j^?ZIVT7|YsHY?Wcr zSm);txA*b-{AwQTB;=_33^N@l`rDg(1q8)nr@aQSW;oEu)x(Dm?r-PuF)Y*3Tr>Ai zFOQ1mIaU{JPX_Vs!+WE{l|~HW<4?cDAHV-yJw;00oxCLAyysPnr3F6FTs)<{pMLr! z=DUTmWRUg%Z9tO0tMxXvyWitK{^LL5m2B+gIez-(qn-~6e!(6Z4q}m#tZk1N$84Hd z3)^tb$D>;z^c)eD5qkHC@XJJwVE6i}=S;7h>XArj_QzO#`Q}yvv-df=L(oPAiQXdf z_UhpaTLI0m<$OD%tw0u3d*XZcKG(8yBJ0pRlL3CSg)=FhOI1jU6|Xek>-mcWsd4<= zo7Iy+hZXFVUFa%UZy?nxYo|Kq-o4BIvKhj(^bC|@2Wg2;QrM`TZB^K;!8a>~{fKDP1q7fMLzWU%hPu9na}|`sBn3 z2fhCqcdY9(yCngqRNQdt!8sQ=@FZGgI1Z>}QDIZCrsSW*3-!Na9EY=*FYn{-{a@qb zum4xP|M`E%aCxtG)Co?8!{>NL#coSAZxp-LA-+EE}eG#$V z9%GFxHq$PLVZ5$Su{jRnh|dGKHy_9JJkjhr93!mh)n+F=Lf1pT?g7{9I(uoO9nn9e z<7(g29`mxi)0eR;LbKROo26fVUIC!G()Sx#ZXelQem<{q-q)F;H(aqoT_WrKWkX&Y zt^d6KbJ|i)8>F}qUI=63DmRr({lCCkW+&Do*9 zuer}|BPEEZn5WwE+I1PY%IkIBcIa*!)qA=qyinQAz2a4wNd2s?Rp`!E!Km6f1xm_N zeSOs^ldBMBDXYv`8}^C`tA8#&*ODu3pJ8QRMuG1Ima;?IbcUVpi&wr3ebKtM#vMbT zurb>MGSoRk&gU>Ui!;Lkl`|+Fb*c(K|MI~qa@jIb@FCTt-UvTFe~-`KKF49ViQ5~a z4pYYyO4-(e6D|+b;BXV%rSY`K-sf=j>cpa3qt4GtEaiuubmEEgeGOyAn zXk|M4DGg`&ZFXH*c#GVxfX>eSvX5OEyQn-f=x=Sa_GD9`(w@ru)9%gI4$=a-F0*Ux zBVUWMTJH0zXo-<8IpDeXPfst(%pvSK2UVh^H9oU$#$t1vFK)EY=&PeC@c8ts z7S)_Yva7V7R?aj6X%{>0iR`m$Xvbyq>k6yydyU#2yH;8U@;lqF)bpt-qNks0y=K!` zifsf>N+Zl{Dqw836(O@heQ$RXa8qq27BxgQw3^2A*z6ZE8Q;Zeavz7$GB)Q~#C{a3 z{UFx6L9DhoezDm^oVT%Guj6qAf z+>bF_Bg6|;-bZ$R)jay!{O)xw9f$Ho@4naS?s}qmeNz3(nZ;VDcE**(o5ilD!o5bM z{#ey$9a3A7xOOUikG`MpFJ?I(U(MZ&vh&{6q9o(NR1Twe<9_*+njbq?E=+W28u`-r3_%6s3XSmn1mEs(Ds24hB z9@@?XwkF-r6lIVQL=qFZ(%^FXayD1r5t>y>zB2Ut9<_pBp5f z`(ohHJh6`*j=1`}W&WG0gEhQuEMc@u z6#Lj>I^`U2kgZedQOo8eAh4kS4TpQ5o!O~#obh-T6Dkbzn^-+RNxzz`yK_48g=XR@ zZv(yol=Job_xSkp&myPrINUKtQ51#v+I*OU0%uwG zAC7fBc-Dg@9{K%j>5(7qrvPb#iJosc?XoVUjk~&cxo;bUi)YI{+tF3_Dg#qsAkY*> z5KNZW6cww%$?KD~pvury$-J#LmgBEhO;wk=_10iNI!kp`g=~M;RYS9!{r4tyrQ^UfgQG^A9Dk3UVp19ugdz2HX1MW_`HrC9+b5{9K}w-A1$$EoX59ubN6dZmp?}= zKE(Psi#?h5`55c{L4ePVrfbXwcRp@oyWYxy1C*ODrdr<+&R}bvwMR{^OfRE6#N)~h1;wn}onz{{cct$-$y@8-gt+4byhO+Qj4 zG8^9Z7}vo~eP2ciXU?dO%6JfzBquhnz6a^+FrwS#(OOe=K9y}$w%rO)lu^QIbPheK zIr|oZv##oso9c3?vVLhRw;-ol*HsZ92r1)yeLj_8Y4-h;lC%o2=ta8P076}3dW``q z$xS||`o=0P(%%~~(&cMcb>aC*fSY?5;~?DFE;JfuUigLDFqA{#Bfww_#5b9#A^?>t zbLYSO@=JGr`T6cl1{vzNi*gpGJ6aOEV=R~D=(60KmbWrdt`n*-T0k1Dku#cjq9Qe% z)zZi@JTefndC{^~e{#?LbXAJa;j>@4hXgFD4wOBy(2Lj-bGBX8205KtqddFfU2qvy zl~5Ttl{eiFS`P(^zSP%Z6~ z-N{ti+y@CCtsrVjuw#js6ggNX85KY1_sPq3jgYEfpskV+)NMxRSOcn@0-4yw2mz?H zJ*};&*QM_=%ctFnlSAEOq2%G3&slRY6^xr5PXTOXwK>P0mN3-96WTz7ICHPYH*p*; zVs`UWoM-p3IZb2pypQAKcfC(ZIkx)*c@X1`d^Y#Qz)|)Vt%NP@sQq3Joi#!$P62;v zMv%b|G|p=~3%Hoz7!s-byIau~V^;+5rTW?SR@zr<#M+--|9AJ`u1ev&YD}Xx%3DU? zGsb%Nr4tR87utuFk17A|a^d#B&qbT$C1va>N0gDS1zpj6yQD1J=aC3ry(4R@5cx@0 z|9$P$+jDR4g+Ip`E;`nJ&^@6W1^WtV1H+Q$<-3QR< zw!}Hk*`Gac>5CykV|FqsER^cp`tam!^K|@Rd z&~vr8im@H^`^ff`5NQ6`JxMuaIk{>7Ijgle{o zB9h8i7Qp~3;>jJg+RQa_^2kq;%^hV&wmR8wJ|fH0=wey z&$dTQok0sEiIxHTFZs`{r!bLoYOhhFZKD0{L3y1$6?m@K&Y%jX@yaRFKHQ0Y+{`91 z9I*fF?5-=MgH)`m3SpYnd>+2;vgZWa6&!IRIDZ)7cJN5-2Qi%A$8kfZ4L|)n2GeDX zri(aC=CM0Z;_>AW6J(l6o(7xPA4gh4`fT(UR*$M8Ohk2T3QUCOr+F$Qer_T ze}E8<*NrPemU=Z)rg<||H4(0W{RVz#tO=D1hkhNUR$uL{SC!xpVj;qAk5LcjEl1Wm zUoZAr#y`HUv-<1b=_`R}tx`|>fXgveW>?3&%o^L?Yt4jTQj=a+F4}8pqvz|*dj0n; zK&C%t5-o5)I~6xaum-~LW#ea|5X%_OrgKG(GOH}(ixI++RW?;wK8|ocbML(cMixiA?qyPb3Z!zyDu;U7lnV;G6?pE0}eRn`Ol&krjP`-t-R|kter%7G7Hwa)*&X#gpoJ9#)8RF}U zscAKSHyjDn#%D=w?(sS2%#C#a{Q0vK?fBc**R_!4Dy1uMS;yid;z7ecBQ2q&X5PQ9 zU9zaMS0IpQoj{S=4rJ^_W1^`I1Li0(sw}T(o26#RJ{VO4;ScpM+T|mLn4FDv89m|` zWb?Rl?Ek&wADQ)Sm2*VdqvXk~Nv4^{Y{_Nz6`X ztpSk_(HBQ_r>Yj2WfL$VV#9IJNhjz*;3P&lwtkj3y>rwl@=)z;flit} z(KYa_{<{`cTRyrjk+jae4Gi9L)P+Q^%&m7gSw0tARqxQ-%(6YcL3cf$`dtxKI9kKGsAn>rN#+s?OU+a_ z3%1VR%4Y@u)yC~_sx_Xg^lqg+OXJE+jNLyj2ZMAc_=JR!bZB5JV0kRAWDILQd^9o` zsjUpuS}D!v?!LE5cUju>^GKtOL2V``irA%&*FEoq5RiRp;}5+ayOBIGhMnR>DU`X^ z28W<)nmJ3Hh9yBeqo*oD58(0)Hkq}VCq~mz9J8d1)1rE!^74Ks=fQD{cNrjDho-(D zKIxr-iG7m%L>c5>tZ*P^IoDT4y!PhQCVPZN_S@G_x<(@U)zfp==Af?*07&4!{Z7If zUq62{K~9q6)V}4qXgx5S&bn&BVT`uTX4{LvP+}~5oNUC9dkirKG_|SIED#jG)aZ^4 zw5ARUJUTR<0`C33<>0YBvQ!*;otySevKtOFfTKU}N{oqX+^an)SkS0b@)0lvASa$k z@FJILxefZsmP_H1TDu(qQ&;Z&ajdm{PwV8nc1=TOQ`Fh|UDL9>sIIkb!NyKV_WFv~ z;3CP8ikGwE*6x(5oG>v`abr~L$KHp_*r$L=KVW{yniC}wl)9^_kt7*BDeW*sbMy>sKZ>v{T~{n#dzFc8$m z$p)&jHgp+<{ z2NlAxGL9_OR4>N&IHTe0m3H2;ZhHQH)HuS{QPzWN7js*ZvT^Qv^!*}ql+~516k_)Q zM*BG|70*?-z@G{x^m(1bB^vI_*E-+qm17W5Poo0j_{p=9Q|q1z6agR(v?XO2_v$=*E*&9_ zZS|6lWvDJ@%-PT>Bim;HeNfhx4E27Tj+Ec5&Sp#vsBH{iQm;1SYi*`~-5RN5LeL`q zWXA0%$uh@EZ|*o#DXWgbNK}>Ni-xy*Rx-$wh|yjYts=H;1u90Au||1*2N_2)S6`-Q zpJ8>v0TwF0vM7%MxwKzj+@H$UwSR;JPs-5A*rja|vK%$Cwk9yy9(bB+Pb`UDFfK5*p&G`2b1ekUVhRKouv*6}6`Gkx$kcYo=zlgvTbzE{B<2hB z-yg*bEx=+j$%z;LkSa~e%wJPq-Q#xLH>wCY{rWrBV+A&3`iI@pz&`@Ede%^`a({F5 zNrWwGuXwF{1Qn-U)s|Wto(t#MvTvo}2Awc`?E6!Uv-jCLIhW)?-8sXx;RcDC| zj^e;sr)T!PswJa%*(7&GY9X-J)JG=>^KMM3*FNB(|J@0vSmva!{!uy57@3g3`We@a zBO^eTjymJCXH+3gN9&OP+^MVO_)XgGI7;?lXaLCJT+AV1(V(`9B&-;VsG>hHex(+S2m+E3M{H~`*AVTV zQ+Y~l=H4l54m%OeUQE_*MHjcr3e^X8Bxc@mGBTH~JZovkqKlUHw~1CH=8+B?xlHv& z%c&zwHl7mibem1(zaw+SH)7AiVEyt7J=dvFp~u}ORxj&VEN8Lb0yrWI>PyLeJeL5D z>|ZnLQJa+Og~3N41)M(7sze}iA?4dAgGn5>$5?IF{qeg>26B5Fk4B6pF1e5B@y_Br zoWub+KIjBB#^$VJ4E5pEWGQ}T=x6(PihENJUUHxG|JW9Xy$mx3`rOdF@?VGS(bh`= z#mSoO`Z=?}BAF5nUi)jehufUz?%lV3eC~obHsVPcqa$lj%?g;R%q1;h7Q2lWdfyyd zgdvkj90H)tBxZw&=s-=Yx^qx89mQ5W;zZ?>7z-B&;L0GDj>II1BH$m_`O(`IxR>5~ z1y(M}io#UtR=qr@_}1yQvwo-anxDEpI_p;sf%SR>K|YJ8*O#uWx=L_RRTowRvR?wa zQ;dewxVwE9??3z+%jNr+%_qi#r`u2(V3HUaC^K?S9M z3uxfrL9yekKmGB0OyGEaIL9-jG8h{i)K`ar>8F z;*URG)Z2%3@b}+;mz*od0JS??E`;`_Cr%lbYa%e&ysk`+lhrHz_jwpg0)sQuzb5_R z`4f1G6o%l!{Uep)g@=%CH>hqhLKK8?;(ZyooSe#%4XF00fTonT{C7N4j?c`x15dYE zOp;@;;rYz^adIJokDWzdDl@mRj5Y3CaPLKnCrir3o6v$HD?kRxtia&ZQ?Rmcj)$$J zgXd>j8f2=rw_Vvg$EpCQYP}Lf?{}F&8Xcda?3u}C1*5Y1a)eW;NmG^<9LFSOLnS%Q zSeC0?#bJLQ5b$RvNzeCW(Vvg!K|H^##W^6ANQ76ob}_B>K?-}!ttO6DwA?v5CMbz9 z7pffYJ$;~HC8c3iag$jgbU4R^@6$X9v^pN@b4A#5-pM=T?AY()bZ!KZtW`!KM~I_{ zrI6=myH-Jx$YZ9iWDi1j5!63drJ<85-oj12j0p?_{ z84)}{5=D|gB7L9s#>u$V-B=N$fGVkrSVWvpB$JxI^mAPhc8Ne)l|xZIEEY2l;$OYm zGHYe&U1lZlLa(Kbl9wZyo^5CZ*WXpt*_MgPK< zHmiKj;+N}?|1h<^x>7T68=!iAWLhd0NmkHEU~wS>emau{Woeu!UZWb!iW;2M(a2JM zBA^&mYlnGm>&I7gt00KYnt_5GL4)ii(sgjr&*N$xf(WI&n^l}TUiB@j+)6N5qmIgi zvxHfF_tnZ95P(i8tKkHMXwRq_er7~RhND?LJba9gAAZ%i7;A_ueR!P(64>&Y2#uUi zG2_}v1O@UlU8u515fiz0UFC3)?T~%&2=|qVx_+J^w63>{i0#Bxmipc1yo(*J#lcb4 zN#*TS+0NrQ3W%7kPFOy`AM@ zSu^y$2l7{}UE2dPbCuK8lTVsonD}TT!df_4s8>Fm(*C-O>GD2Cvv(1bn>dXYv58r1 zkHdK0pW|hJi0#p;XnIV#1u@e>xq+d<;nuycs#}NLzAb zJ7bl(hTkO>DY-wcl$e@%y#i0;eOLSkqVv@}|5&B^ajDAq1}8W&=YBiInf$#%3cm6I{pW^B9 zF+P6yIi};87op0{I0!S8)k3Q=Fv|!#>(pqL5FK{hLe6HnUOg-veNqPY+V6E!*pzv_ z%ugos7>>k!94|PIFF&pf+0LEFR;pEuInCxVnR^t;h<58zn+eSlss`00>N9)kZN|`o z&rHg)j|C`Qfh!98kQq&~|JC;uR??>EXc-464H@vlb*KfRN06d2sj#LJpV*p=2~Z_N z*Jsd&430SIX#)(E1y0Di7t5TVJ#=fX)=xXGrv*Nq#9_3LU5>$Z{p~B!pss97Z+Cc( z<=k_{)ds2x3py#`sb%d39%skieW%5_3`CN%!AJ_FZ$j6%P>Vf001BWNkl7}dJ?Cx>0%gyDycoL_g{vzZq8%L&Xj`CbA~54f*)!EL1!NNA@il1-85?&+kKJEO z<3B`u?IdEdfZF&W#`BvvAs4NLW*h?~MPX7q({ict-?KrA!bq5@&JU;Mrl8V3i1D1# z`i&<-#)}xw?qV>zjninRu`|lsue*&n623pJ;stg}RsJ04OKfIiaHo!a004ImIFlp_ z#Jbz>R3Slhh!!7?UaX0%Rls+m`6YnuCv}W=--Tt~t^O!+skQA8RZNMspoTYvCGnud z2f>;NEwi_r@DIR>H|8VX>e;;YYJnOp+fTiEJ>RC}oeuraUfsD->K?Vd_j2Z5K<*=( zhy`lU5AV-1#C1)S2SMCA<8#ZQ2Y)%LWc=4rym1ElnKBV-JzmTsrSEpa{N9GbSvO-p zrO7*_8X*2(BDfS;kvHXEcUEc~M37?q_mu|so;}~# zqFCErq}a3oZglKdg`-FkgLLQ^gVr$VbBBYty}$S9N0RYeKv#1lNm;Nmv|hAFS@&Qj zj&_0u$RZdQAyCs?>|iKovU(viw4xBt!0Uy3jj`Q&4mgQj3iaL^GY)2B{Uac=oPEs- z^STax3YE;4sW$DKn}~5_ z6=1hJYJ9Cev-XA0-{3U9JT7Nm^CuYI2Dhr(+}z$p%omove0oyVK+>jXete^!!2kxp zk>9;z{`_cOd@4A+2t5Alzy2#m>w$+gg5>MG^Q{p^Sc{YUdD5+$x;J6 zb=8Gg2H>GRLJ-2bW@_R<^+%PgMVzM#^UNQ}!gq0ec@hu9W*_mqImc#yme9)6YAfbD z-P1_|RI%UFlQ<=um>PV^Jw!<6u-V4r>dB+3tm_BL#;py zN={IWSXBz?$DrH`N$^*dKC+6DB1Rr3$~nSFgt{KO`L?W3g|LVIb|@wyql1&=;EIyB zH3-hoGdOCQraB5u8@jGvB&}ltAU0_Nc+~gW30%^fB@4H3ugLb{*EXJ^Dj3u}F!2}eotk0XCk^wFf*EqP>x8E}&;?k9RbH}}u%q)ZHk~nv; zO5wFOTc_Tk>67anrsFbNtxh~-CX+(kr$a5G8IBKcd~LWg7z?rK4HXP>Ot_xuD~maA zf|Mxp)Hv&jMonrWVR?5aLsT1^V4%pEDwvRv3xP^1%ykum2Fb6|_u;HkIK(lOt6x?t z8vufb<*i6>-fees*lHVWR`L4stm?pe{Tjc2`Xg?aiTtk7BD2MNM@aOjdy2WHr@{5?vGr-J!WsiQz9EsD`6hkANRECO@Z?!$H``49i zk)?=OgCI^&i3RO9jy!z*dz}F-sHy-$bM3%w_}%}xa%G}2E3n; zF{swKqGl|tA=@gDWqXb7J-xQKtsO81$20yo2L1ij?0eTjKs@~Fm^e@ZN%gODe~%l~ z{OJUCg}p=tY!K7gNa8^I{V2{ijLXhqv!@DWUUO+fB!LX#Sl;4pqw1a(iMt|wj}&$` zyBS{Q=VGOVoe{w4coy^f4{EP~@pyQ65QoF$`8l2*nc{FS`Ba?yb0kT@YoIhqHqG?K zI$l>#@$~v^zJ$|Sfg)M|4(!LCw%;gD@Tm`GaT?5}|Gu0Iq;bxd!M3}Y!qleG%xT;# z5yf&p9GlA?1cSnyIp=~c*=m+xZ}>iJjC{AvQATU^pSwuC4pw>l2Y zVxXJ2Bt4H(d23`0={f2CQGwF$+>27iI)y;NGN-+!JEbkIsUKZx#c)dcv@+|uPc4q4 zepY`^KvS=}e}zcKSg&4QI|pB-_TKP%R=S%%Pm&xAhJ++;?_zm-qbvjb13JgErDsXm z_#lS`g%WNAAkQXNtC!gAw{kee``wZBNP_lK42Nu=&wE*IV!7Pun3UERvw7UV+e(S; z{l}l;>*r5#czlfU?Oehva75F(0jS1xaQeXo6WR+*A}s^e1posTFvpTM#(rlp3UD>Xu-=e0F$+xB{ofPz^^(|O#! z{}}H-{;UiYfF{#DgZ(IWPgGiuvge1Kn3*3=@oqGY+r@pXXS^VjGdYhgGEAXc37h|>Akee#`H@ls-2VlJ*GVeeEaI2~e3Ii0ah*(Xyu zv*w;(R~lcVa!YWuoYv&T!CLaHca67ty2SRk_%U1otK>sd9cS}qkSwSLM^Z!LrD_@D zw_POJGYr|ud8j~$@SUay7UhibjU372%+r94 zz!QuPao*GSHkzD(NMlwasA1vv#=jVw9C^|EF?NA_K^ADE0m#r%J|He)Vx&oxLC8^W zV}-2a-kF#CmVE%JtXE8F>F~2Wt_s7U7ogx(Wpie#MX9Tvw`Wi#S(}*^Wn+}cSRnH` z$myiu%^onvQwE=OlCYX#w3sso0beYBbsq=_Zg1`^IVsdR?>(wtjAPXXReL8%NRG)z zuJ%qJL>E9!q%Rs1I=PwxYae}NS~Sa>nBU&V&x4^#^5@Yso?l+Y)xG%6=xI>akxKDL@Ot+rBwtPy<-zFlD3xilkZgpW17L| zIeH^qBn;dy5$!NpQ$iwg5FY8$@e?$MLBsP{dm;C2DbjU37qyjrEcQ_6AT^SSZRwdJ zue0PnllIzX;zYkoX0IBXD!z)E&}hNHH~<0`R|Nb0>JoZY`rPYhJWOl3$Ml*rdrVEhg zcgotI*QYpdcJcJIlXBV9sbvv|o>|>PbB>1~J`^I;;sV z1y_v5(k|0j8g{_}0TnIjC$S#0$_d_s_7}&zTiz%cWts}4JXOvy=y{FxQT?<%auq1$ zQ`=~22fq z=#dfCOpG``93=q>$VhXl>hBnY!{0KZW)O#gUZ9BO02pm34rvX(dNe~L6^uV{gPDm; zS_{o=6K!qT(32R83Ui_ozJim~jUG;B39iA9OyUR#P6l$Ktd5ZiN8gU@AUtTFgMx&H zhyA*L*G?F8&XxD8cY8J;`FjedE) z(^UZr`#8%kguS0Dn}VKhm8&>A7Q2XR$i&m=yLI8~z>tHgtt_RzHV~!7D_;FlT}LwD z?RPz%pwOaKmFS)P)RA~PPXz&)p;rdZtDLIoXI;uwId?qKrpI_yBwwu*a1c03N~BB( z$f2KhBA5Uxa6BDMMDd0OK;K8N8UEx(=Q^p<2uzu+8?{NMargd%N|b;5+u!v4=Rf`# zH;Y-!=8O39`#)p3n8dr=n~OPYsmASG;^V);2Z$VJx06&X-0);3x+e0UbYj*YVAS#) z1JLd1>~ZGiQqP$!O0vg-v2s1`u@X?(0GmyZ2^gk17=5LZAl5zCiSzR^;v6X`c59&qY5y z1EGtuJsDimCu=XHJ-l}4+%vEkZC2jy{|exhpc##qL86-g+9!I{K%w^mhWv6#i(?b7@dkmj%-pn(?H4O?)C!^k~xk_uHwI#x>T z$R-ZSY{;=7p}O#gk@%3rmgzXjO5(RiYfm z`EZUY*$PgPOa=qIKgIl(EPWZ9%}O8%%1CUO)po4~$NVaRt8||=s|@p%iAJg?tc*|@ zbB>J>6e!D?X_E}c=QxhiLDFMlev?Q`y%ZZK^|ObNMY#NqF=mts#vzFTjL~YgT%X2( zddQm^^);7#Jr<~Ek>|ZH_B4&xy(8K;DWNYV{xO-@kn)@? zOahG~Mhu~m$JB#1SO;D1ZSs@zx9VYLfU=k~*J^HZC}5c}m)z|EDb<-~#c}ql@7pYy zzR1y(5Q|5Rs-$a2r}%uS+3x;*@q7<7CIiU@Bo-Js06UaA)n+)n=sv%^ z5R`aqW;P#duAGXtjH}9()}Zg?R~dCmX<&eOqQQibZ_IcP$mAX&e;i`8xlZfM-z?{G zyPT_SA%?{DD!zUC?8*Xt#-YV_K=+#rXsdOkwp;NcWM!uVe?kJ^v;j*ri098SHe2}d zGxJNkRb)|87i;8$G3*CTIA9BUGA#3NyCOsKP)@RfNG1drpOtNx8p$s;v*h)!_Eeid zl`ZYY>Oi|^K+VhTr_89uZ{b;Q*@XODRSq(k>HuX4?3F_2co=hzF=s^V7=z6q1`AiW z*6T^ER=aF}k7G54!`!2TXQnNVgLv8Ov`;}4((`3u(L;7?A}bggZ%dz(;N+_ODhL@e zpZyZQ{qZRtU$>eY=iY2YLkvaoG}fDaZ1Y|nxc6%Pu(zC?P^)DMsG>AZ1#sxi-7yA} zb+QMtHY$kbgY7)`>sO8UEtvLLOkz$;Ym&lVN4OpyWwUv%BCI`I1c^itpVb0&WuK@5 z<=WzRcXue{9fB72w9J}oN?J;8Y@*MX!_c5b_HlOO=e)|1$O#l7g zoT0bT>Hm~LU%z@0j<=n8o1ItRt&M1Lau->A-cXN)6?JR&W{BcD8C8$LsFMq_o&JXw zzCNj6@btP9xlR_1Bcj~PW+eI% zu|NDU6s;5YPfb5cxf}1~>OiTgX|^yGcF58-8lf3Vz$_ND5C?e^W!H#9-OC?P><2rz zHrT3bsJ~&ReWwV}GwaTB%uOxIS4ES>SKX>a^@>^N!?SnNg-}+{H-l9w zBsf!kPmdU*OfbPbHU<>VaDG-svPC)DC>wiGk$K(wl2pY_X$G9$e@-t@so?x@?981* z%UZIRy^JgZMLYv$uuZDzd+g_nv8c*K?Kg|z;K0Tr&@eUdKxOtB6qMpUr<6U4hj%~4 z>1adv;isQtw=n~q^r}y1jpzLLKYo*;05FH4`}*aRvLD8SBo30e6jeNOT~g^%MJBUy z*0e-5D3QuY19k*3MYSr+*qR)nkIC82HxU z_WQC=fXZ36cClUrQ7yJZbSgO1x-VHBz!6?EFzWo0`$6;E4e+?#ul1hRzB`z)Mucs% z$JP9|0ApGAMUBmW*mk#p#OZL3+xcy5H(tBvxQW%;%3%b!(_zHsz$6OvrP#z#9J3-Y zQOk}t9eF}xcuJTmElROCQo;NF?J0(nWz45$AEa+Sozn8MlhdTl(ZMLy9Wlx&!61oX zcY5rrWQ*Zy_%NQu4b?Wac_61c$8Jw0U?1BZHeefcs3EAD&u-#wF^dJlGc-!l-fj+i zX~heVbKHq!>U3aT%;MqQZLD8jJ&lwBAkVQxo}9t=08HMGjjXB+Z4-mH-3n#Txm`Ms z)$m2*vFpQ52?ocYJWmJJJ+B;dst0Z$M>lJdl&|ND9y|ZTiPn4C#nU?UdbJC?b37o; zwVF~!u;cR1$TxeHH5#RkPt7d~L}p1j{V)5#?Bi~E7pv!& z7*40|;llbw$#<9;xo#}wZdj{QCRSr><{u{7g^rNS#U5N)t>^rjg{V>5^{Gy{^Z-`fIfI0qrj z%_A)Y0WAVCu|aDJ+Y+v)1q(Ay`$$QiJ>B!Av=@ z+U_Wmv9S4X0XHO0*u()5{HLX8reQ5CG*xggE&S(fk!|1 z@7tRjA#u4c1OqDFv(Yl^X9k;BWkynP13gUX7a^5IsPkSvw>GBNxi_I_pr;A`8N_sf zlU>C9yZ3Q>_n^!jCoE>CGWd|}e*QJKJ`FKxGUns%lHFs#{}7HOQc zg2&=YFC{YtotF~A!y&-99za|PhblXX1Gq?lXc07oH#%=o6=PTWW9xi1@nIsTRt52T zL|BA3!qX(#NCnc2(DJjy1eATI+Ds58JH)z6%>)SVgiXl|lPq+%U&|S(Z;oaH%ybNM zXG;Uy3|7~^k?aii3@ci<>n3TDAhd%rno5(F?CoE6i_NNqKS z;L&v;+jk&nD(LNT6R$5XabBF_-Fuh$3#>aH&h&n-3-1kAxl_#s?72^K>;|5a3*+7ZGcK~dtI@Ug)pEW6Pd)WEN^Fnq_a*`} z7rY5pQne?M>SkE7lPKsLRDkAK_fN{O3fQKoccLsqV^l+zLoo8c{``x2>^q{O+zefR zxrl3Wp8YaVxdzAhziSq1~F<{T25znO^Fw`+8udqm@y!qP@|oW3w1hAkw|b zz=U%b-6&w3oS9c$Lri)AOQx}(%;U6P#eTaM;ZIc)BIdqD%%_QDGz-Wf>MZ`Q81!+6k5Q+aYY!+ou%ErX@f#7^_zRE8`51OO$mU^H9($b44=QCuj zxo<6inB+6D$I>AVO^wf3r7*kr8) zp{lm^wynpVI6xNNZ!-a6o6=XRHoNtueaN7q?X7!sw9nMbR$l8zTm%L=XI}}%?r7Ww z+pJmw^v~4>ob*a>Z`t7%wf{rq6}!lqOTneW2E0{~bp^q`fzP8eNiZnqM$jc}LyF-f zVg4Wk9CKwgXD>^PJ)u@d>J=cc~OyHz&&46B|i$#AoAh-5N8?leCj(_G4Pd7Y4vpPRCgjD#bRmCKP+mOl1a{0a?NPR4rhH)my)^cyMlfS`W< z_BF}#Gs_dtw9&CDoh88y#={Gz7CRff*9LC2(%Vg2yya{cdhYHE*&vSqAK}n5x|7q9 zqe+UxRIDOP#z-4{o1;RVJgNKX!WcBOvlRdo$gRr6lx^BzO5_G&jLT(6VS-B2FNvFcAHAU`FrezAm7J!^J<{k z;ACYj`f+=}UX-NiDURLO6IOv9vmGMkSV0(@8PwS#VSf5xCA7g}u@ z6I;bQ0mt6OeEx^H<)5BkH1@?g(-W7IQ6QASD%WS4bxiUSL8tY78tr4ht|1HO-l$EE<>^K>60ze4$0wRh9&y!2CFWqoJ zuHz9E07iB4Ge!04D$IE3arRuK001BWNkl<5 z?O{w{(14ATiBmoGwAt+4-NwCl7#`Oz&sy(f>)@4~XdYsqV8nh<%!ozZ3%29h0bOV7 zRaR`Bc^Bo?C`3~NYLE4nL%#?TC`mV@CIV$C3ooLXde{~MF~MJH85(fHq_NV=xHAd!D`1^6pk)C($f-mxtxJH%0+UJ zfdSbofFp^r2nAgW&&FBQg%UUz#sNCh!=)ax79jF`5EJZOO0V;3Wm2oB-0^*9INW6d z0xQ)ssqCf3bT9_oyOJlodZJ3#bcG>thGlN9qQidXu$hw~&h zkcuGQ^Wv;m84(VBGK}417t_r|k?HO2GM3ycu|b(1yzT*|#+!OF z4qavTrMJ_;X~X$ zSbrRFV3F6T2dm)1YGVWigL4IUeiB@(31f`L2l4B5(t~XP5f*??TZk;0{`6ra$NTN^ zQNWvrd&>TI@%78^DLV-of2j(If>(k_+CC!A;ri$C%KgbXSy;i$(r5i;I=812&#fj@ zj;S|qC*J8_cXQ|czY^{c!<@mFs-7ffMRrxBDYP7hGGH)|O|s>sOon}*!b=1Jg_)pD zQ|R{XcI7>uS^x0}dc0?W!+A6BkFzPqUG1BCrfqUkXyr~mwFsUXo2Fn)Rm;mUv>vpY zi9$nO7(^k*ct-}Clepby#2)qU>n4k*M{q)Cyfn&1=0(`)lan)`_J(RqvzF)Q&`6lJp%a5 zSFdq|-#>xW1e^dRJFxGF1o2gCUk*20Z=S|TeG;|eJjJ4buc^>_^fX!TlA@az8UF!= z!u>984*QtjKqh0HQz71GlSH#C3Br94Z%K`mq7kVpvbKP%l&>Q-V3fC zXYPQm{Hg_R&YTw&K()9?`i?Py0TIlDCJvg?&~+BxMdnxFw(j4ibY6e=uU^-{3?JWf zkTn@v3o@9>6h#<}w-8qKl*B-E5?pn}9o(96S02OCRIgr(I6+IV4Vr0fg#$Nj7A$Z#~5M8 zgSbN#8_Jff=DbF6#S6d%$G$;!fGtr&lZb|}AC`$FaD-}>GpRN4xO&wrJ*9R=c;bsQ z=*V;3srnI;Lxo9kGMTFab~tVX9@;#8*KwE!*Pa6CnEVf=PDeoMX%9=7Cdj385Cu$C zRWJE1>>zVIwaI1_G%$0^&loqwNdTJco`0YH9=9*ugoJPsx3{sp@v}dj_}3sac*VVj zIp4~x5f3uRwzpmWo-%v|R=$sJ+b|Z{(X6IJ>j1tNBwbb&>!n?bs~>w-V`rB{Gk#r? zA3;{4-!)@&3fgzZyf7)i+6OCBt)aG}(Awnd_Gx}les-NlA8^^BK;a4hPXEM`tAoa9Plfm=I9Yk|MoI+E@ZufyiVN*0I%eh#A{_&-!4AzBO$s zmyQhr6%Fweg*13Y9Avru;k|4p+_QMPEy>=_@i!DNiHZdB^_oST&D>e%*sc+S+Nfee zutE!o8Vt69z(*5QB$t$(xvgR{1?L3FnFLpcs3+)Xo$a4x?&Z7-tP_8-c-r9Lt)F+l z6P=jL)~N%Nb1z1*YZC+dDMwQp;+mrb++xW_q8=hy47`!e+<{5FK0R914QEESI56~o zJ{!gT{jKMqQ$|zeJrJ9e-UTLeG%cZ&iwL;yxoh57^OZhdmu=kVm-^43|CyD=(2+j} zBi@=%&t7{ubQFP9woJeo#zhfiRzy1f`xwP~zt$*NWsn+2gIE0Zr7MB)J5<38B&iWa z_rf^$0&VEpQRBC2Q6=O@e<2HjAvpe8{OQikFL3T<~y_O#+aap zL5>HFPys~4k(9Hw@!Ja-y*~^!;zqA|vtDcClsJcHN*9XOJ0>huOpazAtBhlCipR&t z*sWK>DhQK6DQ&)x{3jU&_lsF=$rdsro_yvN$g*ZSgt2HeDOZDyILE`yy?(FAp4nT< zh_iXzJ-mzihxf{!IcDjsJ7co5qU=^bGbpQ^O_7V7V$QQ5GsdT#$1&$vDcUfK+{)ziW++ zrbyL-#o3x2?nr<^o5+1~suOZtaun`W8sui>Jw0F9joz*>Gwx~&fFJ-)3(x!Gz%_wE zcIBQr6#-SdRF-v#mkVa>k+DoRw)7dmMZk3T^PRza1WoBs*?a77I3ct{)dHc8Y_Ok% zJY;T41=70f+{^iVqACK($3DCVg&Sb)7As?A^s0oFWHjL4!~@EA_N_76OSJ|npirQa z_E?IH<>s$J%feA*`8DU(aUQDPXuCP*H2qM248E5W<#$D(ldNHCWhOBWdvMD4WP`H7 zrnbd=h&Q9y7LPC#5>VXPjtrmWAbE~37^>wkWt?>o6ZZZH(5I^%8v*Xh7gXYiWU6r% z3+^|;4|CpNZFcL}tX^bS0UI-)t|7>2y z#Ha!th?-JZ2zq0{bjjGsx^VTgf-VzkbxCmwX|W%vLasK6{Ay3*ptU?Y}U_8N~e>dem9s5V>)sYLQ78mS0MI73{P8S=yamzh|X;H)NCAy z3Dw?Z-!2=Ogw4*|;tO6tGORf&R8HYd!sBmn<^(J%$t7R5 z$J5-i14+(Qf%LmK+Ze+V#|9$WTv94pD4H#UP(09NuIrUq-6)qTx~Bh0kC%v(av1WJ ziqCKi^nF3GVie9XA=}%mOQbOD(m|H347BY%eLgYFYY|$RKt6(yU7;G{$fBNU>Y`L|M%861O6a`79~=2 zTZGx&k7U=BmBXC}+3hMT;QtqRuwVTG|%z+1~w|LOlv7`olk_6ld^6ZPh@gk zybW45RHtIZQ%SO}sScJms$9`4pEIfgK~4eg9P{)km(moKIc$CyvZImu;T&*SKt64s zwI1yj<=K6zmQN24vADU>b*@jR`10|inD&}KPgg1FcB{q1)1_iDV_a&F@HT+^Q**(7 z;pdmW z&$Pd*RhVSRl!UG-mxJBCZ`vHR1k%r4>T{NrE<0hl(Tzs25cA%4s3b(po5Q!@PZ^x3 z-R3h}Duvcs6)HlY&{4tIAP{gpi!^Q#&Z!_}RFK4m>Qe56BEB8;yX8U+A_^@fMu_c7 zDeVN?eH<}`8^X_mv2(WWFH$lbXpHq3GxP{_tQ@76V3IdXb+g<(ip;s{n85QopAa_s zBBC4m3hFttmm^WiBV;>|jIy&>(cQ@CuJ8WVI3E^^z&!7Gn z^VuvmPY17!J;l_4jg7IA}W?tv!cQ(a#8iUk7xJLi^-0_Lyhscx@hKSv#%+QW=JZXT&J1IW`r*M z{zP=4`tMC%GyTasTC` zJ(IgJpOkcM>}QLpMD;78lYaM3!Dw;4jkoXK#Pa6WN#$f7_g}v#piD0GRIgM4abdT& zTLmI-T(?q|*Ee22z<-URSF4q7X;a@bAvB}D!oMQ1xVkX{vUTr_ByPT-3RuKMvaeL# zqYk!5tG)IThX>ELM4dGDBNC;pWHF7If=bNiaXQ-l4?`A+dY~R=xEk`dufWM|l4e>% z)pwG)l!VU~x*pi;99Ww5&z4LjG+*xT6$E*{r*lq4bbaTP<nj2leOBHN zgx6PtM&sF7=!EW{#)SLxx;yjJWwK7*5`EGBuOE;aW)XvX9ue)0B6Mj?SILh1*5k2J zA@h#%{O9z-LtL#0!g;j;OtzEFDCGLJNgDa0w$5xy3kc(=skktn3INr~ zGc4OB>?e{@eg<1vP{#G}qT*pdG6RCfULFlpR5E_)B=Dqy?>zCDMM*uHla$OTi&QMJ zAMv3d^WTgLpd%0Zn2RhS_hcZKqu8s_ir4-0S`h95`9@S6?_v8ShrELEa~JnaRmKE# zfam`asB7$l*N{FfJ@bUPvl8&le95f$VdIB_FR$Jo`CBUpk>6jC*Zuw1_|0#Aqsose zunt#(qZGQ5g{c`%3DvO4_Hlujplr`rM!lw6he=8qWdKlx<8d^N9PzsOcOX2fcpU_i zX(F(Dq{hbe{r#yqXTe%!YQZ5X)}{mgd^(LiRftS)P9lZ*@Tg?0zy5;s=)d{Qa&lFf zEk8#EQyZXW-32vj=9Kqi@3>kIMZTM+#3SM%$cWMygtjYBEZAE=O&idhq#-};)fr8iZ^e6jM+c`9QR*7DPGK$vpDXaf=QE` zw?o1ExGHgQlITo^leoJDy)l|mEcFUnLRD%uyj-#vEu2hanPX!pJF#xG#`3V`-ckMW zC;S0kQ{Lpy5BgqR55%@J$pP1r<7q%<2ZAWf?i{nD-w#7S+hX0w65NET$F+)GE68TehH|L2rBd z^~?%l?*n?dUB2{!uXDSVPp;2?3V<8qV8r~nR4#`}F3eWgk`^1meoSF7is7F3w)YeO z1Vx_h!ND06PiU-)B4hGBK;(!AY&(Bx_bLpGU(Q9w%bK%=dgbQ^B@&lmkEMAVtz{Py3wtc>2WBsEi!OuE0$@(A|8FPe=Wn2=LK z{t}S^3Io2XY`>Www|2C%rtkIlD~Tbn&}048uYMJO{nvjTKfHfyL6%fV>Ig5FWV=gZ zv8rAlp6a`GkRykS$xIfe;ZG_f!?+6Ynm2b9FV!zm2RtgF8Wj~QLGj;u(HGib#idk1 z%T4YqjXu#VA<^D#Eyw)(#3~P<_BC3rL{(EFO#vh2{p$UsdnK*9ZuRSTd-adhbKURa zd>N_d`t-=`7(f5+A7k_MRfmR@v@m&~9WtKB6cmF)Cap!UugsDyenC5?RR7)HkNUTo0cUgZ zel&C4%^HtH%8{tdjG6ACVs_W_uf6+% zIZaZMS_?}4^7+)t?E*_9kkjtP*IXSAH`|_0)T*%X2J69Sl19AfO;gpf-ymF4J;N6u zpr7_mXdyj5JO~-PySa_4o3~2nzTAJ(?^%lEcaGx_vQy7nk(&{Cs%1FBUD4b}tR6RMMjQs{$>YiCM$3Oke5 zQsj$U#~!DTO+w5*EGI_xrZ`FHL@ewtzCELDpm*M%x3sZnBhKa$y1H5{V}^Pnu4(gW z++3|hM&o^*&}m;k$L{eV*7x_)f7or;F<~};w~E2^sP@qQX)Qf^(3Ho)ecasKbhgRJ zz1Fl3i316K=_|+vdF_6`94To96IaGovO}#7YuRxJspN(egeK3`yr|Y%v(*bPm@UUh zY?AOT5w3S}d);F{@Z^Ww+X@OCJypo1KxvWNrfvmH;|macHEl!DOSG36cR-s0fFR3 zP$#pV&t&;0g{~yNSsAMTS&zen2fvXq0DYcytl+l-z9d8rR}7`$LJcL^xY)+ zy58tL1Di>bwnmI0L5PH)WmDj z(?cxAQ&*OZ74ZfznMx)V%v^P+vSQ9y7fJ8L!6F+>v)`Y2-$3mgdb?c=5DiiPew3e+4w1P53r*XbKx?D2fItZ!9OEy>zDzTx2{;Z}YKlXT_Fj>*)fICt;fi7iYY@(EF$=~yF23?!dOMvv#19S*T90;ZDV zo!-ZsF~8K+KT3hj6A&235~_42sjAUskDl>t%yxGVU*ZBt%TC>P z713432Nx%Qaa5wmf9*+_=t;*=a>vi>ZOm7mD$+Dht{Gk%sGM;%&RC#qZYpa77#!$* zh9xrNxkA?tagqz$RxEr=Nq-f(wcoB|%$_8HW=wUnj!&DlzP?{?kiXOUyF2XSfu8-r zf>tOSc2>-^RL=HD=k;0RD*A+`j$?P+#dI>!`7=icM9O!o7`NGSJ>*;h-NS2P$F|y) zC_y*F{4%J%_?r4&64Ae)WrA#Bc_o%DtWGa0;>} zB!$fg8HKMSU8`$;f$(Ia*PsXWZyeBS!N3ep;}2EEgOLK!hc6HD{!h>Gr+@OxSiS!- zuHO9+pFjL_Y@WWvc)pM?aZDo?%zEcR1u|pRx0gQXr4CkF1ufiKZ1);@s|wZ3Y)m5d z5;j59f^oYV>tW1@-)SW&;K^ysCPN_=LU>X$ADDkMK54zs_f;YRbDr_c0Ri1CaE;T= z5Rx$$qU(7wj+1hcQnWhmJtM187gv{3DI`(N77EO0SpNJS#Hy~9dsFOuL*Hp0lh5SX ztcP5{+K@$}F^{&z|c(kD6vR;acJiienmIYNjZnB6mY%q#5qQo3HJBBXy-iUrFir0(pB*XZ`j<80__*bsoHg=wG6HYC|N6P-H+zWV1Agp}&rO>W*u% zo(1=IPamCi#xp$Qgb7lClx$M8L7m2ybEOKGi3`&qTZp-jouCT}oA8j1AWZv%By$hL zbDZJ#a6hI9$+-2&dq+KP0z?jvX)#x@6?I9;u00ia6YLjm&}ueUi)O#WFJKX14z&NC z9v2cco_E&_p&qQ^|^Og z@$%`Uq)>CFYNoNep2heu6H+{$Z{qUxL0{(#*BGwsn2$DR`CcG={qZuhYx**kl`A9H z+eoOp59VGx7PZ%R37JU&7{-rM2*y=8WV4=#HW~SFmG-%?82YISXX?Mm>$iDNUBb~o z{$|+sT!6YBRitFg$5Z_L^Us3aKY#hyNq=_Io6NG30BSsoc}ix>QzWBo9QC4BBr?1X z5e^3`Gsejxg~X-2DL(Lm=S8;4v8bFsca>8;bm$NgKu<<&Zm4bq%Kf}P@TIOh)k*3; z7aZt=)$DOkHTYA41*eibWQCHg?o`>gvaJ z+t^$puJ7K(udc4*-LHNX4xKXG$|m}ED$i^y~^_o)D>`@Oaj?UG$> z&f8A04V`Pv!*YdSY3R^$y6qb7XPhB~?Tip?VZNHJY|#*pg;6o`zJc&aXe6gG9IAcr z=G{9%lxjaDv$mos4FCWj07*naRNT{s=mgjfwGJAMpQ%bukL~K|m90iW%#}12ZzU@L z@Auc~c)x~gEEM7(?_cYjdD~jYDUig0&-)XpY(O9^_W3X-7dS3fw4*W`-;d*YdyHTF z^2eB8UB{arei09!Kk3cMdX}?X{FO^=;uw4Rb*E+nYI@HkqNljY>XTlsf)c-@Aq{F$ z143ht^9f~0orUVbm&yiQtU^AWR5I3S$kpHn#KMRz*Vfpi@;N(CJQ@Y}Vl-8NXDqB6 z>s0b-`RY+B)s<6Zp_S4B`A#wRuf>BGfnBG!eoK0(`&mnzNJ~1^E>8#tp|jvMInp?i zZ#XLikmM+jc#rJi>L}b+afM#936v+uahs>uPZs{!DF(hw0AWMST0mq4raMzLGZ%l^ zcIA1Iq%W9M(dRsd$16?49Jgz+=!I6~I@Z3%-d3E5LmUt5IPM-bb|+HkaUb)W8_n1s z5Bu0|)`}(5*-9;eGG4*k9)X=-{^|#zJT|AY_|n7US}0Ss%SbHS;z@0{m6OO%w2F?G zSPgGHGIyc%z`t4iO4B=)f%REqAHdrOTN|{^(9Od71&$)(bRm|#DsZYR*vGJCsiZK+Sgs5mV&szYtx9I( z$Lw(p&2#7cH>=>3j8_Q?%-#1vW>jus+k-3}1-TPY1pB0#RHG!-_w;K{(y)}eQOb%_ zIUi`MRMcKU$Ervhmp1N&9nWmtS#qUf*TzMPXn*xre-)R}B>wsHm-zhk_i-L>;!K~L zcEE0{3>)~J%?Ctm6)&?yf!-}X(6?ubcqQ@^h{p&-#EN8|=|5@FGd^}44&s5H+2WuL zdw0EzcR$?4_UniEhyUll#Ah0I`>l5Da=D7hbQq7%sj!z-VOxop|9Phmp9gXU9p;~1 zsTPOEq%TPsr_?Fc0AeTA%QUHR5zECYcKc_KS>?2V`sO)~1=&!>D?qEryQa1|38GAV zN-eR0WjU-7A|aT=)P+nc)~s4akN|O>+6fwDbdYKs_>kvEKe$Zh2&SixFJ-{@eD3DV8<_F4ZTuNlsjE;_+TlR1_cg+K<O;deZXs` z4}6O8l%R}AxIsUgfag)y(-il=Ugfe{V!H1+O;P>s7G{6_@tVW)qOfC6s>bq~V6}2m zQ6w4d;B1!oc5-FpqsQEf-Q3P7bJqAWG;Ct0kaD45-r@#H;o=-BQ~y#xJB+Ki@*XBlu*MWV0e z2ok-va?R3Vw9h~^cI6^;yMd0VGU`B*U1n-y^YQWH$5>u1;?3K)^0_715L_do8{Y%r zMv>6{@!2FG7|y09BoI_4Fq~J{F`Zv&EY0lOB&j5NAs4Dq+WaMpyOYUeaZ5(f_qPtf zE`d?6$FirAf6apho4%5+Ws^fWVAFWtr7?nHjyL%v-&1Fdp!?IeB8m(}1z*8UtoMy( z9b>ihSenMd;u7-(1dU^z5Sgk z)>+5rKr1_Yn>u@|%65%iBsg;&8bwJtYo#z#Gy3W(mP80AtK{V>7@oc*uBH>4=cQB0 zOTo|ob`tFE1ob3I;2hUHd4DLW80XCQaHQ7D=6AoBJ?y)8Z{o+dZ#71FIGN4Qb)WYH z;?R6OTK(Khkp!0uRaXy>j|$|xADp$;kB^4oGZ}_>Xa_NSu}fxDGwzm5W#U777r`6m zh&x3fUl;cUNzcO(d)$lk&{bS$^bKoa&uDY_EN`!s0N{>S`*=FDJTJ`e<(xCfdqo0b zIY-ajvRoBaM0{(NT?D(=5c}(%y7q;vmThv<7EY>`k645bL@<;MN1W9TQi3J~h_%K1 z8U=&@T@IQ#AryPJl-L=nx&eJsXy!0n+n6ZTAs4f$nB>nJ6G*FQVB(2$i|Zt5RTgnN z#%eK-$zmL*{UV+pCh`0zTcMaRDIipVKE0<_7*B=&qO<5oB1e#4#MAmw=f+o9?Yp%S zF|LQRUG2JI#B#Zao15Es-fdN|0{7E9U%uWe&|cr&icJjbkg*1_X{Do`!V5ZpOq7z~!2HSzUh`$l7gu5*Q=Ri-%)@34 zk?jfp?yB;{u9b_Hd&4!-Cn%2%k#d3^gPAcTs?6$7HraH$A^m{olpk{>^`k|KTtHGJf^TpW^mm13`@O6!~itP(7YfkZx7T>aPRcr3~u+e2CF} z8q1sOSghu;J3hzdIMtyb+0;4O16~7Fi3_^UKwc1c=Vk>NFA)sB?`m>o5t{)inXxM5Dt*mk9E)21}Xq-uQ# zo}^kpM2M;p6+jRk^suSSAHK$?Pak5vc@nYGuq*!0p6cLFL4mVJwm43#?^A7;8aOSBdT7GvSx(dIbqHt9{k zo@CT-X3c>i`Xn&Jr!hRyvhexC8sQ!yrD~XWB5F2NVOe zI6-gbGkrof)xDq3%+^oUJ<#3ZY!c(sG!_-|E|<8=fL_xgDx}~FTn6z3nK%uHG#(7Z zzum?JE&Q$(iep{p!czxCCd}Edtv+%a)Y}K@N}IrA#UqcIrP&BUfgCiibvz?ffHHr}}DrkghQ+GafAr!DecEKJDR9Do}!xcOGHm z=imMKgWl60KYobSlB&$iRIfRSvO9Z3oPTu{^To9^yQ$DQ0FdK^tU;E{q3Tn{Kf|a= z*IQ%*cm3iNc3?s4+I?8Hv#+h5c!@tq@TBmx=A%eCmH6;p&C>AS?Ni32$V;U^W}wNS zIS7jZDzXXidXm^Yw#T}0O9RM~`}T+5{Vx8m|L}jtzxne&i~BX|Y`+t`oLOw{563OA zFHjr-#tfKObLchGpJ)O1kRs0Qg5*SiLQH!SAEF|RqG+BwXRf&%nB=F^I_489X{&3I z3G+HaMVSmvE(`&)xSf!_x<-%U#h^o5g59 zj@YNPC?*jxk2Ry05}-jc7SfGJBYAIfQj(P9GPgu;scMJ9K2X-!kPcw>9L)AKpJ4VC z_U`)WK@$e77tP&I%miLPvzB#pxkI{sWv&!tnU; z>>2f0@{R!bn2laW%q2OSfgQI;_yDEUsTk?;+nToNB%n*$`_=ebok1PRP6Ty7Pmh)5 z$SujS0wR4%3IT}e1j&&|UxL$xj3N{@iOm+ZK3DqtokgTbOf=6gNL?$<623vT9uobc zKmcHX?;zK_3yFI2GvQWXPYhX7&jJ5~vDNQL=HaP~2C;s$jkBtG_6*~2AjH`|k*LcU zBd3kjAW1ePK~1uaf+Y%*B#oLb@EI?$D0mE1*dUiuD72)v%!_y*a~mny0Lt!p_B zDllQP&sUbItrlpZq@(>vqrvOTQ^Nci(7zW5zFUnqjQ7_MyU+N{P^FKV3D0 zU{xv9LCE;P{o_NdZf~+mj@azB>Jj4zvJQlIbt|bQXqR)(GQ#j6W}>c`t@US-ODvqBX>qeIIs$h;r>(AA_a-usf1h< z@M^3s(_f4ga+dSq{vl=vs*pjW-M+kz^XajxDp{$WcuvB>MGCC7RrBdwFYAM#LWyA% zA@!mNhPdEmpS^SmR4HlflOyG*o*CD{Vd8!(>)S0TjjrL)Hk&Dlsdh*T7j)H?f}aL> z4KZRv32%d5<>URA*kDkzXPoZ23zGM!R^@#ZH{)OrfJzujW);T1nC^*q@pYyqFci`r z0fFiE=(m$Fud8zB~p90K5B&4dITnpwP#d)@9PPkc1BzG z@_dSiM?>v=uzreEN7aam9?yq(NU-5>=XT{P&$t0v}Z5*z$sa@Jw#6 zuNBlu=mr0oo>1?Ze_8_;=V8h_lR6v@Oxn207o7rN0*!UVmR#^=mZGBu1F*GUZXAAIBN1 zT@(uuN}9~$dA5t`U=#BRHlb)j95mm*MS}nx1&CriH_rl?ba){E6Hg8?%>MiF1i~b# zwqQ1KfVA>us-%JdKY(mTt3xfyhZtYXN2=spXJIDFYUnV6yLa1UvqRYBImV;8NY9`u zASw2+aFM6ARaUkw4x*~#`_`w&tIz7buO8R4$%_M^Pi6rdLn5oR1a3Y zS{O(cf=;wO5r6hGh^=x~`!HXQvAJ^4Cgd|M=&TmW14K9l*w^s8=ehYVNMQsWYnSU& zj4>X*Uss2$UbCNX^7x7ssR|0Otg#L}k$J=x1k%kua%PuhY|;n$WGPQ4F*N?)P{~`YQ!yh~Ly2jCX=gbh#Rk-hISwz%CLIis%%5+4N?H{lqW;UhO-H@47>87-A z%{wv%m7iq&^x%7uj2>$5s`w<)v9MMvDqRz=Zm#C>5C8S=^(UU)asZo^>+o#912u$ zYk~m!%+G67{@?)2Rj%0@H==e8Q6qWeL zaln_iK%E)3D)Jbl$eP(lA2Ca;^U!Nj9jGz>=pN0R(mzgtmJ-zvvmG7sYB^-JsP&oR zN!?nNqnDEes#R6(3Ut`eI%)H$;ntPY7_%6pjNwuw+A_M>>5=_GKlJWSlB=wR|1$Zn zYMsmyWz-1iGva3lp?dOapHe}dVgN~YWpkm!@DKyW7h!#iES&bu#b?s^RuTvio6+n& zsZ*}cBm0{KnYDM&WQGz#-t)v0AQEzE#?I)?+qh~dqavAC4V#IQuBvMn)-6NP)$SKK4^)sJE1Exn~urQic3XRM<%_jRe%rRTR7I_`R9qkMX3G1^n z;&(g~NiHJ5F$>PWsk4xZG&{}|#{SSL0i{zb7>CHUErUtAM#I=Z7CmfY0dmLd?oYAX z?BlTQH9UOQu-iY;%VE=4hWb04FF;~_V`8(Zru?>bET%;EJ% z7yPBwoPf>Q7MxJsc(M*FK#r zjW7UF^Lm;ww8?{dmzqU#B4&~rH(?U9g)8A!RHsEb+7Y!@B~6=dd=X?#l0XlRR?sY; zGl8~jS2>W#o_!x_6F{8P@Tvq$q@6#tHnb|E+<)}aN`6-o!v`~f$?hF+y>_YmGG!6V zR)VB#c-Fs?G0QWHft!;GTu;fra&HU9Zj}J}APH!h?zIkEl&(D!x(Zw)sV}RzuBvMY zo>erIhJF3rlK>WW0a$^zhFYXO-WS)e zvCL-OGcuZpl{o?Bufcjg$K-+`6#)v76T{iazPe98l-#n&ZG#ek%I7xbZn56|%!C>? z1h}@<)D}rCy3xh}jpWH=t8d$u?mQDoB(wazOsJHErsAiOfb=$qRHfYYZC--bBJbh; z1fiLvhkG*>QILMP^aEzN=8Xg2lhbJ{sbd*dsz>Wqp*Tb+D4zGK)+J7J7{=3X6Hkv@ zwJs2wLj1~ToJE94PIk08bp9@4Hor>AWu%uu1bN?Hv+PaKwABqQ*p+@>GPUI)k_lS% ziTUsD3_sd{swPZoy~}F&zx0@J@cB(2e&+7B=kjcpCbz;ClABB;k(q*TD zF`*-8f|0N!Mw0pGY^d4t{XwVf7(!Kg|WRulvE)yRL zUd&w2Gy`<^ESoIRZhFO7BuU3$cB^Q=A@#4O|@Yc8F+aHVk4Ch4{2I|#34TVKI^c3!)VtJO`+=Ma@(opT_| z)j{{GzhrWbN_VOT2erzTy-V>8UE1HVJYy?)4W<(x_Bk zB-!FMu8B}!-Gz{$?y2&MZ?si8rsE=s~8qiPaOEQ@_1opvN zIu5i4w(G6NVR1^_j=X2NmvTwWeard6)Cp(Je0Ci-H+Le+aU8IpEy3K2@kpJKB2cO| zOkLm#h!;ApXgoKQ+6=2(l~gKoC8U(7Bwwqfs`eU*K7Z%DJ#K*8d)<`r>rA`-X!|0s zv+;UJauCueOC8sR$X=MDE~ z<|8XcWczXcyZFJ-C5ED#bx4Ho4ZXDTNIuB7|-LeM$@ zSHrx7*s+>xB#i}3j~ycxb^{CevR^BClN94-ZAh%7JqrQiJ*hhNk>LJpRS~E@A;RN6 zIy~0_Fz5U#W~&>KPgNaaPeOZ{&Pbo`f~ZB35)se8SFk?M90Z<&;A{a35C@VE@lR^@ zzKDUAK2xS&s$&`@fQA#%Dgy65J&mDlC%Q}nAZ=5m!Gi{0nA@&|JO6CYF!SLuQ&<)1VfDxXTagP z6hplkfAchspSgvs@_bif%(0+WOBonid3qQsV?ROz(a3^?{!01D9m1w!rD&b>~AQ6oCgwtyZkXa3f;_r4V~$CZ7}4h7TpjVuk15H$Niwq?JF!-MdV;@m)H%^Q9#&FC zK(`r>r%({kVWNnyp|~lzTHPZfU1ND$D?2k}T@S3Ft!^|etxoxLaAdxbp99KBxLnFj zgBYOQtNs^|VTs6?~=JvUleRk zDrht4)i1m}XSKmm$~M*jKj}M|WH&Ba#11%AT zQK}s6@!PckjRNgusqCy11lb!da#Gd9$UZR3fhc(d^qxpEMl)?1nL$V{(J-Wxvj#Tp z05%ivK@|io2ULpO^JDR^RtvGRCA%p7Y~s&R`q~^)v&%tMjLb=ZkXhu%Z1YG^h==_T zH2?r007*naQ~*asz4w@#)TGF8k%lAz;{Y1RXg=4yA1_xClVz;WmsrI)ez?1d#r0AL zm>}i-Hij$EjD4V1j&1A55BD*f%;RbIB@WCPzxy%H`>mkv^KlxdA-!0og;|Zks^x&U zI0WmF>t!w#iCZTe;+@BKbBL>}g_B#BNQ?xtL)2q-SuFK*?E|VaRDZMs-(VTb8Y_xH ztcHvLnu)J!gGwB`UQHaFV@Q7-A{%q}>xbBrwV)-vqw1mkvWww)AI}euCL|r;Svbol z;RQiqCRheUqj8)B|DPPRGdEjiR_eSKMltP9*hhoQvOmV zN@|c-aJK^8903*0GLNO6=Y!EBjobtyNhkHp)v8hQV1>$#N0T!feVZn==CMSbdM2C% zwMb%>Bz1juB}q9(y5EVpO!9NRTIej$X~cRzU*hZICjR*0vnoW4HQv4ZA^yML|DijG zMIM!K(Oij?sVXj~Jw9esf^{z>EQ1%qk!UlVK^Cd7^M;CF(jilJa&!V^gh5uYgLCXr zJ3D5}LRO{LSYRgpazQc0_mJN~|J{A_OWcibtm!dw(ke!_ei7q+2Wj2Aa&qgC$&s#Q znG*(Lg=d>Z)Egz|g^mJ=nE>nG>2-2Q3szcC>&-@MllCCLpS?$7Ys81%I$R+4$%X1> z(ssrxd^C+c>Y*^?&u2{^j3?)~nl55{3tCb673mtxRKni@}k_pSUij z7MNOMf&nSl$$aTPIs#F*H*t6O#wZOQ08((|3}=+k0hyr9dL{mu%Qtaq2^(0@QKzKRH}wS8BcNb0<(yb9Gt8 zQH`k@O`c8p?xuKj5BF3d$Od3#X5T+yyRO1uxumc8d3X`jzPg@^05_b_OYz9UbT(JN ze87g0D2x#Y#!Fb3a0FN=0y~v3Bug__qwG;R-$r8qYe1C038RPwnqy$rTQ_VdVU32{ zP{DaN^Q`@DOYh!B4t&BX@bl|oVgHQ9NaW|P`*f136W6bUH%Tz{;b*mwnMx&fElb-% zAm`XV!;H4sL06&Wu0`DmWir^MQ+k5QsMV-aaswdq$bRD$aiFaVKtZH6MUp~~>h^6c zZr{XY&b&Y35N5lN&}mNwr%mLM_OR8qvn zs?%AL&rxHNy?IFLU3G~Ey-@{ql6gj~Vvv@@PS`NMFsh6}&RK`=$1fglRlm6*akgh> zi*AzDlrYU=Y6rW08mzQcu|>5U=+UZY8pBR|URT!qCP4D649`0$?j@ns{<%Og2Oa0=p%| z=Mesa5r>vf0klpl%4@-B1dzJY0x|PFGJGCR;>cQITk&R&?CA(-0!(`FGoU~!vV`&v zQ@Qabu2y%_a>r|d>m{IjGG-df)m5yno?^N(hlTA%a3;y~S_IMLnT}(&_FtGHYP?;jgyz0B^JDP(CXu5J=9b6@2nFkG-7l$pghl`bAnZ=5O zc_uAj&BrPcpn~Ke?1?0`DV2ezq-}c`)?rpX?ACs&h+u7CYg-<*@J*m%{9|S_m-I5{ zSvbS%(Uup7VOBO&Byyw!@j!4v5{*>OnP~Adz&!ao%Me8V+WWE8v4wj%SEK z3yhtb?M1v2(^znIPfpZRq-CS5lO(MUZZoXm0Z2e{Jd4HEZM^^CN9k~{Zr;S|`o^Ej z>zHRtquUS!vCT%%^7HePq3BE~xIeSyGOpsv+RCpEV$GJ~=oGf4l{^s1MaTHBkwB(2 zob)oHMlhI&#AB$s)`OmdG_0vwmC0$uh|^-OIbowAU7van``&QBAZ}-?osNDP=E$7n zv{UlIAqj-OM-Eu~#w0in8KEO^7E+W&V{n~}tt;M2=&JgvHiRqgKJc^wU29G<#r1F1 zPq!muvD+0)Qliy}n5#MNfkv>BnAqxGIM9A8TH_IOSExLPdLQjNSM%o8xZCTGzDn=E zuSkysZh|VvK_wU@O-zf>MPi_g;0l#WxGwzZP~V|J?ugvd+4;&R5_bd zp#3zqFx3bfX_~?!eVHHO+$F_#GI`I9+dgx zOK*`{d$C|(Kc|=d^lA@vYowI@6tG|It*k&5u!_lFqBbHiIH3U={gIvL(>c*SC|jlo`tD?Os9m@y8*eUWG!G0-&(kJ zGdje<%q6EIlBDJJfW?3(Msam>8cp_Asi~Xy?R>946xr^P#$fkyb~0jnz)6uQ_)EqGqh(+<#Aw8ddV6J2`YO zh-{NjU|S$e7TbDvj(Lu{6#KGEnwU8k#K>nIx{XTS$-&+U9FX_RnPQpVNDg%>PK0=T1U(~dyR?^Q~KPP zgB(z!!)WKCnOZ}aCKYj55TFU>($`OD?{M69L7Y~_)AK`P=j!!QQwk;_dLpC9l3lWp zJ@8Jg?N!oQA9bj+M}@{^1ylCCeM0)u$xD*LV~^oTBxN?s{nO8hcMR(s`Skm9U=?dP zOo^s;Agr4E-1KxhKi&Zf5TB^j!cwkoCyWiNN$URz*v)*o{`H&)ydjLL9R!7HTsh z@ykh#6y%wl`l*%K3`EfhhhHN(H;KyC)I&Rs(iRw{6!?MzrS@abO={2BI(zF(Ga-*F zF!I-$*zi$P7D)U${97E0fIb>b;-uJ8lK_W&Hk;V&Bc66J-@!Hlkc7|6Qi#MpMr6dRQfMN054$iZs z<lBuQ@fY=)x4@UJsG^)1DexiE;wEDfcd(yH9eMoq^Rbo3BvTFH5b3J+L5Ie z8h3On{KYS0 zDw5)LvWp>HQdKxh#vSYV{!4uP_(3whhaH<`7X$jSsHriJOVXJeswFMCGE8oT`uUk9 zqsoLDmy$M=)6Owl7%}m*Lob`lx(DGwoaK6drP*pFIJB+LHcmkRgZJDC*Ju)_uV|fU z(SE|56BjltCJ8#|_5;~%)s_N%(7~5M{&KR1_tV#V`!MHhZmmUW05rbt+=up~0(*Ce zHwSkc)UDs=q`di`PT!&Tt*T&Paumr7{cQS)o;RY9Y#IXxN5iyPFoyPK)rJI$olpTf&onK z=kskqKNHl@1W{QxirKjL9T{ZdM%!yRXYVmXjwuW01!Jx=af8Uikq@U**CYvI@fhJC zdN%iHCk~tJQw7x%f;U^Y@74qLu8Co27l@ChWXS55Jf|JPQ>TN*gK>A%x=2R1X30mO zREQV3eIgY=wQPM4=*6?Y8FOV+avY!*2b~eC)s=|LO6==r+YMqkpsylx8{`<4`_zWg zoUO42VGSz?s((WrzZ^$~RJAQ5R@3ktT)@( zarBgcbHh~Ten8xV(T<_XoA*D&n|JSHd3B@D+q<`NGNK(KFYHWq2v*zOMljc>4}Xl$ zpFVhIlZ_#`%UN>uL3@O!uMBHH7(q&}D9wInHAW&tvTMLo2L?=83|jCpmy6oiNJbt0 za|umU9A(3%{(L@Hnd&qXA8c%KN;R|ZKKha1rmvxn#ldmvs&qD}COss)Vshrw^P`D^ zA~(XH>&Id$I26aD)|?L9%eQ-_g;eX$Ztv9Cp`M@T+ueF`a?*P#^dnGh8wZram0=$o z%=Ye+<3e-VJ)nZ(I|02Dpz7Z9%Y^0iM;C08xlQG>Tux&~0BkDiLQ<-wRe~^eX4Mn{ zQl!OC0huWSlak$KJ#2Q6SY5H3G?~anH@k_%=~#gWeui2|Ac8pOF+Bu&r5Sb+6p0QbOje|GPYdX}=d-vO4ur(`EOf%$#U@#`4rB04-#m?g zutQFJSoR^Va1;{Ue+bK()Y$Li@zM8uwU}woOSL~|(F;ja#XdNz9Yn~QeM6#H^{^2l90i1D+E#+a>wb>D#Uj<&b%NP~A8NgYpIb9R+ga^(+o%-ns(-d(_ z_Nb-lo?}{mu#_llxKtq%L5G-c6MLyD5kw@m&U7eB3kh5M1H& z??niD2~+izhu+^eQo9+7zcVV>2K71+3A#1s+Cs!)6N`=P_vD_Gb)qY?Ca{5ERCOlU zu@my(evhSIr0;EhZymz&q*vbxb*#r6n@ja6;45h`yB|;V(lg^;O-52`Q-D_+#WSt0 z-tzioF-sq7BK0LiYi{rE;`)Z3`L#%JOb=9bEq(FSo!@PrWApSFj}Q0p>BGOo*H0f~ zyJlo!l?Wm9m}= zgRrNsvn%Yu{ke$pN)nYt~=z zzXtC8nosz}%ZaLACnPDJq3y@fG(mAnSiVM-F5eqlD%OeB9g~A54GIx0)3plXtAnBY zzeePW@onTuZ3ZPIITF}ZdToN+?SrmO_5D71&o2M|N4*x6a?MP)!ZY>0mJ93XyQO64 z+-zxA;PQCL;8q86^+BojJN{6Kw`6Oi5HPi6P`xAAriF5~rIgf>sLE5j+Bi~LXl!fQ zvwc6iJvaLG+*iEabJLVjzc$C)guE}Q3E#|A*R}b+ynLO`^S$FNWfE8S`PF^zPv<%Z zb6us<-!Qp2N=D?7Fjqh)-xpgT^+*Wl%$x5{w%6ut9%6^eRO9Rv%i|!Xs6vjGF_w9j zd*szJQEOo|kh#icztMCSS`v&d@+oWD**r$Fz1=zKNRN8RliS@khRnsEcR~V1cq0I7 zHk~AI7rX6RLRz|)ry4s&^>ZCt&d}jSlRKvaL`)-{h2W@4Cz(niEv*Fzek!W5ab>Ld zS(70ocjIK_@2e5iRZ1i*|qqoCB zH}kj?Y;6uLS{FlvBN!KwRBtcR0)cYAV-moNt*QVM8qsY;^3(JH8FI7XHBk? zU{tncFl5+0KgAZ^`^U%lOhCW?9NW!PoY2>XqpK6NM;PeCl|N+MM`d;Qa= z<3N#~c@X^ON;;I&XUO{Wywo)M_!HYhH(^Y(;@#ar&B!W6d)r5Q3Hn zl^trmkW?TN0(^(nCX9Drcaj!n{qgRm%|aC~=Rppk=cm|hU0u3D8fw(1gP@yUGNhkY zCb{E&yxL#Yx0S`HAaf^H1tt2P`Z_zrJKz3#pX&R?Qg?zcAMGS_s>t~7e6(mn zySLgRL6uFB@nm_LeO%gsSG+H*Iu9B}Q#FgT77!>27Ycqw@{-G)iCMfg&_$~ARt%_& zjr2jwMIv1N`|x%sK{ny_yuY$~__K~kuLM+YqQz;9shbBbaNj(b} zkL*iO3RNDU8>nbYVPqv^E}J_N4hs8~DkA%wg936}iwK?o@X`965 zG>M(OI-bSb@Otb`a#$}U3BG6M8>|+L(%A*`bn+SAk+GfWdBdvQSJhcPa(cxUUr=9G z@~9~kFu;S^HmGE-n&(wOx1oZ3VH375sD2_lRhYOXN$CvS{Rj7h#Q<&|JVC)ykh9b@ z_h!@g)Phsby(dyApyX?m5***lYpLolgNw9#B_Yv56r_&1%0gbZLyf2*B13lP>tnu{ z%1}X@Lw^HgMqjD|ZZD6>2LZ25E@}h{-Domvn|G9pm;>2t|a zl-`pd^CWg?#06b&d(pFaE9>>an!l5Z_ToxRA`)WB`vB!YhR_2Gybc$Fs$@hnlP;*p zz2}`ObpnQ}86{mDB(BIVf+5dxN`g2^wzm?e6(8KK=3M`1ntMh(G@Phgd&6#9_0J!*(5u(O7f)2!qte zYf%TUKPR!=Pf0jRdev>2k}GB%aPO}dS2AhA-}vnhKgO5)hq$|YE7KTR9L`X+Tj{mA zS0p54;7*u}q?G}P0G+*b&7Nuoo+`vz?YqGt794U4xp$;+X{`(*QP zHeYfry7$`!Vi1~Ci8~)WE?1JtU2@g1oa->Ge^aHcWWdi$Q!EqDmDk9ftM-yzJ?UQ5 z2T3SZg*3O5e8j;f@9HE(G1AB1rN}pO&;4}9pn`qlk=XXU=uiX&q~dSb4X+XkJ?8|= zs`^w{w@i%qKEy|MVYa&jSt6buF7nU@KIge}FKN59zq<%bl_V>;HF<|L9;mjn1;zQu z+9^diP#o?H39k?n5;EOGp!*_-fxLLnkt~~TkqMdB0R`*0uk?hJSQDUnvt6Ysl*EW) z6(#k)>$9GJB_*!Z{e9K*E(Av!B2C+|)`~qkn33i0f8JjUnG zUpgV2Qiya=H-b!@+HAJcSATqb(nQH(JdMK^lI>P|cQU@j{CcG#gX9om{@dA`zX_nsoLcl((2e-+mYo3!+j;;EYfFR0CC?Ps2STtSX$ zvzNGhsodBtZIFwg|Fj#B1HWxmwZytkydFf8sj2D#0if#WD)An|s-Efm28qvYCpN}oGpelmoSUEM!MW5XFz{>bsh8Nl>!QZ2jw6LURSfF$Z;MM zuytXZTy(SeMaaqd@%FIMA(^n0A?m!wBo&nxx&wDVKinV0nXR7<{f|byd}aNP*T_Wo zZ$e-CioIOZG>2SS{wwDtjYs7iX$5{Aco*Alwwtm%drz}epG$x+Qq|PeLZUp((KEJ@ zK}9s48qHBxgtiDWo1WLkjDfz?>F^xK?J|zCAicz4J&3_^qRn#LZDaHBDIPw4h)@6W zbA0{$A$Ct#4AMU*Ag7;kl7gtPDxjUh3f(TMmi~J#~^) zM%vEyRM6xA6(i8QDSw_#2_cCzH|Qlna`W^Y&%l->tAh~HO}v~@B2n^f2c;au zVm^sy6z6p2@J!$%F-c`RSoScLeJL^W&?I`MaW>-1Ij#`V(z$8!E}~WkB^^c>xxc;t z!7Ro#KkoUyys=_@d%}i70E4uXAs+^Xz;M}Km zkoDpeVNS|O7LL%gSQ@5C>QVg}AG96(t`VOM-Z`JCV4$?sLN$dpct*b`oG8EWI~ z7KiAx&zCWoE!96CjAj#UUtZo*y;oNuN{|wPsqU6~dGzp<)|aAH2KQIO z5-c*_VnOZ){CcTUH7e!+!6*mcHv?`@=BzCmdwE#}0FZ+iYJpBB9Ey+&O{VJZB}pMH zR{Bx{dRfnLc%H-t2n*=yu#UL8i_`YO!GM6b-^Q0uALHXc{bPLi`S-E;`b8Sb1WH;Q z_1;;dFx1(k8Wq9v5|8#wu5>^tp+IJL%8ha|GyoYmbq5Q?N%Z8M(7|e6#M|rJxVpKP zQH`xOeMs=(1HwtN4KgyIzY08s$ViytH0sGV2nV4Yha;J6CC$vXz)cl;Dm~+{Lm{kb z(PUsi;cAPQ^7;_Ng^`2y5Uzkx-~SqB@Bf}Y_EI^^bt%%UN<&p+Qr81fm>OXN?Xeeu z{jVL&sXop2XAh|5m`UC7WC4%K-UP#{4mHJ*s;=K_1=L4dK(v3BZ$Kdx^}WTP#x{tH~!wHJ<>f);4IFj9AgA6mT(v63g^kxw#CsAyZQA0IoUh+s<+@bvJg9y)7RiL6l=%qdW9 z!gV;NT=OL3!i)mv#p1Uwc`2;%-}GK2pL*^cb8Jn=A!BPtLC$=QDm~qPq^T|iDQA#n zgDGMelBQ|Ka(Z1w<_L`7+L9K`;LAUF#D=8E6$^oX)cJ@zDUsS0|Arcxk_0CZ)>Ntm zW@5@A7d;P1ee>m&{uGp^Ic>|hT7P>O+h>m~w3V_?h+N1W>Fnj0OnZ%8CEU!!)&XuZ zANGJR1s6KejU=KO=6Y>5<7t3GINFWmfLs}JQ>mm$3aV~{Lj`mnw7qV3uR{%qjps=M z#6p+4oy?0oB3I%UHJjTB7v+>g!F}QsBmyX_dnh4y88}? zf_y+mY-lSFrhWjsUM{TSQJT6;#!YNRJ2E8-r7NDMuBNQg5N8W*!; z9G7Y$$rOiulBvX@kjH`(#L);+VTmiHwP_~7 z?k6&oWM{IcwNrh+PmjiRs&oGh5?s62Ui5EYp$>KZBu0f8aL;QT&Ct9Bc=Wn5lw!(* z!?~Xe*SHc*680;BClwXjy>G#(OsHjwYu(7Q;RJgutuzI+ z@MhA3tA{KjiY&!kd6!vdFxQ(X0~TANBJ0JGGPX?4oWKB9NJV>3IQzpADWpLT-DBLn%O8Z65v}D&!&tWagFqT zIZT{2t2b4`As6>n#L}kn(_(kvVotHG$Y1tl8HK*gtP)jNC6TqP#Uq2#P4=-~fwRf+d=XbY%wj0JthwrVi#= zRG*J(%q9Y5*;$NqOQEs}>Df}nv-NxpVnx#zly5uFg({ui+AfY5sxU5eKE&m)iT!LA zhi9uV>G>mc^ZXR|pFYRe&mZHs+bA(&&79F*9#2$FGmi??e*g7R{pM#e^xe~?{`gZz)tYk%|ZtpfaF!IZ>OhZ#gF^_9o15}W@=&8Uhg zLNS^Ok~P4AI-}(=it`NN8ua^_w15>20%VAr3S`e3Aej>p&MtH3*;(WrGH#?Y7=q-5r{RNUBLW(>5f zsoX8^PJW5^_j8frK(i!+IRWI1>Qmdxw`p z9O%(AUwXo}*d#|G!smmMLe{l>6HX5L44&vLRYmXp;rjwtCMRfkUrd^8wmQ4y<*~8K zCA`7)W*z&K9wwwsId=yTgu5!z0jmRUQi+wys}I&d>|X3Zi#q5eTu`h?XCpjQ!B}pb zHv!1Ncw4RNut*^mXKz`tN>0_|Qp(Ho#$y1|Rui?T)QeBsNO=jTbZ0TBE66Z|+4ZYM z3Yw`J7rd)ULK`O-qT$~LX0kH7DBW$tHiAG-eGj8ODB6RgJ)qkUU3;=xJ7`Py!NCmD zm|pjkRjEiYKs<(7>az=w->F2}>b&D5bUk!4#0k{?p{($Ac+;Qn%@g$Av&VKmqm;x# zW}o$vlSPCfA}b4(lH92yVa0H-!@LvPke@iVhUrJn;gu}|6L>7@LV+*S5WP7LLGt2b zY>&GbZicbW-We4Pt%LRBgQQ-O=p=k<-dut+%%d*i&E30LE>|*@p@(+=<)a{At`R0Z z5c(v=Za6V@X!8W}YnqTrg9W_cfBf;sxO?|jBWu^UZ{qs;#@9HV#!a%Kr&AJPCw@l5 zUCFtsN)#oDT3QqOhmsDR$~llz3J$^GJVRtYj(fwu97y#D+n!|w7Oy*tH$f^?qMIJ! z+>^M5X?%>~W@ol^lSS?Kx7l8CcJ)z*Gwd?n-ECRmI?-3AKy#RT(0o5 z=h=8xyVmYl+z{Fd1C0U3aHnL1;I6h#_B=@-J4NX4e7xR=FB062f73WeHah(tIUB@i z#=h!(tZRQ)fG){R=KK|mRr$TFW*yM8rBTJp_h#pdSe6NOy`R_DU>F}5mUF0|OsW&M z{W2xddtSC`2DS*~}sL7&l&#`ar;pHMN^cU-+wOCH1u1y45#IjzaO&m$$ z^3{?cY-G4IrC~1$&_SaiUqiO73DYOHi}eIy5JN3-IZBF_Ah~C)uQgVNKf2nl=UtqS zyV&#dXL{6FNAIP)2xsw}Y;yYJ6jgjbq}<`<7(4ctD)6JMYB{#~ot!IF)VhX7q0@<= z_v(CRThN~!9O;0`&A z)5mN~SL48%%!2zDSkIXSD5$y((qCTDYmJj;WzopXFM1 zjL{K7Axu^T7Lwy2=|#6|RH7>LPm1dhGMGoSfZT89Btu z7=Z~?=1Ah!TOTy7%w*f+1Bqfi09Q-BFn(zpIuo)L+L*HvHXD#%Z)qYWWyzVM^~W=ZH|YbW4V>t>l-cyJ3&ObeX4%tnZZOz?N=w{J}Zk*Yt*qfpQ+~~VW))heU6#gEYv4W zSh~XIzw^-+2YsyQ$)m-2X<700eWifd1^i}B)xX#ISS)v4mlBI~oYO5lsS=ND6DXHd z51j;+pzZSmqA>qhR>!-2(|Xi%JI0pkR$PvK=TKR)s(M@}w~F9JD0!x6?S#>CdI-23 zeG2$AoN?-V(~={O8G%wTPkjyTL#lV+dWsJfAf|JcUV-mnp7YXn@O9Y2HVL8`X|*nx z008oz(EdwQsT;F0w(BfW@Ed=UZCbcxijTRRZGbkNPV(O#C8}At9=OW<{uIO-zqZW~SR|>R{A+YfXLQiMT0xFoP>VOCIwKy=0=#qK_@58F1IHxyVq*F85KzG#9c zqq3TFewNt^P>$iA4jHeInZ;a--NG4+X?O;l=T*T`*Ov(Zu)6|g&h`$24Kz}6Hk=^B zag4?4B$-_&d?M8Zam<+KoX+Fs>RMK& zATA3=f~K>$S}vtFcfDE1c4t8cg7<(;jKU!V6UO!yIidtKI<+DkeJe~JuJ7I`n7@7h zgPHCe!1HO$RCU(eDYBd- zr?piqV>?3Gpa%AE!J?yTZwO(t(9h-aDAFE@i%_?zp=SDWs`L+bXfrJRs>Rd%U#C2;0}$MB4A`%~0ke znxhXSaeG}0i!v4I(~G#2>R+IO8Oz)vWRH1%+0KzUF>@NmV48tN0aa7|J;8L8Xk*G$ z3yDYxV2K^UZ%E@Co~b++y6~FsBL%eD-f|0JYwYxe;$80RtWG&2bv%~Tu7bIRVHDW$ zW%agi0=tcBkF9rXkrXO6XiXgKQU_vH^5)#+#k{&o_lOi@qzRBxa)|SROgzS zk&qfmBGRo~Gwy>t2ekY--`J>Jggl>Bq0{Q(-focnmBS}V`9_?q3;L+C>8-J1^GK%W zsqAbC?AY6?=dE)!&9+kK-3i*bn_{AEXa174C?rZn@i`jWyeEalq^EF#;H3qSX^);a z1TdQ-jCgZU{^?f?XMN>;yu^0Bj>+mqGOyNE_YL+#&%SO|s2sq^fRa-Ya8nM?L?aV? zY&Y7&S)%rm0WAu#|Z(ok=lk12pb z)u6@V9ys?w<0-mdIr@`Hm(UEUd6~h_e-A)-d7~+egBsKFYMCtlW6WoxIPO_oKDaC4 zDa9<{$L%n+@70q+7L#7pF~%_4K>$eZavojJYIoLX2K_e{F4wCJcQ$nwM~4LDFIoe~ znByNn-;;3;DssLrC5Stz+hz<;@a+P)mytxE|CtCl8 z&fZF+p!e@CsMqWd&tz{=mfLN#Hl~YdjMg);;5A-nVMRS>**cPNz}OuP)3AgIUjCKYb9~2U<{?>tIm5@ZG;lm1m(eO6~V$ixT53m#2yx% z`Q7;>$xDLnmoJ~<R%a=bPdqUHOVF&$FB&yp&b!Xzo!sT5RGxNQ;1kAKYK2YVXh2UnIv>hbpU!QOm+fc3d1}-sVcvw< z_1fx9qhOfAS$LVJ4t_b4*|ouQ^-2kq1*NTG^rTR61El09!3Ui?sC%M*$=?|vC3ue} z%h>KAjGY9vI44-c_fKe&aobQP`M`2_SJ+bHmEI6paOB~d+yGkg&$?TOtNmExz* zh_om$EEWorTXt?IGrWg$R0){hYB|yxX?XFj8>HG zr^*_ONuKDEqLc%#VL07*lj#UadFQ`PL5-T{n841Lq&ww-z3!vCr|OMu@AbaT(pC1E&zEyhN0>`>HT9%&R84AaNdjsKKs84! zDbZJRxP4}Ce!yX1;SiZrlveci97C%56yXtJM&o0a#3a!{C!ilib1?8>nMN-nPWk{P zSt~YnL0Q1K7&z?G`fv~YrfWp7!Uw%tBeS_Gavb*_H(SX9(?3LrL;yL-0&qMt_6aGY zvM46DNMls!$ptlK!IRt^67V8&kBIarmNe)QXjBGy0%NLH=|HK`HV%eu@1NW;k|hF# z7>y5QCE*uW-&gaicyo6r9>I3I7ec`tzZH6|g-?axF(QwA`h5?C)VMu#w1#%gp$h@X z`C<+%5jCxhrXYHx-_Jg!U+y*&1lGsaWs#2do0A!Ba zuVJGldrcTbFLEhKL_^Zbwfv%go5^h3PU1a49pL@n-Qs8OHkwCv=?h!ioBM>+a0}%t zxHl$Cg{JW<_4*CO&G$eWe1WP7nd$j39kDLS0=@Z2w$xHXABhCc;7n0G)|SL$@8RYI zN%$86pey%2$q{VL1d$rmz6b8r_V2kX>O9ZsGF{R z>YHogDYY>ao;-VQw@T0wDsKu&)*Q%9!rzyJi^F8ngAA8%IVx>RTrRZ#_Nfz}ZiYDm z=yME%Blr=i)sgnYjsslZ!6>DY%uCEbO~cPqN#L0C--&b~6?LCVjc_nvJemYLMYR@T&LUfL)v)G4W_brBlL*3L6DyIW1w~FWZ&TXRH_92HzFx!oBa_FfC!;`s0}YUD zEnLB1>6oOOo+LJjxNv*}^BMu7KhHn@V|fSV6vdDm|i$sF2IZL++M<$NWUB&=r+l|t1qhqe{B(5W!0S73ak2YpPk^G%tToqVPv`NtpkvY);m^r`?Qo*Y+1*z9OOD{dy zuNf4puXeLs#Rw>Sc@yt`{4wUsRh;j?>VWTH(zH)3rg9O2n9a68Q}&f}I?JRur-7s)}_e>;7{vh#hNQN4<8rG*QS*h65osv$+}MR8E-O?2n9Hnr(i! zgdlhqfBZm|vX3E}^$DqJ+laRjK>ucQ?{cd?SOte31jLtLp?xWYeW`-G(@Vma`- z9nroX0lht+`WB-R%O1V#3An!gEQUI#wUi9Es)|1|K54X>XAJVBWF0O8=U=F;u{}oY zjzjp`(nA+2vfsty1D@pfao9b}rA$s}jIABAm=aIQB23!yOttWzXO4m%h)mCAlvBOll%nsuxwkq5K*6O{i{) z6xRm|_gCFlu>;TxDOi}-%#nApL0lAz(8eyFL*)>$w!7pva#R3P3|YUn25@5_*fICm z+5{J_i5?mc{sfMvKT(sq_9A34V7JMQM%;y)hP&5lDhR@(IgqcsiAYc&EgVadRn@4g z79=~zvsH}H-o}{+cd*W7jNc90ut*BEvS0RQ#n7a-!Gv{km!{RIi-&*L*iPMAB;hv*zKus{vsnktKx>yc&vC!GvLi{#Y z!2QVm{N>7Hm?qiWzDQO|FS(L29niQS0i#dGlH|M{jWp_p5Bu%SU6RYTx__>gQwKXq zXzm5lVDly$=S_V5@(_17Z}Mw?#(eS|>R^-% zagq%E?AC%>xkr;HEJz=enD{xkYPSnnC93}KUM|x}f>A_97D*Ns;>B30)L$>MnfN|b zbi3X?PlhdWnDqPWs#J~0rXGAIuf<`hO0gsV(UNHrX-K|WpN$BOU-Ko|tgY(XbE*@T z>8z5A0sV3U$L2tWdy6DjqkjE8vnEA*?!E4@*YEF=>gHNr5ade16HK^KwPX}j@2`k+ zWm3cW#J#;}-qRy%RN;+%t1DkB=ajL&P#6qiw?D@2c#-xyoES@nZ{z9dKAs=$HKuCQ zBdb%YZ=HrY`z`A?QB>}OdXMZs+|`aTI$Q*o!@VlBt$hx>_fB;&3xoE4l*DlrF;(2O zD289J3~^FqCR^7Pm+GA5->hiovs&r4Z!RwgOm4L^$!@A|4D@T*oj@%pII~@4-BjoV z$_o!3>ro6&V9ic6O{uv=RjtREjMa3C3t9MRrr&wyYpLe5OQ=KrC#xDn1g~ZIOdDkY z4JOG~g6pTTJ8jfU1p%NRtDYi(%UVGWuSzak$lFwB{$*VQE}cpYyx5;iI*jfKr? zmD`o4G@N)$$)?dx-tRl7I06X2Z@t~zh@a2B(Ze3Bi zg>~tmcVuBJd4w;p+hLOn;zWDU2k3U|F}#{~=_}J7c6LzrI_AECqyXd3r&F=+wV$&M z2DGoZF7#k4XDtkmD*1))prDzdOibpCiCXKL6;J2N?+C{flGPvj{aBp#L^`E$emM~K zlNg=edlPVL-dwz$9FsIkmSnaRm8$1zWwJUyd|wE<7JfHxrQ;h2*)tND1HzU%?K~>{ zEZXbot}As7%IdmvR?MoulgRB%Ug&`vHL|>GCA@vo>kZYD3(uPRF%JObn*DIt@6=MG z66ZVv7T?Ktoe@wcnYv!dDswg?vy7GMT(N?<249MiVJdompZYPW2FKdY@l?dgX0zZ( z^|&VqH(VpPMuqlBBH4T+S~l=0%A!^GQEwc6lM53IZuRoYb#_`CgqZkJg%1TyXFg;) zjD+dNmS;8wca0ND@gSe4|^&z2OY>Vhut|IzT!5u z(anJ%#iE!`Cb3*hV>+D2Wi*c?(|wE(;s#Z&iv&ej7>}?uy!J=zs^l?h&)K&cQm`*3JciXY(vul4j zkX8H{;xtz8GpLf1wr~*2$k~H-c5(~{K)Jh6SnT`Fngvfi?+EgsB@E=)W%!H&mj?4`8 zSs~6c*rpJ{$#WV?&vE=D6V<+m)GOMxzIna%r)q8RL74m8lGp|SdJ@K^clO#zt@EE3tR6;o$-KC4L#6Pu7n~kv{E^F^k$9CB>eFK#>AL10SB*F@DVtrspwTx z*g>8pg-y8OG14UkG8mhzwx%1YC>A6i9J3%m=gPKFh8m9+a+=&M?)&HYv+W32RJHf) z+zIsO_|h&QxQVdOm$sw4ppmIbn^B@y$pVQwmlwH7@B5R=bXLc*Gsj5Ekjg$*6)fhAal9wO}QaauuaB#!VFcl-Wz^mm8cC@%ylO z{Jb71doi#{lBKD$#nn=oH^)U0;v}XDG{-MT?PxoRI84X;DDIFM|2ZT8T0o`05PNB@ zYkfOYbvBn@9NVCY9mQS+azz#@KZ~r(j`ewt*Ho?gxx6NylaCz7s17~b4%V2q!>_Zf z`Fa`fz!|8l9TgD;5Nw9yvAs)0&Lc10ATF`x$d*P?q9^v_$B$s9vnUVG&CDK7f42rM z?RWsCx@d1-x9z|G@o!-eh@`gzEvVZDQpG~OZMkaeC1afy@i66aMCky)G$KeafCHw@ z5+hY(i>g2tLlj}S?i^3nUSAO+WW`8tv2hnSO7pJAh1&tenDt$6V_xaq#9XILd5igj@i>3 z<`zfD$5}c6CbMv*@|rU$fglfi1?>>W&=R1(`Op8Fv=ycAmvv-eozq>8Mj4*D7M6Fb z`B7aExe5eA5m-&9=u>mgdrQjv5U#M9u5&7!!Fslmp{LYtRWq{{;`l`5afcCXuLObb z+)IFgX?U$TM^K(YWdAOBxX_wTWj~=Z-SzR=%2jZdBrT4s8Dz}WZ8A2K(xBPSolB3Mr z!8l=)vi0#y%RAUeoTd{;%Q^?|fwVrDQZg!BqhuPfVp__a`bX5y6wrCROJk9W7+8PD zwwT_VC@_LZM_TK`HiPX1E=Qg`B zszf#fO=^@x8NE4Q+y2Nr?yZd(f6+M4tz8fBIh*N6Mj3De*%;_S$`$($WjN4!!nynT z@uU6m$B%YDpJW^$d}y22w$Vd$6t!sU<=XwS9NGE>3Nwvak`!bQxjG(4jgI1f+22x@ z{3xuF<#$J$T!b1~N7+qa#E^W|%;uvmd^*J1hp7QZ@8|bYT5h~7o$I-UETUEb@;$O& zGn9*;dhE&?OGN(M3(7}UKJp&$;9j${^|}D&4cY#X;aJeeAQg&bkDSm%s5MyX#vu)n z0}lc}@nUCmyTHkv6dmKxc`dW*=gWsm@MP;>0p7jRcb^1Ty#tKN1fBPpdb~NN1|TIT z0xWP5j!Wb{qjuJ0LCyi2c|~P+%6TE>6F8r>$6g2Lc9Dn+AU*>aDOszW2(>PV_d?K;IDy(b z&9$Q5aFlu_q9Gd0t`Mfesm6Z@nhtF|y0irW?D^JC_e1;FfB!>4#ozwNw|0fEe$Cj> z(QOM5*(zOoO_)F@#G5>{V=|w)nFv>lna-E}uPFrr`I%*UX|Z8=0l_U8$qmX=925zN zrgx;&=!8K+9lK9Cq7;+Sxo3Ge%GeLnB$08cWM4>no^8N&*h#q*duBB~oqCvly^nP+hK=+HBu@5lL2;mdP*Li5+4 z(DoqE-my<_g*eByWfrZJ2;vwqRw*VK?#zS1zR+hhX2uz-JW0rDHl_v3NaLZ6NiJ_q z)s@2$r8I&757A5-||#WFo6gTQ1O# zb}!An5G!F}T#oE4^~~n&I$5*}4xR!j%q{kaN&ac~T zn?`RkH;VcaY9~07wpMVbrA*01)4pB|QpiX-MsyP03OI;4Mn4_}UDR)EGl6Wzr39ny z5&Xs(Y?NyR$xD`XPKQo7A!8cZYjSbd@{Tg#OQNJ>{#9feIEoO?NI)AL#}|yQokZ$a zOLRkQZryp?fS82GT*-F6Y|eD}GV(zW%6z{h{$liLI%n+1PAH9;x#91UR@B&AfLewb z_b3lOIDc&*gW@_M(8uTvgMs!e{Am2)V>lipgIL8$cpcz7T1@}`_aE(l|6l*7ef#aV zc0_#R?sW z;|8^(1ZzC6Pf62lcCM8f%P4Pay&M7O-P?MRq&ye(rvZo2e){sdZO8qmKzc9RO$BfpHtqe#cNt2LX}Q9YYbW;`OFQX1)w2z-jJ_fLo$cT2JvPXQ%mFVX5q zS?1$ZgxZS5h8YVLG{^Ums$4pEM1>f^)E;+hf%cNCgv|Am1+piYlcb$X_RlElyzNd0 zmC)}C({!&F&ZfbO5JqTi-S988s1IRH=dJhV^|it|#xI?gtnTz23nMYhZBnoU2H_0w4?)P1pA3y@|pb*pZOy zwyifHC1Cyl1QhL>_3M&IQu?DZ4vs#O6eAIRsYb=c z<|aYqhZ84LAE~4R`j}wu-d@PWQOF5$7cL^C6fka40g%IvnLi^NACc*`@0$iMjlcRs zjLMbgTj(UC*{*ulk)sKgGLeQ9%Zgkii#In#9VHuHS5VsA@RRiUDht*l-*#^PTqu3B z10Z4ga@?+L1{_2oQ;6#Q8m)Ksw-xZq2Vmv_se+piMcx zL#T2Mn$x9t-Dvm7GbHhaF0R)tzxu}o+=br>B%YnHIz?JO8%sqETB`MAS z`}<$*fB)bAr%evb$j`K?0C19-1E!O)yj%s8qNn!y`YOgX24m?VgG%4P@I9*)oUl<58G3tCnfBPbYu(1(b zBOJ#4j^Y|a9wSw%?3`ly0X8a8O$QT|kiW?yW{TfBO)&(RnSI2py+l1F)IcFrY+#y2?jj*pthgt%Fi0` zQDp(>CW;4BEoaLvt7^ljRRn4SvCPwcA1Z)h64F-W8hV<nIwv%+ED#PP2Q^A%c|=0eao@k+#4eW*%pw=N=&}bP+^I&VJd3* z+Uc1=cnAs9Tb{S^Y}IC~ZJVs#+60Hb+_oF4TFS(Xs-xdX^mn|C+DWKEX8t(PYr6yM zr`(|xZ=#To{i(g5u5EWZ8-O67giC%z`~p=ne+>98$_u85y|oDhG?XIGp#IDh$KQ!^ zFp2^ONjH`f%027yeRn?`^%9_R=a$AaVW$Yu0r0_lhmaj*MlsmCl;TaBnH zKXr#UaK1kQG|Vw6u2QV_QtTAz*5gk*~dfLDwI2vEn;ly|a zTIRDyN?3TSMd=twR?g3SAl60BaEfb0kGpPyJoj3eSVRUBCQ}0wbs7QGxB{A}oRASh z#2`$F2y5ob%14t^8y^qm)t=AW_U%<|9gna9IPs*zaz)>HAz4(O$7ivr_v5CF9r7iR zv1bJ!z50NI6;4I1g}Z0hne|p>361lkoVj}Hchuw%i(nocB8`KKAhV3?+`YP+Uas?U%$R-`r*F3 zw%anMGsG2Tf+bDRFh5MNfX!hl2OB^#F^mV9V1~>+fkz5_0d$3otDP`oof!1JFd9Z3 zyBd%{Sp@}DCZhD3ta+KWitLv5K+2;=P@%C~miYr${9`N5RWt7u(R5YCzZ}0UGxXKo z*v51Lncnt$Bz{TzlG&ctVD!vYVWYLD>P+HWLZvp&-PiO@CWA=fdh8c zS$8eh_pc1pHQA)&^;Z&}^~$No40Z2BEiUwy+Eb$&l`Nb!p6J?ERNyA#w)>zG^sY6D zjUDhr8g7me#xeA*hc?lOtg8n}Jv zSM8u?u23l^BmsnUyU3w`?9M?nf7j+dk$EUwjh@$Z-cI7#owX~JeMH12v{v@6SWxIo z8-Mo#JbNp0i<0g7#=`~&vlv;>StRw18*!V7S{4dTZsyx+CB*F4mu-95Y?UbijsxvZ znMnOi;T|40mWApo=kp_)cgR$R#rAU+9si36*N&!d;=(8wH$@qS%8AaR&GHVFDp3`964Dy<#xXFxpPrX`rHXP&*wg6fb^w; z7Xrgc20iX2tBRy7Swpl6uyhk}GPGyZAH$K;5;B9F39~{QTUog|yy107@J%Xb&1NUH znKsbdszeU`u^kx(@3>gB4^kOQfK&Gi{qaU6Y(fDjq42fVis*jU)J%{Zd(BmX7W+{EZC{)}-Q~`ybSwr3Hf=OpHS}GMR{%^XrFx75Bsv*7q&Dw|qv=v5KdL>`PDCStylxZEvZ}{E zg&H&DPBqp8DGSC;WY$(Q3k_bBD=-eQNDZ4LP^ANlU65>GkO0A4w3*>HH$lnEcH1@x zX>7LbWo_>61Q4-FQK&N6y)*N4ym@i!27E5}4i0e`Z;Oqa$o43;@%O=z%dmt5Amzge z^R`A}Y93VvA6Z08K~-n?{55Qx+-zjdH@-~63a2^Z5)YaAZK{YoX*}lH&zAQIu zW$ZZgBt2nc;E1q=AfdS;5=a^3I62Z2j0e)7XYHe|^X&fw>pyhI{ z2`wR_(Cp5P&|Ln^xF(o#)NcGNN5oj(tgWt#HaSDQVIrf&6$d%j-uT=Zc=v#2E>f0u zT91Y|`<&7XjG1?#$T==HFMI)`dpk&d>LMO(Wq8bc(|;78*0bRal^1n_m+EwxaFu|T1#yKzLQ zH8J|pjyneht6??WCNN@UXAx-l;GjqltEO*st)Jyf30!V%iDG6txI((4y&9};=}@vF z;K0JpTA;J15j8z8s*}TY9k4f@P3;CJIa&=N%2SWe(#kX4BfmauvTUPiZTWGLwoA#t zt=(zAT`ukOeb@f_{)aGE1eXc|Gr-U^6O4s!LFCAnkPnP9u9ns!KOdyfI1aL#bj(!} z7X1xn?katEY3mFGYOq&Fiu3+4yG~_U!GmyHo!6h|VP|SZlKipGqnkF}Hd`!qqvhAO zKzVBOrfgan3~|_Wr3@Y9 zat*-&rN;wv0gE!E{|Wa4P}Oo)G4DulPOVVjJ2U6gnAg)HsbpsAbBd! z4Sm1tnMT=6AT|m+@%QWjxysN>{m+iQ_KtEv*WQs3t{T6fd>csi0Kw%w$)A4}$T%o@ zMD>#q<#RCdtWWm`<9>+U&ZBE&W(0A6eZ039#7;Krw%oq7)Bp2d!fGrRD+%^|{rXh_ z>#%7e!yyAc9wL}PC62uTam|8^*<+L#d_ZngLICK}MzLIHP>_m=%8tULG7|gMMn!z) zOpiOoe}aBAx!zGullmaR+`ym}4vAiGP~6gPB8w5pQ=ps$+Bsd?4}zCitGZ{w=k090 z2e8S+mmsY)Kw>(KIb+c;V{F84Pql#SVZfb^P2PwqU#OjdSD0ro=}|*v#SMi-@3mxP zGs#Ajl(Tmm^tTeSfTv&F{s(v<-C+R4tgakvPJ8 z8?ds@)qvS+!PSvu`x4mlk;!Ah=aa0kcdA1kKiC|a^t~sZPQKd5tSr{-`v%}@V>!c#$7rK;-I=hR@ zox;6(9t#^p`sCY}*S2}tnl|+Ht-WqvHIpuspvs!`_bn7rop%KQ)gDh?v|46*cKVMu zBVPBwvh<$la2c`a>oGAf4uS-YpXehY^)LZL3b8WD z;9gi~R3L?_l9PN(cL9b_5ZIZ!RpqKi`A01&)|cug5ytHDPdSLs1e1OZVFOul+$ zebG-7H$o80v=lzUFwwUT4(u8zWPp=II`!VDybr%KoXbKZgN5dr1FBo9gvV>x&~IOV zYp-9wh<27uN?`c)%WrKW1~D^8Wpx5$f4xlG`QVLP%cp#{5WK1kIJq0nKR6@B&#l?* zDDP$#1L2X@=BV9H?!W3>CP`iD?8H3P)}&Ef!AD~#uv zBnR152suu|jIa`ilDp`KPga;a9u%mgkrGdY=A@@;yYWmyKY}yePXYZ-9x+uLE&^qO zXvyo2#bHDLo6Ifu0gE`tdr||Mb$yPp(ICASxCx#C-gnnNJSqoUq|^dq9T6|Z#0zVe z<0t#Wp>uq8@NO5>iW?Q9L@p~3jf&L(x(qe3YKUto9*3s24QGL}`Pc(tD^Nevejet+ z3vH~D9Xo2OAKp6w%pFD}eSBg!jIp$I41TZNw;q22_{qKPLPmXRr|!?p!n@P$!Gb@d ze~$K6Npc=&PQzBQ$1;=D>w-c%-|x9akpX93hxvT%|7ZIoF*U-w0GbV3B%z+M_9Uiu zy;!xseWQ)L69)tSh1S@KNvoR!c>>A_LHU{WO=fTV>A=avX?c8V4O8iniKJ>3{wQ0K zQS#0$$d`|Q_2C4@N*_*FHXZ2O*;6LHsT7h!;rJXc>wrs2Mrp+j|6R~_A z+K=5{y__GrL;LZ0XuE@{@l>{3OeI>80v(?_F494pd9k46PEnG{F9ShcO@ z3He&8yul`Qt8d58M0P87QGE#Cy88OC8f)quL%En5^2+zWF z+W!3W&$imU2qgE{kB_!LA2hbNeOb39dg^fuB5;WHhqGb)P1)3ovtpHfCzm#dkr0Px z$e}ZBGCvdt8JVHKM(-1cE9E?|<21BGOGWD;`1b{zWb6rJWKa#u=6biNNku^OT1mvJ zHQ>>jh0xwp&4Fu{ezj`5H3Aci+05G?3nTyl03ZNKL_t(;hlY1J423%5hy9t_?7mNc zLQ4-dj!$?RS|{4Ch-H8gAd^N#?b4<&P~s4A{`-UER7Ik~&*DHotCFTJl=`WG+qg{H zbsXsU7^zEHR*dTnbbPGE#F9`+%!jCJS<3=6d5wtzw-A45eGY;;evX5%$KX^t3shXr zNE#DF@;g^RoXPiz7~wjkI~&zKN%l_vgF_1kTC%y!Y;h=zQnk@uY2gXUxQORgv1X33PdD2`5b>fNhI$e$i!6Nk894I4$4Y1J34**;AN)8GH zOatr+Q3iOzg#7|zk&Zsq+OiE<%k?A+nH1$?`r|ZHV}CT;wom9>j^lQ^-`e3iYoG1f zj`SmL!t+vnk^jZI(9**2LZGLx$|-XGMjIDP-Fzh`73wBlg0nSD&EWR%wLNTb4IjiQmGX`DHW`gjN}?m3jRM)|RDHxNtA=50BhwKZk;vB7a0 z)RY2n#YF-9#PM;17W5$lAsE;TD-dbU+$B340^b3^Xsn6Z(K9rIM=3RF0jjiS9cZ#j zwjlh_D#zqFm;i4c!GS}5p?+i2_)%s&j7!jRQ(GYB6d9KSn4}e<(s#)HjpyxcJ8tjq zFH9pqu%I0u z5O4TzUteNkAUM@$v-bJdhqw|orwqUIZRL?Bs6!j#G6#bag8(8cBPy?_RDs4UjRv2R zwMl*zBzI&y!9|b?FIl(Id&*f+C9njmaU3bjIM!$#(-X?5BdfNPnQMFv9_rt|zWJWR zKfw6TY}$5*vpCXWIYVn)<$pq7Nj*?WG5sZEm~!B(@d)T>*J;#E#)cs3q&ArHd}fW2 zzzXMx6DD|{Ie2=&siWYMkgF*oaHoC6{WMQQR@ySird>qFDWX4B#9ZcH9^?y;K-g_j~;Bg3A1&t(lP!OhrlCx%=azB@= zm%%ZBH8RQ@yJ;KVsYENkM542wZ0X=+qw?fd)nex1TP}fRHG(>;^noq8wbC!HbDV6WK?_)tWa&qVVXR2;};jA>=cHi=2gdreA++bAf+s zOxN?7vhvsU*4g>o&fJj~n^f|}$)hKWxAiY~*bh)R^Y&RR1Q$Qkg;o;DaIEpAQB>Xr@83Q$*~!2M zh%TeZ3V4%IM@_7N2pzgQK*-W!jsEj<@@ts04^%Ms@^U0t@EA&xM4Mr*GkX!ky9ebj zuom>n?~|D-Cm4yp{ja~vDFQr#?^}Q^VL5QD7%7kZktsl5%wpm==HrD~*CeFk44fXj zknPeMj}}p`uh6e{&oXchA-C#jf-IxjnP=v5zmD2Tv*VF1F*iQUiTkV#w81$Ldbm=; z>p8D4Z*T2me+b4r2w2G280AAqi8AG_{rK30BPg@zk?m^zD%ka%V^pt~6P-z`{4IBm z!Gib%jeAdHsKP<7QYF>WCJ6^9$B-mcalKM&!ifKn>txL-W;qWt!8lq6e0ENn-KT;S z%#g!)sxTLB>(nZnN6=b99d{(o}_%^N$_Qo}> z*sG`w2C-JHv?PW1h0L7sYHUn+M;Om$p@F8%iHo35Y7P=Z109*S?Q!7}TgghC+Lr|Xp>eq~(Q z+or5X1RlU62LTFeguG6yL~?S}K3mQbJ3@Dr#=7(-pm7Bx)$0J?^^&uCd-F+~-Ca68 zgkz$u@Eh~ApF0Ivpxq^9tdQZ{?&Fhi2cLTfWa91@k9G*qL^i4xLx8-D#tvsDoJ#2} z$MFrUTB<-LnTlBt+^e?3Hrdq8OoH0~7iI2BDn*5C=SRYzd1``@09yLO#kC6wVoA~l z=XrNbL13Z_m7Ek&f{z~hHOD+tR7r1UkHl${CF4-&6?1O~42232qjrc4Z*agxDNVLd z0$Wshtkk9|8x;nP*r8d#`Qv?)>zqD67b3`FB#u&rluS1C=#Z0k*<-)PnRKU6%edV} z`gb)*siooC_pgCo{rxkhrat=m?ms`+xj?