From d6ef4386a7c750985f03da9ef387e858b987963c Mon Sep 17 00:00:00 2001 From: spf Date: Mon, 4 Aug 2025 14:08:43 +0800 Subject: [PATCH 01/11] =?UTF-8?q?doc:=20=E5=AE=8C=E5=96=84=E8=AE=BE?= =?UTF-8?q?=E8=AE=A1=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/design-doc.md | 522 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 522 insertions(+) create mode 100644 docs/design-doc.md diff --git a/docs/design-doc.md b/docs/design-doc.md new file mode 100644 index 0000000..f85869b --- /dev/null +++ b/docs/design-doc.md @@ -0,0 +1,522 @@ + +# CodeAgent 产品设计文档 + +## 1. 产品概述 + +### 1.1 CodeAgent 是什么 + +CodeAgent 是一个基于 AI 的代码代理系统,专门为 GitHub 开发流程设计。它能够: + +- **自动处理 GitHub Issue 和 Pull Request**:通过 Webhook 监听 GitHub 事件,自动响应开发者的指令 +- **智能代码生成和修改**:利用 AI 模型(Claude、Gemini)理解需求并生成代码 +- **无缝集成开发流程**:直接在 GitHub 界面中通过评论触发,无需切换工具 +- **基于 Git Worktree 的工作空间管理**:为每个任务创建独立的工作环境,确保代码隔离 + +### 1.2 工作机制 + +CodeAgent 的工作机制如下: + +1. **事件监听**:通过 GitHub Webhook 监听 Issue 评论、PR 评论等事件 +2. **命令解析**:解析评论中的特定命令(如 `/code`、`/continue`、`/fix`) +3. **工作空间创建**:基于 Git Worktree 为每个任务创建独立的工作环境 +4. **AI 处理**:调用 AI 模型(Claude/Gemini)理解需求并生成代码 +5. **代码提交**:自动将生成的代码提交到 Git 仓库并创建/更新 PR +6. **结果反馈**:在 GitHub 界面中展示处理结果 + +**核心流程示例**: +``` +开发者评论 "/code 实现用户登录功能" +→ CodeAgent 创建独立工作空间 +→ 调用 AI 生成代码 +→ 自动提交到新分支 +→ 创建 PR 并展示结果 +``` + +### 1.3 当前功能 + +- 支持 Claude 和 Gemini 两种 AI 模型 +- 基于 Git Worktree 的工作空间管理 +- GitHub Webhook 集成和签名验证 +- Docker 容器化执行环境 +- 自动代码生成和 PR 创建 +- 支持 `/code`、`/continue`、`/fix` 等命令 +- 历史评论上下文理解 +- 自动清理过期工作空间 + +## 2. 竞品分析 + +### 2.1 与 Claude Code 和 Gemini-Cli 的横向对比 + +| 功能特性 | CodeAgent | Claude Code | Gemini-Cli | +|---------|-----------|-------------|------------| +| **集成方式** | GitHub Webhook | 本地 CLI | 本地 CLI | +| **工作空间管理** | Git Worktree | 本地目录 | 本地目录 | +| **多模型支持** | Claude + Gemini | 仅 Claude | 仅 Gemini | +| **自动化程度** | 全自动 | 半自动 | 半自动 | +| **成本控制** | 计划支持 | 无 | 无 | +| **负载均衡** | 计划支持 | 无 | 无 | +| **API 接口** | 计划支持 | 无 | 无 | +| **监控统计** | 计划支持 | 无 | 无 | +| **团队协作** | GitHub 集成 | 本地使用 | 本地使用 | +| **部署复杂度** | 中等 | 简单 | 简单 | + +**CodeAgent 优势**: +- **团队协作友好**:直接集成 GitHub,支持团队协作 +- **自动化程度高**:从代码生成到 PR 创建全自动 +- **扩展性强**:支持多模型、负载均衡、成本控制等高级功能 + +**CodeAgent 劣势**: +- **部署复杂度**:需要配置 Webhook 和服务器 +- **学习成本**:需要了解 GitHub 集成流程 +- **依赖外部服务**:需要 GitHub 和 AI 服务商 + +### 2.2 AI 智能网关竞品分析 + +#### 2.2.1 CC Replay (Claude Code Router) + +**产品定位**:基于 Claude Code 的路由器,支持多模型切换和负载均衡 + +**核心功能**: +- 多 Claude 账号管理 +- 智能路由和负载均衡 +- 成本控制和用量统计 +- 故障自动切换 + +**与 CodeAgent 对比**: +- **相似点**:都支持多账号管理和负载均衡 +- **差异点**:CC Replay 专注于 Claude,CodeAgent 支持多模型 +- **优势**:CC Replay 更专注于单一模型优化 +- **劣势**:缺乏 GitHub 集成和团队协作功能 + +#### 2.2.2 Qiniu AIGC API + +**产品定位**:七牛云提供的统一 AI 服务 API 网关 + +**核心功能**: +- 多 AI 模型统一接口 +- 智能路由和负载均衡 +- 成本控制和用量统计 +- 高可用和故障转移 + +**与 CodeAgent 对比**: +- **相似点**:都提供统一的 AI 服务接口 +- **差异点**:Qiniu AIGC 是通用 API 网关,CodeAgent 专注于代码生成 +- **优势**:Qiniu AIGC 更通用,支持更多 AI 模型 +- **劣势**:缺乏 GitHub 集成和代码生成优化 + +#### 2.2.3 Claude Router + +**产品定位**:开源的 Claude API 路由和负载均衡工具 + +**核心功能**: +- Claude API 路由 +- 多账号负载均衡 +- 简单的成本控制 +- 故障切换 + +**与 CodeAgent 对比**: +- **相似点**:都支持多账号管理和负载均衡 +- **差异点**:Claude Router 更轻量,专注于路由功能 +- **优势**:Claude Router 更简单易用 +- **劣势**:功能相对简单,缺乏高级特性 + +### 2.3 市场定位分析 + +**CodeAgent 的差异化优势**: + +1. **GitHub 原生集成**:唯一深度集成 GitHub 的 AI 代码代理 +2. **团队协作导向**:支持团队协作和代码审查流程 +3. **全流程自动化**:从需求到代码到 PR 的全自动流程 +4. **多模型智能选择**:支持多种 AI 模型并智能选择最优方案 + +**目标用户群体**: +- **开发团队**:需要 AI 辅助代码生成的团队 +- **开源项目**:需要自动化代码贡献的项目 +- **企业开发**:需要标准化 AI 代码生成流程的企业 + +## 3. 当前问题分析 + +### 3.1 技术架构问题 + +1. **AI 模型支持有限**: + - 仅支持 Claude 和 Gemini + - 缺乏对新 AI 模型的快速接入能力 + - 没有统一的模型接口标准 + +2. **成本控制不足**: + - 无法根据任务类型智能选择最经济的 AI 模型 + - 缺乏用量统计和成本分析 + - 没有预算控制机制 + +3. **账号管理简单**: + - 仅支持单一账号配置 + - 缺乏多账号池管理 + - 没有账号状态监控和故障转移 + +4. **API 接口缺失**: + - 仅支持 GitHub Webhook 触发 + - 缺乏标准化的 API 接口 + - 无法被其他系统集成 + +5. **Workflow 流程固化**: + - 当前 prompt 和流程写死在代码中 + - 缺乏灵活的工作流配置 + - 无法根据项目需求定制流程 + +### 3.2 业务功能问题 + +1. **任务分类不智能**: + - 无法区分编码任务和非编码任务 + - 缺乏针对不同任务类型的优化策略 + - 没有成本效益分析 + +2. **负载均衡缺失**: + - 无法在多个 AI 模型间智能分配任务 + - 缺乏基于用量和成本的负载均衡 + - 没有故障自动切换机制 + +3. **监控运维不足**: + - 缺乏详细的用量统计 + - 没有成本监控和告警 + - 缺乏性能指标监控 + +## 4. 产品目标 + +### 4.1 总体目标 + +将 CodeAgent 从一个简单的 GitHub 代码代理,扩展为一个功能完整的 AI 服务代理平台,为开发者提供统一的、智能的、成本优化的 AI 服务接口。 + +### 4.2 具体目标 + +#### 目标 1:支持 Classfile 编码 +**背景**:当前 CodeAgent 仅支持通用语言的代码生成,缺乏Classfile DSL的支持。 + +**目标**:扩展 AI 模型支持,增加对 Classfile 等特殊格式的编码能力。 + +**实现思路**: +- 设计统一的编码接口,支持多种文件格式 +- 为不同 AI 模型实现编码适配器 +- 提供编码格式转换和验证功能 + +#### 目标 2:融合 CLI 支持 +**背景**:当前所有任务都使用相同的 AI 模型,无法根据任务类型和成本要求进行优化。 + +**目标**:智能选择最适合的 CLI 工具来处理不同类型的任务,优化成本和性能。 + +**实现思路**: +- 建立任务分类体系(编码任务 vs 非编码任务) +- 设计 CLI 选择算法,考虑成本、性能、质量等因素 +- 实现动态 CLI 切换和故障转移 + +#### 目标 3:多渠道账号池管理 +**背景**:当前仅支持单一账号配置,缺乏多账号管理和故障转移能力。 + +**目标**:统一管理多个 AI 服务商的账号,包括账号状态监控、用量统计、负载均衡等功能。 + +**实现思路**: +- 设计账号池管理架构,支持多服务商、多账号 +- 实现账号状态监控和自动故障转移 +- 提供账号用量统计和成本分析 + +#### 目标 4:账号池账号的 AccessToken 有效性维持 +**背景**:AI 服务商的 AccessToken 会过期,需要手动更新,影响服务可用性。 + +**目标**:自动监控和刷新 AccessToken,确保服务持续可用。 + +**实现思路**: +- 实现 Token 有效性检测机制 +- 设计自动刷新流程 +- 提供 Token 轮换和备份策略 + +#### 目标 5:账号池账号状态/用量查询 +**背景**:缺乏对账号状态和用量的实时监控,无法及时发现问题和优化使用。 + +**目标**:实时监控账号状态和用量,提供详细的统计和分析。 + +**实现思路**: +- 设计监控指标体系 +- 实现实时状态查询和用量统计 +- 提供可视化监控界面 + +#### 目标 6:对外提供 OpenAI 范式 API +**背景**:当前仅支持 GitHub Webhook 触发,无法被其他系统集成。 + +**目标**:提供标准化的 OpenAI 兼容 API 接口,支持 API Key 认证、QPS 限制、用量统计等功能。 + +**实现思路**: +- 设计 OpenAI 兼容的 API 接口 +- 实现 API Key 管理和认证 +- 提供 QPS 限制和用量统计 + +#### 目标 7:API 提供 QPS 限制,用量,费用预估 +**背景**:缺乏对 API 使用的限制和成本控制。 + +**目标**:为 API 提供完整的限制、监控和成本控制功能。 + +**实现思路**: +- 设计 QPS 限制和配额管理 +- 实现实时用量统计和费用预估 +- 提供成本告警和预算控制 + +#### 目标 8:转发 API 请求时,负载均衡账号用量 +**背景**:无法在多个账号间智能分配请求,可能导致某些账号过载而其他账号闲置。 + +**目标**:基于账号用量、成本、性能等因素进行智能负载均衡,确保资源的最优利用。 + +**实现思路**: +- 设计负载均衡算法,考虑用量、成本、性能等因素 +- 实现动态负载分配和故障转移 +- 提供负载均衡策略配置 + +#### 目标 9:Workflow 流程引擎 +**背景**:当前 prompt 和流程写死在代码中,缺乏灵活性,无法根据项目需求定制。 + +**目标**:设计可配置的工作流引擎,支持自定义 prompt 和流程。 + +**实现思路**: +- 设计 Workflow 配置格式,支持 YAML/JSON 配置 +- 实现可插拔的 prompt 模板系统 +- 支持条件分支和循环流程 +- 提供 Workflow 版本管理和回滚功能 + +## 5. 最终交付产品 + +### 5.1 产品形态 + +CodeAgent 将从一个 GitHub 代码代理,扩展为一个完整的 AI 服务代理平台,包含以下核心组件: + +1. **AI 服务网关**:统一的 API 入口,支持多种 AI 模型 +2. **账号池管理系统**:多账号、多服务商的统一管理 +3. **智能负载均衡器**:基于成本、性能、用量的智能分配 +4. **监控分析平台**:用量统计、成本分析、性能监控 +5. **Workflow 引擎**:可配置的工作流系统 +6. **GitHub 集成模块**:保持原有的 GitHub 集成能力 + +### 5.2 核心功能 + +#### 5.2.1 统一 AI 服务接口 +- **OpenAI 兼容 API**:提供标准的 OpenAI 格式 API +- **多模型支持**:支持 Claude、Gemini 等多种 AI 模型 +- **智能路由**:根据任务类型和成本要求智能选择模型 + +#### 5.2.2 智能账号管理 +- **多账号池**:支持多个 AI 服务商的账号管理 +- **自动故障转移**:账号故障时自动切换到备用账号 +- **Token 自动刷新**:自动监控和刷新过期的 AccessToken + +#### 5.2.3 成本优化系统 +- **智能 CLI 选择**:根据任务类型选择最经济的 AI 模型 +- **成本监控**:实时监控用量和成本 +- **预算控制**:设置预算限制和告警 + +#### 5.2.4 负载均衡系统 +- **多维度负载均衡**:基于用量、成本、性能的智能分配 +- **动态调整**:根据实时情况动态调整负载分配 +- **故障恢复**:自动检测故障并恢复服务 + +#### 5.2.5 监控分析平台 +- **实时监控**:API 调用量、响应时间、错误率等指标 +- **成本分析**:详细的成本统计和分析报告 +- **性能优化**:基于监控数据的性能优化建议 + +#### 5.2.6 Workflow 引擎 +- **可配置流程**:支持 YAML/JSON 配置工作流 +- **模板系统**:可插拔的 prompt 模板 +- **条件分支**:支持复杂的条件判断和分支流程 +- **版本管理**:Workflow 版本控制和回滚功能 + +### 5.3 技术架构 + +``` +┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ +│ 客户端应用 │ │ CodeAgent │ │ AI 服务商 │ +│ (GitHub/API) │───▶│ 网关平台 │───▶│ (Claude/Gemini)│ +└─────────────────┘ └─────────────────┘ └─────────────────┘ + │ + ▼ + ┌─────────────────┐ + │ 账号池管理 │ + │ 负载均衡 │ + └─────────────────┘ + │ + ▼ + ┌─────────────────┐ + │ Workflow 引擎 │ + │ 流程管理 │ + └─────────────────┘ +``` + +### 5.4 用户价值 + +1. **降低 AI 使用成本**:通过智能选择和负载均衡,显著降低 AI 服务使用成本 +2. **提高开发效率**:统一的 API 接口,简化 AI 服务集成 +3. **增强系统可靠性**:多账号管理和故障转移,提高服务可用性 +4. **优化资源利用**:智能负载均衡,最大化资源利用效率 +5. **保持开发体验**:继续支持 GitHub 集成,保持原有的开发体验 +6. **灵活定制能力**:Workflow 引擎支持根据项目需求定制流程 + +## 6. Workflow 设计 + +### 6.1 当前流程分析 + +CodeAgent 目前有以下固定的流程: + +1. **Issue 处理流程**: + - 解析 `/code` 命令 + - 创建工作空间 + - 生成代码 + - 创建 PR + - 更新 PR Body + +2. **PR 继续流程**: + - 解析 `/continue` 命令 + - 获取历史上下文 + - 继续开发 + - 提交代码 + - 添加评论 + +3. **PR 修复流程**: + - 解析 `/fix` 命令 + - 分析问题 + - 修复代码 + - 提交修复 + - 添加评论 + +### 6.2 Workflow 引擎设计 + +#### 6.2.1 配置格式 + +```yaml +workflows: + issue_processing: + triggers: + - type: "github_issue_comment" + command: "/code" + steps: + - name: "parse_issue" + type: "prompt" + template: "issue_analysis" + output: "issue_analysis" + + - name: "generate_code" + type: "prompt" + template: "code_generation" + input: "issue_analysis" + output: "generated_code" + + - name: "create_pr" + type: "github_action" + action: "create_pull_request" + input: "generated_code" + + - name: "update_pr_body" + type: "github_action" + action: "update_pr_body" + input: "generated_code" + + pr_continue: + triggers: + - type: "github_pr_comment" + command: "/continue" + steps: + - name: "get_context" + type: "github_action" + action: "get_pr_context" + output: "pr_context" + + - name: "continue_development" + type: "prompt" + template: "continue_development" + input: "pr_context" + output: "continued_code" + + - name: "commit_changes" + type: "github_action" + action: "commit_and_push" + input: "continued_code" +``` + +#### 6.2.2 Prompt 模板系统 + +```yaml +templates: + issue_analysis: + content: | + 分析以下 Issue 并制定实现计划: + + Issue 标题:{{.issue.title}} + Issue 描述:{{.issue.body}} + + 请提供: + 1. 实现方案 + 2. 需要修改的文件 + 3. 技术要点 + model: "claude" + temperature: 0.7 + + code_generation: + content: | + 根据以下分析生成代码: + + 分析结果:{{.issue_analysis}} + + 要求: + 1. 生成完整的代码实现 + 2. 包含必要的测试 + 3. 遵循项目代码规范 + model: "claude" + temperature: 0.3 + + continue_development: + content: | + 基于以下上下文继续开发: + + PR 描述:{{.pr_context.body}} + 历史评论:{{.pr_context.comments}} + 当前指令:{{.args}} + + 请根据指令继续开发,保持代码一致性。 + model: "gemini" + temperature: 0.5 +``` + +#### 6.2.3 条件分支支持 + +```yaml +workflows: + smart_code_generation: + triggers: + - type: "github_issue_comment" + command: "/code" + steps: + - name: "analyze_task" + type: "prompt" + template: "task_analysis" + output: "task_type" + + - name: "select_model" + type: "condition" + condition: "task_type == 'complex'" + true: + - name: "generate_with_claude" + type: "prompt" + template: "complex_code_generation" + model: "claude" + false: + - name: "generate_with_gemini" + type: "prompt" + template: "simple_code_generation" + model: "gemini" +``` + +### 6.3 Workflow 优势 + +1. **灵活性**:支持自定义流程和 prompt +2. **可扩展性**:易于添加新的步骤和模板 +3. **可维护性**:配置与代码分离,便于维护 +4. **可测试性**:每个步骤可以独立测试 +5. **版本控制**:支持 Workflow 版本管理和回滚 + +通过 Workflow 引擎,CodeAgent 将从一个固定的代码生成工具,转变为可配置的、灵活的 AI 开发助手,能够根据不同的项目需求和团队偏好进行定制。 + + From e4a2f9226604c64581570f0783d6ab75ede57a0b Mon Sep 17 00:00:00 2001 From: spf Date: Mon, 4 Aug 2025 14:10:53 +0800 Subject: [PATCH 02/11] =?UTF-8?q?doc:=20=E5=AE=8C=E5=96=84=E8=AE=BE?= =?UTF-8?q?=E8=AE=A1=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/design-doc.md | 128 +-------------------------------------------- 1 file changed, 1 insertion(+), 127 deletions(-) diff --git a/docs/design-doc.md b/docs/design-doc.md index f85869b..382e9f9 100644 --- a/docs/design-doc.md +++ b/docs/design-doc.md @@ -382,134 +382,8 @@ CodeAgent 目前有以下固定的流程: - 提交修复 - 添加评论 -### 6.2 Workflow 引擎设计 - -#### 6.2.1 配置格式 - -```yaml -workflows: - issue_processing: - triggers: - - type: "github_issue_comment" - command: "/code" - steps: - - name: "parse_issue" - type: "prompt" - template: "issue_analysis" - output: "issue_analysis" - - - name: "generate_code" - type: "prompt" - template: "code_generation" - input: "issue_analysis" - output: "generated_code" - - - name: "create_pr" - type: "github_action" - action: "create_pull_request" - input: "generated_code" - - - name: "update_pr_body" - type: "github_action" - action: "update_pr_body" - input: "generated_code" - - pr_continue: - triggers: - - type: "github_pr_comment" - command: "/continue" - steps: - - name: "get_context" - type: "github_action" - action: "get_pr_context" - output: "pr_context" - - - name: "continue_development" - type: "prompt" - template: "continue_development" - input: "pr_context" - output: "continued_code" - - - name: "commit_changes" - type: "github_action" - action: "commit_and_push" - input: "continued_code" -``` - -#### 6.2.2 Prompt 模板系统 - -```yaml -templates: - issue_analysis: - content: | - 分析以下 Issue 并制定实现计划: - - Issue 标题:{{.issue.title}} - Issue 描述:{{.issue.body}} - - 请提供: - 1. 实现方案 - 2. 需要修改的文件 - 3. 技术要点 - model: "claude" - temperature: 0.7 - - code_generation: - content: | - 根据以下分析生成代码: - - 分析结果:{{.issue_analysis}} - - 要求: - 1. 生成完整的代码实现 - 2. 包含必要的测试 - 3. 遵循项目代码规范 - model: "claude" - temperature: 0.3 - - continue_development: - content: | - 基于以下上下文继续开发: - - PR 描述:{{.pr_context.body}} - 历史评论:{{.pr_context.comments}} - 当前指令:{{.args}} - - 请根据指令继续开发,保持代码一致性。 - model: "gemini" - temperature: 0.5 -``` - -#### 6.2.3 条件分支支持 - -```yaml -workflows: - smart_code_generation: - triggers: - - type: "github_issue_comment" - command: "/code" - steps: - - name: "analyze_task" - type: "prompt" - template: "task_analysis" - output: "task_type" - - - name: "select_model" - type: "condition" - condition: "task_type == 'complex'" - true: - - name: "generate_with_claude" - type: "prompt" - template: "complex_code_generation" - model: "claude" - false: - - name: "generate_with_gemini" - type: "prompt" - template: "simple_code_generation" - model: "gemini" -``` -### 6.3 Workflow 优势 +### 6.2 Workflow 优势 1. **灵活性**:支持自定义流程和 prompt 2. **可扩展性**:易于添加新的步骤和模板 From 74989aff0592cc74dcc77dd9c4caa305d061e8cc Mon Sep 17 00:00:00 2001 From: spf Date: Mon, 4 Aug 2025 15:17:47 +0800 Subject: [PATCH 03/11] =?UTF-8?q?doc:=20=E4=BF=AE=E6=94=B9=E4=BA=86cc?= =?UTF-8?q?=E7=9A=84=E4=B8=80=E4=BA=9B=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/design-doc.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/design-doc.md b/docs/design-doc.md index 382e9f9..a258474 100644 --- a/docs/design-doc.md +++ b/docs/design-doc.md @@ -57,7 +57,7 @@ CodeAgent 的工作机制如下: | **负载均衡** | 计划支持 | 无 | 无 | | **API 接口** | 计划支持 | 无 | 无 | | **监控统计** | 计划支持 | 无 | 无 | -| **团队协作** | GitHub 集成 | 本地使用 | 本地使用 | +| **团队协作** | GitHub 集成 | GitHub 集成,但prompt黑盒 | 本地使用 | | **部署复杂度** | 中等 | 简单 | 简单 | **CodeAgent 优势**: @@ -383,6 +383,7 @@ CodeAgent 目前有以下固定的流程: - 添加评论 + ### 6.2 Workflow 优势 1. **灵活性**:支持自定义流程和 prompt From 7af8e82038af041996899d247aa1bc043695bd71 Mon Sep 17 00:00:00 2001 From: spf Date: Mon, 4 Aug 2025 15:49:00 +0800 Subject: [PATCH 04/11] =?UTF-8?q?doc:=20=E4=BF=AE=E6=94=B9=E4=BA=86?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E9=A1=BA=E5=BA=8F=E4=BB=A5=E5=8F=8A=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/design-doc.md | 158 +++++++++--------- .../\346\265\201\347\250\213\345\233\276.png" | Bin 0 -> 138948 bytes 2 files changed, 80 insertions(+), 78 deletions(-) create mode 100644 "docs/\346\265\201\347\250\213\345\233\276.png" diff --git a/docs/design-doc.md b/docs/design-doc.md index a258474..fb8a822 100644 --- a/docs/design-doc.md +++ b/docs/design-doc.md @@ -45,7 +45,7 @@ CodeAgent 的工作机制如下: ## 2. 竞品分析 -### 2.1 与 Claude Code 和 Gemini-Cli 的横向对比 +### 与 Claude Code 和 Gemini-Cli 的横向对比 | 功能特性 | CodeAgent | Claude Code | Gemini-Cli | |---------|-----------|-------------|------------| @@ -70,69 +70,6 @@ CodeAgent 的工作机制如下: - **学习成本**:需要了解 GitHub 集成流程 - **依赖外部服务**:需要 GitHub 和 AI 服务商 -### 2.2 AI 智能网关竞品分析 - -#### 2.2.1 CC Replay (Claude Code Router) - -**产品定位**:基于 Claude Code 的路由器,支持多模型切换和负载均衡 - -**核心功能**: -- 多 Claude 账号管理 -- 智能路由和负载均衡 -- 成本控制和用量统计 -- 故障自动切换 - -**与 CodeAgent 对比**: -- **相似点**:都支持多账号管理和负载均衡 -- **差异点**:CC Replay 专注于 Claude,CodeAgent 支持多模型 -- **优势**:CC Replay 更专注于单一模型优化 -- **劣势**:缺乏 GitHub 集成和团队协作功能 - -#### 2.2.2 Qiniu AIGC API - -**产品定位**:七牛云提供的统一 AI 服务 API 网关 - -**核心功能**: -- 多 AI 模型统一接口 -- 智能路由和负载均衡 -- 成本控制和用量统计 -- 高可用和故障转移 - -**与 CodeAgent 对比**: -- **相似点**:都提供统一的 AI 服务接口 -- **差异点**:Qiniu AIGC 是通用 API 网关,CodeAgent 专注于代码生成 -- **优势**:Qiniu AIGC 更通用,支持更多 AI 模型 -- **劣势**:缺乏 GitHub 集成和代码生成优化 - -#### 2.2.3 Claude Router - -**产品定位**:开源的 Claude API 路由和负载均衡工具 - -**核心功能**: -- Claude API 路由 -- 多账号负载均衡 -- 简单的成本控制 -- 故障切换 - -**与 CodeAgent 对比**: -- **相似点**:都支持多账号管理和负载均衡 -- **差异点**:Claude Router 更轻量,专注于路由功能 -- **优势**:Claude Router 更简单易用 -- **劣势**:功能相对简单,缺乏高级特性 - -### 2.3 市场定位分析 - -**CodeAgent 的差异化优势**: - -1. **GitHub 原生集成**:唯一深度集成 GitHub 的 AI 代码代理 -2. **团队协作导向**:支持团队协作和代码审查流程 -3. **全流程自动化**:从需求到代码到 PR 的全自动流程 -4. **多模型智能选择**:支持多种 AI 模型并智能选择最优方案 - -**目标用户群体**: -- **开发团队**:需要 AI 辅助代码生成的团队 -- **开源项目**:需要自动化代码贡献的项目 -- **企业开发**:需要标准化 AI 代码生成流程的企业 ## 3. 当前问题分析 @@ -279,9 +216,74 @@ CodeAgent 的工作机制如下: - 支持条件分支和循环流程 - 提供 Workflow 版本管理和回滚功能 -## 5. 最终交付产品 -### 5.1 产品形态 +## 5 AI 智能网关竞品分析 + +### 5.1.1 CC Replay (Claude Code Router) + +**产品定位**:基于 Claude Code 的路由器,支持多模型切换和负载均衡 + +**核心功能**: +- 多 Claude 账号管理 +- 智能路由和负载均衡 +- 成本控制和用量统计 +- 故障自动切换 + +**与 CodeAgent 对比**: +- **相似点**:都支持多账号管理和负载均衡 +- **差异点**:CC Replay 专注于 Claude,CodeAgent 支持多模型 +- **优势**:CC Replay 更专注于单一模型优化 +- **劣势**:缺乏 GitHub 集成和团队协作功能 + +### 5.1.2 Qiniu AIGC API + +**产品定位**:七牛云提供的统一 AI 服务 API 网关 + +**核心功能**: +- 多 AI 模型统一接口 +- 智能路由和负载均衡 +- 成本控制和用量统计 +- 高可用和故障转移 + +**与 CodeAgent 对比**: +- **相似点**:都提供统一的 AI 服务接口 +- **差异点**:Qiniu AIGC 是通用 API 网关,CodeAgent 专注于代码生成 +- **优势**:Qiniu AIGC 更通用,支持更多 AI 模型 +- **劣势**:缺乏 GitHub 集成和代码生成优化 + +### 5.1.3 Claude Router + +**产品定位**:开源的 Claude API 路由和负载均衡工具 + +**核心功能**: +- Claude API 路由 +- 多账号负载均衡 +- 简单的成本控制 +- 故障切换 + +**与 CodeAgent 对比**: +- **相似点**:都支持多账号管理和负载均衡 +- **差异点**:Claude Router 更轻量,专注于路由功能 +- **优势**:Claude Router 更简单易用 +- **劣势**:功能相对简单,缺乏高级特性 + +### 5.2 市场定位分析 + +**CodeAgent 的差异化优势**: + +1. **GitHub 原生集成**:唯一深度集成 GitHub 的 AI 代码代理 +2. **团队协作导向**:支持团队协作和代码审查流程 +3. **全流程自动化**:从需求到代码到 PR 的全自动流程 +4. **多模型智能选择**:支持多种 AI 模型并智能选择最优方案 + +**目标用户群体**: +- **开发团队**:需要 AI 辅助代码生成的团队 +- **开源项目**:需要自动化代码贡献的项目 +- **企业开发**:需要标准化 AI 代码生成流程的企业 + +## 6. 最终交付产品 + +### 6.1 产品形态 CodeAgent 将从一个 GitHub 代码代理,扩展为一个完整的 AI 服务代理平台,包含以下核心组件: @@ -292,40 +294,40 @@ CodeAgent 将从一个 GitHub 代码代理,扩展为一个完整的 AI 服务 5. **Workflow 引擎**:可配置的工作流系统 6. **GitHub 集成模块**:保持原有的 GitHub 集成能力 -### 5.2 核心功能 +### 6.2 核心功能 -#### 5.2.1 统一 AI 服务接口 +#### 6.2.1 统一 AI 服务接口 - **OpenAI 兼容 API**:提供标准的 OpenAI 格式 API - **多模型支持**:支持 Claude、Gemini 等多种 AI 模型 - **智能路由**:根据任务类型和成本要求智能选择模型 -#### 5.2.2 智能账号管理 +#### 6.2.2 智能账号管理 - **多账号池**:支持多个 AI 服务商的账号管理 - **自动故障转移**:账号故障时自动切换到备用账号 - **Token 自动刷新**:自动监控和刷新过期的 AccessToken -#### 5.2.3 成本优化系统 +#### 6.2.3 成本优化系统 - **智能 CLI 选择**:根据任务类型选择最经济的 AI 模型 - **成本监控**:实时监控用量和成本 - **预算控制**:设置预算限制和告警 -#### 5.2.4 负载均衡系统 +#### 6.2.4 负载均衡系统 - **多维度负载均衡**:基于用量、成本、性能的智能分配 - **动态调整**:根据实时情况动态调整负载分配 - **故障恢复**:自动检测故障并恢复服务 -#### 5.2.5 监控分析平台 +#### 6.2.5 监控分析平台 - **实时监控**:API 调用量、响应时间、错误率等指标 - **成本分析**:详细的成本统计和分析报告 - **性能优化**:基于监控数据的性能优化建议 -#### 5.2.6 Workflow 引擎 +#### 6.2.6 Workflow 引擎 - **可配置流程**:支持 YAML/JSON 配置工作流 - **模板系统**:可插拔的 prompt 模板 - **条件分支**:支持复杂的条件判断和分支流程 - **版本管理**:Workflow 版本控制和回滚功能 -### 5.3 技术架构 +### 6.3 技术架构 ``` ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ @@ -346,7 +348,7 @@ CodeAgent 将从一个 GitHub 代码代理,扩展为一个完整的 AI 服务 └─────────────────┘ ``` -### 5.4 用户价值 +### 6.4 用户价值 1. **降低 AI 使用成本**:通过智能选择和负载均衡,显著降低 AI 服务使用成本 2. **提高开发效率**:统一的 API 接口,简化 AI 服务集成 @@ -355,9 +357,9 @@ CodeAgent 将从一个 GitHub 代码代理,扩展为一个完整的 AI 服务 5. **保持开发体验**:继续支持 GitHub 集成,保持原有的开发体验 6. **灵活定制能力**:Workflow 引擎支持根据项目需求定制流程 -## 6. Workflow 设计 +## 7. Workflow 设计 -### 6.1 当前流程分析 +### 7.1 当前流程分析 CodeAgent 目前有以下固定的流程: @@ -384,7 +386,7 @@ CodeAgent 目前有以下固定的流程: -### 6.2 Workflow 优势 +### 7.2 Workflow 优势 1. **灵活性**:支持自定义流程和 prompt 2. **可扩展性**:易于添加新的步骤和模板 diff --git "a/docs/\346\265\201\347\250\213\345\233\276.png" "b/docs/\346\265\201\347\250\213\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..e8c5b47fc2de85efb772547ec2d932742cd9b2b3 GIT binary patch literal 138948 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%0DQA>|iI*uS7X>FXoTs}>Pv zn;pIwBx~=W=KwauYpH7)L@7o*v}Bbs3^?Jf;I1=QxrlRdT+oEpRJF2|6FCE~b%CX7 z-yA2z$x3#1=KrKsEvyv_;@};PKv~CWA(KJO1BYi&Eo8XOX83CX$bV=AI5mPsCrhc} z)dFz2t|al>eYESEusf29%Dr|+`y$EvWo_5M7by(!5K1y772P@4{l$blnr^;>=F>_H z0Es)Xyc{mO653C$PoKWW7sz&5J}*n!UiASPW?`gQW4WqDjpiNnSQo+J_h!SBJ1(ad zJxPtQP`>+hkYCdOeh4?;&qGzW9T##%>`mJqv=Fae-zcB^_Q5Ye!Kk&b%I1OP4VK$B z0jL7&wxUFdd+uuaO@cN)jL9F#MqUL7+!OT_ZNa|Cf8OeCl3yB!6=-j&d2=uD+{OWx z@d}IjQ0Ft1SZKvDM!XX8F2C5%xc<-h$A2w^1%u;1<`aX`Keua>)ooE_un-7)2&{ti|=Q6EoUF_)8+sA?tfnSXAnPc)nBNGKd14Z zmH4Zf`E!ac3jc`HKjQSG0{clg{*P#)FrA%~2`Gr*6`1Sznx+VL!0A&iyt@&UFc zL~z>^E*LQRbCS~UqXc2`{6S7v?TTdBR;%e9&1nF4S=_Sjji!-<1jrM3kTKLU#|_I15*;JTm>5%sK>CRb<(;yz0BnClI!xo*ISmpK{@}8WC6S46tgvO3u|LWBA(C9V!Uz?-{;`Jr* zWOK`RKn75VC|B(UUsn8*_Tnvgi*fq|ma`91s=2y6k4R$RVoui*$UaZxs_w~{2;LH; zOsm9b4gM7Ott!6f3z(gch(z*ZzStwb0AJyUZH!^>>ql@`mAL-n2Kqv1na6;$7tgQR z)6=chMaSv8x@xy)^IP|CYu25QALBfI@O-)lr{IR%ru~#m?sG--FIOGSdRJ$%UGTdz ztxJev+ffBJD`k1%@9KKy)f6RCk1=WwPge^O3{{HAw|`~#@8Ebv7Zu~yBnxIUkA1ir z{B$}*e}jN#_pID1skq336E#lWfkNV&nc6FAc&zflMwQ*=%-7V)wsBn5|uNC6wsm&s`{#>r_0Qh4G8mGnNg z4qwQtv@68q!6noZu#gnWODi0cO8(P1Xi6bB4~*o`Xt$_ zW6riFfWKGNBFMQI=gS>!YgKgkg4RpDte5H^TWvm;3R?@K8)jalel;!kr3EUHdEWzD zA|vZx()n?BDQ^FoaVP3tO-%DaxTzzXN$1(>#DChGu^K>9+hykojd4-!G}S|ws4?qu zzF)G;%-sBl02ys53aS`z*{;ZE;6x$T%P;jHR{sb$|4#HQ_ix9;uwaH^%B8T6l&;Gf9rx55o@=DgrTmHgaawg2mG zNKFLCMxtysjVXS;^Aptkq05)W0Hy|P2nRF%-1QHS{5&={N*FR^!=<4 z@Wl5jPdJnRQuqJT_cv7lh4~IbN`K~+erflIN}^A|w-|g{-WYKF%U$$K-*=3_cbhFt z2#ozFsr=>Hf3595i}9aj{J*TqKa26dzB5Gauy>JbgO&#r1aCrpU0)O z)8h{4d+oZI#u#n<_*pBM%R$o?NC5N$siN|qbN@=-Qz_8_C6#AwEY4tYm>c%rz#a1od z)|=}DpLRL&}euFfqbx}p+>H&c4!<{8YdEz8o2Zw;bax6H13IF=Z#&wD+M>?{5hB8IM{F{fw8XIr+-HJ>VB zB>2@P9lg4U3e%{bJlFHqvYAXVnyx%zHw_(lMN_3q0b%~=NyCTnK!fB5I!LuqeTh(< zGJi47Ra_BY{CABvUFq#|z!?Ak6R z?Vcv zmW{croDMyA zeVs`|1rolG_U?S0RaLkZ8C9) zP`IZj;3dui(k@a!vRzE+T*&HRHnVsLDOvK#El)Eq41V8?7}XEUM@Vq&wilT(+;6ed zIZ)dzT5+`5f5F2hFzX^`WYM*|Z4J z8fol)KuZ(sEY|6gO_f{CH5Q#643n0>z}4gln)z(>-}^=R8a1+ z@d$g(M$w4gpa7F9ZuP3e+_(wPsa+^5-Q|@VnZ$Xfjhd~YDTHdp5bFIZ$c|-4c&Oh& z%F#`Y(j6hXkZK+i9qkE^(-FjztR5D@{Y{Y&EDJ;E4Pte-^TxIIX#I*!;q$wl>@a3J z63$qr>sj!m7x#7Y%{LIac+d`(p%cf(0hc#?0^RY^CS}v+x;_vEck1TwV{3&KIoTt} ztwj&?|BJ7$j*D{Z+LjUo5mZ7XRYC>^6qJw_>5`UKVMys7S_OlY7&@dI>28o1x?xD^ zZibqf@8&$`yf1p5@AVIVKXkZf-+QmU;#${Q>-h-c4mA*RnFB^!RUz%Q;cb9k|E^+x zxVjmlgsNW2s^@ii?XvfwZf=03fDlno8BK~|oy%ZCsUE#6(=LpEI|xJzE0a+C>tod;*8-d33G}wfF7iSIXx+BjJ+HN0l zM#igq412nWM;$PuYU<9vJWLics;4T0?BlX=SYLRHf_*N^?`oStLD{2uI*S1n8taU* zx>Q0?dA^O1+XJ;#4qDG9T}Piv1e4-y2R%z(IxO`#bDA5c+#*tl8JhG_t7z7-u8S3! z4id1Wf(aO&emEcuwyt!zfJ;LZ4XBal#yie)=rg(;#}F7;=c7V(o&j4g;lFI}e~vfP z$Vb=%x-2y;0MtT&PSn=kop~GG9pj6zkoOw5+>1T17qgxJ86XF55v>*CL@-V|jHQ?* zO_NtoQ3utSe0t=(Ji&e9u*PM*a?;ncDol^WFi+Y~6a$Rv&F8^#yo&q3M7l#+^%2f7 zLNqS>8YeYxiL8YWY%4ZbSe~~rSp@HC=57RZvBkaTNtmIdw0_ds-1fSOsO;EU+seFC zY1f+&$SD3fST;bm_+Zut9ZX?Nf9L!-ry*V@ER zl&61@{Se5nQh3EjRhs`OzDix;we*|m1F%y2wy^7pw5RGgr@P?7piT3B`OtXJDCQ1$ zXPTG(y0sTdF@6#1DDbRnq-yDg&oiQNKv{r&%BP`hKpnfrcQ+(m2U$giFCInI(Kk^G z+6sA1<3z)8 zo}r539EF^u?ZYXGZo52==HZRZuQuKj=z80i#!wp<@<%@HAICM5!sps;=8piMYMH*6 zHJ$<>X;fV`Z4XQ?Un`UI<$u=2rB%KtIYRx^UEWjY`XmC?lz$Hh&ds!!qn!6pZy(Ln z_?OBdUFREv2iwv{bsi>0ij2_{DH-fb-q~C2eN(!LA*0aCGtBFr@j}a02_v7E;$Rsr z+38VUTdwtbowrvR!6&iVia1czB!ZtG0~K&_fmTZUy&le(WE@$>=v_=$8sFY*wUQ@~ zmM6#ja$~cd|2@S#9ZmCzT(ehJDH3ZF?1@186H?MtURoEYJbj4#osg>7VBC57HhNg2wm9$59-=#M7jFeTPAl!-{jCw7Wd zN?x*$lpja8F^~9rtiP{|v5j_evJaM+g}rCyx%T)Y}hSFCb(zU`B)XTHrKvoAdb z;Y_$aldMSrv(aP5IEY{lJSP9^p)AUlQ#hTb+ua zjCT8Ovo1WUpmCIHRE4Gl<3SXO!RC%<6nK z!=NcrCU!X?!vml^O#@vD=G?|o(=ux45VsMxX6O+mW0;>W%BV z4o9bMUQKX@yfRw^S_Cxt^0n^DvVnOOJXBq1{@@1vPcRO6=>XYcNknp3K#0ca)#44O zJ-Bmo6K$JtbZAdZfZwQX)-TnLvgkZ@ZDtteAi}yy>4PVU$c4wb8R zB$W@M$*t2)%pC`J3?zNUwuu$?DfBCk%5)naKWIyD`?^kxzT?4J4i@%2>knRC(f5xpD@rKas;{a?o<{uIk6PbPIT$pPq%h1 z@9~UzrS;XQZ`vfS?5zns<(9N`A2Y8^K52UcnEc)u4J5ns$$JU_i!}C`z^E(kzuAyZ zs=}S7*4)Jtc2Gwx}+qTL=!!(DV&4_STX&)~ywfR+=fYCmz&JDKnZN4*73N#wLks@{* znGUu?W8cCo6NjFb2Ln1fU2irmQlAjWO)HOiVQ`uN0tm%KX{^NriH4sWMNmG^>?X3g zr}~{Zu3S95?0MyZV_NAQMt?J!wh$5v5`9;KXjQ=BOqdqkSb5DKoD zr=RGdTyc&+(@H1$98(;dv`pyfjbm$%$>s`bkDMyd6NqLwYKEZMPr)7YRTZzzsi10t zuyjJDf(v>OWpe_-P$oe4DoLdZ*yP<%mdiFPb8Z<|eNR-2Co_;A=2~v|puCQ@aD=}m z6VL9*VSgX(bBhcjTcu?MNvnQU6C(>@{wlql%uxG)KqZx6MXK=1Kq@lmVA_p1-rA(u z%F5okBQ3Q0yluv|_~K8m9uG5eiMDt>=Fp$XagA)LEL)xiQ(Tu9AQxGP7OjNr-|(2x zX(e3k^}$3xvhs@)@sc^qX)0h0`f#P80W~gp1q+u{^uPVZkWG|{OAP3QwCJSo?k9W7 z9-Xk0+CE{6Xv87C>v@CMHJwuTJaYl(*_cTUF&FKm=*|FV)CMj0;Pk3qB;@TN6U-Ld zda{~gXZ%y)_E3-4(9*yX6LC@d4#fdxXY zFkLFJi`AQ0t<%Fa+3?O9MJXR65Cizh;<&%b4H6>Z`uOH%_CPe%KDz=e&_vr?_9bKl z=E~*SO;*jJqi7Y`YwQ?anU~?OB#(L0>=a+(SIpZhSE_szogGjYHiBYY6BE1Q(|$9G z3sQ6heg=dh-W~?h|80N|u6qZjA8)hlNBBpFHb{5;mwl8ZNTgRohkAg6=GzyJEsT zJv<-zeftttUry8~;B=7M6@ngJxd;VU%@6|_-}vBDq_d-TEnu{XJEa;7AdI0D%rk}A#i&AQk#(7+gQiLlw~D@ z_KK_Zc>I`_ta-WYT$xs0!}~HZ9N!rga)e4YoMcKHs&MOeOVX@1Mf5~|tc433pQqX` z)E}CF=a>7qrd-<&LUUNo!+0}A>+ZnPOeMB->#XU**lSU;_OZ*fp{=NqSdY#p-JDPB zSyyew^@>%KzCJTKf#EU9eS5-HJCz94sPCs|AHY7G9-N>t!KjK0dhWcy$agsLmD1!Z z4{=rbz*EjfARlnHO{lSOn>YX{b&Qy*u^Bgis@h6lxhmDHyDCL?BdUI2cE7~n<*$@uo&FW$)+t84u+hd>lcO&xla?^SNEiS;~jc zUbP=mrtrK^<=t0mH6SrEL2BcR1DkSt^YtR@VnLK8r`8jtye>HjQ>-eC@*Ivt!zC8H zcX?=Ll1=th>G)NRxnsb+<|nhqh4Wey$$LLhXUId$&C~7rWCt_~%p%Ri?bnJut7;WC&2wvDyd)<>(i_Z54m^B7D7IIt6q^3G5F&J>akO!uT*slg`8~ zPYhEZLU(WZGHK>-7@v)RtJ%e%KwGP)$VGS}JU8bn;Sm@1L6Mo5k6yhM3y3IwCPk{q zeH=t3;#B3i6}0Kr@m}JnvHRz1L&+0PEdA%Pa)B}GjCDM{5IN0uksO{CJvF}?=b5~P zNBglcA3&fS-Qp$sPU?x$jlLq>o`gmE_H^tC=)s!liMG1W=Q1qlA$1KWlN|XlY)l~& zyy@0({g@iv%vdXAExe9QwK5>#!Z{c!sw2KTJW!xRm9uD!+~Uu~r#V^|(ES-ipWDk> z;pG`!{0h#ijmdA}B2_quvCG0(`W| zal0oMWPp9V9`j=;XG->`63uYMfim@YkD>(h2WVsyRz4R`QbG2LOb(rkngHqubQ)W>3!BWBuptENxbP>1pWi({kK zeOzQcmPik*$E=ia01|7y0uW?er^9Nh-rO+Q`_WtB7>378J>Zopgfo66&uBB|b zPHC*`RilQb)kHM?J6lZHQP7>l!DPC!w6pA=r~LT|2P6Y>vG7r+a(&*Sxhy7E+IU3! zP{tAO9TjD}2)HS)Uk))9QF^!{(RxRCaAZg6VEJOp2$9&;RpN)--0k1p$jg+DNf)p- zUR?39xoLyqAm_+1B*jgxYk)^`cFFwgf4}owHG3&5l^*s;5u01O*NI=ZbpOMBG}Xd@ zg^%|P`&JIpTCdEPtXD;?Kmg6ckZHA$y}Q?BoL`0_(d9F$UM-<}u#*~hNGfOP{~HDfa}Yw)L^N7AE! zAI9D0tU6Am4r@bNI@r!hEnjZ4Tu-S*i>vQM5Dus=X2N_F@HVsTmJVF)wZ`sC5Utd^ zKU6;jkC)h1qfJp-w`&tmmuGVtIMsW@M(^et<2Ge^fOPb~l3|JDmTvc{Sj|-Bn0TmS zy+LjP!>=}SpVheq-xyFMD&pSiAD+p2m?ylI+$#lH6!2K8VTyW5Ye@DK`Mnt$t+k%5 zUcdnI?yfjmAGMb44DSfsDuOyTaK0UK1+Yo$E!9S7rJYG+FT!aQp{7yurui)DY*<(0 zd=umEd!1^aGnap!(evAH_xk7&E`v}Z~WDqtN_2_<)BDKTIjmr)7%+J zT|JetqndA8$o*yP^xEEPdUSJoG4V_FfxQvuH$_?A4i=Ge zq>^INT@g$xrq~f7Be?5k3>0Nm*(j+P+Y9L=*>XHh=xoa18qP|Fg_nXOgQkagZ>N3b zL|Pw@Z-o+lLWNv+MuzrOs0>4i>~T@hO>JI{oIu{4;j8I&!XNv z@D?4zd+X;xASudlN{~5Q7#-_n3vC4L^zanxzv3F^7w*W}?ksQ$LYpMdTYVdPw(&s> zc16f>0(*5|rt>4~0Yi1zs1l-kVX~WO;I*uMwUZRF2wFfK-o@M8&rzGFbI6&hNJ@1Q zN7sG>m()h<^}&krslh8^y7N4sR=s_3K3Ti%91ojohIWMO7nK-Pz-i-YhIW!ShU5vz zKc4UkA{jEE3a|Y6Wt~2$!UQQ+TTo!F0w2ifO|0)LF3gJG9?dtt*2jI-t6oFh-b^E6 zQ30=kpRLTtPBKxuG$&Tf%%oS>=5A^R%=d7&@am%+2HpqKN?;rd9UiM45(m}Mg_Rmm zpCY7Pm5P951KF!+LQ`*o#7Y5Kidet7)~709YUv%#M|Qx7*S zCYCOV4>7NYZpS<5eXYUz}M%SK(R`u%h z(Kl}~+$9xdP{V#|F+z5zsSdOQVP>`Kep$5bcHUd8GxaujWI+r{U6Nl4YXW2ut2}fPkGFcbiAn44-izb06#c0} z&bN}8d8M%d3!0tiEN?9}C4pC+wP>o&s!H?8$CMqjY&>)?WowKm%7`jce&RfoU?w#q%0@bU1A1gYK71kI?NFjRQGeAQRT8& zeklg^_taw+f;xrIc%7-L!9>)DLK_<+_-x<8qijE<$t???7B%@qa^2WEUa7-;D@)x6 zO1lr*+BI{?OnTz9h<>nV;csRwpP%f#DxS2(MVfo}UlrW1D9a4QJw2s8&QG0?cF)V0+N{*z9P~ zK26#Yk$q+uP`zQI+SEQ=D%BC^YjBF%%FsQEuf6dQ1wx8_<0$#jl z)#9yixSYY=AMeKPLOByLT(LgOo12?yoTX;elT;N-MwSLuE)vG)8<pTkRUOJzTu@>iv zHVPW+slN+s3y$YlyQy|9uDhqKAUHU9GhGWguthSbr*DeoEU6rQ5Jw(i*`w@wI)wSe zU&<*H+7eVHUE^Zg?G$0#r?oocTmjMiDZk2&D5L&zizWPvYF%Um+lbtkP_&m%I*eNb z>k}N7A5PEGJ5ud6S@fMzZt2`DVlxUclgc9r{4p_Ss!e`g$n~34zFWD^K}zWsWef#R6EjdRh4p4icO`7C_R2k zj|==li6V;I?b~Ffn^JvCs?2RTK7Gydj@__{+S;_md0|e|A?$AhF!}I>NXXt)>Ix75qwg z*P--$%sd*_(s(*P&@2#q*sLx(muf7x;m37^*i6C#LPZ6D3S^UF#GpjxayofR%q`Kh zz?GJTx#hM79i>M+G~nFGGdS&ng)v#|bwQ`}(6-^5tjSAtr~{61ho({p;SIfm-kyUt zA9A~sd=Jn(t%=k6pl;c=Ql-mTvc4vkM-SJT#L!b;BV7Xn%$1(b2sXLym~8>UCmOl0 zl3~PZSQG`-nGmoSX6CB>-9@-YXgd8UZ@DF#`E;RS+Y&yHPB`gEZ@fST%FZs$Rjng* zF-=e4jBL~xpOUQ>dRT%RQt1-qusR@tkpr1v8RiGwjyTOK$hj{;*nWDbv(U0Tc*<2q zS@L>_dSW0wd(5~^6-x)wNfAbju^Nnw+8oP@pb?=XO^xI<$bY1#{SItT-3qeVio?`S znySk!pam@goUCnWN}@!(tiS>~Rw>m_PBY8sQb)^?kBaju!`xuw_g+d&!2y?)H1nys z<*BI``|NtG3`jkjIniUJYi?nPvu_9)`uUh?B2A96)LSS*ea{ajV_Q&m-lrin-x$rE zLEF=6T4TQ)MDbZr!;1{8twu7Yiq)`&LqYhvf%RS{%IrD^^zguk{gDC#$^|?Y*>LF# zyG#yJ>+?kCvHKEH-Y60gxOsu7>E0eI+7;oqM~6=H>y%yJ>*k%|6MTu{&_j7Dqw2zM zL47{pb9NS+pc9?bWxvTo5BD&F{09%r;Xm{%NV6Gg%V+YFJ(jpd&ziTB-|%~c3-L&; z9u&Quyup9mYv!7a*NmtCYq-B<{eYFtyaQph`kanz#Z++k=+}vyhvs#B8A@{pHr6#; z0Ft9pH~C&CSfE{0rZ`jdYmp(dm#=NafCSz&jmB)Nu>TZiY7M)O_V(zx2lx+rF+Mp_63Qm-OAKG zu@rLC?@z|kT1*}|Z+b=}kcOmsN|aIa3It77F*>tUfEgMvODJu1~og!NaKatfvo1j1FdQ z91}g_Ebu<9Jwq~89{KwFz1TgpH|FG-afrcR{2eCF_x6aI-V zDqfcB2S(aHT8F$O5~SXM+-D#$&VXZ^4WyDEzD#>JUbJ_zym@$9YM}|)U+P}EB>{Bk zBoh(AFnu|^!GqZtD-<7^kF~Cn0m^mKfZk9l`MRz}g%fv_C4LJs1SMvH8ws_Uj^i(0 z1S(!{aKZ^X*_4w%hJ(~)NxJOEzDfQak`R0o?F?r@a?bG&6Q$dum-|8ykBXow>+y5*9}_(76qx~ z_5!}7b$1~l4z&_Rkj8t;(YwMly81*z#dQ07t#T)B2Tms@MP5rSp@DnmVxDR5<8mgb z0DsQGVE9!zU*&xALP4nd+c9?-_hHzg-R6NM>l9yN_*q5L;O;wNVY`V>v;+*K&wL)< zPDQ?`t`u@FeWzXX>TxSeU*JQB$TnqykGi7Z`MXLwid%DGpNh^l^j*=vDqY-MKe;n( z5+Gg^nap&#&*S4h6+smpPL6;V?J>JJGNb}^ zkTxRlUE7%x9B8cddvA*znC4kdTR>0!IN}DE?UdTMlX=Dy(2rCDeBG zn?8=XMOzxzqRwu_VtI@gnZO$0_31KU1MWFM2>UblQ#zMpCr#G!>u8_(3HQKIhCbcE zqY&Y?ey-Cr#rWp{Qp`%#Q1UJUeW6PPs8?qslfuWBLp(!A#;J9#hEv^`Z zBxHNq+m`66HuKm@O2Q{}pN>J(VIXf&M?m6|gJFbOGC8sRBnHKxYm^Ap;LKlCbwr2= z6`gfI%p4?@C7q_V$GxaS=X_6~RXSAlu@j3pa8+&37_{gF(4Nkqnc$W2!!?q81_12u zCsCzBQyl7XN~Twb5|;+J)xu4^R_KN@(P!blon5>DPKy@vkL8rEMK3aD!5;5)?&>U+ zE@XwvgrVg*Y}S#GtaGJa zA2lAk4B5?RQp~W!^y6fl4c*Y>8cvf5ouDyn3~Jpwj<(qLqO2o{ouANnhjXJmVd71- zT#%m7y~OS{Q!^s-ls0SB!gPuoj3Wo5V_{_?lQ5pkqBP4^IaqUVT-7*&ukaV{$)lxX zd7==9AzrK8iqi_Su+;uGwfVbkQ7ozNMft9|oFX%LEGNvpI^16g3W+M!((WzvnANcb z(Fxt7E|qu94hQQ@zT*W|+AoIyyzJH3YG>L$?&>V!QX{L`b(!#0PX)9LdhsqB{{9z#c(AD(8j}5(IHmi)*p&fNT`wollC?ol@ju z9u0OWY9@z2B}Y?N7Dc1lf})v&aUf^asbCgC&kZHxM0XzeU`${E2#;`~-vWe~Ua|eq zH6>n0%NEP4Rj(N>U1qxP`7dmBU_R;+IFdBfY zbF?we0t{sssmtH+x@NaF#JY+o4_;{hruWQo?IExAbU@3v9q12<+yMvx^L`F1efnpH zxl1>24nP{Y4}o}l5ba`@;jp@w2D_GcrFQ4Qg#F?deOACPs~pULE07uzEMjSpPVD3Hn}pJ*j;Vbzl|@+wzBB&@E5%Oc{K8AZ?I@9>y|(i zgV3-PSm$iG=xQ?d`A|`b_)Ij5h36y~BR`Qg8hE8vvKb^d<+;c{zB9Bd7QtwCOIpv8 zYHDoPu;Ux?@&cmM-e|u@JQ>!bE>UX25yzZ)Z|sxkN8qHFxAGhCyfkeg;g617(;;Tc zqtFXx13H(MA1 z$*HA-w=D!yXX=nxwh-aO1P?_#JWsx?=dBjOJ2)p(bc+d&pvsg>q*eJyZT3_KnT6O-N014tvwY6Jz?ej#8OE9c-E_>`^Hn5 z5340bJm0;$dUC!VH1k5}AwdlXmJ%AB3L{ya@k%P|GO8SHrCwcDhZo+Bo=;aOt<)sv zG~%T!{b;$$W!>?$e)J2WD7UN+c4c7pV&yOky-cum-7q3s-Hg$ET!*|bk}Iu1aNzx@ zV&XFvi_v#O#mx#aTxy+~56$?eol*d-M5V&UlhvRwHKEk{WI)|+WmdV?KgR2){9L42 zE+j|t^l5fu{n~&5FcPF9d<1q{Yda6Cd-8+u*%R4T*|flHbR4&d2I|>J-V{5C`%Ue$ zyws^>Fr!uxW0CdDJ*|q@(ZWG%=boG9w5}o)q_aeoMjnJOux6SXJ3XDtJIJo)~##Sy-My zy-&i^0_fpdS@+OCx|Rm_7PEY&Nzd8&{?Xi{m^0#U97=W_22XP?5~wf|#Qj8hkKUTk z_`IkCc4rVDSU;4{xY|+zZ(HxYSEOQltJIrOD4x>mH3Hmz8o2L#h_bzn7cbL$hf)0~ zb>O6HqR!p^jt>csF^!!R<{wOKPJIENVk_M=11{mG!JTGCU|(;!=-d+BUul_trYP9Qf5OuAa{$m zFdVL|JwlJjOf>A!2MY}9?>p=@fBFDfF-Uo@x2FL%h~;`iDD={Hby`G1=$(IO6w(Tv zU8VpPdJ~7c_on}u(`FfQY{``lqH@mFMt_iZpH_!?SXQqV{lrZIfA5q69VyE<{8C2r zu?%9^DEv|YiFt99mC|zZweB#TU8ib*i}FEiT$(cCVHPAvRSa6jWR2D>i#4uQoN_io zRdw%;CR!YnDL+V$I(x1X&3ED^^hyzoFlV1KcXLN3#5X-%kp~|l3inyKjEB@vPs}Uz z4heLPd+69eERfC=lKuTufV}j2 zaNuF3pv%t73HQ@d_E&rox0q#L(;XeGs#4{3yG;bwuUJZar3lX&^b854c9uSKnp#B8 zpu^(@j@GckB1*0_^Vy=jjuV8OYbNWFqIO2TZ-XS5_Hb_j_&EMdmH`DYXE#_Lm_G(g z1*jDCLQlrE#0xm5>Xa8i_7-HgjM|-5s-5~UGq35S@qP!)XG;kLUH4uXOgJ6y&~Nl$ zfcXY8y$Q940qafzW`ENRd>#>%nC=#$E0xxUuyV?MU0?Fj%%Zl^4j6=dt zc@6m5rIO8PpzVg0tNy+yh~T4gL%+#J&_t6<%tJ4iaDoB!tA=Y&cM zAog1i2>E)Pt|O{kn>5L-V-4MFHd79(YxjKxp-0kc%z`PI7OT5fnwv5E@Tga}1C6Uq z=3``yz|6yYb$R$}3c9=sbi%HtM|pA8?;UcEe4Cj}!&;R<1{&9%@vU^m=RiaB7j+lY z8g&l4Y_k{u1Rpns*ZMmq3C64-D%t%baK%$9=elDVP=M1JVG}c#=kle=i84ya&A6H; z&?^I))SIT=ub}=9!Sd0WOoHMPZ#)mgD$34W>NsBYq5NTcBayMv_2Q-cVFmyl}?6zu>J!tTUk zQI{$MY++$k%pKGl#+#A3;b!h05&g)fFg`L^sR1dMVzA7qy&hztVLcRywS_Q=dT0pX zmrVu^TNcK5x(dK)0%n~^AQi(E^JrCos?WM2PQbbUI*nT6dpyFWh+HjhS-Zh*5xg1$RQ{dAetr{At9tDS*u?Q?cA={DPB$xbXB?g zB$E@gzq~W|pcI*f8Z~O^3Q+!A*Zvc->5{*ycFLnmDtFyyhTmITMth=8?QK=E1825Qht@#kxhz5eRY z6Gr_3z9Nr)FKELo;30p8W?uKko9SSVF70wLvpbQ^eka4E5$Ao3Wq5u5q;;S20^c7m zU5Gjtuun{oc)6)+uevy~iYT(2^Ewr`Tn0rd@2PdNQ|+aNykMQb2q|wAh#jU~$Piwf z*P)-sJIOv=I+6We!dn9As854eBs_cs&Fni4D8d%jrgH4iM-u#A>+frZnp|(UDlk%o zrbp0Z6$xDL;m*&M4+}mTRzG|w4Bgb!2Q6$p3!ldK7%+CQNGo)wL_X4`nq#HFWm z1G%?o0o7<}h`t$!F6%XLv}DWE_A)}e5PFYix6poXf0;7`(BGY!29DnpVsq&?GB<%7 zQo9uWQJM;A?OC!hL5)BnTYA=Srr zM=x+@c{&TfZV=sc&eCi4A2IyNI>lH|msDokgB3mF5y*~t;~zbj|1xkxv7p#Ao;S5I z|x__)?wwt_qN8VxuH6;Ki8(B1Ch3c}O1OXx-~Zn`)!8 zxz@xj;(h7#_gP)@dzu}|CRK=Cg!1?S9Lob;Cgzx(Lb&FZB7fDjz~UN;&oKcmW!<@G z$P3omA5wHoaIR;+$8>jL9+Ly>7miOLBUygwQivyQNG*C1pOY3wix z$9I_ivi=9=LOGOkBPlFBFrDvs*|ZB^3IJY2Rz~+wmoMyUv-{ z7XZ^nl;G+SbM$qM_k#p<(z{j0Q>APql`?21YoUryBZ%#-LhZm8le|*I|?nR-(t4? zb3SV#EyU0UUFeV9;D3b^~JAYx5bu{lw z@<|B4Cr9BKyt(4LyBBn?)GhMcamTODuZ0MJ;$#OVG}ZdG5&2yqN-$v|D@ulooRA>Y z;#t*KLAP_=UJ&ImjqUBWn-ON)yB{)qoMl>-h-4PaMuuOjdB=9@W_%@tsmgU3v%xfq z$Yj7kf;{4meo#GOSh~VPbz#o?5eTvYuAQl&;_dheM=gJ?l%wHomo=eI z%E%YTThA&Ry7uc?75fC~=Mn6P>4zD3Kdzql`Vi8v!zw>B281zaS63iftM@&6RqI7I z#|q_iCI(M61-6dr-qsQD-7+26z{yf6jWg<6(3UI>pc?!F9Xgv8s-B}W8^@s+x^avd z{5WA(9zM$Uvi4L!d#QH~=v!xBLgIAV0YF3Sx9SE!!Qh7G}9PlIsRH@M4VV%FASTtueu;Nn8Uo|#DCVU@)l z8l%i&7@B*G6DX(HQpwSDDc`>jczx3ovAD^U94!`<4 zO9hpK*^vj89;S3bM$$0-yXGWc&j>5dJbHV@>qTxRE!P>Sb_tqdMP&62U#U%!y7eUm zLZU_@J9O)1G!-?k)qQ%;R|Wuo3Lu}j=YVb9o8uM$W>2b08sR|x)H0XLPWdff4le@3 zUoXY}@jL#C5AVNhQ1;gMB_uZ*NM(Jlkx1~-#1uFq25j8(gxyLv+#ix-A^ohPO7~8U z{M2NW@+Ln|0zE^l*d3j`-PO?yINP#Kp!hefAS1LUvcISpWhV67|{!J zpo{dYH%gO~bcSQxAFcg6!({+)D z{tU$iwh;z&?Y3c}yEe$`@jIXy6QJ=>HW$Wq03-I?`)&{JR5QGh<0d+^A(>(0sX z{1U7&=BWjT{nGjUYquDGlobE9tXVp2TSGro@!97(6=%#jYqG~3dMsQ)rG}|(x4GSD zSC@dB{o4V3b&B6k<2AvmvCMA-T~E(_YlhI=U$v3wqZF2(>F7AdpkNm_JoZjn@wd|K zU|LgA|1`I7gmiZIj8nWRc~Zv2Lts_j8H5%49-PlSy!M8W^rOC4u=~XsfQ)>R)l@x~ z)5e_(OzimNWR)_%2&l$+A_F8YIR-P7BJCDCrASEgZ~YdDea5|*X(L;pF9bF*A56~! z%2a<2{JeUhp}pM*GJ9uLnLfjpx3+fe9?Jn+=ZEdSwMEAXH3du_@qlUosJ%yusH_;Q zwCKB;t{=R(n1;VNzG)M7mHcV6_E{ozseTE_JoZB4yA*j>&mfcGNERhe5<5!(^cTXd zDM`EyAb0Ff&43+S_HPfz}bk_jOKbkHb= zXn|ZLCj@Bv`CRyp)L$OQi)&biuAi$Je=5J;LZ7IHyYxrn0>&ibKi|H*_1!f-x8Kg{ zu*@O2Bb!nJK&1fZ)!`;!%k}il@^1s1<5G(abiN-fUL&R#e*UY~-z2(gC`&a>)aSei zdME;O`W=J;@^_SDC1xp4tf#x|M7O6s08#z?A5kUM0(>7bt${dvEZpR;SCF-td$PDf z!67w@xT|=U9r~AF>2oqRz<@nFq6Mg)9xB;ttZ;U9jaujFEDp;FcMx)Gs(8Z?=eLs+ zWia)zU+$3s_|)w2KzckKGQ4hS_UDHho?^W}(6vvdylit{DEr7qbD3%Fk94l|8*acV z;)Ok`7J3tdbD_!yrH0yw2u+?n#pGXr|txr9;N|x0)pc#Hce|OCw(w^5?tRsC)NLq0*9HFvflDm7_sO{c1TFq5opob}KeY zNYg;|^e;Dpfixf6-HT9D@v1nWB=1Wwc${7@dfN)3;G3`G4E|9+i4|Y4+h>(o{>D;J;9)7LCcq#zB zRa~Qr)&i-xwT*ku$GLcZS3=$bM1Ua5-Jlt>uKXw$ng6QnpJ4KD!Fc|lVR`GmGP5-2 z6HbP<--ZZ&rRt*C3 zdg+Wm?_tvlIE9FykDIxAHxbUVzgoV4E#LkAc!H0L06U?t(w6M<##MX~g~Py*nL5;s z;f?*ll!!>W0eGe+_TonR7js@AO>7;gMFGAQNt<=RmTGcgn+_Wl#1l7 z=b9t{-UyZ)_3vA91^YWCgEZ%X6U~>)XJK_egjqowc)4H^#V|&h&{xK_uN&Prn={Uf zTz2ovRi^~reBh@O(~)j6_xiV6H7WlZeeODtqp1YX{X{~4@2N$d^`CMl%J2>wch$E$ zIOTHC-w=okm<49QqJ)?aXX_YyY)+_~4P}1M?1GNw>lJTs^L!U`0oxwIJHyTZs!p(6ovM!9n5u3o>&OLIs?)iuzq<>QVzU4Uty1{b6|QD6oXrF@ zd42uwcXkIzRYdese_!pt{SDsRz+jD^+Ot!_S;{HtkfqTAgGhiRwxV?i@C%c-sh=IV z$*N550{zHtCU;P6l8gBM}@`P!x0T*h6d z|CWTefF$_e(Uknn)8nO(2IOwC!uCOnrYKJ>X_)Qh10#6xqk%-^dYDWYvsMq6<%E(- z**mR&-{qSu7pouV;`(Ft07v5a(|w>4wgX81J$GcszkINOYX*Mgg?3*ZFa87>6ZSZj z1=1$})=w{Tfjz&u4qv&vp|i%=5p0@-hXIL#uJ=JNgMSZAYpi^_V|itYjTP7jO{Z&o zDN07+|CZ1eB0xfSf5rg}t^d8ylhUu7{k)o==#(yO0z9CmCs*-*-|9Cv`Ml6IYMC#m zxn2OCI;1n4{=cj_2w3yC`7W*heK4tL12OLN>aM)aw5bZ)5AUF54FBYL{t{V+0ld9M zxFNp@kSbl=uGf4uG4?m$_|Nh_3j!X&{oWYv%bO@lMv+zF=*2(-45K4!(4Q z@(JWkpTHxm4*pVNHp<=%LX_WEDC)3T@@YwCu&9VH-gCB;h=%_sr@O(Ke*^F%!w@z( zn?}fUUqXv8uHsM_vnQ_ zdUOAhw2InbdpeiS1e=rmwGICt9R&i)GPE5R!-w=j72oH0_DN!P)PRy-NEdR~b#LLzAZp_; z2?N3^Kou7)1drcfNyk1Is?~!eCSNRVi_vC(Nr>NhD_1}vy7K;OmX|+X>sRyKZBlx@ zJ^f*h_s)ZR-lD13Y^(#Gm@5K${u?_$z;s{jPpMwa1>i`S)248FN#Xwlf4D4-*o61Af4(`_C?Ktf&KkcBG0sRO#jqH{)ij=RCwsezD;{QRc{7 zxr}`DR;dZl27rGE!l@`0c|^N@D@RbvR)u~$9X8H%(g=(9Kf_ImZ}y+_v* zvAO@aU4Q&&qdwc@yRY*7Ilmk-Sz;#Cb)VwD+{nAY!Ab;<`ekEdj*M_ z8}rL-qnoUHRi>%&!2sswy^bx1E>{Vn5m-INI=HZalhO><)01}VBVhZVyT4k)fKgeo zf4VKW$q9gxQr>?0M)I;|CH2J>Hk;xj?Doq7z7Ytovq)1-o_^T?Z{7R`?l~c~Q4qyj zRlZoK64^t|{9GClE8=!UJtm1oA2j-#u_tf|2fl#r(5?#E+Vc5kb1kR$_ybZ&th%dB z1nqOmilVg{t_D(-k-pblE3O#W)1k5LU4L6i9^M*IQ>#;MRd@#|YmgksP`d2WeI~&2 z#L(Q#4geg;ei^{KS~)P6nzJ|rV2h~7t^$&Ck)N|9-g`$zQer85o9$w~FC~gf`dKSv zm&;FtU5348q2wX*9Z+ls;Dub0P|QxRG;(r8`iVZdxiVQ9 z#%@s8Wmh_w(Hk<52EQx|_n(V;z_x+lV$E5J42T!Kp-L*GHY`}l$&;(Yd$X04Ep3RdVBS6xS9e-NJ0T5CejAo zQV4YcpOObDN#cnD9v~?88pyjE{c5=elLNR~_3j7ChL_|?^u@KEv((R_5MAJ_6fcA` z11Plk&EDgZ?wDd7j&}7X2-&*?u0>{@mlliP1@r{NT>`#pUVxVRs_-qKS&64{bnjzt zfq*NGeQ~8Brxz^lD(CIXy5>KZhQXZZ2ZhFvr$-d+W&8ifop>Sc1J>b@8%!U0=c=Bq z76G^vQsTrMRR5T_zn*1d4cNHJvqQt9%aZUPNAQ2{)$AK=N)Fu+fIj=KG8^bSuL=Mq zR+lv3e^%81%;+1i4<7xZb^njwzw{$;whz^_KMH!B4%JMQm<@J}#N`>=PQceq{mzibsEjngkVzz?IlS#ymE>>H6>??rbrS)fEfp{ zabSWIhS7Su=HD7|QVFodNVo2&$N$IixrB%=_rx3R{*r*P0b^52YR!9^kA;M4{T7z{Lag3HW)iv=M@GvVfCBm2*x zKEMA10;d2N!G((=3PL5TkH`54OY@ z*kly;*tdLPDS25&UafBU87Ax9dWkz&)wPk9SWDJ}drv{JMy)UB${60M_`6`sl1kYxlt*H&{fNkGDcRl zoG`r^wg~WauUw=Yu5qQcW8e<2Tyn z9Q#WHFF!KYA7B6)n_xfaAA=aP=wEaEy>Kwx=a1rLrXT;|SiLXJ4Z_}{pG};bA1g}c zHakij+v>?I>dJ0#ay?9^Vn{X2OcE!4R*DKCKif6!?-2^oG2Km*Bv?bEKQ9^#uWrtB zQE|COjVWi#IWz*G$Fe1S5hJ@G>_*ZAx%)i7eXP&8C z{v`OT#c+idNrzJG`i$GxrAqy=OVxSay?y|y`?*q6qiTl)Q10C_Y=Kq>)!jnG%_kpf z=YN)OOm(y;&lGKXvZff!%EzF29JR}=HB@ueIgH!l;9TkL&5f7Sr`Mro__>GsBr^HB zu~Q9=MbPf=%ij~lMcTFQyrZk8d!01ahB!WwA!pajAXtE{dU+<8^hBo`x4qa%yJown zx&!sjR?jT1e^1?TyRW)(d+UsF?+v{pZ6kz(8SkR_i>#m3blx2;IQJDA;T-TQw>6)( zPn4QBHr)Z_q1x#&Sf$i#U^R5GD_pTe(*?A|t3sPjWwm>ZUUOcdyqvK<98X=<=^-SHvYX)J)r*_&IuNN#}3v$DL zmYbja#oG#O7Pl_ACc1o;1r!s{-UFQSl8nc7ycIstRBe#p zDPpRv=I-vEQW_Cr@)a?hazqf{G)MT|fR~$yrRkY;X_z^ub#1p-#-wU{RkMl=8(OW)HqBoU z=$6c=3FD*}O;T{|eI4md__=QcYg_u}Dh#;Lq3mu(MWek<0L|UlbKA~)*<(HBnDf)d z%n{_fFl&a-;}0zKIyDC^&)}xLtUm-%s-dFC>g=PHFxJ;4E$%FLh6K|}J+9k12g^?S z5adCJ0VFcr<3k0nQOk!mBiyXNZ1?Aljv`}{NRiRK*GYZ^w-}9O9VAr>EIV7ONP*RC8Nb8?}6GxK1T{abIPIk%NOH9R{k2OZM?Y ziQcjS=1#ey7SGW-HRj=zb=QychUu9DhtH5h~y-)qrxAwpG_^C zhxP553Ez@}RuN`p*a@)KrxO?Kbb9 zp*DV?KBUrNsl!gH5f0Mh#cdLqH~RN_4w=eA`K0g5P;6;pP`|oW?l(XUE>ss*6TCG9 zQytyLC#Jm3AW71JljgK^G;AA_{C;^DEmg#Hjb^#9*kWWnUVj%Ls@o(?V}_o zRPK6Nq{Uyag8~=Kp1L7=aHpkfV=_pq=_MA<|EPQFf%Gj2W!4^kvS=!Hg=`g#4!waS zxTc(fJ!4umtc>u!n7sFfr8(ASx5${iD?5_QIG9i~;XMn>%c)r^qRooE*&iX7XKc%i zlEWT<4Kf{GR*;!Hs@Rd7NB7cE2~AN;hqJtf?vA9&sJ@MQ)3nO{tjp;+bwcutt#;)Y z4S(UsNv2-!Cjp^!;_ka1FE|X8&@23u6Li!Y`Yg1}9r=2CT-gA*{94!`rV?A&WnFo1 zi;4-s?if?YnbY5!wIx}1VGXrs>Po7K!KzY0e1vPI->9%2^S~`E`q=a}Ch<0KA}Exb zE3Vcx$obxlz6Kp()#gLc@)4XQ(hMUqqTD%210^7xwNjGuzIrZqz|uE? ztd`0nA>z8GeM^x`=Pt&N%omipe&;~l&@P2!AN^hIy;ZodPdZUTVz13)DF0i zmIn!eHV#NycIUxcEc;o6xZF+Gn~yuQ3!cB$dzx_fUOOgkNhdNN{;UEtXHCjm07Agb zlWzR@xIg0BpN*b}7}=m75@z@i+Ec;tTMulOfmEe8FVEWp0i6tnk?sinrD3xST@Ik~ zP;7?0&lDJ+NHCw7N~)qCkS)Rfwaoe_=X`H=5$1UP`Rs7-LU)nbbYryA0`F=&8`S2kMQG1mXf!dbKFs*As_E2g>)HS}c=s0MbdfO1- ze}2yNME*>|o>m4eKR^C4Pkd%8|C=$avSGeEF>1LM>t>29t4@NAeq*p=C{otP2-)kL)i8w4W#)t7i0 z%vntXohXfB)H&*ZbIxDc7I6ENAhxEuBy`fPfU@5cef{H$MxXpE>=}wen-m>(*Lid% zv-5`++BIn&zxCI&EYt|QuxA74n4yiL7s3M~yR^PjahYb(9;9Cde9H#QL0xcEQ1Q)~ zWvZrz)Ko!d{HoIPxamyNy1kx|junX6OSQf?WQERTtqAOBi?O%j< z)fmV~$MA*J7&^VklV#u6L4Ca%%HUSJK19Kx9g(MZAsBOnJy=0r559&1hk(&N1iR+A z)uC&=AEEQn!lGlST=P0yoalR zYlN^tlAzO4_#hXB^hVHOk$NUNr7?7Fu+Drxqe3&36UuV@MCo;Lj#5@J5V*R^o0;A3 zv(Ic7F;{Za)S5Q#v*++F(26f7!5ZkXK4!`sYy19ap@mo)q_!ENh}J(8s?=z%+O zL{+994K!c4EsnebXhbAP$PX6Vd6H<6B#Z2*{wx+2DZUg5yuDPC;+(vzlcf@#b6Cwc zsH}Ffr@eabdchZXBE%p%GwcfDoq>K$Wdl_vlCZ(?NADN;7VcAnw2E{Yx99i)X!!Tr zjyA)OZ)3_%|H-OezPthIVmInQf#pPjl~fit(4-Dh?dqPcm)jI)$mZg5JO-QZa|j+B ztCo}$47oPE{g{Kmi}O)KV63JzM$t<)^T1I<<6vLDtD+a~s{f8~^W#=CpL8l-I~95H)m@JJ}Eq>^B_ zGaLEpdwv-TXMDOvyb!l_w6DTw?ORr4+_t!#j<*4)Oz-sZmke0o;I}j488&AHke|?k zNrJ`gg8Yij{-O}aMS-V%d4snO_dGG!`r>6;a~(YF2sV|TJS3jQ{2+))E&5k-#G%Jr z5k)F6$CVLgmgFP_WwfXYHZ|qGOt^rk@k4Ez3q=g@kou$vQkyqd=O_a1+F zn@;Hj>9FsGt|eQ#LUuFe?6-!Gk0q1C@cJ=DzY}j@yaH^MJgrU)5bfWDfAuT?;0Mn2 zCvpzK1XC)xcREDx%r}KE8m%@+0R(6o=@=`UK()v45o;yJ#vI$!d{y}9-C+GN^d-7S+6MrM^=B+9d~ z@v?F2VV?3>_U`BI1RAx#pd1kZHVNi3c5LiSK5j~pMnMn|=kradmX+_xsid`1-p3jYa5(8SXDJ^b zcwJqp_Z}IKQcXn!$(t|lt11FcNC7(LiJM#!j6)`=x0hi)yJ9H*VJM>=Nj@FN$Jn!U zbU^mugPy03eh4M!l%NTKx&OD!h>MNE7^uJc6+-_ujM}ewO%d#Q1a-2p_p}dag*o$8 z@s{6H_R0geEfchvjCa_A6<|~%h8(ho??rA=UV6}#DvLSr3uk}O10g&LvKQ&zXyy5l zX(a`XIJr1J2E1Z1s_?|ec%C!@&dTk+sWZtW$IcZo{n3gN z#Ts}1`HsZo8eB`zD5Kd-x?PCJY4n)Gswzab!qF^UlzMg>^xYbj-ZVP-G(3JI$Nt`^ zxu}VJXqt7F>eBmE3k#CH)vr;7_lb;@ylQ*1)U0pwwWFQM?1kJ7MQ`h*ePlaCBD)fv zu@8?zdgbFqI2y0v){S;^##LxWyqHzpR#K^Ou;Q5fevm>S7}sC8mMS0r$V2CoGBQ12 z>_@n4zTmzjRN_#YDA+s`PbzEQF*k~R%Cp&{4*};BWXdWQb$6De6>+~EeNV?NSILix zD-C@FdjNpU!DweCWjF_Ia#+{=?wpq^P+TkC~WEb9C5#XK^#8JwyaH~xU&&@v@(POqtrY zB3|o99!-QXUYutH8`YLrb?x$Z#~8kX2kz~P;*MM%w2bL;v7kLHclE*R9nk5gadi|` z<6Om~br(bY^oqV;1p_FGL(1^ce3K#)3HC|BZ8#EBcu6XZlRGwvt3lX=xkB*hv!i zJR}B#8ooCth~uz_fzvKCgU$6n%dLG8WdCH0dnbG?hzh}SN6h#y6*_lb-&1^NG0f8s zPgI#jWI`*IB-kCOBS0UHhf2geDXurue(-tW)HWj3!)F`X-v)EVuLio6@Jvx+_$5Z1 z2v3z+w;XmvHjtoE&FnC&By5gh*cj-^JcJ*V=wNemwqIA6tpH^0vJ0`SYLLJ9?`%fP z*4N;5Um&D|+c~*fPBPK*hzlF_y|9eq+PoXIl6X{t6*IwxI4Y56RMNWSi_bty%*&d5 zfy&KH`=L&IS9;<5tchDnCMwl#5tX@*Nm(OQ2@mABeQ%PoR!m2S&*zLZ93x+iW zz+Aoy>KE39uwduZE#B!EV~(sDm<0Q`#T>(?n6be;x?#k^kgD=bMJ>>)t687Do{hsR zID%eZ55@Aq#wJz?#)w2b#N*jM5_Q|gqLe7Ww?1GXy&tqW6P9K_Pfw?kBBPL!O-Dz6 z4QpOX(v=KL0XK!v@0P5@l@O-t#|mO86!VF`rO0|M+s0H12>iIJbYx{|X{iM@fj3hV zJ1^L!os8uwP-*&5@da1Zqm;M-mS{mIjm8L`q82Ug-f4CoXMSLi6F?Gf-CaErl+z+S zkE@?s9BU3wAL}|GT?8E#t`C-4>8bZdZZrg4hXagTB)d#Rj$)~$PNv>5&uz6l?XtXd zQeflpwSBo-sXCQTu`Fz=IUmW?sXrN(b)UO%B24%zU^pvLYbQDLV4geukKfQUf3j;3 z*>&$rBIWQ{`$jR9Xk?Buw)E^e2hbAdbl6SvJ9y&iPr(i+Mp%*& zXSw7)v%m-`kBaCal{sCP&PYRhJrDO}BZbWhU~*3Ar7^2OhtHX72F84`tZUlOZmY#n z1;jiRT1{}YFiR^E_W|hnV7MZ>*0LcQGH-5^2s4@wEfx^e?npU4T)Z@VgOON(R>0Yt zM^Hy2lGEX#)VC29JsbxIRbh)#h7#xO5CeF>6ro{TjD$Ure1+R~p2mtJz{IPHt;vDx zrnF?az(Z7rWNjTJiH!}{<$1Jx&r{__iY!J^p;?qODD$9x4{|!v>*!4gj$Gwee>B*=Nbvx91ysMDoLf6kl7~7_rED*+ zqgr`VbM!wxiRAit2;j=mgQ!iq2fp@99Gsp3v{ZKl6}PvM;XRo?9FvP5-!Ig!c^ZD- zEQeSnTAXuji_(5aCk)q&3yB1EqH^b@Py8w5&01 z?|4vK7rBkntG)v*6O4qfomXt)UW^uM6(e({0PL(w zXjj{9=0JVnt z)(a1ldMid2lkkwZmFqLDT1@gdC24ZIBO>wi5}YPoOJr`Ud4hfGF?yaQO(OBP6q5MJ zQs8}rZSUudBSr@sK83MqC>Gf}sh9RKRxyM^bj#S-$CeB|$!8nGWG-CW>uy?P^N(l& z5X*Im6oIDi-eMqvz?AWfhHGGzZ0dLPY7W+A_}$P?K2-eM0i5ahSy(36GAGhUSB ze9q%d-tuXGqTWR{*V&?UOkGMPo`a&`cliqr58*KCRTU{jkvhoIU~ zH6SIxu9`ae#N}^4CSF5tUD&$XAbrRtuqD5maHCZ>f;EZ%qwh^ z2qU(rgU(N%)V*W-rxhQ_?4u8Fpd5~B30Erg{bXa&i61_DCu@~1Kmgk|;!%D{i0}Ia zDgTJ~HzfnppG0Q$vOK{DDADZ$xS>av&{A?HGKIvfHXQUQYw zW_jdt%7W?e@xBKfsoy(7yS-ZJD3s{84!0Uji?m-HyQd9J&hD6QRx{kna!9Lyo2l{S ztL5v4)l^GqY}O#;5hN*~PoRzaM_mC#o9U z$=j?-Ak2R5lJh%!iqMI?+Dg=CE-Y67D77iQtni{7UUJj^q0+-Vjor~8PRpguv!l=J zS0$TgeI1`2VV6Va`x6N$eH~$jZ6a`$u2 zQoLu}oo$i|_aglJZIOqm0W^2NSt1A4a8kScIX+GXr3ZaTeDJ*)^d$|~lBSKiryE$c zxZ-A91>R_kX&a-v+t&>DT+G;;T~RB-Ox#1jV)7j#O*l5t%0&g2I44zYG{#zzA)6+gdZ1;je}}5muX_zySU7 zYE4dOWuPF8M+wT2F7%&s{cQlK41_35UOoM0d~rceV8kIwIa>N7hW~-R8kG?&TkX)W z>85<#lcuVt_bvBFBTBU#d7If5-o;f5s@q&YcR!c;eTnvTV_15saZqAki=6zBcz_0d zNBq3f?2o`}ZV#&3<0XS+^0#%`^}z)6x8|0xq$iOShO6Us7kDYop<`B zkW4xi+=b7#C?-DUusfK}>NlLH>X!aVk4LZL`GR7mh3ZbW)(dFT{zwy-O#r6(B^Ra3itU?GRK#39{532+g{2! z%HJW$GB1N@dgaGV2h~NQgqm@w0RmW2B(}U3a(Sq&#z*vx8F_!l!npPnUMOg^EranE z!+_V4qk(<|$fs{&S*qN33(wQ+c%2jI602^Dt(3}A&WvfY2F?WwJKke2^PDB|QfHZs zff?0&fmhLhii~R` zHo2`>^^RT1)o_|OGbOHDkC~+8;keg%(h!C%AIIjaCIO5$T|zX7=dEl13QnQJ#)VEQ z83+98jaf+3Ya+NeUeF@jo4rUmTM{qcF=r)R&qLx}^zby3I%*pkYdlqLJMDM=n!rO~ z=}b8I=Rc_CYOWoXH)u(+jyxQXwgSd3=V)!(>d&DXF<2A}uXbRm#riXFxOnC4(Xu2i zYXaZt--wNnNkQ4`cD_gFM_#!3_=;_1#u79e39#>UP1IKmCRjp1E zI<$98AFLiT*?;uO*3dal3{c6YqOEGe0R_@UcXlp>eKl$;(t0r>p3FX?t&ON6?8XCu zjmU6L6~Bb^`@(sex!!Z+-Hi=|s*djHM>D!SX4N<6xp3KdvtjItn;NWhO)e$|%lk=; zTscs)`15LF5s(|YS;}{d@GQE02##zwzRQ|LYI)kRDA4;}@wqCzVnCdctCXHM=&?I( zOvP`TlB2VqtW*TiE~5iQFgTz*HrBrjYbh+3!{Za9qa{2z+E-mf_+LOHRl>&yjpM@s zd92|9aRtCKolMI}!>|J~zNJ7MPWLt}A;Eo`O`JkS+u@*jZ}0!)aR_~RH`KMgRtADE zk}1w4-n_WGIo}<{Zao-`*1M&pXwUFX)QgHszC88)tPlhk`U@t43rnR|sOf2-md{pVWZL>-w!r7~ssh3ahV`Hm+Vkfxe*axr zq}b8HE_7>wXML-``6lRA%H?)X&!x*oGlAk;IEJ)T?Y14$W{2Tz10_r;AP9`=sove7 zkZKHV`M&h(%O871tQd1eix0}DQSkphaap=pYgCEhY}=^noiSX1e}1pT0NR->KxFv? zptv*@LiGe=Cjqej@(W~5ELrhhxKb%l5ugV%(Xy0i3I4OF>6o@}rnJtVzxex#FQW+o ze?)4i#Eir9z(!rbap~sR*q9vq;bJ}_MIqU@Z@r8Rkd}qzX8FWwFXQ5$pX1;%_L%4i zKRP6kioS>9`ycU}J*J*Hn$+`0IQ-9BEGu}KpPwH<#ii=FJj769)_<peBEX0t~` zFbK6VLKNPy%s5_Ux9*s9J*47ae~_M5YO$ZUx!8~VAJO;o`vB|o@oB2usiX5>|6bdQ z7w55Oq5<5hO^j@1}NSF)s2 zIuqbK>H$9O)Q5&YUg8<-yBO@h-7}6Xo_fZOK4rk>6B0cs^;O(A%6t9n%#Ei)y6O5EP zk(d43L3oRU4b%#P0hHUT+4hmAB>H%*w`GC zVXwrLfd-qWlE)4h0?0Dc7Rw9>YqtM+&vcHsJ7YTa7T%kX{m~Gu?UiWRZRuZkTIO>G z5kK-%CxQ5nI}g$tFX_MfW2}1LaNyHVFy4(NeMY;=Spnk^!E}aj9y3+JSpPY3pb!iN zAb>)L#lE+?k6myB#7ZqujUbzd;r{-fngc+E|7&-2XmCHHvfi63`}_XKU*Dhw^Y^19 ze^KeiZ3tKQ=WQ13tp2b_r^^^kkd;xlA9X%&rj|>Q5wFf&7T{R}qSlJ(au%7o)loD8 z_CMyeok>1hjz0Gbq`b>k1%G-0OAC-zo^e8(4ENQYT(?&k02kf*ze|LmvOS$C77p^LFYJH3FH&o2FOV;3cs*5u4u8I;nAzoDH&kLd zDz8}l;@SK_LG>J)+fP}3Tf`Uv{b(9Sb%%IpDq7{XYPM8(!tIA)vA~UWXHT z*T8qG87}!f@EQX+W^4qmZ|aZNl1u?LN4de4wAuPP@mtv7Bnts4hCq0RQhFe0pcecO zk1qrPIo@;iqqakWByjC<{GZTV&kMd-17vtU5rnke=j}AIHP8*z8 z18eY|XZKBp(K?`!5R6HRLBVXPCjq2mGT`*gowi|B$ASsQw1L;%G|#u{g^vPM7gmfD z7{GShUMY!CS)qeNbP6{>swMFz0F=00hS6UoYb%n!yP*zTwm22-^ATiKXr$vbdQ@MyTd2VW)@!yoG;DLTV_7fz@W_k&X&)ovpn&#-f%l$OBMsmklq@$*`pPbEK4Uwnjjm7R)D ztX)BSW0MABMXTIiWk=<+6vPOvi7(*p_sf$-|GazFU3jEJCYOXNWZqRaajkSSLof~=9lCvo=sI7a?~ItvWgWr03ogWL<6t`V+pXPp817YVH}1sVtgiim<-0%uq2*cc zqdyP0aZ*4wFQ*aOd9%4ZEFa1!GxOuZ_F|Qb9+;D{_*Ey)JC3yj6nJ(IHZ*2TW(Vz(%72rT~j7O&MM zRxx(FCPQ147ec7`XjZCXDrr_t#>!yF(&pWi;Z}*8_SdYELx()xJ#W}eaQLuQ7wjt(~tUZ^rbZXwd7%Vm?d}L zJ)CM3_1XM`_X8Z!Tw$pmtc3f^d!5o1W{omyFA%5S{L*hLJ_1xv_w88Aib|CvL7%t$ zJoUYif8G089WeySJJ!pSFXSiow&fEM)G-*!hBwha#y7@1`=WdtCCsmIrGr<3_Y&|D zqU(c>7OMz_v$Ay9x{l(sg?>6qH1E z4bx7Te>t}M@l-jAT^Q8k`+*NHceE)Td0QoqJ6}FrDe3m-5%=3*NytCmv(QX&bDHb8 z&S^O^Af?y-+D2X<6kLIa0O610q|Ap~H}pKp>qU%CYr%j|aH6pGr>n+=%yc`1&#rtd zCc$i^+9F)-Lx^qotVVSj?;o4~Y<-N_;a>j3@^v7((mdS^Pu3#34 zM_J$@nGC+)N!I;vceD(fxW0$cavKo;OF>mUg-MJ<>+{n8xFL36jaaB4E!=q%rLLP> ze}!VIj2n*8MtHZ@{^GWXRgsNvD^gkjgHp|GoPSL`LwXbc?{|oKT=2|q z?_$+BQP@P!FI-~Y3}p_zdGG%pngaGONY6Wm-h;B3q!~1E7++}m4faJ)gjd~mRtG!9q&Gf?=Q*x0Djnf0|mhF3sVjRC*#>a=Zk+9*m#_1Hk@ zM8|g&sNmtDROxv5B(yg{Y4?0U@MPVN9vYnHqJ|;a5{;fn)~umNq#Zz;aEz7L$s2RY2>a6Waq(Dh9g#u!m0Oy#ObNOpW^o)zXBLU zT}rVSM^P-~mD?lv3dOf{&uUlOFz9ZE$^8!t3n9~Af)v_n&yudnuH}r>*eQkX+;lQr z+lxOl8Fp~%?}HRXEjMMudvv1i3r-}wMDif`227&@#CpJO`&ZoHsV}VEL)Jvxly-l< zn>PZfAv%AcAHb$wCRD@K;raJdpV(w{PrP!6)qFL4F{X6a%jo@3<7b_HddG{Yzw5wW zl$V_8WmrrEOEu2-%9X^ieKH*p7_8DyXLbsyxj~u)4CqFe^{)wdzk?2Ic55Jc2BM6x z;nKsL{$X+5>(e|hIyxNirvArspIEngY7o0mv}(yp{=PisBk68>fho$734+8`8yl5m zFZ6YPp-!*8tOh!PzjvvJzZ zFn10C&g_tXP>_6apEUIBLlrR}1*yBtwFtcDZ4pry-%4YNP#Y-1D?s~{2^T=BC?^I| z#)1%G^{)gR{(b)XSGCn{AOyIa*E1gn%)5Mc|9&+HG_E5QNQy;G4Q{BNuL+vdgbD5KA_eEF9mFQ$E^ z1JUoh=`->eS}}ipe6AQUwH3+1v>71U6&Ki3qWym> zcmDeD@kq>l%|2tF^|Id4&)czgV2q9}#b z$0`_TP=|ToNjLCkRS;Z?)O&O1#wjasX1`-Q^=5sCUN0#LM~iC)mCtmm3K94}G=}Kp?SDzm7grt2BYbx-%l5-1u`tc%ok2|K0KW)_zj3kNIee#n# z&pEIbs3n3aTX4f4!F6>4z4>~cn1VKFxiAdyt5L((sWUp?{O+sV}tM-;4lR#Kl*ElTu&nWk{jlop)nU}W*qxrQ31z$Hthxql&-9&jj;Td5ABE(DS+IKjR_{7%gq>H#EJxQbdwL#Imbd$%JTPNrB-{>- z<>JFiL@k2>>i*Th3Mj8NW`&zgcO;4?A0FKp`v6dSf9)hvV_YD~`l@PMmm*U!wGfxM zLncnByrg*f4AA4cu0D3Jtty%OU(p)6dwBLjYm51+jR0LR`g}>YLCK+N6+rFiza<>* zT6|UAot~8qsfhFc$K}djQY4`LT~qA3D17@VU6B3aTHehkbBut1 z^I^NYTpa@W7s_AM{APKA9)A+-515PqGIjUP=+J|a1o z-f+yG{>~`sVsM}Awz9BVM(f^YY`E?0jIfC)BF>N_;&xAAU|4?}@`EQ@&z=U1=aMf! zmj3e4eVf)q4Dt|!93Xzjf0!jUJ{MxpHPPAzaDW75_H?FAQ|(hNgBzSLteseQ*q#;B z#R|LC5#lbqIrN2WMruW)WnUJM0I>JKY6%L@+kL(@2eJHx27I4qpXK`hs( zyRJRT7&I$YZ8V?D+p4FZ4L@#oM{az!8fLefWeWjpCp=b!bscY^L$jQ8Bxm`#j&5wv zLzgcf_L0YhZ%a#^KAHXa+Yxx}FoSW>oR?!tO}fA9$9jVNUeNqO z$6!c1Y;7tm61vN479&@qiAbYraIZEY0GWZE!0dup!-`RB9G&#B+e>wvGsDFzmfuO# z@*T_ z3|tYduVOgJeMcT=ll!SW&Ok*~|0DcOYN+@4n0s|{%Z~k%6oMLi6D^pxDnSwV`{+AQ z0is~3rw5`l7Gc*{t(LC|X8k#ajll#Pqg$!@!q2&ORLF8&PT+NDnyqWn{iN+n9H|eP zAFND<&4(~}Mjir!@6bQ}La~D@12wSdCvig3vkwestmec;UpW zcy^A4{{UXH@D;*unyYHF)1hYz;FQv_Lu$6du@6jpTowE%f@-LuC^$4B{rRJxqCecW z!_VAWmqFWfT!XDT93MRpFNzIx==HnQPUhG|w5Y$27A`bs&{bLjeyw%j`M4PX-O`^6 zW8$8C@3rw@7~!-XC%mGO@zBKkB$~2Sr*hDC)i-)RoQo@C*>WN z?43AA3Ao|haDI`CVv*MNXImhj9=Wmm9OJ9I4z}dh*EUHQEh@M}7D^zO*L=5dvmvR` z!u!XDXo|2WV!C`Kktgc0Rx}aB!p8=6c`)E9g~) zZ7uRP=SF)Nsfxu?t@g2tHb!lAeyC*dl?_G6$ApR;3cTL=Rwlxp?d8g4+!8ig8SA-g z1(;0gbLZWz+RsV7IpQ;Q%-2KQmVxJ38wys}tbVae@`=RMmN6&(>Ju*z+x|$BAesia zBAdZF&>V~$uQHBv`9AH!dE&@ED?JV(*Q7~JBy8WOnLe5q73`wN77j=gjZ>Ll8Eqy$ zAwJq^bb3Z&SiB^AK^Ih0Y^Mv8u#ED$I1uKc;@1Nl9Gcpi!?aMz3%b2KXW6}X>9}-rxnfK2ozVH6`vnf!mh0(cKQd%G7aXEiG#pfN zM}90ZKl#v6wQ#*c^LyDjpH!1cCy8sK$L5K}u9cZEUE?7^^Y;e$a##5>OuDUxmu&iK zXZ^`NRe_52J?n@;#Ilpt%1AXU2!}$9<6D^ph~fh6M4jJj5_<|B4B zKbiR$&GArsj9%rA{s&A?Cr8Alt}lDb;C+#4LY&CblC(+p0j$s@al@%SZ!cZkqMf&e zqgPOrc}yDnzJaAqIYW`4K>Mxb1D8D#tyYet7dg^*T5;K z<-mX(@`E}%&|Zs0E;rP^L3@NLa6B#$D92<5{PE57TYGTg7$`blv-zj4uv-i6s*1Tz z{rrIrVjp*&|DE;A+DV`zidx&V+va0QkSRkia&^VI$QhTor7u%ET7jdUu6p18!;)(4 z$hi1qikD!0 zhkHt9nWJ(u=X%u^OF}j5m_B-CKFunYe}7=@w=`CQ6zPlAMUmJETv!$(V6#G&8?et0 zGYlvd05Eend!N4cP;q9e61*=7Cp3`R!NFzxiv;1vGd0YL>7kggt1H!CW`>OldR+4| z{gnfi_NaC$6;}f&1Q7ZP{j$`FPqmF@%i&nD@Ygp!j+K*H?f3ygWBw z+3?~rdnvkJM1trEP43jeu0JQV%Xocy!fKf|0H9tMda{kK6O45ZZpAgmDplAoSQ*t( z^FQ}%i7SyBL-p!{vG#@}?szrd3p`O{!n^h}*pYlkm%~zvW?JL8I$e{tI=RbT>9x?z z(7Gg(b=3_B(~GBYN9Sy)fk}VjYhmk|46Zq|a@%(QV;s+o59VDdA~TKMKvMprnvU;- zF#PV`0{ox$XXFW3!?d(8N;BQLli%fdW%ih4Cm3M+PBvK{8{aLu@=;RhLJeN{i~QJV z8kcUP0M4yN+nOld&k_Br=nFe_YFrDcV-Q}AFp zm*>9Gzs%&mDH|(dKLp~#w3g6sNC|!^RC)>ZQko}v*V$w+DVx8qm-jwlm)msj)jo<0 zEG|Qu0$Rsj8&O#S-M(z6TI4&Nc70d%_ZwQW3%ENZuzD{`_eyG1Yj=qB)~ z23k0<{UcDeDvX{s>ouw3L8nVM;5%q{gg~^iVK2JYzSKGfZdeS}SYqGcS+yJpe#Z$j zs(s=O%}uD^6j!}ESZq>BGvGO(X~b8_gQIIANjCALl*@Z*hd@JsO(E$a=VVxCn(U3% zr<5s#7ydpy=mO8J>c~zZKUoZWz(Em3DqA(zup{9{->W-VB+!R7-y7Vfn^ACb9bHHJ zT#2+B<&TX*c$rjr_V>2yqv3~BsL@$y?+&}|WN3WM0IaRWSuLfnJCx;t?e2K#OriN4 z{$TZjyq)YUa4T3(Jd}>ARwiP(kY$N-60KP zQ_>xhBHbMp-Q6JF-Feqha2)5Gd%yd~aZt~B-@W%*d&RS!XPvl&_7wJ|KtiUnn_*YE zluQ@hhprz>67VN}2R^>m)j~0l! zXbnEa!-ePr!EHR+U|CW*H!E&=G040hE@@p|A*jBpT%3C=XqwgzG6u7c_jf^qq5>Dy z?*1ucn}uGT+NnAF*s8M`b!Po2)BqC2CV0;_js45tCm=zna7Nle zNkkjhGacL06-q`60wz?XD$-nr>#Oij{G40_)H^S5z1^bx8a19f01e??$;=9*t~TPa=~7b{hN2e7))1B@WZC^zlqRs1XgKZqr01J9*ShdtbOD zi$(DWIcGHFOZ6ja43=dyW?e&Fte?tDdDE(r-XxApTls!NZ}-&M1>$Msp^&z2yXM6%;%6yC@mKi zjyu0Vs!Y4n*r)Rh$uD8e=XPhQ#ucpwG6%*mcdE3|3hvUV{lWzbwdD(Yo^smMpoUiOaYdQzLl1-rtoJci>*v( zOmg)NIRiq)@#(fI{lg$ro$@Q;w9E7BN>RJVndm0IiZ9Ik$x0(N{<39;n9dT7YMDQC zowAO-{2Sb=!*f`6m~`_!78P8jbF&>Wiu_4DpE#@?*NNNDV-2?XGaNE$+k@&=j?*ls z-{k4X?Z`&u^s?{WBH!TJhppmLq0|$7FzO0HvEmVHgWRq@8SScXzbwLZIWol-c5xrn zK?{oOv|(?KL}!|^L0}H2!%NW>UCxT+d#(YhH*_i&*X|9*cGB94ar=Ft$CbJZ%Y%>~40gGPb>88JRxf@;%ffqRmZ6ab`VrmTSFt;xx61O21_>he8BFbJ6lz)G;y!s94chX;B+O@& zsTYqI4oY3d^UuqVhPC)OspPj1X{=-BeoPV5_JPs07YZ*CeObi)GR%eKAd6eN_zhHR z;w&abvn;32GbO7)k{h#$X8c%jBZhFkQ)#bn{RX|YEBW0bhg7uHX<>&+uf18zjsBK8 zZEMbkl$Led77F90Ln}U~JytdR;@(n0MWI=)(A2)^k?WVHvWn;uQNQA$q-k4MF=s8l z(vVEHr%viF;vbeW?+P7AH)#ohI&(p}3zgGCOQK6uaTTyDwfK4wt|1*JM%&ua(>Eqe zzH!9Z8~mE@sH~oA=P8(FFv&GNke~fH6D{hJSdWu29k>0V(^jWh6EIwItUs2K&(SPO zIn>G)4rP^Uly@^@kVd~)-`cavZZk#WHLhZ{QS{`houZJiW_FDgdS6f~l|1*pW*K2U zF{_$K$a~}J=19pLxqI0q5Bw6=Q$Cett$bgq$9+ZwX$i@h78T!`mSi0Kk%S8ot zY_PYMmA(>=THER`beTF34jI{Kuk$Li9Z7~|uvL%ZSl0380=9a4Ox@;EwDDA!p4i(O z^)?@_IKUwe2ej{@c7p+QZ&Q}uFuoBv?eVx2H$+Db8v4VaZErK}bN;`Je z73YL*JU%T~D;-o|m7uB|V-zley+V%jbB=dR`CldIP81?QbYMSVXP7Go_Neb{iMf1HW?GEIgCS1j4l%$S~s~nR$m!?LQ2$ zuwCWUP_a-H67q;*?M^BoMTG0L)U&Mbg(RnjyT80TkO?bAz_1xLo1ZdO2XNRj8d#Un z``(_8)pJ`f+UuON^@_XqYM}V+Z6+*z@ksiiOg)W?Hsts^|96ebLo7l&Gq?pXL;FpR zHLatIPSLvio*j(d-$`WDzQ)gxaqbA)T@VYT0YSpzgD{bzIbMqg;LZT?F!>@&Jtl)l zdV?@_tFgdynCocazX7$#!;y$wItw+N?L9V$4nuQe}<6dCxS;nYTot z4pFZo$vGbtuelCWJ!?;@J9ud$ec=)3ao^O%;H0y&bD{NoDD#sltJROYJId;oiT2nj zyZw$A$ngpe9(M{V58k?|C_ilf!20m>i?+_^6epSTl}l$#L_V$vX(nTATFIsXT?+mn zCJdDB4W-z*#RKl>NE^WYI34K7^^g*}EOKGTQF4SV=O8RBn7oxh2R%p;||*|8DS8lo-EvNgI;vXim9$ zy>^Qyv~?F~mb%^6EE6~wXmqKk4DCV*2y|N7@_QlZFXR54*~W+^*cOM(#*VAZFA(L> z;4@0i)ScahA&E&hjhn>IGsz#HLP5@Mtxv(wwt>l#U zWFLwV-7z#kTGv(-n(!jry!Tpc*DFVRrR`oiOs)oaCwOL{eRGHi4W?|sWwh#jl?8NV zNiYsp(wC6PrrN1stN~N%4V@bUcN)$US9$LnHR>&0uHi(jpByY5W{O>rUx-{JNJXTc zfN}(uV@h%{w-qNS2b)R{eUQ*#vQPn_)o1C*`$u;U;^O%lSFxbH8~-T(lQxIYV(h4O z1be>M8lBa)TorO*he3&Mdi{IsZ!=GOU`$hMHZZ~*irE6=VT`StZ>C;6I(tX~1KfhQ zPl&a>RLz$geaV#tln=!>9ILnLr!87@S5LIus*~^3zXD{U{yo|FLLlW93mH;Yp~=U` zEe6f|`!?e}IuSuR5x1A6w!4WIuN`50c)F2@Orf4lX^@-JFtHAUwW23&?-=)=E?-`TvGFA|oYs`evTi{T^VlpE>9!j3g7LP@$qYPSC6>>EH~69t+v^et!)lU(zQlS%EMOKr&x5S zc6~n;$(*8)O_MWN5mR(C54A)eOb=@E744L~*jw3~J9xY9NxOY~(S;k~L!^f7S)8do zCkPr36}T?851^bztH1EH5#@AelB|e(FqMy$tqQjR;W?72wzcmcoLawPptMskTfVGF z?&OK*l1TpKmdU23NA!j49FYGb@&~EsgO7jU74D%Rh6zt$lV${_a;lY*?k%pn=sL+! zL#Mn`?J-`G`1=^((Q6{@qzM0Q$d$Yj6_9k~WMUC?WFnDTLqf7IwhT8=YW&&UA_!U{ z)@R8Y)ZQoSqlgBmID7)!MsVfNViZAT4V(F=cV8>OqePOOx< zML~?N&n^dChipyTsdE*X9Q{MwCOl#vBSI( zDqV`uBiF}NzddZw}8649z&)KWmsKD%Lr5Czfg8n{3n7UQJ5ZULBQ}+4tqo5GK>(-u8 z`8_h9w12+_1A=_4UCog{F^)eqalGe7 zBb1>(2OSpDt72hn**nL64|vvKZ3CBe;c|LZ?9&hFZ~W|pZWwHoR!qMy?+7uy_K0o& zZh;1OdtHh^cFLh&zgz`wd2E8%Np4f)b8(YfJzaOcwfRzQ)U*x8Ra z*V&p@#f?q+gYbiK*llypoV@}M;s+91`+P^t-J+$1@V#AsLZ!Bq?UiD$1h@{<(4E>C ziwvt~P0A>-h<mbk;vLQn0yGSI^#vMckseCNNZ;mW3>i4oq@Fhs=f}};Xy$d zDxt^tRzw4b)Y}CuuC!|#dH1pm2^BF{mbX8H>Wx~goz0TD-mP$s= z?=~r(eC{TcZ8>GI?y5AOjy4_OQ1*eXGsOJTJv-dgp4rP{F6!lhqN!G|uMRc(dD?N4DyHn?VdK zSLZ}K;Sv7nX*~!>L-H3Eg9Kb(_A308yuq&TiCJBuIeACGT*)DR$1E; z>l|jEXnQ5zgM|BfWnWA7mH? zOG2W2X(oUDc|B#P6`w&dOopWmIc}Hi>syRN3$PYEvOkTEadniUSY3-qVw_!&ueoL$ zch-l^A{>32#?Fwfo&CL+QWLw|S6PypYBLodIrkLHe5Xe+-66B_tYLM37T?kug8cK|xo=q1F z_=q>wp2XDpkx!P%Ei$$Qt=DQ{Cl6Q>l=9^2RHtyivENLrn`ne0H%j!hc>z1kko~}* z&!&A|P<*Fk1zXBVcC7AJ%Z+-ryTeTq>1Fzy#LsAr%+_nyEBNA|2%=rd8PTvf*W)t2 zDj48&n=?b|yBt@6<@EDhjzwv`&KNz~q3z{Cb|8w=dai;tN3$jrsYm!uVlQ?kDM~vyDjyPm2NIz$B1>&<$6=cRvGSU`MngA8 zpS^$FKz&p$eEr;|F~e%Um(AcV!z*mn%)o4{QePPH6oOIJI2eqBtd5XcJep^Uz_e39 zZKfU7e8;llD_L2YUdpL^>Q3J>s3Q62+g~n`=IAa5qBqwCFSnde`(D}^QOl_eOt;~h zV%K~u#o~R1q1gB0zRlN?oxUy4R3^6B$o79$bdB{IZk zEmUBabz8k8;MSqe&cE21>e7>yZ`?y2rI`HW(#}=21Rt_8Rfc?%q0GSY0j*F!8d;WX z6l1S&F#xi7S-;$rCTmqbXxL2HN?tc8ESU>tW*XWsDsEtN{7}H(@@(baVN2`m{u6CH z@2_u4l~o7^>!oR&d`s=mvf~W_Bu2FAh!hBi3ySCfc>^?&*L_U6kDr^SS0%!T{Trk z1K%mxQ-MM0XlZw>_Lo{%^ls*;XV^K1=J9Sg9R@{|+b*BXUi9l%#CY6zdHV(j1)(|D zlT*uhAHtOt9M-1pn(y8>c!a!P*|E=P8d%EhAZuXHJ=ORPS9Ux$p>C|P!JhKO5(0nF zgCW?y!^jn(Fc_lz$X9OOEZ{SSf~6G}z#VZA5}JJ8S98g6Vv&gItp`J?7qJZVdSOhR zZ9vFvs5fWEIMBQKWI1qj3x(nYhL{#DmAl0W_*Fa5=rZtDu2E))1!Z^aHUM`}Y5$`{ z`qcP_yXlH`#@BA&vl^{xyeVrSu3EU#RQyp!ay#L6U(+m0C=^IAcu)2F%5An;Rx7B; z0vbk-N2Pg9DLMpYRiO^;Xpo$Td;-OiQYqqO6HrYXCP{9iVOFm$qi>OrTBJs6|5ol- zR~a@iU_MPE*4ADmlC6u~Tny;2kaME5U9VIK=pz$~KeetK+=F{CwAIXtOkzZL(|@?}e~wL;?)%vjm4^dN!Bh z#iZGS(?6kLV&}KU{0M*G9eX-r>5BvIn5ZPFmY4OIPt@zxKDD)#A0l8pJ9WOEm(hy$ zX>;_a*3#YBka*5GgO*m$NtK4H28l)lSay9yW7yO~F&XG~m`b*3liAf`OxA)sb7Iwp z7+UXWw_64CJ`;{7eJ1=$^Imp1Mxu99bc8*8a%4z$yv;@?^h9YFn(RAnr~N+t#aq-e zyM%?(2h{SLHKHM1>!)ljB&Bg3F2+AJ1wj6TWS7~)kFo3ck6*e>qNgZj%6RRs=MQ8? zb+K`i7(|`U8eJq?*3;jd<3c1!M*0dn<2EtKvUCb8EN-gBHYD%z6|I;)S+ctg);Cp# z-b*FV$68+ko}te3IkM1saSoshvxX7Qu=y2s@~$KcgBn%x{M@gzMueQ^&uD|o>%-Gk zVtsRS_!Ns%k|Q8{>vnVMN%@qA>m0>+@8wQh3Vmj>0PN)jF zUb^T{VMWv2{ro-%b*GQ@A-FdU;ycB^5`ATmnkcN6u9OB(<$~!79pEsEgxjaZke862 zElc+70#MM#3{U zxuQ)qBV62J_i3t(1M|7gJ}sy;3!qO;&hCG4;lbo}0^Iad&RmyQi}rPq)>NidWg<<2 zn*e08AYEE#VLo1ug~%xgWfz5*+=l#6Tkndl0u{KoJOb#uhi1B4Kpl;&Q}lvr+V4G8 z>hNu>euc>k^+DtuK|-H^AE{?qyGg+?Qh%Vt_SIB^SPXEcerkVz&ytCYkWQ~H9$hxV z6;mXVRSM{_$V~&MRRIkS0z*i0 zcSEqWmrfYk;G>7ZpK7zl1qJg-KOyg1zT~X(y~vInMeoy+zj->uczxOIP~);uuVLj! zsbW#z8>Q)fVWZ?QGU>}|)~^z2Gc?GpInZQJqU;;mVNgfhS^p-@_rP#>YwP*;>hO%h z3KEKFBnLH(jA1sLid|+xNf+mqGqLqa>)*=tKjD<*l1TO`uT)6%;+dtwxisx&6QW?~ zZ^&nUP2r=k8MVxu{N2U+kkyrS+2py=RxLqR)am_|)rY%EJvcJarWdZOzRw|9%KJvN z*!D`DdEaq_tcAjq8TIUq_FE+>@=Re4B&SlKq}PMpMCN7oRd%+^pP)AIg0eEN+ZqNz z4MXniDzsQ}H$*yCw zw)DslOaDHxw68KB5Ax^g1Ki45pcF$u^G&3N?=~yWA*1 z+pYO*)zY>vn%YdA%;5anoKD_i!Z;q+y;hhJh~{J6P;&)gX!&g5bS$!(wKHXiO*i;9 zGZvUjw)jqnD!srttqcdcyaPDQjc+luf-Zoq&KbdDvkWf=jaW>F1WJ{0YSZZL4qa(0bd2s zu`y=8-9pNwt8jjiN!Pf~aetU%mb#m$v)#%|mZ&i#Iyl-yBj?Mlf3RluyQm7e8h0W@F?~jaDr`Xe~cH(X^<0dqdo9 zc4ouz9+v^}l4)a})~m7hPwv+5B1dKN(*}LoWDb&$3C61{oyVGA`oS69a84S7g4f(= z^@8s3P$0#r@mJJ+^>elgV(v*D@fGepyeX2%>z0K5mOTzyp z?!>wiUvOwfVczyZGT=O0Y6Y~G`G#!`YUHtUEaHHe(p?sbp(cbzEs*(9S=r3_R3K}c zS(C@zOQ@s1ZTOhV)W>vjcDS$k2`98<^0jty*jB#v$4~S^U|sz&0547_{VaWu7uGzQ zKuV%E^SeeL(I|EU?Y*{;-AiJnGi(vc>0!*-vJZ4-+wSEu5IE96ATm|(Lf161GgWAE zW&?O>!V)z%7w=v}lsv{Q3%zannD1m~W04FB<#-phf9o*l8sCqc|3WgRJLG>H!2kV_ zsEhNEeYE0`Q%ttT6L?3y7I1rItbxKy`kK?BW6(g>gEyZ^^SW-8E+qh;Z4J;Tx^uaN z-Qph(kM#lxUsmg@`*sI=d@Xp4x0!XfboW;ChK#o7+FocIiZ$si4K88t7AW1~-DTFA zF(uSR6`ygdh53kpFP(06jyqP2GyzlVEfIP9I#FL0sGl952V4YGlipBS>0Ix+E}PvW zGT=JCK2W^*4jNjub2BD{?N#p3!fwBvh>F>kq1@8*T)o&PWXMhC zLDhG+#@M%SX#2hVLetAMgIZP=-UiU_ZI^x5J~J(bMcL#4&q4sxpy zA@?(U=Bh4+e)EuYq0R$#o%EEb+&-?T;(9;HVjIGmHR0~$*(7gJ`^(nE59!;sFSOf8 zkf*d+fBu-VTrNU~w9dTLTBrLSc_ha3{q+5(7`*xCOevaY=CxN8zVuR7(=ORMhBD<) zu_rcNA}M(4zu5*5LO`0`s%tz;$l6FtvAZ9t`rwW-T8w%;R%CTu>@CcW3P+8#6;J=I&6I3r2+3Y$5|JFzj4Es7yqf=;R{t0(j@dar|SRoxVYmbmRW@@6Hy%6ujs8 z3yb>~_B)$CmDv<$GYxSr2yYCeIEG#D?l0?%^cW|LN^??6etWV`_PXAX!O$RCoX+N_ zhs!ac`zA}xkswhQdQnk&pO8Hzs5IEbeCZOpa#pX(hdWje-^B^8Kla%Dw(*AgvIXD1 zXnS9k;)c_1X-huUKqPD4eD;xwciQ>x0<&0P*t!oxU2!C>O(0Gl-W6ZBs}NbigaV1N zF-;@!6;I+>8@ue@DMu-)py;T(U+v|Xi-Rt#KkZ);baRLy^`@uVjJSib*6v};_Esm5 z!04N)ZEY!e5>tYMrG@=o-@$6jgofaO?MkRbbfT9;7Yn9}tDpqcnbr;O1Q`iDtc|Tb zkskJW7sD{Kior!Ou02Wf0H;B&zNkEI7^P)ZcDcfth--0z2K|F-4yRq%%deMI%NzZPj62Zk%WPBAtz6schd|?#FSEfTU7dYu_M0ipI=P zK@)!(ewK>#r>ny8r|lI(!X8K{PgJ6R}nIKYuhX z?TVKK+`KVevT-_bAK$*O@W71qLU_C+0>Ge{_8dsM+b*M;lAWESQ{VB=h4TBAn#fNuZ=7%x+*M~#}1Yt~gF6f#6b2AVdwDh{-wa>n$WP-e8 z+>}ry6NTV~fPiEj_n`cs@U8Vb0>;H1voz@!d>$u(=*F9pm6bXM0UkFZ$!MO)YCR)P zgFM>SLte*9(slb1YNG`X`Rl#_v#^}$RR zcJm5K!%LVVl1&ME-n_R*IO;p7*g#& zxZG$~EMWZ_A1j-0cU_6qIovzx?QZ**7WbWaMJ4BDnRKUhD(l!kV;kavCV+E_ZBVs{y^-F7<)?zoB7v^l3U|QF{HFVKO$IS zIKrm4ZmuUgH*I&9016mffq(?kwMA+=AI;OW-)J*YGR?)De?1q?&tTTicH=)--ao7{^Za$`kIyf$n)39qkdyNOr{85rfm&8j zj$Ucl3F*Rg;Sk$<1e?}B{`H?fF>6G>6nLmj4u&<1 ze*~|8#InGT;D%~ER7RI1$%)6ugEyIUg%kfM;JxX6g3oS(O?K_CxygS9!$+T2fsAsn zzxfi_0(!4s#lljioMFj7T4r)J`jcaEJA=>G3Ta(RK8rdm$#Z{iH17St)(# z{$m3xkdP2MB2dtLL|AjMKP2@1GsC05mfHeDJWi)^^3Z&^)LUVi@;k zeCBovyKjYo@2^iv+t}Y$3OonX=63An zf3Z@O=eG`akw+F)Zwq>RlkD=TI4pm=ZhQXdU#dAF4yN;2!vCEgpd&aeXaF$y zy0uN!nUlIFOUv7r%Js-hJ8`1uy8{rQ{)nH38I#qluoDPgy@yO?+lSQsT% zt{qzvJ2(OPNhQYf|L5+3Nb!X&FpxO)Zz~dZ))V#e2!5ZxPC`Z?oP-}$8Yb43-4z)>3{AB;q$+FrvlfC1QAvK^_h;GNGRLZfPVQ{ zh)(2Reojpp);-1En2_-Qwm_aM=qak@qA(B{Pr?Zd1pvE~1{vOfK&oTAH^79WHNRRn z^~ZtyPyee#yEL5`CAhz{o)f#Xvr`L71mC*u#Q*hSvxpDdx2Qk;Uz}5=YZ;(?Vms>j zvbP062;6tZuIoWVT-C9jWh51kPvm5T#lycdNBqYVGK}I1&;da|N)vs$M3DaDa*GTi z2%2OD1=1hy!NKoxh`AK)*C761JXrYEjHk<2^g8E^QkS7kSM$w1DCg4g8GjlHha%FZ zk?=24nSb3(7i83lrYI^p#k^*P`ruo!z_@*{?%c7<(gB;E44I6O_}^Jie*AS-9<|OC z`PMum;?#H`FRq(z)5-nokx_I(KCMN4JuK)OK!{?BsZ|pZ+t*jxBpjujNaK0A5*w%RW1l`ZSJxuOe z)5p z2L3#LCfGk$6bz-qNiqp+e3TIy)9F@$LbK72B}@08EU%25f9OEc^OF^C8$nO=PNmdN z|5R-VQ{vuQn*`k>7Z*I#w20lhw_ntS!IQX1q4rN$=jSiJsLNH%pU2K^{CV75?w(%S z9y_b!%Jq-)k>?qm);8mqY@C^812f$r&jpgFTLpb6k?v3TEPD^4mVaGQv4EOJMWpT^0EshI1r(6|KLX<@9LAJsG!{;~X0=nrf>Ig7%R(D1w)i}-w0 zICdK7|GbKRJ1c6pT!HkNAF{L@3D1kSgz@Q>etn5)JkQ|)Sv7!Cb9nJ-WP~>s1`>}S z08V!>#4hdvmG`zYiZ>r{${`+1?A)+plT_pF(f?o&;a6|ktzAr#O)u+w3c_VtUtX^N zvS8WMpe~^J>{+GmE4%RkS94*IeEB6!82X|n}KmFP^c-u3{B$dm3IeK(3 zQg=@J;-@3)qd~D-o1*;m=~M4}zz}QhT^5`_jYCTg7#yYSMQ9SaxlI8)1!<)col>l#4STYHz1x~jCyz%Y+Twdum~SV`r!(+`)*DkmL;v&{JZ-8X z!9?$s(z`aedyC_$io^>C+?XE~7}e2AtC3~c)-PpG^T`No*`4pBeW9Y#U&!{|H^+r% z53!myZM7rm}7o4nxUlpqIoYDVihR=tjo@d!x=Q3ScW z{rf?X5CGYmL=K-9w|=dAN#8+a8y?-ddVF5s;n9?+g_f;(i6P#IcVj}Ld40@ecXr~S|Mm+v4G}#o*R9jt zLz@c^BKX>A7wscgwl73k)N%c3%-0^cAeBC!$~1Y-15D4?Acuz~B=+%b2)iTHmzS#5 z7;gK}3-70IK7XUR$Vv#vYeCP)AYD2DL=*JbXi&;1uYVXRDz;V8+jB0rZN%fWGC7%D zzGz!(wYe2Z6(m!V)Yq;p8X&pQj~TR^cX$QgYG~IW-}uqbZHMOSu^1W}R0S&!Sr3ax_eQ@Tl_ZgwVx!5gypO-gx0NMxiGGT?% z%5KgZda7x~20EdLtJsw6WLj}?Q{hu3v5_AJn8=>~cFwow?fex6n`<2Ax~gLOVV6bl z#zU+mr2Rq+4=rLB2vYI!vJv(sgMV{(H!{(IOMaWVy8Gz9_;taX=2iebisxshv$HEepvh>8FecB!G zrgNj_k>L8hZ|?rXDILd@PoG!7`8%YkRb-g$O!WgQB!{_z)rkfw5bN?Dcu9pzdDCjf zvd^}F7J(dU5r1`de(r@G97mSppkV2m>*4+)R^Pngdd~_H5>dCYees$=@e0TBMTtWN z>BPv_Z5%djYMDav&p%d(pPCU70*aFvLC zSO<9P?-|H9{UX0y*XR%j1`4g#I2@xs?9SY=>RBTyj=@-NYncfYyGm?zd3$g)HIb+dI=^|W^ABSOuMphFe}@tlDXtwN4Cs8+-uoiz@r=!c#&S+=W` zMoaU3`G{I&=da~;amj`V%p#C>{_nJzzu7~u;P7m^jgTi1^XR}N$o^E?t6B>e@Bri1 zSm`Fa0hUPcl8*-oaoq9O2}LX9c4^Ia()C8)wVt~$Zav+LcD$P|E^dh8?ak{AfBNsA z@dzCBU|BVgIBG4iRVzWO5Vl)Zx0n)zEXog3H+>_grF+~VcTCa{HzdM=opFT@WHm%A zIiIY7TA6D{_u0`OA^tp^4zlR%7kajgIUkm*hiAlTOALQ!47B-<`GWw~6w}fYW z31?d!TklHNqXQe0fjQ&kqgP9z6Ng*^G%8-PRD+bfka)8kq!`D>S#TdJr?S^A{>FRu z`$;(|h5kX_dS$EzH<618zN#R+Xc=mH--gNytUciMKsm+!=uEmWqau`R?%FK0qjhEL zFo1fO|8Fm*L;)|B9LM$#)zsr{bD>80{N;;LzOd1iDlZauD`!Gaa21WogsnH+evZ4AuE~t+W4haE7xlM^eIb+hjCJ$uCym{$2slWy=f&o z3uq*`s2p4&NUjBVQ4TWJ#ijSaz99F@If2*1hjh7P)k{^Z+clKk@R7qS1Aq}in5dJt?R5cY>NK$KUhUVMQqK!?GjV7CUS>az>Bng?BLEH7f=jF!s(ohdA6i=BwEec%*An3C-y}6<{;MlG zugo(rm}fC*lk1dY*dque_etYdp25Z6t^LFR_gt-%7$*hLIJ2nB^h@y!tYjz`ZzxQH zp_X_M-;p`m;owK0GOE7v1)E!!^+K0YO%dl@bCDg9VhsHGAf7RDFm zojk7nk-w{kONn9yeR%2E$^3N$kA9a1W-kwT(%WZKFjm{?j6vtvWK1qI%_S--3a&U_ zMx92(Gb=;RhXH6dp+DR=?iV5U8Z#*gxauG{`Xv7=MH3=~vP9}qFqHv-ivNrfEUr18@nLeWqO zW^~v(ZPZN6k`lyXRA3eJ@;<^!u05-O8W<=B_^v>RrT0iRM>i9+M}Bv)3$$>l+>IjH zITjiCYi*ByH;m&73S)v$&(SqnpK6gRvRQl&-zvpZiVrZsG%VmV-fqn|Av?Azc2^Ky z=riV1RRH7w_IxyuLHa%P9Q@6@x)g(HPcG=ZKKR#o;2OW${*F~^nzCZ5CwOZn!59s_mTo{ zuJg9-0oAXc9B=jUB{p(31DMbIzU|rdra>Pf2rL<~H54};cg`d!7w5fvuiYkM1sBUK?i{#`iRVF09_eovq}dQ z+bkZx-leMuGIhnvDtLts+rBN)pyQaLTs){!pmRn*vy$9R4yDDB5L;WBP_seO=9V5`147(}cqaM5>Ttg-L|Q_QdY z8?vb$M2~ZqFz)d8@A`F7B2KNf>+rAuqjtTnh{jm8L~9J65Ev|v5(=<@kdryFiuY-O zC>f&Pa%9IicU;rUdM`u5;tvkAultsA(OQ<%{zGc{thnQf1h}S*XAmmLu)2Gk{LN4O zZe2^Jz+TB4|HykG^u9MKXT0Ja&O{?n9H2$z+KMi>oLNiDTi@GWjf1=S$QhDbBY`eW zZiBg^A|$L&<`6k9F^eG%5LEmsq=V!Q9=OXCb4tQf$7%iFUKehU_eeAMouP7&(~_^> zp#UKYxGfz1*A-jKWI%T%l0yk>*)(L1w^fef5e}7McZRZea5vXN1;P`H2`;XvdyC^i z?iY`fd$27Ugl)xV*BoWX|Gbp3aakRQ&LP30AOz?2Mb@EW z4V9{dqXYv8<@1eGZ|jPye*XN~11n3jrsbW_(_=0G^{{)3nACC^(Z4TxC}Pp?#(Mli zJ?UuWmvCIcKD&(rWQB;0AW5Zw*!Zcvy@4$f$|Z`W?aA3V-4=BPi-yoriXn&WM@I`V z1v=G543RyOE{GwBQiRCh5(KS23}xN4kj(>{>DZcFq`|(j zXF{};j(_q;805l-iYS!pKa8xdql!wwu}W6NM^T~}UQ|`mZU~JfSpZBJKvPQ2GG739 zvZRZ!2`CeX>7#v&c4|v#Sow^}063y!!>Oo+`$K+vj*;c~Cx1Ay3U#C}udw}+q_{gD zG9&INP<%$5GCZV{Cr_Tga9ieXJNPdesQh&O2&rADFlgno; zi1To?c@;B=Z`?n_#C80WKfmz`LW(lzGB27zEFv*QLCZs2=>?L}7L)X?#WrN~@1Qmn z09m>IkL|4RLxIxQb%65e^MVw0kP)h#;)4Ok@Sl|~*uJIPV89&n9!x6#_KnYx;AZvR z9Gs0?FVSgIX-!qMLHI27(`N`7ANS_8xUT>~J^LTxGa-?;fMAIse#&SvU2K58V94k3Zqck z_JIHa;U8^qP6JqKye_D#2-ZUuRQj5JW)fV;-;hC7M9vsLKLIsrhA36S@i1O1nO#pXh=o=BgFCZpfxxhos==rR#!+0#fw& z@jU4c+ZfRCV!>ETF@1(>dqyc)U<|k7JG5`ckz^c(G=#BL9==hDOZ-T2RlC`JuNE3y z;e-URzaEpWfFp33MfthEg$sC}en_+Ze$e>~c(S!k>Hyf2`%(r(Gyr;r`1*oaMBbF5 zkgMR}Kswkw1so)SP$nqSu$jh%m%}k}1)C4t9JH71D~Hkv1Z_FjP9iPi3@eCmG z3DY4qxN>cYB4mos4!ijC|AJb(0@C6B5c=p}h;qo11o0C@&C68hr1RlOmg#r(RCg-T z@OR+;e>&)j6eOtx;Xrz2c7uU*1z@#PEtfdDIewVe>uYvCD&}M+%YwewY752xKa26Y zyrMhv9*lCLq`CsqgC8ae5T{xj=k)2*@1lY0LAHE*f>^IR!}Vt%Tu+H}{yeR6aap=m zvEBO23fyRjzmI+nmf`+dH^E7i`s+u_5D*N@@R6n|jz0l!CJE{Pb9j~sg1Ma|9iaM{ ziYP1#si|Rt|8WUH0d3Gg0Ue8zWM!XpV73v-arb7=g_Jiyg^(W5=ctPX8zaa!7Akuhqfx1 zv}C7WowD?`^XZwm|A*IFCfHgiUW`*IEmA<%-za(VMT(Qx&v#(~zeD8j~8*KQR``>2GgcpCm| zE}>@UDwT*(O^DAidz>OCz;*ESBjTknkf7y`=*{T!O5~Rg{10Q_9oA&lyuG4`f*k>s zswjvwl`2(N5flLh=~cndLFp|-L_k15dN0z8fDn2MDuVQ01B5Cygc1@UB>A0yyYKG4 z?|#?!U*dJiljoc{bMCq4o*6*Z?;Fpk6311u_h9&`{E|l6eOm>ydDUN-cMn0Hss$LM zyZXbwP7!)pd|OK^hSEV#@?kK`trwvBc?xZvUtM74eHq;BKxxzxDEPDI7!XejG=-2; z_hFv%>2uO<5m*e_YakH-&(>7Az`sx(uWz@3`}e!mw|#o+Y&$E z(0`qu{Y&4a2E1tqep36de(7(3mix$|!=mBfoDJvzO=TV!EUp4hyph}i0Oqto_#;|^ zAXN#-1=Q@PxV#$9f@EO~U~wNW{l4+j>!v$S@2^X{Y67nOB&!C-|Mh-*|90Z+?_cxfZ>Uw6c|+oJ84|{ab*~; z3&QK{{aw_gJ;o-b0GQug)?%gjvYU>J!he0iQ|{mepWA+q`qvjcdP=LxAqUhlC|N!O z#Os-J=O}*}q%1)t_dB+ndm40!GYE1-Twqr|9oo09ngpFn`-UO(g@q}3&JG~RF7Y$e>~+< zQvZgU4uFztabLjvt}DV06sH5WDB)sPp`oGfv(KKAJD?w9t312X%f?BwKS}phaSB9S zi4ZdS7YnU-q=J!LpX?F?&1tZBL4iO<{=F<0N3qS=VahD$`=`$h={aG>f2GCbX(?(U zaQyN_av)X5X)pXml|+$w-3~SQZ<*JBfH1HN(C8)#OhsVU1!{sP1E02^*3@immQWag z&_i|GkV2E@_21LqD*$471_12+i1y{%+kl<6hR+5K#w~WIal^+fF8vu=fE4T&zrxq! z=KmHz-{!dBbxr+RGe~QGl!m`(6@B942Jq7J6N;RZ20VfEG zBWm{EBbAatY6gL8DR+T>H5bsY-QK_c*BIsp^79VSsPs5t1~CVL5IB2(fA{|;7=$M0 z7W^vxmy+Z^5BlSi7x~cPWAlPQ)jS{tl<8MMjpkmK<`n!j0`}_Yas5o|m%CenI9-&* z{yPR!f!kM(OXWm2?!xtnyXVDUe)!u16DSXar(gNwo&U3gd!Op3slg;}0prH^11yx0 z+<-javzk>C3JC)$Bl4`l7*&C76!{lxdE1JTX3_)~OF-E+D3;EEkq`VLEB60j5m?h( z1K|UIywRVl{p-mg43rLXH3S=O>s^p<2>;oBaPMR_7*L|8RJKs2P1}6XGA~r^6D8XL zijMGO!8ff(gsrPT-t|)iS=W7#zfW<1zya{nH9Y+Pmc3=;J~g&%U_DY23ACZ^3DgJg z*LPD{h)Rp(8O(rWxc?azDW3hzGsk@|=kWy&kPq!jVh2$j+P*6KZ%Y{rma^kjhWfuP zrSYL)c3A-iUX89s-O|OSo36#4lG4@(fhoQVzil>u6O0i|C{qbx8=LJ_8Qf<`C!SEI zi8g~Wni4Ef$^8oJ{tUtjc0|mol7y?olZm zlT^B8R^fn5vOHe9cApar^1|%8yOujO;#IvDQPW5ByUE3~E{`DH}K# z{a;w?kK0g@?yTU7;N;|F<2ki-g^PfnViFYeBwD3>egibmb!1YCN!xr@saEj}FGcmY z@1sj>#vTGWbk?0mG1s4rL-Epob=?yl2Rs$0JdA_)_w>)#|MRPs>O|?_wN?-SWCo#; zw)h9W$IkCrfw+bdnRM_8?K8TwKjwzKy8ytC(E&LCMu6F=td9XX$a;q)>t8+hYfDPH zKS)UaPlog#hRSy(MSuj`?AIKL0mF-mYP#U1WrS{>YhW z<5Nds?og=Lx4r_sRc>H#dyZaZ>YgEXo-rF(=102U%@&;p5u(E1Q$(*{TT*-Ixr+z; zzWxz!TjqV>KnT4HrnXGAV3e0l%;xZagT?{+m|OO~?=Og`G7kaTIb9=vWX}>31W%nh z#c}73aRxYtjbG|WJC^3%sg-SslBgd=XT-elDB|r7;+& z9#DI2X%JH^Tf%+h4By1`G-n{A(u0?h!eD^?QBarqwb$3Gc@4KbthhcWXw+PE+|R8^`%0@_bn-v|9!231R)^d?tuJ4wqt>2;doD`lJ1@z70}O*Rt6?W zI6eeHhZ&1QbJ!IyoK}?LeM60}*igxmT%>FyKZ{V=aGYXG`h7_*^O5UpGVGpEv`}wCUPup1aTDzztZ$Q<HIE4hvx;S`VWI_&0v? z@8y+1dhO%KR?sc#CLkCL(&$+w>x|={2KSLjK$w|xC&l091qH;*X9UMSBcix zy$N|RH;fn<35^QS2J)4o%h8(9Vg`8tZK zmKx|*DDw13px-~22og+DEK)97>p$BqXSDp|>!Yk&r^*iM0t(>;bxU-f?QqeJ>xa(V z<+vM+?XgOgVSf1>>uoHfJ(1^1FtPs;%x(JvAnH?TVBdm5egE2${15lF@4ac61g_#& z#(Ft$D@5h6%MbP!##k=_q5>kwTFUPwr@Q21EONaEAs!?(RvZ8(Uk#_4iD4UAVa+R zj>4QQkCf^HBEwqB9=PErLW?=NsNy{fzO2U~B_-8pDVw_q8g7jgk}vNnlu(SkBDo%o z)FV3~;J=5A>Vv7Oqr_v~vVd!TTMr`nS#VW#%krBZ&k^g#rMINXffSb(x zIIV-fA9R5q;O@Pr0CmGJDtKug5R|it&Jw>8lwMm$U!u7^ZI%HY_><|~0#WdiE$Q@4 zkQxB^H)&eQe6P~uADD^q^?C-SPU{}e_`*<8nge>IJ!1M}?-34;9#Bt8;4JpJ*2pSi zVX_~&{MCAt&w^L+uMqyvWSze+VT{~F6MKjPkg}Dm4CJaS0-ead@839@J&f)9VAuTPDd3#r5j3$S$ zLoC>!!NXm}FX)CV?X&(0eD=)xB_%)(7R!+PH}vzA>K5o!xf2iY`Ea={V($-Z&{1qK z3B)DV9O}7G!_=}!e{B1Ieq%7D5U41rwPn4g$nJ)5gKUtWnKUbaNcg%>=4)gEQRg(AeU$096 zkQ*eA<#kKr^|&mLhjstm&TTGFh|0PB|5p)--%U}9A1DS%)_h7D_d$}B>mGQ~QmOCk zRO!nHG&&GOL;*pB{6F_p{2nNKxn!f3?mP>L*>#^QAbuRs-uE~_lOvP-zce}WbdF`Uh+YZTc-LraK3@84m6aB+vUf(?=YCFzH;TlH( zu~c~ssO9$Y(P;_{$d;eEa{2N-Fqiezt?v?la}uWnz2*ywuD-Yn+0ur9H{yoa!NTM)U^a5qo zK4Z1qi+hDGE&)LJon)7Jp8IbASWR44>Z$@{`efwHY92Sk?0a{u0#R>K!y2 z-GUXv$j*P@bgza}Kv4cX+a8oF0ZsBa{*0O|t|^#O)B}YF53kqd$4cVA&eow3?`93Q zzHPo6O34=ltD><^V#T+_L|f zKpBwzOAKLTaKKUeo^-{E&A7b+C}pl60lP2Ov>nvxYG)oguB2Y!B*do?H)us|)6Ku& z5w1u}f3`|api6D~@prdt(F^9Nd0#n72f6FDuVYa_wZGAf6%;=Fw_gTsep4?h>h)GM zatEWU{w3&I-yXZl#vl&nW?xoGda5W(_JACvt4`bJunx8Hq;Pdru68Otu#7kIU0V4m z<%b0Wvp?~JgRnHm899~-9qf9*YcwVi*xs!i4=G#+8kFiSJqeOa+M!Q=f=}u^gU$6V%kC-ND z9Bx`pVc~vxpX*t#3st@rj!C-DKoF!EEA|n<`Y#=gAwoM(54N#(`@#*+uSu&25NFi! zC7lV^GDa(z1n|~mIljd@{GiQP@DVgDODXhGO>Nk@%FCc`&CPw7B;2(AKA#+lq0gtq z?w1sN&i%t|atmb}!F~T%t6qI zDQB>v;4;%ym(W6!w@NEvpKX?^6hDD$*7Wq@qpTJeW$(_~Ra~&Ye9N-0Q+@7;7Xy|p&1Im5k z^#6z!_O=E>e}s-M9N-kQG38`1O>1}~Xy0N$z0!rMN1*v_Dq6vitrr{KZY3 zQm+T@J?x%PvW-J!_87PK>r(0!6he>&#~$TP0}F6UDYx+%_Ux`g)hW#!2YYYa$u6^N zKU1PMh#9NqUaZLNS?2=2y?n1gwJ7mD%d+l6I5+uS1j8_#AUXWm zGk%wdKh951zg?@Lx9R4pYUm=f0y>c!gkf;RQ!kndojomK(s~uErV(=rU_V_C1+zJh zZN6}RTO`TfZ$fn;NDl&Qp7Q_Kt&mOni+%&1yZk;GFINSmwL5!N;;yLGqc;@{DMa| z0Dl`M_fai%nJKiwVIB!H}}q|`q^DBh54}ln;s^Vp-q`Z?M24i z_cn#f6iK_4vx9~(*wjzKx)>$ZtOuJ7=po7?t!_u0lE(cbtMt;R9<*#qfBZ2zm1S|z zQ00DeC}q)EE>aYDJ;g6l_zY@>%me^qu7~i{2jv0+oic<^q0WshATBZa9x!{;W%V(L z`~!tfOy01z8Lm--bn5X@<^XC#f?tjDYJ7@hXqAora@QTCs~Jfd=7b`q4)b91LS#}&rD8JT)wJO)C+yo-ZB&A@p#W{3zrlOS-c&I1 z7X0okrEQbT`b$awYgNl*_Az>8`u1*FYIF;u86r=?&7kT9ex`!=;p4O3CwJl<4i#Z= z9|e_v^wc3|+Mh&bJXR-O*vgPCP}~|DVj7TR5gFUap^RO*cQyCO%LkqOcC%R2nR9wd zJtl4~E&^4N@i3oeY*ccyY_#pe^{lXm2!7iKEhRju$Osmy%rg^J1n=HiMoNYkT%WB7 zFbUB;@@5XwVae+Z?9#-2s@&J;fp%RS8*zK?1p(!3MRp2ik+Hz8{|Kd78YJ)Nwh}TQ zUA$!v5h~LywX1#4EZP4qxde=C7Am&KXW6YRQ^$(f`R3c=&BuwEy0;@P%nzoW0$!N#G$+{Hoji@l~n44dC!rh=BTD63>^C06cPwL09l zL}`12`^S>cW!)8XOACJb=_!{op#d@tb%%X8fp$9|?^$e@S@ZOI;pzBSv%8gGFzmXX z`yjJu?iE2Mf1OcwleT?+m3`}X^>y3sl$Nk`RRrxc5P&df|veP*6Mchlr^ zK8L3d+TQ6MNTM|f6N44y`*)upAs&Ly#8!Un;ze7QFpSZI5<7}#3NPazkTL__XcZzu zG#45v%BHWqyEJHAsN9Y6z^)NJ*`a5R$7;b*bM-lg?HY@2N zkLyOA8QC|{E%jb=D%qMp?BX|}kjH&*;o$#@!nLc(?E5j7TRs2`X0}_=h==?gWT5NK| z^@b+S<+zxSEv>dyHN8r_#+ck#|6G0}>$DW7f!;|E(r$9u*Ln_ujnX*n^#YY$0!HZx zeCPWM9yMI#IkA%`PexnoIybAxvWC-_`JV)hGr7s*H9Y5q(!*=E?VCYkvPfD6MgI_$ zUBU2`@lusOku-<0=Hp3EM=S71jJ1#w=}NPe(7K#nxPQThtOx8~-^{T^RM55C4t)rA zNB5E0Rv9?Esy_UILg;u4!%15)B4oO%@j4^F$4jxRj?z4Jg%8qhfB>qVA5cxVtOV<9 zd(v}iugX{s_zC4y$>M;;*wp*!v5+SH z`@PBW-Ua9t*Ov4rWe;!)0*YVWuajEt-^`kJtMnxKzOAWzDA88PD;VV>&{Bt3mf%Nu zu1`39Lqi6mT+61uu-cz|_+`*eA$Te_%?fnYf>WSS5a<kI$&{J=4E_1zlM|x?$%a zYaH!pS+0OD@J?5%E(fI{zwvB8RC*%&xn1{q^U(eLr_kCrjPfTgkPE%D*`NN3uK#x3 zt1vvK=2;Yd8X}NO5kkel3fJdx4FIIv{+$}qnPkk{SN$TnUm!J~S&S4)p=XXWiw@Ck zg4p!@T7(*j^fTTTO#QY1iegFkB7+@lx8YOgmM@7z^HJ@F&DE^zBv0w}k9{-0@sbpe zof}e*8}dXY-BUl?@TxhEKafxNhQ5U3yd{FMt4>KJ?J=goA0-D}GvH_HFf1YGuVCS( zcxRmBW>X~Z;PMgy&l+L!fc@+>sd%0=C&kfsLF!+g;qf#hbVv}K-C7vVGj32TtHw!j zbKc(!Cs^pDX$knyf!-jk#!bpUCQde87*xJwo6aRV1UE&r#ls)n9NxM0tf%WLwPlWV z_&JkK(i^ClExWDp`kNoR!x{4Rt`_)Zf(2+}L)X2}?{z;qsu^aqa_nqxTgJx&R4h`Ma{`9AD;j;bu{Y~|MFuU~Bx8_*VMyV#QXKTR3Nz@dgjW*5!#u9%6K4^4+lK(P~c{VMb%xseogk&N3fEdUmdz!#ULGvaFNaOaOf`S>mJNfEDlei(!~zw* zFW9P^i8$_@Ge12f_jC;vjCNm!*D9Sz;#>^GhemJPNBg@;RXvKYy4`n|zgy{HicR@Q zrla!{IXjERkVf*JmchQ|X=6+eRCih3_S$MQlmFUy7|3vKp(ZHq;yjd)^S-=pwezt+E>G;m2Q*U4Vi-PGea;ldESehP(S-^Ui&!{a32A43fFO@3hKrU8d!&`6D`zkr$%Jy15@|-5ie=a< zWAABeB3NQ%ohymVF9D}9I_{Tf2(=_y7wZHTJ8qqBZI3TE z>3JJ_)44;{-J(BWb4{Q}?RfTsBapTWrid#R@nyEd$TpxkhYm;|`SBaP6x`<@2UfNm=6sgl!7tFRnt7Gv3eBZS50&h;R zSIL07w98fnse9>H-*TLp^3Myao%hCfSC?a&DIo!&^khL=-ta~Zl#MOVlU$rSq6x?6 zP{}$nk4C77D?2oCQD(ti1c?dv1RA$zR9@_!Tish;B^IT$s#Vx;*R})^qx8n11}zbF zscaVhF$Yxg^Vp?;gfvT|^!p$#sOVZ@Bz&&Gpwgx-g(1>~RKcu}_;oGH!ZwS|qU=+_s$- zPf)LQYb|P_`os?zb^VM;Ip|#hmmWUr4G_C>EPiC%%+LKWF^t>1`NHs{LZ`qN_PyAi zY>JVoPrur8_&3-+xzi2rXx`llOij{0+k5_o`!$I4=A#&U@f%C7Ki_UM_3~tHv}wOL z?a;n=WA5#{dfEP^wv~Fm&#eO0LWHPJasB@Oes$Zd=u>9Jf<+ zCMNyZTd1%}9>v$rT|#8ZhuoS5{a~3=qG{G1y}lhz%Li|}`HFycZUBW4VRQqM0zEx3 z+gR|Q8V%gh=gY^ObXQuJ^5!5D+MI5iI+qaDUy{L!Pii^#t3O9UX-pI+l*RNNU+a1& ze+s=YO2i=L+|q|tn^ert_uV~-k~DCgZC|!UfAfW&<-G5~I7T{>Z~^dJGp2FojYH6o z#o?`oKq9%D8S?JC-olJjS!`eYm)T>&8!Ow4XAQuOQ*4{WiFLQ-_8vbNW zb*SZ@(N|bv)Pp9+@cKSR7i@^_+l-BZs>SsirkyLpde?$f=Q-br0XF6MPs3cy;4q-aOhn(`ke6&4;op{^n zVDhNgmy706)oW@pDFTs#bfl$Xs?dPS#J8@ zvO|5U+9BJ-4Nc*)X5GP?P+^+*QWAQw$(!+7;-j+ z@5qfYLAUwtsRt~oNOSWk?-SwzlI^8~hUd(O$469Y=cQ!CmW({P8a!&lm2aia+@lqn zwXzsju^6n=cT$j;BjTmwtTDBi4(-o|w2To)PMMvj0+rVK$IgAWoy0E(@D^x^9)!u1 zOQAbaXUXH{l1fM|&sLu_b%8F43}O3mRU+d%?m~BdgIbKYjyG1uov^gEuoM~^1y8gd z&qY00*b=5k(N`Kb4QLIBMs`Y>&S|CFc5bcZ8BP_Ct+Y{Lz&NU=f-}5UwPqs;92wep zT(#>4-(yVcGt~EmC4F{cr#^wM7(U&CKvU0{^9Dy zZ%VY+nLRc?Sozih28}m9wf17Q2LY`P`=sFY+FYZWnkk_?dmD=`#`44cGaLuUxq8ay z8&&kHI~dJ%wj+A1oSWG6OQAo94;oi3$sruISKI|J#M_h^Fs7G(4N#mT{no4dVcbL__x_(=b^k-jF)yI@m!a#Z zo=d9cKDP?`Pck&I*joW^97=EY<{>R`z+G>t%omWr90kiSwTZk!mwHbF5n6JJSSQG; zrZ>rwUEQ$D!$JdwFz+Fga3wqV7spQiCnM5KLn7^mn)rOCF}X3} zOQ8%g4|8LIZfBb#?`(F|oASjlgN}SQtg_9*;976hQoex}>s15>jDPA7&BAEa>Zo|4 z(vw1@EN(lgTxlmot6D65@IDMdwhAJiI)xY~mX-;$^+cg#+Q{h7y-}}*CJ82`z)-$@ zeL^Sj)I%`i^K?j1-r;0=^C-j#*rzuU0kC#{URloz(p7GvKT2$OV{wgz$(vojaY5ES*rL+$hMnQ@*bVvbdnX}hHdFryyG^= zhQ0mqBr+N9`OmU739 z-Q&8H0St})`WcU$o3B`iQiSt-+wd7Qbhk`DsX(u|;H{byA#)190QV@f{Gmi{PwEvL z8PG1b{pi*?YUO2KwIS?2ehnJM8!^bOAjrBq<}7Ps{b=yxwIiRqCR~`A3|^|^4%pUA z@eyqNWiLeJX1)L8uK&Y49|u#})^2JDWWRW+=Q2sX_U)uPOtCq{_@fVF%bN{Rq}7H; zs40L4!j@hnB0=6Qoul^br|37hhZ!X-E8s{aORp156CDSBuQ#9_0qQzk#v1%u6Z>3V z-@|fCeNNQC#A?M^muYhiC2IU8G1+hzzAi)-xmqoD(=+1*spcMw!;d8GHCdIsq-Q`l zP)N>_RodO%c2ipO=+KUaWGNj8W45Z$NUv{|B-z_ay@aWAJgAacnxzuy<$K3z@Adv5 zPUc!(GS!`4Vyef5tq|A?dad-`<}6kQb5~>>Pd_UR@->b?*wmGb(l2msPc0q+`avs! z32f^*nHu%cm)|z85XQkAVzcCU$Io?zn6Mz_JCoeW$6JZW_3BSPr#U@CmI|s1Of1b~ z=bX@SDhNfV;$yUa$K568h_31?O+*%N8bkfVwFQe)&M5U-<;9W7jSfkCi1y~;#uJju zT7%!REQrDf$3_)9LlcGCUGQ5Xg;7#4ojOr|*LX+^VRy_nb!qpzVt3}1PO{ic`|{8@ z@u#3gnj>ogXCq;*yG}qUK_CW3VGc;6SJCC{a&Il?@(q`{q)_u=+|hZbH-Qm zUYcT$heBu~w2*aUn8&kjZpANfL;*f|yiG~g(_-bDvP{PCW{>g1UTEdXX`cRLUGZA+ zKpq%0h94668S7l&uO4rNnuB==<>}&cVc18HCqv%2uefF3X;jxGv>XMv^$%O#`_Qfg ziaI`OzcirjVpe}Hnyl|UCc>104~c=|hU0YyH~qi~2tTW3-!8%_jYE-N%R&aLxn#(@ zArn42!Cc20Lg5 z9QK^)CVVfeRJU4;(=c!yR`^1_?eKlJ-|N1h6xjkOwm13QzuAS;reh}#-nBpAWC(@@ zdJL0RB-!8ZqR71+8PN+28*RPt$AZ?NvoK~Y#JKaFu5BeRugU>8Sj(8D!a{+2VSAD# z0i}#Q`7SHTO{V9Dd1R6*54F;)8uU$S&$ZtdLVGfz^>ojEh_ZG5=<_oWtFVv>BXjG1 zH}k*36r}GoCSmv@tW(qA)!lr@b;YIuosV8lES?QAMPny)XCNLHk)<&!$I->T2Zrsc z%zYc5v3n*2ZL|v3UHjDMFdS*xC?L6#T)B%w+O7@6V<1f{Wdx^CD$+U+3eu8w<*lWn zB43e0EX_htE0M1zQ98-Jz@ixirpdFk%C>$lArUbuqD=+rCdpxVf$C+wP-AA;<7Cjh zdbtdVvO}2qnZOq}SH`5gUuhy=H2*%>G!vDU&#zFZR6S6%HL}qFFRx)pu9bfFVZ1zf z_iRo_o3zC2o1X!)S*6X?3)T)Mj(T70%j@*drkAf;NKelQWio7o z@@ra(Z(xf|i?uO5pB&*G684_XwaLAHDPPFWYBPw~h)h~Tt2Li#oGzvrI;36Iweryq zlSttFy5r-K6Vxs`oUv+MrAp}aBkV?OK{fP0K8-xu^0Te|b2;ijHA7?;PY)d1l>-NX+aiAbyG zFCPt~o+Hl5mPap>M(sNjspqWW?V?xkyq7_Lgj+}X>RbxNXHA<{5r6aoh%k87a9X~x zS4B3`T`G~T?qR2j(sg$;U^?ZMnU0z62e2B-nyQDQU53+WD@y76a87sf7ZhWjA z)hq{xLLo~*n2cyny&&TKdwF)~wWYgpD;~betbsdl9TWo{J72QL?(ls1nqdHLklVib zyEojHlNGv5dbRt?6rz-FE1F^Zg!R?XgCZN7+_i|FW1vy%nX}Q09vez%wKHT)EYoy0 zr}BgTOVkaUE&P^}l?w@Q!N9C!4}th~kG^bF@xo?r5uJdrZNAbjKA2DpHRr0`E!oo4 zU&B;P<8s&6PL7)NIvOuzxCa^Xsr=15f;j)GrPo}NyC@rMcg@PzKP%~)bYQbXuM!i| zrrMgtWA)>Wxde3~Ld0f@V-j$cB8Px>{H$eusT1x8Qg`}=ci4{Ux`*xH9+ zikpUt`r+xbODfG9VTuB=bSz*#xVC8`k2xfl1$m>K#eB!zZO0DQ9w&Zx}^ zE`8}af9|Aqt~*y9avK{#ge0TxjkQRqdLSAiy;2`Gmw&7BYhmRJn~jB*yw2eBrppPP zj7hzpym=lMmPJG%663yvly2U=b%08V^Ybty{sqExE*ar+bSQH{X{>Vx5s!K=#>Qr_ zUN1OK7Uf0YYfPt`mkb59P186v0y^}w1S@S-eGp_(E(3QXEh+JNpDk>DA$&0>UnvAl zABg3bu53>qDM|j#>nA5LkZnCWY4c1fmATBvomtptSaQLxvrN1+g4jXhvkTaO8(;kT zzIHT^o=b|qzdIFJ&`}o|ks05aC5$G>5LV7a8#?K)9DI`XNxXd`nr%}F9Bf7G{92Y3 z4q+TDZS)4BQ)-h4y6B<=?uW3kng?tRY!{bVbH!-D7G6ZX6P9z$iCFGoKdt)uS=`0z z8Q5p5JC?RVA+n^BzKf?9c&Pxlut)g(X&NbQ)Z?ymiG1@jMNMq2(DT^Pt<`TQEm@z0 zu-QYtxB}DAZxb`@4|6NkDDwtZ!EpIA=v_9a5vDD3Lfq&pM=FKo33**>YcI5>&abJP z{4py-oaTg-%!ykwT{|q}mzzG7lP-j^fubq@WZ2FX@GzpwO+57uuOQ;0ZUDCHuJXH1 z8SJ1kCHGICiiOF_^q{%_Hs}*IrxB!c87~(gI~x@=R(JVMZg|ZSeAlk|aMtJ5 zw_fA`K|}$qz~YEwl=y1>m||JXICs3-K2TGUC4L=s$2MuJm@bdr2xiujK{%g~dPxT0 z&*Ak*`utqHEol@p?De83VYi_%EUFATJC5hpxZ*3FtlLx(RnpvSRD>u|!?WJlwd@Of0`ENvC_60{=L;6SN2GQX`uW@zmU(_G&xCj6 zmvZK;fNCE$Yvce~eyK#QvvUMx9WqL@xCUuPnn&k9_hE?kzh&QBSXfSqlOwv|hNGvJ zg#`WO81*?$$UaAY6+VPPydrQrh{Z* z36vP(Z&2;F{TT(=$(^Y{K`xgXP%aaGtfe(1%^8zHI?{m@#XBeD3X1>4yMn9lwjz^) z5GF%DPP@b%zp^DqV-E_g$tfnX!nn@B<0b~5l z`R94>=iy3&t#uzzAI7#P3GBv{5GroeEN!PlqX3i%)YxZ5z7N7sh{Cp-mH#vOR6vGCpb3B`)R1sN;P9tW6HeU(8S57_##aSbk zn1I5%3$f^U*UZ>dLxks*C6T7D)4`Hu24fFfM>1!vc`x$!+j_;o2bZt-*$u|3G!3#7 zPx0E8yR`LJFCB91DNHLlW&>5D?NSt)%b2Li5YyqvEUmGI^03OMXw&w|hGlD?kk2|I z{OR@%hcl`+b#E@X;qM3TPShUZ>?1j)pS~( zC5FJMx~AH^J)R-UmVUcg?_w@1>BFmRcZgg zrp-4miXlF(uBW2oi)mkkH*>`g7~~wor$^eAjR}+|Oca@#)WTMVqv_x%k-nE8h8_5n z<2o15%V?19smQoev7zy5=rrNpqHWyq&qb;_L06My2-v{v*v@FNM*H@RXUu6tUmJTp ze%^D$sA|8y4+~49@2&Unw~|23>Tc2Kx?+D7>I8r%@*LE;nZp}^DNpr~koHe<(lv=v z2vJ=Kmhp*3XK~Lb5X0*dfQcT%IlVPJY>HY)|dOf%t^4l>4?_T+>3du6o7e z`iWcfTmGW<(3QLPZV?X`ys@m#2KptuN<&|SNmr&9Y6&1}?EqL##V z38y^@vMhQhQW&~hri&4|;|ir+L12o+cYdfDW1vpKwYcFN8Kp=4#`lAFWdNU_k>l3k zD>E#K@npx;=(3g!cA+f`wI+xs>q79dE?E_iK^^5^T*I~BQ{3@v-Q~6@t!F+AcC8Wx zrve3ZYIhCfj&*TRD6;p5g2ktPh~tJ}!f9+GR+<(9`a1y8ikVG2lki^RONQRXq6FJ& z?ONnYzvZMGyKeNsxmeSV-#3};@thYV6$;%$ZWYh^_Fg{3vubSt^(PJ*$}==-+fOHF z>4VYJOSla00{?c=z7B z-ot-~1ZfOkzAoq23f`#=Y^BHsUAnsx@9I3K3Zum5#oSh=vL;ma`3O7+9F0*#Csss@ z$z1ukTlgs7s|=X1WakhM-2^kDX!nt)NULJ|&B4mvVB@oCm{P3ba~MGc=;4rx2#SVI5#A-?Pz+u@V((UN%X-YRRjXi!ZALqYW-X z@e3+9%(5h>05L6>%({g06vr-VPPNPXHHlW9$Ga8E8ggQl!vR^Ad3!-2rBN!a>}W*j z?VXe`RazHa5Hl8|Rmt&X-%7f<@m`p2`Q!lMrBNnBk4UAlq(vD5B6=#Z9MyS(+2PeD zpF^~PowdhKlU>=uH)EX>q8aBcw9km373W-VKJGn`iy8LTRoxxhACTYzO^7c-2U(%& z=}-7?4j85Zyc?t_Ajx?@gj8ELroH_d8r;JFefz;OY{I6fAYhSl2M8Wa=R- zxV2zQGe>`zrsen`s&1xE)d%IVp|2s;!~%~T8Cz}v4gOd*X7yUEE0KeSg-N#x-OGoK zaRnK*{LYfIf|VtsXwdb}z|1T-!4b~}yEbF}_e*}`>^$gExU%87Y3zF*a&AFTki$q`Y&fQX#ukgN3WDt*ym+1=QzO-cAwc5SN+BT>mS$ z;iVr#Q-#cp*?K9EszyiFPEP_Gt0I4?%cl`%pZTFzJ6jmoO30vLUKRTX14a9v29|1Z zkfcgQ3bs`nc|U#hlo^C7FMmJ`@9t#8SFVS~2gYkhFZCtz;%X#iTyVY1F}AYXHz2Wa z`^4bngceQ%!p)9x4~1Rq=8qW1g7e1MLPuR%QtQdwm2l^ToMNiW+)c`?RFRZu^-MwP z4dHkq1aNs&Wh_-B03iAV50efMwFp>_KB5Mxp-wAFfuhJ7|_VeDBdd&*oqtVeAV zBzXG;w*fOO$Y@|f@^{R+gAdxS#mYV$Cm4@xYMaJq-02)V7t}6g-x=fj^If>Iged;x zz|=y(##}rX{-ZQBug-C)aa;60Ny^dHb2C!Rc*z>a$5PyhDi1_kY!B#GJE1QHJyVtC z^l7wu#If2f&pr!L&nA7FRFNFOUjdpL`mk6n;Z zu>E#?FgUMZ%Xz?4XLBB_CitVQmmFmP@ds%f$Ej>i75<3+vR9Mevl{QvurMu1f52ycDYo2M#L`hS4)65fbmi?}E zqr(VWlIc8apHT#(mOi#XXx6F9}K<=h&-+LS3 z7j00+;T3J*k$-)pe^9IPvp({E9FIV$smt?PPRku*^iVO{D1l@%Kl|wUclh>M(xtG@53v3>8 z+N&k0blfnHBd+z*hme7N7)6GKteJLO_Lg1axXIq21wzr(VC!kWw(wimAtqqYkcPR>jo=*^ZMRQyQd0bjN-puIvrUlX&uYZz( z3VTArq*HwN2Na&mV@b% zJEZNTEJ;{fK4TcUQZ+X+WQx+~(vfYi5Sxi=eI6?-_@sFJn9x&dnVIMqer+C2m#JpI zrs27yQ@n-6R^6p>kT{&2Ux~G*i0MPxV+mSuL)(n{R$s)yEI=-CkF3PB@g%nIbXw5ebOq|MrhWud0YYlAA) z&QUC6@=g0_n%c1nbGVjK2AfZ@@6b6hfvF;1LjmDZRr2@e(TW3sClYh(w63>f`w?OW z?k}}I8ng!$`oh?qlhzzGBB+jdv3z_+!k}@rl;r%K;10x6go}2)Acb_j|(Q*;;;x>e9$(4K{Tr8M`v|*HIg`-SLwR2T5 zQ>!PV!iCeuYm65uTfbF00yg!@y^Cj+PjhJ?8JNC~`2Uj0v(m~_0hUt*z z##^hWU-g~NGI_z%Wf`qs-cdH!nO_Ir2qwtyOhMgd)OO-MNHX`@jf%U|@*syF8jh2< z=M0M%DH)?$OrR9N+M^8zL%s|5mUTu2E9J4xMn6xKc19Vinvaa8A8}u)HD3Opdmggo z$65T!bEDn4a(Hs&KA1%YvTSo90{UEa9+L>aV{v`v#YE73vgOT4kHsT;MNNHZM}rd+ zj=1z``jWJTB2UFjw4+AgN&7Sa%gUc3s8iLK^wI#e^n&{_FTl^ z%96i^KV&0;3%&`5Tu~c}raGBSLu8z4vtBDnKaKVpVicId$T@5+d~ZT zVTzS?@6*U)X;n*^c|+HMnZ(g0y~g#gcT|4d^mK2(g=nbSXv8Oz zS)k-HlM(=V$?JJ$6E5V5%|L!O%exl zHMjCAJAs#MH@yA9U;}ag|Jr-YfGC@`VfYe35k*i+MM4pf1}SL_K%_*#l}3^7Zg34y z5Kxd#=@6FgQcAj6y1ToUcxP3ROGSLXC%!*7zfN{{=A1d^=o;&`XK3nET~w#JHQjy9 zGW?id;;OK#PqnRy%mmyIGC@#yHNKzVnpuK(O<6g-{sh7Ls(XX$#C(V{n(w=mr!sUg z$5KRD?o_8%<2sQfOH{Mg1*Wf96?CyL-VbWet@RFKuzOm#%m+~?Su2lRchCU^iygz> zv@yX8nPv0=zXLrmxBF2*Gh-Lf;572HQ2Sc(WRu2v*3trVnAGTbj8)794Ke1LZvjHx z>`u@uvDCM>yrj)YHFdL%Ni}u)X5RG{gd@wdA$9n66y0BP?%;@9Gu%n#;>)PM>uOm<-Lx~_L;e0bGqlM z{kHm(P455>gU$CSo1C>>A0&^SDCdg?D2K@a6s>--^gE%SP#c{F6)h%}H5u#{^{NV2 zXoe^)RHOXV-`E|Wx|ZESmoZAI8n;z?EpWuRzC_WiAQ0WZS9&UtQra*r?2pgP7n)SWDU*e z2I0}GN1@)hp^%WO&XOfhMR@_B0*Hmqk4)0CpV%V*ImWb)*Z%t} zOj@v2=nYnIjm_^#?U#`YD9@G_&IbQtVg7#8K;=1#%<)mVSMy7D*Kb7uSROR*DQSM* zi(kBq2d=Qb2(0PCIcbxF*6_K~2k~~CBQyu3`}N|?MBm+LK1P%kKlp6y+wHWGE+xoddr;I$Vc*UsoBcZomL7WMnA z4r0U+K4IjG%wsK^@9wB+DRV^Ky(q<@bli@DUuEJ1a);z@S`+z~179CVP>gCQGcBTi zA>n|F@j>s}_A*CJz#n-YAD6Kx#s6!filK#4U^NCr=>=$Z$F-ow#nMjGluN%>r7oWg ztwTi@q^cJV?0!ZfaqHoGzz-Sf$ zAp9681x`K?=2U<~TEDh?CYz9F%mIFeCv7=Els3RCA`!@0NhEC^2B}Xdl6rJ+Z z?^-X3Qw>+~$PD;aZuyV#9YJxWLH^9^dQ_Pmo@UU2;Hx(T;A07l^ae3stZ(3pgDa&1 z7PE6M!sWhJ?AdZ@E%+BpfIbhu!+>>427ci{$cE0NcExLP%hQ3)aU;=$ZTSSZR^+RJuK|NN_QM&{dnZuH9L~v}C}u>Wv#2-!WJO%$FVWDS7&?nQ6a?02 zPu7bNZEj5V&$mE|{q>a1c2nu<8&Rtx;Ejov%;#olQ%zqlUG)MNb`gS$uIbW6&L6Z~ zew8?M;O3e27>&(wXQIz!;JJcQBLY&FBwRR`YS>8x;EAav9wLeNr0H(~@fL;q(6m87 zhsSP%C*Z3RNi7NVJ#wWMb>1iu2A=R%;_Zz|*u1>{#jLNXb zilEtg19V_kFVxUUP&p2^R{5~VI8)7b-t=HB{Hi-xL0uS#aRc-+tUwSP_>y%WOSKMxObp1Kad zL*^Mn(c-8`$mqx!ph!_y!Z#xlSH=(EIPV$+J&;Jhf=5cR?_+AM+jK@};#eL;$x7g&W#5s1 z%|lb4VH5!8gytZ70#YN@KY(BHoltF@tE$kY9G~BBH5=|DAeog3(= zFNjfF6&(-TF6`RMN;Ybh9UXGvW)FR8!-x4QHWr_}&q7yCL4OwNWklo}){hKKNfbn?F(I9-fHeK~0-v`)Z^=n0p9fUtjH7OzHDENq@btexvUbM1w{_(cTKA z;k^uE13+T*LMu5bs%98X1_%%Xy*DJTOZ?|l?Y)`5K0u?+TwknCeGCe>s5sYI;iue) z%-afLL>+fG9{LCgrH|3AzdwWBWdl{d_WGbQlS+}jz*a7x*2kTCi2WqM5(v~q$JFLS z*pYvJkydmNF=Ez%Uy{!tZ@xFVhD{!C9|^F$LC*74p6ub_ZyqWI``$~5yFNe7nH5ub z%kk9f!fmsv{WL&DfE~d;>?rpqdIWkz`-woy0b!#rmz?mI5v}qDuWQ(QKkfsMN+n3O z6Z1)te)FRJ+8KeZojM17cQLm1tbOx@ZUcpV!eI2yE|LD8G~eeJ@ogI^ zT(laJ6d24}tlcRSB-DE-O#ztbw*mL~0EbvMF~R-)_}#;&7VPs?b#q;c@tXnR>o%3= z%a5ylnOI%)KpDxmshW`-nCO!<<@f)0NB$cP_{lLM+LszXTC+9*_UeN+0q#VNQ%?rv zHQ#;*{vJ%(cBw%~VEBi$CDccIio%v{;*4Qc8eD9k)|PXz&DT4Qe;c_n`s*3sN2!$jSWU=3+dHK$rv9N6A{Y zfr*OWV9=G_88?Y?PbrrM_Hleh(!Y~Eex1^jDyiGNvm9K2BPopl`>8=$2AlH=Gu{>O z{37_+5pWM!LGm6o?}zX%tKe6`K;2mFWdk*DJI-<-nvN{HaUBGOVzfUXlqL;Gg>Jc$ zkbM{9_fGv^4;T1V;uA95;$g%J&5d*Y#i{)Hz`36I+;RYD4(J7>0=1)SG=r;QzP=c!5pg?a(!^UWB8MEHW)w<*Zi*JDcPI=8sYEY{ zk#{#`^XH2_9;+|MP(w=Kuc$;P9NLaLzQv}lYr8sW&`zc&^6f<&=xbZe7ZacH{`NSK zY0XQMnUeT1>@_S+xH(%j?8@cp0eTnQxfcvSR3H1c-1=*%T^8<|Y&WcX-(18ie6!7C z6QTFb$YeQwq%g$4Sf>8?@Aq+)9l8wfCDqR}x??)VsQ6(L$;m3`UDJ>_Xs<<&(G8 zL8%Nt1jI~k<~KDPfFVZV$ZB_dqF$=6Fig-^sUHs#_c5vI+va>RP$KOKyr=^(6pb)` z{|?f7-YD^~0>LipNxgSfLGPY@sOH5B%71rW(<|oSI)dvbV?gpp%>ba;t9vt}OUD70C|HmZ zZcl~WIxU0QU!QSb&Pi5bCr4&&hK|2ea88(($DHze6C{y~FU#|o2JC)+U7Kl#W!c_Oq*;CGJPw2vE9lR3zU zVeu`xRz-_r(QRg-oAk+gzLY@u$+TNdH$jha72QD2WTLwmd-umrwUHkhQO51>SZB>D zbqG-bZ1k5avRjQRK=HKL-cX2+y%52E4K302BCBlpIz2((1L~UQNB+JUr%<}JkBvnd zMX2OUx2CH)-7mfmR8nXP!PU{#eD5Vh?3A)5@YwwJY}DwIO3sRu0O3Li>WB0}=1=s? zWL;3u#bi0hn(eooLHoX4(-O)8tsUiaeRJLfr#fr4XRbgF?7iqc23Tme(IY9d?9O-L z4k3;3$D57+=!qIpQZ(>8dso+mLQ=J@h{VcvH(vbITDp1Qls8bjyQFn37EBJ-lbtg@f6l=+>x1(lwqY^>co|5>UdXPmA6_5&XVb}Z|@y6=SD`&geb=@g+6TrsAu3shxB;%WfgcxfH&!VHI z>OiGbL1qD5D{gy4OsAucso0dsy1MP04}u}2F$eU9-;f7(aou%2gl1C?XMKW9nzOl{ z+~~G4ajZz<4lDe%IPfirB69&EG2Sl%-{8iUbS#W-@b?r8UBDd!nOfW%W2(s=+VQ1` z*+R&<68+ri3#w(C#9Xs^A|I;D-h*_rxm1g(z5>L1DQ%>E>UtUQweTc1%kbrFaVge2 z46fJF+SBXMI$K1;Rds80GrAMaCTXu4JR?%O|2B*wcVyeh^Q&u$9El$(d-$<=frafr z`~WGj7l5Kj9G{qTHxE>>y}YrxHET13vRqbz)I^XAI}w4nG<=Oo{DM|?uY-R|{IDhp zs$AH&=@BzvZKVyybn`9UUsS~j$br`c=#IF6Ezk|$C8YcrQ@*2&=5?r_MleUP{31E!79 zgo+1omV)#{92eS@I}O*5pK4>T<=e^oVMYOoh2BUL9UlohWGWRXxEi;FxsIFAg)YOg z;VRa3m7VLL{M@DT$u2bvU#_Qpw$zcKMUNmslcXn_+d5H$OA?dH`zpcx&OYc(x_HPd75756ZhJtG?xoZ zHZ=&Z2n*!;?vJJ|2`4JBA2iw52K&V!B^3X%kFJS)D}fyv?g1J*S%K!GyJzqWCh zuIX2#>W=A(_u%1&JF0y}AWn}&NTjB~ZvyORco*#L_MZBBfKtP~ITxNCX#k=3xRW{_ zDZBh*2Bel62y-hqY=#?spN^9_^V)6TE@%w`tKKc#oi}9<@TB#DzyxQFj{m^$XCx$L zl!PK?Y)Bu-Cm2WuHHmZ4fn3|UeaLKb1}sP+@rC{Gcd{p;ik_SR6>0g&WfydCTX=va zR`$V(`2G(gT=O)FUcfENrAL*h^h7L{l@|T{q|)8=A`#t+pD2wZS%Qp!*&?j46&+pF-K)_49iE%1EHqF8jz_qJ(-nX&9x$iuUpIsc!M`T2?=q#|fmb@NsBp(l6{sP~gCGT;{?t4u ztF1y=K8BeSv8U#eGP0u4T5z$Z2f6$nmV0lwAk&vKss9T2mBPj@LKMx^rc$bEe|Sfs zvE<0b3Uguo8Hdn;qfjR?n=Nx`TG^$R)pD*S8KC$+=W&!HP+Vg_OkMolp7w#2Q3frs zz}irMyi?D))@nK(UIwaTA^T287g&U@bRX^hh|&P}&O&KmdDOtd%oyup?=rMY{CM3G z7V~TmTcAkCB4fI;UDFbW`=@ebP>>2l?~6-~nFom?0l}fQb!FIg>RO<^s&b3?|T| z?eiW$a%&%yboH)_q|oh^~Hp{xj~P*Gh8SJLgxaoJmvO*rvT}*r5U|`@QHne zbqw%GV)4+5^RB-SOXl8Q8%&;vv)d<)mx0`Ykg%5TBf_6F^sn&e7dUazun20jF|L8@ zIu2S?y#WbFu|MSCJqUoZ8J<+gA-kf!52^uHT|w!0uBPq|qL(>&z`1H4lqW8Os1Ci{ z#9>@q;3QJHEd#lN_gKn+vxnYWex`08G*7gRW^C@t@Xw5_2 zWPyEWo(>e}crigxuX`Z1fBovq3Eh;6D5fW0Y6S3SL1S~;yt!xlV0<4%PXv#e?04w$ zFD!^d1Kqfav!*k4N{|7AtF}8^tEy165f^X~I?^}8&w(+OzZyKhJ{sbq3SZ8ChKBSK zp}E)A%lQMb;cZ^(>hrG&f8_`h<9Ri_P9(;YS9IqkLOprEgTw*sIs&Yv#s%e zgoPGR)Q@DFZtwO2_^UJ{&r9{ub#e3cx7=^{7R2LgJ8X+qocpa1_X;DaOSYX^YtwP-KEX}i|`B(g^xdUfF4Q2 z-8nU9K>IhjtEo3aFQTpF>E{|xW$^lB7nvRJCVsY5xp{fQJ^`gh8)OO=y1!nEiFhJ9 zY{aTa36G6M&0F!mTcAIhP%430;KP<4QN>y(kvc3=&O`aQK_ zl^PiZ7H6ddGWSJp!`Hu5)O!4~En?Du$-FCTDmrYx7im>$LCD=TmYY6ka)^`F>nU7G zsscWp=Vci*K@oaD?m7rUQbEamrikkJc5c$9OV8eH0iushJ;-ciZNLQTrFM@W<;)frBL`RgNiUdj8IUVQ z=bVTU+auMV9z@-WfX#~!qDI=1EudoilDeN-)Y{f+uS=yGg)+!OsmQ$V2?ACi%K;|Y z2~4a?xmae0t#27UiTWV%CQ`Fv^OW^Efr7O-GNp$CxrCAb$`YCdR6d~*ykYOLj30Xo z8i7!qY!l&- zgnu0aNNetSpve&s@q8&ttCK=5 zQ=1hk3Y0f$Y1@L zzgepv86A{HEEr&t=V%0Qad~}D>e<@(HCxD&$*a7@BuF7T>g-&H4)uCYQ07^fR5xn# zfhm9!WQ?F~7-;krf=|Q=t{(+%(oTayI%=O-MR0&$qhq1hc2m3J^#Y1T*aXDPr`s+y za+Xj<+GZoMhGy))bYu_}Z&~%%3*N8Ter~Jdn zlrC^q`QiZrZ7=qDIK;<7DF3Ryt?H0n!T)1%SK1 z2A^Z`UfpwMQj378)D$Jccb%ID=s{3*+Bp!v5CkA}vCgW$d9oyTw%~`BDeZ>bTei30 zfvFVV=T#$}16qcF551zZbH*F$DOt-J^N+DSZi;~2R*VFi3kWk6CW>>b$qOt6}T z0(-Mpm3xd)GgloF%1kkO}@Fc_#w-|Bb@`Dh*IFY zlxOi6_LgT027RUWw4c4IY@LJn#rNrBNTC24%=ik1AHvQgq%~s9FEvU0P%(!ofrh!6 z=tq2j@w6*f`Oz@)HWz4;K^O+l^`k_H*C1$-@&j=yk%(iZ$dG?vM(8*G3B|w%_fru7 zeXvJ>Y^u|u#d0cHXiqbQE+Ex!Uie*!gXHP=<%FW4b1yeD&yVsk$g?!E!WGE$v-&so z0S9P?Ugc(uhei=^pdfw3G>KXF8(sl%kP904IQ+0q_DUV@9CB84_xga}$qg(dUUP^t z$n^2ozzB#f?L~q?t}QTJ3*drv{}v>_XmX)1Pj0RjT9g4l+x-Z`#hP1>+tqe1!txgG z?!~x4N+hra>n6jHrL8|9-@iX0#kt=90%s7^a?vzeZY{%8`11)3@{;#L!J76!q4)1) zZ6G@Yi%9QXLAJ6f2mPDmrP<70}21ugWl9!0%+|i;l{GwzviB_yUM0mGY!?TDBk$bCW5) zr|6;0bfrIQa_8mLk{)*5vyd4p3)`&*ETff?TaTkp!d+!YCoaPHmiliqC}D`(EH?C$ zPcA8>SUcvki1emrKB&9Nv3(>cS3Cr5e7LHq+G2g_zP@a?X>hiWAKCU&`9~{dyEVIr ze?GmAB-ladXV|o6tG`)?Oi9LUY-#X~suvI{ei>!A-!hWUSYKo(8?3@As3IT;jt=@@ zSIt;u`f_uP@MK~anfiEpcFbD2LSa)%5mn1Yse=1*&K4z;%EPIkMnw}9>Arg!2QG{M zBXmgXeNl)wO<&!3P7liNCZNS(8v4ldR3l<%Wd^my(C zqpm$#A*G@$i>A;>^^Ovu#PPi0$o>Sha(`NcKh`u!Mz3nsiFk5MOIc5)oxp$a>Fho16`Jh{KSTs)%7J-#-x5DALX45_$`Ot zyd;%==cFeU_^xN!yGrBZtfw>0PO2J37hpLq=|=i9DXS-=PbWEXB3TNFCYSYED{Z}#CeXP32`E;1aOo;|U3645yC z%FeMi<(NB3KB>pO%%Dk3SSV@?&(k0dY70bkdFqtmw_7S*BeRM~0x7dA7@CbbFj&GN zD#Aa|42-4KRd(X%8{^5j6Lzb)qwdoN)AcG35zR;YW6N}wClJMuf(0+bYNqlRL>65} zy5~tIXy$++^}^kDNFvyvm5VHI!3*|r_S2hqZmnvr@ktm7;dx>?pB^RyU6pXG3dL3X zwU^~=7cl$3NUa3bN5IpHD2_R{o^o<>$n7^u)d?|pVly;DSzZ=mZD`hyFWBnp=u)`0 zXu2KGm!&)wP*@-^+DVd2d!^>30V2f7$%m-mR@26){pLcN)m)7G#dB_J#rXjv5^RPm z6+XJg@0yg2YAHqogrD-;pt6jom$y7PL@#;DFNC(zV-qqrZ4g3OuwFBCCMyIBG^_7? zvBkGOq}tCMvMvhZq0CK!`4O@VR(=xsr`nqY!(6hiSIkFE$V(%P%~)x6N?MJQy++j4ZMy0@z2p1IoMfx*^e?MspcI6`)0{Gnbb{!4PPTJneRD*n*N z&_QMI!KnN6s9$G6(7vKF7|z?ZPvLr8MkVXh_o^8*IC-V$$adh?o8 zo#MRGEwOS>o(;2p^+n@RzD~<(odvn&FuZJcZ@rE_!J`aTrH(?kDKX832bJ!_Q)FD4 z$V2RhveV8Ogts&bbto+iFIzO&Y=sa9*4nSJOT6jEoRguPCh{1`Hy54NYSSw$_r_tf z>!ovdEVOLe;L^2UvoY{vWLWoLAyQgtne;Ei1a()ON5rfXQqz#h34heauwNEA;{`am z+b^m1J69!QvGJ?y7$Tm&AkQd}u#tkB236 z(dafv5nXWa3`{zz%t=27K4hPXS=|;)?XhUeogf$UO_mV$?6%oi8Jk;mur#uq>WMDi zu}7?aM$~ao*h%XxaA>)8HZM(v^bmSL8kRmS_M9_sGl>st&mOEG8W-Qp#k82^np`_s z90cdZRLmJA7C&8xz6$Cy9_)_X#J{umNsjAl-s0w+K7%51TO(&ZZrInYi^+ZfJVN_S!oLhO*Di_Q~Ws2V3hGcOdsp?W^8+;tqt1=k-}CMb&!&^auTrI z!epL5A{5Xfp_ORhj*zpUHAVB1S^rA{N6TLI*c^+yHhQ-9R6w7iata*W3tUSc*z zBetP^!CZTt$3ltnc;Qkc1Md!c7xQPX-t}7XnVh8p521?Sg_^-euJHtWT~hAl`qch0 zcVb_CjWna;?1p!*EuIDH9`EMq#=$>tsV$a;aCD-0LtbOj-X@OF<9XCm)bw1nSIDt- z)<$JnobzTCVphgz$=+BYX_buQ)V`lt18DcyCuc zmh;-8kubn-@lnsffMAu?Nd!i~`P5^do_Gout28vT!=g34jZje4uZ9X6I6i&w=R|m5 zQkmg^zFn%f7VbuYghvLDz?yz3TUCBx+eLZv@~PAMn&NSt$+4NTeZYNpx^M?U`9gVn zVPh`4&aS`;`bzMDZe~P7jD_w-R@=~wb^B5{Z1b|7X;p#5@Yc!9e234E88o>U*sR{@ zU)!2cb|6gLXcfDp6=>5PdpuILB4{EdDmy}Wj`?_CkemC?Xl_XMwJR_&F(m)hs~7Rk z-pMF0o3LNha&nvrPE3|jUi`3C&Re%sOi6DC>8F^<9d4K-FyQ11au_k2rBkRqg@W2a z87d63%gFfJ4eL*|6GnhE%ZfpeIHX67&gRMla5xhsW{>zAg1-JQfG|RKvEK-`BR+TT z)pizc){VYbWNzr7VW8mkzNbgoP6=*m4U1RZT)4oOKy>bIA%&}HRYu3$_4fIyDJ!j~@UeMUTW<7glwX)CGZ;v=2@x-(un3dS zd;Dol_E7~sPN4>~6Fl)`?|L)dI2_`j(wj7$DE}n2an-Dttp7D4#ELqACTlQwDGNd?f3{$4xJg}iZkWM=O2Kx%w5g*O zUtYICvzChoS#8oJR~Y9tv*CWcn1`MB;)+$VOYuMrC0h}ZQDaa4+uqLnq_haXnN--e zdH-gGI&HVHb2E7>(79IT(^xjd`HN2igh!PPM| zmgvA7Im|mZJ^0zpRcOT@#P(eQKw7VNfTGSnp$143WCl!?;dF%#IB$REa&E7qJd+Zn^l4S z8A9R<@s!y#N{tadViiOvE>Y3M3ccuD*GhBy@bsdqEsfzfaE_oP-~gqLQ$+p{S0-|= z($sIejxbrJO+Rv~$-9x{eAH?xIJ)Ur{*zvt!fgRD@+%gpB1#Ftj>q9IHHhu#Kib=p zUSZYc=Gj)BET74nftKN@2audcG!`pik1)(gKytU@b}$GW=0{Zn)`qcW&mjW4ZWzEJ z)7a)a-2{$PX9_B+C3e=jRjYJ2`%PHiuaCZ2|b*qA)b z9!#10q9_qnHJvp2Kr6Mcb7xZqh*RfT^fq>75y?v*&!a|N>LXyqWQjkFzk`iFKKn4s z@X__HCFaj0TMbT+spC!Q;7W6ora?g~ot(PK#p+^{B=!SJ{h^t7>`^@HeG_x(IP}_b zFwMSqTp_3UHb1lWPdMapT-3M&B!#0wNBnN?=U|xSE%HmbbZzn@?uEe$|gTC`;776^t$-dqG~jj@tUrB{68y6 zUp*sUCjt#WpBV36%m6;8N^Q+jH#nyI3!U0r^6usv1~#%Y6vrVjqFfq<9+W!n1%;lu zwl)(9Oh+37+v{CDmVx@$c+6*;#>2Hd>wvBEd4)mw{IOu!0NWtO?o9)WDEHoOqY#-# zrRIdhQUP=<1?&32-0FX$)63kN=0n%?dX?3+qYlxG*B>P^d#Xa!d}nTo{lz>*Rff_< zpeMm!7IMuy^~;mw({>@^or)VsxUMcOv9Tk}!jurCj1XWb)ObY@9h4yY!(GQ1kGj%j z0xRoY6vu+uO-rT@Wa%STZ9Y$wA8S-?pZ*eL>^=_8Ez$^{yXz~!e^LUgxH_x@Dx)n0oRnO44IaswVj*YD2uyw3?@NAfG zS~kA0ggbDb)6XB6Ny;!PFSxa%;y$0MvAI4{HH*>9w?)|>dprcQLRGJKF;mFtWk5|p zeT2`{lk$AX%heDQQS0(gNIQD1E`Ii;!A2@1YLJ=!^D%VnFL>Z*Rgd2u#*VQ`v7`AR z5XgpRr@OZLR?d}=7IJJBJ27BlZEhsb!DsVGr&h~+ zUI4jNnBgCRw&7HC5w|{q{rD}5FMsB#;57Mp(0UfUGovuAxn{Z7ySpY#Ur2PVie@dB zTSSx3c533&_?!1QOeW1H=i=4?^J@LcBhQ`>pmCYu!@(IdkxYg6x!boaxQT=99*fQ7 zjRq_5*-H%0Cy6|u*OZIOjpmxF&$^`;?r?2$N}m0tPJxL|$7aU-v#;6&cGn;)Lm=ZM ztk>+*i&?34$V?io?HHE<;Bw=m z{ggYaWrowM4nYNHdy9K=A#K(^cv4iwph!&g2B|+qe)^=~XOmmSS`{Y|*0&r62h^M; z_{HbdJRt7^7o-OWJ*8~@hGecpbK|N00Y*XiZE8M>jU##N1@mG-J!V2H7Sm{%(Fj?< zBbOu-)XX=Aj>Z=|Y%V%D7FhB0Cr*;wg^2n0vjwxsd-VqT&{>QtD--Bv4Y9YwyH;uH z3NBrN<&8J-*<0LMnFlP^m355V)r3L6t6e|ZF5@(V)$qzAAaY3Lmm6$?FCYTBk7Z6R zd79X>wuV{&9sXn?;?vgWFuWSf7mD4kwV$5FWxr!V1acBfTR5QvEnadn*M$M{br9^21Z;2vn}bmPaok(zm>k+`Ce*L ztTS2Q$3J@S4yK6Ez#>Y%_1HNL2Xnb>FYSz_`o0Z9E}~}3X1#VT(b*PA@i_=##m*mMm3Z*0l!1 z;SE`~S+{7nL8_QY?}uS?$VKc7`-%~q*7G~$^M1P4{o9={upDM<`gejHiTy#2Rp03w@{~AjGnG90CPUK6%YFL`v>&g0mUx3;W!O7_<(-=Q`)*6N3+-ITbm`4*CMcT}( z5z9my2piFy>L~m>3d)P+2m|dii|A=$q_YN7R;qe5q#l^LGKyDjTs@>P_6O~$hX6&8 zO@s4#9{m*tsV)>_XReTsoE&OrjS8!%W^APoZlV+u@U)Pxg^p?YEGeVZ5qQ2IhPnFI zH4d{)qs(y3=O4_-9;M9}>dLXF^qa7;v0OXr5t$MjKd&-XP?id#wBk0;upFKhMwj>~ zODGsz$fs%nfq<^`eAScFv3VJ>xTKUEV#D0y&DZQDf;@uT?T1*H`E(9;C3eug-6Xnh zwVrE}8>xrPpKHRIvsfL^HnUC`A8Kx($cIK4>8TjrrI%p4(6tbScXH(AI;*BBVQ;9< zMIj`%CdlQH&L)Lj@bnA}GSSIX%F7q2@|h zy_Rc}#}WJHA80mBDBt6i6(Q3lqs*hXikY|Zc;L_Us~ ztdb=X81+lpI;O8gV-GdYq<&;AGxm@|piLdvGs0H{<)pR7b|%8yre$k3dwL}qWE!i7 z@OQ&(62|m2!CZFW3gc+EZ69{4sI68Je8*j6xf^V=GvuG%4qvis-`uWm%Ky-i0L;6B z;F+?*WnXXh36h<_v4|TC=i`g7P;!)-2XF9{df&0=y8DwQx4S=d>{kM$>x7#R zTnNDN&_ZL7q(OLMEf*n3`p!N`90@X!E)R-a;1%m$)4KZR&5pnQ%;b!Cz=FSe^Apl> ze}$GcKK2TeSDsYsO3}jN%XdV?jh%&y%ow6rnh#D@(8Ry9UErHHaSgyg!p!IaQ0?Z? zo40bJ-6Pi&CM-RbjHpsg#Jl|$)ip3YNxT9n*qtAp;3$3jd5HCkmNA*gkM;jh{=NqQ zMHP#BL!$K6KmFJ~rk1?%hQ;B>>%ix-{@PT0Xc^d6Y*aDtPklHQN#WL+noGvca zRaXpj@o}05>KCq65XP5&svfw!2%Z8;QPZ!d<%uqoX&W&*gUY;vWfbx&BK$81LYtn4 zPE`|YGhv#IlhZS&y9bv%>nePy=#OxedI?Fg8dH0`)=>~Q8kUrH4Rn6;=3v79#xtQ6 zXq(-3`I56k(m}G1OP^WwXMgB7)i{X=ql#xft{k5KC6@S61vne*7$GlviRCZCUO!me zZ`m$(G~ne<*kbGo4iXk)v*YfIqLMAXPXo)YhHaBZ#|)mQ5f@j*m2`M3)jWUo-#y@e zo$oRMU^dv?Qfv#J(pHDOcn^H{l!0G!xkh~WZwFv!16KXz=zZdYn9<(U-yfPG{GLj7 zsZxjLsP3Z1ZTe7QhJ~l^4`%wizxCQvhQsSl?~mpYx>y9kgr?gCr5GFAb1%M%L7+igolSeGOSTKM|`0+ z$l!33=aoD-wXXG;uShrYw8%N(0WPsxV+1=RBetWXBZd#tpM*PqJZdX1h?v;dD`#k% zWPGg{#RP~Ze)KT#0;GXTtALyBt{}G%T8h$5*Ax8r9S)D6)Sb-o43;`jEc`$nMkh3U z2Bov$Ucfm8=(~6C-sasrSMwb-6a>J8%6>=wE0O*3N$P{X)Q~NO{$$M4ryYk_Ipc(3 z*cHI>i7tA%&nVOLAHM?=P4}V3H&ThB=@YkZ@=EDFPr_> zSND!0Ln7$HumAPw&*Z;vm-i%&xaTHl=*JzHxB26Rrnf_LJ9$DmQS>OK@W&=5{1;O2 zuV6n1yyx6~@Zv+!i1a43prD|>sR`$i+Fk!Dl-i2yKzkl{MNcIj6Diii$A?a%R46WW z3B#tV&H0}e(GnQ)HOdkv6(61>|7{P@3E)hT(J%nL^Y%gD55QrpLh_Y`r$m3vSf!D! zbxxaK@4Y+Vg-}_*SPi_7PtE=1lK4ZB;lY;nPUgem^^HSS8-oF<+$v6g&AVGpXg0>z z_WX6%Qx$IzT?!aJ!o__k3VdgpG2(!enXRlG8iCk_N~!|CXAdn_TmK;yCwmGAzZnQG z$E9ZebzfEAVK6}5s_3-)-W-QK!~x$jBq*QfFcoF@pa8-G4pw#4-12Yn?_LnUw3zkt z;>nu}{$if0aYFt;!InX(&5s+ZnudrE=f%m%iOW>@bix8Ftz^>E0^>j^Uzx*eF-}{H zLxx;gztEU^RHmiTIPPvim;JDGZG2qhu(X$L_Eu$VAVfx_DwcZP7~v(w0gLnYmXcW* zUZIILR+6Eki;f$bMizx6;26>w1gUXlN>fDlnB!k-(W6A;OIFuAcb-TLGCnhbQ8l{i zWR=e&)qUHviX&?5as}NT@od@#%u1@9JH{tHr07LVpBp>VdvrY;dS7+6J2WuNx%!cBl`ZA z{S77c*aI;Rk~H88t+E*=B25*sI%!PlsWI0&#e>@eM1{-yb^R_%@p!!V42(N#IP>2m z!@pTwp?#r&O()_rCVQ8^eY^Isvtj%2C`A5kKInF84wcv(Ki}^}pv;sJLIc~3W^~xz zOr9O&qkWh}y0j``KX?tkFt0stPwy#ZAnL>v;JY^MFyNOi0_xVOjA%cxcBZ zAajZ0GXCDcy#QE!;ISVw>`IvfJ_!{AzwbcRNj>2EUo8QC&tQ{ZKRxJ^G+`hO161@5 zt6BZAOwC4<(}&US4~b!W6dE|pZmm}n04*m@IxQ!DS(2Z_bgrZZ>2wJsBj&} zAJnd&zUsIF&Q~mn?av*-_AirVoa6WpU>yP|{s3ey-icQA!*cQV;PaG%XLRqMLmxCf zk$%)q9klyb_{Y`NM~q(lVH5oXjbBFUodqFoiiZJ*R7&i7J3#)Ue~rrjLH7)uY{5JVbjoRfYkFxnwnQNo338D z_PppLcAM>@+N15w_3ZK#l~2#=dwWB;>iVYefu5baXl8ooTKG{>o|Jo+3HAWwCQ2zzSa3dWYNVq>THDw77lfH>eRQ8yBs-=%%%1Xa2 zsjvl4Bs@`vi5X2rJ2i>9#iPGKFi1reeNIX%QCPf&g30X*RhhKEj)zpL@EbB?XC|)^ z|Dk5xvxBb!AB#q2Q*f{blw803-}^aR^ZRs-FIvxqt3!rxO*jd)v9_-+(|20sNm8IRAPSw7z}atdvT@U1^%KSu*h{A@$fD1qm}{DG zn4w!c=Duq>b%ZM|Cy*1Br?~rzmg7?*IYn`zXTkmYzq}>@Qs-|H{4mx0Bj4jBqg!NK zXY?FHMn;BN#IjDqD56h4moTx|M&RDW&5S1`K7Ss8bH`;i{uh2ex%etfm|+&0Yo%%wbkhXpj|>cq1dA#N1%lY; zLj{?-d~Ia>Ai(CD5s?ux2x=t5vl>@{3@*%6l$ezugQcZ1%U$sl44!$(*_1f&Gov6t ziVtboH(9vNy752%U^NQgz9IcTI`RLv$=d001U!3mh0JaDNcE5hMs~m~(m7T?^_yL? z@*BW^D+O{mS}LeKUm+C5jYd6XD5FI$&scDj21z^!3cU6@t9KaJf>+kexbn(?z0d#b zkE@27JI8OG*PAlb?7nkOZ<8UQ)m3*b&=u45&5I|ox)T_RA7IhB^9DRoS6)!Ie#9iJ z>kUcHji&+T7s<%-O7p-!z!3BmmoALQ&AYRJGRP#Cd( zcT&k>q9#MQQWr|ozr?mtL~$59Q@IYv4N2?bG+pE(TFWi)@!jw&d=9+M z5*8tGrbtNzmq2H|$Npr0oZe4dTru1=*3vT}i1{r`BIc=D&2Sq0>XVB)^T3@Tvb@D3}&8I z>M^S`gLRMkP6kgZ<<=#qbXs(qbko?>zE}ME%@jw|%-0`x*tuo@SEdQ6HG_q_=MtT} zKyM=|R>cS6zbtxbrANPe3IfEx##VusKy);wR|*{je)-6di|TOj7PG@jv`Ms);**am zi~#HES*i{n2{kLg03SJz%WjuU@M4Q9VWPDm z4`7qXVG}0Q2H>}eHddnoGOFK(fkC^&n(}ANKrK+*aaE4P#lo&MBt-ohIEGo2sVB6R zy>anax;$`CAIPi+qc^hHdV+gBdz;EeZ*vu7 ze*18+t<0clwqjOmbG<&XE@6!>?J?mrXMt|6y@b6)dv<;8>Vr*uFrzuKYKmSVWnr{= zh-$@({Ji|v;PXd&iG&I{@c?|yQiBh8oo%LG%psGjL#r%{shSIPXm0(JR@J-udTX}_eN)PNC_rW`VflMh87E;7MIPr~w)vkVlK&zNdXEpW zEXsG{!9BSswNfSxSUO!p96x_qgN=_C%*>=w!L$U$j(Mo(0h)So<^7X55fh~{n*Te# z^*fHJX+H~M=O!moZ6fq*tWvpL2f{u7cNx#$z*NoH-x9R5*7HB8L+da09H?>y$%2rx z)dPnJk{`OGN*szL%lPt&sZ-+6hmtx8MOTJ{L+bxK!hbhl|I_SgyzV{c9t&?QvIW3N zT2H}5s{DF8amtpbO7DeTxPW3DSFQ!}d0K9T63cAxRKyaaEXOp??nUd3SY5%=xY<6Z& zv_0oar1;-*yO1mJ{x5K;Xy^D7S$uJFF>Uxi;7?dU{C46^m1qACK|U8X literal 0 HcmV?d00001 From fd083dfce865e69d13c28aed23c0635f12e4f277 Mon Sep 17 00:00:00 2001 From: spf Date: Mon, 4 Aug 2025 16:25:13 +0800 Subject: [PATCH 05/11] =?UTF-8?q?doc:=20=E6=AD=A3=E7=A1=AE=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E4=BA=86=E6=B5=81=E7=A8=8B=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/design-doc.md | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/docs/design-doc.md b/docs/design-doc.md index fb8a822..6d98fef 100644 --- a/docs/design-doc.md +++ b/docs/design-doc.md @@ -329,24 +329,7 @@ CodeAgent 将从一个 GitHub 代码代理,扩展为一个完整的 AI 服务 ### 6.3 技术架构 -``` -┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ -│ 客户端应用 │ │ CodeAgent │ │ AI 服务商 │ -│ (GitHub/API) │───▶│ 网关平台 │───▶│ (Claude/Gemini)│ -└─────────────────┘ └─────────────────┘ └─────────────────┘ - │ - ▼ - ┌─────────────────┐ - │ 账号池管理 │ - │ 负载均衡 │ - └─────────────────┘ - │ - ▼ - ┌─────────────────┐ - │ Workflow 引擎 │ - │ 流程管理 │ - └─────────────────┘ -``` +![流程图](./流程图.png) ### 6.4 用户价值 From e336fb59e0bd3e85b84888ac0cc91ebf65d5eee4 Mon Sep 17 00:00:00 2001 From: qiniu Date: Wed, 6 Aug 2025 15:51:36 +0800 Subject: [PATCH 06/11] =?UTF-8?q?doc:=E4=BF=AE=E6=94=B9=E8=AE=BE=E8=AE=A1?= =?UTF-8?q?=E6=96=87=E6=A1=A3=EF=BC=8C=E8=A1=A5=E5=85=85=E5=85=B7=E4=BD=93?= =?UTF-8?q?=E5=9C=BA=E6=99=AF=E5=8F=8A=E9=9C=80=E6=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/design-doc.md | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/docs/design-doc.md b/docs/design-doc.md index 6d98fef..102b0fa 100644 --- a/docs/design-doc.md +++ b/docs/design-doc.md @@ -1,6 +1,33 @@ - # CodeAgent 产品设计文档 +## 1. 场景介绍 + +### 1.1 提高基于github合作的效率 + +用于自动化处理 GitHub PR 和issues的通用agent,可以回答问题并实现代码更改。基于webhook监听github仓库中的各类事件,并激活 agent 对不同事件处理的工作流。 + +- **Code Review** :分析 PR 更改并提出改进建议 +- **Code Implementation** :可以实现简单的修复、重构,甚至新功能 +- **PR/Issue Integration**:与 GitHub 评论和公关评论无缝协作 + +### 1.2 支持大量用户接入使用 + +需要面向内部大规模使用,但 LLM 的官方api_key是有限的,无法为每个人提供一个官方的api_key。我们希望设计一个AI Gateway(AI网关/账号池),为每个人分发一个内部账号,该账号会通过AI Gateway映射到一个可用的api_key + +#### 基础功能 + +- **多账户管理**: 可以添加多个Claude账户自动轮换 +- **自定义API Key**: 给每个人分配独立的Key +- **使用统计**: 详细记录每个人用了多少token + +#### 高级功能 + +- **智能切换**: 账户出问题自动换下一个 +- 性能优化**: 连接池、缓存,减少延迟 +- **监控面板**: Web界面查看所有数据 +- **安全控制**: 访问限制、速率控制、客户端限制 +- **代理支持**: 支持HTTP/SOCKS5代理 + ## 1. 产品概述 ### 1.1 CodeAgent 是什么 From ff35a30603c2bb331738dfa34a1a0edeb68daf1a Mon Sep 17 00:00:00 2001 From: qiniu Date: Wed, 6 Aug 2025 15:52:49 +0800 Subject: [PATCH 07/11] =?UTF-8?q?doc:=E4=BF=AE=E6=94=B9=E8=AE=BE=E8=AE=A1?= =?UTF-8?q?=E6=96=87=E6=A1=A3=EF=BC=8C=E8=A1=A5=E5=85=85=E5=85=B7=E4=BD=93?= =?UTF-8?q?=E5=9C=BA=E6=99=AF=E5=8F=8A=E9=9C=80=E6=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/design-doc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/design-doc.md b/docs/design-doc.md index 102b0fa..a539da6 100644 --- a/docs/design-doc.md +++ b/docs/design-doc.md @@ -23,7 +23,7 @@ #### 高级功能 - **智能切换**: 账户出问题自动换下一个 -- 性能优化**: 连接池、缓存,减少延迟 +- **性能优化**: 连接池、缓存,减少延迟 - **监控面板**: Web界面查看所有数据 - **安全控制**: 访问限制、速率控制、客户端限制 - **代理支持**: 支持HTTP/SOCKS5代理 From 86cc34487037f94004d6fc1d21348b3966ff41e7 Mon Sep 17 00:00:00 2001 From: spf Date: Wed, 6 Aug 2025 16:08:46 +0800 Subject: [PATCH 08/11] =?UTF-8?q?docs:=20=E6=9B=B4=E6=94=B9=E4=BA=86?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E5=9B=BE=E7=9A=84=E5=90=8D=E7=A7=B0=EF=BC=8C?= =?UTF-8?q?=E6=A2=B3=E7=90=86agent=E7=9A=84=E5=B7=A5=E4=BD=9C=E6=B5=81?= =?UTF-8?q?=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/design-doc.md | 69 +++++++++++++ .../flowchart.png | Bin ...13\344\273\266\345\244\204\347\220\206.md" | 92 ++++++++++++++++++ 3 files changed, 161 insertions(+) rename "docs/\346\265\201\347\250\213\345\233\276.png" => docs/flowchart.png (100%) create mode 100644 "docs/\345\220\204\347\247\215\345\221\275\344\273\244\347\232\204\344\272\213\344\273\266\345\244\204\347\220\206.md" diff --git a/docs/design-doc.md b/docs/design-doc.md index a539da6..801a1da 100644 --- a/docs/design-doc.md +++ b/docs/design-doc.md @@ -50,6 +50,75 @@ CodeAgent 的工作机制如下: 5. **代码提交**:自动将生成的代码提交到 Git 仓库并创建/更新 PR 6. **结果反馈**:在 GitHub 界面中展示处理结果 +#### 1.2.1 自动化前后对比 + +**传统开发流程**: +```mermaid +graph TD + A[开发者] --> B[手动创建 Issue] + B --> C[手动分析需求] + C --> D[手动编写代码] + D --> E[手动测试] + E --> F[手动创建 PR] + F --> G[手动代码审查] + G --> H[手动合并代码] + + I[开发者] --> J[手动创建 Issue] + J --> K[手动分析需求] + K --> L[手动编写代码] + L --> M[手动测试] + M --> N[手动创建 PR] + N --> O[手动代码审查] + O --> P[手动合并代码] + + Q[开发者] --> R[手动创建 Issue] + R --> S[手动分析需求] + S --> T[手动编写代码] + T --> U[手动测试] + U --> V[手动创建 PR] + V --> W[手动代码审查] + W --> X[手动合并代码] + + style A fill:#ff9999 + style I fill:#ff9999 + style Q fill:#ff9999 +``` + +**CodeAgent 自动化流程**: +```mermaid +graph TD + A[开发者] --> B[批量创建多个 Issue] + B --> C[CodeAgent 自动监听] + C --> D[并行处理多个任务] + + D --> E[任务1: 自动分析需求] + D --> F[任务2: 自动分析需求] + D --> G[任务3: 自动分析需求] + + E --> H[任务1: AI 生成代码] + F --> I[任务2: AI 生成代码] + G --> J[任务3: AI 生成代码] + + H --> K[任务1: 自动测试] + I --> L[任务2: 自动测试] + J --> M[任务3: 自动测试] + + K --> N[任务1: 自动创建 PR] + L --> O[任务2: 自动创建 PR] + M --> P[任务3: 自动创建 PR] + + N --> Q[并行代码审查] + O --> Q + P --> Q + + Q --> R[自动合并代码] + + style A fill:#99ff99 + style C fill:#99ccff + style D fill:#99ccff + style R fill:#99ff99 +``` + **核心流程示例**: ``` 开发者评论 "/code 实现用户登录功能" diff --git "a/docs/\346\265\201\347\250\213\345\233\276.png" b/docs/flowchart.png similarity index 100% rename from "docs/\346\265\201\347\250\213\345\233\276.png" rename to docs/flowchart.png diff --git "a/docs/\345\220\204\347\247\215\345\221\275\344\273\244\347\232\204\344\272\213\344\273\266\345\244\204\347\220\206.md" "b/docs/\345\220\204\347\247\215\345\221\275\344\273\244\347\232\204\344\272\213\344\273\266\345\244\204\347\220\206.md" new file mode 100644 index 0000000..a8db5f0 --- /dev/null +++ "b/docs/\345\220\204\347\247\215\345\221\275\344\273\244\347\232\204\344\272\213\344\273\266\345\244\204\347\220\206.md" @@ -0,0 +1,92 @@ +## /continue + +1. handler.go: 读取模型参数和其余args,要是没读到模型参数就使用默认模型 +2. handler.go: 169行,执行ContinuePRWithArgsAndAI() +3. agent.go: 542, processPRWithArgsAndAI(xxx. "continue") +4. GetOrCreateWorkspaceForPRWithAI()*获取或创建 PR 工作空间,包含AI模型信息* +5. *拉取远端最新代码* +6. *获取所有PR评论历史用于构建上下文* +7. *构建包含历史上下文的 prompt* + +> ### 1. 初始化阶段 +> ```go +> var prompt string +> var taskDescription string +> var defaultTask string +> ``` +> 定义三个变量来存储最终结果和任务描述。 +> +> ### 2. 模式判断(switch 语句) +> 根据 `mode` 参数设置不同的任务描述: +> +> | 模式 | taskDescription | defaultTask | +> | ---------- | ------------------------------------------------------------ | -------------------------------- | +> | "Continue" | "请根据上述PR描述、历史讨论和当前指令,进行相应的代码修改。" | "继续处理PR,分析代码变更并改进" | +> | "Fix" | "请根据上述PR描述、历史讨论和当前指令,进行相应的代码修复。" | "分析并修复代码问题" | +> | 其他 | "请根据上述PR描述、历史讨论和当前指令,进行相应的代码处理。" | "处理代码任务" | +> +> ### 3. 提示词构建逻辑(双重条件判断) +> +> #### 条件1:是否有具体指令(args != "") +> - **有指令 + 有历史上下文**: +> ``` +> 作为PR代码审查助手,请基于以下完整上下文来[模式]: +> +> [历史上下文] +> +> ## 当前指令 +> [args] +> +> [taskDescription]注意: +> 1. 当前指令是主要任务,历史信息仅作为上下文参考 +> 2. 请确保修改符合PR的整体目标和已有的讨论共识 +> 3. 如果发现与历史讨论有冲突,请优先执行当前指令并在回复中说明 +> ``` +> +> - **有指令 + 无历史上下文**: +> ``` +> 根据指令[模式]: +> +> [args] +> ``` +> +> #### 条件2:是否有历史上下文(historicalContext != "") +> - **无指令 + 有历史上下文**: +> ``` +> 作为PR代码审查助手,请基于以下完整上下文来[模式]: +> +> [历史上下文] +> +> ## 任务 +> [defaultTask] +> +> 请根据上述PR描述和历史讨论,进行相应的代码修改和改进。 +> ``` +> +> - **无指令 + 无历史上下文**: +> ``` +> [defaultTask] +> ``` +> +> ## 逻辑流程图 +> +> ``` +> 开始 +> ↓ +> 设置 taskDescription 和 defaultTask(根据 mode) +> ↓ +> args != "" ? +> ├─ 是 → historicalContext != "" ? +> │ ├─ 是 → 构建完整提示词(包含历史上下文和当前指令) +> │ └─ 否 → 构建简单提示词(仅当前指令) +> └─ 否 → historicalContext != "" ? +> ├─ 是 → 构建基于历史上下文的提示词 +> └─ 否 → 使用默认任务描述 +> ↓ +> 返回构建好的 prompt +> ``` +> + +7. 执行AI处理;resp, err := a.promptWithRetry(ctx, codeClient, prompt, 3) agent.go : 435 +8. *提交变更并更新 PR*, *Continue模式不返回错误,继续执行评论* +9. *评论到 PR* \ No newline at end of file From dfc62240fe5cf94e588f6dbdaf5cbd2dfea308d5 Mon Sep 17 00:00:00 2001 From: spf Date: Wed, 6 Aug 2025 16:35:04 +0800 Subject: [PATCH 09/11] =?UTF-8?q?doc:=20=E4=BF=AE=E6=94=B9=E4=BA=86continu?= =?UTF-8?q?e=E5=91=BD=E4=BB=A4=E7=9A=84=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cmd-continue.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) rename "docs/\345\220\204\347\247\215\345\221\275\344\273\244\347\232\204\344\272\213\344\273\266\345\244\204\347\220\206.md" => docs/cmd-continue.md (91%) diff --git "a/docs/\345\220\204\347\247\215\345\221\275\344\273\244\347\232\204\344\272\213\344\273\266\345\244\204\347\220\206.md" b/docs/cmd-continue.md similarity index 91% rename from "docs/\345\220\204\347\247\215\345\221\275\344\273\244\347\232\204\344\272\213\344\273\266\345\244\204\347\220\206.md" rename to docs/cmd-continue.md index a8db5f0..a954e1c 100644 --- "a/docs/\345\220\204\347\247\215\345\221\275\344\273\244\347\232\204\344\272\213\344\273\266\345\244\204\347\220\206.md" +++ b/docs/cmd-continue.md @@ -3,8 +3,8 @@ 1. handler.go: 读取模型参数和其余args,要是没读到模型参数就使用默认模型 2. handler.go: 169行,执行ContinuePRWithArgsAndAI() 3. agent.go: 542, processPRWithArgsAndAI(xxx. "continue") -4. GetOrCreateWorkspaceForPRWithAI()*获取或创建 PR 工作空间,包含AI模型信息* -5. *拉取远端最新代码* +4. agent: 384, GetOrCreateWorkspaceForPRWithAI()*获取或创建 PR 工作空间,包含AI模型信息*, +5. agent:393, *拉取远端最新代码* 6. *获取所有PR评论历史用于构建上下文* 7. *构建包含历史上下文的 prompt* @@ -87,6 +87,8 @@ > ``` > -7. 执行AI处理;resp, err := a.promptWithRetry(ctx, codeClient, prompt, 3) agent.go : 435 -8. *提交变更并更新 PR*, *Continue模式不返回错误,继续执行评论* -9. *评论到 PR* \ No newline at end of file +8. 执行AI处理;resp, err := a.promptWithRetry(ctx, codeClient, prompt, 3) agent.go : 435 + +9. *提交变更并更新 PR*, *Continue模式不返回错误,继续执行评论* + +10. 评论到 PR* \ No newline at end of file From 727b4f75eda79f2eab1c2ffd398d712bbf6f8702 Mon Sep 17 00:00:00 2001 From: qiniu Date: Wed, 6 Aug 2025 17:04:32 +0800 Subject: [PATCH 10/11] =?UTF-8?q?docs:=20=E6=A2=B3=E7=90=86=20codeagent=20?= =?UTF-8?q?=E7=9A=84/code=E5=B7=A5=E4=BD=9C=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/cmd-code.md | 138 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 docs/cmd-code.md diff --git a/docs/cmd-code.md b/docs/cmd-code.md new file mode 100644 index 0000000..397e7b9 --- /dev/null +++ b/docs/cmd-code.md @@ -0,0 +1,138 @@ + + +# AI-Powered Issue to PR Workflow + +## 概述 +该流程通过 GitHub Issue 评论触发,自动创建分支、生成代码修改并提交 PR,全程由 AI 驱动。适用于自动化代码维护场景。 + +## 流程图 +```mermaid +graph TD + A[Issue Comment Event] --> B[创建工作空间] + B --> C[创建Git分支] + C --> D[创建初始PR] + D --> E[初始化Session] + E --> F[调用AI生成代码] + F --> G[解析结构化输出] + G --> H[更新PR内容] + H --> I[提交代码变更] +``` + +--- + +## 详细步骤 + +### 1. 初始化阶段 +| 步骤 | 操作 | 关键数据 | +|------|------|----------| +| 1.1 | 接收 GitHub Issue 评论事件 | `event *github.IssueCommentEvent` | +| 1.2 | 创建带 AI 模型信息的工作空间 | `ws := CreateWorkspaceFromIssueWithAI()` | +| 1.3 | 创建并推送 Git 分支 | `CreateBranch(ws)` | + +### 2. PR 准备阶段 +| 步骤 | 操作 | 关键方法 | +|------|------|----------| +| 2.1 | 创建初始 Pull Request | `CreatePullRequest(ws)` | +| 2.2 | 建立工作空间映射 | `MoveIssueToPR(ws, prNumber)` | +| 2.3 | 创建 Session 目录 | `CreateSessionPath()` | +| 2.4 | 注册工作空间 | `RegisterWorkspace(ws, pr)` | + +### 3. AI 交互阶段 +**Prompt 模板:** +```markdown +根据Issue修改代码: + +标题:{{issue_title}} +描述:{{issue_body}} + +输出格式: +### 改动摘要 +简要说明改动内容 + +### 修改内容 +- 列出修改的文件和具体变动 +``` + +| 关键控制点 | 说明 | +|------------|------| +| 重试机制 | `promptWithRetry(ctx, code, prompt, 3)` | +| 输出解析 | `parseStructuredOutput(aiStr)` | + +### 4. PR 内容生成 +**PR Body 结构:** +```markdown +### 改动摘要 +{{summary}} + +### 修改内容 +{{changes}} + +### 测试计划 +{{testPlan}} + +--- +
AI 完整输出 +{{raw_ai_output}} +
+ +
原始 Prompt +{{original_prompt}} +
+``` + +### 5. 代码提交阶段 +| 操作 | 方法 | 错误处理 | +|------|------|----------| +| 提交变更 | `CommitAndPush(ws, result, code)` | 自动回滚分支 | +| 最终状态 | 更新 PR URL 到日志 | `pr.GetHTMLURL()` | + +--- + +## 数据结构 +### Workspace 关键字段 +```go +type Workspace struct { + Path string // 工作目录路径 + Branch string // Git 分支名 + AIModel string // 使用的AI模型标识 + PRNumber int // 关联的PR编号 + SessionPath string // Session存储路径 + PullRequest *github.PullRequest +} +``` + +### ExecutionResult +```go +type ExecutionResult struct { + Output string // AI原始输出 + // ...其他审计字段 +} +``` + +--- + +## 错误处理策略 +1. **关键步骤失败**:立即终止流程并返回错误 + - 工作空间创建失败 + - 分支创建失败 + - AI 调用连续 3 次失败 + +2. **非关键错误**:记录后继续执行 + - 工作空间移动失败 + - 非阻塞性的文件操作错误 + +3. **错误信息展示**:自动在 PR Body 中标记错误段 + ```markdown + ## 错误信息 + ```text + {{error_details}} + ``` + ``` + +--- + +## 扩展能力 +1. **多模型支持**:通过 `aiModel` 参数指定不同 AI 引擎 +2. **自定义 Prompt**:可通过 `args` 注入额外指令 +3. **审计追踪**:保留完整的 AI 交互记录在 PR 中 + From ba23c82acdd12837c2f35871db2a01f52ee0c306 Mon Sep 17 00:00:00 2001 From: qiniu Date: Fri, 8 Aug 2025 15:54:28 +0800 Subject: [PATCH 11/11] =?UTF-8?q?doc:=20=E5=9C=BA=E6=99=AF=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=EF=BC=8CAI=E7=BD=91=E5=85=B3=E6=9C=80=E4=B8=BB?= =?UTF-8?q?=E8=A6=81=E7=94=B1qnaigc=E8=B4=9F=E8=B4=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/design-doc.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/design-doc.md b/docs/design-doc.md index 801a1da..3866ef4 100644 --- a/docs/design-doc.md +++ b/docs/design-doc.md @@ -10,7 +10,7 @@ - **Code Implementation** :可以实现简单的修复、重构,甚至新功能 - **PR/Issue Integration**:与 GitHub 评论和公关评论无缝协作 -### 1.2 支持大量用户接入使用 +### 1.2 支持大量用户接入使用(交由AIGC部门主要负责“api.qnnaigc.com”) 需要面向内部大规模使用,但 LLM 的官方api_key是有限的,无法为每个人提供一个官方的api_key。我们希望设计一个AI Gateway(AI网关/账号池),为每个人分发一个内部账号,该账号会通过AI Gateway映射到一个可用的api_key